1
Fork 0
mirror of https://git.cs.ou.nl/joshua.moerman/mealy-decompose.git synced 2025-04-30 02:07:44 +02:00

Made isRefinementOf much faster

This commit is contained in:
Joshua Moerman 2023-12-01 16:59:54 +01:00
parent e20251c07d
commit a20e5e9317
2 changed files with 46 additions and 16 deletions

View file

@ -10,9 +10,7 @@ import Control.Monad.Trans.State.Strict
import Control.Monad (forM_, when, forever) import Control.Monad (forM_, when, forever)
import Data.Map.Strict qualified as Map import Data.Map.Strict qualified as Map
import Data.Maybe (mapMaybe) import Data.Maybe (mapMaybe)
-- import Data.Semigroup (Arg(..)) import Data.List.Ordered (nubSort)
-- import Data.Set qualified as Set
-- import Data.List.Ordered (nubSort)
import Data.List (minimumBy) import Data.List (minimumBy)
import Data.Function (on) import Data.Function (on)
import System.Environment import System.Environment
@ -61,8 +59,8 @@ main = do
-- Then compute each projection -- Then compute each projection
-- I did some manual preprocessing, these are the only interesting bits -- I did some manual preprocessing, these are the only interesting bits
let outs = ["10", "10-O9", "2.2", "3.0", "3.1", "3.10", "3.12", "3.13", "3.14", "3.16", "3.17", "3.18", "3.19", "3.2", "3.20", "3.21", "3.3", "3.4", "3.6", "3.7", "3.8", "3.9", "5.0", "5.1", "5.12", "5.13", "5.17", "5.2", "5.21", "5.23", "5.6", "5.7", "5.8", "5.9", "quiescence"] let -- outs = ["10", "10-O9", "2.2", "3.0", "3.1", "3.10", "3.12", "3.13", "3.14", "3.16", "3.17", "3.18", "3.19", "3.2", "3.20", "3.21", "3.3", "3.4", "3.6", "3.7", "3.8", "3.9", "5.0", "5.1", "5.12", "5.13", "5.17", "5.2", "5.21", "5.23", "5.6", "5.7", "5.8", "5.9", "quiescence"]
-- outs = outputs machine outs = outputs machine
projections0 = allProjections machine outs projections0 = allProjections machine outs
projections = zip outs $ fmap refineMealy projections0 projections = zip outs $ fmap refineMealy projections0
@ -72,6 +70,7 @@ main = do
printPartition partition printPartition partition
) )
{-
let totalSize = sum (fmap (numBlocks . snd) projections) let totalSize = sum (fmap (numBlocks . snd) projections)
putStrLn $ "total size = " <> show totalSize putStrLn $ "total size = " <> show totalSize
@ -93,10 +92,10 @@ main = do
) )
print "done" print "done"
-}
{- {-
-- Check refinement relations for all pairs -- Check refinement relations for all pairs
-- This is a bit messy, it skips machines which are equivalent -- This is a bit messy, it skips machines which are equivalent
-- to earlier checked machines, so we thread some state through this -- to earlier checked machines, so we thread some state through this
@ -112,20 +111,17 @@ main = do
forM_ projections (\(o2, b2) -> do forM_ projections (\(o2, b2) -> do
(repr0, _) <- get (repr0, _) <- get
when (o1 < o2 && o2 `Map.notMember` repr0) $ do when (o1 < o2 && o2 `Map.notMember` repr0) $ do
case (isRefinementOf b1 b2, isRefinementOf b2 b1) of case comparePartitions b1 b2 of
(True, True) -> do Equivalent -> do
(repr, ls) <- get (repr, ls) <- get
put (Map.insert o2 o1 repr, ls) put (Map.insert o2 o1 repr, ls)
(True, False) -> do Refinement -> do
(repr, ls) <- get (repr, ls) <- get
put (repr, (o1, o2):ls) put (repr, (o1, o2):ls)
(False, True) -> do Coarsening -> do
(repr, ls) <- get (repr, ls) <- get
put (repr, (o2, o1):ls) put (repr, (o2, o1):ls)
(False, False) -> return () Incomparable -> return ()
-- liftIO $ putStr " vs. "
-- liftIO $ print o2
) )
) )
@ -143,5 +139,4 @@ main = do
) )
return () return ()
-} -}

View file

@ -4,7 +4,7 @@ module Partition
) where ) where
import Control.Monad.Trans.State.Strict (runState, get, put) import Control.Monad.Trans.State.Strict (runState, get, put)
import Data.Partition (Partition(..), isRefinementOf, numStates) import Data.Partition (Partition(..), numStates)
import Data.Vector qualified as V import Data.Vector qualified as V
import Data.Map.Strict qualified as Map import Data.Map.Strict qualified as Map
import Unsafe.Coerce (unsafeCoerce) import Unsafe.Coerce (unsafeCoerce)
@ -27,3 +27,38 @@ commonRefinement p1 p2 =
(vect, (_, nextBlock)) = runState (V.generateM n blockAtIdx) (Map.empty, 0) (vect, (_, nextBlock)) = runState (V.generateM n blockAtIdx) (Map.empty, 0)
in Partition { numBlocks = unsafeCoerce nextBlock, stateAssignment = vect } in Partition { numBlocks = unsafeCoerce nextBlock, stateAssignment = vect }
-- Could be made faster by doing what commonRefinement is doing but
-- stopping early. This is already much faster than what is in
-- the CoPaR library, so I won't bother.
isRefinementOf2 :: Partition -> Partition -> Bool
isRefinementOf2 refined original =
numBlocks refined == numBlocks (commonRefinement refined original)
-- See comment at isRefinementOf2
isEquivalent :: Partition -> Partition -> Bool
isEquivalent p1 p2 =
p1 == p2 || (numBlocks p1 == numBlocks p2 && numBlocks p1 == numBlocks (commonRefinement p1 p2))
-- Instead of checking whether one partition is a refinement of another AND
-- also checking vice versa. We can check the direction at once, computing the
-- common refinement only once. It saves some time.
data Comparison
= Equivalent
| Refinement
| Coarsening
| Incomparable
deriving (Eq, Ord, Read, Show, Enum, Bounded)
-- See comment at isRefinementOf2
comparePartitions :: Partition -> Partition -> Comparison
comparePartitions p1 p2
| p1 == p2 = Equivalent
| otherwise = let glb = commonRefinement p1 p2
n1 = numBlocks p1
n2 = numBlocks p2
n3 = numBlocks glb
in case (n1 == n3, n2 == n3) of
(True, True) -> Equivalent
(True, False) -> Refinement
(False, True) -> Coarsening
(False, False) -> Incomparable