module Math.SetCover.Exact.Priority (
Assign, ESC.label, ESC.labeledSet, ESC.assign,
partitions, search, step,
State(..), initState, updateState,
Tree(..), decisionTree, completeTree,
SetId, queueMap, queueSet, queueBit, queueBitPQ, queueIntSet,
) 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, Tree(Branch,Leaf))
import qualified Math.SetCover.EnumMap as EnumMapX
import qualified Data.EnumMap as EnumMap; import Data.EnumMap (EnumMap)
import qualified Data.Foldable as Fold
import Data.EnumSet (EnumSet)
import Data.Tuple.HT (mapSnd)
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 nextStates #-}
nextStates ::
Methods queue set ->
State queue label set ->
EnumSet SetId -> [State queue label set]
nextStates dict s =
map (flip (updateState dict) s) . EnumMap.elems .
EnumMapX.intersection (availableSubsets s)
{-# INLINE step #-}
step :: Methods queue set -> State queue label set -> [State queue label set]
step dict s =
flip Fold.foldMap (Queue.findMin dict (queue s)) $ nextStates dict s
{-# INLINE search #-}
search :: Methods queue set -> State queue label set -> [[label]]
search dict =
let go s =
case Queue.findMin dict (queue s) of
Nothing -> [usedSubsets s]
Just setIds -> nextStates dict s setIds >>= go
in go
{-# INLINE partitions #-}
partitions :: Methods queue set -> [Assign label set] -> [[label]]
partitions dict = search dict . initState dict
completeTree :: Methods queue set -> State queue label set -> Tree label set
completeTree dict =
let go s =
case Queue.findMinValue dict (queue s) of
Nothing -> Leaf
Just mins ->
uncurry Branch $ flip mapSnd mins $
map (\asn -> (ESC.label asn, go $ updateState dict asn s)) .
EnumMap.elems . EnumMapX.intersection (availableSubsets s)
in go
decisionTree :: Methods queue set -> [Assign label set] -> Tree label set
decisionTree dict = completeTree 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
queueIntSet :: QueueBit.MethodsIntSet
queueIntSet = QueueBit.methodsIntSet
queueBitPQ :: BitPos.C bits => QueueBitPQ.Methods bits
queueBitPQ = QueueBitPQ.methods