diff --git a/slapnet.cabal b/slapnet.cabal index a194e180368864e981fb250d02ada96c16c361cb..144c37c696a091a3415e681f6d42d187687f535a 100644 --- a/slapnet.cabal +++ b/slapnet.cabal @@ -22,7 +22,7 @@ executable slapnet other-modules: -- other-extensions: build-depends: base >=4 && <5, sbv, parsec, containers, transformers, - bytestring, mtl + bytestring, mtl, stm, async, parallel-io hs-source-dirs: src default-language: Haskell2010 - ghc-options: -fsimpl-tick-factor=1000 + ghc-options: -fsimpl-tick-factor=1000 -threaded -rtsopts -with-rtsopts=-N diff --git a/src/Main.hs b/src/Main.hs index 7cfae784503425d400f9cea7e3aa7958a3712453..642ef0947dd57504077f3d2d2384ec48d32284b0 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -3,6 +3,7 @@ module Main where import System.Exit import System.IO import Control.Monad +import Control.Concurrent.ParallelIO import Control.Arrow (first) import Data.List (partition) import Data.Maybe @@ -405,14 +406,19 @@ main = do exitSuccessWith :: String -> IO () exitSuccessWith msg = do putStrLn msg - exitSuccess + cleanupAndExitWith ExitSuccess exitFailureWith :: String -> IO () exitFailureWith msg = do putStrLn msg - exitWith $ ExitFailure 2 + cleanupAndExitWith $ ExitFailure 2 exitErrorWith :: String -> IO () exitErrorWith msg = do hPutStrLn stderr msg - exitWith $ ExitFailure 3 + cleanupAndExitWith $ ExitFailure 3 + +cleanupAndExitWith :: ExitCode -> IO () +cleanupAndExitWith code = do + stopGlobalPool + exitWith code diff --git a/src/Options.hs b/src/Options.hs index c5b4f28abd9861da8c7ca9958659a34225b7249b..ffeec24a42108a8bb7ac8248078fefb20e19e821 100644 --- a/src/Options.hs +++ b/src/Options.hs @@ -59,7 +59,7 @@ startOptions = Options { inputFormat = PNET , optShowVersion = False , optProperties = [] , optTransformations = [] - , optSimpFormula = 6 + , optSimpFormula = 100 , optRefinementType = Just SComponentWithCutRefinement , optMinimizeRefinement = 0 , optInvariant = False diff --git a/src/Solver/Simplifier.hs b/src/Solver/Simplifier.hs index d728dc74d916ee621e1a4d39ef81d9318ba07bfa..ef0ee384fd789aa2ba9c9ddd74f84e37e70ee645 100644 --- a/src/Solver/Simplifier.hs +++ b/src/Solver/Simplifier.hs @@ -7,6 +7,9 @@ module Solver.Simplifier ( import Data.SBV import Data.Maybe +import Data.Ord (comparing) +import Data.List (minimumBy) +import Control.Arrow (second) import Control.Monad import Control.Monad.Identity import qualified Data.Map as M @@ -50,47 +53,66 @@ checkSubsumptionSat c0 cs = cutTransitions :: SimpleCut -> S.Set Transition cutTransitions (c0, cs) = S.unions (c0:cs) -generateCuts :: PetriNet -> Formula Transition -> [Cut] -> OptIO [SimpleCut] -generateCuts net f cuts = do +type SimpConfig = ([[SimpleCut] -> OptIO [SimpleCut]], SimpleCut, SimpleCut, Int) + +simpWithoutFormula :: PetriNet -> Formula Transition -> SimpConfig +simpWithoutFormula net f = + ( + [ return . simplifyCuts + , return . removeImplicants + , greedySimplify net f + , return . combineCuts + , simplifyBySubsumption + ] + , (S.empty, []) + , second (S.fromList (transitions net) :) (formulaToCut f) + , 2 + ) + +simpWithFormula :: PetriNet -> Formula Transition -> SimpConfig +simpWithFormula net f = + ( + [ return . simplifyCuts + , return . removeImplicants + , return . filterInvariantTransitions net + , greedySimplify net FTrue + , return . combineCuts + , simplifyBySubsumption + ] + , second (S.fromList (transitions net) :) (formulaToCut f) + , (S.empty, []) + , 2 + ) + +applySimpConfig :: SimpConfig -> [Cut] -> OptIO [SimpleCut] +applySimpConfig (simpFunctions, initialCut, afterCut, otfIndex) cuts = do simp <- opt optSimpFormula - - let simpFunctions = - [ return . simplifyCuts - , return . removeImplicants - , simplifyBySubsumption - , greedySimplify net f - , simplifyBySubsumption - ] - let (otfSimps, afterSimps) = splitAt 2 $ take simp simpFunctions + let (otfSimps, afterSimps) = splitAt otfIndex $ take simp simpFunctions let simpFunction = foldl (>=>) return afterSimps let otfFunction = foldl (>=>) return otfSimps let cnfCuts = map cutToSimpleDNFCuts cuts - dnfCuts <- foldM (combine otfFunction) [(S.empty, [])] cnfCuts + dnfCuts <- foldM (combine otfFunction) [initialCut] cnfCuts simpCuts <- simpFunction dnfCuts - - let simpFunctions' = - [ return . simplifyCuts - , return . removeImplicants - , return . filterInvariantTransitions net - , simplifyBySubsumption - , greedySimplify net FTrue - , simplifyBySubsumption - ] - let (otfSimps', afterSimps') = splitAt 2 $ take simp simpFunctions' - let simpFunction' = foldl (>=>) return afterSimps' - let otfFunction' = foldl (>=>) return otfSimps' - - let (fc0, fcs) = formulaToCut f - let addedTransitions = S.fromList (transitions net) - let addedCut = (fc0, addedTransitions : fcs) - simpCutsWithFormula <- combine otfFunction' [addedCut] simpCuts - simpCuts' <- simpFunction' simpCutsWithFormula - return simpCuts' + combine otfFunction [afterCut] simpCuts where combine simpFunction cs1 cs2 = simpFunction [ (c1c0 `S.union` c2c0, c1cs ++ c2cs) | (c1c0, c1cs) <- cs1, (c2c0, c2cs) <- cs2 ] +generateCuts :: PetriNet -> Formula Transition -> [Cut] -> OptIO [SimpleCut] +generateCuts net f cuts = do + let configs = [simpWithFormula, simpWithoutFormula] + let tasks = map (\c -> applySimpConfig (c net f) cuts) configs + rs <- parallelIO tasks + return $ minimumBy (comparing length) rs + +combineCuts :: [SimpleCut] -> [SimpleCut] +combineCuts cuts = + M.toList $ M.fromListWith combineFunc cuts + where + combineFunc cs cs' = + simplifyPositiveCut [ c `S.union` c' | c <- cs, c' <- cs' ] + filterInvariantTransitions :: PetriNet -> [SimpleCut] -> [SimpleCut] filterInvariantTransitions net = let ts = S.fromList $ invariantTransitions net @@ -115,12 +137,15 @@ simplifyCuts = mapMaybe simplifyCut simplifyCut :: SimpleCut -> Maybe SimpleCut simplifyCut (c0, cs) = let remove b a = a `S.difference` b - cs' = removeWith S.isSubsetOf $ map (remove c0) cs + cs' = simplifyPositiveCut $ map (remove c0) cs in if any S.null cs' then Nothing else Just (c0, cs') +simplifyPositiveCut :: [S.Set Transition] -> [S.Set Transition] +simplifyPositiveCut = removeWith S.isSubsetOf + simplifyBySubsumption :: [SimpleCut] -> OptIO [SimpleCut] simplifyBySubsumption = simplifyBySubsumption' [] diff --git a/src/Util.hs b/src/Util.hs index ace4266d75c38b086509c18eb2cd63962d5ab1ad..45cf42f57df6bc3052e7d7ba42c05b94ba8ff945 100644 --- a/src/Util.hs +++ b/src/Util.hs @@ -5,15 +5,16 @@ module Util listSet,listMap,val,vals,mval,zeroVal,positiveVal,sumVal, makeVarMap,makeVarMapWith,buildVector,makeVector,getNames, Vector,Model,VarMap,SIMap,SBMap,IMap,BMap,showWeighted, - OptIO,verbosePut,opt,putLine) + OptIO,verbosePut,opt,putLine,parallelIO) where import Data.SBV import qualified Data.Map as M -import Control.Monad import Data.List import Data.Ord import Data.Function +import Control.Concurrent.ParallelIO +import Control.Monad import Control.Monad.Reader import System.IO @@ -115,6 +116,11 @@ verbosePut level str = do putLine :: String -> OptIO () putLine = liftIO . putStrLn +parallelIO :: [OptIO a] -> OptIO [a] +parallelIO tasks = do + opts <- ask + liftIO $ parallel $ map (`runReaderT` opts) tasks + {- - String functions -}