1
Fork 0
mirror of https://git.cs.ou.nl/joshua.moerman/mealy-decompose.git synced 2025-04-30 02:07:44 +02:00
mealy-decompose/src/Merger.hs
2024-06-14 14:43:32 +02:00

61 lines
No EOL
1.9 KiB
Haskell

module Merger where
import Partition
import Control.Monad (replicateM)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.State.Strict
import Data.Bifunctor (first)
import Data.List (minimumBy)
import Data.Map.Strict qualified as Map
import Data.Ord (comparing)
import Data.Set qualified as Set
data MergerStats = MergerStats
{ numberOfComponents :: Int
, maximalComponent :: Int
, totalSize :: Int
}
deriving (Eq, Ord, Read, Show)
data MergerAction = Stop | Continue
deriving (Eq, Ord, Read, Show)
type MergerStrategy = MergerStats -> MergerAction
heuristicMerger :: Ord o => [(o, Partition)] -> MergerStrategy -> IO [([o], Partition)]
heuristicMerger components strategy = do
projmap <- evalStateT (loop 2) (Map.fromList (fmap (first pure) components))
return $ Map.assocs projmap
where
score ps p3 = numBlocks p3 - sum (fmap numBlocks ps)
combine ops =
let os = fmap fst ops
ps = fmap snd ops
p3 = foldr1 commonRefinement ps
in ((os, p3), score ps p3)
isSortedOn f ls = and $ zipWith (\a b -> f a < f b) ls (drop 1 ls)
allCombs n projs = fmap combine . filter (isSortedOn fst) $ replicateM n projs
minComb n projs = minimumBy (comparing snd) (allCombs n projs)
safeStrategy ms@MergerStats{..}
| numberOfComponents <= 1 = Stop
| otherwise = strategy ms
loop n = do
projmap <- get
let numberOfComponents = Map.size projmap
componentSizes = fmap numBlocks . Map.elems $ projmap
maximalComponent = maximum componentSizes
totalSize = sum componentSizes
ms = MergerStats{..}
liftIO . print $ ms
case safeStrategy ms of
Stop -> return projmap
Continue -> do
let ((os, p3), _) = minComb n (Map.assocs projmap)
o3 = mconcat os
newProjmap = Map.insert o3 p3 . Map.withoutKeys projmap $ Set.fromList os
put newProjmap
if Map.size newProjmap < n
then loop (Map.size newProjmap)
else loop n