mios 1.3.0 → 1.4.0
raw patch · 25 files changed
+1219/−1417 lines, 25 filesdep −containersdep −primitivePVP ok
version bump matches the API change (PVP)
Dependencies removed: containers, primitive
API changes (from Hackage documentation)
- SAT.Mios.Clause: getNthClause :: ClauseVector -> Int -> IO Clause
- SAT.Mios.Clause: instance SAT.Mios.Types.VectorFamily SAT.Mios.Clause.Clause SAT.Mios.Types.Lit
- SAT.Mios.Clause: instance SAT.Mios.Types.VectorFamily SAT.Mios.Clause.ClauseVector SAT.Mios.Clause.Clause
- SAT.Mios.Clause: newClauseFromVec :: Bool -> Vec -> IO Clause
- SAT.Mios.Clause: setNthClause :: ClauseVector -> Int -> Clause -> IO ()
- SAT.Mios.Clause: shrinkClause :: Int -> Clause -> IO ()
- SAT.Mios.Clause: sizeOfClause :: Clause -> IO Int
- SAT.Mios.Clause: swapClauses :: ClauseVector -> Int -> Int -> IO ()
- SAT.Mios.ClauseManager: clearManager :: ClauseManager a => a -> IO ()
- SAT.Mios.ClauseManager: garbageCollect :: WatcherList -> IO ()
- SAT.Mios.ClauseManager: instance SAT.Mios.Types.VectorFamily SAT.Mios.ClauseManager.ClauseExtManager SAT.Mios.Clause.Clause
- SAT.Mios.ClauseManager: instance SAT.Mios.Types.VectorFamily SAT.Mios.ClauseManager.WatcherList SAT.Mios.Clause.Clause
- SAT.Mios.ClauseManager: numberOfClauses :: ClauseManager a => a -> IO Int
- SAT.Mios.ClauseManager: pushClause :: ClauseManager a => a -> Clause -> IO ()
- SAT.Mios.ClauseManager: shrinkManager :: ClauseManager a => a -> Int -> IO ()
- SAT.Mios.Data.Singleton: getBool :: BoolSingleton -> IO Bool
- SAT.Mios.Data.Singleton: getDouble :: DoubleSingleton -> IO Double
- SAT.Mios.Data.Singleton: getInt :: IntSingleton -> IO Int
- SAT.Mios.Data.Singleton: modifyBool :: BoolSingleton -> (Bool -> Bool) -> IO ()
- SAT.Mios.Data.Singleton: modifyDouble :: DoubleSingleton -> (Double -> Double) -> IO ()
- SAT.Mios.Data.Singleton: modifyInt :: IntSingleton -> (Int -> Int) -> IO ()
- SAT.Mios.Data.Singleton: newBool :: Bool -> IO BoolSingleton
- SAT.Mios.Data.Singleton: newDouble :: Double -> IO DoubleSingleton
- SAT.Mios.Data.Singleton: newInt :: Int -> IO IntSingleton
- SAT.Mios.Data.Singleton: setBool :: BoolSingleton -> Bool -> IO ()
- SAT.Mios.Data.Singleton: setDouble :: DoubleSingleton -> Double -> IO ()
- SAT.Mios.Data.Singleton: setInt :: IntSingleton -> Int -> IO ()
- SAT.Mios.Data.Singleton: type BoolSingleton = IOVector Bool
- SAT.Mios.Data.Singleton: type DoubleSingleton = IOVector Double
- SAT.Mios.Data.Singleton: type IntSingleton = IOVector Int
- SAT.Mios.Data.Stack: asSizedVec :: Stack -> Vec
- SAT.Mios.Data.Stack: clearStack :: Stack -> IO ()
- SAT.Mios.Data.Stack: data Stack
- SAT.Mios.Data.Stack: instance SAT.Mios.Types.VectorFamily SAT.Mios.Data.Stack.Stack GHC.Types.Int
- SAT.Mios.Data.Stack: lastOfStack :: Stack -> IO Int
- SAT.Mios.Data.Stack: newStack :: Int -> IO Stack
- SAT.Mios.Data.Stack: popFromStack :: Stack -> IO ()
- SAT.Mios.Data.Stack: pushToStack :: Stack -> Int -> IO ()
- SAT.Mios.Data.Stack: shrinkStack :: Stack -> Int -> IO ()
- SAT.Mios.Data.Stack: sizeOfStack :: Stack -> IO Int
- SAT.Mios.Data.Vec: getNth :: Vec -> Int -> IO Int
- SAT.Mios.Data.Vec: modifyNth :: Vec -> (Int -> Int) -> Int -> IO ()
- SAT.Mios.Data.Vec: newSizedVecIntFromList :: [Int] -> IO Vec
- SAT.Mios.Data.Vec: newSizedVecIntFromUVector :: Vector Int -> IO Vec
- SAT.Mios.Data.Vec: newVec :: Int -> IO Vec
- SAT.Mios.Data.Vec: newVecWith :: Int -> Int -> IO Vec
- SAT.Mios.Data.Vec: setAll :: Vec -> Int -> IO ()
- SAT.Mios.Data.Vec: setNth :: Vec -> Int -> Int -> IO ()
- SAT.Mios.Data.Vec: sizeOfVector :: Vec -> IO Int
- SAT.Mios.Data.Vec: swapBetween :: Vec -> Int -> Int -> IO ()
- SAT.Mios.Data.Vec: type Vec = IOVector Int
- SAT.Mios.Data.Vec: vecGrow :: Vec -> Int -> IO Vec
- SAT.Mios.Data.VecBool: getNthBool :: VecBool -> Int -> IO Bool
- SAT.Mios.Data.VecBool: instance SAT.Mios.Types.VectorFamily SAT.Mios.Data.VecBool.VecBool GHC.Types.Bool
- SAT.Mios.Data.VecBool: modifyNthBool :: VecBool -> (Bool -> Bool) -> Int -> IO ()
- SAT.Mios.Data.VecBool: newVecBool :: Int -> Bool -> IO VecBool
- SAT.Mios.Data.VecBool: setNthBool :: VecBool -> Int -> Bool -> IO ()
- SAT.Mios.Data.VecBool: type VecBool = IOVector Bool
- SAT.Mios.Data.VecDouble: getNthDouble :: Int -> VecDouble -> IO Double
- SAT.Mios.Data.VecDouble: instance SAT.Mios.Types.VectorFamily SAT.Mios.Data.VecDouble.VecDouble GHC.Types.Double
- SAT.Mios.Data.VecDouble: modifyNthDouble :: Int -> VecDouble -> (Double -> Double) -> IO ()
- SAT.Mios.Data.VecDouble: newVecDouble :: Int -> Double -> IO VecDouble
- SAT.Mios.Data.VecDouble: setNthDouble :: Int -> VecDouble -> Double -> IO ()
- SAT.Mios.Data.VecDouble: type VecDouble = IOVector Double
- SAT.Mios.Internal: MiosConfiguration :: !Double -> MiosConfiguration
- SAT.Mios.Internal: [variableDecayRate] :: MiosConfiguration -> !Double
- SAT.Mios.Internal: data MiosConfiguration
- SAT.Mios.Internal: defaultConfiguration :: MiosConfiguration
- SAT.Mios.Internal: versionId :: String
- SAT.Mios.Solver: [conflict] :: Solver -> !Stack
- SAT.Mios.Solver: [lastDL] :: Solver -> !Stack
- SAT.Mios.Solver: [pr'seen] :: Solver -> !Vec
- SAT.Mios.Types: Bottom :: LiftedBool
- SAT.Mios.Types: LFalse :: LiftedBool
- SAT.Mios.Types: LTrue :: LiftedBool
- SAT.Mios.Types: asList :: VectorFamily s t => s -> IO [t]
- SAT.Mios.Types: asVec :: VectorFamily s t => s -> IOVector Int
- SAT.Mios.Types: class VectorFamily s t | s -> t where clear = error "no default method for clear" dump msg _ = error $ msg ++ ": no defalut method for dump" asVec = error "asVector undefined" asList = error "asList undefined"
- SAT.Mios.Types: clear :: VectorFamily s t => s -> IO ()
- SAT.Mios.Types: data LiftedBool
- SAT.Mios.Types: dump :: (VectorFamily s t, Show t) => String -> s -> IO String
- SAT.Mios.Types: instance GHC.Classes.Eq SAT.Mios.Types.LiftedBool
- SAT.Mios.Types: instance GHC.Classes.Ord SAT.Mios.Types.LiftedBool
- SAT.Mios.Types: instance GHC.Enum.Bounded SAT.Mios.Types.LiftedBool
- SAT.Mios.Types: instance GHC.Enum.Enum SAT.Mios.Types.LiftedBool
- SAT.Mios.Types: instance GHC.Read.Read SAT.Mios.Types.LiftedBool
- SAT.Mios.Types: instance GHC.Show.Show SAT.Mios.Types.LiftedBool
- SAT.Mios.Types: instance SAT.Mios.Types.VectorFamily SAT.Mios.Data.Vec.Vec GHC.Types.Int
- SAT.Mios.Types: lbool :: Bool -> LiftedBool
- SAT.Mios.Types: newLit :: Var -> Lit
- SAT.Mios.Types: newVar :: VarOrder o => o -> IO Var
- SAT.Mios.Types: newVarOrder :: (VarOrder o, VectorFamily v1 Bool, VectorFamily v2 Double) => v1 -> v2 -> IO o
- SAT.Mios.Types: updateAll :: VarOrder o => o -> IO ()
- SAT.Mios.Util.CNFIO: asCNFString :: BoolForm -> String
- SAT.Mios.Util.CNFIO: asCNFString_ :: BoolForm -> String
- SAT.Mios.Util.CNFIO: clauseListFromFile :: FilePath -> IO [[Int]]
- SAT.Mios.Util.CNFIO: clauseListFromMinisatOutput :: FilePath -> IO [Int]
- SAT.Mios.Util.CNFIO: fromFile :: FilePath -> IO (Maybe ((Int, Int), [[Int]]))
- SAT.Mios.Util.CNFIO: fromMinisatOutput :: FilePath -> IO (Maybe ((Int, Int), [Int]))
- SAT.Mios.Util.CNFIO: toCNFString :: [[Int]] -> String
- SAT.Mios.Util.CNFIO: toFile :: FilePath -> [[Int]] -> IO ()
- SAT.Mios.Util.CNFIO.MinisatReader: clauseListFromMinisatOutput :: FilePath -> IO [Int]
- SAT.Mios.Util.CNFIO.MinisatReader: fromMinisatOutput :: FilePath -> IO (Maybe ((Int, Int), [Int]))
- SAT.Mios.Util.CNFIO.Reader: clauseListFromFile :: FilePath -> IO [[Int]]
- SAT.Mios.Util.CNFIO.Reader: fromFile :: FilePath -> IO (Maybe ((Int, Int), [[Int]]))
- SAT.Mios.Util.CNFIO.Writer: toCNFString :: [[Int]] -> String
- SAT.Mios.Util.CNFIO.Writer: toFile :: FilePath -> [[Int]] -> IO ()
- SAT.Mios.Util.CNFIO.Writer: toLatexString :: [[Int]] -> String
- SAT.Mios.Util.CNFIO.Writer: toString :: [[Int]] -> String -> String -> String
+ SAT.Mios.Clause: instance SAT.Mios.Vec.SingleStorage SAT.Mios.Clause.Clause GHC.Types.Int
+ SAT.Mios.Clause: instance SAT.Mios.Vec.StackFamily SAT.Mios.Clause.Clause SAT.Mios.Types.Lit
+ SAT.Mios.Clause: instance SAT.Mios.Vec.VecFamily SAT.Mios.Clause.Clause SAT.Mios.Types.Lit
+ SAT.Mios.Clause: instance SAT.Mios.Vec.VecFamily SAT.Mios.Clause.ClauseVector SAT.Mios.Clause.Clause
+ SAT.Mios.Clause: newClauseFromStack :: Bool -> Stack -> IO Clause
+ SAT.Mios.ClauseManager: instance SAT.Mios.Vec.SingleStorage SAT.Mios.ClauseManager.ClauseExtManager GHC.Types.Int
+ SAT.Mios.ClauseManager: instance SAT.Mios.Vec.StackFamily SAT.Mios.ClauseManager.ClauseExtManager SAT.Mios.Clause.Clause
+ SAT.Mios.ClauseManager: instance SAT.Mios.Vec.VecFamily SAT.Mios.ClauseManager.ClauseExtManager SAT.Mios.Clause.Clause
+ SAT.Mios.ClauseManager: instance SAT.Mios.Vec.VecFamily SAT.Mios.ClauseManager.WatcherList SAT.Mios.Clause.Clause
+ SAT.Mios.Solver: EndOfStatIndex :: StatIndex
+ SAT.Mios.Solver: [an'lastDL] :: Solver -> !Stack
+ SAT.Mios.Solver: [conflicts] :: Solver -> !Stack
+ SAT.Mios.Solver: data VarHeap
+ SAT.Mios.Types: MiosConfiguration :: !Double -> MiosConfiguration
+ SAT.Mios.Types: [variableDecayRate] :: MiosConfiguration -> !Double
+ SAT.Mios.Types: data MiosConfiguration
+ SAT.Mios.Types: defaultConfiguration :: MiosConfiguration
+ SAT.Mios.Util.DIMACS: asDIMACSString :: BoolForm -> String
+ SAT.Mios.Util.DIMACS: asDIMACSString_ :: BoolForm -> String
+ SAT.Mios.Util.DIMACS: clauseListFromFile :: FilePath -> IO [[Int]]
+ SAT.Mios.Util.DIMACS: clauseListFromMinisatOutput :: FilePath -> IO [Int]
+ SAT.Mios.Util.DIMACS: fromFile :: FilePath -> IO (Maybe ((Int, Int), [[Int]]))
+ SAT.Mios.Util.DIMACS: fromMinisatOutput :: FilePath -> IO (Maybe ((Int, Int), [Int]))
+ SAT.Mios.Util.DIMACS: toDIMACSString :: [[Int]] -> String
+ SAT.Mios.Util.DIMACS: toFile :: FilePath -> [[Int]] -> IO ()
+ SAT.Mios.Util.DIMACS.MinisatReader: clauseListFromMinisatOutput :: FilePath -> IO [Int]
+ SAT.Mios.Util.DIMACS.MinisatReader: fromMinisatOutput :: FilePath -> IO (Maybe ((Int, Int), [Int]))
+ SAT.Mios.Util.DIMACS.Reader: clauseListFromFile :: FilePath -> IO [[Int]]
+ SAT.Mios.Util.DIMACS.Reader: fromFile :: FilePath -> IO (Maybe ((Int, Int), [[Int]]))
+ SAT.Mios.Util.DIMACS.Writer: toDIMACSString :: [[Int]] -> String
+ SAT.Mios.Util.DIMACS.Writer: toFile :: FilePath -> [[Int]] -> IO ()
+ SAT.Mios.Util.DIMACS.Writer: toLatexString :: [[Int]] -> String
+ SAT.Mios.Util.DIMACS.Writer: toString :: [[Int]] -> String -> String -> String
+ SAT.Mios.Vec: Vec :: (UVector a) -> Vec a
+ SAT.Mios.Vec: asList :: VecFamily v a => v -> IO [a]
+ SAT.Mios.Vec: asUVector :: (VecFamily v a, a ~ Int) => v -> UVector Int
+ SAT.Mios.Vec: class SingleStorage s t | s -> t where new' = undefined modify' = undefined
+ SAT.Mios.Vec: class SingleStorage s Int => StackFamily s t | s -> t where newStack = undefined pushTo = undefined popFrom = undefined lastOf = undefined shrinkBy = undefined
+ SAT.Mios.Vec: class VecFamily v a | v -> a where reset = error "no default method: reset" asUVector = error "no default method: asUVector" swapBetween = error "no default method: swapBetween" modifyNth = error "no default method: modifyNth" newVec = error "no default method: newVec" setAll = error "no default method: setAll" asList = error "no default method: asList" growBy = error "no default method: growBy"
+ SAT.Mios.Vec: get' :: SingleStorage s t => s -> IO t
+ SAT.Mios.Vec: getNth :: VecFamily v a => v -> Int -> IO a
+ SAT.Mios.Vec: growBy :: VecFamily v a => v -> Int -> IO v
+ SAT.Mios.Vec: instance SAT.Mios.Vec.SingleStorage SAT.Mios.Vec.Bool' GHC.Types.Bool
+ SAT.Mios.Vec: instance SAT.Mios.Vec.SingleStorage SAT.Mios.Vec.Double' GHC.Types.Double
+ SAT.Mios.Vec: instance SAT.Mios.Vec.SingleStorage SAT.Mios.Vec.Int' GHC.Types.Int
+ SAT.Mios.Vec: instance SAT.Mios.Vec.SingleStorage SAT.Mios.Vec.Stack GHC.Types.Int
+ SAT.Mios.Vec: instance SAT.Mios.Vec.StackFamily SAT.Mios.Vec.Stack GHC.Types.Int
+ SAT.Mios.Vec: instance SAT.Mios.Vec.VecFamily (SAT.Mios.Vec.UVector GHC.Types.Double) GHC.Types.Double
+ SAT.Mios.Vec: instance SAT.Mios.Vec.VecFamily (SAT.Mios.Vec.UVector GHC.Types.Int) GHC.Types.Int
+ SAT.Mios.Vec: instance SAT.Mios.Vec.VecFamily (SAT.Mios.Vec.Vec GHC.Types.Double) GHC.Types.Double
+ SAT.Mios.Vec: instance SAT.Mios.Vec.VecFamily (SAT.Mios.Vec.Vec GHC.Types.Int) GHC.Types.Int
+ SAT.Mios.Vec: lastOf :: StackFamily s t => s -> IO t
+ SAT.Mios.Vec: modify' :: SingleStorage s t => s -> (t -> t) -> IO ()
+ SAT.Mios.Vec: modifyNth :: VecFamily v a => v -> (a -> a) -> Int -> IO ()
+ SAT.Mios.Vec: new' :: SingleStorage s t => t -> IO s
+ SAT.Mios.Vec: newStack :: StackFamily s t => Int -> IO s
+ SAT.Mios.Vec: newStackFromList :: [Int] -> IO Stack
+ SAT.Mios.Vec: newVec :: VecFamily v a => Int -> a -> IO v
+ SAT.Mios.Vec: newtype Vec a
+ SAT.Mios.Vec: popFrom :: StackFamily s t => s -> IO ()
+ SAT.Mios.Vec: pushTo :: StackFamily s t => s -> t -> IO ()
+ SAT.Mios.Vec: reset :: VecFamily v a => v -> IO ()
+ SAT.Mios.Vec: set' :: SingleStorage s t => s -> t -> IO ()
+ SAT.Mios.Vec: setAll :: VecFamily v a => v -> a -> IO ()
+ SAT.Mios.Vec: setNth :: VecFamily v a => v -> Int -> a -> IO ()
+ SAT.Mios.Vec: shrinkBy :: StackFamily s t => s -> Int -> IO ()
+ SAT.Mios.Vec: swapBetween :: VecFamily v a => v -> Int -> Int -> IO ()
+ SAT.Mios.Vec: type Bool' = IOVector Bool
+ SAT.Mios.Vec: type Double' = IOVector Double
+ SAT.Mios.Vec: type Int' = IOVector Int
+ SAT.Mios.Vec: type Stack = Vec Int
+ SAT.Mios.Vec: type UVector a = IOVector a
- SAT.Mios.Clause: Clause :: !Bool -> !DoubleSingleton -> !BoolSingleton -> !Vec -> Clause
+ SAT.Mios.Clause: Clause :: !Bool -> !Double' -> !Bool' -> !Stack -> Clause
- SAT.Mios.Clause: [activity] :: Clause -> !DoubleSingleton
+ SAT.Mios.Clause: [activity] :: Clause -> !Double'
- SAT.Mios.Clause: [lits] :: Clause -> !Vec
+ SAT.Mios.Clause: [lits] :: Clause -> !Stack
- SAT.Mios.Clause: [protected] :: Clause -> !BoolSingleton
+ SAT.Mios.Clause: [protected] :: Clause -> !Bool'
- SAT.Mios.ClauseManager: getKeyVector :: ClauseExtManager -> IO Vec
+ SAT.Mios.ClauseManager: getKeyVector :: ClauseExtManager -> IO (UVector Int)
- SAT.Mios.Solver: Solver :: !VecBool -> !Stack -> !ClauseExtManager -> !ClauseExtManager -> !WatcherList -> !Vec -> !Vec -> !Stack -> !Stack -> !IntSingleton -> !ClauseVector -> !Vec -> !VecDouble -> !VarHeap -> !MiosConfiguration -> !Int -> !DoubleSingleton -> !IntSingleton -> !BoolSingleton -> !Vec -> !Stack -> !Stack -> !Vec -> !Stack -> !Stack -> !Vec -> Solver
+ SAT.Mios.Solver: Solver :: !(Vec Int) -> !Stack -> !ClauseExtManager -> !ClauseExtManager -> !WatcherList -> !(Vec Int) -> !(Vec Int) -> !Stack -> !Stack -> !Int' -> !ClauseVector -> !(Vec Int) -> !(Vec Double) -> !VarHeap -> !MiosConfiguration -> !Int -> !Double' -> !Int' -> !Bool' -> !(Vec Int) -> !Stack -> !Stack -> !Stack -> !Stack -> !(UVector Int) -> Solver
- SAT.Mios.Solver: [activities] :: Solver -> !VecDouble
+ SAT.Mios.Solver: [activities] :: Solver -> !(Vec Double)
- SAT.Mios.Solver: [an'seen] :: Solver -> !Vec
+ SAT.Mios.Solver: [an'seen] :: Solver -> !(Vec Int)
- SAT.Mios.Solver: [assigns] :: Solver -> !Vec
+ SAT.Mios.Solver: [assigns] :: Solver -> !(Vec Int)
- SAT.Mios.Solver: [level] :: Solver -> !Vec
+ SAT.Mios.Solver: [level] :: Solver -> !(Vec Int)
- SAT.Mios.Solver: [model] :: Solver -> !VecBool
+ SAT.Mios.Solver: [model] :: Solver -> !(Vec Int)
- SAT.Mios.Solver: [ok] :: Solver -> !BoolSingleton
+ SAT.Mios.Solver: [ok] :: Solver -> !Bool'
- SAT.Mios.Solver: [phases] :: Solver -> !Vec
+ SAT.Mios.Solver: [phases] :: Solver -> !(Vec Int)
- SAT.Mios.Solver: [qHead] :: Solver -> !IntSingleton
+ SAT.Mios.Solver: [qHead] :: Solver -> !Int'
- SAT.Mios.Solver: [rootLevel] :: Solver -> !IntSingleton
+ SAT.Mios.Solver: [rootLevel] :: Solver -> !Int'
- SAT.Mios.Solver: [stats] :: Solver -> !Vec
+ SAT.Mios.Solver: [stats] :: Solver -> !(UVector Int)
- SAT.Mios.Solver: [varInc] :: Solver -> !DoubleSingleton
+ SAT.Mios.Solver: [varInc] :: Solver -> !Double'
- SAT.Mios.Solver: addClause :: Solver -> Vec -> IO Bool
+ SAT.Mios.Solver: addClause :: Solver -> Stack -> IO Bool
- SAT.Mios.Types: class VarOrder o where newVarOrder _ _ = error "newVarOrder undefined" newVar = error "newVar undefined" update _ = error "update undefined" updateAll = error "updateAll undefined" undo _ _ = error "undo undefined" select = error "select undefined"
+ SAT.Mios.Types: class VarOrder o where update _ = error "update undefined" undo _ _ = error "undo undefined" select = error "select undefined"
- SAT.Mios.Types: int2var :: Integer -> Integer
+ SAT.Mios.Types: int2var :: Int -> Int
Files
- SAT/Mios.hs +38/−42
- SAT/Mios/Clause.hs +71/−70
- SAT/Mios/ClauseManager.hs +82/−174
- SAT/Mios/Data/Singleton.hs +0/−105
- SAT/Mios/Data/Stack.hs +0/−90
- SAT/Mios/Data/Vec.hs +0/−86
- SAT/Mios/Data/VecBool.hs +0/−55
- SAT/Mios/Data/VecDouble.hs +0/−53
- SAT/Mios/Internal.hs +0/−33
- SAT/Mios/Main.hs +163/−156
- SAT/Mios/OptionParser.hs +1/−2
- SAT/Mios/Solver.hs +180/−158
- SAT/Mios/Types.hs +54/−66
- SAT/Mios/Util/CNFIO.hs +0/−31
- SAT/Mios/Util/CNFIO/MinisatReader.hs +0/−73
- SAT/Mios/Util/CNFIO/Reader.hs +0/−130
- SAT/Mios/Util/CNFIO/Writer.hs +0/−58
- SAT/Mios/Util/DIMACS.hs +31/−0
- SAT/Mios/Util/DIMACS/MinisatReader.hs +73/−0
- SAT/Mios/Util/DIMACS/Reader.hs +130/−0
- SAT/Mios/Util/DIMACS/Writer.hs +58/−0
- SAT/Mios/Validator.hs +3/−4
- SAT/Mios/Vec.hs +276/−0
- app/sample.hs +26/−0
- mios.cabal +33/−31
SAT/Mios.hs view
@@ -1,7 +1,7 @@--- | Minisat-based Implementation and Optimization Study on SAT solver {-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE Safe #-} +-- | Minisat-based Implementation and Optimization Study on SAT solver module SAT.Mios ( -- * Interface to the core of solver@@ -36,12 +36,15 @@ import System.IO import SAT.Mios.Types-import SAT.Mios.Internal import SAT.Mios.Solver import SAT.Mios.Main import SAT.Mios.OptionParser import SAT.Mios.Validator +-- | version name+versionId :: String+versionId = "mios 1.4.0 -- https://github.com/shnarazk/mios"+ reportElapsedTime :: Bool -> String -> Integer -> IO Integer reportElapsedTime False _ _ = return 0 reportElapsedTime _ _ 0 = getCPUTime@@ -52,13 +55,13 @@ hPutStrLn stderr $ showFFloat (Just 3) ((fromIntegral (now - t)) / toSecond) " sec" return now --- | executes a solver on the given CNF file--- This is the simplest entry to standalone programs; not for Haskell programs+-- | executes a solver on the given CNF file.+-- This is the simplest entry to standalone programs; not for Haskell programs. executeSolverOn :: FilePath -> IO () executeSolverOn path = executeSolver (miosDefaultOption { _targetFile = Just path }) --- | executes a solver on the given 'arg :: MiosConfiguration'--- | This is another entry point for standalone programs.+-- | executes a solver on the given 'arg :: MiosConfiguration'.+-- This is another entry point for standalone programs. executeSolver :: MiosProgramOption -> IO () executeSolver opts@(_targetFile -> target@(Just cnfFile)) = do t0 <- reportElapsedTime (_confTimeProbe opts) "" 0@@ -102,7 +105,7 @@ executeSolver _ = return () --- | new top-level interface that returns+-- | new top-level interface that returns: -- -- * conflicting literal set :: Left [Int] -- * satisfiable assignment :: Right [Int]@@ -110,31 +113,30 @@ runSolver :: Traversable t => MiosConfiguration -> CNFDescription -> t [Int] -> IO (Either [Int] [Int]) runSolver m d c = do s <- newSolver m d- mapM_ ((s `addClause`) <=< (newSizedVecIntFromList . map int2lit)) c+ mapM_ ((s `addClause`) <=< (newStackFromList . map int2lit)) c noConf <- simplifyDB s if noConf then do x <- solve s [] if x then Right <$> getModel s- else Left . map lit2int <$> asList (conflict s)+ else Left . map lit2int <$> asList (conflicts s) else return $ Left [] ---- | the easiest interface for Haskell programs--- This returns the result @::[[Int]]@ for a given @(CNFDescription, [[Int]])@+-- | The easiest interface for Haskell programs.+-- This returns the result @::[[Int]]@ for a given @(CNFDescription, [[Int]])@. -- The first argument @target@ can be build by @Just target <- cnfFromFile targetfile@.--- The second part of the first argument is a list of vector, which 0th element is the number of its real elements+-- The second part of the first argument is a list of vector, which 0th element is the number of its real elements. solveSAT :: Traversable m => CNFDescription -> m [Int] -> IO [Int] solveSAT = solveSATWithConfiguration defaultConfiguration --- | solves the problem (2rd arg) under the configuration (1st arg)--- and returns an assignment as list of literals :: Int+-- | solves the problem (2rd arg) under the configuration (1st arg).+-- and returns an assignment as list of literals :: Int. solveSATWithConfiguration :: Traversable m => MiosConfiguration -> CNFDescription -> m [Int] -> IO [Int] solveSATWithConfiguration conf desc cls = do s <- newSolver conf desc -- mapM_ (const (newVar s)) [0 .. _numberOfVariables desc - 1]- mapM_ ((s `addClause`) <=< (newSizedVecIntFromList . map int2lit)) cls+ mapM_ ((s `addClause`) <=< (newStackFromList . map int2lit)) cls noConf <- simplifyDB s if noConf then do@@ -144,13 +146,13 @@ else return [] else return [] --- | validates a given assignment from STDIN for the CNF file (2nd arg)--- this is the entry point for standalone programs+-- | validates a given assignment from STDIN for the CNF file (2nd arg).+-- this is the entry point for standalone programs. executeValidatorOn :: FilePath -> IO () executeValidatorOn path = executeValidator (miosDefaultOption { _targetFile = Just path }) --- | validates a given assignment for the problem (2nd arg)--- this is another entry point for standalone programs; see app/mios.hs+-- | validates a given assignment for the problem (2nd arg).+-- This is another entry point for standalone programs; see app/mios.hs. executeValidator :: MiosProgramOption -> IO () executeValidator opts@(_targetFile -> target@(Just cnfFile)) = do (desc, cls) <- parseHeader target <$> B.readFile cnfFile@@ -172,13 +174,13 @@ executeValidator _ = return () --- | returns True if a given assignment (2nd arg) satisfies the problem (1st arg)+-- | returns True if a given assignment (2nd arg) satisfies the problem (1st arg). -- if you want to check the @answer@ which a @slover@ returned, run @solver `validate` answer@,--- where 'validate' @ :: Traversable t => Solver -> t Lit -> IO Bool@+-- where 'validate' @ :: Traversable t => Solver -> t Lit -> IO Bool@. validateAssignment :: (Traversable m, Traversable n) => CNFDescription -> m [Int] -> n Int -> IO Bool validateAssignment desc cls asg = do s <- newSolver defaultConfiguration desc- mapM_ ((s `addClause`) <=< (newSizedVecIntFromList . map int2lit)) cls+ mapM_ ((s `addClause`) <=< (newStackFromList . map int2lit)) cls s `validate` asg -- | dumps an assigment to file.@@ -192,13 +194,10 @@ -- dumpAssigmentAsCNF :: FilePath -> Bool -> [Int] -> IO () dumpAssigmentAsCNF fname False _ = do- withFile fname WriteMode $ \h -> do- hPutStrLn h "UNSAT"+ withFile fname WriteMode $ \h -> hPutStrLn h "UNSAT" dumpAssigmentAsCNF fname True l = do- withFile fname WriteMode $ \h -> do- hPutStrLn h "SAT"- hPutStrLn h . unwords $ map show l+ withFile fname WriteMode $ \h -> do hPutStrLn h "SAT"; hPutStrLn h . unwords $ map show l -------------------------------------------------------------------------------- -- DIMACS CNF Reader@@ -218,8 +217,8 @@ parseClauses :: Solver -> CNFDescription -> B.ByteString -> IO () parseClauses s (CNFDescription nv nc _) bs = do let maxLit = int2lit $ negate nv- buffer <- newVec $ maxLit + 1- polvec <- newVecBool (maxLit + 1) False+ buffer <- newVec (maxLit + 1) 0+ polvec <- newVec (maxLit + 1) 0 let loop :: Int -> B.ByteString -> IO () loop ((< nc) -> False) _ = return ()@@ -231,9 +230,9 @@ checkPolarity :: Int -> IO () checkPolarity ((< nv) -> False) = return () checkPolarity v = do- p <- getNthBool polvec $ var2lit v True- n <- getNthBool polvec $ var2lit v False- when (p == False || n == False) $ setNth asg v $ if p then lTrue else lFalse+ p <- getNth polvec $ var2lit v True+ n <- getNth polvec $ var2lit v False+ when (p == lFalse || n == lFalse) $ setNth asg v p checkPolarity $ v + 1 checkPolarity 1 @@ -267,8 +266,8 @@ c | '0' <= c && c <= '9' -> loop st 0 _ -> error "PARSE ERROR! Unexpected char" -readClause :: Solver -> Vec -> VecBool -> B.ByteString -> IO B.ByteString-readClause s buffer pvec stream = do+readClause :: Solver -> Stack -> Vec Int -> B.ByteString -> IO B.ByteString+readClause s buffer bvec stream = do let loop :: Int -> B.ByteString -> IO B.ByteString loop i b = do@@ -277,20 +276,17 @@ then do -- putStrLn . ("clause: " ++) . show . map lit2int =<< asList stack setNth buffer 0 $ i - 1- addClause s buffer+ void $ addClause s buffer return b' else do let l = int2lit k setNth buffer i l- setNthBool pvec l True+ setNth bvec l lTrue loop (i + 1) b' loop 1 . skipComments . skipWhitespace $ stream - showPath :: FilePath -> String-showPath str- | elem '/' str = take (len - length basename) (repeat ' ') ++ basename- | otherwise = take (len - length basename') (repeat ' ') ++ basename'+showPath str = replicate (len - length basename) ' ' ++ if elem '/' str then basename else basename' where len = 50 basename = reverse . takeWhile (/= '/') . reverse $ str
SAT/Mios/Clause.hs view
@@ -14,37 +14,29 @@ Clause (..) -- , isLit -- , getLit- , shrinkClause- , newClauseFromVec- , sizeOfClause+ , newClauseFromStack -- * Vector of Clause , ClauseVector , newClauseVector- , getNthClause- , setNthClause- , swapClauses ) where -import Control.Monad (forM_) import GHC.Prim (tagToEnum#, reallyUnsafePtrEquality#) import qualified Data.Vector as V import qualified Data.Vector.Mutable as MV-import qualified Data.Vector.Unboxed.Mutable as UV-import Data.List (intercalate)+-- import Data.List (intercalate) import SAT.Mios.Types -- | __Fig. 7.(p.11)__--- clause, null, binary clause.--- This matches both of @Clause@ and @GClause@ in MiniSat--- TODO: GADTs is better?+-- normal, null (and binary) clause.+-- This matches both of @Clause@ and @GClause@ in MiniSat. data Clause = Clause {- learnt :: !Bool -- ^ whether this is a learnt clause--- , rank :: !IntSingleton -- ^ goodness like LBD; computed in 'Ranking'- , activity :: !DoubleSingleton -- ^ activity of this clause- , protected :: !BoolSingleton -- ^ protected from reduce- , lits :: !Vec -- ^ which this clause consists of+ learnt :: !Bool -- ^ whether this is a learnt clause+-- , rank :: !Int' -- ^ goodness like LBD; computed in 'Ranking'+ , activity :: !Double' -- ^ activity of this clause+ , protected :: !Bool' -- ^ protected from reduce+ , lits :: !Stack -- ^ which this clause consists of } | NullClause -- as null pointer -- | BinaryClause Lit -- binary clause consists of only a propagating literal@@ -58,87 +50,96 @@ show NullClause = "NullClause" show _ = "a clause" --- | supports a restricted set of 'VectorFamily' methods-instance VectorFamily Clause Lit where- dump mes NullClause = return $ mes ++ "Null"- dump mes Clause{..} = do- a <- show <$> getDouble activity- (len:ls) <- asList lits- return $ mes ++ "C" ++ show len ++ "{" ++ intercalate "," [show learnt, a, show . map lit2int . take len $ ls] ++ "}"- {-# SPECIALIZE INLINE asVec :: Clause -> Vec #-}- asVec Clause{..} = UV.unsafeTail lits- {-# SPECIALIZE INLINE asList :: Clause -> IO [Int] #-}+-- | 'Clause' is a 'VecFamily' of 'Lit'.+instance VecFamily Clause Lit where+ {-# SPECIALIZE INLINE getNth :: Clause -> Int -> IO Int #-}+ getNth Clause{..} n = error "no getNth for Clause"+ {-# SPECIALIZE INLINE setNth :: Clause -> Int -> Int -> IO () #-}+ setNth Clause{..} n x = error "no setNth for Clause"+ -- | returns a vector of literals in it.+ {-# SPECIALIZE INLINE asUVector :: Clause -> UVector Int #-}+ asUVector = asUVector . lits asList NullClause = return []- asList Clause{..} = do- (n : ls) <- asList lits- return $ take n ls+ asList Clause{..} = take <$> get' lits <*> asList lits+ -- dump mes NullClause = return $ mes ++ "Null"+ -- dump mes Clause{..} = return $ mes ++ "a clause"+{-+ dump mes Clause{..} = do+ a <- show <$> get' activity+ n <- get' lits+ l <- asList lits+ return $ mes ++ "C" ++ show n ++ "{" ++ intercalate "," [show learnt, a, show (map lit2int l)] ++ "}"+-} --- returns True if it is a 'BinaryClause'+-- | 'Clause' is a 'SingleStorage' on the number of literals in it.+instance SingleStorage Clause Int where+ -- | returns the number of literals in a clause, even if the given clause is a binary clause+ {-# SPECIALIZE INLINE get' :: Clause -> IO Int #-}+ get' = get' . lits+ -- getSize (BinaryClause _) = return 1+ -- | sets the number of literals in a clause, even if the given clause is a binary clause+ {-# SPECIALIZE INLINE set' :: Clause -> Int -> IO () #-}+ set' c n = set' (lits c) n+ -- getSize (BinaryClause _) = return 1++-- | 'Clause' is a 'Stackfamily'on literals since literals in it will be discared if satisifed at level = 0.+instance StackFamily Clause Lit where+ -- | drop the last /N/ literals in a 'Clause' to eliminate unsatisfied literals+ {-# SPECIALIZE INLINE shrinkBy :: Clause -> Int -> IO () #-}+ shrinkBy c n = modifyNth (lits c) (subtract n) 0++-- returns True if it is a 'BinaryClause'. -- FIXME: this might be discarded in minisat 2.2 -- isLit :: Clause -> Bool -- isLit (BinaryClause _) = True -- isLit _ = False --- returns the literal in a BinaryClause+-- returns the literal in a BinaryClause. -- FIXME: this might be discarded in minisat 2.2 -- getLit :: Clause -> Lit -- getLit (BinaryClause x) = x --- coverts a binary clause to normal clause in order to reuse map-on-literals-in-a-clause codes+-- coverts a binary clause to normal clause in order to reuse map-on-literals-in-a-clause codes. -- liftToClause :: Clause -> Clause -- liftToClause (BinaryClause _) = error "So far I use generic function approach instead of lifting" --- | copies /vec/ and return a new 'Clause'+-- | copies /vec/ and return a new 'Clause'. -- Since 1.0.100 DIMACS reader should use a scratch buffer allocated statically.-{-# INLINE newClauseFromVec #-}-newClauseFromVec :: Bool -> Vec -> IO Clause-newClauseFromVec l vec = do- n <- getNth vec 0- v <- newVec $ n + 1- forM_ [0 .. n] $ \i -> setNth v i =<< getNth vec i- Clause l <$> {- newInt 0 <*> -} newDouble 0 <*> newBool False <*> return v---- | returns the number of literals in a clause, even if the given clause is a binary clause-{-# INLINE sizeOfClause #-}-sizeOfClause :: Clause -> IO Int--- sizeOfClause (BinaryClause _) = return 1-sizeOfClause !c = getNth (lits c) 0---- | drop the last /N/ literals in a 'Clause' to eliminate unsatisfied literals-{-# INLINABLE shrinkClause #-}-shrinkClause :: Int -> Clause -> IO ()-shrinkClause n !c = modifyNth (lits c) (subtract n) 0+{-# INLINABLE newClauseFromStack #-}+newClauseFromStack :: Bool -> Stack -> IO Clause+newClauseFromStack l vec = do+ n <- get' vec+ v <- newStack n+ let+ loop ((<= n) -> False) = return ()+ loop i = (setNth v i =<< getNth vec i) >> loop (i + 1)+ loop 0+ Clause l <$> {- new' 0 <*> -} new' 0.0 <*> new' False <*> return v ---------------------------------------------------------------------------------+-------------------------------------------------------------------------------- Clause Vector -- | Mutable 'Clause' Vector type ClauseVector = MV.IOVector Clause -instance VectorFamily ClauseVector Clause where+-- | 'ClauseVector' is a vector of 'Clause'.+instance VecFamily ClauseVector Clause where+ {-# SPECIALIZE INLINE getNth :: ClauseVector -> Int -> IO Clause #-}+ getNth = MV.unsafeRead+ {-# SPECIALIZE INLINE setNth :: ClauseVector -> Int -> Clause -> IO () #-}+ setNth = MV.unsafeWrite+ {-# SPECIALIZE INLINE swapBetween :: ClauseVector -> Int -> Int -> IO () #-}+ swapBetween = MV.unsafeSwap asList cv = V.toList <$> V.freeze cv+{- dump mes cv = do l <- asList cv sts <- mapM (dump ",") (l :: [Clause]) return $ mes ++ tail (concat sts)+-} --- | returns a new 'ClauseVector'+-- | returns a new 'ClauseVector'. newClauseVector :: Int -> IO ClauseVector newClauseVector n = do v <- MV.new (max 4 n) MV.set v NullClause return v---- | returns the nth 'Clause'-{-# INLINE getNthClause #-}-getNthClause :: ClauseVector -> Int -> IO Clause-getNthClause = MV.unsafeRead---- | sets the nth 'Clause'-{-# INLINE setNthClause #-}-setNthClause :: ClauseVector -> Int -> Clause -> IO ()-setNthClause = MV.unsafeWrite---- | swaps the two 'Clause's-{-# INLINE swapClauses #-}-swapClauses :: ClauseVector -> Int -> Int -> IO ()-swapClauses = MV.unsafeSwap
SAT/Mios/ClauseManager.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE BangPatterns- , DuplicateRecordFields , FlexibleInstances , MultiParamTypeClasses , RecordWildCards@@ -13,8 +12,6 @@ ( -- * higher level interface for ClauseVector ClauseManager (..)--- -- * vector of clauses--- , SimpleManager -- * Manager with an extra Int (used as sort key or blocking literal) , ClauseExtManager , pushClauseWithKey@@ -25,152 +22,99 @@ , WatcherList , newWatcherList , getNthWatcher- , garbageCollect--- , numberOfRegisteredClauses ) where -import Control.Monad (forM, unless, when)+import Control.Monad (unless, when) import qualified Data.IORef as IORef-import qualified Data.List as L import qualified Data.Vector as V import qualified Data.Vector.Mutable as MV import SAT.Mios.Types import qualified SAT.Mios.Clause as C --- | resizable clause vector+-- | Resizable vector of 'C.Clause'. class ClauseManager a where newManager :: Int -> IO a- numberOfClauses :: a -> IO Int- clearManager :: a -> IO ()- shrinkManager :: a -> Int -> IO () getClauseVector :: a -> IO C.ClauseVector- pushClause :: a -> C.Clause -> IO () -- removeClause :: a -> C.Clause -> IO () -- removeNthClause :: a -> Int -> IO () -{---- | The Clause Container-data SimpleManager = SimpleManager+--------------------------------------------------------------------------------++-- | Clause + Blocking Literal+data ClauseExtManager = ClauseExtManager {- _nActives :: IntSingleton -- number of active clause- , _clauseVector :: IORef.IORef C.ClauseVector -- clause list+ _nActives :: !Int' -- number of active clause+ , _purged :: !Bool' -- whether it needs gc+ , _clauseVector :: IORef.IORef C.ClauseVector -- clause list+ , _keyVector :: IORef.IORef (UVector Int) -- Int list } -instance ClauseManager SimpleManager where- {-# SPECIALIZE INLINE newManager :: Int -> IO SimpleManager #-}- newManager initialSize = do- i <- newInt 0- v <- C.newClauseVector initialSize- SimpleManager i <$> IORef.newIORef v- {-# SPECIALIZE INLINE numberOfClauses :: SimpleManager -> IO Int #-}- numberOfClauses SimpleManager{..} = getInt _nActives- {-# SPECIALIZE INLINE clearManager :: SimpleManager -> IO () #-}- clearManager SimpleManager{..} = setInt _nActives 0- {-# SPECIALIZE INLINE shrinkManager :: SimpleManager -> Int -> IO () #-}- shrinkManager SimpleManager{..} k = modifyInt _nActives (subtract k)- {-# SPECIALIZE INLINE getClauseVector :: SimpleManager -> IO C.ClauseVector #-}- getClauseVector SimpleManager{..} = IORef.readIORef _clauseVector- -- | O(1) inserter- {-# SPECIALIZE INLINE pushClause :: SimpleManager -> C.Clause -> IO () #-}- pushClause !SimpleManager{..} !c = do- !n <- getInt _nActives+-- | 'ClauseExtManager' is a 'SingleStorage` on the numeber of clauses in it.+instance SingleStorage ClauseExtManager Int where+ {-# SPECIALIZE INLINE get' :: ClauseExtManager -> IO Int #-}+ get' m = get' (_nActives m)+ {-# SPECIALIZE INLINE set' :: ClauseExtManager -> Int -> IO () #-}+ set' m = set' (_nActives m)++-- | 'ClauseExtManager' is a 'StackFamily` on clauses.+instance StackFamily ClauseExtManager C.Clause where+ {-# SPECIALIZE INLINE shrinkBy :: ClauseExtManager -> Int -> IO () #-}+ shrinkBy m k = modify' (_nActives m) (subtract k)+ pushTo ClauseExtManager{..} c = do+ -- checkConsistency m c+ !n <- get' _nActives !v <- IORef.readIORef _clauseVector+ !b <- IORef.readIORef _keyVector if MV.length v - 1 <= n then do- v' <- MV.unsafeGrow v (max 8 (MV.length v))- -- forM_ [n .. MV.length v' - 1] $ \i -> MV.unsafeWrite v' i C.NullClause+ let len = max 8 $ MV.length v+ v' <- MV.unsafeGrow v len+ b' <- growBy b len MV.unsafeWrite v' n c+ setNth b' n 0 IORef.writeIORef _clauseVector v'- else MV.unsafeWrite v n c- modifyInt _nActives (1 +)- -- | O(1) remove-and-compact function- {-# SPECIALIZE INLINE removeNthClause :: SimpleManager -> Int -> IO () #-}- removeNthClause SimpleManager{..} i = do- !n <- subtract 1 <$> getInt _nActives- !v <- IORef.readIORef _clauseVector- MV.unsafeWrite v i =<< MV.unsafeRead v n- setInt _nActives n- -- | O(n) but lightweight remove-and-compact function- -- __Pre-conditions:__ the clause manager is empty or the clause is stored in it.- {-# SPECIALIZE INLINE removeClause :: SimpleManager -> C.Clause -> IO () #-}- removeClause SimpleManager{..} c = do- -- putStrLn =<< dump "@removeClause| remove " c- -- putStrLn =<< dump "@removeClause| from " m- !n <- subtract 1 <$> getInt _nActives- -- unless (0 <= n) $ error $ "removeClause catches " ++ show n- !v <- IORef.readIORef _clauseVector- let- seekIndex :: Int -> IO Int- seekIndex k = do- c' <- MV.unsafeRead v k- if c' == c then return k else seekIndex $ k + 1- unless (n == -1) $ do- !i <- seekIndex 0- MV.unsafeWrite v i =<< MV.unsafeRead v n- setInt _nActives n--instance VectorFamily SimpleManager C.Clause where- dump mes SimpleManager{..} = do- n <- getInt _nActives- if n == 0- then return $ mes ++ "empty clausemanager"- else do- l <- take n <$> (asList =<< IORef.readIORef _clauseVector)- sts <- mapM (dump ",") (l :: [C.Clause])- return $ mes ++ "[" ++ show n ++ "]" ++ tail (concat sts)--}-------------------------------------------------------------------------------------- | Clause + Blocking Literal-data ClauseExtManager = ClauseExtManager- {- _nActives :: !IntSingleton -- number of active clause- , _purged :: !BoolSingleton -- whether it needs gc- , _clauseVector :: IORef.IORef C.ClauseVector -- clause list- , _keyVector :: IORef.IORef Vec -- Int list- }+ IORef.writeIORef _keyVector b'+ else MV.unsafeWrite v n c >> setNth b n 0+ modify' _nActives (1 +) +-- | 'ClauseExtManager' is a 'ClauseManager' instance ClauseManager ClauseExtManager where+ -- | returns a new instance. {-# SPECIALIZE INLINE newManager :: Int -> IO ClauseExtManager #-} newManager initialSize = do- i <- newInt 0+ i <- new' 0 v <- C.newClauseVector initialSize- b <- newVec (MV.length v)- ClauseExtManager i <$> newBool False <*> IORef.newIORef v <*> IORef.newIORef b- {-# SPECIALIZE INLINE numberOfClauses :: ClauseExtManager -> IO Int #-}- numberOfClauses !m = getInt (_nActives m)- {-# SPECIALIZE INLINE clearManager :: ClauseExtManager -> IO () #-}- clearManager !m = setInt (_nActives m) 0- {-# SPECIALIZE INLINE shrinkManager :: ClauseExtManager -> Int -> IO () #-}- shrinkManager !m k = modifyInt (_nActives m) (subtract k)+ b <- newVec (MV.length v) 0+ ClauseExtManager i <$> new' False <*> IORef.newIORef v <*> IORef.newIORef b+ -- | returns the internal 'C.ClauseVector'. {-# SPECIALIZE INLINE getClauseVector :: ClauseExtManager -> IO C.ClauseVector #-} getClauseVector !m = IORef.readIORef (_clauseVector m)+{- -- | O(1) insertion function- {-# SPECIALIZE INLINE pushClause :: ClauseExtManager -> C.Clause -> IO () #-} pushClause !ClauseExtManager{..} !c = do -- checkConsistency m c- !n <- getInt _nActives+ !n <- get' _nActives !v <- IORef.readIORef _clauseVector !b <- IORef.readIORef _keyVector if MV.length v - 1 <= n then do let len = max 8 $ MV.length v v' <- MV.unsafeGrow v len- b' <- vecGrow b len+ b' <- growBy b len MV.unsafeWrite v' n c setNth b' n 0 IORef.writeIORef _clauseVector v' IORef.writeIORef _keyVector b' else MV.unsafeWrite v n c >> setNth b n 0- modifyInt _nActives (1 +)+ modify' _nActives (1 +)+-} {- -- | O(n) but lightweight remove-and-compact function -- __Pre-conditions:__ the clause manager is empty or the clause is stored in it. {-# SPECIALIZE INLINE removeClause :: ClauseExtManager -> C.Clause -> IO () #-} removeClause ClauseExtManager{..} c = do- !n <- subtract 1 <$> getInt _nActives+ !n <- subtract 1 <$> get' _nActives !v <- IORef.readIORef _clauseVector !b <- IORef.readIORef _keyVector let@@ -182,15 +126,15 @@ !i <- seekIndex 0 MV.unsafeWrite v i =<< MV.unsafeRead v n setNth b i =<< getNth b n- setInt _nActives n+ set' _nActives n removeNthClause = error "removeNthClause is not implemented on ClauseExtManager" -} --- | sets the expire flag to a clause-{-# INLINE markClause #-}+-- | sets the expire flag to a clause.+{-# INLINABLE markClause #-} markClause :: ClauseExtManager -> C.Clause -> IO () markClause ClauseExtManager{..} c = do- !n <- getInt _nActives+ !n <- get' _nActives !v <- IORef.readIORef _clauseVector let seekIndex :: Int -> IO ()@@ -199,128 +143,92 @@ if c' == c then MV.unsafeWrite v k C.NullClause else seekIndex $ k + 1 unless (n == 0) $ do seekIndex 0- setBool _purged True+ set' _purged True -{-# INLINE purifyManager #-}+{-# INLINABLE purifyManager #-} purifyManager :: ClauseExtManager -> IO () purifyManager ClauseExtManager{..} = do- diry <- getBool _purged+ diry <- get' _purged when diry $ do- n <- getInt _nActives+ n <- get' _nActives vec <- IORef.readIORef _clauseVector keys <- IORef.readIORef _keyVector let loop :: Int -> Int -> IO Int loop ((< n) -> False) n' = return n' loop i j = do- c <- C.getNthClause vec i+ c <- getNth vec i if c /= C.NullClause then do unless (i == j) $ do- C.setNthClause vec j c+ setNth vec j c setNth keys j =<< getNth keys i loop (i + 1) (j + 1) else loop (i + 1) j- setInt _nActives =<< loop 0 0- setBool _purged False+ set' _nActives =<< loop 0 0+ set' _purged False --- | returns the associated Int vector+-- | returns the associated Int vector, which holds /blocking literals/. {-# INLINE getKeyVector #-}-getKeyVector :: ClauseExtManager -> IO Vec+getKeyVector :: ClauseExtManager -> IO (UVector Int) getKeyVector ClauseExtManager{..} = IORef.readIORef _keyVector -- | O(1) inserter-{-# INLINE pushClauseWithKey #-}+{-# INLINABLE pushClauseWithKey #-} pushClauseWithKey :: ClauseExtManager -> C.Clause -> Lit -> IO () pushClauseWithKey !ClauseExtManager{..} !c k = do -- checkConsistency m c- !n <- getInt _nActives+ !n <- get' _nActives !v <- IORef.readIORef _clauseVector !b <- IORef.readIORef _keyVector if MV.length v - 1 <= n then do let len = max 8 $ MV.length v v' <- MV.unsafeGrow v len- b' <- vecGrow b len+ b' <- growBy b len MV.unsafeWrite v' n c setNth b' n k IORef.writeIORef _clauseVector v' IORef.writeIORef _keyVector b' else MV.unsafeWrite v n c >> setNth b n k- modifyInt _nActives (1 +)+ modify' _nActives (1 +) -instance VectorFamily ClauseExtManager C.Clause where+-- | 'ClauseExtManager' is a collection of 'C.Clause'+instance VecFamily ClauseExtManager C.Clause where+ getNth = error "no getNth method for ClauseExtManager"+ setNth = error "no setNth method for ClauseExtManager"+ {-# SPECIALIZE INLINE reset :: ClauseExtManager -> IO () #-}+ reset m = set' (_nActives m) 0+{- dump mes ClauseExtManager{..} = do- n <- getInt _nActives+ n <- get' _nActives if n == 0 then return $ mes ++ "empty ClauseExtManager" else do l <- take n <$> (asList =<< IORef.readIORef _clauseVector) sts <- mapM (dump ",") (l :: [C.Clause]) return $ mes ++ "[" ++ show n ++ "]" ++ tail (concat sts)+-} -------------------------------------------------------------------------------- WatcherList --- | Vector of 'ClauseExtManager'+-- | Immutable Vector of 'ClauseExtManager' type WatcherList = V.Vector ClauseExtManager --- | /n/ is the number of 'Var', /m/ is default size of each watcher list+-- | /n/ is the number of 'Var', /m/ is default size of each watcher list. -- | For /n/ vars, we need [0 .. 2 + 2 * n - 1] slots, namely /2 * (n + 1)/-length vector newWatcherList :: Int -> Int -> IO WatcherList-newWatcherList n m = V.fromList <$> forM [0 .. int2lit (negate n) + 1] (\_ -> newManager m)+newWatcherList n m = V.fromList <$> mapM (\_ -> newManager m) [0 .. int2lit (negate n) + 1] --- | returns the watcher List :: "ClauseManager" for "Literal" /l/+-- | returns the watcher List for "Literal" /l/. {-# INLINE getNthWatcher #-} getNthWatcher :: WatcherList -> Lit -> ClauseExtManager getNthWatcher = V.unsafeIndex -instance VectorFamily WatcherList C.Clause where- dump mes wl = (mes ++) . L.concat <$> forM [1 .. V.length wl - 1] (\i -> dump ("\n" ++ show (lit2int i) ++ "' watchers:") (getNthWatcher wl i))---- | purges all expirable clauses in 'WatcherList'-{-# INLINE garbageCollect #-}-garbageCollect :: WatcherList -> IO ()-garbageCollect = V.mapM_ purifyManager--{--numberOfRegisteredClauses :: WatcherList -> IO Int-numberOfRegisteredClauses ws = sum <$> V.mapM numberOfClauses ws--}--{---------------------------------------------------------------------------------- debugging stuff--checkConsistency :: ClauseManager a => a -> C.Clause -> IO ()-checkConsistency manager c = do- nc <- numberOfClauses manager- vec <- getClauseVector manager- let- loop :: Int -> IO ()- loop i = do- when (i < nc) $ do- c' <- MV.unsafeRead vec i- when (c' == c) $ error "insert a clause to a ClauseMananger twice"- loop $ i + 1- loop 0--checkClauseOrder :: ClauseManager a => a -> IO ()-checkClauseOrder manager = do- putStr "checking..."- nc <- numberOfClauses manager- vec <- getClauseVector manager- let- nthActivity :: Int -> IO Double- nthActivity i = getDouble . C.activity =<< MV.unsafeRead vec i- report :: Int -> Int -> IO ()- report i j = (putStr . (++ ", ") . show =<< nthActivity i) >> when (i < j) (report (i + 1) j)- loop :: Int -> Double -> IO ()- loop i v = do- when (i < nc) $ do- c <- MV.unsafeRead vec i- a <- getDouble (C.activity c)- when (c == C.NullClause) $ error "null is included"- when (v < a) $ report 0 i >> error ("unsorted clause vector: " ++ show (nc, i))- loop (i + 1) a- loop 0 =<< nthActivity 0- putStrLn "done"--}+-- | 'WatcherList' is an 'Lit'-indexed collection of 'C.Clause'.+instance VecFamily WatcherList C.Clause where+ getNth = error "no getNth method for WatcherList" -- getNthWatcher is a pure function+ setNth = error "no setNth method for WatcherList"+ {-# SPECIALIZE INLINE reset :: WatcherList -> IO () #-}+ reset = V.mapM_ purifyManager+-- dump _ _ = (mes ++) . concat <$> mapM (\i -> dump ("\n" ++ show (lit2int i) ++ "' watchers:") (getNthWatcher wl i)) [1 .. V.length wl - 1]
− SAT/Mios/Data/Singleton.hs
@@ -1,105 +0,0 @@-{-# LANGUAGE- BangPatterns- #-}-{-# LANGUAGE Trustworthy #-}---- | A fast(est) mutable data based on Data.Vector.Unboxed.Mutable--module SAT.Mios.Data.Singleton- (- -- * Bool- BoolSingleton- , newBool- , getBool- , setBool- , modifyBool- -- * Int- , IntSingleton- , newInt- , getInt- , setInt- , modifyInt- -- * Double- , DoubleSingleton- , newDouble- , getDouble- , setDouble- , modifyDouble- )- where-import qualified Data.Vector.Unboxed.Mutable as UV---- | mutable Int-type IntSingleton = UV.IOVector Int---- | returns a new 'IntSingleton'-newInt :: Int -> IO IntSingleton-newInt k = do- s <- UV.new 1- UV.unsafeWrite s 0 k- return s---- | returns the value-{-# INLINE getInt #-}-getInt :: IntSingleton -> IO Int-getInt val = UV.unsafeRead val 0---- | sets the value-{-# INLINE setInt #-}-setInt :: IntSingleton -> Int -> IO ()-setInt val !x = UV.unsafeWrite val 0 x---- | modifies the value-{-# INLINE modifyInt #-}-modifyInt :: IntSingleton -> (Int -> Int) -> IO ()-modifyInt val f = UV.unsafeModify val f 0---- | mutable Bool-type BoolSingleton = UV.IOVector Bool---- | returns a new 'BoolSingleton'-newBool :: Bool -> IO BoolSingleton-newBool b = do- s <- UV.new 1- UV.unsafeWrite s 0 b- return s---- | returns the value-{-# INLINE getBool #-}-getBool :: BoolSingleton -> IO Bool-getBool val = UV.unsafeRead val 0---- | sets the value-{-# INLINE setBool #-}-setBool :: BoolSingleton -> Bool -> IO ()-setBool val !x = UV.unsafeWrite val 0 x---- | modifies the value-{-# INLINE modifyBool #-}-modifyBool :: BoolSingleton -> (Bool -> Bool) -> IO ()-modifyBool val f = UV.unsafeModify val f 0---- | mutable Double-type DoubleSingleton = UV.IOVector Double---- | returns a new 'DoubleSingleton'-newDouble :: Double -> IO DoubleSingleton-newDouble d = do- s <- UV.new 1- UV.unsafeWrite s 0 d- return s---- | returns the value-{-# INLINE getDouble #-}-getDouble :: DoubleSingleton -> IO Double-getDouble val = UV.unsafeRead val 0---- | sets the value-{-# INLINE setDouble #-}-setDouble :: DoubleSingleton -> Double -> IO ()-setDouble val !x = UV.unsafeWrite val 0 x---- | modifies the value-{-# INLINE modifyDouble #-}-modifyDouble :: DoubleSingleton -> (Double -> Double) -> IO ()-modifyDouble val f = UV.unsafeModify val f 0
− SAT/Mios/Data/Stack.hs
@@ -1,90 +0,0 @@-{-# LANGUAGE- MultiParamTypeClasses- #-}-{-# LANGUAGE Trustworthy #-}---- | stack of Int, by adding the length field as the zero-th element to a 'Vec'-module SAT.Mios.Data.Stack- (- Stack- , newStack- , clearStack- , sizeOfStack- , pushToStack- , popFromStack- , lastOfStack- , shrinkStack- , asSizedVec--- , isoVec- )- where--import qualified Data.Vector.Unboxed.Mutable as UV-import SAT.Mios.Types---- | Unboxed mutable stack for Int.-newtype Stack = Stack (UV.IOVector Int)--instance VectorFamily Stack Int where- dump str v = (str ++) . show <$> asList v- {-# SPECIALIZE INLINE asVec :: Stack -> Vec #-}- asVec (Stack v) = UV.unsafeTail v- asList (Stack v) = do- (n : l) <- asList v- return $ take n l---- | returns the number of elements-{-# INLINE sizeOfStack #-}-sizeOfStack :: Stack -> IO Int-sizeOfStack (Stack v) = UV.unsafeRead v 0---- | clear stack-{-# INLINE clearStack #-}-clearStack :: Stack -> IO ()-clearStack (Stack v) = UV.unsafeWrite v 0 0---- | returns a new stack which size is @size@-{-# INLINABLE newStack #-}-newStack :: Int -> IO Stack-newStack n = do- v <- UV.new $ n + 1- UV.set v 0- return $ Stack v---- | pushs an int to 'Stack'-{-# INLINE pushToStack #-}-pushToStack :: Stack -> Int -> IO ()-pushToStack (Stack v) x = do- i <- (+ 1) <$> UV.unsafeRead v 0- UV.unsafeWrite v i x- UV.unsafeWrite v 0 i---- | drops the first element from 'Stack'-{-# INLINE popFromStack #-}-popFromStack :: Stack -> IO ()-popFromStack (Stack v) = UV.unsafeModify v (subtract 1) 0---- | peeks the last element in 'Stack'-{-# INLINE lastOfStack #-}-lastOfStack :: Stack -> IO Int-lastOfStack (Stack v) = UV.unsafeRead v =<< UV.unsafeRead v 0---- | Shrink the stack. The given arg means the number of discards.--- therefore, shrink s n == for [1 .. n] $ \_ -> pop s-{-# INLINE shrinkStack #-}-shrinkStack :: Stack -> Int -> IO ()-shrinkStack (Stack v) k = UV.unsafeModify v (subtract k) 0---- | converts Stack to sized Vec; this is the method to get the internal vector-{-# INLINE asSizedVec #-}-asSizedVec :: Stack -> Vec-asSizedVec (Stack v) = v--{---- | isomorphic conversion to 'Vec'------ Note: 'asVec' drops the 1st element and no copy (unsafe operation); 'isoVec' really copies the real elements-{-# INLINE isoVec #-}-isoVec :: Stack -> IO Vec-isoVec (Stack v) = UV.clone . flip UV.take v . (1 +) =<< UV.unsafeRead v 0--}
− SAT/Mios/Data/Vec.hs
@@ -1,86 +0,0 @@--- | The fundamental data structure: Fixed Mutable Unboxed Int Vector-{-# LANGUAGE- BangPatterns- #-}-{-# LANGUAGE Trustworthy #-}--module SAT.Mios.Data.Vec- (- Vec- , sizeOfVector- , getNth- , setNth- , swapBetween- , modifyNth- , setAll- , newVec- , newVecWith- , newSizedVecIntFromList- , newSizedVecIntFromUVector- , vecGrow- )- where--import qualified Data.Vector.Unboxed as U-import qualified Data.Vector.Unboxed.Mutable as UV---- | Costs of all operations are /O/(/1/)-type Vec = UV.IOVector Int---- | returns the size of 'Vec'-{-# INLINE sizeOfVector #-}-sizeOfVector :: Vec -> IO Int-sizeOfVector v = return $! UV.length v---- | returns a new 'Vec'-{-# INLINE newVec #-}-newVec :: Int -> IO Vec-newVec = UV.new---- | returns a new 'Vec' filled with an Int-{-# INLINE newVecWith #-}-newVecWith :: Int -> Int -> IO Vec-newVecWith n x = do- v <- UV.new n- UV.set v x- return v---- | gets the nth value-{-# INLINE getNth #-}-getNth :: Vec -> Int -> IO Int-getNth = UV.unsafeRead---- | sets the nth value-{-# INLINE setNth #-}-setNth :: Vec -> Int -> Int -> IO ()-setNth = UV.unsafeWrite---- | modify the nth value-{-# INLINE modifyNth #-}-modifyNth :: Vec -> (Int -> Int) -> Int -> IO ()-modifyNth = UV.unsafeModify---- | sets all elements-{-# INLINE setAll #-}-setAll :: Vec -> Int -> IO ()-setAll = UV.set---- | swaps two elements-{-# INLINE swapBetween #-}-swapBetween:: Vec -> Int -> Int -> IO ()-swapBetween = UV.unsafeSwap---- | returns a new 'Vec' from a @[Int]@-{-# INLINE newSizedVecIntFromList #-}-newSizedVecIntFromList :: [Int] -> IO Vec-newSizedVecIntFromList !l = U.unsafeThaw $ U.fromList (length l : l)---- | returns a new 'Vec' from a Unboxed Int Vector-{-# INLINE newSizedVecIntFromUVector #-}-newSizedVecIntFromUVector :: U.Vector Int -> IO Vec-newSizedVecIntFromUVector = U.unsafeThaw---- | calls @unasfeGrow@-{-# INLINE vecGrow #-}-vecGrow :: Vec -> Int -> IO Vec-vecGrow = UV.unsafeGrow
− SAT/Mios/Data/VecBool.hs
@@ -1,55 +0,0 @@--- | Mutable Unboxed Boolean Vector------ * __VecBool@::UV.IOVector Bool@ -- data type that contains a mutable list of elements----{-# LANGUAGE- BangPatterns- , FlexibleInstances- , MultiParamTypeClasses- #-}-{-# LANGUAGE Trustworthy #-}--module SAT.Mios.Data.VecBool- (- VecBool- , newVecBool- , getNthBool- , setNthBool- , modifyNthBool- )- where--import Control.Monad (forM)-import qualified Data.Vector.Unboxed.Mutable as UV-import SAT.Mios.Types (VectorFamily(..))---- | Mutable unboxed Bool Vector-type VecBool = UV.IOVector Bool---- | provides 'clear' and 'size'-instance VectorFamily VecBool Bool where- clear _ = error "VecBool.clear"- asList v = forM [0 .. UV.length v - 1] $ UV.unsafeRead v- dump str v = (str ++) . show <$> asList v---- | returns a new 'VecBool'-newVecBool :: Int -> Bool -> IO VecBool-newVecBool n x = do- v <- UV.new n- UV.set v x- return v---- | returns the nth value in 'VecBool'-{-# INLINE getNthBool #-}-getNthBool :: VecBool -> Int -> IO Bool-getNthBool = UV.unsafeRead---- | sets the nth value-{-# INLINE setNthBool #-}-setNthBool :: VecBool -> Int -> Bool -> IO ()-setNthBool = UV.unsafeWrite---- | sets the nth value-{-# INLINE modifyNthBool #-}-modifyNthBool :: VecBool -> (Bool -> Bool) -> Int -> IO ()-modifyNthBool = UV.unsafeModify
− SAT/Mios/Data/VecDouble.hs
@@ -1,53 +0,0 @@--- | Mutable Unboxed Double Vector-{-# LANGUAGE- BangPatterns- , FlexibleInstances- , MultiParamTypeClasses- #-}-{-# LANGUAGE Trustworthy #-}--module SAT.Mios.Data.VecDouble- (- VecDouble- , newVecDouble- , getNthDouble- , setNthDouble- , modifyNthDouble- )- where--import Control.Monad (forM)-import Data.List ()-import qualified Data.Vector.Unboxed.Mutable as UV-import SAT.Mios.Types (VectorFamily(..))---- | Mutable unboxed Double Vector-type VecDouble = UV.IOVector Double--instance VectorFamily VecDouble Double where- clear _ = error "VecDouble.clear"- asList v = forM [0 .. UV.length v - 1] $ UV.unsafeRead v- dump str v = (str ++) . show <$> asList v---- | returns a new 'VecDouble'-newVecDouble :: Int -> Double -> IO VecDouble-newVecDouble n 0 = UV.new n-newVecDouble n x = do- v <- UV.new n- UV.set v x- return v---- | returns the nth value in 'VecDouble'-{-# INLINE getNthDouble #-}-getNthDouble :: Int -> VecDouble -> IO Double-getNthDouble !n v = UV.unsafeRead v n---- | sets the nth value-{-# INLINE setNthDouble #-}-setNthDouble :: Int -> VecDouble -> Double -> IO ()-setNthDouble !n v !x = UV.unsafeWrite v n x---- | updates the nth value-{-# INLINE modifyNthDouble #-}-modifyNthDouble :: Int -> VecDouble -> (Double -> Double) -> IO ()-modifyNthDouble !n v !f = UV.unsafeModify v f n
− SAT/Mios/Internal.hs
@@ -1,33 +0,0 @@--- | Mios Internal Settings-module SAT.Mios.Internal- (- versionId- , MiosConfiguration (..)- , defaultConfiguration- , module Plumbing- )- where-import SAT.Mios.Data.VecBool as Plumbing-import SAT.Mios.Data.VecDouble as Plumbing-import SAT.Mios.Data.Stack as Plumbing---- | version name-versionId :: String-versionId = "mios 1.3.0 -- https://github.com/shnarazk/mios" -- no more LBD---- | solver's parameters; random decision rate was dropped.-data MiosConfiguration = MiosConfiguration- {- variableDecayRate :: !Double -- ^ decay rate for variable activity--- , clauseDecayRate :: !Double -- ^ decay rate for clause activity- }---- | dafault configuration------ * Minisat-1.14 uses @(0.95, 0.999, 0.2 = 20 / 1000)@.--- * Minisat-2.20 uses @(0.95, 0.999, 0)@.--- * Gulcose-4.0 uses @(0.8 , 0.999, 0)@.--- * Mios-1.2 uses @(0.95, 0.999, 0)@.----defaultConfiguration :: MiosConfiguration-defaultConfiguration = MiosConfiguration 0.95 {- 0.999 -} {- 0 -}
SAT/Mios/Main.hs view
@@ -6,7 +6,7 @@ #-} {-# LANGUAGE Safe #-} --- | This is a part of MIOS; main heuristics+-- | This is a part of MIOS; main heuristics. module SAT.Mios.Main ( simplifyDB@@ -14,27 +14,24 @@ ) where -import Control.Monad (forM_, unless, void, when)+import Control.Monad (unless, void, when) import Data.Bits import Data.Foldable (foldrM) import SAT.Mios.Types-import SAT.Mios.Internal import SAT.Mios.Clause import SAT.Mios.ClauseManager import SAT.Mios.Solver--- import SAT.Mios.Ranking --------------------------------------------------------------------------------- Ranking--- | a special version of ranking-{-# INLINE ranking' #-}-ranking' :: Clause -> IO Int-ranking' = sizeOfClause+-- | returns a rank of 'Clause'. Smaller value is better.+{-# INLINE rankOf #-}+rankOf :: Clause -> IO Int+rankOf = get' -- | #114: __RemoveWatch__ {-# INLINABLE removeWatch #-} removeWatch :: Solver -> Clause -> IO () removeWatch (watches -> w) c = do- let lvec = asVec c+ let lvec = asUVector c l1 <- negateLit <$> getNth lvec 0 markClause (getNthWatcher w l1) c l2 <- negateLit <$> getNth lvec 1@@ -44,40 +41,40 @@ -- Operations on 'Clause' -------------------------------------------------------------------------------- --- | __Fig. 8. (p.12)__ create a new LEARNT clause and adds it to watcher lists--- This is a strippped-down version of 'newClause' in Solver+-- | __Fig. 8. (p.12)__ creates a new LEARNT clause and adds it to watcher lists.+-- This is a strippped-down version of 'newClause' in Solver. {-# INLINABLE newLearntClause #-}-newLearntClause :: Solver -> Vec -> IO ()+newLearntClause :: Solver -> Stack -> IO () newLearntClause s@Solver{..} ps = do- good <- getBool ok+ good <- get' ok when good $ do -- ps is a 'SizedVectorInt'; ps[0] is the number of active literals -- Since this solver must generate only healthy learnt clauses, we need not to run misc check in 'newClause'- k <- getNth ps 0+ k <- get' ps case k of 1 -> do l <- getNth ps 1 unsafeEnqueue s l NullClause _ -> do -- allocate clause:- c <- newClauseFromVec True ps- let vec = asVec c+ c <- newClauseFromStack True ps+ let vec = asUVector c -- Pick a second literal to watch: let findMax :: Int -> Int -> Int -> IO Int findMax ((< k) -> False) j _ = return j findMax i j val = do- v' <- lit2var <$> getNth vec i- a <- getNth assigns v'- b <- getNth level v'+ v <- lit2var <$> getNth vec i+ a <- getNth assigns v+ b <- getNth level v if (a /= lBottom) && (val < b) then findMax (i + 1) i b else findMax (i + 1) j val swapBetween vec 1 =<< findMax 0 0 0 -- Let @max_i@ be the index of the literal with highest decision level -- Bump, enqueue, store clause:- setDouble (activity c) . fromIntegral =<< decisionLevel s -- newly learnt clauses should be considered active+ set' (activity c) . fromIntegral =<< decisionLevel s -- newly learnt clauses should be considered active -- Add clause to all managers- pushClause learnts c+ pushTo learnts c l <- getNth vec 0 pushClauseWithKey (getNthWatcher watches (negateLit l)) c 0 l1 <- negateLit <$> getNth vec 1@@ -86,7 +83,7 @@ unsafeEnqueue s l c -- Since unsafeEnqueue updates the 1st literal's level, setLBD should be called after unsafeEnqueue -- setRank s c- setBool (protected c) True+ set' (protected c) True -- | __Simplify.__ At the top-level, a constraint may be given the opportunity to -- simplify its representation (returns @False@) or state that the constraint is@@ -98,9 +95,9 @@ {-# INLINABLE simplify #-} simplify :: Solver -> Clause -> IO Bool simplify s c = do- n <- sizeOfClause c+ n <- get' c let- lvec = asVec c+ lvec = asUVector c loop ::Int -> IO Bool loop ((< n) -> False) = return False loop i = do@@ -135,33 +132,33 @@ -- rest of literals. There may be others from the same level though. -- -- @analyze@ is invoked from @search@--- {-# INLINEABLE analyze #-}+{-# INLINABLE analyze #-} analyze :: Solver -> Clause -> IO Int analyze s@Solver{..} confl = do -- litvec- clearStack litsLearnt- pushToStack litsLearnt 0 -- reserve the first place for the unassigned literal+ reset litsLearnt+ pushTo litsLearnt 0 -- reserve the first place for the unassigned literal dl <- decisionLevel s let- litsVec = asVec litsLearnt- trailVec = asVec trail+ litsVec = asUVector litsLearnt+ trailVec = asUVector trail loopOnClauseChain :: Clause -> Lit -> Int -> Int -> Int -> IO Int loopOnClauseChain c p ti bl pathC = do -- p : literal, ti = trail index, bl = backtrack level when (learnt c) $ do claBumpActivity s c {- -- update LBD like #Glucose4.0- d <- getInt (lbd c)+ d <- get' (lbd c) when (2 < d) $ do nblevels <- lbdOf s c when (nblevels + 1 < d) $ do -- improve the LBD- when (d <= 30) $ setBool (protected c) True -- 30 is `lbLBDFrozenClause`+ when (d <= 30) $ set' (protected c) True -- 30 is `lbLBDFrozenClause` -- seems to be interesting: keep it fro the next round- setInt (lbd c) nblevels -- Update it+ set' (lbd c) nblevels -- Update it -}- sc <- sizeOfClause c+ sc <- get' c let- lvec = asVec c+ lvec = asUVector c loopOnLiterals :: Int -> Int -> Int -> IO (Int, Int) loopOnLiterals ((< sc) -> False) b pc = return (b, pc) -- b = btLevel, pc = pathC loopOnLiterals j b pc = do@@ -176,11 +173,11 @@ if dl <= l -- cancelUntil doesn't clear level of cancelled literals then do -- glucose heuristics- r <- getNthClause reason v- when (r /= NullClause && learnt r) $ pushToStack lastDL q+ r <- getNth reason v+ when (r /= NullClause && learnt r) $ pushTo an'lastDL q -- end of glucose heuristics loopOnLiterals (j + 1) b (pc + 1)- else pushToStack litsLearnt q >> loopOnLiterals (j + 1) (max b l) pc+ else pushTo litsLearnt q >> loopOnLiterals (j + 1) (max b l) pc else loopOnLiterals (j + 1) b pc (b', pathC') <- loopOnLiterals (if p == bottomLit then 0 else 1) bl pathC let@@ -192,33 +189,33 @@ ti' <- nextPickedUpLit ti nextP <- getNth trailVec ti' let nextV = lit2var nextP- confl' <- getNthClause reason nextV+ confl' <- getNth reason nextV setNth an'seen nextV 0 if 1 < pathC' then loopOnClauseChain confl' nextP (ti' - 1) b' (pathC' - 1) else setNth litsVec 0 (negateLit nextP) >> return b'- ti <- subtract 1 <$> sizeOfStack trail+ ti <- subtract 1 <$> get' trail levelToReturn <- loopOnClauseChain confl bottomLit ti 0 0 -- Simplify phase (implemented only @expensive_ccmin@ path)- n <- sizeOfStack litsLearnt- clearStack an'stack -- analyze_stack.clear();- clearStack an'toClear -- out_learnt.copyTo(analyze_toclear);- pushToStack an'toClear =<< getNth litsVec 0+ n <- get' litsLearnt+ reset an'stack -- analyze_stack.clear();+ reset an'toClear -- out_learnt.copyTo(analyze_toclear);+ pushTo an'toClear =<< getNth litsVec 0 let merger :: Int -> Int -> IO Int merger ((< n) -> False) b = return b merger i b = do l <- getNth litsVec i- pushToStack an'toClear l+ pushTo an'toClear l -- restrict the search depth (range) to 32 merger (i + 1) . setBit b . (31 .&.) =<< getNth level (lit2var l) levels <- merger 1 0 let loopOnLits :: Int -> Int -> IO ()- loopOnLits ((< n) -> False) n' = shrinkStack litsLearnt $ n - n'+ loopOnLits ((< n) -> False) n' = shrinkBy litsLearnt $ n - n' loopOnLits i j = do l <- getNth litsVec i- c1 <- (NullClause ==) <$> getNthClause reason (lit2var l)+ c1 <- (NullClause ==) <$> getNth reason (lit2var l) if c1 then setNth litsVec j l >> loopOnLits (i + 1) (j + 1) else do@@ -228,23 +225,23 @@ else loopOnLits (i + 1) j loopOnLits 1 1 -- the first literal is specail -- glucose heuristics- nld <- sizeOfStack lastDL- r <- sizeOfStack litsLearnt -- this is not the right value+ nld <- get' an'lastDL+ r <- get' litsLearnt -- this is not the right value let- vec = asVec lastDL+ vec = asUVector an'lastDL loopOnLastDL :: Int -> IO () loopOnLastDL ((< nld) -> False) = return () loopOnLastDL i = do v <- lit2var <$> getNth vec i- r' <- ranking' =<< getNthClause reason v+ r' <- rankOf =<< getNth reason v when (r < r') $ varBumpActivity s v loopOnLastDL $ i + 1 loopOnLastDL 0- clearStack lastDL+ reset an'lastDL -- Clear seen- k <- sizeOfStack an'toClear+ k <- get' an'toClear let- vec' = asVec an'toClear+ vec' = asUVector an'toClear cleaner :: Int -> IO () cleaner ((< k) -> False) = return () cleaner i = do@@ -263,26 +260,26 @@ -- * @an'toClear@ is initialized by @ps@ in @analyze@ (a copy of 'learnt'). -- This is used only in this function and @analyze@. ---{-# INLINEABLE analyzeRemovable #-}+{-# INLINABLE analyzeRemovable #-} analyzeRemovable :: Solver -> Lit -> Int -> IO Bool analyzeRemovable Solver{..} p minLevel = do -- assert (reason[var(p)]!= NullCaulse);- clearStack an'stack -- analyze_stack.clear()- pushToStack an'stack p -- analyze_stack.push(p);- top <- sizeOfStack an'toClear+ reset an'stack -- analyze_stack.clear()+ pushTo an'stack p -- analyze_stack.push(p);+ top <- get' an'toClear let loopOnStack :: IO Bool loopOnStack = do- k <- sizeOfStack an'stack -- int top = analyze_toclear.size();+ k <- get' an'stack -- int top = analyze_toclear.size(); if 0 == k then return True else do -- assert(reason[var(analyze_stack.last())] != GClause_NULL);- sl <- lastOfStack an'stack- popFromStack an'stack -- analyze_stack.pop();- c <- getNthClause reason (lit2var sl) -- getRoot sl- nl <- sizeOfClause c+ sl <- lastOf an'stack+ popFrom an'stack -- analyze_stack.pop();+ c <- getNth reason (lit2var sl) -- getRoot sl+ nl <- get' c let- cvec = asVec c+ cvec = asUVector c loopOnLit :: Int -> IO Bool -- loopOnLit (int i = 1; i < c.size(); i++){ loopOnLit ((< nl) -> False) = loopOnStack loopOnLit i = do@@ -292,20 +289,24 @@ c1 <- (1 /=) <$> getNth an'seen v' if c1 && (0 /= l') -- if (!analyze_seen[var(p)] && level[var(p)] != 0){ then do- c3 <- (NullClause /=) <$> getNthClause reason v'+ c3 <- (NullClause /=) <$> getNth reason v' if c3 && testBit minLevel (l' .&. 31) -- if (reason[var(p)] != GClause_NULL && ((1 << (level[var(p)] & 31)) & min_level) != 0){ then do setNth an'seen v' 1 -- analyze_seen[var(p)] = 1;- pushToStack an'stack p' -- analyze_stack.push(p);- pushToStack an'toClear p' -- analyze_toclear.push(p);+ pushTo an'stack p' -- analyze_stack.push(p);+ pushTo an'toClear p' -- analyze_toclear.push(p); loopOnLit $ i + 1 else do -- loopOnLit (int j = top; j < analyze_toclear.size(); j++) analyze_seen[var(analyze_toclear[j])] = 0;- top' <- sizeOfStack an'toClear- let vec = asVec an'toClear- forM_ [top .. top' - 1] $ \j -> do x <- getNth vec j; setNth an'seen (lit2var x) 0+ top' <- get' an'toClear+ let+ vec = asUVector an'toClear+ clearAll :: Int -> IO ()+ clearAll ((< top') -> False) = return ()+ clearAll j = do x <- getNth vec j; setNth an'seen (lit2var x) 0; clearAll (j + 1)+ clearAll top -- analyze_toclear.shrink(analyze_toclear.size() - top); note: shrink n == repeat n pop- shrinkStack an'toClear $ top' - top+ shrinkBy an'toClear $ top' - top return False else loopOnLit $ i + 1 loopOnLit 1@@ -320,14 +321,15 @@ -- making assumptions). If 'skip_first' is TRUE, the first literal of 'confl' is ignored (needed -- if conflict arose before search even started). --+{-# INLINABLE analyzeFinal #-} analyzeFinal :: Solver -> Clause -> Bool -> IO () analyzeFinal Solver{..} confl skipFirst = do- clearStack conflict- rl <- getInt rootLevel+ reset conflicts+ rl <- get' rootLevel unless (rl == 0) $ do- n <- sizeOfClause confl+ n <- get' confl let- lvec = asVec confl+ lvec = asUVector confl loopOnConfl :: Int -> IO () loopOnConfl ((< n) -> False) = return () loopOnConfl i = do@@ -336,11 +338,11 @@ when (0 < lvl) $ setNth an'seen x 1 loopOnConfl $ i + 1 loopOnConfl $ if skipFirst then 1 else 0- tls <- sizeOfStack trailLim- trs <- sizeOfStack trail- tlz <- getNth (asVec trailLim) 0+ tls <- get' trailLim+ trs <- get' trail+ tlz <- getNth (asUVector trailLim) 0 let- trailVec = asVec trail+ trailVec = asUVector trail loopOnTrail :: Int -> IO () loopOnTrail ((tlz <=) -> False) = return () loopOnTrail i = do@@ -348,13 +350,13 @@ let (x :: Var) = lit2var l saw <- getNth an'seen x when (saw == 1) $ do- (r :: Clause) <- getNthClause reason x+ (r :: Clause) <- getNth reason x if r == NullClause- then pushToStack conflict (negateLit l)+ then pushTo conflicts (negateLit l) else do- k <- sizeOfClause r+ k <- get' r let- cvec = asVec r+ cvec = asUVector r loopOnLits :: Int -> IO () loopOnLits ((< k) -> False) = return () loopOnLits j = do@@ -365,7 +367,7 @@ loopOnLits 1 setNth an'seen x 0 loopOnTrail $ i - 1- loopOnTrail =<< if tls <= rl then return (trs - 1) else getNth (asVec trailLim) rl+ loopOnTrail =<< if tls <= rl then return (trs - 1) else getNth (asUVector trailLim) rl -- | M114: -- propagate : [void] -> [Clause+]@@ -396,25 +398,25 @@ loop $ i + 1 loop 1 -}- trailVec = asVec trail+ trailVec = asUVector trail while :: Clause -> Bool -> IO Clause while confl False = {- bumpAllVar >> -} return confl while confl True = do- (p :: Lit) <- getNth trailVec =<< getInt qHead- modifyInt qHead (+ 1)+ (p :: Lit) <- getNth trailVec =<< get' qHead+ modify' qHead (+ 1) let (ws :: ClauseExtManager) = getNthWatcher watches p- end <- numberOfClauses ws+ end <- get' ws cvec <- getClauseVector ws bvec <- getKeyVector ws--- rc <- getNthClause reason $ lit2var p--- byGlue <- if (rc /= NullClause) && learnt rc then (== 2) <$> getInt (lbd rc) else return False+-- rc <- getNth reason $ lit2var p+-- byGlue <- if (rc /= NullClause) && learnt rc then (== 2) <$> get' (lbd rc) else return False let {- checkAllLiteralsIn :: Clause -> IO () -- not in use checkAllLiteralsIn c = do nc <- sizeOfClause c let- vec = asVec c+ vec = asuVector c loop :: Int -> IO () loop((< nc) -> False) = return () loop i = do@@ -425,23 +427,23 @@ -} forClause :: Clause -> Int -> Int -> IO Clause forClause confl i@((< end) -> False) j = do- shrinkManager ws (i - j)- while confl =<< ((<) <$> getInt qHead <*> sizeOfStack trail)+ shrinkBy ws (i - j)+ while confl =<< ((<) <$> get' qHead <*> get' trail) forClause confl i j = do (l :: Lit) <- getNth bvec i bv <- if l == 0 then return lFalse else valueLit s l if bv == lTrue then do unless (i == j) $ do -- NOTE: if i == j, the path doesn't require accesses to cvec!- (c :: Clause) <- getNthClause cvec i- setNthClause cvec j c+ (c :: Clause) <- getNth cvec i+ setNth cvec j c setNth bvec j l forClause confl (i + 1) (j + 1) else do -- checkAllLiteralsIn c- (c :: Clause) <- getNthClause cvec i+ (c :: Clause) <- getNth cvec i let- lits = asVec c+ lits = asUVector c falseLit = negateLit p -- Make sure the false literal is data[1] ((falseLit ==) <$> getNth lits 0) >>= (`when` swapBetween lits 0 1)@@ -449,27 +451,27 @@ (first :: Lit) <- getNth lits 0 val <- valueLit s first if val == lTrue- then setNthClause cvec j c >> setNth bvec j first >> forClause confl (i + 1) (j + 1)+ then setNth cvec j c >> setNth bvec j first >> forClause confl (i + 1) (j + 1) else do -- Look for new watch- cs <- sizeOfClause c+ cs <- get' c let forLit :: Int -> IO Clause forLit ((< cs) -> False) = do -- Did not find watch; clause is unit under assignment:- setNthClause cvec j c+ setNth cvec j c setNth bvec j 0 result <- enqueue s first c if not result then do- ((== 0) <$> decisionLevel s) >>= (`when` setBool ok False)+ ((== 0) <$> decisionLevel s) >>= (`when` set' ok False) -- #BBCP- setInt qHead =<< sizeOfStack trail+ set' qHead =<< get' trail -- Copy the remaining watches: let copy i'@((< end) -> False) j' = forClause c i' j' copy i' j' = do- setNthClause cvec j' =<< getNthClause cvec i'+ setNth cvec j' =<< getNth cvec i' setNth bvec j' =<< getNth bvec i' copy (i' + 1) (j' + 1) copy (i + 1) (j + 1)@@ -485,7 +487,7 @@ else forLit $ k + 1 forLit 2 forClause confl 0 0- while NullClause =<< ((<) <$> getInt qHead <*> sizeOfStack trail)+ while NullClause =<< ((<) <$> get' qHead <*> get' trail) -- | #M22 -- reduceDB: () -> [void]@@ -501,11 +503,11 @@ let loop :: Int -> IO () loop ((< n) -> False) = return ()- loop i = (removeWatch s =<< getNthClause vec i) >> loop (i + 1)+ loop i = (removeWatch s =<< getNth vec i) >> loop (i + 1) k <- sortClauses s learnts (div n 2) -- k is the number of clauses not to be purged loop k -- CAVEAT: `vec` is a zero-based vector- garbageCollect watches- shrinkManager learnts (n - k)+ reset watches+ shrinkBy learnts (n - k) -- | (Good to Bad) Quick sort the key vector based on their activities and returns number of privileged clauses. -- this function uses the same metrix as reduceDB_lt in glucose 4.0:@@ -543,7 +545,7 @@ activityScale = fromIntegral activityMax indexMax :: Int indexMax = (2 ^ indexWidth - 1) -- 67,108,863 for 26- n <- numberOfClauses cm+ n <- get' cm -- when (indexMax < n) $ error $ "## The number of learnt clauses " ++ show n ++ " exceeds mios's " ++ show indexWidth ++" bit manage capacity" vec <- getClauseVector cm keys <- getKeyVector cm@@ -552,18 +554,18 @@ assignKey :: Int -> Int -> IO Int assignKey ((< n) -> False) m = return m assignKey i m = do- c <- getNthClause vec i- k <- (\k -> if k == 2 then return k else fromEnum <$> getBool (protected c)) =<< sizeOfClause c+ c <- getNth vec i+ k <- (\k -> if k == 2 then return k else fromEnum <$> get' (protected c)) =<< get' c case k of- 1 -> setBool (protected c) False >> setNth keys i (shiftL 2 indexWidth + i) >> assignKey (i + 1) (m + 1)+ 1 -> set' (protected c) False >> setNth keys i (shiftL 2 indexWidth + i) >> assignKey (i + 1) (m + 1) 2 -> setNth keys i (shiftL 1 indexWidth + i) >> assignKey (i + 1) (m + 1) _ -> do l <- locked s c -- this is expensive if l then setNth keys i (shiftL 1 indexWidth + i) >> assignKey (i + 1) (m + 1) else do- d <- ranking' c- b <- floor . (activityScale *) . (1 -) . logBase claActivityThreshold . max 1 <$> getDouble (activity c)+ d <- rankOf c+ b <- floor . (activityScale *) . (1 -) . logBase claActivityThreshold . max 1 <$> get' (activity c) setNth keys i $ shiftL (min rankMax d) (activityWidth + indexWidth) + shiftL b indexWidth + i assignKey (i + 1) m limit <- min n . (+ nneeds) <$> assignKey 0 0@@ -604,14 +606,14 @@ seek i = do bits <- getNth keys i when (indexMax < bits) $ do- c <- getNthClause vec i+ c <- getNth vec i let sweep k = do k' <- (indexMax .&.) <$> getNth keys k setNth keys k k if k' == i- then setNthClause vec k c- else getNthClause vec k' >>= setNthClause vec k >> sweep k'+ then setNth vec k c+ else getNth vec k' >>= setNth vec k >> sweep k' sweep i seek $ i + 1 seek 0@@ -628,22 +630,22 @@ {-# INLINABLE simplifyDB #-} simplifyDB :: Solver -> IO Bool simplifyDB s@Solver{..} = do- good <- getBool ok+ good <- get' ok if good then do p <- propagate s if p /= NullClause- then setBool ok False >> return False+ then set' ok False >> return False else do -- Clear watcher lists:- n <- sizeOfStack trail+ n <- get' trail let- vec = asVec trail+ vec = asUVector trail loopOnLit ((< n) -> False) = return () loopOnLit i = do l <- getNth vec i- clearManager . getNthWatcher watches $ l- clearManager . getNthWatcher watches $ negateLit l+ reset . getNthWatcher watches $ l+ reset . getNthWatcher watches $ negateLit l loopOnLit $ i + 1 loopOnLit 0 -- Remove satisfied clauses:@@ -653,20 +655,20 @@ for t = do let ptr = if t == 0 then learnts else clauses vec' <- getClauseVector ptr- n' <- numberOfClauses ptr+ n' <- get' ptr let loopOnVector :: Int -> Int -> IO Bool- loopOnVector ((< n') -> False) j = shrinkManager ptr (n' - j) >> return True+ loopOnVector ((< n') -> False) j = shrinkBy ptr (n' - j) >> return True loopOnVector i j = do- c <- getNthClause vec' i+ c <- getNth vec' i l <- locked s c r <- simplify s c if not l && r then removeWatch s c >> loopOnVector (i + 1) j- else setNthClause vec' j c >> loopOnVector (i + 1) (j + 1)+ else setNth vec' j c >> loopOnVector (i + 1) (j + 1) loopOnVector 0 0 ret <- for 0- garbageCollect watches+ reset watches return ret else return False @@ -683,11 +685,11 @@ -- all variables are decision variables, that means that the clause set is satisfiable. 'l_False' -- if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached. {-# INLINABLE search #-}-search :: Solver -> Int -> Int -> IO LiftedBool+search :: Solver -> Int -> Int -> IO Int search s@Solver{..} nOfConflicts nOfLearnts = do -- clear model let- loop :: Int -> IO LiftedBool+ loop :: Int -> IO Int loop conflictC = do !confl <- propagate s d <- decisionLevel s@@ -695,23 +697,23 @@ then do -- CONFLICT incrementStat s NumOfBackjump 1- r <- getInt rootLevel+ r <- get' rootLevel if d == r then do -- Contradiction found: analyzeFinal s confl False- return LFalse+ return lFalse else do -- u <- (== 0) . (flip mod 5000) <$> getNth stats (fromEnum NumOfBackjump) -- when u $ do--- d <- getDouble varDecay--- when (d < 0.95) $ modifyDouble varDecay (+ 0.01)+-- d <- get' varDecay+-- when (d < 0.95) $ modify' varDecay (+ 0.01) backtrackLevel <- analyze s confl -- 'analyze' resets litsLearnt by itself- (s `cancelUntil`) . max backtrackLevel =<< getInt rootLevel- newLearntClause s $ asSizedVec litsLearnt- k <- sizeOfStack litsLearnt+ (s `cancelUntil`) . max backtrackLevel =<< get' rootLevel+ newLearntClause s litsLearnt+ k <- get' litsLearnt when (k == 1) $ do- (v :: Var) <- lit2var <$> getNth (asVec litsLearnt) 0+ (v :: Var) <- lit2var <$> getNth (asUVector litsLearnt) 0 setNth level v 0 varDecayActivity s -- claDecayActivity s@@ -719,20 +721,26 @@ else do -- NO CONFLICT -- Simplify the set of problem clauses: when (d == 0) . void $ simplifyDB s -- our simplifier cannot return @False@ here- k1 <- numberOfClauses learnts+ k1 <- get' learnts k2 <- nAssigns s when (k1 - k2 >= nOfLearnts) $ reduceDB s -- Reduce the set of learnt clauses case () of _ | k2 == nVars -> do -- Model found:- forM_ [0 .. nVars - 1] $ \i -> setNthBool model i . (lTrue ==) =<< getNth assigns (i + 1)- return LTrue+ let+ toInt :: Var -> IO Lit+ toInt v = (\p -> if lTrue == p then v else negate v) <$> valueVar s v+ setModel :: Int -> IO ()+ setModel ((<= nVars) -> False) = return ()+ setModel v = (setNth model v =<< toInt v) >> setModel (v + 1)+ setModel 1+ return lTrue _ | conflictC >= nOfConflicts -> do -- Reached bound on number of conflicts- (s `cancelUntil`) =<< getInt rootLevel -- force a restart+ (s `cancelUntil`) =<< get' rootLevel -- force a restart claRescaleActivityAfterRestart s incrementStat s NumOfRestart 1- return Bottom+ return lBottom _ -> do -- New variable decision: v <- select s -- many have heuristic for polarity here@@ -741,8 +749,8 @@ unsafeAssume s $ var2lit v (0 < oldVal) -- cannot return @False@ -- >> #phasesaving loop conflictC- good <- getBool ok- if good then loop 0 else return LFalse+ good <- get' ok+ if good then loop 0 else return lFalse -- | __Fig. 16. (p.20)__ -- Main solve method.@@ -750,6 +758,7 @@ -- __Pre-condition:__ If assumptions are used, 'simplifyDB' must be -- called right before using this method. If not, a top-level conflict (resulting in a -- non-usable internal state) cannot be distinguished from a conflict under assumptions.+{-# INLINABLE solve #-} solve :: (Foldable t) => Solver -> t Lit -> IO Bool solve s@Solver{..} assumps = do -- PUSH INCREMENTAL ASSUMPTIONS:@@ -760,9 +769,9 @@ b <- assume s a if not b then do -- conflict analyze- (confl :: Clause) <- getNthClause reason (lit2var a)+ (confl :: Clause) <- getNth reason (lit2var a) analyzeFinal s confl True- pushToStack conflict (negateLit a)+ pushTo conflicts (negateLit a) cancelUntil s 0 return False else do@@ -778,33 +787,31 @@ if not x then return False else do- setInt rootLevel =<< decisionLevel s+ set' rootLevel =<< decisionLevel s -- SOLVE: nc <- fromIntegral <$> nClauses s let while :: Double -> Double -> IO Bool while nOfConflicts nOfLearnts = do status <- search s (floor nOfConflicts) (floor nOfLearnts)- if status == Bottom+ if status == lBottom then while (1.5 * nOfConflicts) (1.1 * nOfLearnts)- else cancelUntil s 0 >> return (status == LTrue)+ else cancelUntil s 0 >> return (status == lTrue) while 100 (nc / 3.0) ------ 'enqueue' is defined in 'Solver'; most functions in M114 use 'unsafeEnqueue'---+-- | Though 'enqueue' is defined in 'Solver', most functions in M114 use @unsafeEnqueue@. {-# INLINABLE unsafeEnqueue #-} unsafeEnqueue :: Solver -> Lit -> Clause -> IO () unsafeEnqueue s@Solver{..} p from = do let v = lit2var p setNth assigns v $! if positiveLit p then lTrue else lFalse setNth level v =<< decisionLevel s- setNthClause reason v from -- NOTE: @from@ might be NULL!- pushToStack trail p+ setNth reason v from -- NOTE: @from@ might be NULL!+ pushTo trail p --- __Pre-condition:__ propagation queue is empty+-- | __Pre-condition:__ propagation queue is empty. {-# INLINE unsafeAssume #-} unsafeAssume :: Solver -> Lit -> IO () unsafeAssume s@Solver{..} p = do- pushToStack trailLim =<< sizeOfStack trail+ pushTo trailLim =<< get' trail unsafeEnqueue s p NullClause
SAT/Mios/OptionParser.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE Safe #-} -- | command line option parser for mios@@ -18,7 +17,7 @@ import System.Console.GetOpt (ArgDescr(..), ArgOrder(..), getOpt, OptDescr(..), usageInfo) import System.Environment (getArgs)-import SAT.Mios.Internal (MiosConfiguration (..), defaultConfiguration)+import SAT.Mios.Types (MiosConfiguration (..), defaultConfiguration) -- | configuration swithces data MiosProgramOption = MiosProgramOption
SAT/Mios/Solver.hs view
@@ -12,7 +12,9 @@ ( -- * Solver Solver (..)+ , VarHeap , newSolver+ , getModel -- * Misc Accessors , nAssigns , nClauses@@ -20,13 +22,13 @@ , decisionLevel , valueVar , valueLit+-- , oldLit , locked -- * State Modifiers , addClause , enqueue , assume , cancelUntil- , getModel -- * Activities , claBumpActivity -- , claDecayActivity@@ -43,165 +45,177 @@ ) where -import Control.Monad ((<=<), forM_, unless, when)+import Control.Monad (unless, when) import SAT.Mios.Types-import SAT.Mios.Internal import SAT.Mios.Clause import SAT.Mios.ClauseManager -- | __Fig. 2.(p.9)__ Internal State of the solver data Solver = Solver {- -- Public Interface- model :: !VecBool -- ^ If found, this vector has the model- , conflict :: !Stack -- ^ set of literals in the case of conflicts- -- Clause Database+{- Public Interface -}+ model :: !(Vec Int) -- ^ If found, this vector has the model+ , conflicts :: !Stack -- ^ Set of literals in the case of conflicts+{- Clause Database -} , clauses :: !ClauseExtManager -- ^ List of problem constraints. , learnts :: !ClauseExtManager -- ^ List of learnt clauses.- , watches :: !WatcherList -- ^ a list of constraint wathing 'p', literal-indexed- -- Assignment Management- , assigns :: !Vec -- ^ The current assignments indexed on variables; var-indexed- , phases :: !Vec -- ^ The last assignments indexed on variables; var-indexed- , trail :: !Stack -- ^ List of assignments in chronological order; var-indexed+ , watches :: !WatcherList -- ^ list of constraint wathing 'p', literal-indexed+{- Assignment Management -}+ , assigns :: !(Vec Int) -- ^ The current assignments indexed on variables+ , phases :: !(Vec Int) -- ^ The last assignments indexed on variables+ , trail :: !Stack -- ^ List of assignments in chronological order , trailLim :: !Stack -- ^ Separator indices for different decision levels in 'trail'.- , qHead :: !IntSingleton -- ^ 'trail' is divided at qHead; assignments and queue- , reason :: !ClauseVector -- ^ For each variable, the constraint that implied its value; var-indexed- , level :: !Vec -- ^ For each variable, the decision level it was assigned; var-indexed- -- Variable Order- , activities :: !VecDouble -- ^ Heuristic measurement of the activity of a variable; var-indexed+ , qHead :: !Int' -- ^ 'trail' is divided at qHead; assignment part and queue part+ , reason :: !ClauseVector -- ^ For each variable, the constraint that implied its value+ , level :: !(Vec Int) -- ^ For each variable, the decision level it was assigned+{- Variable Order -}+ , activities :: !(Vec Double) -- ^ Heuristic measurement of the activity of a variable , order :: !VarHeap -- ^ Keeps track of the dynamic variable order.- -- Configuration+{- Configuration -} , config :: !MiosConfiguration -- ^ search paramerters , nVars :: !Int -- ^ number of variables--- , claInc :: !DoubleSingleton -- ^ Clause activity increment amount to bump with.--- , varDecay :: !DoubleSingleton -- ^ used to set 'varInc'- , varInc :: !DoubleSingleton -- ^ Variable activity increment amount to bump with.- , rootLevel :: !IntSingleton -- ^ Separates incremental and search assumptions.- -- Working Memory- , ok :: !BoolSingleton -- ^ return value holder- , an'seen :: !Vec -- ^ scratch var for 'analyze'; var-indexed- , an'toClear :: !Stack -- ^ ditto- , an'stack :: !Stack -- ^ ditto- , pr'seen :: !Vec -- ^ used in propagate- , litsLearnt :: !Stack -- ^ used to create a learnt clause- , lastDL :: !Stack -- ^ last decision level used in analyze- , stats :: !Vec -- ^ statistics information holder {-+ -- , claInc :: !Double' -- ^ Clause activity increment amount to bump with.+ -- , varDecay :: !Double' -- ^ used to set 'varInc'+-}+ , varInc :: !Double' -- ^ Variable activity increment amount to bump with.+ , rootLevel :: !Int' -- ^ Separates incremental and search assumptions.+{- Working Memory -}+ , ok :: !Bool' -- ^ /return value/ holder+ , an'seen :: !(Vec Int) -- ^ used in 'SAT.Mios.Main.analyze'+ , an'toClear :: !Stack -- ^ used in 'SAT.Mios.Main.analyze'+ , an'stack :: !Stack -- ^ used in 'SAT.Mios.Main.analyze'+ , an'lastDL :: !Stack -- ^ last decision level used in 'SAT.Mios.Main.analyze'+ , litsLearnt :: !Stack -- ^ used in 'SAT.Mios.Main.analyze' and 'SAT.Mios.Main.search' to create a learnt clause++{-+ -- , pr'seen :: !(Vec Int) -- ^ used in 'SAT.Mios.Main.propagate'+-}+ , stats :: !(UVector Int) -- ^ statistics information holder+{- , lbd'seen :: !Vec -- ^ used in lbd computation- , lbd'key :: !IntSingleton -- ^ used in lbd computation+ , lbd'key :: !Int' -- ^ used in lbd computation -} } --- | returns an everything-is-initialized solver from the arguments+-- | returns an everything-is-initialized solver from the arguments. newSolver :: MiosConfiguration -> CNFDescription -> IO Solver newSolver conf (CNFDescription nv nc _) = do Solver -- Public Interface- <$> newVecBool nv False -- model- <*> newStack nv -- coflict+ <$> newVec nv 0 -- model+ <*> newStack nv -- coflict -- Clause Database- <*> newManager nc -- clauses- <*> newManager nc -- learnts- <*> newWatcherList nv 2 -- watches+ <*> newManager nc -- clauses+ <*> newManager nc -- learnts+ <*> newWatcherList nv 2 -- watches -- Assignment Management- <*> newVecWith (nv + 1) lBottom -- assigns- <*> newVecWith (nv + 1) lBottom -- phases- <*> newStack nv -- trail- <*> newStack nv -- trailLim- <*> newInt 0 -- qHead- <*> newClauseVector (nv + 1) -- reason- <*> newVecWith (nv + 1) (-1) -- level+ <*> newVec nv lBottom -- assigns+ <*> newVec nv lBottom -- phases+ <*> newStack nv -- trail+ <*> newStack nv -- trailLim+ <*> new' 0 -- qHead+ <*> newClauseVector (nv + 1) -- reason+ <*> newVec nv (-1) -- level -- Variable Order- <*> newVecDouble (nv + 1) 0 -- activities- <*> newVarHeap nv -- order+ <*> newVec nv 0 -- activities+ <*> newVarHeap nv -- order -- Configuration- <*> return conf -- config- <*> return nv -- nVars--- <*> newDouble 1.0 -- claInc--- <*> newDouble (variableDecayRate conf) -- varDecay- <*> newDouble 1.0 -- varInc- <*> newInt 0 -- rootLevel+ <*> return conf -- config+ <*> return nv -- nVars+-- <*> new' 1.0 -- claInc+-- <*> new' (variableDecayRate conf) -- varDecay+ <*> new' 1.0 -- varInc+ <*> new' 0 -- rootLevel -- Working Memory- <*> newBool True -- ok- <*> newVec (nv + 1) -- an'seen- <*> newStack nv -- an'toClear- <*> newStack nv -- an'stack- <*> newVecWith (nv + 1) (-1) -- pr'seen- <*> newStack nv -- litsLearnt- <*> newStack nv -- lastDL- <*> newVec (1 + fromEnum (maxBound :: StatIndex)) -- stats+ <*> new' True -- ok+ <*> newVec nv 0 -- an'seen+ <*> newStack nv -- an'toClear+ <*> newStack nv -- an'stack+-- <*> newVec nv (-1) -- pr'seen+ <*> newStack nv -- litsLearnt+ <*> newStack nv -- lastDL+ <*> newVec (fromEnum EndOfStatIndex) 0 -- stats {---- <*> newVec nv -- lbd'seen--- <*> newInt 0 -- lbd'key+-- <*> newVec nv -- lbd'seen+-- <*> newInt 0 -- lbd'key -} -------------------------------------------------------------------------------- -- Accessors --- | returns the number of current assigments+-- | returns the number of current assigments. {-# INLINE nAssigns #-} nAssigns :: Solver -> IO Int-nAssigns = sizeOfStack . trail+nAssigns = get' . trail --- | returns the number of constraints (clauses)+-- | returns the number of constraints (clauses). {-# INLINE nClauses #-}-nClauses :: Solver -> IO Int-nClauses = numberOfClauses . clauses+nClauses :: Solver -> IO Int+nClauses = get' . clauses --- | returns the number of learnt clauses+-- | returns the number of learnt clauses. {-# INLINE nLearnts #-} nLearnts :: Solver -> IO Int-nLearnts = numberOfClauses . learnts+nLearnts = get' . learnts --- | return the model as a list of literal+-- | returns the model as a list of literal. getModel :: Solver -> IO [Int]-getModel s = zipWith (\n b -> if b then n else negate n) [1 .. ] <$> asList (model s)+getModel = asList . model --- | returns the current decision level+-- | returns the current decision level. {-# INLINE decisionLevel #-} decisionLevel :: Solver -> IO Int-decisionLevel = sizeOfStack . trailLim+decisionLevel = get' . trailLim --- | returns the assignment (:: 'LiftedBool' = @[-1, 0, -1]@) from 'Var'+-- | returns the assignment (:: 'LiftedBool' = @[-1, 0, -1]@) from 'Var'. {-# INLINE valueVar #-} valueVar :: Solver -> Var -> IO Int valueVar = getNth . assigns --- | returns the assignment (:: 'LiftedBool' = @[-1, 0, -1]@) from 'Lit'+-- | returns the assignment (:: 'LiftedBool' = @[-1, 0, -1]@) from 'Lit'. {-# INLINE valueLit #-}-valueLit :: Solver -> Lit -> IO Int -- FIXME: LiftedBool-valueLit (assigns -> a) !p = (\x -> if positiveLit p then x else negate x) <$> getNth a (lit2var p)+valueLit :: Solver -> Lit -> IO Int+valueLit (assigns -> a) p = (\x -> if positiveLit p then x else negate x) <$> getNth a (lit2var p) +{-+-- | returns the assignment (:: 'LiftedBool' = @[-1, 0, -1]@) from 'Lit' in phases.+{-# INLINE oldLit #-}+oldLit :: Solver -> Lit -> IO Lit+oldLit (phases -> a) (lit2var -> v) = (var2lit v . (== 1)) <$> getNth a v+-}+ -- | __Fig. 7. (p.11)__ -- returns @True@ if the clause is locked (used as a reason). __Learnt clauses only__ {-# INLINE locked #-} locked :: Solver -> Clause -> IO Bool-locked s c = (c ==) <$> (getNthClause (reason s) . lit2var =<< getNth (lits c) 1)+locked s c = (c ==) <$> (getNth (reason s) . lit2var =<< getNth (lits c) 1) -------------------------------------------------------------------------------- Statistics -- | stat index data StatIndex =- NumOfBackjump- | NumOfRestart+ NumOfBackjump -- ^ the number of backjump+ | NumOfRestart -- ^ the number of restart+ | EndOfStatIndex -- ^ Don't use this dummy. deriving (Bounded, Enum, Eq, Ord, Read, Show) --- | returns the value of 'StatIndex'+-- | returns the value of 'StatIndex'. {-# INLINE getStat #-} getStat :: Solver -> StatIndex -> IO Int getStat (stats -> v) (fromEnum -> i) = getNth v i --- | sets to 'StatIndex'+-- | sets to 'StatIndex'. {-# INLINE setStat #-} setStat :: Solver -> StatIndex -> Int -> IO () setStat (stats -> v) (fromEnum -> i) x = setNth v i x --- | increments a stat data corresponding to 'StatIndex'+-- | increments a stat data corresponding to 'StatIndex'. {-# INLINE incrementStat #-} incrementStat :: Solver -> StatIndex -> Int -> IO () incrementStat (stats -> v) (fromEnum -> i) k = modifyNth v (+ k) i --- | returns the statistics as list+-- | returns the statistics as a list. {-# INLINABLE getStats #-} getStats :: Solver -> IO [(StatIndex, Int)] getStats (stats -> v) = mapM (\i -> (i, ) <$> getNth v (fromEnum i)) [minBound .. maxBound :: StatIndex]@@ -211,16 +225,14 @@ -- | returns @False@ if a conflict has occured. -- This function is called only before the solving phase to register the given clauses. {-# INLINABLE addClause #-}-addClause :: Solver -> Vec -> IO Bool+addClause :: Solver -> Stack -> IO Bool addClause s@Solver{..} vecLits = do result <- clauseNew s vecLits False case result of- (False, _) -> return False -- Conflict occured- (True, c) -> do- unless (c == NullClause) $ pushClause clauses c- return True -- No conflict+ Left b -> return b -- No new clause was returned becaues a confilct occured or the clause is a literal+ Right c -> pushTo clauses c >> return True --- | __Fig. 8. (p.12)__ create a new clause and adds it to watcher lists+-- | __Fig. 8. (p.12)__ create a new clause and adds it to watcher lists. -- Constructor function for clauses. Returns @False@ if top-level conflict is determined. -- @outClause@ may be set to Null if the new clause is already satisfied under the current -- top-level assignment.@@ -230,8 +242,12 @@ -- For the propagation to work, the second watch must be put on the literal which will -- first be unbound by backtracking. (Note that none of the learnt-clause specific things -- needs to done for a user defined contraint type.)+--+-- * @Left False@ if the clause is in a confilct+-- * @Left True@ if the clause is satisfied+-- * @Right clause@ if the clause is enqueued successfully {-# INLINABLE clauseNew #-}-clauseNew :: Solver -> Vec -> Bool -> IO (Bool, Clause)+clauseNew :: Solver -> Stack -> Bool -> IO (Either Bool Clause) clauseNew s@Solver{..} ps isLearnt = do -- now ps[0] is the number of living literals exit <- do@@ -246,11 +262,11 @@ swapBetween ps j n modifyNth ps (subtract 1) 0 handle j l (n - 1)- _ | - y == l -> setNth ps 0 0 >> return True -- p and negateLit p occurs in ps+ _ | - y == l -> reset ps >> return True -- p and negateLit p occurs in ps _ -> handle (j + 1) l n loopForLearnt :: Int -> IO Bool loopForLearnt i = do- n <- getNth ps 0+ n <- get' ps if n < i then return False else do@@ -261,14 +277,14 @@ else loopForLearnt $ i + 1 loop :: Int -> IO Bool loop i = do- n <- getNth ps 0+ n <- get' ps if n < i then return False else do l <- getNth ps i -- check the i-th literal's satisfiability- sat <- valueLit s l -- any literal in ps is true+ sat <- valueLit s l -- any literal in ps is true case sat of- 1 -> setNth ps 0 0 >> return True+ 1 -> reset ps >> return True -1 -> do swapBetween ps i n modifyNth ps (subtract 1) 0@@ -279,16 +295,16 @@ then return True else loop $ i + 1 if isLearnt then loopForLearnt 1 else loop 1- k <- getNth ps 0+ k <- get' ps case k of- 0 -> return (exit, NullClause)+ 0 -> return (Left exit) 1 -> do l <- getNth ps 1- (, NullClause) <$> enqueue s l NullClause+ Left <$> enqueue s l NullClause _ -> do- -- allocate clause:- c <- newClauseFromVec isLearnt ps- let vec = asVec c+ -- allocate clause:+ c <- newClauseFromStack isLearnt ps+ let vec = asUVector c when isLearnt $ do -- Pick a second literal to watch: let@@ -296,6 +312,7 @@ findMax ((< k) -> False) j _ = return j findMax i j val = do v' <- lit2var <$> getNth vec i+ varBumpActivity s v' -- this is a just good chance to bump activities of literals in this clause a <- getNth assigns v' b <- getNth level v' if (a /= lBottom) && (val < b)@@ -309,13 +326,12 @@ -- unless (length x == length (nub x)) $ error "new clause contains a element doubly" -- Bumping: claBumpActivity s c -- newly learnt clauses should be considered active- forM_ [0 .. k -1] $ varBumpActivity s . lit2var <=< getNth vec -- variables in conflict clauses are bumped -- Add clause to watcher lists: l0 <- negateLit <$> getNth vec 0 pushClauseWithKey (getNthWatcher watches l0) c 0 l1 <- negateLit <$> getNth vec 1 pushClauseWithKey (getNthWatcher watches l1) c 0- return (True, c)+ return (Right c) -- | __Fig. 9 (p.14)__ -- Puts a new fact on the propagation queue, as well as immediately updating the variable's value@@ -328,9 +344,9 @@ {- -- bump psedue lbd of @from@ when (from /= NullClause && learnt from) $ do- l <- getInt (lbd from)+ l <- get' (lbd from) k <- (12 +) <$> decisionLevel s- when (k < l) $ setInt (lbd from) k+ when (k < l) $ set' (lbd from) k -} let signumP = if positiveLit p then lTrue else lFalse let v = lit2var p@@ -342,8 +358,8 @@ -- New fact, store it setNth assigns v signumP setNth level v =<< decisionLevel s- setNthClause reason v from -- NOTE: @from@ might be NULL!- pushToStack trail p+ setNth reason v from -- NOTE: @from@ might be NULL!+ pushTo trail p return True -- | __Fig. 12 (p.17)__@@ -353,7 +369,7 @@ {-# INLINE assume #-} assume :: Solver -> Lit -> IO Bool assume s p = do- pushToStack (trailLim s) =<< sizeOfStack (trail s)+ pushTo (trailLim s) =<< get' (trail s) enqueue s p NullClause -- | #M22: Revert to the states at given level (keeping all assignment at 'level' but not beyond).@@ -362,11 +378,11 @@ cancelUntil s@Solver{..} lvl = do dl <- decisionLevel s when (lvl < dl) $ do- let tr = asVec trail- let tl = asVec trailLim+ let tr = asUVector trail+ let tl = asUVector trailLim lim <- getNth tl lvl- ts <- sizeOfStack trail- ls <- sizeOfStack trailLim+ ts <- get' trail+ ls <- get' trailLim let loopOnTrail :: Int -> IO () loopOnTrail ((lim <=) -> False) = return ()@@ -377,20 +393,21 @@ -- #reason to set reason Null -- if we don't clear @reason[x] :: Clause@ here, @reason[x]@ remains as locked. -- This means we can't reduce it from clause DB and affects the performance.- setNthClause reason x NullClause -- 'analyze` uses reason without checking assigns+ setNth reason x NullClause -- 'analyze` uses reason without checking assigns -- FIXME: #polarity https://github.com/shnarazk/minisat/blosb/master/core/Solver.cc#L212 undo s x -- insertHeap s x -- insertVerOrder loopOnTrail $ c - 1 loopOnTrail $ ts - 1- shrinkStack trail (ts - lim)- shrinkStack trailLim (ls - lvl)- setInt qHead =<< sizeOfStack trail+ shrinkBy trail (ts - lim)+ shrinkBy trailLim (ls - lvl)+ set' qHead =<< get' trail -------------------------------------------------------------------------------- VarOrder -- | Interfate to select a decision var based on variable activity. instance VarOrder Solver where+{- -- | __Fig. 6. (p.10)__ -- Creates a new SAT variable in the solver. newVar _ = return 0@@ -405,6 +422,7 @@ -- newVar order -- growQueueSized (i + 1) propQ -- return i+-} {-# SPECIALIZE INLINE update :: Solver -> Var -> IO () #-} update = increaseHeap {-# SPECIALIZE INLINE undo :: Solver -> Var -> IO () #-}@@ -430,6 +448,7 @@ varActivityThreshold :: Double varActivityThreshold = 1e100 +-- | value for rescaling clause activity. claActivityThreshold :: Double claActivityThreshold = 1e20 @@ -437,32 +456,35 @@ {-# INLINE varBumpActivity #-} varBumpActivity :: Solver -> Var -> IO () varBumpActivity s@Solver{..} x = do- !a <- (+) <$> getNthDouble x activities <*> getDouble varInc- setNthDouble x activities a+ !a <- (+) <$> getNth activities x <*> get' varInc+ setNth activities x a when (varActivityThreshold < a) $ varRescaleActivity s update s x -- update the position in heap -- | __Fig. 14 (p.19)__-{-# INLINE varDecayActivity #-}+{-# INLINABLE varDecayActivity #-} varDecayActivity :: Solver -> IO ()-varDecayActivity Solver{..} = modifyDouble varInc (/ variableDecayRate config)+varDecayActivity Solver{..} = modify' varInc (/ variableDecayRate config) -- varDecayActivity Solver{..} = modifyDouble varInc . (flip (/)) =<< getDouble varDecay -- | __Fig. 14 (p.19)__-{-# INLINE varRescaleActivity #-}+{-# INLINABLE varRescaleActivity #-} varRescaleActivity :: Solver -> IO () varRescaleActivity Solver{..} = do- forM_ [1 .. nVars] $ \i -> modifyNthDouble i activities (/ varActivityThreshold)- modifyDouble varInc (/ varActivityThreshold)+ let+ loop ((<= nVars) -> False) = return ()+ loop i = modifyNth activities (/ varActivityThreshold) i >> loop (i + 1)+ loop 1+ modify' varInc (/ varActivityThreshold) -- | __Fig. 14 (p.19)__ {-# INLINE claBumpActivity #-} claBumpActivity :: Solver -> Clause -> IO () claBumpActivity s Clause{..} = do dl <- decisionLevel s- a <- (fromIntegral dl +) <$> getDouble activity- setDouble activity a- -- setBool protected True+ a <- (fromIntegral dl +) <$> get' activity+ set' activity a+ -- set' protected True when (claActivityThreshold <= a) $ claRescaleActivity s {-@@ -473,66 +495,66 @@ -} -- | __Fig. 14 (p.19)__-{-# INLINE claRescaleActivity #-}+{-# INLINABLE claRescaleActivity #-} claRescaleActivity :: Solver -> IO () claRescaleActivity Solver{..} = do vec <- getClauseVector learnts- n <- numberOfClauses learnts+ n <- get' learnts let loopOnVector :: Int -> IO () loopOnVector ((< n) -> False) = return () loopOnVector i = do- c <- getNthClause vec i- modifyDouble (activity c) (/ claActivityThreshold)+ c <- getNth vec i+ modify' (activity c) (/ claActivityThreshold) loopOnVector $ i + 1 loopOnVector 0 -- modifyDouble claInc (/ claActivityThreshold) -- | __Fig. 14 (p.19)__-{-# INLINE claRescaleActivityAfterRestart #-}+{-# INLINABLE claRescaleActivityAfterRestart #-} claRescaleActivityAfterRestart :: Solver -> IO () claRescaleActivityAfterRestart Solver{..} = do vec <- getClauseVector learnts- n <- numberOfClauses learnts+ n <- get' learnts let loopOnVector :: Int -> IO () loopOnVector ((< n) -> False) = return () loopOnVector i = do- c <- getNthClause vec i- d <- sizeOfClause c+ c <- getNth vec i+ d <- get' c if d < 9- then modifyDouble (activity c) sqrt- else setDouble (activity c) 0- setBool (protected c) False+ then modify' (activity c) sqrt+ else set' (activity c) 0+ set' (protected c) False loopOnVector $ i + 1 loopOnVector 0 -------------------------------------------------------------------------------- VarHeap --- | 'VarHeap' is a heap tree built from two 'Vec'--- This implementation is identical wtih that in Minisat-1.14--- Note: the zero-th element of @heap@ is used for holding the number of elements--- Note: VarHeap itself is not a @VarOrder@, because it requires a pointer to solver+-- | A heap tree built from two 'Vec'.+-- This implementation is identical wtih that in Minisat-1.14.+-- Note: the zero-th element of @heap@ is used for holding the number of elements.+-- Note: VarHeap itself is not a @VarOrder@, because it requires a pointer to solver. data VarHeap = VarHeap {- heap :: Vec -- order to var- , idxs :: Vec -- var to order (index)+ heap :: !Stack -- order to var+ , idxs :: !Stack -- var to order (index) } newVarHeap :: Int -> IO VarHeap newVarHeap n = do- v1 <- newVec (n + 1)- v2 <- newVec (n + 1)+ v1 <- newVec n 0+ v2 <- newVec n 0 let loop :: Int -> IO ()- loop ((<= n) -> False) = setNth v1 0 n >> setNth v2 0 n+ loop ((<= n) -> False) = set' v1 n >> set' v2 n loop i = setNth v1 i i >> setNth v2 i i >> loop (i + 1) loop 1 return $ VarHeap v1 v2 {-# INLINE numElementsInHeap #-} numElementsInHeap :: Solver -> IO Int-numElementsInHeap (order -> heap -> h) = getNth h 0+numElementsInHeap = get' . heap . order {-# INLINE inHeap #-} inHeap :: Solver -> Var -> IO Bool@@ -547,7 +569,7 @@ percolateUp Solver{..} start = do let VarHeap to at = order v <- getNth to start- ac <- getNthDouble v activities+ ac <- getNth activities v let loop :: Int -> IO () loop i = do@@ -556,7 +578,7 @@ then setNth to i v >> setNth at v i -- end else do v' <- getNth to iP- acP <- getNthDouble v' activities+ acP <- getNth activities v' if ac > acP then setNth to i v' >> setNth at v' i >> loop iP -- loop else setNth to i v >> setNth at v i -- end@@ -568,7 +590,7 @@ let (VarHeap to at) = order n <- getNth to 0 v <- getNth to start- ac <- getNthDouble v activities+ ac <- getNth activities v let loop :: Int -> IO () loop i = do@@ -578,8 +600,8 @@ let iR = iL + 1 -- right l <- getNth to iL r <- getNth to iR- acL <- getNthDouble l activities- acR <- getNthDouble r activities+ acL <- getNth activities l+ acR <- getNth activities r let (ci, child, ac') = if iR <= n && acL < acR then (iR, r, acR) else (iL, l, acL) if ac' > ac then setNth to i child >> setNth at child i >> loop ci@@ -587,17 +609,17 @@ else setNth to i v >> setNth at v i -- end loop start -{-# INLINE insertHeap #-}+{-# INLINABLE insertHeap #-} insertHeap :: Solver -> Var -> IO () insertHeap s@(order -> VarHeap to at) v = do n <- (1 +) <$> getNth to 0 setNth at v n setNth to n v- setNth to 0 n+ set' to n percolateUp s n --- | renamed from 'getmin'-{-# INLINE getHeapRoot #-}+-- | returns the value on the root (renamed from @getmin@).+{-# INLINABLE getHeapRoot #-} getHeapRoot :: Solver -> IO Int getHeapRoot s@(order -> VarHeap to at) = do r <- getNth to 1
SAT/Mios/Types.hs view
@@ -1,21 +1,13 @@ {-# LANGUAGE BangPatterns- , FlexibleContexts- , FlexibleInstances- , FunctionalDependencies , MultiParamTypeClasses #-}-{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE Safe #-} -- | Basic data types used throughout mios. module SAT.Mios.Types (- -- Singleton- module SAT.Mios.Data.Singleton- -- Fixed Unboxed Mutable Int Vector- , module SAT.Mios.Data.Vec- -- Abstract interfaces- , VectorFamily (..)+ module SAT.Mios.Vec -- * Variable , Var , bottomVar@@ -25,64 +17,37 @@ , lit2int , int2lit , bottomLit- , newLit+-- , newLit , positiveLit , lit2var , var2lit , negateLit- -- * Assignment- , LiftedBool (..)- , lbool+ -- * Assignment on the lifted Bool domain+-- , LiftedBool (..)+-- , lbool , lFalse , lTrue , lBottom , VarOrder (..) -- * CNF , CNFDescription (..)+ -- * Solver Configuration+ , MiosConfiguration (..)+ , defaultConfiguration ) where -import Control.Monad (forM) import Data.Bits-import qualified Data.Vector.Unboxed.Mutable as UV-import SAT.Mios.Data.Singleton-import SAT.Mios.Data.Vec---- | Public interface as /Container/-class VectorFamily s t | s -> t where- -- * Size operations- -- | erases all elements in it- clear :: s -> IO ()- clear = error "no default method for clear"- -- * Debug- -- | dump the contents- dump :: Show t => String -> s -> IO String- dump msg _ = error $ msg ++ ": no defalut method for dump"- -- | get a raw data- asVec :: s -> UV.IOVector Int- asVec = error "asVector undefined"- -- | converts into a list- asList :: s -> IO [t]- asList = error "asList undefined"- {-# MINIMAL dump #-}---- | provides 'clear' and 'size'-instance VectorFamily Vec Int where- clear = error "Vec.clear"- {-# SPECIALIZE INLINE asList :: Vec -> IO [Int] #-}- asList v = forM [0 .. UV.length v - 1] $ UV.unsafeRead v- dump str v = (str ++) . show <$> asList v- {-# SPECIALIZE INLINE asVec :: Vec -> Vec #-}- asVec = id+import SAT.Mios.Vec --- | represents "Var"+-- | represents "Var". type Var = Int -- | Special constant in 'Var' (p.7) bottomVar :: Var bottomVar = 0 --- | converts a usual Int as literal to an internal 'Var' presentation+-- | converts a usual Int as literal to an internal 'Var' presentation. -- -- >>> int2var 1 -- 1 -- the first literal is the first variable@@ -92,6 +57,7 @@ -- 2 -- literal @-2@ is corresponding to variable 2 -- {-# INLINE int2var #-}+int2var :: Int -> Int int2var = abs -- | The literal data has an 'index' method which converts the literal to@@ -104,9 +70,11 @@ bottomLit :: Lit bottomLit = 0 +{- -- | converts "Var" into 'Lit' newLit :: Var -> Lit newLit = error "newLit undefined"+-} -- | returns @True@ if the literal is positive {-# INLINE positiveLit #-}@@ -125,13 +93,13 @@ -- 4 {-# INLINE negateLit #-} negateLit :: Lit -> Lit-negateLit !l = complementBit l 0 -- if even l then l + 1 else l - 1+negateLit l = complementBit l 0 -- if even l then l + 1 else l - 1 ---------------------------------------- ----------------- Var ---------------------------------------- --- | converts 'Lit' into 'Var'+-- | converts 'Lit' into 'Var'. -- -- >>> lit2var 2 -- 1@@ -145,7 +113,7 @@ lit2var :: Lit -> Var lit2var !n = shiftR n 1 --- | converts a 'Var' to the corresponing literal+-- | converts a 'Var' to the corresponing literal. -- -- >>> var2lit 1 True -- 2@@ -164,7 +132,7 @@ ----------------- Int ---------------------------------------- --- | converts 'Int' into 'Lit' as @lit2int . int2lit == id@+-- | converts 'Int' into 'Lit' as @lit2int . int2lit == id@. -- -- >>> int2lit 1 -- 2@@ -181,7 +149,7 @@ | 0 < n = 2 * n | otherwise = -2 * n + 1 --- | converts `Lit' into 'Int' as @int2lit . lit2int == id@+-- | converts `Lit' into 'Int' as @int2lit . lit2int == id@. -- -- >>> lit2int 2 -- 1@@ -197,6 +165,7 @@ (i, 0) -> i (i, _) -> - i +{- -- | Lifted Boolean domain (p.7) that extends 'Bool' with "⊥" means /undefined/ -- design note: _|_ should be null = 0; True literals are coded to even numbers. So it should be 2. data LiftedBool = Bottom | LFalse | LTrue@@ -217,16 +186,17 @@ lbool :: Bool -> LiftedBool lbool True = LTrue lbool False = LFalse+-} --- | A contant representing False+-- | /FALSE/ on the Lifted Bool domain lFalse:: Int lFalse = -1 --- | A constant representing True+-- | /TRUE/ on the Lifted Bool domain lTrue :: Int lTrue = 1 --- | A constant for "undefined"+-- | /UNDEFINED/ on the Lifted Bool domain lBottom :: Int lBottom = 0 @@ -235,35 +205,53 @@ -- vector of the solver. The method 'select' will return the unassigned variable -- with the highest activity. class VarOrder o where+{- -- | constructor- newVarOrder :: (VectorFamily v1 Bool, VectorFamily v2 Double) => v1 -> v2 -> IO o+ newVarOrder :: (VecFamily v1 Bool, VecFamily v2 Double) => v1 -> v2 -> IO o newVarOrder _ _ = error "newVarOrder undefined" -- | Called when a new variable is created. newVar :: o -> IO Var newVar = error "newVar undefined"-- -- | Called when variable has increased in activity.+-}+ -- | should be called when a variable has increased in activity. update :: o -> Var -> IO () update _ = error "update undefined"-- -- | Called when all variables have been assigned new activities.+{-+ -- | should be called when all variables have been assigned. updateAll :: o -> IO () updateAll = error "updateAll undefined"-- -- | Called when variable is unbound (may be selected again).+-}+ -- | should be called when a variable becomes unbound (may be selected again). undo :: o -> Var -> IO () undo _ _ = error "undo undefined" - -- | Called to select a new, unassigned variable.+ -- | returns a new, unassigned var as the next decision. select :: o -> IO Var select = error "select undefined" --- | misc information on CNF+-- | Misc information on a CNF data CNFDescription = CNFDescription {- _numberOfVariables :: !Int -- ^ number of variables- , _numberOfClauses :: !Int -- ^ number of clauses+ _numberOfVariables :: !Int -- ^ the number of variables+ , _numberOfClauses :: !Int -- ^ the number of clauses , _pathname :: Maybe FilePath -- ^ given filename } deriving (Eq, Ord, Show)++-- | Solver's parameters; random decision rate was dropped.+data MiosConfiguration = MiosConfiguration+ {+ variableDecayRate :: !Double -- ^ decay rate for variable activity+-- , clauseDecayRate :: !Double -- ^ decay rate for clause activity+ }++-- | dafault configuration+--+-- * Minisat-1.14 uses @(0.95, 0.999, 0.2 = 20 / 1000)@.+-- * Minisat-2.20 uses @(0.95, 0.999, 0)@.+-- * Gulcose-4.0 uses @(0.8 , 0.999, 0)@.+-- * Mios-1.2 uses @(0.95, 0.999, 0)@.+--+defaultConfiguration :: MiosConfiguration+defaultConfiguration = MiosConfiguration 0.95 {- 0.999 -} {- 0 -}
− SAT/Mios/Util/CNFIO.hs
@@ -1,31 +0,0 @@-{-# LANGUAGE Safe #-}---- | Read/Write a CNF file only with ghc standard libraries-module SAT.Mios.Util.CNFIO- (- -- * Input- fromFile- , clauseListFromFile- , fromMinisatOutput- , clauseListFromMinisatOutput- -- * Output- , toFile- , toCNFString- , asCNFString- , asCNFString_- -- * Bool Operation- , module SAT.Mios.Util.BoolExp- )- where-import SAT.Mios.Util.CNFIO.Reader-import SAT.Mios.Util.CNFIO.Writer-import SAT.Mios.Util.CNFIO.MinisatReader-import SAT.Mios.Util.BoolExp---- | String from BoolFrom-asCNFString :: BoolForm -> String-asCNFString = toCNFString . asList---- | String from BoolFrom-asCNFString_ :: BoolForm -> String-asCNFString_ = toCNFString . asList_
− SAT/Mios/Util/CNFIO/MinisatReader.hs
@@ -1,73 +0,0 @@-{-# LANGUAGE Safe #-}---- | Read an output file of minisat-module SAT.Mios.Util.CNFIO.MinisatReader- (- -- * Interface- fromMinisatOutput- , clauseListFromMinisatOutput- )- where--- import Control.Applicative ((<$>), (<*>), (<*), (*>))-import Data.Char-import Text.ParserCombinators.ReadP---- parser--- |parse a non-signed integer-{-# INLINE pint #-}-pint = do- n <- munch isDigit- return (read n :: Int)--{-# INLINE mint #-}-mint = do- char '-'- n <- munch isDigit- return (- (read n::Int))---- |parse a (signed) integer-{-# INLINE int #-}-int = mint <++ pint---- |return integer list that terminates at zero-{-# INLINE seqNums #-}-seqNums = do- skipSpaces- x <- int- skipSpaces- if (x == 0) then return [] else (x :) <$> seqNums---- |top level interface for parsing CNF-{-# INLINE parseMinisatOutput #-}-parseMinisatOutput :: ReadP ((Int, Int), [Int])-parseMinisatOutput = do- string "SAT"- skipSpaces- l <- seqNums- return ((length l,0), l)---- |read a minisat output:--- ((numbefOfVariables, 0), [Literal])------ >>> fromFile "result"--- ((3, 0), [1, -2, 3])----{-# INLINE fromMinisatOutput #-}-fromMinisatOutput :: FilePath -> IO (Maybe ((Int, Int), [Int]))-fromMinisatOutput f = do- c <- readFile f- case readP_to_S parseMinisatOutput c of- [(a, _)] -> return $ Just a- _ -> return Nothing---- | return clauses as [[Int]] from 'file'------ >>> clauseListFromMinisatOutput "result"--- [1,-2,3]----clauseListFromMinisatOutput :: FilePath -> IO [Int]-clauseListFromMinisatOutput l = do- res <- fromMinisatOutput l- case res of- Just p -> return (snd p)- _ -> return []
− SAT/Mios/Util/CNFIO/Reader.hs
@@ -1,130 +0,0 @@-{-# LANGUAGE Safe #-}---- | Read a CNF file without haskell-platform-module SAT.Mios.Util.CNFIO.Reader- (- -- * Interface- fromFile- , clauseListFromFile- )- where-import Control.Applicative ((<$>), (<*>), (<*), (*>))-import Data.Char-import Text.ParserCombinators.ReadP---- parser-{-# INLINE newline #-}-newline = char '\n'--{-# INLINE digit #-}-digit = satisfy isDigit--{-# INLINE spaces #-}-spaces = munch (`elem` " \t")--{-# INLINE noneOf #-}-noneOf s = satisfy (`notElem` s)---- |parse a non-signed integer-{-# INLINE pint #-}-pint = do- n <- munch isDigit- return (read n :: Int)--{-# INLINE mint #-}-mint = do- char '-'- n <- munch isDigit- return (- (read n::Int))---- |parse a (signed) integer-{-# INLINE int #-}-int = mint <++ pint---- |Parse something like: p FORMAT VARIABLES CLAUSES-{-# INLINE problemLine #-}-problemLine = do- char 'p'- skipSpaces- (string "cnf" <++ string "CNF")- skipSpaces- vars <- pint- skipSpaces- clas <- pint- spaces- newline- return (vars, clas)---- |Parse something like: c This in an example of a comment line.-{-# INLINE commentLines #-}-commentLines = do- l <- look- if (head l) == 'c'- then do- munch ('\n' /=)- newline- commentLines- else return ()--_commentLines = do- char 'c'- munch ('\n' /=)- newline- l <- look- if (head l) == 'c' then commentLines else return ()---- |Parse the preamble part-{-# INLINE preambleCNF #-}-preambleCNF = do- commentLines- problemLine---- |return integer list that terminates at zero-{-# INLINE seqNums #-}-seqNums = do- skipSpaces- x <- int- skipSpaces- if (x == 0) then return [] else (x :) <$> seqNums---- |Parse something like: 1 -2 0 4 0 -3 0-{-# INLINE parseClauses #-}-parseClauses :: Int -> ReadP [[Int]]-parseClauses n = count n seqNums---- |top level interface for parsing CNF-{-# INLINE parseCNF #-}-parseCNF :: ReadP ((Int, Int), [[Int]])-parseCNF = do- a <- preambleCNF- b <- parseClauses (snd a)- return (a, b)---- |driver:: String -> Either ParseError Int-driver input = readP_to_S (parseClauses 1) input---- |read a CNF file and return:--- ((numbefOfVariables, numberOfClauses), [Literal])------ >>> fromFile "acnf"--- ((3, 4), [[1, 2], [-2, 3], [-1, 2, -3], [3]]----{-# INLINE fromFile #-}-fromFile :: FilePath -> IO (Maybe ((Int, Int), [[Int]]))-fromFile f = do- c <- readFile f- case readP_to_S parseCNF c of- [(a, _)] -> return $ Just a- _ -> return Nothing---- | return clauses as [[Int]] from 'file'------ >>> clauseListFromFile "a.cnf"--- [[1, 2], [-2, 3], [-1, 2, -3], [3]]----clauseListFromFile :: FilePath -> IO [[Int]]-clauseListFromFile l = do- res <- fromFile l- case res of- Just (_, l) -> return l- _ -> return []
− SAT/Mios/Util/CNFIO/Writer.hs
@@ -1,58 +0,0 @@-{-# LANGUAGE Safe #-}---- | Write SAT data to CNF file-module SAT.Mios.Util.CNFIO.Writer- (- -- * Interface- toFile- , toCNFString- , toString- , toLatexString- )- where-import Data.List (intercalate, nub, sort)-import System.IO---- | Write the CNF to file 'f', using 'toCNFString'-toFile :: FilePath -> [[Int]] -> IO ()-toFile f l = writeFile f $ toCNFString l---- | Convert [Clause] to String, where Clause is [Int]------ >>> toCNFString []--- "p cnf 0 0\n"------ >>> toCNFString [[-1, 2], [-3, -4]]--- "p cnf 4 2\n-1 2 0\n-3 -4 0\n"------ >>> toCNFString [[1], [-2], [-3, -4], [1,2,3,4]]--- "p cnf 4 4\n1 0\n-2 0\n-3 -4 0\n1 2 3 4 0\n"----toCNFString :: [[Int]] -> String-toCNFString l = hdr ++ str- where- hdr = "p cnf " ++ show numV ++ " " ++ show numC ++ "\n"- numC = length l- numV = last $ nub $ sort $ map abs $ concat l- str = concat [intercalate " " (map show c) ++ " 0\n" | c <- l]---- | converts @[[Int]]@ to a String-toString :: [[Int]] -> String -> String -> String-toString l and' or' = intercalate a ["(" ++ intercalate o [ lit x | x <- c] ++ ")" | c <- l]- where- lit x- | 0 <= x = "X" ++ show x- | otherwise = "-X" ++ show (abs x)- a = pad and'- o = pad or'- pad s = " " ++ s ++ " "---- | converts @[[Int]]@ to a LaTeX expression-toLatexString :: [[Int]] -> String-toLatexString l = "\\begin{eqnarray*}\n" ++ intercalate a ["(" ++ intercalate o [ lit x | x <- c] ++ ")" | c <- l] ++ "\n\\end{eqnarray*}"- where- lit x- | 0 <= x = "X_{" ++ show x ++ "}"- | otherwise = "\\overline{X_{" ++ show (abs x) ++ "}}"- a = " \n\\wedge "- o = " \\vee "
+ SAT/Mios/Util/DIMACS.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE Safe #-}++-- | Read/Write a CNF file only with ghc standard libraries+module SAT.Mios.Util.DIMACS+ (+ -- * Input+ fromFile+ , clauseListFromFile+ , fromMinisatOutput+ , clauseListFromMinisatOutput+ -- * Output+ , toFile+ , toDIMACSString+ , asDIMACSString+ , asDIMACSString_+ -- * Bool Operation+ , module SAT.Mios.Util.BoolExp+ )+ where+import SAT.Mios.Util.DIMACS.Reader+import SAT.Mios.Util.DIMACS.Writer+import SAT.Mios.Util.DIMACS.MinisatReader+import SAT.Mios.Util.BoolExp++-- | String from BoolFrom+asDIMACSString :: BoolForm -> String+asDIMACSString = toDIMACSString . asList++-- | String from BoolFrom+asDIMACSString_ :: BoolForm -> String+asDIMACSString_ = toDIMACSString . asList_
+ SAT/Mios/Util/DIMACS/MinisatReader.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE Safe #-}++-- | Read an output file of minisat+module SAT.Mios.Util.DIMACS.MinisatReader+ (+ -- * Interface+ fromMinisatOutput+ , clauseListFromMinisatOutput+ )+ where+-- import Control.Applicative ((<$>), (<*>), (<*), (*>))+import Data.Char+import Text.ParserCombinators.ReadP++-- parser+-- |parse a non-signed integer+{-# INLINE pint #-}+pint = do+ n <- munch isDigit+ return (read n :: Int)++{-# INLINE mint #-}+mint = do+ char '-'+ n <- munch isDigit+ return (- (read n::Int))++-- |parse a (signed) integer+{-# INLINE int #-}+int = mint <++ pint++-- |return integer list that terminates at zero+{-# INLINE seqNums #-}+seqNums = do+ skipSpaces+ x <- int+ skipSpaces+ if (x == 0) then return [] else (x :) <$> seqNums++-- |top level interface for parsing CNF+{-# INLINE parseMinisatOutput #-}+parseMinisatOutput :: ReadP ((Int, Int), [Int])+parseMinisatOutput = do+ string "SAT"+ skipSpaces+ l <- seqNums+ return ((length l,0), l)++-- |read a minisat output:+-- ((numbefOfVariables, 0), [Literal])+--+-- >>> fromFile "result"+-- ((3, 0), [1, -2, 3])+--+{-# INLINE fromMinisatOutput #-}+fromMinisatOutput :: FilePath -> IO (Maybe ((Int, Int), [Int]))+fromMinisatOutput f = do+ c <- readFile f+ case readP_to_S parseMinisatOutput c of+ [(a, _)] -> return $ Just a+ _ -> return Nothing++-- | return clauses as [[Int]] from 'file'+--+-- >>> clauseListFromMinisatOutput "result"+-- [1,-2,3]+--+clauseListFromMinisatOutput :: FilePath -> IO [Int]+clauseListFromMinisatOutput l = do+ res <- fromMinisatOutput l+ case res of+ Just p -> return (snd p)+ _ -> return []
+ SAT/Mios/Util/DIMACS/Reader.hs view
@@ -0,0 +1,130 @@+{-# LANGUAGE Safe #-}++-- | Read a CNF file without haskell-platform+module SAT.Mios.Util.DIMACS.Reader+ (+ -- * Interface+ fromFile+ , clauseListFromFile+ )+ where+import Control.Applicative ((<$>), (<*>), (<*), (*>))+import Data.Char+import Text.ParserCombinators.ReadP++-- parser+{-# INLINE newline #-}+newline = char '\n'++{-# INLINE digit #-}+digit = satisfy isDigit++{-# INLINE spaces #-}+spaces = munch (`elem` " \t")++{-# INLINE noneOf #-}+noneOf s = satisfy (`notElem` s)++-- |parse a non-signed integer+{-# INLINE pint #-}+pint = do+ n <- munch isDigit+ return (read n :: Int)++{-# INLINE mint #-}+mint = do+ char '-'+ n <- munch isDigit+ return (- (read n::Int))++-- |parse a (signed) integer+{-# INLINE int #-}+int = mint <++ pint++-- |Parse something like: p FORMAT VARIABLES CLAUSES+{-# INLINE problemLine #-}+problemLine = do+ char 'p'+ skipSpaces+ (string "cnf" <++ string "CNF")+ skipSpaces+ vars <- pint+ skipSpaces+ clas <- pint+ spaces+ newline+ return (vars, clas)++-- |Parse something like: c This in an example of a comment line.+{-# INLINE commentLines #-}+commentLines = do+ l <- look+ if (head l) == 'c'+ then do+ munch ('\n' /=)+ newline+ commentLines+ else return ()++_commentLines = do+ char 'c'+ munch ('\n' /=)+ newline+ l <- look+ if (head l) == 'c' then commentLines else return ()++-- |Parse the preamble part+{-# INLINE preambleCNF #-}+preambleCNF = do+ commentLines+ problemLine++-- |return integer list that terminates at zero+{-# INLINE seqNums #-}+seqNums = do+ skipSpaces+ x <- int+ skipSpaces+ if (x == 0) then return [] else (x :) <$> seqNums++-- |Parse something like: 1 -2 0 4 0 -3 0+{-# INLINE parseClauses #-}+parseClauses :: Int -> ReadP [[Int]]+parseClauses n = count n seqNums++-- |top level interface for parsing CNF+{-# INLINE parseCNF #-}+parseCNF :: ReadP ((Int, Int), [[Int]])+parseCNF = do+ a <- preambleCNF+ b <- parseClauses (snd a)+ return (a, b)++-- |driver:: String -> Either ParseError Int+driver input = readP_to_S (parseClauses 1) input++-- |read a CNF file and return:+-- ((numbefOfVariables, numberOfClauses), [Literal])+--+-- >>> fromFile "acnf"+-- ((3, 4), [[1, 2], [-2, 3], [-1, 2, -3], [3]]+--+{-# INLINE fromFile #-}+fromFile :: FilePath -> IO (Maybe ((Int, Int), [[Int]]))+fromFile f = do+ c <- readFile f+ case readP_to_S parseCNF c of+ [(a, _)] -> return $ Just a+ _ -> return Nothing++-- | return clauses as [[Int]] from 'file'+--+-- >>> clauseListFromFile "a.cnf"+-- [[1, 2], [-2, 3], [-1, 2, -3], [3]]+--+clauseListFromFile :: FilePath -> IO [[Int]]+clauseListFromFile l = do+ res <- fromFile l+ case res of+ Just (_, l) -> return l+ _ -> return []
+ SAT/Mios/Util/DIMACS/Writer.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE Safe #-}++-- | Write SAT data to DIMACS file+module SAT.Mios.Util.DIMACS.Writer+ (+ -- * Interface+ toFile+ , toDIMACSString+ , toString+ , toLatexString+ )+ where+import Data.List (intercalate, nub, sort)+import System.IO++-- | Write the DIMACS to file 'f', using 'toDIMACSString'+toFile :: FilePath -> [[Int]] -> IO ()+toFile f l = writeFile f $ toDIMACSString l++-- | Convert [Clause] to String, where Clause is [Int]+--+-- >>> toDIMACSString []+-- "p cnf 0 0\n"+--+-- >>> toDIMACSString [[-1, 2], [-3, -4]]+-- "p cnf 4 2\n-1 2 0\n-3 -4 0\n"+--+-- >>> toDIMACSString [[1], [-2], [-3, -4], [1,2,3,4]]+-- "p cnf 4 4\n1 0\n-2 0\n-3 -4 0\n1 2 3 4 0\n"+--+toDIMACSString :: [[Int]] -> String+toDIMACSString l = hdr ++ str+ where+ hdr = "p cnf " ++ show numV ++ " " ++ show numC ++ "\n"+ numC = length l+ numV = last $ nub $ sort $ map abs $ concat l+ str = concat [intercalate " " (map show c) ++ " 0\n" | c <- l]++-- | converts @[[Int]]@ to a String+toString :: [[Int]] -> String -> String -> String+toString l and' or' = intercalate a ["(" ++ intercalate o [ lit x | x <- c] ++ ")" | c <- l]+ where+ lit x+ | 0 <= x = "X" ++ show x+ | otherwise = "-X" ++ show (abs x)+ a = pad and'+ o = pad or'+ pad s = " " ++ s ++ " "++-- | converts @[[Int]]@ to a LaTeX expression+toLatexString :: [[Int]] -> String+toLatexString l = "\\begin{eqnarray*}\n" ++ intercalate a ["(" ++ intercalate o [ lit x | x <- c] ++ ")" | c <- l] ++ "\n\\end{eqnarray*}"+ where+ lit x+ | 0 <= x = "X_{" ++ show x ++ "}"+ | otherwise = "\\overline{X_{" ++ show (abs x) ++ "}}"+ a = " \n\\wedge "+ o = " \\vee "
SAT/Mios/Validator.hs view
@@ -19,9 +19,9 @@ -- | validates the assignment even if the implementation of 'Solver' is wrong; we re-implement some functions here. validate :: Traversable t => Solver -> t Int -> IO Bool validate s (toList -> map int2lit -> lst) = do- assignment <- newVec $ 1 + nVars s+ assignment <- newVec (1 + nVars s) (0 :: Int) :: IO (Vec Int) vec <- getClauseVector (clauses s)- nc <- numberOfClauses (clauses s)+ nc <- get' (clauses s) let inject :: Lit -> IO () inject l = setNth assignment (lit2var l) $ if positiveLit l then lTrue else lFalse@@ -40,8 +40,7 @@ loopOnVector :: Int -> IO Bool loopOnVector ((< nc) -> False) = return True loopOnVector i = do- c <- getNthClause vec i- sat' <- satAny =<< asList c+ sat' <- satAny =<< asList =<< getNth vec i if sat' then loopOnVector (i + 1) else return False if null lst then error "validator got an empty assignment."
+ SAT/Mios/Vec.hs view
@@ -0,0 +1,276 @@+{-# LANGUAGE+ BangPatterns+ , FlexibleContexts+ , FlexibleInstances+ , FunctionalDependencies+ , MultiParamTypeClasses+ , TypeFamilies+ #-}+{-# LANGUAGE Trustworthy #-}++-- | Abstraction Layer for Mutable Vectors+module SAT.Mios.Vec+ (+ -- * Vector class+ VecFamily (..)+ -- * Vectors+ , UVector+ , Vec (..)+ -- * SingleStorage+ , SingleStorage (..)+ , Bool'+ , Double'+ , Int'+ -- * Stack+ , StackFamily (..)+ , Stack+ , newStackFromList+ )+ where++import qualified Data.Vector.Unboxed as U+import qualified Data.Vector.Unboxed.Mutable as UV++-- | Interface on vectors.+class VecFamily v a | v -> a where+ -- | returns the /n/-th value.+ getNth ::v -> Int -> IO a+ -- | sets the /n/-th value.+ setNth :: v -> Int -> a -> IO ()+ -- | erases all elements in it.+ reset:: v -> IO ()+ -- | converts to an Int vector.+ asUVector :: (a ~ Int) => v -> UVector Int+ -- | returns the /n/-th value (index starts from zero in any case).+ -- | swaps two elements.+ swapBetween :: v -> Int -> Int -> IO ()+ -- | calls the update function.+ modifyNth :: v -> (a -> a) -> Int -> IO ()+ -- | returns a new vector.+ newVec :: Int -> a -> IO v+ -- | sets all elements.+ setAll :: v -> a -> IO ()+ -- | extends the size of stack by /n/; note: values in new elements aren't initialized maybe.+ growBy :: v -> Int -> IO v+ -- | converts to a list.+ asList :: v -> IO [a]+ {-# MINIMAL getNth, setNth #-}+ reset = error "no default method: reset"+ asUVector = error "no default method: asUVector"+ swapBetween = error "no default method: swapBetween"+ modifyNth = error "no default method: modifyNth"+ newVec = error "no default method: newVec"+ setAll = error "no default method: setAll"+ asList = error "no default method: asList"+ growBy = error "no default method: growBy"+{-+ -- | (FOR DEBUG) dump the contents.+ dump :: Show a => String -> v -> IO String+ dump msg v = (msg ++) . show <$> asList v+-}++-------------------------------------------------------------------------------- UVector++-- | A thin abstract layer for Mutable unboxed Vector+type UVector a = UV.IOVector a++instance VecFamily (UVector Int) Int where+ {-# SPECIALIZE INLINE getNth :: UVector Int -> Int -> IO Int #-}+ getNth = UV.unsafeRead+ {-# SPECIALIZE INLINE setNth :: UVector Int -> Int -> Int -> IO () #-}+ setNth = UV.unsafeWrite+ {-# SPECIALIZE INLINE modifyNth :: UVector Int -> (Int -> Int) -> Int -> IO () #-}+ modifyNth = UV.unsafeModify+ {-# SPECIALIZE INLINE swapBetween:: UVector Int -> Int -> Int -> IO () #-}+ swapBetween = UV.unsafeSwap+ {-# SPECIALIZE INLINE newVec :: Int -> Int -> IO (UVector Int) #-}+ newVec n 0 = UV.new n+ newVec n x = do+ v <- UV.new n+ UV.set v x+ return v+ {-# SPECIALIZE INLINE setAll :: UVector Int -> Int -> IO () #-}+ setAll = UV.set+ {-# SPECIALIZE INLINE growBy :: UVector Int -> Int -> IO (UVector Int) #-}+ growBy = UV.unsafeGrow+ asList v = mapM (UV.unsafeRead v) [0 .. UV.length v - 1]++instance VecFamily (UVector Double) Double where+ {-# SPECIALIZE INLINE getNth :: UVector Double -> Int -> IO Double #-}+ getNth = UV.unsafeRead+ {-# SPECIALIZE INLINE setNth :: UVector Double -> Int -> Double -> IO () #-}+ setNth = UV.unsafeWrite+ {-# SPECIALIZE INLINE modifyNth :: UVector Double -> (Double -> Double) -> Int -> IO () #-}+ modifyNth = UV.unsafeModify+ {-# SPECIALIZE INLINE swapBetween:: UVector Double -> Int -> Int -> IO () #-}+ swapBetween = UV.unsafeSwap+ {-# SPECIALIZE INLINE newVec :: Int -> Double -> IO (UVector Double) #-}+ newVec n x = do+ v <- UV.new n+ UV.set v x+ return v+ {-# SPECIALIZE INLINE setAll :: UVector Double -> Double -> IO () #-}+ setAll = UV.set+ {-# SPECIALIZE INLINE growBy :: UVector Double -> Int -> IO (UVector Double) #-}+ growBy = UV.unsafeGrow+ asList v = mapM (UV.unsafeRead v) [0 .. UV.length v - 1]++-------------------------------------------------------------------------------- Vec++-- | Another abstraction layer on 'UVector'.+--+-- __Note__: the 0-th element of @Vec Int@ is reserved for internal tasks. If you want to use it, use @UVector Int@.+newtype Vec a = Vec (UVector a)++instance VecFamily (Vec Int) Int where+ {-# SPECIALIZE INLINE getNth :: Vec Int -> Int -> IO Int #-}+ getNth (Vec v) = UV.unsafeRead v+ {-# SPECIALIZE INLINE setNth :: Vec Int -> Int -> Int -> IO () #-}+ setNth (Vec v) = UV.unsafeWrite v+ {-# SPECIALIZE INLINE reset :: Vec Int -> IO () #-}+ reset (Vec v) = setNth v 0 0+ {-# SPECIALIZE INLINE asUVector :: Vec Int -> UVector Int #-}+ asUVector (Vec a) = UV.unsafeTail a+ {-# SPECIALIZE INLINE modifyNth :: Vec Int -> (Int -> Int) -> Int -> IO () #-}+ modifyNth (Vec v) = UV.unsafeModify v+ {-# SPECIALIZE INLINE swapBetween :: Vec Int -> Int -> Int -> IO () #-}+ swapBetween (Vec v) = UV.unsafeSwap v+ {-# SPECIALIZE INLINE newVec :: Int -> Int -> IO (Vec Int) #-}+ newVec n x = Vec <$> newVec (n + 1) x+ {-# SPECIALIZE INLINE setAll :: Vec Int -> Int -> IO () #-}+ setAll (Vec v) = UV.set v+ {-# SPECIALIZE INLINE growBy :: Vec Int -> Int -> IO (Vec Int) #-}+ growBy (Vec v) n = Vec <$> UV.unsafeGrow v n+ asList (Vec v) = mapM (getNth v) [1 .. UV.length v - 1]++instance VecFamily (Vec Double) Double where+ {-# SPECIALIZE INLINE getNth :: Vec Double -> Int -> IO Double #-}+ getNth (Vec v) = UV.unsafeRead v+ {-# SPECIALIZE INLINE setNth :: Vec Double -> Int -> Double -> IO () #-}+ setNth (Vec v) = UV.unsafeWrite v+ {-# SPECIALIZE INLINE modifyNth :: Vec Double -> (Double -> Double) -> Int -> IO () #-}+ modifyNth (Vec v) = UV.unsafeModify v+ {-# SPECIALIZE INLINE swapBetween :: Vec Double -> Int -> Int -> IO () #-}+ swapBetween (Vec v) = UV.unsafeSwap v+ {-# SPECIALIZE INLINE newVec :: Int -> Double -> IO (Vec Double) #-}+ newVec n x = Vec <$> newVec (n + 1) x+ {-# SPECIALIZE INLINE setAll :: Vec Double -> Double -> IO () #-}+ setAll (Vec v) = UV.set v+ {-# SPECIALIZE INLINE growBy :: Vec Double -> Int -> IO (Vec Double) #-}+ growBy (Vec v) n = Vec <$> UV.unsafeGrow v n++-------------------------------------------------------------------------------- SingleStorage++-- | Interface for single mutable data+class SingleStorage s t | s -> t where+ -- | allocates and returns an new data.+ new' :: t -> IO s+ -- | gets the value.+ get' :: s -> IO t+ -- | sets the value.+ set' :: s -> t -> IO ()+ -- | calls an update function on it.+ modify' :: s -> (t -> t) -> IO ()+ {-# MINIMAL get', set' #-}+ new' = undefined+ modify' = undefined++-- | Mutable Int+-- __Note:__ Int' is the same with 'Stack'+type Int' = UV.IOVector Int++instance SingleStorage Int' Int where+ {-# SPECIALIZE INLINE new' :: Int -> IO Int' #-}+ new' k = do+ s <- UV.new 1+ UV.unsafeWrite s 0 k+ return s+ {-# SPECIALIZE INLINE get' :: Int' -> IO Int #-}+ get' val = UV.unsafeRead val 0+ {-# SPECIALIZE INLINE set' :: Int' -> Int -> IO () #-}+ set' val !x = UV.unsafeWrite val 0 x+ {-# SPECIALIZE INLINE modify' :: Int' -> (Int -> Int) -> IO () #-}+ modify' val f = UV.unsafeModify val f 0++-- | Mutable Bool+type Bool' = UV.IOVector Bool++instance SingleStorage Bool' Bool where+ {-# SPECIALIZE INLINE new' :: Bool -> IO Bool' #-}+ new' k = do+ s <- UV.new 1+ UV.unsafeWrite s 0 k+ return s+ {-# SPECIALIZE INLINE get' :: Bool' -> IO Bool #-}+ get' val = UV.unsafeRead val 0+ {-# SPECIALIZE INLINE set' :: Bool' -> Bool -> IO () #-}+ set' val !x = UV.unsafeWrite val 0 x+ {-# SPECIALIZE INLINE modify' :: Bool' -> (Bool -> Bool) -> IO () #-}+ modify' val f = UV.unsafeModify val f 0++-- | Mutable Double+type Double' = UV.IOVector Double++instance SingleStorage Double' Double where+ {-# SPECIALIZE INLINE new' :: Double -> IO Double' #-}+ new' k = do+ s <- UV.new 1+ UV.unsafeWrite s 0 k+ return s+ {-# SPECIALIZE INLINE get' :: Double' -> IO Double #-}+ get' val = UV.unsafeRead val 0+ {-# SPECIALIZE INLINE set' :: Double' -> Double -> IO () #-}+ set' val !x = UV.unsafeWrite val 0 x+ {-# SPECIALIZE INLINE modify' :: Double' -> (Double -> Double) -> IO () #-}+ modify' val f = UV.unsafeModify val f 0++-------------------------------------------------------------------------------- Stack++-- | Interface on stacks+class SingleStorage s Int => StackFamily s t | s -> t where+ -- | returns a new stack.+ newStack :: Int -> IO s+ -- | pushs an value to the tail of the stack.+ pushTo :: s -> t-> IO ()+ -- | pops the last element.+ popFrom :: s -> IO ()+ -- | peeks the last element.+ lastOf :: s -> IO t+ -- | shrinks the stack.+ shrinkBy :: s -> Int -> IO ()+ newStack = undefined+ pushTo = undefined+ popFrom = undefined+ lastOf = undefined+ shrinkBy = undefined++-- | Alias of @Vec Int@. The 0-th element holds the number of elements.+type Stack = Vec Int++instance SingleStorage Stack Int where+ {-# SPECIALIZE INLINE get' :: Stack -> IO Int #-}+ get' (Vec v) = UV.unsafeRead v 0+ {-# SPECIALIZE INLINE set' :: Stack -> Int -> IO () #-}+ set' (Vec v) !x = UV.unsafeWrite v 0 x+ {-# SPECIALIZE INLINE modify' :: Stack -> (Int -> Int) -> IO () #-}+ modify' (Vec v) f = UV.unsafeModify v f 0++instance StackFamily Stack Int where+ {-# SPECIALIZE INLINE newStack :: Int -> IO Stack #-}+ newStack n = newVec n 0+ {-# SPECIALIZE INLINE pushTo :: Stack -> Int -> IO () #-}+ pushTo (Vec v) x = do+ i <- (+ 1) <$> UV.unsafeRead v 0+ UV.unsafeWrite v i x+ UV.unsafeWrite v 0 i+ {-# SPECIALIZE INLINE popFrom :: Stack -> IO () #-}+ popFrom (Vec v) = UV.unsafeModify v (subtract 1) 0+ {-# SPECIALIZE INLINE lastOf :: Stack -> IO Int #-}+ lastOf (Vec v) = UV.unsafeRead v =<< UV.unsafeRead v 0+ {-# SPECIALIZE INLINE shrinkBy :: Stack -> Int -> IO () #-}+ shrinkBy (Vec v) k = UV.unsafeModify v (subtract k) 0++-- | returns a new 'Stack' from @[Int]@.+{-# INLINABLE newStackFromList #-}+newStackFromList :: [Int] -> IO Stack+newStackFromList !l = Vec <$> U.unsafeThaw (U.fromList (length l : l))
+ app/sample.hs view
@@ -0,0 +1,26 @@+module Main where+import SAT.Mios (CNFDescription (..), solveSAT)++-- | a sample CNF+clauses :: [[Int]]+clauses =+ [+ [ 1, 2]+ , [ 1, 3]+ , [-1, -2]+ , [1, -2, 3]+ , [-3]+ ]++-- | a property holder+desc :: CNFDescription+desc = CNFDescription -- :: Int -> Int -> Maybe String -> CNFDescription+ (maximum . map abs . concat $ clauses) -- number of variables+ (length clauses) -- number of clauses+ Nothing -- Just pathname or Nothing++main :: IO ()+main = do+ -- solveSAT :: Traversable m => CNFDescription -> m [Int] -> IO [Int]+ asg <- solveSAT desc clauses+ putStrLn $ if null asg then "unsatisfiable" else show asg
mios.cabal view
@@ -2,7 +2,7 @@ -- see http://haskell.org/cabal/users-guide/ name: mios-version: 1.3.0+version: 1.4.0 synopsis: A Minisat-based SAT solver in Haskell description: @@ -20,7 +20,12 @@ category: Artificial Intelligence, Constraints build-type: Simple cabal-version: >=1.16+extra-source-files: app/sample.hs +source-repository head+ type: git+ location: https://github.com/shnarazk/mios+ Flag llvm Description: Compile with llvm Default: False@@ -35,62 +40,59 @@ else buildable: False default-language: Haskell2010- default-extensions: Strict+ default-extensions: Strict+ other-extensions: BangPatterns+ FlexibleContexts+ FlexibleInstances+ FunctionalDependencies+ MagicHash+ MultiParamTypeClasses+ RecordWildCards+ ScopedTypeVariables+ TypeFamilies+ Trustworthy+ TupleSections+ Safe+ UndecidableInstances+ ViewPatterns exposed-modules:- SAT.Mios SAT.Mios.Clause SAT.Mios.ClauseManager- SAT.Mios.Data.VecBool- SAT.Mios.Data.VecDouble- SAT.Mios.Data.Vec- SAT.Mios.Data.Singleton- SAT.Mios.Data.Stack- SAT.Mios.Internal+ SAT.Mios.Vec SAT.Mios.Main SAT.Mios.OptionParser--- SAT.Mios.Ranking SAT.Mios.Solver SAT.Mios.Types SAT.Mios.Validator- SAT.Mios.Util.CNFIO- SAT.Mios.Util.CNFIO.MinisatReader- SAT.Mios.Util.CNFIO.Reader- SAT.Mios.Util.CNFIO.Writer+ SAT.Mios.Util.DIMACS.MinisatReader+ SAT.Mios.Util.DIMACS.Reader+ SAT.Mios.Util.DIMACS.Writer+ SAT.Mios.Util.DIMACS SAT.Mios.Util.BoolExp- build-depends: base ==4.9.*, vector >=0.11, containers >=0.5, ghc-prim >=0.5, bytestring >=0.10, primitive >=0.6+ SAT.Mios+ build-depends: base ==4.9.*, vector >=0.11, ghc-prim >=0.5, bytestring >=0.10 if flag(llvm) ghc-options: -O2 -ignore-asserts -funbox-strict-fields -fllvm -optlo-O3 else- ghc-options: -O2 -ignore-asserts -funbox-strict-fields -msse4.2+ ghc-options: -O2 -ignore-asserts -funbox-strict-fields executable mios main-is: app/mios.hs buildable: True default-language: Haskell2010 default-extensions: Strict- build-depends: base ==4.9.*, vector >=0.11, containers >=0.5, ghc-prim >=0.5, bytestring >=0.10, primitive >=0.6+ build-depends: base ==4.9.*, vector >=0.11, ghc-prim >=0.5, bytestring >=0.10 if flag(llvm) ghc-options: -O2 -ignore-asserts -funbox-strict-fields -fllvm -optlo-O3 else- ghc-options: -O2 -ignore-asserts -funbox-strict-fields -msse4.2+ ghc-options: -O2 -ignore-asserts -funbox-strict-fields other-modules:- SAT.Mios SAT.Mios.Clause SAT.Mios.ClauseManager- SAT.Mios.Data.VecBool- SAT.Mios.Data.VecDouble- SAT.Mios.Data.Vec- SAT.Mios.Data.Singleton- SAT.Mios.Data.Stack- SAT.Mios.Internal+ SAT.Mios.Vec SAT.Mios.Main SAT.Mios.OptionParser--- SAT.Mios.Ranking SAT.Mios.Solver SAT.Mios.Types SAT.Mios.Validator- SAT.Mios.Util.CNFIO- SAT.Mios.Util.CNFIO.MinisatReader- SAT.Mios.Util.CNFIO.Reader- SAT.Mios.Util.CNFIO.Writer- SAT.Mios.Util.BoolExp+ SAT.Mios