module Math.SetCover.Exact.Priority (
Assign, ESC.label, ESC.labeledSet, ESC.assign,
partitions, search, step,
State(..), initState, updateState,
SetId, queueMap, queueSet, queueBit, queueBitPQ,
) where
import qualified Math.SetCover.Queue.Map as QueueMap
import qualified Math.SetCover.Queue.Set as QueueSet
import qualified Math.SetCover.Queue.Bit as QueueBit
import qualified Math.SetCover.Queue.BitPriorityQueue as QueueBitPQ
import qualified Math.SetCover.BitPosition as BitPos
import qualified Math.SetCover.Queue as Queue
import qualified Math.SetCover.Exact as ESC
import Math.SetCover.Queue (Methods, SetId(SetId))
import Math.SetCover.Exact (Assign(Assign), labeledSet)
import qualified Math.SetCover.EnumMap as EnumMapX
import qualified Data.EnumMap as EnumMap; import Data.EnumMap (EnumMap)
import qualified Data.Foldable as Fold
data State queue label set =
State {
availableSubsets :: EnumMap SetId (Assign label set),
queue :: queue,
usedSubsets :: [label]
}
initState ::
Methods queue set -> [Assign label set] -> State queue label set
initState dict subsets =
let numberedSets = EnumMap.fromList $ zip [SetId 0 ..] subsets
in State {
availableSubsets = numberedSets,
queue = Queue.fromEnumMap dict $ fmap labeledSet numberedSets,
usedSubsets = []
}
{-# INLINE updateState #-}
updateState ::
Methods queue set ->
Assign label set -> State queue label set -> State queue label set
updateState dict (Assign attemptLabel attemptedSet) s =
let (attemptElems, remainingQueue) =
Queue.partition dict (queue s) attemptedSet
(removed, remaining) =
EnumMapX.partition (availableSubsets s) attemptElems
in State {
availableSubsets = remaining,
queue = Queue.difference dict remainingQueue $ fmap labeledSet removed,
usedSubsets = attemptLabel : usedSubsets s
}
{-# INLINE step #-}
step :: Methods queue set -> State queue label set -> [State queue label set]
step dict s =
if EnumMap.null (availableSubsets s)
then []
else
flip Fold.foldMap (Queue.findMin dict (queue s)) $
map (flip (updateState dict) s) . EnumMap.elems .
EnumMapX.intersection (availableSubsets s)
{-# INLINE search #-}
search :: Methods queue set -> State queue label set -> [[label]]
search dict =
let go s =
if Queue.null dict (queue s)
then [usedSubsets s]
else step dict s >>= go
in go
{-# INLINE partitions #-}
partitions :: Methods queue set -> [Assign label set] -> [[label]]
partitions dict = search dict . initState dict
queueMap :: Ord a => Queue.Methods queue set -> QueueMap.Methods a queue set
queueMap = QueueMap.methods
queueSet :: Ord a => QueueSet.Methods a
queueSet = QueueSet.methods
queueBit :: BitPos.C bits => QueueBit.Methods bits
queueBit = QueueBit.methods
queueBitPQ :: BitPos.C bits => QueueBitPQ.Methods bits
queueBitPQ = QueueBitPQ.methods