module Math.SetCover.Queue.Bit (Methods, methods) where
import qualified Math.SetCover.Queue as Queue
import Math.SetCover.Queue (SetId)
import qualified Math.SetCover.EnumMap as EnumMapX
import qualified Math.SetCover.BitPosition as BitPos
import qualified Math.SetCover.BitSet as BitSet
import qualified Data.IntPSQ as PSQ
import qualified Data.EnumSet as EnumSet; import Data.EnumSet (EnumSet)
import qualified Data.IntMap as IntMap
import qualified Data.List as List
import Data.Tuple.HT (swap, mapFst, thd3)
type
Methods bits =
Queue.Methods (PSQ.IntPSQ Int (EnumSet SetId)) (BitSet.Set bits)
methods :: BitPos.C bits => Methods bits
methods =
Queue.Methods {
Queue.fromEnumMap =
PSQ.fromList . map (\(elm, ns) -> (elm, EnumSet.size ns, ns)) .
IntMap.toList . EnumMapX.transposeBitSet,
Queue.partition =
\q -> mapFst EnumSet.unions . partitionPSQ q . BitPos.unpack,
Queue.difference = \q ->
foldl (flip deleteSetFromPSQ) q .
IntMap.toList . EnumMapX.transposeBitSet,
Queue.findMin = fmap thd3 . PSQ.findMin,
Queue.null = PSQ.null
}
partitionPSQ :: (Ord p) => PSQ.IntPSQ p v -> [Int] -> ([v], PSQ.IntPSQ p v)
partitionPSQ =
(swap .) .
List.mapAccumL
(\q0 k ->
maybe
(error "partitionPSQ: key not contained in queue's key set")
(\(_p,v,q1) -> (q1, v)) $
PSQ.deleteView k q0)
deleteSetFromPSQ ::
(Int, EnumSet e) -> PSQ.IntPSQ Int (EnumSet e) ->
PSQ.IntPSQ Int (EnumSet e)
deleteSetFromPSQ (elm, ns) =
updatePSQ (flip differenceSizedSet ns) elm
differenceSizedSet :: (Int, EnumSet e) -> EnumSet e -> (Int, EnumSet e)
differenceSizedSet (size, a) b =
let section = EnumSet.intersection a b
in (size - EnumSet.size section, EnumSet.difference a section)
updatePSQ ::
(Ord p) => ((p, v) -> (p, v)) -> Int -> PSQ.IntPSQ p v -> PSQ.IntPSQ p v
updatePSQ f k = snd . PSQ.alter ((,) () . fmap f) k