toysolver 0.9.0 → 0.10.0
raw patch · 103 files changed
+4046/−4695 lines, 103 filesdep +integer-logarithmsdep +language-smtlibdep −ansi-wl-pprintdep ~MIPdep ~aesondep ~arraynew-component:exe:toysolver-checkPVP ok
version bump matches the API change (PVP)
Dependencies added: integer-logarithms, language-smtlib
Dependencies removed: ansi-wl-pprint
Dependency ranges changed: MIP, aeson, array, base, bytestring, hashable, intern, mtl, optparse-applicative, parsec, pseudo-boolean, temporary, text, transformers, transformers-compat
API changes (from Hackage documentation)
+ ToySolver.Converter.MIP: NormalizeMIPObjectiveInfo :: Maybe Var -> NormalizeMIPObjectiveInfo r
+ ToySolver.Converter.MIP: instance Data.Aeson.Types.FromJSON.FromJSON (ToySolver.Converter.MIP.NormalizeMIPObjectiveInfo r)
+ ToySolver.Converter.MIP: instance Data.Aeson.Types.ToJSON.ToJSON (ToySolver.Converter.MIP.NormalizeMIPObjectiveInfo r)
+ ToySolver.Converter.MIP: instance GHC.Classes.Eq (ToySolver.Converter.MIP.NormalizeMIPObjectiveInfo r)
+ ToySolver.Converter.MIP: instance GHC.Num.Num r => ToySolver.Converter.Base.ForwardTransformer (ToySolver.Converter.MIP.NormalizeMIPObjectiveInfo r)
+ ToySolver.Converter.MIP: instance GHC.Show.Show (ToySolver.Converter.MIP.NormalizeMIPObjectiveInfo r)
+ ToySolver.Converter.MIP: instance ToySolver.Converter.Base.BackwardTransformer (ToySolver.Converter.MIP.NormalizeMIPObjectiveInfo r)
+ ToySolver.Converter.MIP: instance ToySolver.Converter.Base.ObjValueBackwardTransformer (ToySolver.Converter.MIP.NormalizeMIPObjectiveInfo r)
+ ToySolver.Converter.MIP: instance ToySolver.Converter.Base.ObjValueForwardTransformer (ToySolver.Converter.MIP.NormalizeMIPObjectiveInfo r)
+ ToySolver.Converter.MIP: instance ToySolver.Converter.Base.ObjValueTransformer (ToySolver.Converter.MIP.NormalizeMIPObjectiveInfo r)
+ ToySolver.Converter.MIP: instance ToySolver.Converter.Base.Transformer (ToySolver.Converter.MIP.NormalizeMIPObjectiveInfo r)
+ ToySolver.Converter.MIP: newtype NormalizeMIPObjectiveInfo r
+ ToySolver.Converter.MIP: normalizeMIPObjective :: (Num c, Eq c) => Problem c -> (Problem c, NormalizeMIPObjectiveInfo r)
+ ToySolver.Data.AlgebraicNumber.Sturm: cauchysBounds :: UPolynomial Rational -> Rational
+ ToySolver.FileFormat.Base: getBaseExtension :: FilePath -> String
+ ToySolver.Internal.SolutionChecker: checkMIPResult :: Tol Scientific -> Problem Scientific -> Solution Scientific -> (Bool, [String])
+ ToySolver.Internal.SolutionChecker: checkMaxSATResult :: WCNF -> (ByteString, Maybe Integer, Maybe Model) -> (Bool, [String])
+ ToySolver.Internal.SolutionChecker: checkPBResult :: Formula -> (ByteString, Maybe Integer, Maybe Model) -> (Bool, [String])
+ ToySolver.Internal.SolutionChecker: checkSATResult :: CNF -> (ByteString, Maybe Model) -> (Bool, [String])
+ ToySolver.Internal.SolutionChecker: checkWBOResult :: SoftFormula -> (ByteString, Maybe Integer, Maybe Model) -> (Bool, [String])
+ ToySolver.SAT.Encoder.Integer: newVarPBLinSum :: AddPBNL m enc => enc -> Integer -> m PBLinSum
+ ToySolver.SAT.LogParser: parseMaxSATLog :: ByteString -> (ByteString, Maybe Integer, Maybe Model)
+ ToySolver.SAT.LogParser: parsePBLog :: ByteString -> (ByteString, Maybe Integer, Maybe Model)
+ ToySolver.SAT.LogParser: parseSATLog :: ByteString -> (ByteString, Maybe Model)
+ ToySolver.SAT.Printer: maxsatModel :: Model -> Int -> Newline -> Builder
+ ToySolver.SAT.Printer: maxsatModelCompact :: Model -> Int -> Newline -> Builder
+ ToySolver.SAT.Printer: musSol :: [Int] -> Newline -> Builder
+ ToySolver.SAT.Printer: pbModel :: Model -> Int -> Newline -> Builder
+ ToySolver.SAT.Printer: satModel :: Model -> Int -> Newline -> Builder
+ ToySolver.SMT.SMTLIB2Solver: assert :: Solver -> Term () -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: checkSat :: Solver -> IO CheckSatResponse
+ ToySolver.SMT.SMTLIB2Solver: checkSatAssuming :: Solver -> [Term ()] -> IO CheckSatResponse
+ ToySolver.SMT.SMTLIB2Solver: data Solver
+ ToySolver.SMT.SMTLIB2Solver: declareConst :: Solver -> String -> Sort () -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: declareFun :: Solver -> String -> [Sort ()] -> Sort () -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: declareSort :: Solver -> String -> Int -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: defineConst :: Solver -> String -> Sort () -> Term () -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: defineFun :: Solver -> String -> [SortedVar ()] -> Sort () -> Term () -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: defineFunRec :: Solver -> String -> [SortedVar ()] -> Sort () -> Term () -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: defineFunsRec :: Solver -> [FunctionDec ()] -> [Term ()] -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: defineSort :: Solver -> String -> [String] -> Sort () -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: echo :: Solver -> Text -> IO Text
+ ToySolver.SMT.SMTLIB2Solver: execCommand :: Solver -> Command () -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: execCommandString :: Solver -> String -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: exit :: Solver -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: getAssertions :: Solver -> IO [Term ()]
+ ToySolver.SMT.SMTLIB2Solver: getAssignment :: Solver -> IO [(Symbol, Bool)]
+ ToySolver.SMT.SMTLIB2Solver: getInfo :: Solver -> InfoFlag () -> IO [InfoResponse ()]
+ ToySolver.SMT.SMTLIB2Solver: getModel :: Solver -> IO [ModelResponse ()]
+ ToySolver.SMT.SMTLIB2Solver: getOption :: Solver -> String -> IO (AttributeValue ())
+ ToySolver.SMT.SMTLIB2Solver: getProof :: Solver -> IO (SExpr ())
+ ToySolver.SMT.SMTLIB2Solver: getUnsatAssumptions :: Solver -> IO [Term ()]
+ ToySolver.SMT.SMTLIB2Solver: getUnsatCore :: Solver -> IO [Symbol]
+ ToySolver.SMT.SMTLIB2Solver: getValue :: Solver -> [Term ()] -> IO [ValuationPair ()]
+ ToySolver.SMT.SMTLIB2Solver: instance GHC.Classes.Eq ToySolver.SMT.SMTLIB2Solver.Mode
+ ToySolver.SMT.SMTLIB2Solver: instance GHC.Classes.Ord ToySolver.SMT.SMTLIB2Solver.Mode
+ ToySolver.SMT.SMTLIB2Solver: instance GHC.Show.Show ToySolver.SMT.SMTLIB2Solver.Mode
+ ToySolver.SMT.SMTLIB2Solver: newSolver :: IO Solver
+ ToySolver.SMT.SMTLIB2Solver: pop :: Solver -> Int -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: printResponse :: Solver -> CommandResponse () -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: push :: Solver -> Int -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: reset :: Solver -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: resetAssertions :: Solver -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: runCommand :: Solver -> Command () -> IO (CommandResponse ())
+ ToySolver.SMT.SMTLIB2Solver: runCommandString :: Solver -> String -> IO (CommandResponse ())
+ ToySolver.SMT.SMTLIB2Solver: setInfo :: Solver -> Attribute () -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: setLogic :: Solver -> String -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: setOption :: Solver -> Option () -> IO ()
+ ToySolver.SMT.SMTLIB2Solver: showSL :: Pretty a => a -> String
- ToySolver.Arith.BoundsInference: inferBounds :: forall r. RealFrac r => BoundsEnv r -> [Atom r] -> VarSet -> Int -> BoundsEnv r
+ ToySolver.Arith.BoundsInference: inferBounds :: RealFrac r => BoundsEnv r -> [Atom r] -> VarSet -> Int -> BoundsEnv r
- ToySolver.Arith.BoundsInference: type BoundsEnv r = VarMap (Interval r)
+ ToySolver.Arith.BoundsInference: type BoundsEnv r = VarMap Interval r
- ToySolver.Arith.CAD: project' :: forall v. (Ord v, Show v, PrettyVar v) => [(UPolynomial (Polynomial Rational v), [Sign])] -> [([(Polynomial Rational v, [Sign])], [Cell (Polynomial Rational v)])]
+ ToySolver.Arith.CAD: project' :: (Ord v, Show v, PrettyVar v) => [(UPolynomial (Polynomial Rational v), [Sign])] -> [([(Polynomial Rational v, [Sign])], [Cell (Polynomial Rational v)])]
- ToySolver.Arith.CAD: solve :: forall v. (Ord v, Show v, PrettyVar v) => Set v -> [OrdRel (Polynomial Rational v)] -> Maybe (Model v)
+ ToySolver.Arith.CAD: solve :: (Ord v, Show v, PrettyVar v) => Set v -> [OrdRel (Polynomial Rational v)] -> Maybe (Model v)
- ToySolver.Arith.CAD: solve' :: forall v. (Ord v, Show v, PrettyVar v) => Set v -> [(Polynomial Rational v, [Sign])] -> Maybe (Model v)
+ ToySolver.Arith.CAD: solve' :: (Ord v, Show v, PrettyVar v) => Set v -> [(Polynomial Rational v, [Sign])] -> Maybe (Model v)
- ToySolver.Arith.Simplex: check :: forall m v. (PrimMonad m, SolverValue v) => GenericSolverM m v -> m Bool
+ ToySolver.Arith.Simplex: check :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> m Bool
- ToySolver.Arith.Simplex: data GenericSolverM m v
+ ToySolver.Arith.Simplex: data GenericSolverM (m :: Type -> Type) v
- ToySolver.Arith.Simplex: data () => OptDir
+ ToySolver.Arith.Simplex: data OptDir
- ToySolver.Arith.Simplex: dualSimplex :: forall m. PrimMonad m => GenericSolverM m Rational -> Options -> m OptResult
+ ToySolver.Arith.Simplex: dualSimplex :: PrimMonad m => GenericSolverM m Rational -> Options -> m OptResult
- ToySolver.Arith.Simplex: dump :: PrimMonad m => SolverValue v => GenericSolverM m v -> m ()
+ ToySolver.Arith.Simplex: dump :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> m ()
- ToySolver.Arith.Simplex: infix 4 .>=.
+ ToySolver.Arith.Simplex: infix 4 .>.
- ToySolver.Arith.Simplex: optimize :: forall m. PrimMonad m => GenericSolverM m Rational -> Options -> m OptResult
+ ToySolver.Arith.Simplex: optimize :: PrimMonad m => GenericSolverM m Rational -> Options -> m OptResult
- ToySolver.Arith.Simplex: type Atom r = OrdRel (Expr r)
+ ToySolver.Arith.Simplex: type Atom r = OrdRel Expr r
- ToySolver.Arith.Simplex.Simple: data () => OptDir
+ ToySolver.Arith.Simplex.Simple: data OptDir
- ToySolver.Arith.Simplex.Textbook: type Tableau r = VarMap (Row r)
+ ToySolver.Arith.Simplex.Textbook: type Tableau r = VarMap Row r
- ToySolver.Arith.Simplex.Textbook.LPSolver: collectNonnegVars :: forall r. RealFrac r => [Atom r] -> VarSet -> (VarSet, [Atom r])
+ ToySolver.Arith.Simplex.Textbook.LPSolver: collectNonnegVars :: RealFrac r => [Atom r] -> VarSet -> (VarSet, [Atom r])
- ToySolver.Arith.Simplex.Textbook.LPSolver: type LP r = State (Solver r)
+ ToySolver.Arith.Simplex.Textbook.LPSolver: type LP r = State Solver r
- ToySolver.Arith.Simplex.Textbook.LPSolver: type Solver r = (Var, Tableau r, VarSet, VarMap (Expr r))
+ ToySolver.Arith.Simplex.Textbook.LPSolver: type Solver r = (Var, Tableau r, VarSet, VarMap Expr r)
- ToySolver.Arith.VirtualSubstitution: type QFFormula = BoolExpr (Atom Rational)
+ ToySolver.Arith.VirtualSubstitution: type QFFormula = BoolExpr Atom Rational
- ToySolver.BitVector.Base: class (IsBV a, IsEqRel a (ComparisonResult a), Complement (ComparisonResult a)) => BVComparison a where {
+ ToySolver.BitVector.Base: class (IsBV a, IsEqRel a ComparisonResult a, Complement ComparisonResult a) => BVComparison a where {
- ToySolver.BitVector.Base: type Model = (Vector BV, Map BV BV, Map BV BV)
+ ToySolver.BitVector.Base: type Model = Vector BV
- ToySolver.Combinatorial.BipartiteMatching: maximumWeightMatching :: forall w. Real w => IntSet -> IntSet -> [(Int, Int, w)] -> (w, IntMap Int)
+ ToySolver.Combinatorial.BipartiteMatching: maximumWeightMatching :: Real w => IntSet -> IntSet -> [(Int, Int, w)] -> (w, IntMap Int)
- ToySolver.Combinatorial.BipartiteMatching: maximumWeightMatchingComplete :: forall w. Real w => IntSet -> IntSet -> (Int -> Int -> w) -> (w, IntMap Int)
+ ToySolver.Combinatorial.BipartiteMatching: maximumWeightMatchingComplete :: Real w => IntSet -> IntSet -> (Int -> Int -> w) -> (w, IntMap Int)
- ToySolver.Combinatorial.BipartiteMatching: maximumWeightPerfectMatching :: forall w. Real w => IntSet -> IntSet -> [(Int, Int, w)] -> Maybe (w, IntMap Int, (IntMap w, IntMap w))
+ ToySolver.Combinatorial.BipartiteMatching: maximumWeightPerfectMatching :: Real w => IntSet -> IntSet -> [(Int, Int, w)] -> Maybe (w, IntMap Int, (IntMap w, IntMap w))
- ToySolver.Combinatorial.BipartiteMatching: maximumWeightPerfectMatchingComplete :: forall w. Real w => IntSet -> IntSet -> (Int -> Int -> w) -> (w, IntMap Int, (IntMap w, IntMap w))
+ ToySolver.Combinatorial.BipartiteMatching: maximumWeightPerfectMatchingComplete :: Real w => IntSet -> IntSet -> (Int -> Int -> w) -> (w, IntMap Int, (IntMap w, IntMap w))
- ToySolver.Combinatorial.BipartiteMatching: minimumWeightEdgeCover :: forall w. Real w => IntSet -> IntSet -> [(Int, Int, w)] -> Maybe (Set (Int, Int))
+ ToySolver.Combinatorial.BipartiteMatching: minimumWeightEdgeCover :: Real w => IntSet -> IntSet -> [(Int, Int, w)] -> Maybe (Set (Int, Int))
- ToySolver.Combinatorial.BipartiteMatching: minimumWeightEdgeCoverComplete :: forall w. Real w => IntSet -> IntSet -> (Int -> Int -> w) -> Maybe (Set (Int, Int))
+ ToySolver.Combinatorial.BipartiteMatching: minimumWeightEdgeCoverComplete :: Real w => IntSet -> IntSet -> (Int -> Int -> w) -> Maybe (Set (Int, Int))
- ToySolver.Combinatorial.BipartiteMatching: minimumWeightPerfectMatching :: forall w. Real w => IntSet -> IntSet -> [(Int, Int, w)] -> Maybe (w, IntMap Int, (IntMap w, IntMap w))
+ ToySolver.Combinatorial.BipartiteMatching: minimumWeightPerfectMatching :: Real w => IntSet -> IntSet -> [(Int, Int, w)] -> Maybe (w, IntMap Int, (IntMap w, IntMap w))
- ToySolver.Combinatorial.BipartiteMatching: minimumWeightPerfectMatchingComplete :: forall w. Real w => IntSet -> IntSet -> (Int -> Int -> w) -> (w, IntMap Int, (IntMap w, IntMap w))
+ ToySolver.Combinatorial.BipartiteMatching: minimumWeightPerfectMatchingComplete :: Real w => IntSet -> IntSet -> (Int -> Int -> w) -> (w, IntMap Int, (IntMap w, IntMap w))
- ToySolver.Combinatorial.HittingSet.DAA: run :: forall prob m. IsProblem prob m => prob -> Options m -> m (Set IntSet, Set IntSet)
+ ToySolver.Combinatorial.HittingSet.DAA: run :: IsProblem prob m => prob -> Options m -> m (Set IntSet, Set IntSet)
- ToySolver.Combinatorial.HittingSet.InterestingSets: Options :: (Set IntSet -> m (Set IntSet)) -> Set IntSet -> Set IntSet -> (IntSet -> m ()) -> (IntSet -> m ()) -> Options m
+ ToySolver.Combinatorial.HittingSet.InterestingSets: Options :: (Set IntSet -> m (Set IntSet)) -> Set IntSet -> Set IntSet -> (IntSet -> m ()) -> (IntSet -> m ()) -> Options (m :: Type -> Type)
- ToySolver.Combinatorial.HittingSet.InterestingSets: [optMaximalInterestingSets] :: Options m -> Set IntSet
+ ToySolver.Combinatorial.HittingSet.InterestingSets: [optMaximalInterestingSets] :: Options (m :: Type -> Type) -> Set IntSet
- ToySolver.Combinatorial.HittingSet.InterestingSets: [optMinimalHittingSets] :: Options m -> Set IntSet -> m (Set IntSet)
+ ToySolver.Combinatorial.HittingSet.InterestingSets: [optMinimalHittingSets] :: Options (m :: Type -> Type) -> Set IntSet -> m (Set IntSet)
- ToySolver.Combinatorial.HittingSet.InterestingSets: [optMinimalUninterestingSets] :: Options m -> Set IntSet
+ ToySolver.Combinatorial.HittingSet.InterestingSets: [optMinimalUninterestingSets] :: Options (m :: Type -> Type) -> Set IntSet
- ToySolver.Combinatorial.HittingSet.InterestingSets: [optOnMaximalInterestingSetFound] :: Options m -> IntSet -> m ()
+ ToySolver.Combinatorial.HittingSet.InterestingSets: [optOnMaximalInterestingSetFound] :: Options (m :: Type -> Type) -> IntSet -> m ()
- ToySolver.Combinatorial.HittingSet.InterestingSets: [optOnMinimalUninterestingSetFound] :: Options m -> IntSet -> m ()
+ ToySolver.Combinatorial.HittingSet.InterestingSets: [optOnMinimalUninterestingSetFound] :: Options (m :: Type -> Type) -> IntSet -> m ()
- ToySolver.Combinatorial.HittingSet.InterestingSets: class Monad m => IsProblem prob m | prob -> m
+ ToySolver.Combinatorial.HittingSet.InterestingSets: class Monad m => IsProblem prob (m :: Type -> Type) | prob -> m
- ToySolver.Combinatorial.HittingSet.InterestingSets: data Options m
+ ToySolver.Combinatorial.HittingSet.InterestingSets: data Options (m :: Type -> Type)
- ToySolver.Combinatorial.HittingSet.MARCO: run :: forall prob. IsProblem prob IO => prob -> Options IO -> IO (Set IntSet, Set IntSet)
+ ToySolver.Combinatorial.HittingSet.MARCO: run :: IsProblem prob IO => prob -> Options IO -> IO (Set IntSet, Set IntSet)
- ToySolver.Combinatorial.Knapsack.DPSparse: solve :: forall value weight. (Real value, Real weight) => [(value, weight)] -> weight -> (value, weight, [Bool])
+ ToySolver.Combinatorial.Knapsack.DPSparse: solve :: (Real value, Real weight) => [(value, weight)] -> weight -> (value, weight, [Bool])
- ToySolver.Combinatorial.Knapsack.DPSparse: solveGeneric :: forall value weight. (Real value, Real weight) => [(value, weight)] -> weight -> (value, weight, [Bool])
+ ToySolver.Combinatorial.Knapsack.DPSparse: solveGeneric :: (Real value, Real weight) => [(value, weight)] -> weight -> (value, weight, [Bool])
- ToySolver.Combinatorial.Knapsack.DPSparse: solveInt :: forall value. Real value => [(value, Int)] -> Int -> (value, Int, [Bool])
+ ToySolver.Combinatorial.Knapsack.DPSparse: solveInt :: Real value => [(value, Int)] -> Int -> (value, Int, [Bool])
- ToySolver.Combinatorial.Knapsack.DPSparse: solveInteger :: forall value. Real value => [(value, Integer)] -> Integer -> (value, Integer, [Bool])
+ ToySolver.Combinatorial.Knapsack.DPSparse: solveInteger :: Real value => [(value, Integer)] -> Integer -> (value, Integer, [Bool])
- ToySolver.Converter.MIP: IP2PBInfo :: Map Var Expr -> Map Var Lit -> !Integer -> IP2PBInfo
+ ToySolver.Converter.MIP: IP2PBInfo :: Map Var Expr -> Map Var Lit -> !Rational -> IP2PBInfo
- ToySolver.Converter.PB: PBInequalitiesToEqualitiesInfo :: !Int -> !Int -> [(Sum, Integer, [Var])] -> PBInequalitiesToEqualitiesInfo
+ ToySolver.Converter.PB: PBInequalitiesToEqualitiesInfo :: !Int -> !Int -> [(Sum, Integer, PBLinSum)] -> PBInequalitiesToEqualitiesInfo
- ToySolver.Converter.PB: normalizePB :: Formula -> Formula
+ ToySolver.Converter.PB: normalizePB :: Formula -> (Formula, PBTseitinInfo)
- ToySolver.Converter.QUBO: pbAsQUBO :: forall a. Real a => Formula -> Maybe (Problem a, PBAsQUBOInfo a)
+ ToySolver.Converter.QUBO: pbAsQUBO :: Real a => Formula -> Maybe (Problem a, PBAsQUBOInfo a)
- ToySolver.Converter.QUBO: type PB2QUBOInfo a = ComposedTransformer PB2QUBOInfo' (PBAsQUBOInfo a)
+ ToySolver.Converter.QUBO: type PB2QUBOInfo a = ComposedTransformer PB2QUBOInfo' PBAsQUBOInfo a
- ToySolver.Data.AlgebraicNumber.Root: findPoly :: forall k. (Fractional k, Ord k) => Polynomial k Var -> [Polynomial k Var] -> UPolynomial k
+ ToySolver.Data.AlgebraicNumber.Root: findPoly :: (Fractional k, Ord k) => Polynomial k Var -> [Polynomial k Var] -> UPolynomial k
- ToySolver.Data.AlgebraicNumber.Root: lift2 :: forall k. (Fractional k, Ord k) => (forall a. Num a => a -> a -> a) -> UPolynomial k -> UPolynomial k -> UPolynomial k
+ ToySolver.Data.AlgebraicNumber.Root: lift2 :: (Fractional k, Ord k) => (forall a. Num a => a -> a -> a) -> UPolynomial k -> UPolynomial k -> UPolynomial k
- ToySolver.Data.AlgebraicNumber.Root: rootSimpPoly :: forall k l. (Fractional k, Ord k) => (l -> UPolynomial k) -> UPolynomial l -> UPolynomial k
+ ToySolver.Data.AlgebraicNumber.Root: rootSimpPoly :: (Fractional k, Ord k) => (l -> UPolynomial k) -> UPolynomial l -> UPolynomial k
- ToySolver.Data.FOL.Arith: type Atom c = OrdRel (Expr c)
+ ToySolver.Data.FOL.Arith: type Atom c = OrdRel Expr c
- ToySolver.Data.LA: type Atom r = OrdRel (Expr r)
+ ToySolver.Data.LA: type Atom r = OrdRel Expr r
- ToySolver.Data.LA: type BoundsEnv r = VarMap (Interval r)
+ ToySolver.Data.LA: type BoundsEnv r = VarMap Interval r
- ToySolver.Data.Polynomial: divModMP :: forall k v. (Eq k, Fractional k, Ord v) => MonomialOrder v -> Polynomial k v -> [Polynomial k v] -> ([Polynomial k v], Polynomial k v)
+ ToySolver.Data.Polynomial: divModMP :: (Eq k, Fractional k, Ord v) => MonomialOrder v -> Polynomial k v -> [Polynomial k v] -> ([Polynomial k v], Polynomial k v)
- ToySolver.Data.Polynomial.Factorization.FiniteField: basisOfBerlekampSubalgebra :: forall k. (Ord k, FiniteField k) => UPolynomial k -> [UPolynomial k]
+ ToySolver.Data.Polynomial.Factorization.FiniteField: basisOfBerlekampSubalgebra :: (Ord k, FiniteField k) => UPolynomial k -> [UPolynomial k]
- ToySolver.Data.Polynomial.Factorization.FiniteField: berlekamp :: forall k. (Eq k, Ord k, FiniteField k) => UPolynomial k -> [UPolynomial k]
+ ToySolver.Data.Polynomial.Factorization.FiniteField: berlekamp :: (Eq k, Ord k, FiniteField k) => UPolynomial k -> [UPolynomial k]
- ToySolver.Data.Polynomial.Factorization.FiniteField: factor :: forall k. (Ord k, FiniteField k) => UPolynomial k -> [(UPolynomial k, Integer)]
+ ToySolver.Data.Polynomial.Factorization.FiniteField: factor :: (Ord k, FiniteField k) => UPolynomial k -> [(UPolynomial k, Integer)]
- ToySolver.Data.Polynomial.Factorization.FiniteField: sqfree :: forall k. (Eq k, FiniteField k) => UPolynomial k -> [(UPolynomial k, Integer)]
+ ToySolver.Data.Polynomial.Factorization.FiniteField: sqfree :: (Eq k, FiniteField k) => UPolynomial k -> [(UPolynomial k, Integer)]
- ToySolver.Data.Polynomial.Factorization.Hensel: hensel :: forall p. KnownNat p => UPolynomial Integer -> [UPolynomial (PrimeField p)] -> Integer -> [UPolynomial Integer]
+ ToySolver.Data.Polynomial.Factorization.Hensel: hensel :: forall (p :: Nat). KnownNat p => UPolynomial Integer -> [UPolynomial (PrimeField p)] -> Integer -> [UPolynomial Integer]
- ToySolver.Data.Polynomial.Factorization.Hensel.Internal: cabook_proposition_5_10 :: forall k. (Num k, Fractional k, Eq k) => [UPolynomial k] -> [UPolynomial k]
+ ToySolver.Data.Polynomial.Factorization.Hensel.Internal: cabook_proposition_5_10 :: (Num k, Fractional k, Eq k) => [UPolynomial k] -> [UPolynomial k]
- ToySolver.Data.Polynomial.Factorization.Hensel.Internal: cabook_proposition_5_11 :: forall k. (Fractional k, Ord k) => [UPolynomial k] -> UPolynomial k -> [UPolynomial k]
+ ToySolver.Data.Polynomial.Factorization.Hensel.Internal: cabook_proposition_5_11 :: (Fractional k, Ord k) => [UPolynomial k] -> UPolynomial k -> [UPolynomial k]
- ToySolver.Data.Polynomial.Factorization.Hensel.Internal: hensel :: forall p. KnownNat p => UPolynomial Integer -> [UPolynomial (PrimeField p)] -> Integer -> [UPolynomial Integer]
+ ToySolver.Data.Polynomial.Factorization.Hensel.Internal: hensel :: forall (p :: Nat). KnownNat p => UPolynomial Integer -> [UPolynomial (PrimeField p)] -> Integer -> [UPolynomial Integer]
- ToySolver.Data.Polynomial.GroebnerBasis: basis :: forall k v. (Eq k, Fractional k, Ord k, Ord v) => MonomialOrder v -> [Polynomial k v] -> [Polynomial k v]
+ ToySolver.Data.Polynomial.GroebnerBasis: basis :: (Eq k, Fractional k, Ord k, Ord v) => MonomialOrder v -> [Polynomial k v] -> [Polynomial k v]
- ToySolver.Data.Polynomial.GroebnerBasis: basis' :: forall k v. (Eq k, Fractional k, Ord k, Ord v) => Options -> MonomialOrder v -> [Polynomial k v] -> [Polynomial k v]
+ ToySolver.Data.Polynomial.GroebnerBasis: basis' :: (Eq k, Fractional k, Ord k, Ord v) => Options -> MonomialOrder v -> [Polynomial k v] -> [Polynomial k v]
- ToySolver.Data.Polynomial.GroebnerBasis: reduceGBasis :: forall k v. (Eq k, Ord k, Fractional k, Ord v) => MonomialOrder v -> [Polynomial k v] -> [Polynomial k v]
+ ToySolver.Data.Polynomial.GroebnerBasis: reduceGBasis :: (Eq k, Ord k, Fractional k, Ord v) => MonomialOrder v -> [Polynomial k v] -> [Polynomial k v]
- ToySolver.EUF.FiniteModelFinder: toSkolemNF :: forall m. Monad m => (Var -> Int -> m FSym) -> Formula -> m [Clause]
+ ToySolver.EUF.FiniteModelFinder: toSkolemNF :: Monad m => (Var -> Int -> m FSym) -> Formula -> m [Clause]
- ToySolver.Graph.Base: type EdgeLabeledGraph a = Array Vertex (IntMap a)
+ ToySolver.Graph.Base: type EdgeLabeledGraph a = Array Vertex IntMap a
- ToySolver.Graph.ShortestPath: bellmanFordDetectNegativeCycle :: forall cost label a. Real cost => Fold cost label a -> Graph cost label -> IntMap (cost, Last (InEdge cost label)) -> Maybe a
+ ToySolver.Graph.ShortestPath: bellmanFordDetectNegativeCycle :: Real cost => Fold cost label a -> Graph cost label -> IntMap (cost, Last (InEdge cost label)) -> Maybe a
- ToySolver.Graph.ShortestPath: dijkstra :: forall cost label a. Real cost => Fold cost label a -> Graph cost label -> [Vertex] -> IntMap (cost, a)
+ ToySolver.Graph.ShortestPath: dijkstra :: Real cost => Fold cost label a -> Graph cost label -> [Vertex] -> IntMap (cost, a)
- ToySolver.Graph.ShortestPath: floydWarshall :: forall cost label a. Real cost => Fold cost label a -> Graph cost label -> IntMap (IntMap (cost, a))
+ ToySolver.Graph.ShortestPath: floydWarshall :: Real cost => Fold cost label a -> Graph cost label -> IntMap (IntMap (cost, a))
- ToySolver.Internal.Data.SeqQueue: data SeqQueue m a
+ ToySolver.Internal.Data.SeqQueue: data SeqQueue (m :: Type -> Type) a
- ToySolver.Internal.Data.Vec: clear :: MArray a e IO => GenericVec a e -> IO ()
+ ToySolver.Internal.Data.Vec: clear :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> IO ()
- ToySolver.Internal.Data.Vec: clone :: MArray a e IO => GenericVec a e -> IO (GenericVec a e)
+ ToySolver.Internal.Data.Vec: clone :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> IO (GenericVec a e)
- ToySolver.Internal.Data.Vec: data GenericVec a e
+ ToySolver.Internal.Data.Vec: data GenericVec (a :: Type -> Type -> Type) e
- ToySolver.Internal.Data.Vec: getCapacity :: MArray a e IO => GenericVec a e -> IO Int
+ ToySolver.Internal.Data.Vec: getCapacity :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> IO Int
- ToySolver.Internal.Data.Vec: getElems :: MArray a e IO => GenericVec a e -> IO [e]
+ ToySolver.Internal.Data.Vec: getElems :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> IO [e]
- ToySolver.Internal.Data.Vec: getSize :: GenericVec a e -> IO Int
+ ToySolver.Internal.Data.Vec: getSize :: forall (a :: Type -> Type -> Type) e. GenericVec a e -> IO Int
- ToySolver.Internal.Data.Vec: growTo :: MArray a e IO => GenericVec a e -> Int -> IO ()
+ ToySolver.Internal.Data.Vec: growTo :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> Int -> IO ()
- ToySolver.Internal.Data.Vec: modify :: MArray a e IO => GenericVec a e -> Int -> (e -> e) -> IO ()
+ ToySolver.Internal.Data.Vec: modify :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> Int -> (e -> e) -> IO ()
- ToySolver.Internal.Data.Vec: modify' :: MArray a e IO => GenericVec a e -> Int -> (e -> e) -> IO ()
+ ToySolver.Internal.Data.Vec: modify' :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> Int -> (e -> e) -> IO ()
- ToySolver.Internal.Data.Vec: new :: MArray a e IO => IO (GenericVec a e)
+ ToySolver.Internal.Data.Vec: new :: forall (a :: Type -> Type -> Type) e. MArray a e IO => IO (GenericVec a e)
- ToySolver.Internal.Data.Vec: peek :: MArray a e IO => GenericVec a e -> IO e
+ ToySolver.Internal.Data.Vec: peek :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> IO e
- ToySolver.Internal.Data.Vec: pop :: MArray a e IO => GenericVec a e -> IO e
+ ToySolver.Internal.Data.Vec: pop :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> IO e
- ToySolver.Internal.Data.Vec: popMaybe :: MArray a e IO => GenericVec a e -> IO (Maybe e)
+ ToySolver.Internal.Data.Vec: popMaybe :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> IO (Maybe e)
- ToySolver.Internal.Data.Vec: push :: MArray a e IO => GenericVec a e -> e -> IO ()
+ ToySolver.Internal.Data.Vec: push :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> e -> IO ()
- ToySolver.Internal.Data.Vec: read :: MArray a e IO => GenericVec a e -> Int -> IO e
+ ToySolver.Internal.Data.Vec: read :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> Int -> IO e
- ToySolver.Internal.Data.Vec: resize :: MArray a e IO => GenericVec a e -> Int -> IO ()
+ ToySolver.Internal.Data.Vec: resize :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> Int -> IO ()
- ToySolver.Internal.Data.Vec: resizeCapacity :: MArray a e IO => GenericVec a e -> Int -> IO ()
+ ToySolver.Internal.Data.Vec: resizeCapacity :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> Int -> IO ()
- ToySolver.Internal.Data.Vec: unsafeModify :: MArray a e IO => GenericVec a e -> Int -> (e -> e) -> IO ()
+ ToySolver.Internal.Data.Vec: unsafeModify :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> Int -> (e -> e) -> IO ()
- ToySolver.Internal.Data.Vec: unsafeModify' :: MArray a e IO => GenericVec a e -> Int -> (e -> e) -> IO ()
+ ToySolver.Internal.Data.Vec: unsafeModify' :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> Int -> (e -> e) -> IO ()
- ToySolver.Internal.Data.Vec: unsafePeek :: MArray a e IO => GenericVec a e -> IO e
+ ToySolver.Internal.Data.Vec: unsafePeek :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> IO e
- ToySolver.Internal.Data.Vec: unsafePop :: MArray a e IO => GenericVec a e -> IO e
+ ToySolver.Internal.Data.Vec: unsafePop :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> IO e
- ToySolver.Internal.Data.Vec: unsafeRead :: MArray a e IO => GenericVec a e -> Int -> IO e
+ ToySolver.Internal.Data.Vec: unsafeRead :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> Int -> IO e
- ToySolver.Internal.Data.Vec: unsafeWrite :: MArray a e IO => GenericVec a e -> Int -> e -> IO ()
+ ToySolver.Internal.Data.Vec: unsafeWrite :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> Int -> e -> IO ()
- ToySolver.Internal.Data.Vec: write :: MArray a e IO => GenericVec a e -> Int -> e -> IO ()
+ ToySolver.Internal.Data.Vec: write :: forall (a :: Type -> Type -> Type) e. MArray a e IO => GenericVec a e -> Int -> e -> IO ()
- ToySolver.SAT.Encoder.Cardinality: data Encoder m
+ ToySolver.SAT.Encoder.Cardinality: data Encoder (m :: Type -> Type)
- ToySolver.SAT.Encoder.Cardinality: getTseitinEncoder :: Encoder m -> Encoder m
+ ToySolver.SAT.Encoder.Cardinality: getTseitinEncoder :: forall (m :: Type -> Type). Encoder m -> Encoder m
- ToySolver.SAT.Encoder.Cardinality.Internal.ParallelCounter: encodeAtLeastWithPolarityParallelCounter :: forall m. PrimMonad m => Encoder m -> Polarity -> AtLeast -> m Lit
+ ToySolver.SAT.Encoder.Cardinality.Internal.ParallelCounter: encodeAtLeastWithPolarityParallelCounter :: PrimMonad m => Encoder m -> Polarity -> AtLeast -> m Lit
- ToySolver.SAT.Encoder.Cardinality.Internal.Totalizer: Encoder :: Encoder m -> MutVar (PrimState m) (Map LitSet (Vector Var)) -> Encoder m
+ ToySolver.SAT.Encoder.Cardinality.Internal.Totalizer: Encoder :: Encoder m -> MutVar (PrimState m) (Map LitSet (Vector Var)) -> Encoder (m :: Type -> Type)
- ToySolver.SAT.Encoder.Cardinality.Internal.Totalizer: data Encoder m
+ ToySolver.SAT.Encoder.Cardinality.Internal.Totalizer: data Encoder (m :: Type -> Type)
- ToySolver.SAT.Encoder.PB: Encoder :: Encoder m -> Strategy -> Encoder m
+ ToySolver.SAT.Encoder.PB: Encoder :: Encoder m -> Strategy -> Encoder (m :: Type -> Type)
- ToySolver.SAT.Encoder.PB: data Encoder m
+ ToySolver.SAT.Encoder.PB: data Encoder (m :: Type -> Type)
- ToySolver.SAT.Encoder.PB: encodePBLinAtLeast :: forall m. PrimMonad m => Encoder m -> PBLinAtLeast -> m Lit
+ ToySolver.SAT.Encoder.PB: encodePBLinAtLeast :: PrimMonad m => Encoder m -> PBLinAtLeast -> m Lit
- ToySolver.SAT.Encoder.PB: encodePBLinAtLeastWithPolarity :: forall m. PrimMonad m => Encoder m -> Polarity -> PBLinAtLeast -> m Lit
+ ToySolver.SAT.Encoder.PB: encodePBLinAtLeastWithPolarity :: PrimMonad m => Encoder m -> Polarity -> PBLinAtLeast -> m Lit
- ToySolver.SAT.Encoder.PB.Internal.Adder: addPBLinAtLeastAdder :: forall m. PrimMonad m => Encoder m -> PBLinAtLeast -> m ()
+ ToySolver.SAT.Encoder.PB.Internal.Adder: addPBLinAtLeastAdder :: PrimMonad m => Encoder m -> PBLinAtLeast -> m ()
- ToySolver.SAT.Encoder.PB.Internal.BDD: encodePBLinAtLeastWithPolarityBDD :: forall m. PrimMonad m => Encoder m -> Polarity -> PBLinAtLeast -> m Lit
+ ToySolver.SAT.Encoder.PB.Internal.BDD: encodePBLinAtLeastWithPolarityBDD :: PrimMonad m => Encoder m -> Polarity -> PBLinAtLeast -> m Lit
- ToySolver.SAT.Encoder.PBNLC: data Encoder m
+ ToySolver.SAT.Encoder.PBNLC: data Encoder (m :: Type -> Type)
- ToySolver.SAT.Encoder.PBNLC: getTseitinEncoder :: Encoder m -> Encoder m
+ ToySolver.SAT.Encoder.PBNLC: getTseitinEncoder :: forall (m :: Type -> Type). Encoder m -> Encoder m
- ToySolver.SAT.Encoder.Tseitin: data Encoder m
+ ToySolver.SAT.Encoder.Tseitin: data Encoder (m :: Type -> Type)
- ToySolver.SAT.Encoder.Tseitin: encodeConjWithPolarity :: forall m. PrimMonad m => Encoder m -> Polarity -> [Lit] -> m Lit
+ ToySolver.SAT.Encoder.Tseitin: encodeConjWithPolarity :: PrimMonad m => Encoder m -> Polarity -> [Lit] -> m Lit
- ToySolver.SAT.Encoder.Tseitin: encodeFACarry :: forall m. PrimMonad m => Encoder m -> Lit -> Lit -> Lit -> m Lit
+ ToySolver.SAT.Encoder.Tseitin: encodeFACarry :: PrimMonad m => Encoder m -> Lit -> Lit -> Lit -> m Lit
- ToySolver.SAT.Encoder.Tseitin: encodeFACarryWithPolarity :: forall m. PrimMonad m => Encoder m -> Polarity -> Lit -> Lit -> Lit -> m Lit
+ ToySolver.SAT.Encoder.Tseitin: encodeFACarryWithPolarity :: PrimMonad m => Encoder m -> Polarity -> Lit -> Lit -> Lit -> m Lit
- ToySolver.SAT.Encoder.Tseitin: encodeFASum :: forall m. PrimMonad m => Encoder m -> Lit -> Lit -> Lit -> m Lit
+ ToySolver.SAT.Encoder.Tseitin: encodeFASum :: PrimMonad m => Encoder m -> Lit -> Lit -> Lit -> m Lit
- ToySolver.SAT.Encoder.Tseitin: encodeFASumWithPolarity :: forall m. PrimMonad m => Encoder m -> Polarity -> Lit -> Lit -> Lit -> m Lit
+ ToySolver.SAT.Encoder.Tseitin: encodeFASumWithPolarity :: PrimMonad m => Encoder m -> Polarity -> Lit -> Lit -> Lit -> m Lit
- ToySolver.SAT.Encoder.Tseitin: encodeITEWithPolarity :: forall m. PrimMonad m => Encoder m -> Polarity -> Lit -> Lit -> Lit -> m Lit
+ ToySolver.SAT.Encoder.Tseitin: encodeITEWithPolarity :: PrimMonad m => Encoder m -> Polarity -> Lit -> Lit -> Lit -> m Lit
- ToySolver.SAT.Encoder.Tseitin: encodeXORWithPolarity :: forall m. PrimMonad m => Encoder m -> Polarity -> Lit -> Lit -> m Lit
+ ToySolver.SAT.Encoder.Tseitin: encodeXORWithPolarity :: PrimMonad m => Encoder m -> Polarity -> Lit -> Lit -> m Lit
- ToySolver.SAT.Encoder.Tseitin: newEncoder :: PrimMonad m => AddClause m a => a -> m (Encoder m)
+ ToySolver.SAT.Encoder.Tseitin: newEncoder :: (PrimMonad m, AddClause m a) => a -> m (Encoder m)
- ToySolver.SAT.Encoder.Tseitin: newEncoderWithPBLin :: PrimMonad m => AddPBLin m a => a -> m (Encoder m)
+ ToySolver.SAT.Encoder.Tseitin: newEncoderWithPBLin :: (PrimMonad m, AddPBLin m a) => a -> m (Encoder m)
- ToySolver.SAT.Solver.CDCL: class AddClause m a => AddCardinality m a | a -> m
+ ToySolver.SAT.Solver.CDCL: class AddClause m a => AddCardinality (m :: Type -> Type) a | a -> m
- ToySolver.SAT.Solver.CDCL: class NewVar m a => AddClause m a | a -> m
+ ToySolver.SAT.Solver.CDCL: class NewVar m a => AddClause (m :: Type -> Type) a | a -> m
- ToySolver.SAT.Solver.CDCL: class AddCardinality m a => AddPBLin m a | a -> m
+ ToySolver.SAT.Solver.CDCL: class AddCardinality m a => AddPBLin (m :: Type -> Type) a | a -> m
- ToySolver.SAT.Solver.CDCL: class AddClause m a => AddXORClause m a | a -> m
+ ToySolver.SAT.Solver.CDCL: class AddClause m a => AddXORClause (m :: Type -> Type) a | a -> m
- ToySolver.SAT.Store.CNF: data CNFStore m
+ ToySolver.SAT.Store.CNF: data CNFStore (m :: Type -> Type)
- ToySolver.SAT.Store.PB: data PBStore m
+ ToySolver.SAT.Store.PB: data PBStore (m :: Type -> Type)
- ToySolver.SAT.Types: class AddClause m a => AddCardinality m a | a -> m
+ ToySolver.SAT.Types: class AddClause m a => AddCardinality (m :: Type -> Type) a | a -> m
- ToySolver.SAT.Types: class NewVar m a => AddClause m a | a -> m
+ ToySolver.SAT.Types: class NewVar m a => AddClause (m :: Type -> Type) a | a -> m
- ToySolver.SAT.Types: class AddCardinality m a => AddPBLin m a | a -> m
+ ToySolver.SAT.Types: class AddCardinality m a => AddPBLin (m :: Type -> Type) a | a -> m
- ToySolver.SAT.Types: class AddPBLin m a => AddPBNL m a | a -> m
+ ToySolver.SAT.Types: class AddPBLin m a => AddPBNL (m :: Type -> Type) a | a -> m
- ToySolver.SAT.Types: class AddClause m a => AddXORClause m a | a -> m
+ ToySolver.SAT.Types: class AddClause m a => AddXORClause (m :: Type -> Type) a | a -> m
- ToySolver.SAT.Types: class Monad m => NewVar m a | a -> m
+ ToySolver.SAT.Types: class Monad m => NewVar (m :: Type -> Type) a | a -> m
- ToySolver.SAT.Types: instantiateAtLeast :: forall m. Monad m => (Lit -> m LBool) -> AtLeast -> m AtLeast
+ ToySolver.SAT.Types: instantiateAtLeast :: Monad m => (Lit -> m LBool) -> AtLeast -> m AtLeast
- ToySolver.SAT.Types: instantiateClause :: forall m. Monad m => (Lit -> m LBool) -> Clause -> m (Maybe Clause)
+ ToySolver.SAT.Types: instantiateClause :: Monad m => (Lit -> m LBool) -> Clause -> m (Maybe Clause)
- ToySolver.SAT.Types: instantiatePBLinAtLeast :: forall m. Monad m => (Lit -> m LBool) -> PBLinAtLeast -> m PBLinAtLeast
+ ToySolver.SAT.Types: instantiatePBLinAtLeast :: Monad m => (Lit -> m LBool) -> PBLinAtLeast -> m PBLinAtLeast
- ToySolver.SAT.Types: instantiateXORClause :: forall m. Monad m => (Lit -> m LBool) -> XORClause -> m XORClause
+ ToySolver.SAT.Types: instantiateXORClause :: Monad m => (Lit -> m LBool) -> XORClause -> m XORClause
Files
- CHANGELOG.markdown +59/−16
- README.md +49/−12
- Smtlib/Smtlib/Parsers/CommandsParsers.hs +0/−653
- Smtlib/Smtlib/Parsers/CommonParsers.hs +0/−473
- Smtlib/Smtlib/Parsers/ResponseParsers.hs +0/−375
- Smtlib/Smtlib/Syntax/ShowSL.hs +0/−247
- Smtlib/Smtlib/Syntax/Syntax.hs +0/−279
- app/maxsatverify.hs +0/−48
- app/pbverify.hs +0/−47
- app/pigeonhole.hs +0/−1
- app/toyconvert.hs +44/−41
- app/toyqbf.hs +1/−1
- app/toysat/toysat.hs +41/−30
- app/toysmt/ToySolver/SMT/SMTLIB2Solver.hs +0/−888
- app/toysmt/toysmt.hs +77/−35
- app/toysolver.hs +132/−58
- app/toysolver_check.hs +163/−0
- samples/programs/assign/assign.hs +1/−1
- samples/programs/htc/htc.hs +1/−1
- samples/programs/knapsack/knapsack.hs +1/−1
- samples/programs/numberlink/numberlink.hs +1/−1
- samples/programs/shortest-path/shortest-path.hs +5/−10
- samples/programs/survey-propagation/survey-propagation.hs +0/−1
- samples/sat/empty-clause.cnf +0/−1
- src/ToySolver/Arith/CAD.hs +1/−3
- src/ToySolver/Arith/ContiTraverso.hs +1/−1
- src/ToySolver/Arith/Cooper/Base.hs +1/−1
- src/ToySolver/Arith/FourierMotzkin/Base.hs +1/−1
- src/ToySolver/Arith/MIP.hs +1/−1
- src/ToySolver/Arith/OmegaTest/Base.hs +1/−1
- src/ToySolver/Arith/Simplex.hs +2/−2
- src/ToySolver/Arith/Simplex/Textbook.hs +1/−1
- src/ToySolver/BitVector/Base.hs +6/−20
- src/ToySolver/BitVector/Solver.hs +3/−11
- src/ToySolver/Combinatorial/HittingSet/HTCBDD.hs +1/−3
- src/ToySolver/Combinatorial/HittingSet/SHD.hs +1/−3
- src/ToySolver/Combinatorial/Knapsack/BB.hs +3/−3
- src/ToySolver/Combinatorial/Knapsack/DPDense.hs +6/−4
- src/ToySolver/Combinatorial/Knapsack/DPSparse.hs +1/−1
- src/ToySolver/Converter/MIP.hs +226/−141
- src/ToySolver/Converter/MIP2SMT.hs +1/−1
- src/ToySolver/Converter/PB.hs +133/−80
- src/ToySolver/Converter/PB/Internal/Product.hs +2/−3
- src/ToySolver/Converter/QUBO.hs +1/−1
- src/ToySolver/Converter/SAT2MIS.hs +3/−5
- src/ToySolver/Data/AlgebraicNumber/Real.hs +1/−1
- src/ToySolver/Data/AlgebraicNumber/Root.hs +1/−1
- src/ToySolver/Data/AlgebraicNumber/Sturm.hs +15/−6
- src/ToySolver/Data/BoolExpr.hs +1/−1
- src/ToySolver/Data/LA.hs +1/−1
- src/ToySolver/Data/Polyhedron.hs +24/−27
- src/ToySolver/Data/Polynomial/Base.hs +30/−20
- src/ToySolver/Data/Polynomial/Factorization/FiniteField.hs +1/−1
- src/ToySolver/Data/Polynomial/Factorization/Kronecker.hs +1/−1
- src/ToySolver/Data/Polynomial/Factorization/Zassenhaus.hs +1/−1
- src/ToySolver/Data/Polynomial/Interpolation/Hermite.hs +1/−1
- src/ToySolver/EUF/FiniteModelFinder.hs +1/−1
- src/ToySolver/FileFormat/Base.hs +18/−3
- src/ToySolver/Internal/SolutionChecker.hs +307/−0
- src/ToySolver/QBF.hs +4/−3
- src/ToySolver/SAT/Encoder/Integer.hs +32/−8
- src/ToySolver/SAT/Encoder/PB/Internal/BCCNF.hs +2/−2
- src/ToySolver/SAT/Encoder/PB/Internal/BDD.hs +2/−2
- src/ToySolver/SAT/Encoder/PB/Internal/Sorter.hs +3/−3
- src/ToySolver/SAT/Internal/JSON.hs +25/−8
- src/ToySolver/SAT/LogParser.hs +121/−0
- src/ToySolver/SAT/MUS/Base.hs +0/−1
- src/ToySolver/SAT/MUS/Deletion.hs +1/−1
- src/ToySolver/SAT/MUS/Enum/CAMUS.hs +0/−1
- src/ToySolver/SAT/MUS/Insertion.hs +1/−1
- src/ToySolver/SAT/MUS/QuickXplain.hs +1/−1
- src/ToySolver/SAT/PBO/BCD.hs +1/−1
- src/ToySolver/SAT/Printer.hs +102/−37
- src/ToySolver/SAT/Solver/CDCL.hs +9/−24
- src/ToySolver/SAT/Solver/SLS/ProbSAT.hs +1/−14
- src/ToySolver/SAT/Solver/SLS/UBCSAT.hs +1/−1
- src/ToySolver/SAT/Types.hs +1/−1
- src/ToySolver/SMT.hs +14/−32
- src/ToySolver/SMT/SMTLIB2Solver.hs +896/−0
- src/ToySolver/Version.hs +1/−1
- test/Test/AReal.hs +32/−0
- test/Test/Arith.hs +0/−1
- test/Test/BitVector.hs +7/−6
- test/Test/ContiTraverso.hs +0/−1
- test/Test/Converter.hs +242/−7
- test/Test/MIPSolver.hs +0/−1
- test/Test/Misc.hs +16/−0
- test/Test/QUBO.hs +1/−1
- test/Test/SAT.hs +51/−0
- test/Test/SAT/Encoder.hs +27/−1
- test/Test/SAT/LogParser.hs +269/−0
- test/Test/SAT/Types.hs +1/−1
- test/Test/SAT/Utils.hs +1/−1
- test/Test/SDPFile.hs +0/−1
- test/Test/SMT.hs +29/−0
- test/Test/SMTLIB2Solver.hs +104/−72
- test/Test/Simplex.hs +0/−1
- test/Test/SimplexTextbook.hs +0/−1
- test/Test/Smtlib.hs +0/−604
- test/Test/SolutionChecker.hs +576/−0
- test/TestPolynomial.hs +2/−2
- test/TestSuite.hs +4/−2
- toysolver.cabal +92/−278
CHANGELOG.markdown view
@@ -1,7 +1,50 @@+0.10.0 (Unreleased)+-----++* SMT+ * Migrate `toysmt` from the `Smtlib` fork to the newly developed [language-smtlib](https://hackage.haskell.org/package/language-smtlib) package (#206, #214)+ * The `toysmt` REPL now supports multi-line input (#206, #213)+ * Support `define-const` command in `ToySolver.SMT.SMTLIB2Solver` (#215)+ * Update the semantics of zero division on bitvectors to conform to SMT-LIB >=2.6 (#209)+ * `toysmt` now suppresses the prompt and does not use haskeline when stdin is not a terminal (#211)+ * Fix SMT model not to contain a bogus entry for an unused uninterpreted function (#216)+ * Modify the `(get-model)` command to return the definition of the zero-division function (`/0`) instead of the assertions about division by zero results (#217)+* Converter and `toyconvert` command+ * Do not produce `obj<T` constraint in `wbo2pb` when all interpretations are admissible (#157)+ * Optimize `unconstrainPB` a little (#159, #161)+ * Change `ToySolver.SAT.Encoder.Integer` to encode integer variables without introducing `<=` constraints (#162)+ * Store surplus expression instead of raw variables in `inequalitiesToEqualitiesPB` (#164)+ * Refactor `ToySolver.SAT.Encoder.Integer` (#167)+ * Improve `inequalitiesToEqualitiesPB` to produce more compact output (#168)+ * Extend `normalizePB` to transform constant terms in the objective function into non-constant terms (#169)+ * Support semi-integer variables in IP→PB conversion and improve error messages (#170)+ * Simplify JSON that represents `PBSum` (#171)+ * Scale objective function and constraints using rational instead of integer in IP→PB transformation (#172)+ * Linearize constant term in objective function when writing LP/MPS file (#185)+ * Add `--[no-]mps-obj-name` option to `toyconvert` (#188)+ * Rename `--lp` option to `--mip` and keep `--lp` as an alias (#189)+ * Optimize `pb2ip` and `wbo2ip` by not calling `convVar` repeatedly (#191)+* `toysat`+ * Conform to MaxSAT Evaluation 2024 (#177)+ * It outputs `SATISFIABLE` in MaxSAT mode if it finds a model but fails to prove optimality+ * Add `--exit-code` option to set exit code+* Dependencies+ * Stop supporting 32-bit Windows (#154)+ * Stop supporting GHC 9.4 and below (#156, #205)+ * Use `pseudo-boolean-0.1.12.0` (#158)+ * Require `aeson >=2.0`, `array >=0.5.6`, `hashable >=1.4.3`, and `optparse-applicative >=0.18` (#208)+ * Require `language-smtlib >=0.2.0.0` (#206, #214)+* Misc+ * Add `toysolver-check` command to check solution (#174, #196)+ * Improve model output speed by printing using `ByteString` (#175)+ * Build statically linked Linux binaries (#194)+ * Use Cauchy's bounds instead of Lagrange's bounds as the bounds for all roots (#203)+ * Optimize `divModMP` by rewriting it from a full-reduction strategy to the standard textbook leading-term multivariate division algorithm (#212)+ 0.9.0 (2025-02-18) ----- -* Converters updates+* Converter updates * Add `--dump-info` option to `toyconvert` (#119, #120, #125) * Change the signs of QUBO-related converter's representation of offset (#126) * Change `WBO2IPInfo` not to store weights (#124)@@ -14,9 +57,9 @@ * Restructure converter modules (#142) * Support SOS constraints over non-binary variables in `mip2pb` (#140) * Rename `mip2pb` to `ip2pb`-* Pseudo-boolean and cardinality constarint encoder updates+* Pseudo-boolean and cardinality constraint encoder updates * Consider polarity in encoding of pseudo-boolean and cardinality constraints (#88)- * Add BC-CNF pseudo boolean constraint encoder (#85)+ * Add BC-CNF pseudo-boolean constraint encoder (#85) * Support specifying PB encoding strategy (#77) * Dependencies * Support GHC 9.4 (#92), 9.6, 9.8, 9.10@@ -28,7 +71,7 @@ * Remove features that depend on OpenCL (#90) * Improve `ToySolver.Graph` module (#130, #150) -0.8.0+0.8.0 (2022-07-26) ----- * Separate Formula type from `ToySolver.SAT.Encoder.Tseitin` into `ToySolver.SAT.Formula` (#74)@@ -41,15 +84,15 @@ * Remove deprecated API (#56) * Support GHC-9.2 (#76) and stop supporting GHC 8.0, 8.2, and 8.4 (#50) -0.7.0+0.7.0 (2021-02-08) ----- * add `toysat-ipasir` foreign library which implements [IPASIR](https://github.com/biotomas/ipasir) API for incremental SAT solving. * `ToySolver.SAT` * Restructure SAT solver modules under `ToySolver.SAT.Solver.*`- * add `SequentialCounter`, `ParallelCounter` and `Totalizer` as methods for encoding cardinality constraints+ * add `SequentialCounter`, `ParallelCounter`, and `Totalizer` as methods for encoding cardinality constraints * add `PackedLit` type to reduce memory footprint- * use structure of array (SOA) approach to reduce memory footprint+ * use structure of array (SOA) approach to reducethe memory footprint * add `setLearnCallback`/`clearLearnCallback` and `setTerminateCallback`/`clearTerminateCallback` which correspond to [IPASIR](https://github.com/biotomas/ipasir)'s `ipasir_set_learn()` and `ipasir_set_terminate()`. * add `clearLogger` * change `getFailedAssumptions` and `getAssumptionsImplications` to return `IntSet` instead of `[Int]`@@ -61,7 +104,7 @@ * stop supporting GHC-7.10 * add `ExtraBoundsChecking` flag for debugging -0.6.0+0.6.0 (2019-10-04) ----- * new solvers: * `ToySolver.SAT.SLS.ProbSAT` and sample `probsat` program@@ -88,7 +131,7 @@ * switch from `System.Console.GetOpt` to `optparse-applicative` * stop supporting GHC-7.8 -0.5.0+0.5.0 (2017-10-09) ----- * new solvers: * `ToySolver.BitVector`@@ -102,7 +145,7 @@ * add `--init-sp` option to initialize variable state using survey propagation * allow using `UBCSAT` when solving PBO/WBO problems * `toysmt`- * suport bit-vector logic+ * support bit-vector logic * `toyconvert` * `pbconvert` and `lpconvert` were merged into a single command `toyconvert` * add `--ksat=NUMBER` option to convert to k-SAT formula@@ -133,18 +176,18 @@ * use `clock` package for measuring duration * add simple numberlink solver sample -0.4.0+0.4.0 (2016-06-25) ------* add experimental SMT (Satisfiablity Modulo Theories) solver 'toysmt', which supports theory of uninterpreted functions and linear real arithmetics.+* add experimental SMT (Satisfiability Modulo Theories) solver 'toysmt', which supports theory of uninterpreted functions and linear real arithmetics. * fix toysat to output model in Max-SAT format instead of PB/WBO format when solving Max-SAT problems * add experimental getAssumptionsImplications functions to ToySolver.SAT module. * add getFixedLiterals to ToySolver.SAT module. * use 'mwc-random' package instead of 'random' package.-* introduce 'Config' data type in ToySolver.SAT to simplify configulation management.+* introduce 'Config' data type in ToySolver.SAT to simplify configuration management. * add subset-sum problem solver-* implement backracking and explanation generation in simplex solver and congruence closure solver.+* implement backtracking and explanation generation in simplex solver and congruence closure solver. -0.3.0+0.3.0 (2015-05-31) ------* split OPB/WBO file library into a serarate 'pseudo-boolean' library.+* split OPB/WBO file library into a separate 'pseudo-boolean' library.
README.md view
@@ -3,6 +3,7 @@ [](https://opensource.org/licenses/BSD-3-Clause) [](https://gitter.im/msakai/toysolver)+[](https://deepwiki.com/msakai/toysolver) Hackage: [](https://hackage.haskell.org/package/toysolver)@@ -11,9 +12,9 @@ [](https://github.com/msakai/toysolver/actions) [](https://coveralls.io/r/msakai/toysolver) -It provides solver implementations of various problems including SAT, SMT, Max-SAT, PBS (Pseudo Boolean Satisfaction), PBO (Pseudo Boolean Optimization), MILP (Mixed Integer Linear Programming) and non-linear real arithmetic.+It provides solver implementations of various problems, including SAT, SMT, Max-SAT, PBS (Pseudo Boolean Satisfaction), PBO (Pseudo Boolean Optimization), MILP (Mixed Integer Linear Programming), and non-linear real arithmetic. -In particular, it contains moderately-fast pure-Haskell SAT solver 'toysat'.+In particular, it contains a moderately fast pure-Haskell SAT solver `toysat`. Installation ------------@@ -32,8 +33,8 @@ * Mixed Integer Linear Programming (MILP or MIP) * Boolean SATisfiability problem (SAT) * PB- * Pseudo Boolean Satisfaction (PBS)- * Pseudo Boolean Optimization (PBO)+ * Pseudo-Boolean Satisfaction (PBS)+ * Pseudo-Boolean Optimization (PBO) * Weighted Boolean Optimization (WBO) * Max-SAT families * Max-SAT@@ -45,7 +46,7 @@ Usage: toysolver [OPTION...] [file.lp|file.mps]- toysolver --lp [OPTION...] [file.lp|file.mps]+ toysolver --mip [OPTION...] [file.lp|file.mps] toysolver --sat [OPTION...] [file.cnf] toysolver --pb [OPTION...] [file.opb] toysolver --wbo [OPTION...] [file.wbo]@@ -64,8 +65,8 @@ * Minimally Unsatisfiable Subset (MUS) * Group-Oriented MUS (GMUS) * PB- * Pseudo Boolean Satisfaction (PBS)- * Pseudo Boolean Optimization (PBO)+ * Pseudo-Boolean Satisfaction (PBS)+ * Pseudo-Boolean Optimization (PBO) * Weighted Boolean Optimization (WBO) * Max-SAT families * Max-SAT@@ -82,7 +83,7 @@ toysat --pb [file.opb|-] toysat --wbo [file.wbo|-] toysat --maxsat [file.cnf|file.wcnf|-]- toysat --lp [file.lp|file.mps|-]+ toysat --mip [file.lp|file.mps|-] PB'12 competition result: @@ -92,7 +93,7 @@ ### toysmt -SMT solver based on toysat.+SMT solver based on `toysat`. Usage: @@ -102,7 +103,7 @@ ### toyfmf -SAT-based finite model finder for first order logic (FOL).+SAT-based finite model finder for first-order logic (FOL). Usage: @@ -118,8 +119,44 @@ Supported formats: -* Input formats: .cnf .wcnf .opb .wbo .gcnf .lp .mps-* Output formats: .cnf .wcnf .opb .wbo .lsp .lp .mps .smp .smt2 .ys+|Format Name|File Extension|Input|Output|Description|+|-|-|-|-|-|+|DIMACS CNF|`.cnf`|✅|✅|Standard file format for SAT instances|+|WCNF Format|`.wcnf`|✅|✅|Standard file format for Max-SAT instances ([specification](https://maxsat-evaluations.github.io/2024/rules.html#input))|+|OPB Format|`.opb`|✅|✅|PBS (Pseudo-Boolean Satisfaction) and PBO (Pseudo-Boolean Optimization) instances ([specification](https://www.cril.univ-artois.fr/PB24/OPBcompetition.pdf))|+|WBO Format|`.wbo`|✅|✅|WBO (Weighted-Boolean Optimization) instances ([specification](https://www.cril.univ-artois.fr/PB24/OPBcompetition.pdf))|+|Group oriented CNF Input Format|`.gcnf`|✅|-|Used in Group oriented MUS track of the SAT Competition 2011 ([specification](https://web.archive.org/web/20131116055022/http://www.satcompetition.org/2011/rules.pdf))|+|LP File Format|`.lp`|✅|✅|Linear programming (LP) and mixed integer programming (MIP) problems|+|MPS File Format|`.mps`|✅|✅|Linear programming (LP) and mixed integer programming (MIP) problems|+|LSP Format|`.lsp`|-|✅|Input format for [LocalSolver](http://www.localsolver.com/) (only binary variables are supported)|+|SMP Format|`.smp`|-|✅|Input format for [Nuorium Optimizer (NUOPT)](https://www.msi.co.jp/solution/nuopt/top.html) (only binary variables are supported)|+|SMT-LIB 2 Format|`.smt2`|-|✅|Satisfiability Modulo Theories (SMT) problem instances ([website](https://smt-lib.org/))|+|Yices Input Language|`.ys`|-|✅|SMT problem instances for SMT solver [Yices](https://yices.csl.sri.com/)|+|qbsolv QUBO Input File Format|`.qubo`|✅|✅|Unconstrained quadratic binary optimization problems ([specification](https://github.com/dwavesystems/qbsolv?tab=readme-ov-file#qbsolv-qubo-input-file-format))|++### toysolver-check++Solution checker for various problem files.+Usage:++ toysolver-check [OPTION...] [problem_file] [solution_file]+ toysolver-check --mip [OPTION...] [file.lp|file.mps] [file.sol]+ toysolver-check --sat [OPTION...] [file.cnf] [file.log]+ toysolver-check --pb [OPTION...] [file.opb] [file.log]+ toysolver-check --wbo [OPTION...] [file.wbo] [file.log]+ toysolver-check --maxsat [OPTION...] [file.cnf|file.wcnf] [file.log]++ --encoding ENCODING file encoding for LP/MPS files+ --pb-fast-parser use attoparsec-based parser instead of+ megaparsec-based one for speed+ --tol-integrality REAL If a value of integer variable is within this amount+ from its nearest integer, it is considered feasible.+ (default: 1.0e-5)+ --tol-feasibility REAL If the amount of violation of constraints is within+ this amount, it is considered feasible.+ (default: 1.0e-6)+ --tol-optimality REAL Feasibility tolerance of dual constraints.+ (default: 1.0e-6) Bindings --------
− Smtlib/Smtlib/Parsers/CommandsParsers.hs
@@ -1,653 +0,0 @@-{-|-Module : Smtlib.Parsers.CommandsParsers-Description : Parsers for Smtlib Commands-Copyright : Rogério Pontes 2015-License : WTFPL-Maintainer : rogerp62@outlook.com-Stability : stable--This module contains all the required individual parsers for each Smtlib command,-plus one parser to parse an entire SMTLib2 file, parseSource.---}-module Smtlib.Parsers.CommandsParsers where--import Control.Applicative as Ctr hiding ((<|>))-import Control.Monad-import Data.Functor.Identity-import Smtlib.Parsers.CommonParsers-import Smtlib.Syntax.Syntax-import Text.Parsec.Prim as Prim-import Text.ParserCombinators.Parsec as Pc----{-- #########################################################################- # #- # Parser for an SMTLib2 File #- # #- #########################################################################--}---parseSource :: ParsecT String u Identity Source-parseSource = emptySpace *> (Pc.many $ parseCommand <* Pc.try emptySpace)---{-- "###################### Parser For Commands ###############################--}-parseCommand :: ParsecT String u Identity Command-parseCommand = Pc.try parseSetLogic- <|> Pc.try parseSetOption- <|> Pc.try parseSetInfo- <|> Pc.try parseDeclareSort- <|> Pc.try parseDeclareConst- <|> Pc.try parseDefineSort- <|> Pc.try parseDeclareFun- <|> Pc.try parseDefineFun- <|> Pc.try parseDefineFunRec- <|> Pc.try parseDefineFunsRec- <|> Pc.try parsePush- <|> Pc.try parsePop- <|> Pc.try parseAssert- <|> Pc.try parseCheckSat- <|> Pc.try parseCheckSatAssuming- <|> Pc.try parseGetAssertions- <|> Pc.try parseGetModel- <|> Pc.try parseGetProof- <|> Pc.try parseGetUnsatCore- <|> Pc.try parseGetUnsatAssumptions- <|> Pc.try parseGetValue- <|> Pc.try parseGetAssignment- <|> Pc.try parseGetOption- <|> Pc.try parseGetInfo- <|> Pc.try parseReset- <|> Pc.try parseResetAssertions- <|> Pc.try parseEcho- <|> parseExit----{-- #########################################################################- # #- # Parser for each command #- # #- #########################################################################--}-----parseSetLogic :: ParsecT String u Identity Command-parseSetLogic = do- _ <- aspO- _ <- emptySpace- _ <- string "set-logic"- _ <- emptySpace- symb <- symbol- _ <- emptySpace- _ <- aspC- return $ SetLogic symb---parseSetOption :: ParsecT String u Identity Command-parseSetOption = do- _ <- aspO- _ <- emptySpace- _ <- string "set-option"- _ <- emptySpace- attr <- parseOption- _ <- emptySpace- _ <- aspC- return $ SetOption attr--parseSetInfo :: ParsecT String u Identity Command-parseSetInfo = do- _ <- aspO- _ <- emptySpace- _ <- string "set-info"- _ <- emptySpace <?> "foi aqui1?"- attr <- parseAttribute <?> "foi aqui2?"- _ <- emptySpace- _ <- aspC- return $ SetInfo attr---parseDeclareSort :: ParsecT String u Identity Command-parseDeclareSort = do- _ <- aspO- _ <- emptySpace- _ <- string "declare-sort"- _ <- emptySpace- symb <- symbol- _ <- emptySpace- nume <- numeral- _ <- emptySpace- _ <- aspC- return $ DeclareSort symb (read nume :: Int)--parseDefineSort :: ParsecT String u Identity Command-parseDefineSort = do- _ <- aspO- _ <- emptySpace- _ <- string "define-sort"- _ <- emptySpace- symb <- symbol- _ <- emptySpace- _ <- aspO- symbs <- Pc.many $ symbol <* Pc.try emptySpace- _ <- aspC- _ <- emptySpace- sort <- parseSort- _ <- emptySpace- _ <- aspC- return $ DefineSort symb symbs sort---parseDeclareConst :: ParsecT String u Identity Command-parseDeclareConst = do- _ <-aspO- _ <- emptySpace- _ <- string "declare-const"- _ <- emptySpace- symb <- symbol- _ <- emptySpace- sort <- parseSort- _ <- emptySpace- _ <- aspC- return $ DeclareConst symb sort---parseDeclareFun :: ParsecT String u Identity Command-parseDeclareFun = do- _ <-aspO- _ <- emptySpace- _ <- string "declare-fun"- _ <- emptySpace- symb <- symbol- _ <- emptySpace- _ <- aspO- _ <- emptySpace- sorts <- Pc.many $ parseSort <* Pc.try emptySpace- _ <- aspC- _ <- emptySpace- sort <- parseSort- _ <- emptySpace- _ <- aspC- return $ DeclareFun symb sorts sort---parseDefineFun :: ParsecT String u Identity Command-parseDefineFun = do- _ <- aspO- _ <- emptySpace- _ <- string "define-fun"- _ <- emptySpace- symb <- symbol- _ <- emptySpace- _ <- aspO- sVars <- Pc.many $ parseSortedVar <* Pc.try emptySpace- _ <- aspC- _ <- emptySpace- sort <- parseSort- _ <- emptySpace- term <- parseTerm- _ <- emptySpace- _ <- aspC- return $ DefineFun symb sVars sort term---parseDefineFunRec :: ParsecT String u Identity Command-parseDefineFunRec = do- _ <- aspO- _ <- emptySpace- _ <- string "define-fun-rec"- _ <- emptySpace- symb <- symbol- _ <- emptySpace- _ <- aspO- sVars <- Pc.many $ parseSortedVar <* Pc.try emptySpace- _ <- aspC- _ <- emptySpace- sort <- parseSort- _ <- emptySpace- term <- parseTerm- _ <- emptySpace- _ <- aspC- return $ DefineFunRec symb sVars sort term---parseDefineFunsRec :: ParsecT String u Identity Command-parseDefineFunsRec = do- _ <- aspO- _ <- emptySpace- _ <- string "define-funs-rec"- _ <- emptySpace- _ <- aspO- _ <- emptySpace- fundecs <- Pc.many $ parseFunDec <* Pc.try emptySpace- _ <- aspC- _ <- emptySpace- _ <- aspO- _ <- emptySpace- terms <- Pc.many $ parseTerm <* Pc.try emptySpace- _ <- aspC- _ <- emptySpace- _ <- aspC- return $ DefineFunsRec fundecs terms--parseFunDec :: ParsecT String u Identity FunDec-parseFunDec = do- _ <- aspO- _ <- emptySpace- symb <- symbol- _ <- emptySpace- _ <- aspO- _ <- emptySpace- sVars <- Pc.many $ parseSortedVar <* Pc.try emptySpace- _ <- aspC- _ <- emptySpace- sort <- parseSort- _ <- emptySpace- _ <- aspC- return (FunDec symb sVars sort)---parsePush :: ParsecT String u Identity Command-parsePush = do- _ <- aspO- _ <- emptySpace- _ <- string "push"- _ <- emptySpace- nume <- option 1 $ do- nume <- numeral- _ <- emptySpace- return (read nume :: Int)- _ <- aspC- return $ Push nume---parsePop :: ParsecT String u Identity Command-parsePop = do- _ <- aspO- _ <- emptySpace- _ <- string "pop"- _ <- emptySpace- nume <- option 1 $ do- nume <- numeral- _ <- emptySpace- return (read nume :: Int)- _ <- aspC- return $ Pop nume----parseAssert :: ParsecT String u Identity Command-parseAssert = do- _ <- aspO- _ <- emptySpace- _ <- string "assert"- _ <- emptySpace- term <- parseTerm- _ <- emptySpace- _ <- aspC- return $ Assert term---parseCheckSat :: ParsecT String u Identity Command-parseCheckSat = do- _ <- aspO- _ <- emptySpace- _ <- string "check-sat"- _ <- emptySpace- _ <- aspC- return CheckSat--parseCheckSatAssuming :: ParsecT String u Identity Command-parseCheckSatAssuming = do- _ <- aspO- _ <- emptySpace- _ <- string "check-sat-assuming"- _ <- emptySpace- _ <- aspO- emptySpace- terms <- Pc.many $ parseTerm <* Pc.try emptySpace- _ <- aspC- _ <- emptySpace- _ <- aspC- return (CheckSatAssuming terms)---parseGetAssertions :: ParsecT String u Identity Command-parseGetAssertions = do- _ <- aspO- _ <-emptySpace- _ <- string "get-assertions"- _ <- emptySpace- _ <- aspC- return GetAssertions--parseGetModel :: ParsecT String u Identity Command-parseGetModel = do- _ <- aspO- _ <- emptySpace- _ <- string "get-model"- _ <- emptySpace- _ <-aspC- return GetModel--parseGetProof :: ParsecT String u Identity Command-parseGetProof = do- _ <- aspO- _ <- emptySpace- _ <- string "get-proof"- _ <- emptySpace- _ <-aspC- return GetProof--parseGetUnsatCore :: ParsecT String u Identity Command-parseGetUnsatCore = do- _ <- aspO- _ <- emptySpace- _ <- string "get-unsat-core"- _ <- emptySpace- _ <- aspC- return GetUnsatCore--parseGetUnsatAssumptions :: ParsecT String u Identity Command-parseGetUnsatAssumptions = do- _ <- aspO- _ <- emptySpace- _ <- string "get-unsat-assumptions"- _ <- emptySpace- _ <- aspC- return GetUnsatAssumptions--parseGetValue :: ParsecT String u Identity Command-parseGetValue = do- _ <- aspO- _ <- emptySpace- _ <- string "get-value"- _ <- emptySpace- _ <- aspO- terms <- Pc.many1 $ parseTerm <* Pc.try emptySpace- _ <- aspC- _ <- emptySpace- _ <- aspC- return $ GetValue terms--parseGetAssignment :: ParsecT String u Identity Command-parseGetAssignment = do- _ <- aspO- _ <- emptySpace- _ <- string "get-assignment"- _ <- emptySpace- _ <- aspC- return GetAssignment---parseGetOption :: ParsecT String u Identity Command-parseGetOption = do- _ <- aspO- _ <- emptySpace- _ <- string "get-option"- _ <- emptySpace- word <- keyword- _ <- emptySpace- _ <- aspC- return $ GetOption word---parseGetInfo :: ParsecT String u Identity Command-parseGetInfo = do- _ <- aspO- _ <- emptySpace- _ <- string "get-info"- _ <- emptySpace- flag <- parseInfoFlags- _ <- emptySpace- _ <- aspC- return $ GetInfo flag---parseEcho :: ParsecT String u Identity Command-parseEcho = do- _ <- aspO- _ <- emptySpace- _ <- string "echo"- _ <- emptySpace- s <- str- _ <- emptySpace - _ <- aspC- return $ Echo s---parseExit :: ParsecT String u Identity Command-parseExit = do- _ <- aspO- _ <- emptySpace- _ <- string "exit"- _ <- emptySpace- _ <- aspC- return Exit---parseReset :: ParsecT String u Identity Command-parseReset = do- _ <- aspO- _ <- emptySpace- _ <- string "reset"- _ <- emptySpace- _ <- aspC- return Reset---parseResetAssertions :: ParsecT String u Identity Command-parseResetAssertions = do- _ <- aspO- _ <- emptySpace- _ <- string "reset-assertions"- _ <- emptySpace- _ <- aspC- return ResetAssertions---{-- #########################################################################- # #- # Parse Command Options #- # #- #########################################################################--}--parseOption :: ParsecT String u Identity Option-parseOption = Pc.try parsePrintSuccess- <|> Pc.try parseExpandDefinitions- <|> Pc.try parseInteractiveMode- <|> Pc.try parseProduceProofs- <|> Pc.try parseProduceUnsatCores- <|> Pc.try parseProduceUnsatAssumptions- <|> Pc.try parseProduceModels- <|> Pc.try parseProduceAssignments- <|> Pc.try parseProduceAssertions- <|> Pc.try parseGlobalDeclarations- <|> Pc.try parseRegularOutputChannel- <|> Pc.try parseDiagnosticOutputChannel- <|> Pc.try parseRandomSeed- <|> Pc.try parseVerbosity- <|> Pc.try parseReproducibleResourceLimit- <|> Pc.try parseOptionAttribute----- parse PrintSucess-parsePrintSuccess :: ParsecT String u Identity Option-parsePrintSuccess = do- _ <- string ":print-success"- _ <- spaces- val <- parseBool- return $ PrintSuccess val---parseExpandDefinitions :: ParsecT String u Identity Option-parseExpandDefinitions = do- _ <- string ":expand-definitions"- _ <- spaces- val <- parseBool- return $ ExpandDefinitions val---parseInteractiveMode :: ParsecT String u Identity Option-parseInteractiveMode = do- _ <- string ":interactive-mode"- _ <- spaces- val <- parseBool- return $ InteractiveMode val--parseProduceProofs :: ParsecT String u Identity Option-parseProduceProofs = do- _ <- string ":produce-proofs"- _ <- spaces- val <- parseBool- return $ ProduceProofs val---parseProduceUnsatCores :: ParsecT String u Identity Option-parseProduceUnsatCores = do- _ <- string ":produce-unsat-cores"- _ <- spaces- val <- parseBool- return $ ProduceUnsatCores val--parseProduceUnsatAssumptions :: ParsecT String u Identity Option-parseProduceUnsatAssumptions = do- _ <- string ":produce-unsat-assumptions"- _ <- spaces- val <- parseBool- return $ ProduceUnsatAssumptions val--parseProduceModels :: ParsecT String u Identity Option-parseProduceModels = do- _ <- string ":produce-models"- _ <- spaces- val <- parseBool- return $ ProduceModels val--parseProduceAssignments :: ParsecT String u Identity Option-parseProduceAssignments = do- _ <- string ":produce-assignments"- _ <- spaces- val <- parseBool- return $ ProduceAssignments val--parseProduceAssertions :: ParsecT String u Identity Option-parseProduceAssertions = do- _ <- string ":produce-assertions"- _ <- spaces- val <- parseBool- return $ ProduceAssertions val--parseGlobalDeclarations :: ParsecT String u Identity Option-parseGlobalDeclarations = do- _ <- string ":global-declarations"- _ <- spaces- val <- parseBool- return $ GlobalDeclarations val---parseRegularOutputChannel :: ParsecT String u Identity Option-parseRegularOutputChannel = do- _ <- string ":regular-output-channel"- _ <- spaces- val <- str- return $ RegularOutputChannel val---parseDiagnosticOutputChannel :: ParsecT String u Identity Option-parseDiagnosticOutputChannel = do- _ <- string ":diagnostic-output-channel"- _ <- spaces- val <- str- return $ DiagnosticOutputChannel val--parseRandomSeed :: ParsecT String u Identity Option-parseRandomSeed = do- _ <- string ":random-seed"- _ <- spaces- val <- numeral- return $ RandomSeed (read val :: Int)---parseVerbosity :: ParsecT String u Identity Option-parseVerbosity = do- _ <- string ":verbosity"- _ <- spaces- val <- numeral- return $ Verbosity (read val :: Int)---parseReproducibleResourceLimit :: ParsecT String u Identity Option-parseReproducibleResourceLimit = do- _ <- string ":reproducible-resource-limit"- _ <- spaces- val <- numeral- return $ ReproducibleResourceLimit (read val :: Int)---parseOptionAttribute :: ParsecT String u Identity Option-parseOptionAttribute = do- attr <- parseAttribute- return $ OptionAttr attr-----{-- #########################################################################- # #- # Parsers for Info FLags #- # #- #########################################################################--}--parseInfoFlags :: ParsecT String u Identity InfoFlags-parseInfoFlags = Pc.try parseErrorBehaviour- <|> Pc.try parseName- <|> Pc.try parseAuthors- <|> Pc.try parseVersion- <|> Pc.try parseStatus- <|> Pc.try parseReasonUnknown- <|> Pc.try parseAllStatistics- <|> Pc.try parseAssertionStackLevels- <|> parseInfoKeyword---parseErrorBehaviour :: ParsecT String u Identity InfoFlags-parseErrorBehaviour = string ":error-behavior" *> return ErrorBehavior---parseName :: ParsecT String u Identity InfoFlags-parseName = string ":name" *> return Name--parseAuthors :: ParsecT String u Identity InfoFlags-parseAuthors = string ":authors" *> return Authors--parseVersion :: ParsecT String u Identity InfoFlags-parseVersion = string ":version" *> return Version--parseStatus :: ParsecT String u Identity InfoFlags-parseStatus = string ":status" *> return Status--parseReasonUnknown :: ParsecT String u Identity InfoFlags-parseReasonUnknown = string ":reason-unknown" *> return ReasonUnknown--parseAllStatistics :: ParsecT String u Identity InfoFlags-parseAllStatistics = string ":all-statistics" *> return AllStatistics--parseAssertionStackLevels :: ParsecT String u Identity InfoFlags-parseAssertionStackLevels = string ":assertion-stack-levels" *> return AssertionStackLevels--parseInfoKeyword :: ParsecT String u Identity InfoFlags-parseInfoKeyword = liftM InfoFlags keyword
− Smtlib/Smtlib/Parsers/CommonParsers.hs
@@ -1,473 +0,0 @@-{-|-Module : Smtlib.Parsers.CommandsParsers-Description : Common parsers for commands and responses.-Copyright : Rogério Pontes 2015-License : WTFPL-Maintainer : rogerp62@outlook.com-Stability : stable--This module contains some auxiliar parsers, used to parse commands or responses.--}-module Smtlib.Parsers.CommonParsers where---{-- In the String terminal, it does not parse C-style characters.- Quoted Symbol does not parse all printable ASCII characters.--}--import Control.Applicative as Ctr hiding ((<|>))-import Data.Functor.Identity-import qualified Data.Set as Set-import Text.Parsec.Prim as Prim-import Text.ParserCombinators.Parsec as Pc-import Smtlib.Syntax.Syntax-import Control.Monad--(<:>) :: Applicative f => f a -> f [a] -> f [a]-(<:>) a b = (:) <$> a <*> b--(<++>) :: Applicative f => f [a] -> f [a] -> f [a]-(<++>) a b = (++) <$> a <*> b--parseBool :: ParsecT String u Identity Bool-parseBool = (true *> return True) <|> (false *> return False)----- Parse a Numeral--numeral :: ParsecT String u Identity String-numeral = many1 digit--num :: ParsecT String u Identity String-num = Pc.many digit--- Parse a decimal--decimal :: ParsecT String u Identity String-decimal = numeral <++> dot <++> Pc.try zeros <++> num--zeros :: ParsecT String u Identity String-zeros = Pc.many $ char '0'---dot :: ParsecT String u Identity String-dot = string "."---- parse a Hexadecimal--hexadecimal :: ParsecT String u Identity String-hexadecimal = string "#x" *> many1 hexDigit-----parsea a Binary-binary :: ParsecT String u Identity String-binary = string "#b" *> many1 bin--bin :: ParsecT String u Identity Char-bin = char '0' <|> char '1'-----parse a String--- Dosent parse strings with escape characters-str :: ParsecT String u Identity String-str = string "\"" <++> liftM concat (Pc.many (liftM (\c -> [c]) strChar <|> Pc.try (string "\"\""))) <++> string "\""--strChar :: ParsecT String u Identity Char-strChar = (oneOf $ ['\t','\n','\r'] ++ [c | c <- [toEnum 32 .. toEnum 126], c /= '"']) <|> satisfy (toEnum 128 <=)-----parse a Symbol-symbol :: ParsecT String u Identity String-symbol = symbol' reservedWordsSet--symbol' :: Set.Set String -> ParsecT String u Identity String-symbol' reserved = simpleSymbol' reserved <|> quotedSymbol--quotedSymbol :: ParsecT String u Identity String-quotedSymbol = char '|' *> Pc.many (noneOf "|") <* char '|'--simpleSymbol :: ParsecT String u Identity String-simpleSymbol = simpleSymbol' reservedWordsSet--simpleSymbol' :: Set.Set String -> ParsecT String u Identity String-simpleSymbol' reserved = Pc.try $ do- s <- (letter <|> spcSymb) <:> sq- guard $ s `Set.notMember` reserved- return s- where- sq = Pc.many (alphaNum <|> spcSymb)--spcSymb :: ParsecT String u Identity Char-spcSymb = oneOf "+-/*=%?!.$_~^&<>@"---- parse a key word-keyword :: ParsecT String u Identity String-keyword = char ':' <:> Pc.many (alphaNum<|> spcSymb)---aspO :: ParsecT String u Identity Char-aspO = char '('--aspC :: ParsecT String u Identity Char-aspC = char ')'--aspUS :: ParsecT String u Identity Char-aspUS = char '_'---true :: ParsecT String u Identity String-true = string "true"--false :: ParsecT String u Identity String-false = string "false"---emptySpace :: ParsecT String u Identity String-emptySpace = liftM concat $ Pc.try $ Pc.many emptySpaceSingle--emptySpace1 :: ParsecT String u Identity String-emptySpace1 = liftM concat $ Pc.try $ Pc.many1 emptySpaceSingle--emptySpaceSingle :: ParsecT String u Identity String-emptySpaceSingle = liftM (\c -> [c]) (char ' ' <|> char '\n' <|> char '\t' <|> char '\r') <|> comment--comment :: ParsecT String u Identity String-comment = char ';' <:> scan- where- scan = do{ c <- char '\n' <|> char '\r'; return [c] }- <|>- do{ c <- anyChar; cs <- scan; return (c:cs) }--reservedWords :: ParsecT String u Identity String-reservedWords = string "let"- <|> string "par"- <|> string "_"- <|> string "!"- <|> string "as"- <|> string "forall"- <|> string "exists"- <|> string "NUMERAL"- <|> string "DECIMAL"- <|> string "STRING"-----{-- #########################################################################- # #- # Parsers for Terms #- # #- #########################################################################--}----- Term-parseTerm :: ParsecT String u Identity Term-parseTerm = parseTSPC- <|> Pc.try parseTQID- <|> Pc.try parseTQIT- <|> Pc.try parseTermLet- <|> Pc.try parseTermFA- <|> Pc.try parseTermEX- <|> parseTermAnnot--parseTSPC :: ParsecT String u Identity Term-parseTSPC = liftM TermSpecConstant parseSpecConstant--parseTQID :: ParsecT String u Identity Term-parseTQID = liftM TermQualIdentifier parseQualIdentifier--parseTQIT :: ParsecT String u Identity Term-parseTQIT = do- _ <- aspO- _ <- emptySpace- iden <- parseQualIdentifier- _ <- emptySpace- terms <- Pc.many $ parseTerm <* Pc.try emptySpace- _ <- aspC- return $ TermQualIdentifierT iden terms--parseTermLet :: ParsecT String u Identity Term-parseTermLet = do- _ <- aspO- _ <- emptySpace- _ <- string "let"- _ <- emptySpace- _ <- aspO- _ <- emptySpace- vb <- Pc.many $ parseVarBinding <* Pc.try emptySpace- _ <- aspC- _ <- emptySpace- term <- parseTerm- _ <- emptySpace- _ <- aspC- return $ TermLet vb term--parseTermFA :: ParsecT String u Identity Term-parseTermFA = do- _ <- aspO- _ <- emptySpace- _ <- string "forall"- _ <- emptySpace- _ <- aspO- sv <- Pc.many $ parseSortedVar <* Pc.try emptySpace- _ <- aspC- _ <- emptySpace- term <- parseTerm- _ <- emptySpace- _ <- aspC- return $ TermForall sv term---parseTermEX :: ParsecT String u Identity Term-parseTermEX = do- _ <- aspO- _ <- emptySpace- _ <- string "exists"- _ <- emptySpace- _ <- aspO- sv <- Pc.many $ parseSortedVar <* Pc.try emptySpace- _ <- aspC- _ <- emptySpace- term <- parseTerm- _ <- emptySpace- _ <- aspC- return $ TermExists sv term--parseTermAnnot :: ParsecT String u Identity Term-parseTermAnnot = do- _ <- aspO- _ <- emptySpace- _ <- char '!'- _ <- emptySpace- term <- parseTerm- _ <- emptySpace- attr <- Pc.many $ parseAttribute <* Pc.try emptySpace- _ <- aspC- return $ TermAnnot term attr----- -- Parse Sorted Var-parseSortedVar :: ParsecT String u Identity SortedVar-parseSortedVar = do- _ <- aspO- _ <- emptySpace- symb <- symbol- _ <- emptySpace- sort <- parseSort- _ <- emptySpace- _ <- aspC- return $ SV symb sort---- -- Parse Qual identifier-parseQualIdentifier :: ParsecT String u Identity QualIdentifier-parseQualIdentifier = Pc.try parseQID <|> parseQIAs--parseQID :: ParsecT String u Identity QualIdentifier-parseQID = liftM QIdentifier parseIdentifier-----parseQIAs :: ParsecT String u Identity QualIdentifier-parseQIAs = do- _ <- aspO- _ <- emptySpace- _ <- string "as"- _ <- emptySpace1- ident <- parseIdentifier- _ <- emptySpace- sort <- parseSort- _ <- emptySpace- _ <- aspC- return $ QIdentifierAs ident sort----- -- Parse Var Binding-parseVarBinding :: ParsecT String u Identity VarBinding-parseVarBinding = do- _ <- aspO- _ <- emptySpace- symb <- symbol- _ <- emptySpace- term <- parseTerm- _ <- emptySpace- _ <- aspC- return $ VB symb term------{-- #########################################################################- # #- # Parsers for Attributes #- # #- #########################################################################--}----Parse Attribute Value-parseAttributeValue :: ParsecT String u Identity AttrValue-parseAttributeValue = parseAVSC <|> parseAVS <|> parseAVSexpr--parseAVSC :: ParsecT String u Identity AttrValue-parseAVSC = liftM AttrValueConstant parseSpecConstant--parseAVS :: ParsecT String u Identity AttrValue-parseAVS = liftM AttrValueSymbol symbol--parseAVSexpr :: ParsecT String u Identity AttrValue-parseAVSexpr = do- _ <- aspO- _ <- emptySpace- expr <- Pc.many $ parseSexpr <* Pc.try emptySpace- _ <- aspC- return $ AttrValueSexpr expr------ Parse Attribute--parseAttribute :: ParsecT String u Identity Attribute-parseAttribute = Pc.try parseKeyAttAttribute <|> parseKeyAttribute---parseKeyAttribute :: ParsecT String u Identity Attribute-parseKeyAttribute = liftM Attribute keyword--parseKeyAttAttribute :: ParsecT String u Identity Attribute-parseKeyAttAttribute = do- kw <- keyword- _ <- emptySpace- atr <- parseAttributeValue- return $ AttributeVal kw atr---{-- #########################################################################- # #- # Parsers Sort #- # #- #########################################################################--}---- Parse Sot--parseSort :: ParsecT String u Identity Sort-parseSort = Pc.try parseIdentifierS <|> parseIdentifierSort--parseIdentifierS :: ParsecT String u Identity Sort-parseIdentifierS = liftM SortId parseIdentifier--parseIdentifierSort :: ParsecT String u Identity Sort-parseIdentifierSort = do- _ <- aspO- _ <- emptySpace- identifier <- parseIdentifier- _ <- emptySpace- sorts <- many1 (parseSort <* Pc.try emptySpace)- _ <- aspC- return $ SortIdentifiers identifier sorts-----{-- #########################################################################- # #- # Parsers Identifiers #- # #- #########################################################################--}----- Parse Identifiers--parseIdentifier :: ParsecT String u Identity Identifier-parseIdentifier = parseOnlySymbol <|> parseNSymbol--parseOnlySymbol :: ParsecT String u Identity Identifier-parseOnlySymbol = liftM ISymbol symbol--parseNSymbol :: ParsecT String u Identity Identifier-parseNSymbol = do- _ <- aspO- _ <- emptySpace- _ <- aspUS- _ <- emptySpace1- symb <- symbol- _ <- emptySpace- indexes <- many1 ((liftM (IndexNumeral . read) numeral <|> liftM IndexSymbol symbol) <* Pc.try spaces)- _ <- aspC- return $ I_Symbol symb indexes--{-- #########################################################################- # #- # Parsers S-exprs #- # #- #########################################################################--}----- parse S-expressions--parseSexprConstant :: ParsecT String u Identity Sexpr-parseSexprConstant = liftM SexprSpecConstant parseSpecConstant--parseSexprSymbol :: ParsecT String u Identity Sexpr-parseSexprSymbol = liftM SexprSymbol (symbol' Set.empty)--parseSexprKeyword :: ParsecT String u Identity Sexpr-parseSexprKeyword = liftM SexprKeyword keyword--parseAtomSexpr :: ParsecT String u Identity Sexpr-parseAtomSexpr = parseSexprConstant- <|> parseSexprSymbol- <|> parseSexprKeyword---parseListSexpr :: ParsecT String u Identity Sexpr-parseListSexpr = do- _ <- aspO- list <- Pc.many parseSexpr- _ <- aspC- return $ SexprSxp list----parseSexpr :: ParsecT String u Identity Sexpr-parseSexpr = do- _ <- emptySpace- expr <- parseAtomSexpr <|> parseListSexpr- _ <- emptySpace- return expr------ parse Spec Constant-parseSpecConstant :: ParsecT String u Identity SpecConstant-parseSpecConstant = Pc.try parseDecimal- <|> parseNumeral- <|> Pc.try parseHexadecimal- <|> parseBinary- <|> parseString----parseNumeral :: ParsecT String u Identity SpecConstant-parseNumeral = liftM SpecConstantNumeral (read <$> numeral)--parseDecimal :: ParsecT String u Identity SpecConstant-parseDecimal = liftM SpecConstantDecimal decimal--parseHexadecimal :: ParsecT String u Identity SpecConstant-parseHexadecimal = liftM SpecConstantHexadecimal hexadecimal--parseBinary :: ParsecT String u Identity SpecConstant-parseBinary = liftM SpecConstantBinary binary--parseString :: ParsecT String u Identity SpecConstant-parseString = liftM SpecConstantString str
− Smtlib/Smtlib/Parsers/ResponseParsers.hs
@@ -1,375 +0,0 @@-{-|-Module : Smtlib.Parsers.ResponseParsers-Description : Parsers for Smtlib commands response.-Copyright : Rogério Pontes 2015-License : WTFPL-Maintainer : rogerp62@outlook.com-Stability : stable--This module contains all the required individual parsers for each reasponse to -a Smtlib command, plus one parser to parse every result, parseCmdResult.---}--module Smtlib.Parsers.ResponseParsers where--import Control.Applicative as Ctr hiding ((<|>))-import Control.Monad-import Data.Functor.Identity-import Smtlib.Parsers.CommonParsers-import Smtlib.Parsers.CommandsParsers-import Smtlib.Syntax.Syntax as CmdRsp-import Text.Parsec.Prim as Prim-import Text.ParserCombinators.Parsec as Pc----parseCmdResult :: ParsecT String u Identity CmdResponse-parseCmdResult = Pc.try parseCmdGenResponse- <|> Pc.try parseCmdCheckSatResponse- <|> Pc.try parseCmdGetInfoResponse- <|> Pc.try parseCmdGetAssertions- <|> Pc.try parseCmdGetAssignment- <|> Pc.try parseCmdGetProof- <|> Pc.try parseCmdGetProof- <|> Pc.try parseCmdGetValueResponse- <|> Pc.try parseCmdGetModelResponse- <|> Pc.try parseCmdGetOptionResponse- <|> Pc.try parseCmdEchoResponse--{-- #########################################################################- # #- # Parser Cmd Gen Response #- # #- #########################################################################--}--parseCmdGenResponse :: ParsecT String u Identity CmdResponse-parseCmdGenResponse = liftM CmdGenResponse parseGenResponse--parseGenResponse :: ParsecT String u Identity GenResponse-parseGenResponse = parseUnsupported <|> parseSuccess <|> parseGenError--parseSuccess :: ParsecT String u Identity GenResponse-parseSuccess = string "success" *> return Success--parseUnsupported :: ParsecT String u Identity GenResponse-parseUnsupported = string "unsupported" *> return Unsupported---parseGenError :: ParsecT String u Identity GenResponse-parseGenError = do- _ <- aspO- _ <- emptySpace- _ <- string "error"- _ <- emptySpace- err <- str- _ <- emptySpace- _ <- aspC- return $ CmdRsp.Error err-------{-- #########################################################################- # #- # Parser get info response #- # #- #########################################################################--}--parseCmdGetInfoResponse :: ParsecT String u Identity CmdResponse-parseCmdGetInfoResponse = liftM CmdGetInfoResponse parseGetInfoResponse---parseGetInfoResponse :: ParsecT String u Identity [InfoResponse]-parseGetInfoResponse = do- _ <-aspO- _ <- emptySpace- infoResp <- Pc.many $ parseInfoResponse <* Pc.try emptySpace- _ <- aspC- return infoResp----parseInfoResponse :: ParsecT String u Identity InfoResponse-parseInfoResponse =- Pc.try parseResponseName <|>- Pc.try parseResponseErrorBehavior <|>- Pc.try parseResponseAuthors <|>- Pc.try parseResponseVersion <|>- Pc.try parseResponseReasonUnknown <|>- Pc.try parseResponseAssertionStackLevels <|>- parseResponseAttribute-----parseResponseName :: ParsecT String u Identity InfoResponse-parseResponseName = string ":name" *> emptySpace *> liftM ResponseName str---parseResponseErrorBehavior :: ParsecT String u Identity InfoResponse-parseResponseErrorBehavior = string ":error-behavior" *> emptySpace *>- liftM ResponseErrorBehavior parseErrorBehavior--parseErrorBehavior :: ParsecT String u Identity ErrorBehavior-parseErrorBehavior =- (string "immediate-exit" >> return ImmediateExit) <|>- (string "continued-execution" >> return ContinuedExecution)---parseResponseAuthors :: ParsecT String u Identity InfoResponse-parseResponseAuthors = string ":authors" *> emptySpace *>- liftM ResponseAuthors str--parseResponseVersion :: ParsecT String u Identity InfoResponse-parseResponseVersion = string ":version" *> emptySpace *>- liftM ResponseVersion str----parseResponseReasonUnknown :: ParsecT String u Identity InfoResponse-parseResponseReasonUnknown = string ":reason-unknown" *> emptySpace *>- liftM ResponseReasonUnknown parseRReasonUnknown--parseRReasonUnknown :: ParsecT String u Identity ReasonUnknown-parseRReasonUnknown =- (string "memout" >> return Memout) <|>- (string "incomplete" >> return Incomplete)--parseResponseAssertionStackLevels :: ParsecT String u Identity InfoResponse-parseResponseAssertionStackLevels =- string ":assertion-stack-levels" *> emptySpace *>- liftM ResponseAssertionStackLevels (liftM read numeral)---parseResponseAttribute :: ParsecT String u Identity InfoResponse-parseResponseAttribute = liftM ResponseAttribute parseAttribute--------{-- #########################################################################- # #- # Parser check sat response #- # #- #########################################################################--}----parseCmdCheckSatResponse :: ParsecT String u Identity CmdResponse-parseCmdCheckSatResponse = liftM CmdCheckSatResponse parseCheckSatResponse------ Parser for check sat response-parseCheckSatResponse :: ParsecT String u Identity CheckSatResponse-parseCheckSatResponse =- (string "sat" >> return Sat) <|>- Pc.try (string "unsat" >> return Unsat) <|>- (string "unknown" >> return Unknown)-----{-- #########################################################################- # #- # Parser get assertions cmd #- # #- #########################################################################--}---parseCmdGetAssertions :: ParsecT String u Identity CmdResponse-parseCmdGetAssertions =- liftM CmdGetAssertionsResponse parseGetAssertionsResponse------ parse Get Assertion Response-parseGetAssertionsResponse :: ParsecT String u Identity [Term]-parseGetAssertionsResponse = do- _ <- aspO- _ <- emptySpace- terms <- Pc.many $ parseTerm <* Pc.try emptySpace- _ <- aspC- return terms--{-- #########################################################################- # #- # Parser get proof response #- # #- #########################################################################--}---parseCmdGetProof :: ParsecT String u Identity CmdResponse-parseCmdGetProof = liftM CmdGetProofResponse parseGetProofResponse---- parse Get Proof response-parseGetProofResponse :: ParsecT String u Identity Sexpr-parseGetProofResponse = parseSexpr----{-- #########################################################################- # #- # Parser get unsat core response #- # #- #########################################################################--}---parseCmdGetUnsatCore :: ParsecT String u Identity CmdResponse-parseCmdGetUnsatCore = liftM CmdGetUnsatCoreResponse parseGetUnsatCoreResp----- parse Get unsat core response-parseGetUnsatCoreResp :: ParsecT String u Identity [String]-parseGetUnsatCoreResp = do- _ <- aspO- _ <- emptySpace- symb <- Pc.many $ symbol <* Pc.try emptySpace- _ <- aspC- return symb---{-- #########################################################################- # #- # Parser Cmd Get value response #- # #- #########################################################################--}---parseCmdGetValueResponse :: ParsecT String u Identity CmdResponse-parseCmdGetValueResponse = liftM CmdGetValueResponse parseGetValueResponse------ parse Get Value response-parseGetValueResponse :: ParsecT String u Identity [ValuationPair]-parseGetValueResponse =- aspO *> (Pc.many $ parseValuationPair <* Pc.try emptySpace) <* aspC--parseValuationPair :: ParsecT String u Identity ValuationPair-parseValuationPair = do- _ <- aspO- _ <- emptySpace- term1 <- parseTerm- _ <- emptySpace- term2 <- parseTerm- _ <- emptySpace- _ <- aspC- return $ ValuationPair term1 term2---{-- #########################################################################- # #- # Parser Cmd get assignment Resp #- # #- #########################################################################--}---parseCmdGetAssignment :: ParsecT String u Identity CmdResponse-parseCmdGetAssignment = liftM CmdGetAssignmentResponse parseGetAssignmentResp---- parse get Assignent Response-parseGetAssignmentResp :: ParsecT String u Identity [TValuationPair]-parseGetAssignmentResp = do- _ <- aspO- _ <- emptySpace- pairs <- Pc.many $ parseTValuationPair <* Pc.try emptySpace- _ <- aspC- return pairs---- parse t valuation pair-parseTValuationPair :: ParsecT String u Identity TValuationPair-parseTValuationPair = do- _ <- aspO- _ <- emptySpace- symb <- symbol- _ <- emptySpace- bval <- parseBool- _ <- emptySpace- _ <-aspC- return $ TValuationPair symb bval---{-- #########################################################################- # #- # Parser Cmd Get model response #- # #- #########################################################################--}---parseCmdGetModelResponse :: ParsecT String u Identity CmdResponse-parseCmdGetModelResponse = liftM CmdGetModelResponse parseGetModelResponse------ parse Get Model response-parseGetModelResponse :: ParsecT String u Identity [Command]-parseGetModelResponse =- aspO *> (Pc.many $ parseCommand <* Pc.try emptySpace) <* aspC---{-- #########################################################################- # #- # Parser Cmd get option response #- # #- #########################################################################--}---parseCmdGetOptionResponse :: ParsecT String u Identity CmdResponse-parseCmdGetOptionResponse = liftM CmdGetOptionResponse parseGetOptionResponse----- parse Get Option Response-parseGetOptionResponse :: ParsecT String u Identity AttrValue-parseGetOptionResponse = parseAttributeValue--{-- #########################################################################- # #- # Parser Cmd get option response #- # #- #########################################################################--}---parseCmdEchoResponse :: ParsecT String u Identity CmdResponse-parseCmdEchoResponse = liftM CmdEchoResponse parseEchoResponse----- parse Echo Response-parseEchoResponse :: ParsecT String u Identity EchoResponse-parseEchoResponse = str--{-- #########################################################################- # #- # Parser check-sat Alterg'os response #- # #- #########################################################################--}
− Smtlib/Smtlib/Syntax/ShowSL.hs
@@ -1,247 +0,0 @@-{-|-Module : Smtlib.Syntax.ShowSL-Description : Instance to print the syntax.-Copyright : Rogério Pontes 2015-License : WTFPL-Maintainer : rogerp62@outlook.com-Stability : stable--Functions to print the syntax as a SMTLib.---}-module Smtlib.Syntax.ShowSL where--import Data.Char-import qualified Data.Set as Set-import Data.List-import Smtlib.Syntax.Syntax------joinA ::(ShowSL a) => [a] -> String-joinA = unwords.fmap showSL--joinNs :: [Int] -> String-joinNs = unwords.fmap show--showSymbol :: String -> String-showSymbol = showSymbol' reservedWordsSet--showSymbol' :: Set.Set String -> String -> String-showSymbol' reserved s- | c:_ <- s, isDigit c = quoted- | all p s && s `Set.notMember` reserved = s- | otherwise = quoted- where- quoted = "|" ++ s ++ "|"- p c = (isAscii c && isAlpha c) || isDigit c || c `elem` "~!@$%^&*_-+=<>.?/"--class ShowSL a where- showSL :: a -> String----{-- #########################################################################- # #- # ShowSL for an SMTLib2 File #- # #- #########################################################################--}---instance ShowSL Command where- showSL (SetLogic s) = "(set-logic " ++ showSymbol s ++ ")"- showSL (SetOption opt) = "(set-option " ++ showSL opt ++ ")"- showSL (SetInfo info) = "(set-info " ++ showSL info ++ ")"- showSL (DeclareSort str val) = "(declare-sort " ++ showSymbol str ++- " " ++ show val ++ ")"- showSL (DefineSort str strs sort) = "(define-sort " ++ showSymbol str ++- " (" ++ unwords (map showSymbol strs) ++ ") " ++ showSL sort ++ ") "- showSL (DeclareConst str sort) = "(declare-const " ++ showSymbol str ++- " " ++ showSL sort ++ ") "- showSL (DeclareFun str sorts sort) = "(declare-fun " ++ showSymbol str ++- " (" ++ joinA sorts ++ ") " ++ showSL sort ++ ") "- showSL (DefineFun str srvs sort term) = "(define-fun " ++ showSymbol str ++- " (" ++ joinA srvs ++ ") " ++ showSL sort ++ " " ++ showSL term ++ ")"- showSL (DefineFunRec str srvs sort term) = "(define-fun-rec " ++ showSymbol str ++- " (" ++ joinA srvs ++ ") " ++ showSL sort ++ " " ++ showSL term ++ ")"- showSL (DefineFunsRec fundecs terms) = "(define-funs-rec " ++- " (" ++ joinA fundecs ++ ") (" ++ joinA terms ++ "))"- showSL (Push n) = "(push " ++ show n ++ ")"- showSL (Pop n) = "(pop " ++show n ++ ")"- showSL (Assert term) = "(assert " ++ showSL term ++ ")"- showSL CheckSat = "(check-sat)"- showSL (CheckSatAssuming terms) = "(check-sat-assuming (" ++ joinA terms ++ "))"- showSL GetAssertions = "(get-assertions)"- showSL GetModel = "(get-model)"- showSL GetProof = "(get-proof)"- showSL GetUnsatCore = "(get-unsat-core)"- showSL GetUnsatAssumptions = "(get-unsat-assumptions)"- showSL (GetValue terms) = "(get-value (" ++ joinA terms ++ "))"- showSL GetAssignment = "(get-assignment)"- showSL (GetOption opt) = "(get-option " ++ opt ++ ")"- showSL (GetInfo info) = "(get-info " ++ showSL info ++ ")"- showSL Reset = "(reset)"- showSL ResetAssertions = "(reset-assertions)"- showSL (Echo str) = "(echo " ++ str ++ ")"- showSL Exit = "(exit)"---instance ShowSL Bool where- showSL True = "true"- showSL False = "false"--instance ShowSL Option where- showSL (PrintSuccess b) = ":print-success " ++ showSL b- showSL (ExpandDefinitions b) = ":expand-definitions " ++ showSL b- showSL (InteractiveMode b) = ":interactive-mode " ++ showSL b- showSL (ProduceProofs b) = ":produce-proofs " ++ showSL b- showSL (ProduceUnsatCores b) = ":produce-unsat-cores " ++ showSL b- showSL (ProduceUnsatAssumptions b) = ":produce-unsat-assumptions " ++ showSL b- showSL (ProduceModels b) = ":produce-models " ++ showSL b- showSL (ProduceAssignments b) = ":produce-assignments " ++ showSL b- showSL (ProduceAssertions b) = ":produce-assertions " ++ showSL b- showSL (GlobalDeclarations b) = ":global-declarations " ++ showSL b- showSL (RegularOutputChannel s) = ":regular-output-channel " ++ s- showSL (DiagnosticOutputChannel s) = ":diagnostic-output-channel " ++ s- showSL (RandomSeed n) = ":random-seed " ++ show n- showSL (Verbosity n) = ":verbosity " ++ show n- showSL (ReproducibleResourceLimit n) = ":reproducible-resource-limit " ++ show n- showSL (OptionAttr attr) = showSL attr--instance ShowSL InfoFlags where- showSL ErrorBehavior = ":error-behavior"- showSL Name = ":name"- showSL Authors = ":authors"- showSL Version = ":version"- showSL Status = ":status"- showSL ReasonUnknown = ":reason-unknown"- showSL AllStatistics = ":all-statistics"- showSL AssertionStackLevels = ":assertion-stack-levels"- showSL (InfoFlags s) = s---instance ShowSL Term where- showSL (TermSpecConstant sc) = showSL sc- showSL (TermQualIdentifier qi) = showSL qi- showSL (TermQualIdentifierT qi terms) =- "(" ++ showSL qi ++ " " ++ joinA terms ++ ")"- showSL (TermLet vb term) =- "(let (" ++ joinA vb ++ ") " ++ showSL term ++ ")"- showSL (TermForall svs term) =- "(forall (" ++ joinA svs ++ " ) " ++ showSL term ++ ")"- showSL (TermExists svs term) =- "(exists (" ++ joinA svs ++ " ) " ++ showSL term ++ ")"- showSL (TermAnnot term atts) =- "(! " ++ showSL term ++ " " ++ joinA atts ++ ")"--instance ShowSL VarBinding where- showSL (VB str term) = "("++ showSymbol str ++ " " ++ showSL term ++ ")"--instance ShowSL SortedVar where- showSL (SV str sort) = "(" ++ showSymbol str ++ " " ++ showSL sort ++ ")"--instance ShowSL QualIdentifier where- showSL (QIdentifier iden) = showSL iden- showSL (QIdentifierAs iden sort) =- "(as " ++ showSL iden ++ " " ++ showSL sort ++ ")"--instance ShowSL FunDec where- showSL (FunDec str srvs sort) =- "(" ++ showSymbol str ++ " (" ++ joinA srvs ++ ") " ++ showSL sort ++ ")"--instance ShowSL AttrValue where- showSL (AttrValueConstant spc) = showSL spc- showSL (AttrValueSymbol str) = showSymbol str- showSL (AttrValueSexpr sexprs) = "(" ++ joinA sexprs ++ ")"--instance ShowSL Attribute where- showSL (Attribute str) = str- showSL (AttributeVal str attrVal) = str ++ " " ++ showSL attrVal--instance ShowSL Index where- showSL (IndexNumeral i) = show i- showSL (IndexSymbol str) = showSymbol str--instance ShowSL Identifier where- showSL (ISymbol str) = showSymbol str- showSL (I_Symbol str is) = "(_ " ++ showSymbol str ++ " " ++ joinA is ++ ")"--instance ShowSL Sort where- showSL (SortId iden) = showSL iden- showSL (SortIdentifiers iden sorts) =- "(" ++ showSL iden ++ " " ++ joinA sorts ++ ")"--instance ShowSL SpecConstant where- showSL (SpecConstantNumeral n) = show n- showSL (SpecConstantDecimal str) = str- showSL (SpecConstantHexadecimal str) = "#x" ++ str- showSL (SpecConstantBinary str) = "#b" ++ str- showSL (SpecConstantString str) = str--instance ShowSL Sexpr where- showSL (SexprSpecConstant sc) = showSL sc- showSL (SexprSymbol str) = showSymbol' Set.empty str- showSL (SexprKeyword str) = str- showSL (SexprSxp srps) = "(" ++ joinA srps ++ ")"---{-- #########################################################################- # #- # Command Response #- # #- #########################################################################--}--instance ShowSL CmdResponse where- showSL (CmdGenResponse x) = showSL x- showSL (CmdGetInfoResponse x) = "(" ++ joinA x ++ ")"- showSL (CmdCheckSatResponse x) = showSL x- showSL (CmdGetAssertionsResponse x) = "(" ++ joinA x ++ ")"- showSL (CmdGetAssignmentResponse x) = "(" ++ joinA x ++ ")"- showSL (CmdGetProofResponse x) = showSL x- showSL (CmdGetUnsatCoreResponse x) = "(" ++ unwords (map showSymbol x) ++ ")"- showSL (CmdGetUnsatAssumptionsResponse terms) = "(" ++ joinA terms ++ ")"- showSL (CmdGetValueResponse x) = "(" ++ joinA x ++ ")"- showSL (CmdGetModelResponse cmds) = "(" ++ joinA cmds ++ ")"- showSL (CmdGetOptionResponse x) = showSL x- showSL (CmdEchoResponse x) = x---instance ShowSL GenResponse where- showSL Unsupported = "unsupported"- showSL Success = "success"- showSL (Error s) = "(error " ++ s ++ ")"--instance ShowSL ErrorBehavior where- showSL ImmediateExit = "immediate-exit"- showSL ContinuedExecution = "continued-execution"--instance ShowSL ReasonUnknown where- showSL Memout = "memout"- showSL Incomplete = "incomplete"--instance ShowSL CheckSatResponse where- showSL Sat = "sat"- showSL Unsat = "unsat"- showSL Unknown = "unknown"--instance ShowSL InfoResponse where- showSL (ResponseErrorBehavior x) = ":error-behavior " ++ showSL x- showSL (ResponseName s) = ":name " ++ s- showSL (ResponseAuthors s) = ":authors " ++ s- showSL (ResponseVersion s) = ":version" ++ s- showSL (ResponseReasonUnknown x) = ":reason-unknown " ++ showSL x- showSL (ResponseAssertionStackLevels n) = ":assertion-stack-levels " ++ show n- showSL (ResponseAttribute x) = showSL x--instance ShowSL ValuationPair where- showSL (ValuationPair term1 term2) =- "(" ++ showSL term1 ++ " " ++ showSL term2 ++ ")"--instance ShowSL TValuationPair where- showSL (TValuationPair str b) = "(" ++ showSymbol str ++ " " ++ showSL b ++ ")"
− Smtlib/Smtlib/Syntax/Syntax.hs
@@ -1,279 +0,0 @@-{-|-Module : Smtlib.Parsers.CommandsParsers-Description : Smtlib Syntax-Copyright : Rogério Pontes 2015-License : WTFPL-Maintainer : rogerp62@outlook.com-Stability : stable--This module contains The syntax to create commands and responses.---}-module Smtlib.Syntax.Syntax where--import qualified Data.Set as Set--{-- #########################################################################- # #- # Parser for an SMTLib2 File #- # #- #########################################################################--}--reservedWordsSet :: Set.Set String-reservedWordsSet = Set.fromList $- ["BINARY", "DECIMAL", "HEXADECIMAL", "NUMERAL", "STRING", "_", "!", "as", "let", "exists", "forall", "par"] ++- ["set-logic", "set-option", "set-info", "declare-sort", "define-sort", "declare-const", "declare-fun", "declare-fun-rec", "declare-funs-rec", "push", "pop", "reset", "reset-assertions", "assert", "check-sat", "check-sat-assuming", "get-assertions", "get-model", "get-proof", "get-unsat-core", "get-unsat-assumptions", "get-value", "get-assignment", "get-option", "get-info", "echo", "exit"]---type Source = [Command]---data Command = SetLogic String- | SetOption Option- | SetInfo Attribute- | DeclareSort String Int- | DefineSort String [String] Sort- | DeclareConst String Sort- | DeclareFun String [Sort] Sort- | DefineFun String [SortedVar] Sort Term- | DefineFunRec String [SortedVar] Sort Term- | DefineFunsRec [FunDec] [Term]- | Push Int- | Pop Int- | Reset- | ResetAssertions- | Assert Term- | CheckSat- | CheckSatAssuming [Term]- | GetAssertions- | GetModel- | GetProof- | GetUnsatCore- | GetUnsatAssumptions- | GetValue [Term]- | GetAssignment- | GetOption String- | GetInfo InfoFlags- | Echo String- | Exit- deriving (Show,Eq)--data Option = PrintSuccess Bool- | ExpandDefinitions Bool- | InteractiveMode Bool- | ProduceProofs Bool- | ProduceUnsatCores Bool- | ProduceUnsatAssumptions Bool- | ProduceModels Bool- | ProduceAssignments Bool- | ProduceAssertions Bool- | GlobalDeclarations Bool- | RegularOutputChannel String- | DiagnosticOutputChannel String- | RandomSeed Int- | Verbosity Int- | ReproducibleResourceLimit Int -- fixme- | OptionAttr Attribute- deriving (Show,Eq)---data InfoFlags = ErrorBehavior- | Name- | Authors- | Version- | Status- | ReasonUnknown- | AllStatistics- | AssertionStackLevels- | InfoFlags String- deriving (Show,Eq)---- Terms--data Term = TermSpecConstant SpecConstant- | TermQualIdentifier QualIdentifier- | TermQualIdentifierT QualIdentifier [Term]- | TermLet [VarBinding] Term- | TermForall [SortedVar] Term- | TermExists [SortedVar] Term- | TermAnnot Term [Attribute]- deriving (Show,Eq)----data VarBinding = VB String Term deriving (Show,Eq)----data SortedVar = SV String Sort deriving (Show,Eq)----data QualIdentifier = QIdentifier Identifier- | QIdentifierAs Identifier Sort- deriving (Show,Eq)---data FunDec = FunDec String [SortedVar] Sort deriving (Show,Eq)-------- Attributes--data AttrValue = AttrValueConstant SpecConstant- | AttrValueSymbol String- | AttrValueSexpr [Sexpr]- deriving (Show,Eq)----data Attribute = Attribute String- | AttributeVal String AttrValue- deriving (Show,Eq)---- Identifiers--data Index = IndexNumeral Int- | IndexSymbol String- deriving (Show,Eq)--data Identifier = ISymbol String- | I_Symbol String [Index] deriving (Show,Eq)---- Sorts--data Sort = SortId Identifier | SortIdentifiers Identifier [Sort]- deriving (Show,Eq)----- S-expressions-data SpecConstant = SpecConstantNumeral Integer- | SpecConstantDecimal String- | SpecConstantHexadecimal String- | SpecConstantBinary String- | SpecConstantString String- deriving (Show, Eq)----data Sexpr = SexprSpecConstant SpecConstant- | SexprSymbol String- | SexprKeyword String- | SexprSxp [Sexpr]- deriving (Show, Eq)----------{-- #########################################################################- # #- # Command Response #- # #- #########################################################################--}------ CmdResponse--data CmdResponse = CmdGenResponse GenResponse- | CmdGetInfoResponse GetInfoResponse- | CmdCheckSatResponse CheckSatResponse- | CmdGetAssertionsResponse GetAssertionsResponse- | CmdGetAssignmentResponse GetAssignmentResponse- | CmdGetProofResponse GetProofResponse- | CmdGetUnsatCoreResponse GetUnsatCoreResponse- | CmdGetUnsatAssumptionsResponse GetUnsatAssumptionsResponse- | CmdGetValueResponse GetValueResponse- | CmdGetModelResponse GetModelResponse- | CmdGetOptionResponse GetOptionResponse- | CmdEchoResponse EchoResponse- deriving (Show, Eq)----- Command Responses----- Gen Response--data GenResponse = Unsupported | Success | Error String deriving (Show, Eq)----- Error behavior--data ErrorBehavior = ImmediateExit | ContinuedExecution deriving (Show, Eq)----- Reason unknown--data ReasonUnknown = Memout | Incomplete deriving (Show, Eq)---- Status--data CheckSatResponse = Sat | Unsat | Unknown deriving (Show, Eq)---- Info Response--type GetInfoResponse = [InfoResponse]--data InfoResponse = ResponseErrorBehavior ErrorBehavior- | ResponseName String- | ResponseAuthors String- | ResponseVersion String- | ResponseReasonUnknown ReasonUnknown- | ResponseAssertionStackLevels Int- | ResponseAttribute Attribute- deriving (Show, Eq)---- Get Assertion Response--type GetAssertionsResponse = [Term]----- Get Proof Response--type GetProofResponse = Sexpr-----Get Unsat Core Response--type GetUnsatCoreResponse = [String]---- Get Unsat Assumptions Response--type GetUnsatAssumptionsResponse = [Term]---- Get Valuation Pair--data ValuationPair = ValuationPair Term Term deriving (Show, Eq)---type GetValueResponse = [ValuationPair]--type GetModelResponse = [Command]----- get Assignment Response--data TValuationPair = TValuationPair String Bool deriving (Show, Eq)--type GetAssignmentResponse = [TValuationPair]----- Get Option Response--type GetOptionResponse = AttrValue---- Echo Response--type EchoResponse = String
− app/maxsatverify.hs
@@ -1,48 +0,0 @@-{-# LANGUAGE CPP #-}-module Main where--import Control.Monad-import Data.Array.IArray-import Data.IORef-import System.Environment-import Text.Printf-import qualified ToySolver.FileFormat.CNF as CNF-import ToySolver.SAT.Types-import ToySolver.Internal.Util (setEncodingChar8)--main :: IO ()-main = do-#ifdef FORCE_CHAR8- setEncodingChar8-#endif-- [problemFile, modelFile] <- getArgs- wcnf <- CNF.readFile problemFile- model <- liftM readModel (readFile modelFile)- costRef <- newIORef 0- forM_ (CNF.wcnfClauses wcnf) $ \(w,c) ->- unless (eval model c) $- if w == CNF.wcnfTopCost wcnf- then printf "violated hard constraint: %s\n" (show c)- else do- tc <- readIORef costRef- writeIORef costRef $! tc + w- printf "total cost = %d\n" =<< readIORef costRef--eval :: Model -> PackedClause -> Bool-eval m lits = or [evalLit m lit | lit <- unpackClause lits]--readModel :: String -> Model-readModel s = array (1, maximum (0 : map fst ls2)) ls2- where- ls = lines s- ls2 = do- l <- ls- case l of- 'v':xs -> do- w <- words xs- case w of- '-':ys -> return (read ys, False)- ys -> return (read ys, True)- _ -> mzero-
− app/pbverify.hs
@@ -1,47 +0,0 @@-{-# LANGUAGE CPP #-}-module Main where--import Control.Monad-import Data.Array.IArray-import System.Environment-import Text.Printf-import qualified Data.PseudoBoolean as PBFile-import qualified ToySolver.FileFormat as FF-import ToySolver.SAT.Types-import ToySolver.Internal.Util (setEncodingChar8)--main :: IO ()-main = do-#ifdef FORCE_CHAR8- setEncodingChar8-#endif-- [problemFile, modelFile] <- getArgs- formula <- FF.readFile problemFile- model <- liftM readModel (readFile modelFile)- forM_ (PBFile.pbConstraints formula) $ \c ->- unless (eval model c) $- printf "violated: %s\n" (show c)--eval :: Model -> PBFile.Constraint -> Bool-eval m (lhs, op, rhs) = op_v lhs_v rhs- where- lhs_v = sum [c | (c,lits) <- lhs, all (evalLit m) lits]- op_v = case op of- PBFile.Ge -> (>=)- PBFile.Eq -> (==)--readModel :: String -> Model-readModel s = array (1, maximum (0 : map fst ls2)) ls2- where- ls = lines s- ls2 = do- l <- ls- case l of- 'v':xs -> do- w <- words xs- case w of- '-':'x':ys -> return (read ys, False)- 'x':ys -> return (read ys, True)- _ -> mzero-
app/pigeonhole.hs view
@@ -2,7 +2,6 @@ module Main where import qualified Data.ByteString.Builder as ByteStringBuilder-import Data.List import qualified Data.Map as Map import Data.Map (Map) import System.Environment
app/toyconvert.hs view
@@ -23,7 +23,7 @@ import Data.Char import Data.Default.Class import qualified Data.Foldable as F-import Data.List+import Data.List (intercalate) import Data.Map.Lazy (Map) import Data.Maybe import Data.Scientific (Scientific)@@ -35,14 +35,8 @@ import qualified Options.Applicative import System.IO import System.Exit-import System.FilePath-#if MIN_VERSION_optparse_applicative(0,18,0) import Prettyprinter ((<+>)) import qualified Prettyprinter as PP-#else-import Text.PrettyPrint.ANSI.Leijen ((<+>))-import qualified Text.PrettyPrint.ANSI.Leijen as PP-#endif import qualified Data.PseudoBoolean as PBFile import qualified Numeric.Optimization.MIP as MIP@@ -73,6 +67,7 @@ , optLinearizationUsingPB :: Bool , optKSat :: Maybe Int , optFileEncoding :: Maybe String+ , optMPSObjName :: Bool , optRemoveUserCuts :: Bool , optNewWCNF :: Bool , optPBFastParser :: Bool@@ -96,6 +91,7 @@ <*> linearizationPBOption <*> kSATOption <*> encodingOption+ <*> mpsObjNameOption <*> removeUserCutsOption <*> newWCNFOption <*> pbFastParserOption@@ -196,6 +192,17 @@ <> metavar "ENCODING" <> help "file encoding for LP/MPS files" + mpsObjNameOption :: Parser Bool+ mpsObjNameOption = asum+ [ flag' True+ ( long "mps-obj-name"+ <> help ("Write OBJNAME section in MPS file" ++ (if MIP.optMPSWriteObjName def then " (default)" else "")))+ , flag' False+ ( long "no-mps-obj-name"+ <> help ("Do not write OBJNAME section in MPS file" ++ (if MIP.optMPSWriteObjName def then "" else " (default)")))+ , pure (MIP.optMPSWriteObjName def)+ ]+ removeUserCutsOption :: Parser Bool removeUserCutsOption = switch $ long "remove-usercuts"@@ -231,8 +238,6 @@ <> long "version" <> help "Show version" -#if MIN_VERSION_optparse_applicative(0,18,0)- supportedFormatsDoc :: PP.Doc ann supportedFormatsDoc = PP.vsep@@ -243,20 +248,6 @@ ] ] -#else--supportedFormatsDoc :: PP.Doc-supportedFormatsDoc =- PP.vsep- [ PP.text "Supported formats:"- , PP.indent 2 $ PP.vsep- [ PP.text "input:" <+> (PP.align $ PP.fillSep $ map PP.text $ words ".cnf .wcnf .opb .wbo .gcnf .lp .mps .qubo")- , PP.text "output:" <+> (PP.align $ PP.fillSep $ map PP.text $ words ".cnf .wcnf .opb .wbo .lsp .lp .mps .smp .smt2 .ys .qubo")- ]- ]--#endif- data Trail sol where Trail :: (Transformer a, J.ToJSON a) => a -> Trail (Target a) @@ -268,7 +259,9 @@ readProblem :: Options -> String -> IO Problem readProblem o fname = do enc <- T.mapM mkTextEncoding (optFileEncoding o)- case getExt fname of+ let mipOpt = def{ MIP.optFileEncoding = enc, MIP.optMPSWriteObjName = optMPSObjName o }++ case FF.getBaseExtension fname of ".cnf" | optAsMaxSAT o -> do prob <- FF.readFile fname@@ -304,10 +297,10 @@ (prob2, info2) -> return $ ProbWBO prob2 (Trail (ComposedTransformer info1 info2)) ".lp" -> do- prob <- MIP.readLPFile def{ MIP.optFileEncoding = enc } fname+ prob <- MIP.readLPFile mipOpt fname return $ ProbMIP prob (Trail IdentityTransformer) ".mps" -> do- prob <- MIP.readMPSFile def{ MIP.optFileEncoding = enc } fname+ prob <- MIP.readMPSFile mipOpt fname return $ ProbMIP prob (Trail IdentityTransformer) ".qubo" -> do (qubo :: QUBO.Problem Scientific) <- FF.readFile fname@@ -317,14 +310,6 @@ ext -> error $ "unknown file extension: " ++ show ext -getExt :: String -> String-getExt name | (base, ext) <- splitExtension name =- case map toLower ext of-#ifdef WITH_ZLIB- ".gz" -> getExt base-#endif- s -> s- transformProblem :: Options -> Problem -> Problem transformProblem o = transformObj o . transformPBLinearization o . transformMIPRemoveUserCuts o @@ -373,14 +358,26 @@ case wbo2maxsatWith (optPBEncoding o) wbo of (wcnf, info') -> (wcnf, Trail (ComposedTransformer info info')) +transformNormalizeOPB :: (PBFile.Formula, Trail SAT.Model) -> (PBFile.Formula, Trail SAT.Model)+transformNormalizeOPB (opb, Trail info) =+ case normalizePB opb of+ (opb', info') -> (opb', Trail (ComposedTransformer info info'))+ transformPB2QUBO :: (PBFile.Formula, Trail SAT.Model) -> ((QUBO.Problem Integer, Integer), Trail QUBO.Solution) transformPB2QUBO (opb, Trail info) = case pb2qubo opb of ((qubo, th), info') -> ((qubo, th), Trail (ComposedTransformer info info')) +transformNormalizeMIP :: (MIP.Problem Scientific, Trail (Map MIP.Var Rational)) -> (MIP.Problem Scientific, Trail (Map MIP.Var Rational))+transformNormalizeMIP (ip, Trail info) =+ case normalizeMIPObjective ip of+ (ip', info') -> (ip', Trail (ComposedTransformer info info'))+ writeProblem :: Options -> Problem -> IO () writeProblem o problem = do enc <- T.mapM mkTextEncoding (optFileEncoding o)+ let mipOpt = def{ MIP.optFileEncoding = enc, MIP.optMPSWriteObjName = optMPSObjName o }+ let mip2smtOpt = def { MIP2SMT.optSetLogic = optSMTSetLogic o@@ -456,10 +453,12 @@ ProbOPB opb _ -> pb2lsp opb ProbWBO wbo _ -> wbo2lsp wbo ProbMIP _ _ -> pb2lsp (fst opbAndTrail)- case getExt fname of+ case FF.getBaseExtension fname of ".opb" -> do- FF.writeFile fname $ normalizePB (fst opbAndTrail)- writeInfo' (snd opbAndTrail)+ case transformNormalizeOPB opbAndTrail of+ (opb, trail) -> do+ FF.writeFile fname opb+ writeInfo' trail ".wbo" -> do FF.writeFile fname $ normalizeWBO (fst wboAndTrail) writeInfo' (snd wboAndTrail)@@ -484,11 +483,15 @@ Just _ -> error "--dump-info is not supported for LSP output" Nothing -> return () ".lp" -> do- MIP.writeLPFile def{ MIP.optFileEncoding = enc } fname (fst mipAndTrail)- writeInfo' (snd mipAndTrail)+ case transformNormalizeMIP mipAndTrail of+ (mip, Trail info) -> do+ MIP.writeLPFile mipOpt fname mip+ writeInfo info ".mps" -> do- MIP.writeMPSFile def{ MIP.optFileEncoding = enc } fname (fst mipAndTrail)- writeInfo' (snd mipAndTrail)+ case transformNormalizeMIP mipAndTrail of+ (mip, Trail info) -> do+ MIP.writeMPSFile mipOpt fname mip+ writeInfo info ".smp" -> do withBinaryFile fname WriteMode $ \h -> ByteStringBuilder.hPutBuilder h (pb2smp False (fst opbAndTrail))
app/toyqbf.hs view
@@ -18,7 +18,7 @@ import Control.Monad import Data.Char import qualified Data.IntSet as IntSet-import Data.List+import Data.List (sortBy) import Data.Ord import Data.Version import Options.Applicative
app/toysat/toysat.hs view
@@ -36,7 +36,7 @@ import qualified Data.Traversable as T import Data.Char import Data.IORef-import Data.List+import Data.List (intercalate, isSuffixOf, sort, sortBy) import Data.Maybe import Data.Ord import qualified Data.Vector.Unboxed as V@@ -50,7 +50,6 @@ import System.IO import System.Exit import System.Clock-import System.FilePath import qualified System.Info as SysInfo import qualified System.Random.MWC as Rand import Text.Printf@@ -108,6 +107,7 @@ , optFileEncoding :: Maybe String , optMaxSATCompactVLine :: Bool , optPBFastParser :: Bool+ , optExitCode :: Bool } instance Default Options where@@ -132,6 +132,7 @@ , optFileEncoding = Nothing , optMaxSATCompactVLine = False , optPBFastParser = False+ , optExitCode = False } optionsParser :: Parser Options@@ -155,6 +156,7 @@ <*> fileEncodingOption <*> maxsatCompactVLineOption <*> pbFastParserOption+ <*> exitCodeOption where fileInput :: Parser String fileInput = strArgument $ metavar "(FILE|-)"@@ -168,7 +170,8 @@ , flag' ModePB $ long "pb" <> help "solve pseudo boolean problem in .opb file" , flag' ModeWBO $ long "wbo" <> help "solve weighted boolean optimization problem in .wbo file" , flag' ModeMaxSAT $ long "maxsat" <> help "solve MaxSAT problem in .cnf or .wcnf file"- , flag' ModeMIP $ long "lp" <> help "solve LP/MIP problem in .lp or .mps file"+ , flag' ModeMIP $ long "mip" <> help "solve LP/MIP problem in .lp or .mps file"+ , flag' ModeMIP $ long "lp" <> help "alias for --mip (deprecated)" ] randomSeedOption = optional $ fmap (Rand.toSeed . V.fromList . map read . words) $ strOption@@ -261,6 +264,9 @@ $ long "pb-fast-parser" <> help "use attoparsec-based parser instead of megaparsec-based one for speed" + exitCodeOption = switch+ $ long "exit-code"+ <> help "exit with an exit code based on solution status (only for SAT and MaxSAT mode)" satConfigParser :: Parser SAT.Config satConfigParser = SAT.Config@@ -437,7 +443,7 @@ case optMode opt of Just m -> m Nothing ->- case getExt (optInput opt) of+ case FF.getBaseExtension (optInput opt) of ".cnf" -> ModeSAT ".gcnf" -> ModeMUS ".opb" -> ModePB@@ -476,14 +482,6 @@ putCommentLine $ printf "total wall clock time = %.3fs" (durationSecs startWC endWC) printGCStat -getExt :: String -> String-getExt name | (base, ext) <- splitExtension name =- case map toLower ext of-#ifdef WITH_ZLIB- ".gz" -> getExt base-#endif- s -> s- printGCStat :: IO () #if defined(__GLASGOW_HASKELL__) printGCStat = do@@ -631,11 +629,15 @@ SAT.setVarPolarity solver v val result <- SAT.solve solver- putSLine $ if result then "SATISFIABLE" else "UNSATISFIABLE"- when result $ do+ if result then do+ putSLine "SATISFIABLE" m <- SAT.getModel solver satPrintModel stdout m (CNF.cnfNumVars cnf) writeSOLFile opt m Nothing (CNF.cnfNumVars cnf)+ when (optExitCode opt) $ exitWith (ExitFailure 10)+ else do+ putSLine "UNSATISFIABLE"+ when (optExitCode opt) $ exitWith (ExitFailure 20) initPolarityUsingSP :: SAT.Solver -> Int -> Int -> [(Double, SAT.PackedClause)] -> IO (IntMap Double) initPolarityUsingSP solver nvOrig nv clauses = do@@ -983,27 +985,36 @@ case ret of Nothing -> do b <- PBO.isUnsat pbo- if b- then putSLine "UNSATISFIABLE"- else putSLine "UNKNOWN"+ if b then do+ putSLine "UNSATISFIABLE"+ when (isMaxSat && optExitCode opt) $ exitWith (ExitFailure 20)+ else do+ putSLine "UNKNOWN"+ if isMaxSat && optExitCode opt then+ exitWith ExitSuccess -- ExitFailure 0 is prohibited+ else+ exitFailure Just (m, val) -> do+ let printModel =+ if isMaxSat then+ if optMaxSATCompactVLine opt then+ maxsatPrintModelCompact+ else+ maxsatPrintModel+ else+ pbPrintModel+ b <- PBO.isOptimum pbo if b then do putSLine "OPTIMUM FOUND"- if isMaxSat then- if optMaxSATCompactVLine opt then- maxsatPrintModelCompact stdout m nv- else- maxsatPrintModel stdout m nv- else- pbPrintModel stdout m nv+ printModel stdout m nv writeSOLFile opt m (Just val) nv- else if not isMaxSat then do+ when (isMaxSat && optExitCode opt) $ exitWith (ExitFailure 30)+ else do putSLine "SATISFIABLE"- pbPrintModel stdout m nv+ printModel stdout m nv writeSOLFile opt m (Just val) nv- else- putSLine "UNKNOWN"+ when (isMaxSat && optExitCode opt) $ exitWith (ExitFailure 10) -- ------------------------------------------------------------------------ @@ -1058,7 +1069,7 @@ case ret of Left msg -> do putCommentLine msg- putSLine "UNKNOWN"+ putSLine "UNSUPPORTED" exitFailure Right (obj, info) -> do (linObj, linObjOffset) <- Integer.linearize pbnlc obj@@ -1101,7 +1112,7 @@ b <- PBO.isUnsat pbo if b then putSLine "UNSATISFIABLE"- else putSLine "UNKNOWN"+ else putSLine "UNKNOWN" >> exitFailure Just (m,val) -> do b <- PBO.isOptimum pbo if b
− app/toysmt/ToySolver/SMT/SMTLIB2Solver.hs
@@ -1,888 +0,0 @@-{-# OPTIONS_GHC -Wall #-}--------------------------------------------------------------------------------- |--- Module : ToySolver.SMT.SMTLIB2Solver--- Copyright : (c) Masahiro Sakai 2015--- License : BSD-style------ Maintainer : masahiro.sakai@gmail.com--- Stability : experimental--- Portability : portable----------------------------------------------------------------------------------module ToySolver.SMT.SMTLIB2Solver- ( module Smtlib.Syntax.Syntax- , ShowSL (..)-- -- * The solver type- , Solver- , newSolver-- -- * High-level API- , execCommand- , execCommandString- , runCommand- , runCommandString- , printResponse-- -- * Individual commands-- -- ** (Re)starting and terminating- , reset- , setLogic- , setOption- , exit-- -- ** Modifying the assertion stack- , push- , pop- , resetAssertions-- -- ** Introducing new symbols- , declareSort- , defineSort- , declareConst- , declareFun- , defineFun- , defineFunRec- , defineFunsRec-- -- ** Asserting and inspecting formulas- , assert- , getAssertions-- -- ** Checking for satisfiability- , checkSat- , checkSatAssuming-- -- ** Inspecting models- , getValue- , getAssignment- , getModel-- -- ** Inspecting proofs- , getProof- , getUnsatCore- , getUnsatAssumptions-- -- ** Inspecting settings- , getInfo- , getOption-- -- ** Script information- , setInfo- , echo- ) where--import qualified Control.Exception as E-import Control.Monad-import Data.Interned (unintern)-import Data.Interned.Text-import Data.IORef-import Data.Map (Map)-import qualified Data.Map as Map-import Data.Maybe (catMaybes)-import Data.Ratio-import Data.String-import qualified Data.Text as T-import qualified Data.Version as V-import Numeric (readDec, readFloat, readHex)-import System.Exit-import System.IO-import qualified Text.Parsec as Parsec--import qualified ToySolver.BitVector as BV-import qualified ToySolver.SMT as SMT-import ToySolver.Version-import Smtlib.Syntax.Syntax-import Smtlib.Syntax.ShowSL-import qualified Smtlib.Parsers.CommandsParsers as CommandsParsers---- ------------------------------------------------------------------------data Mode- = ModeStart- | ModeAssert- | ModeSat- | ModeUnsat- deriving (Eq, Ord, Show)--type EEnv = Map String EEntry-type SortEnv = Map String SortEntry-type Env = (EEnv, SortEnv)--data EEntry- = EFSymBuiltin InternedText- | EFSymDeclared SMT.FSym [SMT.Sort] SMT.Sort- | EExpr SMT.Expr Bool- | EFunDef EEnv [(String, SMT.Sort)] SMT.Sort Term--data SortEntry- = SortSym SMT.SSym- | SortExpr SMT.Sort- | SortDef SortEnv [String] Sort--interpretSort :: SortEnv -> Sort -> SMT.Sort-interpretSort env s =- case s of- SortId ident -> f ident []- SortIdentifiers ident args -> f ident args- where- f ident@(I_Symbol "BitVec" indexes) args- | not (null args) = E.throw $ SMT.Error (showSL ident ++ ": wrong number of arguments (" ++ show (length args) ++ " for 0)")- | [IndexNumeral n] <- indexes = SMT.sBitVec n- | otherwise = E.throw $ SMT.Error ("BitVec: wrong number of indexes (" ++ show (length indexes) ++ " for 1)")- f ident@(I_Symbol _ _) _ =- E.throw $ SMT.Error ("unknown sort: " ++ showSL ident)- f ident@(ISymbol name) args =- case Map.lookup name env of- Nothing -> E.throw $ SMT.Error ("unknown sort: " ++ showSL ident)- Just (SortSym ssym)- | SMT.ssymArity ssym == length args -> SMT.Sort ssym args'- | otherwise -> E.throw $ SMT.Error (showSL ident ++ ": wrong number of arguments (" ++ show (length args) ++ " for " ++ show (SMT.ssymArity ssym) ++ ")")- Just (SortExpr s')- | null args -> s'- | otherwise -> E.throw $ SMT.Error (showSL ident ++ ": wrong number of arguments (" ++ show (length args) ++ " for 0)")- Just (SortDef env' params body) ->- interpretSort (Map.fromList (zip params (map SortExpr args')) `Map.union` env') body- where- args' = map (interpretSort env) args--interpretFun :: Env -> Term -> SMT.Expr-interpretFun (env,senv) t =- case t of- TermSpecConstant (SpecConstantNumeral n) -> SMT.EValue $ SMT.ValRational $ fromInteger n- TermSpecConstant (SpecConstantDecimal s) -> SMT.EValue $ SMT.ValRational $ fst $ head $ readFloat s- TermSpecConstant (SpecConstantHexadecimal s) ->- let n = fst $ head $ readHex s- in SMT.EValue $ SMT.ValBitVec $ BV.nat2bv (length s * 4) n- TermSpecConstant (SpecConstantBinary s) ->- SMT.EValue $ SMT.ValBitVec $ BV.fromDescBits [c == '1' | c <- s]- TermSpecConstant c@(SpecConstantString _s) -> E.throw $ SMT.Error (show c)- TermQualIdentifier qid -> f qid []- TermQualIdentifierT qid args -> f qid args- TermLet bindings body ->- interpretFun (Map.fromList [(v, EExpr (interpretFun (env,senv) t2) False) | VB v t2 <- bindings] `Map.union` env, senv) body- TermForall _bindings _body -> E.throw $ SMT.Error "universal quantifiers are not supported yet"- TermExists _bindings _body -> E.throw $ SMT.Error "existential quantifiers are not supported yet"- TermAnnot t2 _ -> interpretFun (env,senv) t2 -- annotations are not supported yet- where- unIdentifier :: Identifier -> (String, [Index])- unIdentifier (ISymbol name) = (name, [])- unIdentifier (I_Symbol name indexes) = (name, indexes)-- f (QIdentifierAs ident sort) args =- case ident of- ISymbol ('@':s) | (n,[]):_ <- reads s ->- SMT.EValue $ SMT.ValUninterpreted n (interpretSort senv sort)- _ -> f (QIdentifier ident) args- f (QIdentifier ident) args- | ('b':'v':xs, [IndexNumeral n]) <- unIdentifier ident- , ((x,_):_) <- readDec xs- , x < 2^n- = if not (null args)- then E.throw $ SMT.Error (showSL ident ++ " does not take indexes")- else SMT.EValue $ SMT.ValBitVec $ BV.nat2bv n x- f qid@(QIdentifier ident) args =- case Map.lookup name env of- Nothing -> E.throw $ SMT.Error ("unknown function symbol: " ++ showSL qid)- Just (EFSymBuiltin name') ->- SMT.EAp (SMT.FSym name' indexes') (map (interpretFun (env,senv)) args)- Just _ | not (null indexes) -> E.throw $ SMT.Error (showSL ident ++ " does not take indexes")- Just (EExpr e _) -> e- Just (EFSymDeclared fsym _ _) -> SMT.EAp fsym (map (interpretFun (env,senv)) args)- Just (EFunDef env' params _y body) ->- interpretFun (Map.fromList [(p,a) | ((p,_s),a) <- zip params (map (\t -> EExpr (interpretFun (env,senv) t) False) args) ] `Map.union` env', senv) body- where- (name, indexes) = unIdentifier ident- indexes' = map g indexes- g (IndexNumeral n) = SMT.IndexNumeral (fromIntegral n)- g (IndexSymbol s) = SMT.IndexSymbol (fromString s)--valueToTerm :: SMT.Value -> Term-valueToTerm (SMT.ValRational v) =- case v `compare` 0 of- GT -> f v- EQ -> TermSpecConstant (SpecConstantNumeral 0)- LT -> TermQualIdentifierT (QIdentifier $ ISymbol "-") [ f (negate v) ]- where- f v = TermQualIdentifierT (QIdentifier $ ISymbol "/")- [ TermSpecConstant (SpecConstantNumeral (numerator v))- , TermSpecConstant (SpecConstantNumeral (denominator v))- ]-valueToTerm (SMT.ValBool b) =- TermQualIdentifier $ QIdentifier $ ISymbol $ if b then "true" else "false"-valueToTerm (SMT.ValBitVec bv) =- TermSpecConstant (SpecConstantBinary $ [if b then '1' else '0' | b <- BV.toDescBits bv])-valueToTerm (SMT.ValUninterpreted n s) =- TermQualIdentifier $ QIdentifierAs (ISymbol $ "@" ++ show n) (sortToSortTerm s)--fsymToIdentifier :: SMT.FSym -> Identifier-fsymToIdentifier (SMT.FSym f indexes) =- case indexes of- [] -> ISymbol (T.unpack $ unintern f)- _ -> I_Symbol (T.unpack $ unintern f) (map g indexes)- where- g (SMT.IndexNumeral n) = IndexNumeral (fromIntegral n)- g (SMT.IndexSymbol s) = IndexSymbol (T.unpack $ unintern s)--exprToTerm :: SMT.Expr -> Term-exprToTerm (SMT.EValue v) = valueToTerm v-exprToTerm (SMT.EAp f []) = TermQualIdentifier (QIdentifier (fsymToIdentifier f))-exprToTerm (SMT.EAp f xs) = TermQualIdentifierT (QIdentifier (fsymToIdentifier f)) (map exprToTerm xs)--ssymToSymbol :: SMT.SSym -> Identifier-ssymToSymbol SMT.SSymBool = ISymbol "Bool"-ssymToSymbol SMT.SSymReal = ISymbol "Real"-ssymToSymbol (SMT.SSymBitVec n) = I_Symbol "BitVec" [IndexNumeral n]-ssymToSymbol (SMT.SSymUninterpreted name _) = ISymbol (T.unpack (unintern name))--sortToSortTerm :: SMT.Sort -> Sort-sortToSortTerm (SMT.Sort s []) = SortId (ssymToSymbol s)-sortToSortTerm (SMT.Sort s xs) = SortIdentifiers (ssymToSymbol s) (map sortToSortTerm xs)---- ------------------------------------------------------------------------data Solver- = Solver- { svSMTSolverRef :: !(IORef SMT.Solver)- , svEnvRef :: !(IORef Env)- , svModeRef :: !(IORef Mode)- , svSavedContextsRef :: !(IORef [(Maybe (EEnv, SortEnv), [Term])])- , svStatusRef :: IORef (Maybe Bool)- , svAssertionsRef :: IORef [Term]- , svRegularOutputChannelRef :: !(IORef (String, Handle))- , svDiagnosticOutputChannelRef :: !(IORef (String, Handle))- , svPrintSuccessRef :: !(IORef Bool)- , svProduceAssertionsRef :: !(IORef Bool)- , svProduceAssignmentRef :: !(IORef Bool)- , svProduceModelsRef :: !(IORef Bool)- , svProduceUnsatAssumptionsRef :: !(IORef Bool)- , svProduceUnsatCoresRef :: !(IORef Bool)- , svGlobalDeclarationsRef :: !(IORef Bool)- , svUnsatAssumptionsRef :: !(IORef [Term])- }--newSolver :: IO Solver-newSolver = do- solverRef <- newIORef =<< SMT.newSolver- envRef <- newIORef initialEnv- modeRef <- newIORef ModeStart- savedContextsRef <- newIORef []- statusRef <- newIORef Nothing- assertionsRef <- newIORef ([] :: [Term])- regOutputRef <- newIORef ("stdout", stdout)- diagOutputRef <- newIORef ("stderr", stderr)- printSuccessRef <- newIORef True- produceAssertionsRef <- newIORef False- produceAssignmentRef <- newIORef False- produceModelsRef <- newIORef False- produceUnsatAssumptionsRef <- newIORef False- produceUnsatCoresRef <- newIORef False- globalDeclarationsRef <- newIORef False- unsatAssumptionsRef <- newIORef undefined- return $- Solver- { svSMTSolverRef = solverRef- , svEnvRef = envRef- , svModeRef = modeRef- , svUnsatAssumptionsRef = unsatAssumptionsRef- , svSavedContextsRef = savedContextsRef- , svStatusRef = statusRef- , svAssertionsRef = assertionsRef- , svRegularOutputChannelRef = regOutputRef- , svDiagnosticOutputChannelRef = diagOutputRef- , svPrintSuccessRef = printSuccessRef- , svProduceAssertionsRef = produceAssertionsRef- , svProduceAssignmentRef = produceAssignmentRef- , svProduceModelsRef = produceModelsRef- , svProduceUnsatCoresRef = produceUnsatCoresRef- , svProduceUnsatAssumptionsRef = produceUnsatAssumptionsRef- , svGlobalDeclarationsRef = globalDeclarationsRef- }--initialEnv :: Env-initialEnv = (fenv, senv)- where- fenv = Map.fromList- [ (name, EFSymBuiltin (fromString name))- | name <- ["=", "true", "false", "not", "and", "or", "xor", "ite", "=>", "distinct"- , "+", "-", "*", "/", ">=", "<=", ">", "<"- , "extract", "concat", "bvnot", "bvneg"- , "repeat", "zero_extend", "sign_extend", "rotate_left", "rotate_right"- , "bvcomp"- , "bvand", "bvor", "bvxor", "bvnand", "bvnor", "bvxnor"- , "bvadd", "bvsub", "bvmul", "bvudiv", "bvurem", "bvsdiv", "bvsrem", "bvsmod", "bvshl", "bvlshr", "bvashr"- , "bvule", "bvult", "bvuge", "bvugt", "bvsle", "bvslt", "bvsge", "bvsgt"- ]- ]- senv = Map.fromList- [ ("Real", SortSym SMT.SSymReal)- , ("Bool", SortSym SMT.SSymBool)- ]--execCommand :: Solver -> Command -> IO ()-execCommand solver cmd = do- -- putStrLn $ showSL cmd- printResponse solver =<< runCommand solver cmd--printResponse :: Solver -> CmdResponse -> IO ()-printResponse solver rsp = do- b <- readIORef (svPrintSuccessRef solver)- unless (rsp == CmdGenResponse Success && not b) $ do- (_,h) <- readIORef (svRegularOutputChannelRef solver)- hPutStrLn h (showSL rsp)--runCommand :: Solver -> Command -> IO CmdResponse-runCommand solver cmd = E.handle h $ do- case cmd of- SetLogic logic -> const (CmdGenResponse Success) <$> setLogic solver logic- SetOption opt -> const (CmdGenResponse Success) <$> setOption solver opt- GetOption s -> CmdGetOptionResponse <$> getOption solver s- SetInfo attr -> const (CmdGenResponse Success) <$> setInfo solver attr- GetInfo flags -> CmdGetInfoResponse <$> getInfo solver flags- Push n -> const (CmdGenResponse Success) <$> push solver n- Pop n -> const (CmdGenResponse Success) <$> pop solver n- DeclareSort name arity -> const (CmdGenResponse Success) <$> declareSort solver name arity- DefineSort name xs body -> const (CmdGenResponse Success) <$> defineSort solver name xs body- DeclareConst name y -> const (CmdGenResponse Success) <$> declareConst solver name y- DeclareFun name xs y -> const (CmdGenResponse Success) <$> declareFun solver name xs y- DefineFun name xs y body -> const (CmdGenResponse Success) <$> defineFun solver name xs y body- DefineFunRec name xs y body -> const (CmdGenResponse Success) <$> defineFunRec solver name xs y body- DefineFunsRec fundecs terms -> const (CmdGenResponse Success) <$> defineFunsRec solver fundecs terms- Assert tm -> const (CmdGenResponse Success) <$> assert solver tm- GetAssertions -> CmdGetAssertionsResponse <$> getAssertions solver- CheckSat -> CmdCheckSatResponse <$> checkSat solver- CheckSatAssuming ts -> CmdCheckSatResponse <$> checkSatAssuming solver ts- GetValue ts -> CmdGetValueResponse <$> getValue solver ts- GetAssignment -> CmdGetAssignmentResponse <$> getAssignment solver- GetModel -> CmdGetModelResponse <$> getModel solver- GetProof -> CmdGetProofResponse <$> getProof solver- GetUnsatCore -> CmdGetUnsatCoreResponse <$> getUnsatCore solver- GetUnsatAssumptions -> CmdGetUnsatAssumptionsResponse <$> getUnsatAssumptions solver- Reset -> const (CmdGenResponse Success) <$> reset solver- ResetAssertions -> const (CmdGenResponse Success) <$> resetAssertions solver- Echo s -> CmdEchoResponse <$> echo solver s- Exit -> const (CmdGenResponse Success) <$> exit solver- where- h SMT.Unsupported = return (CmdGenResponse Unsupported)- h (SMT.Error s) = return $ CmdGenResponse $- -- GenResponse type uses strings in printed form.- Error $ "\"" ++ concat [if c == '"' then "\"\"" else [c] | c <- s] ++ "\""--execCommandString :: Solver -> String -> IO ()-execCommandString solver cmd = do- printResponse solver =<< runCommandString solver cmd--runCommandString :: Solver -> String -> IO CmdResponse-runCommandString solver cmd =- case Parsec.parse (Parsec.spaces >> CommandsParsers.parseCommand <* Parsec.eof) "" cmd of- Left err ->- -- GenResponse type uses strings in printed form.- return $ CmdGenResponse $ Error $ "\"" ++ concat [if c == '"' then "\"\"" else [c] | c <- show err] ++ "\""- Right cmd ->- runCommand solver cmd---- ------------------------------------------------------------------------reset :: Solver -> IO GenResponse-reset solver = do- writeIORef (svSMTSolverRef solver) =<< SMT.newSolver- writeIORef (svEnvRef solver) initialEnv- writeIORef (svModeRef solver) ModeStart- writeIORef (svSavedContextsRef solver) []- writeIORef (svStatusRef solver) Nothing- writeIORef (svRegularOutputChannelRef solver) ("stdout",stdout)- writeIORef (svDiagnosticOutputChannelRef solver) ("stderr",stderr)- writeIORef (svPrintSuccessRef solver) True- writeIORef (svProduceAssertionsRef solver) False- writeIORef (svProduceAssignmentRef solver) False- writeIORef (svProduceModelsRef solver) False- writeIORef (svProduceUnsatAssumptionsRef solver) False- writeIORef (svProduceUnsatCoresRef solver) False- writeIORef (svUnsatAssumptionsRef solver) undefined- return Success--setLogic :: Solver -> String -> IO ()-setLogic solver logic = do- mode <- readIORef (svModeRef solver)- if mode /= ModeStart then do- E.throwIO $ SMT.Error "set-logic can only be used in start mode"- else do- writeIORef (svModeRef solver) ModeAssert- case logic of- "QF_UFLRA" -> return ()- "QF_UFRDL" -> return ()- "QF_UF" -> return ()- "QF_RDL" -> return ()- "QF_LRA" -> return ()- "QF_BV" -> return ()- "QF_UFBV" -> return ()- "ALL" -> return ()- "ALL_SUPPORTED" -> return ()- _ -> E.throwIO SMT.Unsupported--setOption :: Solver -> Option -> IO ()-setOption solver opt = do- mode <- readIORef (svModeRef solver)- case opt of- PrintSuccess b -> do- writeIORef (svPrintSuccessRef solver) b- ExpandDefinitions _b -> do- -- expand-definitions has been removed in SMT-LIB 2.5.- E.throwIO SMT.Unsupported- InteractiveMode b -> do- -- interactive-mode is the old name for produce-assertions. Deprecated.- unless (mode == ModeStart) $ do- E.throwIO $ SMT.Error "interactive-mode option can be set only in start mode"- writeIORef (svProduceAssertionsRef solver) b- return ()- ProduceProofs b -> do- if mode /= ModeStart then- E.throwIO $ SMT.Error "produce-proofs option can be set only in start mode"- else if b then- E.throwIO SMT.Unsupported- else- return ()- ProduceUnsatCores b -> do- unless (mode == ModeStart) $ do- E.throwIO $ SMT.Error "produce-unsat-cores option can be set only in start mode"- writeIORef (svProduceUnsatCoresRef solver) b- return ()- ProduceUnsatAssumptions b -> do- unless (mode == ModeStart) $ do- E.throwIO $ SMT.Error "produce-unsat-assumptions option can be set only in start mode"- writeIORef (svProduceUnsatAssumptionsRef solver) b- return ()- ProduceModels b -> do- unless (mode == ModeStart) $ do- E.throwIO $ SMT.Error "produce-models option can be set only in start mode"- writeIORef (svProduceModelsRef solver) b- return ()- ProduceAssignments b -> do- unless (mode == ModeStart) $ do- E.throwIO $ SMT.Error "produce-assignments option can be set only in start mode"- writeIORef (svProduceAssignmentRef solver) b- return ()- ProduceAssertions b -> do- unless (mode == ModeStart) $ do- E.throwIO $ SMT.Error "produce-assertions option can be set only in start mode"- writeIORef (svProduceAssertionsRef solver) b- return ()- GlobalDeclarations b -> do- unless (mode == ModeStart) $ do- E.throwIO $ SMT.Error "global-declarations option can be set only in start mode"- writeIORef (svGlobalDeclarationsRef solver) b- smt <- readIORef (svSMTSolverRef solver)- SMT.setGlobalDeclarations smt b- RegularOutputChannel fname -> do- h <- if fname == "stdout" then- return stdout- else- openFile fname AppendMode- writeIORef (svRegularOutputChannelRef solver) (fname, h)- return ()- DiagnosticOutputChannel fname -> do- h <- if fname == "stderr" then- return stderr- else- openFile fname AppendMode- writeIORef (svDiagnosticOutputChannelRef solver) (fname, h)- return ()- RandomSeed _i ->- if mode /= ModeStart then- E.throwIO $ SMT.Error "random-seed option can be set only in start mode"- else- E.throwIO SMT.Unsupported- Verbosity _lv -> E.throwIO SMT.Unsupported- ReproducibleResourceLimit _val -> do- if mode /= ModeStart then- E.throwIO $ SMT.Error "reproducible-resource-limit option can be set only in start mode"- else- E.throwIO SMT.Unsupported- OptionAttr _attr -> E.throwIO SMT.Unsupported--getOption :: Solver -> String -> IO GetOptionResponse-getOption solver opt =- case opt of- ":expand-definitions" -> do- -- expand-definitions has been removed in SMT-LIB 2.5.- let b = False- return $ AttrValueSymbol (showSL b)- ":global-declarations" -> do- b <- readIORef (svGlobalDeclarationsRef solver)- return $ AttrValueSymbol (showSL b)- ":interactive-mode" -> do- -- interactive-mode is the old name for produce-assertions. Deprecated.- b <- readIORef (svProduceAssertionsRef solver)- return $ AttrValueSymbol (showSL b)- ":print-success" -> do- b <- readIORef (svPrintSuccessRef solver)- return $ AttrValueSymbol (showSL b)- ":produce-assertions" -> do- b <- readIORef (svProduceAssertionsRef solver)- return $ AttrValueSymbol (showSL b)- ":produce-assignments" -> do- b <- readIORef (svProduceAssignmentRef solver)- return $ AttrValueSymbol (showSL b)- ":produce-models" -> do- b <- readIORef (svProduceModelsRef solver)- return $ AttrValueSymbol (showSL b)- ":produce-proofs" -> do- let b = False -- default value- return $ AttrValueSymbol (showSL b)- ":produce-unsat-cores" -> do- b <- readIORef (svProduceUnsatCoresRef solver)- return $ AttrValueSymbol (showSL b)- ":produce-unsat-assumptions" -> do- b <- readIORef (svProduceUnsatAssumptionsRef solver)- return $ AttrValueSymbol (showSL b)- ":regular-output-channel" -> do- (fname,_) <- readIORef (svRegularOutputChannelRef solver)- return $ AttrValueConstant (SpecConstantString fname)- ":diagnostic-output-channel" -> do- (fname,_) <- readIORef (svDiagnosticOutputChannelRef solver)- return $ AttrValueConstant (SpecConstantString fname)- ":random-seed" -> do- return $ AttrValueConstant (SpecConstantNumeral 0) -- default value- ":reproducible-resource-limit" -> do- return $ AttrValueConstant (SpecConstantNumeral 0) -- default value- ":verbosity" -> do- return $ AttrValueConstant (SpecConstantNumeral 0) -- default value- _ -> do- E.throwIO SMT.Unsupported--setInfo :: Solver -> Attribute -> IO ()-setInfo solver (AttributeVal ":status" (AttrValueSymbol s)) = do- v <- case s of- "sat" -> return $ Just True- "unsat" -> return $ Just False- "unknown" -> return $ Nothing- _ -> E.throwIO $ SMT.Error $ "invalid status value: " ++ s- writeIORef (svStatusRef solver) v-setInfo _solver _ = return ()--getInfo :: Solver -> InfoFlags -> IO GetInfoResponse-getInfo solver flags = do- mode <- readIORef (svModeRef solver)- case flags of- ErrorBehavior -> return [ResponseErrorBehavior ContinuedExecution]- Name -> return [ResponseName "toysmt"]- Authors -> return [ResponseName "Masahiro Sakai"]- Version -> return [ResponseVersion (V.showVersion version)]- Status -> E.throwIO SMT.Unsupported- ReasonUnknown -> do- if mode /= ModeSat then- E.throwIO $ SMT.Error "Executions of get-info with :reason-unknown are allowed only when the solver is in sat mode following a check command whose response was unknown."- else- return [ResponseReasonUnknown Incomplete]- AllStatistics -> do- if not (mode == ModeSat || mode == ModeUnsat) then- E.throwIO $ SMT.Error "Executions of get-info with :all-statistics are allowed only when the solver is in sat or unsat mode."- else- E.throwIO SMT.Unsupported- AssertionStackLevels -> do- saved <- readIORef (svSavedContextsRef solver)- let n = length saved- n `seq` return [ResponseAssertionStackLevels n]- InfoFlags _s -> do- E.throwIO SMT.Unsupported--push :: Solver -> Int -> IO ()-push solver n = do- replicateM_ n $ do- (env,senv) <- readIORef (svEnvRef solver)- assertions <- readIORef (svAssertionsRef solver)- globalDeclarations <- readIORef (svGlobalDeclarationsRef solver)- if globalDeclarations then- modifyIORef (svSavedContextsRef solver) ((Nothing, assertions) :)- else- modifyIORef (svSavedContextsRef solver) ((Just (env,senv), assertions) :)- SMT.push =<< readIORef (svSMTSolverRef solver)- writeIORef (svModeRef solver) ModeAssert--pop :: Solver -> Int -> IO ()-pop solver n = do- replicateM_ n $ do- cs <- readIORef (svSavedContextsRef solver)- case cs of- [] -> E.throwIO $ SMT.Error "pop from empty context"- ((m,assertions) : cs) -> do- case m of- Just (env,senv) -> writeIORef (svEnvRef solver) (env,senv)- Nothing -> return ()- writeIORef (svAssertionsRef solver) assertions- writeIORef (svSavedContextsRef solver) cs- SMT.pop =<< readIORef (svSMTSolverRef solver)- writeIORef (svModeRef solver) ModeAssert--resetAssertions :: Solver -> IO ()-resetAssertions solver = do- cs <- readIORef (svSavedContextsRef solver)- pop solver (length cs)--echo :: Solver -> String -> IO String-echo _solver s = return s--declareSort :: Solver -> String -> Int -> IO ()-declareSort solver name arity = do- smt <- readIORef (svSMTSolverRef solver)- s <- SMT.declareSSym smt name arity- insertSort solver name (SortSym s)- writeIORef (svModeRef solver) ModeAssert--defineSort :: Solver -> String -> [String] -> Sort -> IO ()-defineSort solver name xs body = do- (_, senv) <- readIORef (svEnvRef solver)- insertSort solver name (SortDef senv xs body)- writeIORef (svModeRef solver) ModeAssert--declareConst :: Solver -> String -> Sort -> IO ()-declareConst solver name y = declareFun solver name [] y--declareFun :: Solver -> String -> [Sort] -> Sort -> IO ()-declareFun solver name xs y = do- smt <- readIORef (svSMTSolverRef solver)- (_, senv) <- readIORef (svEnvRef solver)- let argsSorts = map (interpretSort senv) xs- resultSort = interpretSort senv y- f <- SMT.declareFSym smt name argsSorts resultSort- insertFun solver name (EFSymDeclared f argsSorts resultSort)- writeIORef (svModeRef solver) ModeAssert--defineFun :: Solver -> String -> [SortedVar] -> Sort -> Term -> IO ()-defineFun solver name xs y body = do- writeIORef (svModeRef solver) ModeAssert- (_, senv) <- readIORef (svEnvRef solver)- let xs' = map (\(SV x s) -> (x, interpretSort senv s)) xs- y' = interpretSort senv y- if null xs' then do- body' <- processNamed solver body- (fenv, _) <- readIORef (svEnvRef solver)- -- use EExpr?- insertFun solver name (EFunDef fenv [] y' body')- else do- (fenv, _) <- readIORef (svEnvRef solver)- insertFun solver name (EFunDef fenv xs' y' body)- writeIORef (svModeRef solver) ModeAssert--defineFunRec :: Solver -> String -> [SortedVar] -> Sort -> Term -> IO ()-defineFunRec _solver _name _xs _y _body = do- E.throwIO SMT.Unsupported--defineFunsRec :: Solver -> [FunDec] -> [Term] -> IO ()-defineFunsRec _solver _fundecs _terms = do- E.throwIO SMT.Unsupported--assert :: Solver -> Term -> IO ()-assert solver tm = do- let mname =- case tm of- TermAnnot _body attrs- | name:_ <- [name | AttributeVal ":named" (AttrValueSymbol name) <- attrs] ->- Just name- _ -> Nothing- tm' <- processNamed solver tm- smt <- readIORef (svSMTSolverRef solver)- env <- readIORef (svEnvRef solver)- case mname of- Nothing -> SMT.assert smt (interpretFun env tm')- Just name -> SMT.assertNamed smt name (interpretFun env tm')- do b <- readIORef (svProduceAssertionsRef solver)- when b $ modifyIORef (svAssertionsRef solver) (tm :)- writeIORef (svModeRef solver) ModeAssert--getAssertions :: Solver -> IO GetAssertionsResponse-getAssertions solver = do- mode <- readIORef (svModeRef solver)- when (mode == ModeStart) $ do- E.throwIO $ SMT.Error "get-assertions cannot be used in start mode"- b <- readIORef (svProduceAssertionsRef solver)- unless b $ do- E.throwIO $ SMT.Error ":produce-assertions is not enabled"- reverse <$> readIORef (svAssertionsRef solver)--checkSat :: Solver -> IO CheckSatResponse-checkSat solver = checkSatAssuming solver []--checkSatAssuming :: Solver -> [Term] -> IO CheckSatResponse-checkSatAssuming solver xs = do- smt <- readIORef (svSMTSolverRef solver)-- env <- readIORef (svEnvRef solver)- ref <- newIORef Map.empty- ys <- forM xs $ \x -> do- let y = interpretFun env x- modifyIORef ref (Map.insert y x)- return y-- ret <- SMT.checkSATAssuming smt ys-- do expected <- readIORef (svStatusRef solver)- writeIORef (svStatusRef solver) Nothing -- I'm not sure if we should reset or not.- h <- snd <$> readIORef (svDiagnosticOutputChannelRef solver)- case expected of- Just True | not ret -> hPutStrLn h "WARNING: unexpected unsat; expecting sat"- Just False | ret -> hPutStrLn h "WARNING: unexpected sat; expecting unsat"- _ -> return ()- hFlush h-- if ret then do- writeIORef (svModeRef solver) ModeSat- return Sat- else do- writeIORef (svModeRef solver) ModeUnsat- m <- readIORef ref- es <- SMT.getUnsatAssumptions smt- writeIORef (svUnsatAssumptionsRef solver) [m Map.! e | e <- es]- return Unsat--getValue :: Solver -> [Term] -> IO GetValueResponse-getValue solver ts = do- ts <- mapM (processNamed solver) ts- mode <- readIORef (svModeRef solver)- unless (mode == ModeSat) $ do- E.throwIO $ SMT.Error "get-value can only be used in sat mode"- smt <- readIORef (svSMTSolverRef solver)- m <- SMT.getModel smt- env <- readIORef (svEnvRef solver)- forM ts $ \t -> do- let e = interpretFun env t- let v = SMT.eval m e- return $ ValuationPair t (valueToTerm v)--getAssignment :: Solver -> IO GetAssignmentResponse-getAssignment solver = do- mode <- readIORef (svModeRef solver)- unless (mode == ModeSat) $ do- E.throwIO $ SMT.Error "get-assignment can only be used in sat mode"- smt <- readIORef (svSMTSolverRef solver)- m <- SMT.getModel smt- (env, _) <- readIORef (svEnvRef solver)- liftM concat $ forM (Map.toList env) $ \(name, entry) -> do- case entry of- EExpr e True -> do- s <- SMT.exprSort smt e- if s /= SMT.sBool then do- return []- else do- let v = SMT.eval m e- case v of- (SMT.ValBool b) -> return [TValuationPair name b]- _ -> E.throwIO $ SMT.Error "get-assignment: should not happen"- _ -> return []--getModel :: Solver -> IO GetModelResponse-getModel solver = do- mode <- readIORef (svModeRef solver)- unless (mode == ModeSat) $ do- E.throwIO $ SMT.Error "get-model can only be used in sat mode"- smt <- readIORef (svSMTSolverRef solver)- m <- SMT.getModel smt- (env, _) <- readIORef (svEnvRef solver)- defs <- liftM catMaybes $ forM (Map.toList env) $ \(name, entry) -> do- case entry of- EFSymDeclared sym argsSorts resultSort -> do- case SMT.evalFSym m sym of- SMT.FunDef [] val -> do -- constant- return $ Just $ DefineFun name [] (sortToSortTerm resultSort) (valueToTerm val)- SMT.FunDef tbl defaultVal -> do -- proper function- let argsSV :: [SortedVar]- argsSV = [SV ("x!" ++ show i) (sortToSortTerm s) | (i,s) <- zip [(1::Int)..] argsSorts]- args :: [Term]- args = [TermQualIdentifier (QIdentifier (ISymbol x)) | SV x _ <- argsSV]- f :: ([SMT.Value], SMT.Value) -> Term -> Term- f (vals,val) tm =- TermQualIdentifierT (QIdentifier (ISymbol "ite")) [cond, valueToTerm val, tm]- where- cond =- case zipWith (\arg val -> TermQualIdentifierT (QIdentifier (ISymbol "=")) [arg, valueToTerm val]) args vals of- [c] -> c- cs -> TermQualIdentifierT (QIdentifier (ISymbol "and")) cs- return $ Just $ DefineFun name argsSV (sortToSortTerm resultSort) $- foldr f (valueToTerm defaultVal) tbl- _ -> return Nothing- return $ defs ++ [Assert (exprToTerm x) | x <- SMT.modelGetAssertions m]--getProof :: Solver -> IO GetProofResponse-getProof solver = do- mode <- readIORef (svModeRef solver)- if mode /= ModeUnsat then- E.throwIO $ SMT.Error "get-proof can only be used in unsat mode"- else- E.throwIO SMT.Unsupported--getUnsatCore :: Solver -> IO GetUnsatCoreResponse-getUnsatCore solver = do- smt <- readIORef (svSMTSolverRef solver)- mode <- readIORef (svModeRef solver)- unless (mode == ModeUnsat) $ do- E.throwIO $ SMT.Error "get-unsat-core can only be used in unsat mode"- SMT.getUnsatCore smt--getUnsatAssumptions :: Solver -> IO [Term]-getUnsatAssumptions solver = do- mode <- readIORef (svModeRef solver)- unless (mode == ModeUnsat) $ do- E.throwIO $ SMT.Error "get-unsat-assumptions can only be used in unsat mode"- readIORef (svUnsatAssumptionsRef solver)--exit :: Solver -> IO ()-exit _solver = exitSuccess---- ------------------------------------------------------------------------insertSort :: Solver -> String -> SortEntry -> IO ()-insertSort solver name sdef = do- (fenv, senv) <- readIORef (svEnvRef solver)- case Map.lookup name senv of- Nothing -> writeIORef (svEnvRef solver) (fenv, Map.insert name sdef senv)- Just _ -> E.throwIO $ SMT.Error (name ++ " is already used")--insertFun :: Solver -> String -> EEntry -> IO ()-insertFun solver name fdef = do- (fenv, senv) <- readIORef (svEnvRef solver)- case Map.lookup name fenv of- Nothing -> writeIORef (svEnvRef solver) (Map.insert name fdef fenv, senv)- Just _ -> E.throwIO $ SMT.Error (name ++ " is already used")---- TODO: check closedness of terms-processNamed :: Solver -> Term -> IO Term-processNamed solver = f- where- f t@(TermSpecConstant _) = return t- f t@(TermQualIdentifier _) = return t- f (TermQualIdentifierT qid args) = do- args' <- mapM f args- return $ TermQualIdentifierT qid args'- f (TermLet bindings body) = do- body' <- f body- return $ TermLet bindings body'- f (TermForall bindings body) = do- body' <- f body- return $ TermForall bindings body'- f (TermExists bindings body) = do- body' <- f body- return $ TermExists bindings body'- f (TermAnnot body attrs) = do- body' <- f body- forM_ attrs $ \attr -> do- case attr of- AttributeVal ":named" val ->- case val of- AttrValueSymbol name -> do- env <- readIORef (svEnvRef solver)- let e = interpretFun env body'- -- smt <- readIORef (svSMTSolverRef solver)- -- s <- SMT.exprSort smt e- insertFun solver name (EExpr e True)- _ -> E.throwIO $ SMT.Error ":named attribute value should be a symbol"- _ -> return ()- let attrs' = [attr | attr <- attrs, attrName attr /= ":named"]- where- attrName (Attribute s) = s- attrName (AttributeVal s _v) = s- if null attrs' then- return body'- else- return $ TermAnnot body' attrs'
app/toysmt/toysmt.hs view
@@ -1,5 +1,6 @@ {-# OPTIONS_GHC -Wall #-} {-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-} ----------------------------------------------------------------------------- -- | -- Module : toysmt@@ -13,25 +14,31 @@ ----------------------------------------------------------------------------- module Main where -import Control.Applicative-import Control.Monad-import Control.Monad.Trans import Data.Version import Options.Applicative hiding (Parser) import qualified Options.Applicative as Opt+import Control.Monad (when)+import qualified Data.Text.IO as T #ifdef USE_HASKELINE_PACKAGE+import Control.Monad.IO.Class (liftIO)+import Data.Text (Text)+import qualified Data.Text as T import qualified System.Console.Haskeline as Haskeline+import Language.SMTLIB.Parser (frameCommand, Result (..)) #endif+import Language.SMTLIB.Reader.Handle (newHandleReader, readCommand) import System.Exit import System.IO-import Text.Parsec hiding (many)-import Text.Parsec.String -import Smtlib.Parsers.CommandsParsers+import Language.SMTLIB (errorBundlePretty)+import Language.SMTLIB.Parser (parseScript') import ToySolver.Version+-- 'noAnn' is re-exported by ToySolver.SMT.SMTLIB2Solver (via Language.SMTLIB.Syntax). import ToySolver.SMT.SMTLIB2Solver+#ifdef FORCE_CHAR8 import ToySolver.Internal.Util (setEncodingChar8)+#endif data Mode = ModeHelp@@ -87,48 +94,83 @@ loadFile :: Solver -> FilePath -> IO () loadFile solver fname = do- ret <- parseFromFile (parseSource <* eof) fname- case ret of+ txt <- T.readFile fname+ case parseScript' fname txt of Left err -> do- hPrint stderr err+ hPutStr stderr (errorBundlePretty err) exitFailure- Right source -> do- forM_ source $ \cmd -> do- execCommand solver cmd+ Right script -> do+ mapM_ (execCommand solver) script repl :: Solver -> IO () repl solver = do+ -- Use the interactive frontend (prompt, and line editing via haskeline if+ -- available) only when stdin is connected to a terminal. When stdin is a pipe+ -- or a regular file, toysmt is typically driven by another program over the+ -- SMT-LIB protocol; in that case we suppress the prompt so that it does not+ -- pollute the response stream on stdout, and we avoid haskeline entirely.+ tty <- hIsTerminalDevice stdin #ifdef USE_HASKELINE_PACKAGE- replHaskeline solver+ if tty then+ replHaskeline solver+ else+ replSimple False solver #else- replSimple solver+ replSimple tty solver #endif -replSimple :: Solver -> IO ()-replSimple solver = do+replSimple :: Bool -> Solver -> IO ()+replSimple showPrompt solver = do hSetBuffering stdin LineBuffering- forever $ do- putStr "toysmt> "- hFlush stdout- s <- getLine- case parse (spaces >> parseCommand <* eof) "<stdin>" s of- Left err -> do- hPrint stderr err- Right cmd -> do- execCommand solver cmd+ hr <- newHandleReader stdin+ let loop = do+ when showPrompt $ do+ putStr "toysmt> "+ hFlush stdout+ r <- readCommand hr+ case r of+ Left err -> do+ hPutStrLn stderr err+ loop+ Right Nothing -> return ()+ Right (Just cmd) -> do+ execCommand solver (noAnn cmd)+ loop+ loop #ifdef USE_HASKELINE_PACKAGE replHaskeline :: Solver -> IO ()-replHaskeline solver = Haskeline.runInputT Haskeline.defaultSettings $ forever $ do- m <- Haskeline.getInputLine "toysmt> "- case m of- Nothing -> return ()- Just s -> do- case parse (spaces >> parseCommand) "<stdin>" s of- Left err -> do- lift $ hPrint stderr err- Right cmd -> do- lift $ execCommand solver cmd+replHaskeline solver = Haskeline.runInputT Haskeline.defaultSettings $ loop T.empty+ where+ loop :: Text -> Haskeline.InputT IO ()+ loop buf = do+ let prompt = if T.null (T.strip buf) then "toysmt> " else "... "+ m <- Haskeline.getInputLine prompt+ case m of+ Nothing -> return ()+ Just s -> process (buf <> T.pack s <> "\n")++ process :: Text -> Haskeline.InputT IO ()+ process buf =+ case frameCommand buf of+ Partial _ -> loop buf -- incomplete command: prompt for more input+ Done (Right cmd) rest -> do+ liftIO $ execCommand solver (noAnn cmd)+ continue rest+ Done (Left err) rest -> do+ liftIO $ hPutStr stderr (errorBundlePretty err)+ continue rest+ Failed err _ -> do+ -- A framing error (e.g. a stray top-level ')') is not consumed by the+ -- framer, so its leftover would re-trigger the same error forever.+ -- Discard the buffer and prompt afresh.+ liftIO $ hPutStrLn stderr ("framing error: " ++ show err)+ loop T.empty++ continue :: Text -> Haskeline.InputT IO ()+ continue rest+ | T.null (T.strip rest) = loop T.empty+ | otherwise = process rest #endif
app/toysolver.hs view
@@ -20,7 +20,8 @@ import Data.Array.IArray import Data.Char import Data.Default.Class-import Data.List+import Data.IORef+import Data.List (intercalate) import Data.Maybe import Data.Scientific (Scientific) import qualified Data.Scientific as Scientific@@ -79,6 +80,7 @@ , optFileEncoding :: Maybe String , optMaxSATCompactVLine :: Bool , optPBFastParser :: Bool+ , optExitCode :: Bool } deriving (Eq, Show) optionsParser :: Parser Options@@ -96,6 +98,7 @@ <*> fileEncodingOption <*> maxsatCompactVLineOption <*> pbFastParserOption+ <*> exitCodeOption where fileInput :: Parser FilePath fileInput = argument str (metavar "FILE")@@ -106,7 +109,8 @@ <|> flag' ModePB (long "pb" <> help "solve pseudo boolean problem in .opb file") <|> flag' ModeWBO (long "wbo" <> help "solve weighted boolean optimization problem in .wbo file") <|> flag' ModeMaxSAT (long "maxsat" <> help "solve MaxSAT problem in .cnf or .wcnf file")- <|> flag' ModeMIP (long "lp" <> help "solve LP/MIP problem in .lp or .mps file")+ <|> flag' ModeMIP (long "mip" <> help "solve LP/MIP problem in .lp or .mps file")+ <|> flag' ModeMIP (long "lp" <> help "alias for --mip (deprecated)") solverOption :: Parser String solverOption = strOption@@ -177,6 +181,11 @@ $ long "pb-fast-parser" <> help "use attoparsec-based parser instead of megaparsec-based one for speed" + exitCodeOption :: Parser Bool+ exitCodeOption = switch+ $ long "exit-code"+ <> help "exit with an exit code based on solution status (only for SAT and MaxSAT mode)"+ parserInfo :: ParserInfo Options parserInfo = info (helper <*> versionOption <*> optionsParser) $ fullDesc@@ -190,13 +199,23 @@ -- --------------------------------------------------------------------------- +data SolutionStatus+ = UNKNOWN+ | UNSUPPORTED+ | SATISFIABLE+ | UNSATISFIABLE+ | OPTIMUM_FOUND+ | UNBOUNDED+ deriving (Show, Eq, Ord, Bounded, Enum)+ run :: String -> Options -> MIP.Problem Rational+ -> (SolutionStatus -> IO ()) -> (Map MIP.Var Rational -> IO ()) -> IO ()-run solver opt prob printModel = do+run solver opt prob setSolutionStatus printModel = do unless (Set.null (MIP.semiContinuousVariables prob)) $ do hPutStrLn stderr "semi-continuous variables are not supported." exitFailure@@ -259,16 +278,14 @@ solveByQE = case mapM LAFOL.fromFOLAtom (cs1 ++ cs2) of Nothing -> do- putSLine "UNKNOWN"- exitFailure+ setSolutionStatus UNKNOWN Just cs -> case f vs2 cs ivs2 of Nothing -> do- putSLine "UNSATISFIABLE"- exitFailure+ setSolutionStatus UNSATISFIABLE Just m -> do putOLine $ showValue (FOL.evalExpr m obj)- putSLine "SATISFIABLE"+ setSolutionStatus SATISFIABLE let m2 = Map.fromAscList [(v, m IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs] printModel m2 where@@ -300,19 +317,16 @@ return (cs',obj') case prob2 of Nothing -> do- putSLine "UNKNOWN"- exitFailure+ setSolutionStatus UNSUPPORTED Just (cs',obj') -> case TextbookMIP.optimize (MIP.objDir $ MIP.objectiveFunction prob) obj' cs' ivs2 of TextbookMIP.OptUnsat -> do- putSLine "UNSATISFIABLE"- exitFailure+ setSolutionStatus UNSATISFIABLE TextbookMIP.Unbounded -> do- putSLine "UNBOUNDED"- exitFailure+ setSolutionStatus UNBOUNDED TextbookMIP.Optimum r m -> do putOLine $ showValue r- putSLine "OPTIMUM FOUND"+ setSolutionStatus OPTIMUM_FOUND let m2 = Map.fromAscList [(v, m IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs] printModel m2 @@ -355,17 +369,15 @@ ret <- MIPSolver.optimize mip case ret of Simplex.Unsat -> do- putSLine "UNSATISFIABLE"- exitFailure+ setSolutionStatus UNSATISFIABLE Simplex.Unbounded -> do- putSLine "UNBOUNDED"+ setSolutionStatus UNBOUNDED Just m <- MIPSolver.getBestModel mip let m2 = Map.fromAscList [(v, m IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs] printModel m2- exitFailure Simplex.Optimum -> do Just m <- MIPSolver.getBestModel mip- putSLine "OPTIMUM FOUND"+ setSolutionStatus OPTIMUM_FOUND let m2 = Map.fromAscList [(v, m IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs] printModel m2 Simplex.ObjLimit -> do@@ -373,21 +385,19 @@ solveByCAD | not (IntSet.null ivs2) = do- putSLine "UNKNOWN"+ setSolutionStatus UNSUPPORTED putCommentLine "integer variables are not supported by CAD"- exitFailure | otherwise = do let cs = map (fmap f) $ cs1 ++ cs2 vs3 = Set.fromAscList $ IntSet.toAscList vs2 case CAD.solve vs3 cs of Nothing -> do- putSLine "UNSATISFIABLE"- exitFailure+ setSolutionStatus UNSATISFIABLE Just m -> do let m2 = IntMap.map (\x -> AReal.approx x (2^^(-64::Int))) $ IntMap.fromAscList $ Map.toAscList $ m putOLine $ showValue (FOL.evalExpr m2 obj)- putSLine "SATISFIABLE"+ setSolutionStatus SATISFIABLE let m3 = Map.fromAscList [(v, m2 IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs] printModel m3 where@@ -404,9 +414,8 @@ solveByContiTraverso | not (vs `Set.isSubsetOf` ivs) = do- putSLine "UNKNOWN"+ setSolutionStatus UNSUPPORTED putCommentLine "continuous variables are not supported by Conti-Traverso algorithm"- exitFailure | otherwise = do let tmp = do linObj <- LAFOL.fromFOLExpr obj@@ -414,18 +423,16 @@ return (linObj, linCon) case tmp of Nothing -> do- putSLine "UNKNOWN"+ setSolutionStatus UNSUPPORTED putCommentLine "non-linear expressions are not supported by Conti-Traverso algorithm"- exitFailure Just (linObj, linCon) -> case ContiTraverso.solve P.grlex vs2 (MIP.objDir $ MIP.objectiveFunction prob) linObj linCon of Nothing -> do- putSLine "UNSATISFIABLE"- exitFailure+ setSolutionStatus UNSATISFIABLE Just m -> do let m2 = IntMap.map fromInteger m putOLine $ showValue (FOL.evalExpr m2 obj)- putSLine "OPTIMUM FOUND"+ setSolutionStatus OPTIMUM_FOUND let m3 = Map.fromAscList [(v, m2 IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs] printModel m3 @@ -438,8 +445,7 @@ mipPrintModel :: Handle -> Bool -> Map MIP.Var Rational -> IO () mipPrintModel h asRat m = forM_ (Map.toList m) $ \(v, val) ->- hPrintf h "v %s = %s\n" (MIP.fromVar v) (showRational asRat val)-+ hPrintf h "v %s = %s\n" (MIP.varName v) (showRational asRat val) putCommentLine :: String -> IO () putCommentLine s = do@@ -467,54 +473,122 @@ setEncodingChar8 #endif - o <- execParser parserInfo+ opt <- execParser parserInfo - case fromMaybe ModeMIP (optMode o) of+ ref <- newIORef Nothing+ let putStatus status = do+ m <- readIORef ref+ case m of+ Just _ -> error "solution status is already set"+ Nothing -> writeIORef ref (Just status)++ setSolutionStatusSAT status = do+ putStatus status+ case status of+ UNKNOWN -> putSLine "UNKNOWN"+ UNSUPPORTED -> putSLine "UNKNOWN"+ SATISFIABLE -> putSLine "SATISFIABLE"+ UNSATISFIABLE -> putSLine "UNSATISFIABLE"+ OPTIMUM_FOUND -> putSLine "SATISFIABLE"+ UNBOUNDED -> putSLine "UNKNOWN"++ setSolutionStatusMaxSAT status = do+ putStatus status+ case status of+ UNKNOWN -> putSLine "UNKNOWN"+ UNSUPPORTED -> putSLine "UNKNOWN"+ SATISFIABLE -> putSLine "SATISFIABLE"+ UNSATISFIABLE -> putSLine "UNSATISFIABLE"+ OPTIMUM_FOUND -> putSLine "OPTIMUM FOUND"+ UNBOUNDED -> putSLine "UNKNOWN"++ setSolutionStatusPB status = do+ putStatus status+ case status of+ UNKNOWN -> putSLine "UNKNOWN"+ UNSUPPORTED -> putSLine "UNSUPPORTED"+ SATISFIABLE -> putSLine "SATISFIABLE"+ UNSATISFIABLE -> putSLine "UNSATISFIABLE"+ OPTIMUM_FOUND -> putSLine "OPTIMUM FOUND"+ UNBOUNDED -> putSLine "UNKNOWN"++ case fromMaybe ModeMIP (optMode opt) of ModeSAT -> do- cnf <- FF.readFile (optInput o)+ cnf <- FF.readFile (optInput opt) let (mip,info2) = sat2ip cnf- run (optSolver o) o (fmap fromInteger mip) $ \m -> do++ run (optSolver opt) opt (fmap fromInteger mip) setSolutionStatusSAT $ \m -> do let m2 = transformBackward info2 m satPrintModel stdout m2 0- writeSOLFileSAT o m2+ writeSOLFileSAT opt m2++ when (optExitCode opt) $ do+ status <- readIORef ref+ case fromMaybe UNKNOWN status of+ UNKNOWN -> exitSuccess+ UNSUPPORTED -> exitSuccess+ SATISFIABLE -> exitWith (ExitFailure 10)+ UNSATISFIABLE -> exitWith (ExitFailure 20)+ OPTIMUM_FOUND -> exitWith (ExitFailure 10)+ UNBOUNDED -> exitSuccess+ ModePB -> do pb <-- if optPBFastParser o then- liftM FF.unWithFastParser $ FF.readFile (optInput o)+ if optPBFastParser opt then+ liftM FF.unWithFastParser $ FF.readFile (optInput opt) else- FF.readFile (optInput o)+ FF.readFile (optInput opt) let (mip,info2) = pb2ip pb- run (optSolver o) o (fmap fromInteger mip) $ \m -> do+ run (optSolver opt) opt (fmap fromInteger mip) setSolutionStatusPB $ \m -> do let m2 = transformBackward info2 m pbPrintModel stdout m2 0- writeSOLFileSAT o m2+ writeSOLFileSAT opt m2+ ModeWBO -> do wbo <-- if optPBFastParser o then- liftM FF.unWithFastParser $ FF.readFile (optInput o)+ if optPBFastParser opt then+ liftM FF.unWithFastParser $ FF.readFile (optInput opt) else- FF.readFile (optInput o)+ FF.readFile (optInput opt) let (mip,info2) = wbo2ip False wbo- run (optSolver o) o (fmap fromInteger mip) $ \m -> do+ run (optSolver opt) opt (fmap fromInteger mip) setSolutionStatusPB $ \m -> do let m2 = transformBackward info2 m pbPrintModel stdout m2 0- writeSOLFileSAT o m2+ writeSOLFileSAT opt m2+ ModeMaxSAT -> do- wcnf <- FF.readFile (optInput o)+ wcnf <- FF.readFile (optInput opt) let (mip,info2) = maxsat2ip False wcnf- run (optSolver o) o (fmap fromInteger mip) $ \m -> do+ run (optSolver opt) opt (fmap fromInteger mip) setSolutionStatusMaxSAT $ \m -> do let m2 = transformBackward info2 m- if optMaxSATCompactVLine o then+ if optMaxSATCompactVLine opt then maxsatPrintModelCompact stdout m2 0 else maxsatPrintModel stdout m2 0- writeSOLFileSAT o m2+ writeSOLFileSAT opt m2++ when (optExitCode opt) $ do+ status <- readIORef ref+ case fromMaybe UNKNOWN status of+ UNKNOWN -> exitSuccess+ UNSUPPORTED -> exitSuccess+ SATISFIABLE -> exitWith (ExitFailure 10)+ UNSATISFIABLE -> exitWith (ExitFailure 20)+ OPTIMUM_FOUND -> exitWith (ExitFailure 30)+ UNBOUNDED -> exitSuccess+ ModeMIP -> do- enc <- T.mapM mkTextEncoding $ optFileEncoding o- mip <- MIP.readFile def{ MIP.optFileEncoding = enc } (optInput o)- run (optSolver o) o (fmap toRational mip) $ \m -> do- mipPrintModel stdout (optPrintRational o) m- writeSOLFileMIP o m+ enc <- T.mapM mkTextEncoding $ optFileEncoding opt+ mip <- MIP.readFile def{ MIP.optFileEncoding = enc } (optInput opt)+ run (optSolver opt) opt (fmap toRational mip) setSolutionStatusPB $ \m -> do+ mipPrintModel stdout (optPrintRational opt) m+ writeSOLFileMIP opt m++ status <- readIORef ref+ case fromMaybe UNKNOWN status of+ UNKNOWN -> exitFailure+ UNSUPPORTED -> exitFailure+ _ -> exitSuccess -- FIXME: 目的関数値を表示するように writeSOLFileMIP :: Options -> Map MIP.Var Rational -> IO ()
+ app/toysolver_check.hs view
@@ -0,0 +1,163 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Main where++import Control.Monad+import qualified Data.ByteString.Lazy.Char8 as BL+import Data.Default.Class+import Data.Scientific+import qualified Data.Version as V+import qualified Numeric.Optimization.MIP as MIP+import qualified Numeric.Optimization.MIP.Solution.Gurobi as GurobiSol+import Options.Applicative hiding (Const)+import System.Exit+import System.IO++import qualified ToySolver.FileFormat as FF+import ToySolver.Internal.SolutionChecker+import ToySolver.SAT.LogParser (parseSATLog, parseMaxSATLog, parsePBLog)+import ToySolver.Internal.Util (setEncodingChar8)+import ToySolver.Version+++data Mode = ModeSAT | ModePB | ModeWBO | ModeMaxSAT | ModeMIP+ deriving (Eq, Ord, Show)++data Options = Options+ { optInputFile :: FilePath+ , optSolutionFile :: FilePath+ , optMode :: Maybe Mode+ , optFileEncoding :: Maybe String+ , optPBFastParser :: Bool+ , optMIPTol :: MIP.Tol Scientific+ }++optionsParser :: Parser Options+optionsParser = Options+ <$> fileInput+ <*> solutionFileInput+ <*> modeOption+ <*> fileEncodingOption+ <*> pbFastParserOption+ <*> mipTolOptions+ where+ fileInput :: Parser FilePath+ fileInput = argument str (metavar "FILE")++ solutionFileInput :: Parser FilePath+ solutionFileInput = argument str (metavar "SOLUTION_FILE")++ modeOption :: Parser (Maybe Mode)+ modeOption = optional $+ flag' ModeSAT (long "sat" <> help "load boolean satisfiability problem in .cnf file")+ <|> flag' ModePB (long "pb" <> help "load pseudo boolean problem in .opb file")+ <|> flag' ModeWBO (long "wbo" <> help "load weighted boolean optimization problem in .wbo file")+ <|> flag' ModeMaxSAT (long "maxsat" <> help "load MaxSAT problem in .cnf or .wcnf file")+ <|> flag' ModeMIP (long "mip" <> help "load LP/MIP problem in .lp or .mps file")+ <|> flag' ModeMIP (long "lp" <> help "alias for --mip (deprecated)")++ fileEncodingOption :: Parser (Maybe String)+ fileEncodingOption = optional $ strOption+ $ long "encoding"+ <> metavar "ENCODING"+ <> help "file encoding for LP/MPS files"++ pbFastParserOption :: Parser Bool+ pbFastParserOption = switch+ $ long "pb-fast-parser"+ <> help "use attoparsec-based parser instead of megaparsec-based one for speed"++ mipTolOptions :: Parser (MIP.Tol Scientific)+ mipTolOptions = MIP.Tol <$> intTol <*> feasTol <*> optTol+ where+ intTol = option auto+ $ long "tol-integrality"+ <> metavar "REAL"+ <> help "If a value of integer variable is within this amount from its nearest integer, it is considered feasible."+ <> value (MIP.integralityTol def)+ <> showDefault+ feasTol = option auto+ $ long "tol-feasibility"+ <> metavar "REAL"+ <> help "If the amount of violation of constraints is within this amount, it is considered feasible."+ <> value (MIP.feasibilityTol def)+ <> showDefault+ optTol = option auto+ $ long "tol-optimality"+ <> metavar "REAL"+ <> help "Feasibility tolerance of dual constraints."+ <> value (MIP.optimalityTol def)+ <> showDefault++parserInfo :: ParserInfo Options+parserInfo = info (helper <*> versionOption <*> optionsParser)+ $ fullDesc+ <> header "toysolver-check - a solution checker"+ where+ versionOption :: Parser (a -> a)+ versionOption = infoOption (V.showVersion version)+ $ hidden+ <> long "version"+ <> help "Show version"++main :: IO ()+main = do+#ifdef FORCE_CHAR8+ setEncodingChar8+#endif++ opt <- execParser parserInfo+ let mode =+ case optMode opt of+ Just m -> m+ Nothing ->+ case FF.getBaseExtension (optInputFile opt) of+ ".cnf" -> ModeSAT+ ".opb" -> ModePB+ ".wbo" -> ModeWBO+ ".wcnf" -> ModeMaxSAT+ ".lp" -> ModeMIP+ ".mps" -> ModeMIP+ _ -> ModeSAT++ (ok, ls) <- case mode of+ ModeSAT -> do+ cnf <- FF.readFile (optInputFile opt)+ (status, m) <- liftM parseSATLog (BL.readFile (optSolutionFile opt))+ pure $ checkSATResult cnf (status, m)++ ModePB -> do+ opb <-+ if optPBFastParser opt then+ liftM FF.unWithFastParser $ FF.readFile (optInputFile opt)+ else+ FF.readFile (optInputFile opt)+ (status, o, m) <- liftM parsePBLog (BL.readFile (optSolutionFile opt))+ pure $ checkPBResult opb (status, o, m)++ ModeWBO -> do+ wbo <-+ if optPBFastParser opt then+ liftM FF.unWithFastParser $ FF.readFile (optInputFile opt)+ else+ FF.readFile (optInputFile opt)+ (status, o, m) <- liftM parsePBLog (BL.readFile (optSolutionFile opt))+ pure $ checkWBOResult wbo (status, o, m)++ ModeMaxSAT -> do+ wcnf <- FF.readFile (optInputFile opt)+ (status, o, m) <- liftM parseMaxSATLog (BL.readFile (optSolutionFile opt))+ pure $ checkMaxSATResult wcnf (status, o, m)++ ModeMIP -> do+ enc <- mapM mkTextEncoding $ optFileEncoding opt+ mip <- MIP.readFile def{ MIP.optFileEncoding = enc } (optInputFile opt)+ sol <- GurobiSol.readFile (optSolutionFile opt)+ let tol = optMIPTol opt+ pure $ checkMIPResult tol mip sol++ mapM_ putStrLn ls++ unless ok $ exitFailure
samples/programs/assign/assign.hs view
@@ -31,7 +31,7 @@ import qualified Data.IntMap as IntMap import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet-import Data.List+import Data.List (unfoldr) import qualified Data.Vector.Unboxed as VU import System.Environment import ToySolver.Combinatorial.BipartiteMatching
samples/programs/htc/htc.hs view
@@ -5,7 +5,7 @@ import Control.Monad import Data.Char-import Data.List+import Data.List (intercalate) import qualified Data.IntSet as IntSet import qualified Data.Set as Set import System.Environment
samples/programs/knapsack/knapsack.hs view
@@ -4,7 +4,7 @@ module Main where import Control.Monad-import Data.List+import Data.List (intersperse) import System.Environment import System.IO import Text.Printf
samples/programs/numberlink/numberlink.hs view
@@ -8,7 +8,7 @@ import qualified Data.ByteString.Lazy.Char8 as BL import Data.Char import Data.Default.Class-import Data.List+import Data.List (intersperse) import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map import Data.Maybe
samples/programs/shortest-path/shortest-path.hs view
@@ -11,9 +11,7 @@ import Data.Foldable (toList) import qualified Data.IntMap.Strict as IntMap import Data.Int-import Data.List import Data.Maybe-import Data.Ord import qualified Data.Sequence as Seq import System.Console.GetOpt import System.Environment@@ -64,20 +62,20 @@ let ret = ShortestPath.dijkstra ShortestPath.unit g vs _ <- evaluate ret when (PrintResult `elem` o) $ do- forM_ (sortBy (comparing fst) (IntMap.toList ret)) $ \(v, (cost,_)) -> do+ forM_ (IntMap.toAscList ret) $ \(v, (cost,_)) -> do putStrLn $ show v ++ ": " ++ show cost "bellmanford" -> do let ret = ShortestPath.bellmanFord ShortestPath.unit g vs _ <- evaluate ret when (PrintResult `elem` o) $ do- forM_ (sortBy (comparing fst) (IntMap.toList ret)) $ \(v, (cost,_)) -> do+ forM_ (IntMap.toAscList ret) $ \(v, (cost,_)) -> do putStrLn $ show v ++ ": " ++ show cost "floydwarshall" -> do let ret = ShortestPath.floydWarshall ShortestPath.unit g _ <- evaluate ret when (PrintResult `elem` o) $ do- forM_ (sortBy (comparing fst) (IntMap.toList ret)) $ \(v, m) -> do- forM_ (sortBy (comparing fst) (IntMap.toList m)) $ \(u, (cost,_)) -> do+ forM_ (IntMap.toAscList ret) $ \(v, m) -> do+ forM_ (IntMap.toAscList m) $ \(u, (cost,_)) -> do putStrLn $ show v ++ "-" ++ show u ++ ": " ++ show cost _ -> error ("unknown method: " ++ method) (_,_,errs) -> do@@ -88,10 +86,7 @@ load fname = do s <- BL.readFile fname let f l = do- -- 'BL.stripPrefix' is available only on bytestring >=0.10.8.0,- -- But we still want to support bytestring-0.10.4.0 (lts-2.22) and bytestring-0.10.6.0 (lts-3.22).- (c,l2) <- BL.uncons l- guard $ c == 'a'+ l2 <- BL.stripPrefix "a" l (v,l3) <- BL.readInt $ BL.dropWhile isSpace l2 (u,l4) <- BL.readInt $ BL.dropWhile isSpace l3 (w,_) <- BL.readInt $ BL.dropWhile isSpace l4
samples/programs/survey-propagation/survey-propagation.hs view
@@ -3,7 +3,6 @@ import Control.Exception import Control.Monad import Data.Default.Class-import Data.List import System.Console.GetOpt import System.Environment import System.Exit
samples/sat/empty-clause.cnf view
@@ -1,3 +1,2 @@ p cnf 0 1 0-
src/ToySolver/Arith/CAD.hs view
@@ -52,7 +52,7 @@ import Control.Exception import Control.Monad import Control.Monad.State-import Data.List+import Data.List (intercalate, sortOn) import Data.Maybe import Data.Ord import Data.Map (Map)@@ -73,8 +73,6 @@ import ToySolver.Data.Polynomial (Polynomial, UPolynomial, X (..), PrettyVar, PrettyCoeff) import qualified ToySolver.Data.Polynomial as P import qualified ToySolver.Data.Polynomial.GroebnerBasis as GB--import Debug.Trace -- ---------------------------------------------------------------------------
src/ToySolver/Arith/ContiTraverso.hs view
@@ -34,7 +34,7 @@ import qualified Data.IntMap as IM import qualified Data.IntSet as IS import qualified Data.Map as Map-import Data.List+import Data.List (foldl') import Data.Monoid import Data.Ratio import Data.VectorSpace
src/ToySolver/Arith/Cooper/Base.hs view
@@ -50,7 +50,7 @@ import Control.Monad import qualified Data.Foldable as Foldable-import Data.List+import Data.List (foldl', foldl1') import Data.Maybe import qualified Data.IntMap as IM import qualified Data.IntSet as IS
src/ToySolver/Arith/FourierMotzkin/Base.hs view
@@ -53,7 +53,7 @@ ) where import Control.Monad-import Data.List+import Data.List (foldl', foldl1') import Data.Maybe import Data.Ratio import qualified Data.IntMap as IM
src/ToySolver/Arith/MIP.hs view
@@ -62,7 +62,7 @@ import Control.Concurrent import Control.Concurrent.STM import Data.Default.Class-import Data.List+import Data.List (maximumBy) import Data.OptDir import Data.Ord import Data.IORef
src/ToySolver/Arith/OmegaTest/Base.hs view
@@ -43,7 +43,7 @@ import Control.Exception (assert) import Control.Monad import Data.Default.Class-import Data.List+import Data.List (foldl', foldl1', minimumBy) import Data.Maybe import Data.Ord import Data.Ratio
src/ToySolver/Arith/Simplex.hs view
@@ -127,7 +127,7 @@ import Data.Char import Data.Default.Class import Data.Ord-import Data.List+import Data.List (foldl', maximumBy, minimumBy) import Data.Maybe import Data.Monoid import Data.Primitive.MutVar@@ -504,7 +504,7 @@ where c = c1 * c2 c1 = fromIntegral $ foldl' lcm 1 [denominator c | (c, _) <- LA.terms e]- c2 = signum $ head ([c | (c,x) <- LA.terms e] ++ [1])+ c2 = signum $ fromMaybe 1 (listToMaybe [c | (c,_) <- LA.terms e]) assertLower :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> Var -> v -> m () assertLower solver x l = assertLB solver x (Just (l, IntSet.empty))
src/ToySolver/Arith/Simplex/Textbook.hs view
@@ -53,7 +53,7 @@ ) where import Data.Ord-import Data.List+import Data.List (foldl', intersperse, maximumBy, minimumBy) import qualified Data.IntMap as IM import qualified Data.IntSet as IS import Data.OptDir
src/ToySolver/BitVector/Base.hs view
@@ -44,8 +44,6 @@ import Prelude hiding (repeat) import Data.Bits-import Data.Map (Map)-import qualified Data.Map as Map import Data.Ord import qualified Data.Semigroup as Semigroup import qualified Data.Vector as V@@ -490,10 +488,10 @@ -- ------------------------------------------------------------------------ -type Model = (V.Vector BV, Map BV BV, Map BV BV)+type Model = V.Vector BV evalExpr :: Model -> Expr -> BV-evalExpr (env, divTable, remTable) = f+evalExpr env = f where f (EConst bv) = bv f (EVar v) = env VG.! varId v@@ -511,23 +509,11 @@ evalOp2 OpAdd x y = bvadd x y evalOp2 OpMul x y = bvmul x y evalOp2 OpUDiv x y- | y' /= 0 = bvudiv x y- | otherwise =- case Map.lookup x divTable of- Just d -> d- Nothing -> nat2bv (width x) 0- where- y' :: Integer- y' = bv2nat y+ | bv2nat y /= (0 :: Integer) = bvudiv x y+ | otherwise = fromAscBits (replicate (width x) True) evalOp2 OpURem x y- | y' /= 0 = bvurem x y- | otherwise =- case Map.lookup x remTable of- Just r -> r- Nothing -> nat2bv (width x) 0- where- y' :: Integer- y' = bv2nat y+ | bv2nat y /= (0 :: Integer) = bvurem x y+ | otherwise = x evalOp2 OpSDiv x y | width x < 1 || width y < 1 || width x /= width y = error "invalid width" | not msb_x && not msb_y = evalOp2 OpUDiv x y
src/ToySolver/BitVector/Solver.hs view
@@ -61,7 +61,6 @@ , svSATSolver :: SAT.Solver , svTseitin :: Tseitin.Encoder IO , svEncTable :: IORef (Map Expr (VU.Vector SAT.Lit))- , svDivRemTable :: IORef [(VU.Vector SAT.Lit, VU.Vector SAT.Lit, VU.Vector SAT.Lit, VU.Vector SAT.Lit)] , svAtomTable :: IORef (Map NormalizedAtom SAT.Lit) , svContexts :: Vec.Vec (IntMap (Maybe Int)) }@@ -72,7 +71,6 @@ sat <- SAT.newSolver tseitin <- Tseitin.newEncoder sat table <- newIORef Map.empty- divRemTable <- newIORef [] atomTable <- newIORef Map.empty contexts <- Vec.new Vec.push contexts IntMap.empty@@ -82,7 +80,6 @@ , svSATSolver = sat , svTseitin = tseitin , svEncTable = table- , svDivRemTable = divRemTable , svAtomTable = atomTable , svContexts = contexts }@@ -156,12 +153,8 @@ m <- SAT.getModel (svSATSolver solver) vss <- Vec.getElems (svVars solver) let f = fromAscBits . map (SAT.evalLit m) . VG.toList- isZero' = not . or . toAscBits env = VG.fromList [f vs | vs <- vss]- xs <- readIORef (svDivRemTable solver)- let divTable = Map.fromList [(f s, f d) | (s,t,d,_r) <- xs, isZero' (f t)]- remTable = Map.fromList [(f s, f r) | (s,t,_d,r) <- xs, isZero' (f t)]- return (env, divTable, remTable)+ return env explain :: Solver -> IO IntSet explain solver = do@@ -387,12 +380,11 @@ c <- do tmp <- encodeMul (svTseitin solver) False d t encodeSum (svTseitin solver) w False [tmp, r]- tbl <- readIORef (svDivRemTable solver)+ -- Semantics of division and remainder operators has been changed in SMT-LIB 2.6. Tseitin.addFormula (svTseitin solver) $ ite (isZero t)- (And [(isEQ s s' .&&. isZero t') .=>. (isEQ d d' .&&. isEQ r r') | (s',t',d',r') <- tbl, w == VG.length s'])+ (And [Atom l | l <- VG.toList d] .&&. isEQ s r) (isEQ s c .&&. isULT r t)- modifyIORef (svDivRemTable solver) ((s,t,d,r) :) return (d,r) encodeSDiv :: Solver -> SBV -> SBV -> IO SBV
src/ToySolver/Combinatorial/HittingSet/HTCBDD.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE DeriveDataTypeable #-} {-# OPTIONS_GHC -Wall #-} {-# OPTIONS_HADDOCK show-extensions #-} -----------------------------------------------------------------------------@@ -34,7 +33,6 @@ import qualified Data.IntMap as IntMap import Data.Set (Set) import qualified Data.Set as Set-import Data.Typeable import System.Exit import System.IO import System.IO.Temp@@ -69,7 +67,7 @@ } data Failure = Failure !Int- deriving (Show, Typeable)+ deriving (Show) instance Exception Failure
src/ToySolver/Combinatorial/HittingSet/SHD.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE DeriveDataTypeable #-} {-# OPTIONS_GHC -Wall #-} {-# OPTIONS_HADDOCK show-extensions #-} -----------------------------------------------------------------------------@@ -33,7 +32,6 @@ import qualified Data.IntMap as IntMap import Data.Set (Set) import qualified Data.Set as Set-import Data.Typeable import System.Exit import System.IO import System.IO.Temp@@ -60,7 +58,7 @@ } data Failure = Failure !Int- deriving (Show, Typeable)+ deriving (Show) instance Exception Failure
src/ToySolver/Combinatorial/Knapsack/BB.hs view
@@ -22,10 +22,10 @@ import Control.Monad import Control.Monad.State.Strict-import Data.Function (on) import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet-import Data.List+import Data.List (sortOn)+import Data.Ord type Weight = Rational type Value = Rational@@ -41,7 +41,7 @@ ) where items' :: [(Value, Weight, Int)]- items' = map fst $ sortBy (flip compare `on` snd) [((v, w, n), (v / w, v)) | (n, (v, w)) <- zip [0..] items, w > 0, v > 0]+ items' = sortOn (\(v, w, _) -> Down ((v / w, v))) [(v, w, n) | (n, (v, w)) <- zip [0..] items, w > 0, v > 0] sol :: IntSet sol = IntSet.fromList [n | (n, (v, w)) <- zip [0..] items, w == 0, v > 0] `IntSet.union`
src/ToySolver/Combinatorial/Knapsack/DPDense.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -Wall #-} {-# OPTIONS_HADDOCK show-extensions #-} {-# LANGUAGE ScopedTypeVariables #-} -----------------------------------------------------------------------------@@ -24,8 +25,6 @@ import Control.Monad import Control.Monad.ST import Data.Array.ST-import Data.Function (on)-import Data.List type Weight = Int type Value = Rational@@ -56,5 +55,8 @@ (obj, w, sol) <- readArray table limit return (obj, w, reverse sol) -test1 = solve [(5,4), (4,5), (3,2)] 9-test2 = solve [(45,5), (48,8), (35,3)] 10+_test1 :: (Value, Weight, [Bool])+_test1 = solve [(5,4), (4,5), (3,2)] 9++_test2 :: (Value, Weight, [Bool])+_test2 = solve [(45,5), (48,8), (35,3)] 10
src/ToySolver/Combinatorial/Knapsack/DPSparse.hs view
@@ -22,7 +22,7 @@ , solveGeneric ) where -import Data.List+import Data.List (foldl', foldl1') import Data.IntMap.Strict (IntMap) import qualified Data.IntMap.Strict as IntMap import Data.Map.Strict (Map)
src/ToySolver/Converter/MIP.hs view
@@ -1,6 +1,5 @@ {-# OPTIONS_GHC -Wall #-} {-# OPTIONS_HADDOCK show-extensions #-}-{-# LANGUAGE CPP #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -34,6 +33,10 @@ , ip2pb , IP2PBInfo (..) , addMIP++ -- * Linearization of the constant term in objective function+ , normalizeMIPObjective+ , NormalizeMIPObjectiveInfo (..) ) where import Control.Monad@@ -43,14 +46,12 @@ import Control.Monad.Trans.Except import qualified Data.Aeson as J import qualified Data.Aeson.Types as J-#if MIN_VERSION_aeson(2,0,0) import qualified Data.Aeson.Key as Key-#endif import Data.Aeson ((.=), (.:)) import Data.Array.IArray import Data.Default.Class import qualified Data.IntSet as IntSet-import Data.List (intercalate, foldl', sortBy)+import Data.List (intercalate, foldl', foldl1', sortBy) import Data.Maybe import Data.Map (Map) import qualified Data.Map as Map@@ -60,11 +61,15 @@ import qualified Data.Set as Set import Data.String import qualified Data.Text as T+import qualified Data.Vector as V+import qualified Data.Vector.Generic as VG import Data.VectorSpace+import Text.Printf import qualified Data.PseudoBoolean as PBFile import qualified Numeric.Optimization.MIP as MIP +import qualified ToySolver.Combinatorial.SubsetSum as SubsetSum import ToySolver.Converter.Base import ToySolver.Converter.PB import ToySolver.Data.OrdRel@@ -74,7 +79,6 @@ import qualified ToySolver.SAT.Types as SAT import qualified ToySolver.SAT.Encoder.Integer as Integer import ToySolver.SAT.Store.PB-import ToySolver.Internal.Util (revForM) -- ----------------------------------------------------------------------------- @@ -125,27 +129,30 @@ vs = [convVar v | v <- [1..PBFile.pbNumVars formula]] + varTable :: Array SAT.Var MIP.Var+ varTable = listArray (1, PBFile.pbNumVars formula) vs+ obj2 = case PBFile.pbObjectiveFunction formula of- Just obj' -> def{ MIP.objDir = MIP.OptMin, MIP.objExpr = convExpr obj' }+ Just obj' -> def{ MIP.objDir = MIP.OptMin, MIP.objExpr = convExpr varTable obj' } Nothing -> def{ MIP.objDir = MIP.OptMin, MIP.objExpr = 0 } cs2 = do (lhs,op,rhs) <- PBFile.pbConstraints formula- let (lhs2,c) = splitConst $ convExpr lhs+ let (lhs2,c) = splitConst $ convExpr varTable lhs rhs2 = rhs - c return $ case op of PBFile.Ge -> def{ MIP.constrExpr = lhs2, MIP.constrLB = MIP.Finite rhs2 } PBFile.Eq -> def{ MIP.constrExpr = lhs2, MIP.constrLB = MIP.Finite rhs2, MIP.constrUB = MIP.Finite rhs2 } -convExpr :: PBFile.Sum -> MIP.Expr Integer-convExpr s = sum [product (fromIntegral w : map f tm) | (w,tm) <- s]+convExpr :: Array SAT.Var MIP.Var -> PBFile.Sum -> MIP.Expr Integer+convExpr varTable s = sum [product (fromIntegral w : map f tm) | (w,tm) <- s] where f :: PBFile.Lit -> MIP.Expr Integer f x- | x > 0 = MIP.varExpr (convVar x)- | otherwise = 1 - MIP.varExpr (convVar (abs x))+ | x > 0 = MIP.varExpr (varTable ! x)+ | otherwise = 1 - MIP.varExpr (varTable ! abs x) convVar :: PBFile.Var -> MIP.Var convVar x = fromString ("x" ++ show x)@@ -184,16 +191,10 @@ [ "type" .= ("WBO2IPInfo" :: J.Value) , "num_original_variables" .= nv , "relax_variables" .= J.object- [ toKey (MIP.varName v) .= jPBConstraint constr+ [ Key.fromText (MIP.varName v) .= jPBConstraint constr | (v, constr) <- relaxVariables ] ]- where-#if MIN_VERSION_aeson(2,0,0)- toKey = Key.fromText-#else- toKey = id-#endif instance J.FromJSON WBO2IPInfo where parseJSON =@@ -217,8 +218,13 @@ , MIP.varDomains = Map.fromList [(v, (MIP.IntegerVariable, (0,1))) | v <- vs] } - vs = [convVar v | v <- [1..PBFile.wboNumVars formula]] ++ [v | (ts, _) <- cs2, (_, v) <- ts]+ vs1 = [convVar v | v <- [1..PBFile.wboNumVars formula]]+ vs2 = [v | (ts, _) <- cs2, (_, v) <- ts]+ vs = vs1 ++ vs2 + varTable :: Array SAT.Var MIP.Var+ varTable = listArray (1, PBFile.wboNumVars formula) vs1+ obj2 = def { MIP.objDir = MIP.OptMin , MIP.objExpr = MIP.Expr [MIP.Term w [v] | (ts, _) <- cs2, (w, v) <- ts]@@ -237,7 +243,7 @@ cs2 :: [([(Integer, MIP.Var)], MIP.Constraint Integer)] cs2 = do (v, (w, (lhs,op,rhs))) <- relaxVariables- let (lhs2,c) = splitConst $ convExpr lhs+ let (lhs2,c) = splitConst $ convExpr varTable lhs rhs2 = rhs - c (ts,ind) = case w of@@ -318,7 +324,7 @@ formula <- lift $ getPBFormula db return $ (formula{ PBFile.pbObjectiveFunction = Just obj }, info) -data IP2PBInfo = IP2PBInfo (Map MIP.Var Integer.Expr) (Map MIP.Var SAT.Lit) !Integer+data IP2PBInfo = IP2PBInfo (Map MIP.Var Integer.Expr) (Map MIP.Var SAT.Lit) !Rational deriving (Eq, Show) instance Transformer IP2PBInfo where@@ -326,7 +332,7 @@ type Target IP2PBInfo = SAT.Model instance ForwardTransformer IP2PBInfo where- transformForward (IP2PBInfo vmap nonZeroTable _d) sol+ transformForward (IP2PBInfo vmap nonZeroTable _s) sol | Map.keysSet vmap /= Map.keysSet sol = error "variables mismatch" | otherwise = array (1, x_max) $ [(x, val) | (var, Integer.Expr s) <- Map.toList vmap, (x, val) <- f s (sol Map.! var)] ++@@ -343,60 +349,45 @@ f :: SAT.PBSum -> Rational -> [(SAT.Var, Bool)] f s val | denominator val /= 1 = error "value should be integer"- | otherwise = g (numerator val - sum [c | (c, []) <- s]) (Map.toDescList tmp)+ | otherwise =+ case SubsetSum.subsetSum (V.fromList (map fst s')) d of+ Nothing -> error "failed to reconstruct boolean assignment"+ Just sol -> [if l > 0 then (l, v) else (- l, not v) | (l, v) <- zip (map snd s') (VG.toList sol)] where- tmp :: Map Integer SAT.Var- tmp =- Map.fromList- [ if c < 0 then- error "coefficient should be non-negative"- else if length ls > 1 then- error "variable definition should be linear"- else- (c, head ls)- | (c, ls) <- s, not (null ls), c /= 0- ]-- g :: Integer -> [(Integer, SAT.Var)] -> [(SAT.Var, Bool)]- g 0 [] = []- g _ [] = error "no more variables"- g v ((c,l) : ys)- | v >= c = (l, True) : g (v - c) ys- | otherwise = (l, False) : g v ys+ s' = [if null ls then (c, l) else error "variable definition should be linear" | (c, l : ls) <- s]+ d = numerator val - sum [c | (c, []) <- s] instance BackwardTransformer IP2PBInfo where- transformBackward (IP2PBInfo vmap _nonZeroTable _d) m = fmap (toRational . Integer.eval m) vmap+ transformBackward (IP2PBInfo vmap _nonZeroTable _s) m = fmap (toRational . Integer.eval m) vmap instance ObjValueTransformer IP2PBInfo where type SourceObjValue IP2PBInfo = Rational type TargetObjValue IP2PBInfo = Integer instance ObjValueForwardTransformer IP2PBInfo where- transformObjValueForward (IP2PBInfo _vmap _nonZeroTable d) val = asInteger (val * fromIntegral d)+ transformObjValueForward (IP2PBInfo _vmap _nonZeroTable s) val = asInteger (val * s) instance ObjValueBackwardTransformer IP2PBInfo where- transformObjValueBackward (IP2PBInfo _vmap _nonZeroTable d) val = fromIntegral val / fromIntegral d+ transformObjValueBackward (IP2PBInfo _vmap _nonZeroTable s) val = fromIntegral val / s instance J.ToJSON IP2PBInfo where- toJSON (IP2PBInfo vmap nonZeroTable d) =+ toJSON (IP2PBInfo vmap nonZeroTable s) = J.object [ "type" .= ("IP2PBInfo" :: J.Value) , "substitutions" .= J.object- [ toKey (MIP.varName v) .= jPBSum s+ [ Key.fromText (MIP.varName v) .= jPBSum s | (v, Integer.Expr s) <- Map.toList vmap ] , "nonzero_indicators" .= J.object- [ toKey (MIP.varName v) .= (jLitName lit :: J.Value)+ [ Key.fromText (MIP.varName v) .= (jLitName lit :: J.Value) | (v, lit) <- Map.toList nonZeroTable ]- , "objective_function_scale_factor" .= d+ , "objective_function_scale_factor" .=+ J.object+ [ "numerator" .= numerator s+ , "denominator" .= denominator s+ ] ]- where-#if MIN_VERSION_aeson(2,0,0)- toKey = Key.fromText-#else- toKey = id-#endif instance J.FromJSON IP2PBInfo where parseJSON = withTypedObject "IP2PBInfo" $ \obj -> do@@ -408,107 +399,146 @@ nonZeroTable <- liftM Map.fromList $ forM (Map.toList tmp2) $ \(name, s) -> do lit <- parseLitName s return (MIP.Var name, lit)- d <- obj .: "objective_function_scale_factor"- pure $ IP2PBInfo subst nonZeroTable d+ v <- obj .: "objective_function_scale_factor"+ s <- fmap fromInteger (J.parseJSON v) `mplus` parseRat v+ pure $ IP2PBInfo subst nonZeroTable s+ where+ parseRat = J.withObject "Rational" $ \obj -> (%)+ <$> obj .: "numerator"+ <*> obj .: "denominator" addMIP :: (SAT.AddPBNL m enc, PrimMonad m) => enc -> MIP.Problem Rational -> m (Either String (Integer.Expr, IP2PBInfo)) addMIP enc mip = runExceptT $ addMIP' enc mip addMIP' :: forall m enc. (SAT.AddPBNL m enc, PrimMonad m) => enc -> MIP.Problem Rational -> ExceptT String m (Integer.Expr, IP2PBInfo) addMIP' enc mip = do- if not (Set.null nivs) then do- throwE $ "cannot handle non-integer variables: " ++ intercalate ", " (map (T.unpack . MIP.varName) (Set.toList nivs))- else do- vmap <- liftM Map.fromList $ revForM (Set.toList ivs) $ \v -> do- case MIP.getBounds mip v of- (MIP.Finite lb, MIP.Finite ub) -> do- v2 <- lift $ Integer.newVar enc (ceiling lb) (floor ub)+ let contVars = Map.filter p (MIP.varDomains mip)+ where+ p (MIP.ContinuousVariable, _) = True+ p (MIP.SemiContinuousVariable, _) = True+ p (_, _) = False+ unless (Map.null contVars) $ do+ let n = Map.size contVars+ vars = intercalate ", " (map (T.unpack . MIP.varName) (take 10 (Map.keys contVars)) ++ ["..." | n > 10])+ msg = printf "Unsupported problem: %d (semi-)continuous variables (%s)" n vars+ throwE msg++ let unboundedVars = Map.filter p (MIP.varDomains mip)+ where+ p (_, (MIP.Finite _, MIP.Finite _)) = False+ p (_, _) = True+ unless (Map.null unboundedVars) $ do+ let n = Map.size unboundedVars+ vars = intercalate ", " (map (T.unpack . MIP.varName) (take 10 (Map.keys unboundedVars)) ++ ["..." | n > 10])+ msg = printf "Unsupported problem: %d unbounded variables (%s)" n vars+ throwE msg++ nonZeroTableRef <- lift $ newMutVar Map.empty++ vmap <- fmap Map.fromDistinctAscList $ forM (Map.toAscList (MIP.varDomains mip)) $ \(v, dom) ->+ case dom of+ (vt, (MIP.Finite lb, MIP.Finite ub)) -> do+ let lb' = ceiling lb+ ub' = floor ub+ if vt == MIP.IntegerVariable || lb' <= 0 && 0 <= ub' then do+ v2 <- lift $ Integer.newVar enc lb' ub' return (v,v2)- _ -> do- throwE $ "cannot handle unbounded variable: " ++ T.unpack (MIP.varName v)- forM_ (MIP.constraints mip) $ \c -> do- let lhs = MIP.constrExpr c- let f op rhs = do- let d = foldl' lcm 1 (map denominator (rhs:[r | MIP.Term r _ <- MIP.terms lhs]))- lhs' = sumV [asInteger (r * fromIntegral d) *^ product [vmap Map.! v | v <- vs] | MIP.Term r vs <- MIP.terms lhs]- rhs' = asInteger (rhs * fromIntegral d)- c2 = case op of- MIP.Le -> lhs' .<=. fromInteger rhs'- MIP.Ge -> lhs' .>=. fromInteger rhs'- MIP.Eql -> lhs' .==. fromInteger rhs'- case MIP.constrIndicator c of- Nothing -> lift $ Integer.addConstraint enc c2- Just (var, val) -> do- let var' = asBin (vmap Map.! var)- case val of- 1 -> lift $ Integer.addConstraintSoft enc var' c2- 0 -> lift $ Integer.addConstraintSoft enc (SAT.litNot var') c2- _ -> return ()- g = do- case MIP.constrIndicator c of- Nothing -> lift $ SAT.addClause enc []- Just (var, val) -> do- let var' = asBin (vmap Map.! var)- case val of- 1 -> lift $ SAT.addClause enc [- var']- 0 -> lift $ SAT.addClause enc [var']- _ -> return ()- case (MIP.constrLB c, MIP.constrUB c) of- (MIP.Finite x1, MIP.Finite x2) | x1==x2 -> f MIP.Eql x2- (lb, ub) -> do- case lb of- MIP.NegInf -> return ()- MIP.Finite x -> f MIP.Ge x- MIP.PosInf -> g- case ub of- MIP.NegInf -> g- MIP.Finite x -> f MIP.Le x- MIP.PosInf -> return ()+ else do+ -- vt == MIP.IntegerVariable && (0 <= lb' || ub' <= 0)+ v2@(Integer.Expr s) <- lift $ Integer.newVar enc (min 0 lb') (max 0 ub')+ lift $ do+ y <- SAT.newVar enc+ SAT.addPBNLAtLeast enc (s ++ [(- lb', [y])]) 0+ SAT.addPBNLAtMost enc (s ++ [(- ub', [y])]) 0+ modifyMutVar nonZeroTableRef (Map.insert v y)+ return (v,v2)+ _ -> error "should not happen" - nonZeroTableRef <- lift $ newMutVar Map.empty- let isNonZero :: MIP.Var -> ExceptT String m SAT.Lit- isNonZero v = do- tbl <- lift $ readMutVar nonZeroTableRef- case Map.lookup v tbl of- Just lit -> pure lit- Nothing -> do- let (MIP.Finite lb, MIP.Finite ub) = MIP.getBounds mip v- e@(Integer.Expr s) = vmap Map.! v- lit <-- if lb == 0 && ub == 1 then do- return (asBin e)- else do- v <- lift $ SAT.newVar enc- -- F(v) → F(s ≠ 0)- -- ⇐ s≠0 → v- -- ⇔ ¬v → s=0- lift $ SAT.addPBNLExactlySoft enc (- v) s 0- return v- lift $ writeMutVar nonZeroTableRef (Map.insert v lit tbl)- pure lit+ forM_ (MIP.constraints mip) $ \c -> do+ let lhs = MIP.constrExpr c+ let f op rhs = do+ let m = foldl' lcm 1 (map denominator (rhs:[r | MIP.Term r _ <- MIP.terms lhs]))+ d = foldl1' gcd (map (abs . numerator) (rhs:[r | MIP.Term r _ <- MIP.terms lhs]))+ -- For ease of understanding, no scaling is performed if the values were already integers+ s = if m == 1 then 1 else m % d+ lhs' = sumV [asInteger (r * s) *^ product [vmap Map.! v | v <- vs] | MIP.Term r vs <- MIP.terms lhs]+ rhs' = asInteger (rhs * s)+ c2 = case op of+ MIP.Le -> lhs' .<=. fromInteger rhs'+ MIP.Ge -> lhs' .>=. fromInteger rhs'+ MIP.Eql -> lhs' .==. fromInteger rhs'+ case MIP.constrIndicator c of+ Nothing -> lift $ Integer.addConstraint enc c2+ Just (var, val) -> do+ let var' = asBin (vmap Map.! var)+ case val of+ 1 -> lift $ Integer.addConstraintSoft enc var' c2+ 0 -> lift $ Integer.addConstraintSoft enc (SAT.litNot var') c2+ _ -> return ()+ g = do+ case MIP.constrIndicator c of+ Nothing -> lift $ SAT.addClause enc []+ Just (var, val) -> do+ let var' = asBin (vmap Map.! var)+ case val of+ 1 -> lift $ SAT.addClause enc [- var']+ 0 -> lift $ SAT.addClause enc [var']+ _ -> return ()+ case (MIP.constrLB c, MIP.constrUB c) of+ (MIP.Finite x1, MIP.Finite x2) | x1==x2 -> f MIP.Eql x2+ (lb, ub) -> do+ case lb of+ MIP.NegInf -> return ()+ MIP.Finite x -> f MIP.Ge x+ MIP.PosInf -> g+ case ub of+ MIP.NegInf -> g+ MIP.Finite x -> f MIP.Le x+ MIP.PosInf -> return () - forM_ (MIP.sosConstraints mip) $ \MIP.SOSConstraint{ MIP.sosType = typ, MIP.sosBody = xs } -> do- case typ of- MIP.S1 -> do- ys <- mapM (isNonZero . fst) xs- lift $ SAT.addAtMost enc ys 1- MIP.S2 -> do- ys <- mapM (isNonZero . fst) $ sortBy (comparing snd) xs- lift $ SAT.addSOS2 enc ys+ let isNonZero :: MIP.Var -> ExceptT String m SAT.Lit+ isNonZero v = do+ tbl <- lift $ readMutVar nonZeroTableRef+ case Map.lookup v tbl of+ Just lit -> pure lit+ Nothing -> do+ let (MIP.Finite lb, MIP.Finite ub) = MIP.getBounds mip v+ e@(Integer.Expr s) = vmap Map.! v+ lit <-+ if lb == 0 && ub == 1 then do+ return (asBin e)+ else do+ v <- lift $ SAT.newVar enc+ -- F(v) → F(s ≠ 0)+ -- ⇐ s≠0 → v+ -- ⇔ ¬v → s=0+ lift $ SAT.addPBNLExactlySoft enc (- v) s 0+ return v+ lift $ writeMutVar nonZeroTableRef (Map.insert v lit tbl)+ pure lit - let obj = MIP.objectiveFunction mip- d = foldl' lcm 1 [denominator r | MIP.Term r _ <- MIP.terms (MIP.objExpr obj)] *- (if MIP.objDir obj == MIP.OptMin then 1 else -1)- obj2 = sumV [asInteger (r * fromIntegral d) *^ product [vmap Map.! v | v <- vs] | MIP.Term r vs <- MIP.terms (MIP.objExpr obj)]+ forM_ (MIP.sosConstraints mip) $ \MIP.SOSConstraint{ MIP.sosType = typ, MIP.sosBody = xs } -> do+ case typ of+ MIP.S1 -> do+ ys <- mapM (isNonZero . fst) xs+ lift $ SAT.addAtMost enc ys 1+ MIP.S2 -> do+ ys <- mapM (isNonZero . fst) $ sortBy (comparing snd) xs+ lift $ SAT.addSOS2 enc ys - nonZeroTable <- readMutVar nonZeroTableRef+ let obj = MIP.objectiveFunction mip+ m = foldl' lcm 1 [denominator r | MIP.Term r _ <- MIP.terms (MIP.objExpr obj)]+ d = if null (MIP.terms (MIP.objExpr obj)) then 1+ else foldl1' gcd [abs (numerator r) | MIP.Term r _ <- MIP.terms (MIP.objExpr obj)]+ -- For ease of understanding, no scaling is performed if the values were already integers+ s = (if MIP.objDir obj == MIP.OptMin then 1 else -1) * (if m == 1 then 1 else m % d)+ obj2 = sumV [asInteger (r * s) *^ product [vmap Map.! v | v <- vs] | MIP.Term r vs <- MIP.terms (MIP.objExpr obj)] - return (obj2, IP2PBInfo vmap nonZeroTable d)+ nonZeroTable <- readMutVar nonZeroTableRef - where- ivs = MIP.integerVariables mip- nivs = MIP.variables mip `Set.difference` ivs+ return (obj2, IP2PBInfo vmap nonZeroTable s) + where asBin :: Integer.Expr -> SAT.Lit asBin (Integer.Expr [(1,[lit])]) = lit asBin _ = error "asBin: failure"@@ -517,5 +547,60 @@ asInteger r | denominator r /= 1 = error (show r ++ " is not integer") | otherwise = numerator r++-- -----------------------------------------------------------------------------++normalizeMIPObjective :: (Num c, Eq c) => MIP.Problem c -> (MIP.Problem c, NormalizeMIPObjectiveInfo r)+normalizeMIPObjective prob@MIP.Problem{ MIP.objectiveFunction = obj }+ | offset == 0 = (prob{ MIP.objectiveFunction = obj{ MIP.objExpr = e }}, NormalizeMIPObjectiveInfo Nothing)+ | otherwise =+ ( prob+ { MIP.objectiveFunction = obj{ MIP.objExpr = e + MIP.Expr [MIP.Term offset [unit_var]] }+ , MIP.varDomains = Map.insert unit_var (MIP.IntegerVariable, (MIP.Finite 1, MIP.Finite 1)) (MIP.varDomains prob)+ }+ , NormalizeMIPObjectiveInfo (Just unit_var)+ )+ where+ offset = sum [c | MIP.Term c [] <- MIP.terms (MIP.objExpr obj)]+ e = MIP.Expr [t | t@(MIP.Term _ (_:_)) <- MIP.terms (MIP.objExpr obj)]+ used = MIP.variables prob+ candidates = map MIP.Var $ "unit" : [T.pack ("unit" ++ show i) | i <- [(1::Int)..]]+ unit_var = head [name | name <- candidates, name `Set.notMember` used]++newtype NormalizeMIPObjectiveInfo r = NormalizeMIPObjectiveInfo (Maybe MIP.Var)+ deriving (Eq, Show)++instance Transformer (NormalizeMIPObjectiveInfo r) where+ type Source (NormalizeMIPObjectiveInfo r) = Map MIP.Var r+ type Target (NormalizeMIPObjectiveInfo r) = Map MIP.Var r++instance Num r => ForwardTransformer (NormalizeMIPObjectiveInfo r) where+ transformForward (NormalizeMIPObjectiveInfo Nothing) sol = sol+ transformForward (NormalizeMIPObjectiveInfo (Just v)) sol = Map.insert v 1 sol++instance BackwardTransformer (NormalizeMIPObjectiveInfo r) where+ transformBackward (NormalizeMIPObjectiveInfo Nothing) sol = sol+ transformBackward (NormalizeMIPObjectiveInfo (Just v)) sol = Map.delete v sol++instance ObjValueTransformer (NormalizeMIPObjectiveInfo r) where+ type SourceObjValue (NormalizeMIPObjectiveInfo r) = r+ type TargetObjValue (NormalizeMIPObjectiveInfo r) = r++instance ObjValueForwardTransformer (NormalizeMIPObjectiveInfo r) where+ transformObjValueForward (NormalizeMIPObjectiveInfo _) val = val++instance ObjValueBackwardTransformer (NormalizeMIPObjectiveInfo r) where+ transformObjValueBackward (NormalizeMIPObjectiveInfo _) val = val++instance J.ToJSON (NormalizeMIPObjectiveInfo r) where+ toJSON (NormalizeMIPObjectiveInfo m) =+ J.object+ [ "type" .= ("NormalizeMIPObjectiveInfo" :: J.Value)+ , "unit_var" .= fmap MIP.varName m+ ]++instance J.FromJSON (NormalizeMIPObjectiveInfo r) where+ parseJSON = withTypedObject "NormalizeMIPObjectiveInfo" $ \obj -> do+ (NormalizeMIPObjectiveInfo . fmap MIP.Var) <$> obj .: "unit_var" -- -----------------------------------------------------------------------------
src/ToySolver/Converter/MIP2SMT.hs view
@@ -22,7 +22,7 @@ import Data.Char import Data.Default.Class import Data.Ord-import Data.List+import Data.List (intersperse, sortBy) import Data.Ratio import qualified Data.Set as Set import Data.Map (Map)
src/ToySolver/Converter/PB.hs view
@@ -85,7 +85,6 @@ import qualified Data.Aeson as J import Data.Aeson ((.=), (.:)) import Data.Array.IArray-import Data.Bits hiding (And (..)) import Data.ByteString.Builder import Data.Default.Class import qualified Data.Foldable as F@@ -93,7 +92,7 @@ import qualified Data.IntMap.Strict as IntMap import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet-import Data.List+import Data.List (foldl', foldl1', intersperse) import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map import Data.Maybe@@ -102,13 +101,18 @@ import Data.Set (Set) import qualified Data.Set as Set import qualified Data.PseudoBoolean as PBFile+import qualified Data.Vector as V+import qualified Data.Vector.Generic as VG +import ToySolver.Data.Boolean (true) import ToySolver.Converter.Base+import qualified ToySolver.Combinatorial.SubsetSum as SubsetSum import qualified ToySolver.Converter.PB.Internal.Product as Product import ToySolver.Converter.Tseitin import qualified ToySolver.FileFormat.CNF as CNF import ToySolver.Internal.JSON import qualified ToySolver.SAT.Types as SAT+import qualified ToySolver.SAT.Encoder.Integer as Integer import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin import ToySolver.SAT.Encoder.Tseitin (Formula (..)) import qualified ToySolver.SAT.Encoder.PB as PB@@ -119,21 +123,59 @@ -- ----------------------------------------------------------------------------- --- XXX: we do not normalize objective function, because normalization might--- introduce constant terms, but OPB file format does not allow constant terms.+-- | Normalize 'PBFile.Formula' to be suitable for writing as OPB file. ----- Options:--- (1) not normalize objective function (current implementation),--- (2) normalize and simply delete constant terms (in pseudo-boolean package?),--- (3) normalize and introduce dummy variable to make constant terms--- into non-constant terms (in pseudo-boolean package?).-normalizePB :: PBFile.Formula -> PBFile.Formula+-- This may introduce a new variable.+normalizePB :: PBFile.Formula -> (PBFile.Formula, PBTseitinInfo) normalizePB formula =- formula- { PBFile.pbConstraints =- map normalizePBConstraint (PBFile.pbConstraints formula)- }+ case PBFile.pbObjectiveFunction formula of+ Nothing ->+ ( formula{ PBFile.pbConstraints = cs }+ , PBTseitinInfo (TseitinInfo nv nv IntMap.empty)+ )+ Just obj | (obj', offset) <- normalizePBSum obj ->+ if offset == 0 then+ ( formula+ { PBFile.pbObjectiveFunction = Just obj'+ , PBFile.pbConstraints = cs+ }+ , PBTseitinInfo (TseitinInfo nv nv IntMap.empty)+ )+ else+ case msum [detectTrueVar c | c <- cs] of+ Just v ->+ ( formula+ { PBFile.pbObjectiveFunction = Just (obj' ++ [(offset, [v])])+ , PBFile.pbConstraints = cs+ }+ , PBTseitinInfo (TseitinInfo nv nv IntMap.empty)+ )+ Nothing ->+ let v = nv + 1+ in ( formula+ { PBFile.pbObjectiveFunction = Just (obj' ++ [(offset, [v])])+ , PBFile.pbConstraints = cs ++ [([(1, [v])], PBFile.Ge, 1)]+ , PBFile.pbNumVars = v+ }+ , PBTseitinInfo (TseitinInfo nv v (IntMap.singleton v true))+ )+ where+ cs = map normalizePBConstraint (PBFile.pbConstraints formula)+ nv = PBFile.pbNumVars formula +detectTrueVar :: PBFile.Constraint -> Maybe SAT.Var+detectTrueVar (lhs, op, rhs) =+ case op of+ PBFile.Ge -> f lhs rhs+ PBFile.Eq -> f lhs rhs `mplus` f [(- c, ls) | (c,ls) <- lhs] (- rhs)+ where+ f [(c, ls)] rhs+ | c > 0 && (rhs + c - 1) `div` c >= 1 =+ -- c L ≥ rhs ↔ L ≥ ⌈rhs / c⌉+ listToMaybe [l | l <- ls, l > 0]+ f _ _ = Nothing++-- | Normalize 'PBFile.SoftFormula' to be suitable for writing as WBO file. normalizeWBO :: PBFile.SoftFormula -> PBFile.SoftFormula normalizeWBO formula = formula@@ -143,11 +185,18 @@ normalizePBConstraint :: PBFile.Constraint -> PBFile.Constraint normalizePBConstraint (lhs,op,rhs) =- case mapAccumL h 0 lhs of- (offset, lhs') -> (lhs', op, rhs - offset)+ case normalizePBSum lhs of+ (lhs', offset) -> (lhs', op, rhs - offset)++normalizePBSum :: PBFile.Sum -> (PBFile.Sum, Integer)+normalizePBSum s =+ case foldl' h ([], 0) s of+ (s', offset) -> (reverse s', offset) where- h s (w,[x]) | x < 0 = (s+w, (-w,[-x]))- h s t = (s,t)+ h (s', offset) (0,_) = (s', offset)+ h (s', offset) (w,[x]) | x < 0 = ((-w,[-x]) : s', offset+w)+ h (s', offset) (w,[]) = (s', offset + w)+ h (s', offset) t = (t : s', offset) -- ----------------------------------------------------------------------------- @@ -403,7 +452,7 @@ -- ----------------------------------------------------------------------------- --- | Convert inequality constraints into equality constraints by introducing surpass variables.+-- | Convert inequality constraints into equality constraints by introducing surplus variables. inequalitiesToEqualitiesPB :: PBFile.Formula -> (PBFile.Formula, PBInequalitiesToEqualitiesInfo) inequalitiesToEqualitiesPB formula = runST $ do db <- newPBStore@@ -419,17 +468,20 @@ Just clause -> do SAT.addPBNLExactly db [(1, [- l | l <- clause])] 0 return Nothing- Nothing -> do- let maxSurpass = max (SAT.pbUpperBound lhs - rhs) 0- maxSurpassNBits = head [i | i <- [0..], maxSurpass < bit i]- vs <- SAT.newVars db maxSurpassNBits- SAT.addPBNLExactly db (lhs ++ [(-c,[x]) | (c,x) <- zip (iterate (*2) 1) vs]) rhs- if maxSurpassNBits > 0 then do- return $ Just (lhs, rhs, vs)- else- return Nothing+ Nothing+ | SAT.pbLowerBound lhs > rhs -> return Nothing+ | otherwise -> do+ let (lhs', rhs') = simplifyPBAtLeast (lhs, rhs)+ maxSurplus = max (SAT.pbUpperBound lhs' - rhs') 0+ surplus <- Integer.newVarPBLinSum db maxSurplus+ SAT.addPBNLExactly db (lhs' ++ [(-c,[l]) | (c,l) <- surplus]) rhs'+ if maxSurplus > 0 then do+ return $ Just (lhs', rhs', surplus)+ else+ return Nothing formula' <- getPBFormula db+ unless (all (\(_, op, _) -> op == PBFile.Eq) (PBFile.pbConstraints formula')) $ error "should not happen" return ( formula'{ PBFile.pbObjectiveFunction = PBFile.pbObjectiveFunction formula } , PBInequalitiesToEqualitiesInfo (PBFile.pbNumVars formula) (PBFile.pbNumVars formula') defs@@ -452,8 +504,21 @@ (lhs'', 1) | all (\(c,_) -> c == 1) lhs'' -> return (map snd lhs'') _ -> mzero + simplifyPBAtLeast :: (SAT.PBSum, Integer) -> (SAT.PBSum, Integer)+ simplifyPBAtLeast (lhs, rhs) =+ case splitConst lhs of+ (lhs', offset) ->+ let rhs' = rhs - offset+ d = case lhs' of+ [] -> 1+ _ -> abs $ foldl1' gcd (map fst lhs')+ in ([(c `div` d, ls) | (c,ls) <- lhs'], (rhs' + d - 1) `div` d)++ splitConst :: SAT.PBSum -> (SAT.PBSum, Integer)+ splitConst s = ([t | t@(c, _:_) <- s, c /= 0], sum [c | (c, []) <- s])+ data PBInequalitiesToEqualitiesInfo- = PBInequalitiesToEqualitiesInfo !Int !Int [(PBFile.Sum, Integer, [SAT.Var])]+ = PBInequalitiesToEqualitiesInfo !Int !Int [(PBFile.Sum, Integer, SAT.PBLinSum)] deriving (Eq, Show) instance Transformer PBInequalitiesToEqualitiesInfo where@@ -462,7 +527,16 @@ instance ForwardTransformer PBInequalitiesToEqualitiesInfo where transformForward (PBInequalitiesToEqualitiesInfo _nv1 nv2 defs) m =- array (1, nv2) $ assocs m ++ [(v, testBit n i) | (lhs, rhs, vs) <- defs, let n = SAT.evalPBSum m lhs - rhs, (i,v) <- zip [0..] vs]+ array (1, nv2) $ assocs m ++ concat+ [ if lhsVal >= rhs then+ case SubsetSum.subsetSum (V.fromList (map fst surplus)) (lhsVal - rhs) of+ Nothing -> error ("failed to construct surplus assignment")+ Just sol -> [if l > 0 then (l, v) else (- l, not v) | (l, v) <- zip (map snd surplus) (VG.toList sol)]+ else+ [if l > 0 then (l, False) else (-l, True) | (_, l) <- surplus]+ | (lhs, rhs, surplus) <- defs+ , let lhsVal = SAT.evalPBSum m lhs+ ] instance BackwardTransformer PBInequalitiesToEqualitiesInfo where transformBackward (PBInequalitiesToEqualitiesInfo nv1 _nv2 _defs) = SAT.restrictModel nv1@@ -483,13 +557,13 @@ [ "type" .= ("PBInequalitiesToEqualitiesInfo" :: J.Value) , "num_original_variables" .= nv1 , "num_transformed_variables" .= nv2- , "slack" .=+ , "definitions" .= [ J.object [ "lhs" .= jPBSum lhs , "rhs" .= rhs- , "slack" .= [jVarName v :: J.Value | v <- vs]+ , "surplus" .= jPBLinSum surplus ]- | (lhs, rhs, vs) <- defs+ | (lhs, rhs, surplus) <- defs ] ] @@ -498,15 +572,13 @@ PBInequalitiesToEqualitiesInfo <$> obj .: "num_original_variables" <*> obj .: "num_transformed_variables"- <*> (mapM f =<< obj .: "slack")+ <*> (mapM f =<< obj .: "definitions") where- f = J.withObject "slack" $ \obj -> do+ f = J.withObject "definition" $ \obj -> do lhs <- parsePBSum =<< obj .: "lhs" rhs <- obj .: "rhs"- vs <- mapM g =<< obj .: "slack"- return (lhs, rhs, vs)- g ('x' : rest) = pure $! read rest- g s = fail ("fail to parse variable: " ++ show s)+ surplus <- parsePBLinSum =<< obj .: "surplus"+ return (lhs, rhs, surplus) -- ----------------------------------------------------------------------------- @@ -569,14 +641,26 @@ p = obj1ub - obj1lb + 1 obj2 = [(p*c, IntSet.toList ls) | (ls, c) <- Map.toList obj2', c /= 0] obj2' = Map.unionsWith (+) [sq ((-rhs, []) : lhs) | (lhs, PBFile.Eq, rhs) <- PBFile.pbConstraints formula]- sq ts = Map.fromListWith (+) $ do- (c1,ls1) <- ts- (c2,ls2) <- ts- let ls3 = IntSet.fromList ls1 `IntSet.union` IntSet.fromList ls2- guard $ not $ isFalse ls3- return (ls3, c1*c2)- isFalse ls = not $ IntSet.null $ ls `IntSet.intersection` IntSet.map negate ls+ sq ts = Map.unionWith (+) sq1 sq2+ where+ ts' = [ (c, ls', neg, pos)+ | (c, ls) <- ts, c /= 0+ , let ls' = IntSet.fromList ls, let (neg, pos) = IntSet.split 0 ls'+ , not (contradict neg pos)+ ]+ sq1 = Map.fromListWith (+) [(ls, c^(2::Int)) | (c, ls, _, _) <- ts']+ sq2 = Map.fromListWith (+) $ do+ ((c1, ls1, neg1, pos1), (c2, ls2, neg2, pos2)) <- pairs ts'+ guard $ not $ contradict neg1 pos2+ guard $ not $ contradict neg2 pos1+ return (ls1 `IntSet.union` ls2, 2*c1*c2)+ contradict ls1 ls2 =+ not $ IntSet.null $ IntSet.fromAscList (map negate (IntSet.toDescList ls1)) `IntSet.intersection` ls2 +pairs :: [a] -> [(a, a)]+pairs [] = []+pairs (x:xs) = [(x,y) | y <- xs] ++ pairs xs+ -- ----------------------------------------------------------------------------- pb2qubo' :: PBFile.Formula -> ((PBFile.Formula, Integer), PB2QUBOInfo')@@ -716,7 +800,6 @@ objRef <- newMutVar [] objOffsetRef <- newMutVar 0 defsRef <- newMutVar []- trueLitRef <- newMutVar SAT.litUndef forM_ (PBFile.wboConstraints wbo) $ \(cost, constr@(lhs,op,rhs)) -> do case cost of@@ -724,11 +807,6 @@ case op of PBFile.Ge -> SAT.addPBNLAtLeast db lhs rhs PBFile.Eq -> SAT.addPBNLExactly db lhs rhs- trueLit <- readMutVar trueLitRef- when (trueLit == SAT.litUndef) $ do- case detectTrueLit constr of- Nothing -> return ()- Just l -> writeMutVar trueLitRef l Just w -> do case op of PBFile.Ge -> do@@ -767,42 +845,17 @@ modifyMutVar defsRef ((sel,constr) :) offset <- readMutVar objOffsetRef- when (offset /= 0) $ do- l <- readMutVar trueLitRef- trueLit <-- if l /= SAT.litUndef then- return l- else do- v <- SAT.newVar db- SAT.addClause db [v]- modifyMutVar defsRef ((v, ([], PBFile.Ge, 0)) :)- return v- modifyMutVar objRef ((offset,[trueLit]) :)+ when (offset /= 0) $ modifyMutVar objRef ((offset,[]) :) obj <- liftM reverse $ readMutVar objRef defs <- liftM IntMap.fromList $ readMutVar defsRef case PBFile.wboTopCost wbo of- Nothing -> return ()- Just t -> SAT.addPBNLAtMost db obj (t - 1)+ Just t | t <= sum [w | (Just w, _) <- PBFile.wboConstraints wbo] -> SAT.addPBNLAtMost db obj (t - 1)+ _ -> return () return (obj, defs) --detectTrueLit :: PBFile.Constraint -> Maybe SAT.Lit-detectTrueLit (lhs, op, rhs) =- case op of- PBFile.Ge -> f lhs rhs- PBFile.Eq -> f lhs rhs `mplus` f [(- c, ls) | (c,ls) <- lhs] (- rhs)- where- f [(c, [l])] rhs- | c > 0 && (rhs + c - 1) `div` c == 1 =- -- c l ≥ rhs ↔ l ≥ ⌈rhs / c⌉- return l- | c < 0 && rhs `div` c == 0 =- -- c l ≥ rhs ↔ l ≤ ⌊rhs / c⌋- return (- l)- f _ _ = Nothing -- -----------------------------------------------------------------------------
src/ToySolver/Converter/PB/Internal/Product.hs view
@@ -16,10 +16,9 @@ import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet-import Data.List hiding (insert)+import Data.List (foldl', sortOn) import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map-import Data.Ord import Data.Set (Set) import qualified Data.Set as Set @@ -31,7 +30,7 @@ decompose1 :: Set IntSet -> Map IntSet (Maybe (IntSet,IntSet)) decompose1 ss = snd $ foldl' (flip f) (LargestIntersectionFinder.empty, Map.empty) ss' where- ss' = map fst $ sortBy (comparing snd) [(s, IntSet.size s) | s <- Set.toList ss]+ ss' = sortOn IntSet.size (Set.toList ss) f :: IntSet -> (LargestIntersectionFinder.Table, Map IntSet (Maybe (IntSet,IntSet)))
src/ToySolver/Converter/QUBO.hs view
@@ -38,7 +38,7 @@ import Data.Array.Unboxed import Data.IntMap.Strict (IntMap) import qualified Data.IntMap.Strict as IntMap-import Data.List+import Data.List (foldl') import Data.Maybe import qualified Data.PseudoBoolean as PBFile import Data.Ratio
src/ToySolver/Converter/SAT2MIS.hs view
@@ -102,11 +102,9 @@ instance ForwardTransformer SAT3ToISInfo where transformForward (SAT3ToISInfo _nv clusters nodeToLit) m = IntSet.fromList $ do nodes <- clusters- let xs = [node | node <- nodes, SAT.evalLit m (nodeToLit ! node)]- if null xs then- error "not a model"- else- return (head xs)+ case [node | node <- nodes, SAT.evalLit m (nodeToLit ! node)] of+ [] -> error "not a model"+ x : _ -> return x instance BackwardTransformer SAT3ToISInfo where transformBackward (SAT3ToISInfo nv _clusters nodeToLit) indep_set = runSTUArray $ do
src/ToySolver/Data/AlgebraicNumber/Real.hs view
@@ -50,7 +50,7 @@ import Control.Exception (assert) import Control.Monad-import Data.List+import Data.List (delete, elemIndex, sort) import Data.Ratio import qualified Data.Set as Set import qualified Text.PrettyPrint.HughesPJClass as PP
src/ToySolver/Data/AlgebraicNumber/Root.hs view
@@ -20,7 +20,7 @@ ----------------------------------------------------------------------------- module ToySolver.Data.AlgebraicNumber.Root where -import Data.List+import Data.List (inits) import Data.Maybe import Data.Map (Map) import qualified Data.Map as Map
src/ToySolver/Data/AlgebraicNumber/Sturm.hs view
@@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module : ToySolver.Data.AlgebraicNumber.Sturm--- Copyright : (c) Masahiro Sakai 2012+-- Copyright : (c) Masahiro Sakai 2012-2026 -- License : BSD-style -- -- Maintainer : masahiro.sakai@gmail.com@@ -31,6 +31,8 @@ , narrow' , approx , approx'++ , cauchysBounds ) where import Data.Maybe@@ -95,14 +97,21 @@ | otherwise = go x2 xs (r+1) -- | Closed interval that contains all real roots of a given polynomial.--- 根の限界--- <http://aozoragakuen.sakura.ne.jp/taiwa/taiwaNch02/node26.html>+--+-- Currently Cauchy's bounds ('cauchysBounds') is used. bounds :: UPolynomial Rational -> (Rational, Rational) bounds p = (-m, m) where- m = if p==0- then 0- else max 1 (sum [abs (c/s) | (c,_) <- P.terms p] - 1)+ m = cauchysBounds p++-- | Cauchy's upper bounds for the magnitudes of all roots+--+-- <https://en.wikipedia.org/wiki/Geometrical_properties_of_polynomial_roots>+cauchysBounds :: UPolynomial Rational -> Rational+cauchysBounds p+ | P.deg p == 0 = 0+ | otherwise = 1 + maximum (0 : [abs (c/s) | (c,xs) <- P.terms p, P.deg xs /= P.deg p])+ where s = P.lc P.nat p boundInterval :: UPolynomial Rational -> Interval Rational -> Interval Rational
src/ToySolver/Data/BoolExpr.hs view
@@ -44,7 +44,7 @@ | Imply (BoolExpr a) (BoolExpr a) | Equiv (BoolExpr a) (BoolExpr a) | ITE (BoolExpr a) (BoolExpr a) (BoolExpr a)- deriving (Eq, Ord, Show, Read, Typeable, Data)+ deriving (Eq, Ord, Show, Read, Data) instance Functor BoolExpr where fmap = fmapDefault
src/ToySolver/Data/LA.hs view
@@ -65,7 +65,7 @@ import Control.Monad import Control.DeepSeq-import Data.List+import Data.List (intersperse) import Data.Maybe import Data.IntMap.Strict (IntMap) import qualified Data.IntMap.Strict as IntMap
src/ToySolver/Data/Polyhedron.hs view
@@ -20,7 +20,7 @@ , toConstraints ) where -import Data.List+import Data.List (foldl', transpose) import Data.Ratio import qualified Data.IntSet as IntSet import Data.Map (Map)@@ -52,16 +52,13 @@ vars (Polyhedron m) = IntSet.unions [vars e | e <- Map.keys m] vars Empty = IntSet.empty -instance JoinSemiLattice Polyhedron where- join Empty b = b- join a Empty = a- join (Polyhedron m1) (Polyhedron m2) =- normalize $ Polyhedron (Map.intersectionWith Interval.join m1 m2)--instance MeetSemiLattice Polyhedron where- meet = intersection+instance Lattice Polyhedron where+ Empty \/ b = b+ a \/ Empty = a+ Polyhedron m1 \/ Polyhedron m2 =+ normalize $ Polyhedron (Map.intersectionWith Interval.hull m1 m2) -instance Lattice Polyhedron+ (/\) = intersection instance BoundedJoinSemiLattice Polyhedron where bottom = empty@@ -69,8 +66,6 @@ instance BoundedMeetSemiLattice Polyhedron where top = univ -instance BoundedLattice Polyhedron- normalize :: Polyhedron -> Polyhedron normalize (Polyhedron m) | any Interval.null (Map.elems m) = Empty normalize p = p@@ -96,10 +91,10 @@ map (foldl' intersection univ) $ transpose $ map fromAtom cs fromAtom :: AtomR -> [Polyhedron]-fromAtom (Rel lhs NEq rhs) =+fromAtom (OrdRel lhs NEq rhs) = fromAtom (lhs .<. rhs) ++ fromAtom (lhs .>. rhs)-fromAtom (Rel lhs op rhs) =- case LA.extract LA.unitVar (lhs .-. rhs) of+fromAtom (OrdRel lhs op rhs) =+ case LA.extract LA.unitVar (lhs ^-^ rhs) of (c, e1) -> case toRat e1 of (lhs1, d) ->@@ -110,10 +105,10 @@ else (lhs1, op, rhs1) ival = case op of- Lt -> Interval.interval Nothing (Just (False, rhs2))- Le -> Interval.interval Nothing (Just (True, rhs2))- Ge -> Interval.interval (Just (True, rhs2)) Nothing- Gt -> Interval.interval (Just (False, rhs2)) Nothing+ Lt -> Interval.NegInf Interval.<..< Interval.Finite rhs2+ Le -> Interval.NegInf Interval.<..<= Interval.Finite rhs2+ Ge -> Interval.Finite rhs2 Interval.<=..< Interval.PosInf+ Gt -> Interval.Finite rhs2 Interval.<..< Interval.PosInf Eql -> Interval.singleton rhs2 NEq -> error "should not happen" in filter (Empty /=) [normalize $ Polyhedron (Map.singleton lhs2 ival)]@@ -124,14 +119,16 @@ toConstraints (Polyhedron m) = do (e, ival) <- Map.toList m let e' = LA.mapCoeff fromIntegral e- xs = case Interval.lowerBound ival of- Nothing -> []- Just (True,c) -> [LA.constant c .<=. e']- Just (False,c) -> [LA.constant c .<. e']- ys = case Interval.upperBound ival of- Nothing -> []- Just (True,c) -> [e' .<=. LA.constant c]- Just (False,c) -> [e' .<. LA.constant c]+ xs = case Interval.lowerBound' ival of+ (Interval.NegInf, _) -> []+ (Interval.PosInf, _) -> undefined+ (Interval.Finite c, Interval.Closed) -> [LA.constant c .<=. e']+ (Interval.Finite c, Interval.Open) -> [LA.constant c .<. e']+ ys = case Interval.upperBound' ival of+ (Interval.NegInf, _) -> undefined+ (Interval.PosInf, _) -> []+ (Interval.Finite c, Interval.Closed) -> [e' .<=. LA.constant c]+ (Interval.Finite c, Interval.Open) -> [e' .<. LA.constant c] xs ++ ys p :: ExprZ -> Bool
src/ToySolver/Data/Polynomial/Base.hs view
@@ -139,7 +139,8 @@ import qualified Data.FiniteField as FF import Data.Function import Data.Hashable-import Data.List+import Data.List (foldl', foldl1', intersperse, maximumBy, sortBy)+import qualified Data.List.NonEmpty as NonEmpty import Data.Numbers.Primes (primeFactors) import Data.Ratio import Data.String (IsString (..))@@ -175,7 +176,7 @@ -- | Polynomial over commutative ring r newtype Polynomial r v = Polynomial{ coeffMap :: Map (Monomial v) r }- deriving (Eq, Ord, Typeable)+ deriving (Eq, Ord) instance (Eq k, Num k, Ord v) => Num (Polynomial k v) where (+) = plus@@ -404,7 +405,7 @@ divModMP :: forall k v. (Eq k, Fractional k, Ord v) => MonomialOrder v -> Polynomial k v -> [Polynomial k v] -> ([Polynomial k v], Polynomial k v)-divModMP cmp p fs = go IntMap.empty (terms' p)+divModMP cmp p fs = go IntMap.empty [] (terms' p) where terms' :: Polynomial k v -> [Term k v] terms' g = sortBy (flip cmp `on` snd) (terms g)@@ -421,20 +422,26 @@ 0 -> merge xs ys c -> (c, snd x) : merge xs ys - ls = zip [0..] [(lt cmp f, terms' f) | f <- fs]+ -- For each divisor: its index, its leading term, and its remaining+ -- (lower) terms in descending order with respect to @cmp@.+ -- Zero divisors have no terms and are simply skipped.+ ls :: [(Int, Term k v, [Term k v])]+ ls = [(i, a, rest) | (i, f) <- zip [0..] fs, (a : rest) <- [terms' f]] - go :: IntMap (Polynomial k v) -> [Term k v] -> ([Polynomial k v], Polynomial k v)- go qs g =- case xs of- [] -> ([IntMap.findWithDefault 0 i qs | i <- [0 .. length fs - 1]], fromTerms g)- (i, b, g') : _ -> go (IntMap.insertWith (+) i b qs) g'- where- xs = do- (i,(a,f)) <- ls- h <- g- guard $ a `tdivides` h- let b = tdiv h a- return (i, fromTerm b, merge g [(tscale (-1) b `tmult` m) | m <- f])+ -- @g@ holds the terms of the dividend not yet processed, kept sorted in+ -- descending order with respect to @cmp@; @rs@ accumulates the terms of+ -- the remainder. At each step we look at the leading term @h@ of @g@ and+ -- either reduce it by a divisor or, if no divisor's leading term divides+ -- it, move it to the remainder.+ go :: IntMap (Polynomial k v) -> [Term k v] -> [Term k v]+ -> ([Polynomial k v], Polynomial k v)+ go qs rs [] = ([IntMap.findWithDefault 0 i qs | i <- [0 .. length fs - 1]], fromTerms rs)+ go qs rs (h : g) =+ case [(i, b, rest) | (i, a, rest) <- ls, a `tdivides` h, let b = tdiv h a] of+ [] -> go qs (h : rs) g+ (i, b, rest) : _ ->+ go (IntMap.insertWith (+) i (fromTerm b) qs) rs+ (merge g [tscale (-1) b `tmult` m | m <- rest]) -- | Multivariate division algorithm --@@ -445,7 +452,10 @@ reduce cmp p fs = go p where ls = [(lt cmp f, f) | f <- fs]- go g = if null xs then g else go (head xs)+ go g =+ case xs of+ [] -> g+ x : _ -> go x where ms = sortBy (flip cmp `on` snd) (terms g) xs = do@@ -486,7 +496,7 @@ | otherwise = eisensteinsCriterion' (pp p) eisensteinsCriterion' :: UPolynomial Integer -> Bool-eisensteinsCriterion' p = or [criterion prime | prime <- map head $ group $ primeFactors c]+eisensteinsCriterion' p = or [criterion prime | prime <- map NonEmpty.head $ NonEmpty.group $ primeFactors c] where Just ((_,an), ts) = Map.maxViewWithKey (coeffMap p) a0 = coeff mone p@@ -615,7 +625,7 @@ -- | Variable "x" data X = X- deriving (Eq, Ord, Bounded, Enum, Show, Read, Typeable, Data)+ deriving (Eq, Ord, Bounded, Enum, Show, Read, Data) instance NFData X where rnf a = a `seq` ()@@ -778,7 +788,7 @@ -- | Monic monomials newtype Monomial v = Monomial{ mindicesMap :: Map v Integer }- deriving (Eq, Ord, Typeable)+ deriving (Eq, Ord) type UMonomial = Monomial X
src/ToySolver/Data/Polynomial/Factorization/FiniteField.hs view
@@ -34,7 +34,7 @@ import Control.Exception (assert) import Data.FiniteField-import Data.List+import Data.List (sortOn) import Data.Ord import Data.Set (Set) import qualified Data.Set as Set
src/ToySolver/Data/Polynomial/Factorization/Kronecker.hs view
@@ -21,7 +21,7 @@ ( factor ) where -import Data.List+import Data.List (find) import Data.MultiSet (MultiSet) import qualified Data.MultiSet as MultiSet import Data.Numbers.Primes (primes)
src/ToySolver/Data/Polynomial/Factorization/Zassenhaus.hs view
@@ -28,7 +28,7 @@ import Control.Monad import Control.Monad.ST import Control.Exception (assert)-import Data.List+import Data.List ((\\)) import Data.Maybe import Data.Numbers.Primes (primes) import Data.Ratio
src/ToySolver/Data/Polynomial/Interpolation/Hermite.hs view
@@ -12,7 +12,7 @@ -- -- References: ----- * Lagrange polynomial <https://en.wikipedia.org/wiki/Hermite_interpolation>+-- * Hermite interpolation, <https://en.wikipedia.org/wiki/Hermite_interpolation> -- ----------------------------------------------------------------------------- module ToySolver.Data.Polynomial.Interpolation.Hermite
src/ToySolver/EUF/FiniteModelFinder.hs view
@@ -63,7 +63,7 @@ import Data.Interned (intern, unintern) import Data.Interned.Text import Data.IORef-import Data.List+import Data.List (intercalate) import Data.Maybe import Data.Map (Map) import qualified Data.Map as Map
src/ToySolver/FileFormat/Base.hs view
@@ -1,7 +1,6 @@ {-# OPTIONS_GHC -Wall #-} {-# OPTIONS_HADDOCK show-extensions #-} {-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE OverloadedStrings #-} ----------------------------------------------------------------------------- -- |@@ -22,6 +21,9 @@ , parseFile , readFile , writeFile++ -- * Utility functions+ , getBaseExtension ) where import Prelude hiding (readFile, writeFile)@@ -29,7 +31,7 @@ import Control.Monad.IO.Class import qualified Data.ByteString.Lazy.Char8 as BS import Data.ByteString.Builder hiding (writeFile)-import Data.Typeable+import Data.Char import System.IO hiding (readFile, writeFile) #ifdef WITH_ZLIB@@ -48,7 +50,7 @@ -- | 'ParseError' represents a parse error and it wraps a error message. data ParseError = ParseError String- deriving (Show, Typeable)+ deriving (Show) instance Exception ParseError @@ -87,3 +89,16 @@ #else hPutBuilder h (render a) #endif++-- | Get base extension of a filename+--+-- Supported compression format extensions (e.g. @.gz@) are removed, and extensions such as @.cnf@ are returned.+--+-- @since 0.10.0+getBaseExtension :: FilePath -> String+getBaseExtension name | (base, ext) <- splitExtension name =+ case map toLower ext of+#ifdef WITH_ZLIB+ ".gz" -> getBaseExtension base+#endif+ s -> s
+ src/ToySolver/Internal/SolutionChecker.hs view
@@ -0,0 +1,307 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+-----------------------------------------------------------------------------+-- |+-- Module : ToySolver.Internal.SolutionChecker+-- Copyright : (c) Masahiro Sakai 2025+-- License : BSD-style+--+-- Maintainer : masahiro.sakai@gmail.com+-- Stability : unstable+-- Portability : non-portable+--+-----------------------------------------------------------------------------++module ToySolver.Internal.SolutionChecker+ ( checkSATResult+ , checkMaxSATResult+ , checkPBResult+ , checkWBOResult+ , checkMIPResult+ ) where++import Control.Monad+import Control.Monad.RWS.Lazy+import qualified Data.ByteString.Char8 as BS+import Data.List (intercalate, sortBy)+import qualified Data.Map.Lazy as Map+import Data.Maybe+import Data.Ord+import qualified Data.PseudoBoolean as PBFile+import Data.Scientific+import Data.String+import qualified Data.Text as T+import qualified Numeric.Optimization.MIP as MIP+import Text.Printf++import qualified ToySolver.FileFormat.CNF as CNF+import qualified ToySolver.SAT.Types as SAT++-- ------------------------------------------------------------------------++type M = RWS () [String] Bool++execM :: M () -> (Bool, [String])+execM m = execRWS m () True++addInfo :: String -> M ()+addInfo s = tell [s]++addError :: String -> M ()+addError s = tell [s] >> put False++-- ------------------------------------------------------------------------++checkSATResult :: CNF.CNF -> (BS.ByteString, Maybe SAT.Model) -> (Bool, [String])+checkSATResult cnf (status, m) = execM $ do+ case status of+ "SATISFIABLE" -> do+ when (isNothing m) $ do+ addError "SATISFIABLE, but a model is missing"+ "UNSATISFIABLE" -> do+ when (isJust m) $ do+ addError "UNSATISFIABLE, but a model is provided"+ "UNKNOWN" -> return ()+ _ -> do+ addError $ "unknown status: " ++ BS.unpack status++ case m of+ Nothing -> return ()+ Just model -> do+ forM_ (CNF.cnfClauses cnf) $ \constr ->+ unless (SAT.evalClause model (SAT.unpackClause constr)) $ do+ addError $ printf "violated: %s" (showClause constr :: String)++checkMaxSATResult :: CNF.WCNF -> (BS.ByteString, Maybe Integer, Maybe SAT.Model) -> (Bool, [String])+checkMaxSATResult wcnf (status, o, m) = execM $ do+ case status of+ "OPTIMUM FOUND" -> do+ when (isNothing m) $ do+ addError "OPTIMUM FOUND, but a model is missing"+ "SATISFIABLE" -> do+ when (isNothing m) $ do+ addError "SATISFIABLE, but a model is missing"+ "UNSATISFIABLE" -> do+ when (isJust m) $ do+ addError "UNSATISFIABLE, but a model is provided"+ "UNKNOWN" -> return ()+ _ -> do+ addError $ "unknown status: " ++ BS.unpack status++ case m of+ Nothing -> return ()+ Just model -> do+ cost <- fmap sum $ forM (CNF.wcnfClauses wcnf) $ \(w, constr) ->+ if SAT.evalClause model (SAT.unpackClause constr) then do+ return 0+ else if w == CNF.wcnfTopCost wcnf then do+ addError $ printf "violated hard constraint: %s" (showClause constr :: String)+ return 0+ else do+ return w+ addInfo $ "total cost = " ++ show cost++ case o of+ Just oVal | oVal /= cost -> do+ addError $ printf "o-line value (%d) is inconsistent" oVal+ _ -> return ()++checkPBResult :: PBFile.Formula -> (BS.ByteString, Maybe Integer, Maybe SAT.Model) -> (Bool, [String])+checkPBResult opb (status, o, m) = execM $ do+ case status of+ "SATISFIABLE" -> do+ when (isNothing m) $ do+ addError "SATISFIABLE, but a model is missing"+ "OPTIMUM FOUND" -> do+ when (isNothing m) $ do+ addError "OPTIMUM FOUND, but a model is missing"+ "UNSATISFIABLE" -> do+ when (isJust m) $ do+ addError "UNSATISFIABLE, but a model is provided"+ "UNSUPPORTED" -> return ()+ "UNKNOWN" -> return ()+ _ -> do+ addError $ "unknown status: " ++ BS.unpack status+++ case (PBFile.pbObjectiveFunction opb, o) of+ (Nothing, Just _) -> do+ addInfo $ "o-line(s) exist even though it is a PBS problem. (will be ignored)"+ _ -> pure ()++ case m of+ Nothing -> return ()+ Just model -> do+ case PBFile.pbObjectiveFunction opb of+ Nothing -> return ()+ Just objFunc -> do+ let val = SAT.evalPBSum model objFunc+ addInfo $ "objective function value = " ++ show val+ case o of+ Just oVal | val /= oVal -> do+ addError $ printf "o-line value (%d) is inconsistent" oVal+ _ -> return ()++ forM_ (PBFile.pbConstraints opb) $ \constr -> do+ unless (SAT.evalPBConstraint model constr) $ do+ addError $ printf "violated: %s" (showPBConstraint constr :: String)++checkWBOResult :: PBFile.SoftFormula -> (BS.ByteString, Maybe Integer, Maybe SAT.Model) -> (Bool, [String])+checkWBOResult wbo (status, o, m) = execM $ do+ case status of+ "SATISFIABLE" -> do+ when (isNothing m) $ do+ addError "SATISFIABLE, but a model is missing"+ "OPTIMUM FOUND" -> do+ when (isNothing m) $ do+ addError "OPTIMUM FOUND, but a model is missing"+ "UNSATISFIABLE" -> do+ when (isJust m) $ do+ addError "UNSATISFIABLE, but a model is provided"+ "UNSUPPORTED" -> return ()+ "UNKNOWN" -> return ()+ _ -> do+ addError $ "unknown status: " ++ BS.unpack status++ case m of+ Nothing -> return ()+ Just model -> do+ cost <- fmap sum $ forM (PBFile.wboConstraints wbo) $ \(w, constr) -> do+ if SAT.evalPBConstraint model constr then+ return 0+ else do+ case w of+ Nothing -> do+ addError $ printf "violated hard constraint: %s" (showPBConstraint constr :: String)+ return 0+ Just w' -> do+ return w'+ addInfo $ "total cost = " ++ show cost++ case PBFile.wboTopCost wbo of+ Just top | top <= cost -> do+ addError $ printf "total cost (%d) is greater than or equal to top cost (%d)" cost top+ _ -> return ()++ case o of+ Just oVal | oVal /= cost -> do+ addError $ printf "o-line value (%d) is inconsistent" oVal+ _ -> return ()++checkMIPResult :: MIP.Tol Scientific -> MIP.Problem Scientific -> MIP.Solution Scientific -> (Bool, [String])+checkMIPResult tol mip sol = execM $ do+ let m = MIP.solVariables sol++ let objVal = MIP.eval tol m (MIP.objExpr (MIP.objectiveFunction mip))+ addInfo $ "objective value = " ++ show objVal+ case MIP.solObjectiveValue sol of+ Nothing -> return ()+ Just declaredObjVal -> do+ unless (abs (objVal - declaredObjVal) <= MIP.feasibilityTol tol) $ do+ addError $ printf "declared objective value (%s) does not match to the computed value (%s)"+ (show declaredObjVal) (show objVal)++ forM_ (Map.toList (MIP.varDomains mip)) $ \(v, (vt, bounds@(lb,ub))) -> do+ let val = MIP.eval tol m v+ flag1 =+ case vt of+ MIP.ContinuousVariable -> True+ MIP.SemiContinuousVariable -> True+ MIP.IntegerVariable -> isIntegral tol val+ MIP.SemiIntegerVariable -> isIntegral tol val+ flag2 =+ case vt of+ MIP.ContinuousVariable -> isInBounds tol bounds val+ MIP.IntegerVariable -> isInBounds tol bounds val+ MIP.SemiIntegerVariable -> isInBounds tol (0,0) val || isInBounds tol bounds val+ MIP.SemiContinuousVariable -> isInBounds tol (0,0) val || isInBounds tol bounds val+ unless flag1 $ do+ addError $ printf "variable %s is not integral" (T.unpack (MIP.varName v))+ unless flag2 $ do+ let f MIP.NegInf = "-inf"+ f MIP.PosInf = "+inf"+ f (MIP.Finite x) = show x+ addError $ printf "variable %s is out of bounds lb=%s ub=%s" (T.unpack (MIP.varName v)) (f lb) (f ub)++ forM_ (MIP.constraints mip) $ \constr -> do+ unless (MIP.eval tol m constr) $ do+ addError $ case MIP.constrLabel constr of+ Just name -> printf "violated: %s" (T.unpack name)+ Nothing -> printf "violated: %s" (showMIPConstraint constr)++ forM_ (MIP.sosConstraints mip) $ \constr -> do+ unless (MIP.eval tol m constr) $ do+ addError $ case MIP.sosLabel constr of+ Just name -> printf "violated: %s" (T.unpack name)+ Nothing -> printf "violated: %s" (showMIPSOSConstraint constr)++-- ------------------------------------------------------------------------++showClause :: (Monoid a, IsString a) => SAT.PackedClause -> a+showClause = foldr (\f g -> f <> fromString " " <> g) mempty . map (fromString . show) . SAT.unpackClause++showPBSum :: (Monoid a, IsString a) => PBFile.Sum -> a+showPBSum = mconcat . map showWeightedTerm+ where+ showWeightedTerm :: (Monoid a, IsString a) => PBFile.WeightedTerm -> a+ showWeightedTerm (c, lits) = foldr (\f g -> f <> fromString " " <> g) mempty (x:xs)+ where+ x = if c >= 0 then fromString "+" <> fromString (show c) else fromString (show c)+ xs = map showLit $ sortBy (comparing abs) lits++ showLit :: (Monoid a, IsString a) => PBFile.Lit -> a+ showLit lit = if lit > 0 then v else fromString "~" <> v+ where+ v = fromString "x" <> fromString (show (abs lit))++showPBConstraint :: (Monoid a, IsString a) => PBFile.Constraint -> a+showPBConstraint (lhs, op, rhs) =+ showPBSum lhs <> f op <> fromString " " <> fromString (show rhs)+ where+ f PBFile.Eq = fromString "="+ f PBFile.Ge = fromString ">="++showMIPConstraint :: MIP.Constraint Scientific -> String+showMIPConstraint constr = concat+ [ case MIP.constrIndicator constr of+ Nothing -> ""+ Just (MIP.Var var, val) ->+ let rhs =+ case floatingOrInteger val of+ Right (i :: Integer) -> show i+ Left (_ :: Double) -> show val -- should be error?+ in T.unpack var ++ " = " ++ rhs ++ " -> "+ , case MIP.constrLB constr of+ MIP.NegInf -> ""+ MIP.PosInf -> "+inf <= "+ MIP.Finite x -> show x ++ " <= "+ , showMIPExpr (MIP.constrExpr constr)+ , case MIP.constrUB constr of+ MIP.NegInf -> "<= -inf"+ MIP.PosInf -> ""+ MIP.Finite x -> " <= " ++ show x+ ]++showMIPSOSConstraint :: MIP.SOSConstraint Scientific -> String+showMIPSOSConstraint constr = concat $+ [show (MIP.sosType constr), " ::"] ++ [+ " " ++ T.unpack (MIP.varName v) ++ " : " ++ show r+ | (v, r) <- MIP.sosBody constr+ ]++showMIPExpr :: MIP.Expr Scientific -> String+showMIPExpr e = intercalate " "+ [ intercalate "*" (((if c >= 0 then "+" ++ show c else show c) : map (T.unpack . MIP.varName) vs))+ | MIP.Term c vs <- MIP.terms e+ ]++isIntegral :: RealFrac r => MIP.Tol r -> r -> Bool+isIntegral tol x = abs (x - fromIntegral (floor (x + 0.5) :: Integer)) <= MIP.integralityTol tol++isInBounds :: (Num r, Ord r) => MIP.Tol r -> MIP.Bounds r -> r -> Bool+isInBounds tol (lb, ub) x =+ lb - MIP.Finite (MIP.feasibilityTol tol) <= MIP.Finite x &&+ MIP.Finite x <= ub + MIP.Finite (MIP.feasibilityTol tol)++-- ------------------------------------------------------------------------
src/ToySolver/QBF.hs view
@@ -41,7 +41,8 @@ import qualified Data.IntMap as IntMap import qualified Data.IntSet as IntSet import Data.Function (on)-import Data.List (groupBy, foldl')+import Data.List (foldl')+import qualified Data.List.NonEmpty as NonEmpty import Data.Maybe import ToySolver.Data.Boolean@@ -65,9 +66,9 @@ removeEmptyQuantifiers = filter (\(_,xs) -> not (IntSet.null xs)) groupQuantifiers :: Prefix -> Prefix-groupQuantifiers = map f . groupBy ((==) `on` fst)+groupQuantifiers = map f . NonEmpty.groupBy ((==) `on` fst) where- f qs = (fst (head qs), IntSet.unions [xs | (_,xs) <- qs])+ f qs = (fst (NonEmpty.head qs), IntSet.unions [xs | (_,xs) <- NonEmpty.toList qs]) quantifyFreeVariables :: Int -> Prefix -> Prefix quantifyFreeVariables nv prefix
src/ToySolver/SAT/Encoder/Integer.hs view
@@ -14,6 +14,7 @@ module ToySolver.SAT.Encoder.Integer ( Expr (..) , newVar+ , newVarPBLinSum , linearize , addConstraint , addConstraintSoft@@ -24,6 +25,7 @@ import Control.Monad.Primitive import Data.Array.IArray import Data.VectorSpace+import Math.NumberTheory.Logarithms (integerLog2) import Text.Printf import ToySolver.Data.OrdRel@@ -33,19 +35,41 @@ newtype Expr = Expr SAT.PBSum deriving (Eq, Show, Read) -newVar :: SAT.AddPBNL m enc => enc -> Integer -> Integer -> m Expr+newVar+ :: SAT.AddPBNL m enc+ => enc+ -> Integer -- ^ lower bound+ -> Integer -- ^ upper bound+ -> m Expr newVar enc lo hi | lo > hi = do SAT.addClause enc [] -- assert inconsistency return 0- | lo == hi = return $ fromInteger lo | otherwise = do- let hi' = hi - lo- bitWidth = head $ [w | w <- [1..], let mx = 2 ^ w - 1, hi' <= mx]- vs <- SAT.newVars enc bitWidth- let xs = zip (iterate (2*) 1) vs- SAT.addPBAtMost enc xs hi'- return $ Expr $ [(lo,[]) | lo /= 0] ++ [(c,[x]) | (c,x) <- xs]+ s <- newVarPBLinSum enc (hi - lo)+ return $ Expr $ [(lo,[]) | lo /= 0] ++ [(c, [l]) | (c,l) <- s]++-- | Lower-level version of 'newVar'+--+-- * It takes only upper bound. Lower bound is always 0.+--+-- * Return type is 'SAT.PBLinSum'. It is inconvenient for performing operations,+-- but it is sometimes useful to be guaranteed to be in a linear form.+newVarPBLinSum+ :: SAT.AddPBNL m enc+ => enc+ -> Integer -- ^ upper bound+ -> m SAT.PBLinSum+newVarPBLinSum enc hi+ | hi < 0 = do+ SAT.addClause enc [] -- assert inconsistency+ return []+ | hi == 0 = return []+ | otherwise = do+ let bitWidth = integerLog2 hi + 1+ vs <- SAT.newVars enc (bitWidth - 1)+ v <- SAT.newVar enc+ return $ [(c,x) | (c,x) <- zip (iterate (2*) 1) vs] ++ [(hi - (2 ^ (bitWidth - 1) - 1), v)] instance AdditiveGroup Expr where Expr xs1 ^+^ Expr xs2 = Expr (xs1++xs2)
src/ToySolver/SAT/Encoder/PB/Internal/BCCNF.hs view
@@ -61,7 +61,7 @@ import Data.Function (on) import Data.List (sortBy) import Data.Maybe (listToMaybe)-import Data.Ord (comparing)+import Data.Ord (comparing, Down (..)) import ToySolver.SAT.Types import qualified ToySolver.SAT.Encoder.Cardinality as Card@@ -165,7 +165,7 @@ preprocess constr = (lhs2, rhs1) where (lhs1, rhs1) = normalizePBLinAtLeast constr- lhs2 = sortBy (flip (comparing fst) <> comparing (abs . snd)) lhs1+ lhs2 = sortBy (comparing (Down . fst) <> comparing (abs . snd)) lhs1 -- | Algorithm 2 in the paper but with a bug fixed encodePrefixSum :: PrefixSum -> Integer -> [[BCLit]]
src/ToySolver/SAT/Encoder/PB/Internal/BDD.hs view
@@ -26,7 +26,7 @@ import Control.Monad.State.Strict import Control.Monad.Primitive import Data.Ord-import Data.List+import Data.List (sortBy) import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map import qualified ToySolver.SAT.Types as SAT@@ -39,7 +39,7 @@ encodePBLinAtLeastWithPolarityBDD :: forall m. PrimMonad m => Tseitin.Encoder m -> Tseitin.Polarity -> SAT.PBLinAtLeast -> m SAT.Lit encodePBLinAtLeastWithPolarityBDD enc polarity (lhs,rhs) = do- let lhs' = sortBy (flip (comparing fst)) lhs+ let lhs' = sortBy (comparing (Down . fst)) lhs flip evalStateT Map.empty $ do let f :: SAT.PBLinSum -> Integer -> Integer -> StateT (Map (SAT.PBLinSum, Integer) SAT.Lit) m SAT.Lit f xs rhs slack
src/ToySolver/SAT/Encoder/PB/Internal/Sorter.hs view
@@ -40,12 +40,13 @@ import Control.Monad.Primitive import Control.Monad.State import Control.Monad.Writer-import Data.List+import Data.List (sortBy) import Data.Maybe import Data.Ord import Data.Vector (Vector, (!)) import qualified Data.Vector as V import qualified Data.Vector.Mutable as MV+import Math.NumberTheory.Logarithms (intLog2) import ToySolver.Data.Boolean import qualified ToySolver.SAT.Types as SAT import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin@@ -85,8 +86,7 @@ | V.length v <= 1 = (v, V.empty) | otherwise = (V.slice 0 len1 v, V.slice len1 len2 v) where- n = head $ dropWhile (< V.length v) $ iterate (*2) 1- len1 = n `div` 2+ len1 = 2 ^ intLog2 (V.length v - 1) len2 = V.length v - len1 splitOddEven :: Vector a -> (Vector a, Vector a)
src/ToySolver/SAT/Internal/JSON.hs view
@@ -74,19 +74,25 @@ parseConst = withTypedObject "constant" $ \obj -> obj .: "value" jPBSum :: SAT.PBSum -> J.Value+jPBSum [t] = jPBWeightedTerm t jPBSum s = J.object [ "type" .= ("operator" :: J.Value) , "name" .= ("+" :: J.Value)- , "operands" .=- [ J.object- [ "type" .= ("operator" :: J.Value)- , "name" .= ("*" :: J.Value)- , "operands" .= (jConst c : [jLit lit | lit <- lits])- ]- | (c, lits) <- s- ]+ , "operands" .= map jPBWeightedTerm s ] +jPBWeightedTerm :: PBFile.WeightedTerm -> J.Value+jPBWeightedTerm (c, lits) =+ case [jConst c | c /= 1] ++ [jLit lit | lit <- lits] of+ [] -> jConst (1 :: Int)+ [x] -> x+ xs ->+ J.object+ [ "type" .= ("operator" :: J.Value)+ , "name" .= ("*" :: J.Value)+ , "operands" .= xs+ ]+ parsePBSum :: J.Value -> J.Parser SAT.PBSum parsePBSum x = msum [ withOperator "+" (fmap concat . mapM parsePBSum) x@@ -99,6 +105,17 @@ , parseLit y >>= \lit -> pure (1, [lit]) , withOperator "*" (fmap ((product *** concat) . unzip) . mapM f) y ]++jPBLinSum :: SAT.PBLinSum -> J.Value+jPBLinSum s = jPBSum [(c, [l]) | (c,l) <- s]++parsePBLinSum :: J.Value -> J.Parser SAT.PBLinSum+parsePBLinSum x = do+ s <- parsePBSum x+ forM s $ \(c, ls) ->+ case ls of+ [l] -> pure (c, l)+ _ -> fail "non-linear expression (linear expression expected)" jPBConstraint :: PBFile.Constraint -> J.Value jPBConstraint (lhs, op, rhs) =
+ src/ToySolver/SAT/LogParser.hs view
@@ -0,0 +1,121 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}+-----------------------------------------------------------------------------+-- |+-- Module : ToySolver.SAT.LogParser+-- Copyright : (c) Masahiro Sakai 2025+-- License : BSD-style+--+-- Maintainer : masahiro.sakai@gmail.com+-- Stability : provisional+-- Portability : portable+--+-----------------------------------------------------------------------------+module ToySolver.SAT.LogParser+ ( parseSATLog+ , parseMaxSATLog+ , parsePBLog+ ) where++import Data.Array.IArray+import qualified Data.ByteString.Char8 as BS+import qualified Data.ByteString.Lazy.Char8 as BL+import Data.Char+import Data.Maybe (fromMaybe)+import qualified Data.Vector.Unboxed as VU++import ToySolver.SAT.Types as SAT++parseSATLog :: BL.ByteString -> (BS.ByteString, Maybe SAT.Model)+parseSATLog s = f "UNKNOWN" Nothing (BL.lines s)+ where+ f :: BS.ByteString -> Maybe [BL.ByteString] -> [BL.ByteString] -> (BS.ByteString, Maybe SAT.Model)+ f !status vlines (l : ls) =+ case BL.uncons l of+ Just ('c', _) -> f status vlines ls+ Just ('s', BS.toStrict -> BS.strip -> rest) -> f rest vlines ls+ Just ('v', rest) ->+ let vlines' = Just $ rest : fromMaybe [] vlines+ in f status vlines' ls+ Just (c, _) -> error ("unknown line type: " ++ show c)+ Nothing -> f status vlines ls+ f !status vlines [] =+ ( status+ , case vlines of+ Nothing -> Nothing+ Just lss ->+ let xs = VU.fromList $ map (read . BL.unpack) $ concat $ map BL.words $ reverse lss+ xs' = VU.init xs+ n = maximum $ map abs $ VU.toList xs'+ in if VU.last xs /= 0 then+ error "vlines are not terminated with zero"+ else if 0 `VU.elem` xs' then+ error "multiple zeros in vlines"+ else+ Just $ array (1, n) [if lit > 0 then (lit, True) else (- lit, False) | lit <- VU.toList xs']+ )++parseMaxSATLog :: BL.ByteString -> (BS.ByteString, Maybe Integer, Maybe SAT.Model)+parseMaxSATLog s = f "UNKNOWN" Nothing Nothing (BL.lines s)+ where+ f :: BS.ByteString -> Maybe Integer -> Maybe [BL.ByteString] -> [BL.ByteString] -> (BS.ByteString, Maybe Integer, Maybe SAT.Model)+ f !status obj vlines (l : ls) =+ case BL.uncons l of+ Just ('c', _) -> f status obj vlines ls+ Just ('s', BL.toStrict -> BS.strip -> rest) -> f rest obj vlines ls+ Just ('v', rest) ->+ let vlines' = Just $ rest : fromMaybe [] vlines+ in f status obj vlines' ls+ Just ('o', BL.toStrict -> BS.strip -> rest) ->+ case BS.readInteger rest of+ Just (!val, "") -> f status (Just val) Nothing ls+ _ -> error "failed to parse o-line"+ Just (c, _) -> error ("unknown line type: " ++ show c)+ Nothing -> f status obj vlines ls+ f !status obj vlines [] =+ ( status+ , obj+ , case vlines of+ Nothing -> Nothing+ Just lss ->+ let tmp1 = BL.filter (not . isSpace) $ BL.concat $ reverse lss+ tmp2 = map (read . BL.unpack) $ concat $ map BL.words $ reverse lss+ in if BL.all (\c -> c == '0' || c == '1') tmp1 then+ Just $ array (1, fromIntegral (BL.length tmp1)) [(v, c=='1') | (v, c) <- zip [1..] (BL.unpack tmp1)]+ else+ Just $ array (1, maximum (map abs tmp2)) [if lit > 0 then (lit, True) else (- lit, False) | lit <- tmp2]+ )++parsePBLog :: BL.ByteString -> (BS.ByteString, Maybe Integer, Maybe SAT.Model)+parsePBLog s = f "UNKNOWN" Nothing Nothing (BL.lines s)+ where+ f :: BS.ByteString -> Maybe Integer -> Maybe [BL.ByteString] -> [BL.ByteString] -> (BS.ByteString, Maybe Integer, Maybe SAT.Model)+ f !status obj vlines (l : ls) =+ case BL.uncons l of+ Just ('c', _) -> f status obj vlines ls+ Just ('s', BL.toStrict -> BS.strip -> rest) -> f rest obj vlines ls+ Just ('v', rest) ->+ let vlines' = Just $ rest : fromMaybe [] vlines+ in f status obj vlines' ls+ Just ('o', BL.toStrict -> BS.strip -> rest) ->+ case BS.readInteger rest of+ Just (!val, "") -> f status (Just val) Nothing ls+ _ -> error "failed to parse o-line"+ Just (c, _) -> error ("unknown line type: " ++ show c)+ Nothing -> f status obj vlines ls+ f !status obj vlines [] =+ ( status+ , obj+ , case vlines of+ Nothing -> Nothing+ Just lss ->+ let lits = map (parseLit . BL.unpack) $ concat $ map BL.words $ reverse lss+ in Just $ array (1, maximum (map abs lits)) [if lit > 0 then (lit, True) else (- lit, False) | lit <- lits]+ )++ parseLit :: String -> SAT.Lit+ parseLit ('-' : 'x' : rest) | [(v, "")] <- reads rest = - v+ parseLit ('x' : rest) | [(v, "")] <- reads rest = v+ parseLit w = error ("failed to parse a literal: " ++ show w)
src/ToySolver/SAT/MUS/Base.hs view
@@ -17,7 +17,6 @@ import Control.Monad import Data.Default.Class-import Data.List import qualified Data.IntSet as IS import qualified ToySolver.SAT as SAT import ToySolver.SAT.Types
src/ToySolver/SAT/MUS/Deletion.hs view
@@ -18,7 +18,7 @@ import Control.Monad import Data.Default.Class-import Data.List+import Data.List (intercalate) import qualified Data.IntSet as IS import qualified ToySolver.SAT as SAT import ToySolver.SAT.Types
src/ToySolver/SAT/MUS/Enum/CAMUS.hs view
@@ -38,7 +38,6 @@ import Data.Array.IArray import Data.Default.Class import qualified Data.IntSet as IS-import Data.List import Data.IORef import Data.Set (Set) import qualified Data.Set as Set
src/ToySolver/SAT/MUS/Insertion.hs view
@@ -22,7 +22,7 @@ import Control.Monad import Data.Default.Class-import Data.List+import Data.List (intercalate) import qualified Data.IntSet as IntSet import qualified ToySolver.SAT as SAT import ToySolver.SAT.Types
src/ToySolver/SAT/MUS/QuickXplain.hs view
@@ -25,7 +25,7 @@ import Control.Monad import Data.Default.Class-import Data.List+import Data.List (intercalate) import qualified Data.IntSet as IS import qualified ToySolver.SAT as SAT import ToySolver.SAT.Types
src/ToySolver/SAT/PBO/BCD.hs view
@@ -32,7 +32,7 @@ import Control.Monad import qualified Data.IntSet as IntSet import qualified Data.IntMap as IntMap-import Data.List+import Data.List (foldl') import qualified ToySolver.SAT as SAT import qualified ToySolver.SAT.Types as SAT import qualified ToySolver.SAT.PBO.Context as C
src/ToySolver/SAT/Printer.hs view
@@ -1,27 +1,39 @@+{-# OPTIONS_GHC -Wall #-}+{-# OPTIONS_HADDOCK show-extensions #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-} ----------------------------------------------------------------------------- -- | -- Module : ToySolver.SAT.Printer--- Copyright : (c) Masahiro Sakai 2012+-- Copyright : (c) Masahiro Sakai 2012-2025 -- License : BSD-style -- -- Maintainer : masahiro.sakai@gmail.com -- Stability : provisional--- Portability : portable+-- Portability : non-portable -- -- Printing utilities. -- ----------------------------------------------------------------------------- module ToySolver.SAT.Printer- ( satPrintModel+ (+ -- * Model/Solution printer+ satPrintModel , maxsatPrintModel , maxsatPrintModelCompact , pbPrintModel , musPrintSol++ -- * Low-level builder functions+ , satModel+ , maxsatModel+ , maxsatModelCompact+ , pbModel+ , musSol ) where -import Control.Monad import Data.Array.IArray-import Data.List+import qualified Data.ByteString.Builder as Builder import System.IO import ToySolver.SAT.Types @@ -29,64 +41,97 @@ -- See <http://www.satcompetition.org/2011/rules.pdf> for details. satPrintModel :: Handle -> Model -> Int -> IO () satPrintModel h m n = do- let as = if n > 0- then takeWhile (\(v,_) -> v <= n) $ assocs m- else assocs m- forM_ (split 10 as) $ \xs -> do- hPutStr h "v"- forM_ xs $ \(var,val) -> hPutStr h (' ': show (literal var val))- hPutStrLn h ""- hPutStrLn h "v 0"+ newline <- getNewline h+ Builder.hPutBuilder h $ satModel m n newline hFlush h -- | Print a 'Model' in a way specified for Max-SAT Evaluation. -- See <http://maxsat.ia.udl.cat/requirements/> for details. maxsatPrintModel :: Handle -> Model -> Int -> IO () maxsatPrintModel h m n = do- let as = if n > 0- then takeWhile (\(v,_) -> v <= n) $ assocs m- else assocs m- forM_ (split 10 as) $ \xs -> do- hPutStr h "v"- forM_ xs $ \(var,val) -> hPutStr h (' ' : show (literal var val))- hPutStrLn h ""- -- no terminating 0 is necessary+ newline <- getNewline h+ Builder.hPutBuilder h $ maxsatModel m n newline hFlush h -- | Print a 'Model' in the new compact way specified for Max-SAT Evaluation >=2020. -- See <https://maxsat-evaluations.github.io/2020/vline.html> for details. maxsatPrintModelCompact :: Handle -> Model -> Int -> IO () maxsatPrintModelCompact h m n = do- let vs = if n > 0- then take n $ elems m- else elems m- hPutStrLn h $ "v " ++ [if v then '1' else '0' | v <- vs]+ newline <- getNewline h+ Builder.hPutBuilder h $ maxsatModelCompact m n newline hFlush h -- | Print a 'Model' in a way specified for Pseudo-Boolean Competition. -- See <http://www.cril.univ-artois.fr/PB12/format.pdf> for details. pbPrintModel :: Handle -> Model -> Int -> IO () pbPrintModel h m n = do- let as = if n > 0- then takeWhile (\(v,_) -> v <= n) $ assocs m- else assocs m- forM_ (split 10 as) $ \xs -> do- hPutStr h "v"- forM_ xs $ \(var,val) -> hPutStr h (" " ++ (if val then "" else "-") ++ "x" ++ show var)- hPutStrLn h ""+ newline <- getNewline h+ Builder.hPutBuilder h $ pbModel m n newline hFlush h musPrintSol :: Handle -> [Int] -> IO () musPrintSol h is = do- forM_ (split 10 is) $ \xs -> do- hPutStr h "v"- forM_ xs $ \i -> hPutStr h (' ': show i)- hPutStrLn h ""- hPutStrLn h "v 0"+ newline <- getNewline h+ Builder.hPutBuilder h $ musSol is newline hFlush h -- ------------------------------------------------------------------------ +satModel :: Model -> Int -> Newline -> Builder.Builder+satModel m n newline = mconcat+ [ Builder.char7 'v' <> mconcat [Builder.char7 ' ' <> Builder.intDec (literal var val) | (var, val) <- xs] <> nl+ | xs <- split 10 as+ ] <> Builder.string7 "v 0" <> nl+ where+ as = if n > 0+ then takeWhile (\(v,_) -> v <= n) $ assocs m+ else assocs m+ nl = newlineBuilder newline++maxsatModel :: Model -> Int -> Newline -> Builder.Builder+maxsatModel m n newline = mconcat+ [ Builder.char7 'v' <> mconcat [Builder.char7 ' ' <> Builder.intDec (literal var val) | (var, val) <- xs] <> nl+ | xs <- split 10 as+ ] -- no terminating 0 is necessary+ where+ as = if n > 0+ then takeWhile (\(v,_) -> v <= n) $ assocs m+ else assocs m+ nl = newlineBuilder newline++maxsatModelCompact :: Model -> Int -> Newline -> Builder.Builder+maxsatModelCompact m n newline =+ Builder.string7 "v " <> mconcat [Builder.char7 (if v then '1' else '0') | v <- vs] <> nl+ where+ vs = if n > 0+ then take n $ elems m+ else elems m+ nl = newlineBuilder newline++pbModel :: Model -> Int -> Newline -> Builder.Builder+pbModel m n newline = mconcat+ [ Builder.char7 'v' <> mconcat+ [ Builder.char7 ' ' <> (if val then mempty else Builder.char7 '-') <> Builder.char7 'x' <> Builder.intDec var+ | (var, val) <- xs+ ] <> nl+ | xs <- split 10 as+ ]+ where+ as = if n > 0+ then takeWhile (\(v,_) -> v <= n) $ assocs m+ else assocs m+ nl = newlineBuilder newline++musSol :: [Int] -> Newline -> Builder.Builder+musSol is newline = mconcat+ [ Builder.char7 'v' <> mconcat [Builder.char7 ' ' <> Builder.intDec i | i <- xs] <> nl+ | xs <- split 10 is+ ] <> Builder.string7 "v 0" <> nl+ where+ nl = newlineBuilder newline++-- ------------------------------------------------------------------------+ split :: Int -> [a] -> [[a]] split n = go where@@ -94,3 +139,23 @@ go xs = case splitAt n xs of (ys, zs) -> ys : go zs++#ifdef mingw32_HOST_OS++getNewline :: Handle -> IO Newline+getNewline h = do+ m <- hGetEncoding h+ case m of+ Nothing -> return LF+ Just _ -> return CRLF++#else++getNewline :: Handle -> IO Newline+getNewline _ = return LF++#endif++newlineBuilder :: Newline -> Builder.Builder+newlineBuilder LF = Builder.char7 '\n'+newlineBuilder CRLF = Builder.string7 "\r\n"
src/ToySolver/SAT/Solver/CDCL.hs view
@@ -2,7 +2,6 @@ {-# OPTIONS_HADDOCK show-extensions #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RecursiveDo #-}@@ -142,9 +141,6 @@ import Data.Array.IO import Data.Array.Unsafe (unsafeFreeze) import Data.Array.Base (unsafeRead, unsafeWrite)-#if !MIN_VERSION_hashable(1,4,3)-import Data.Bits (xor) -- for defining 'combine' function-#endif import Data.Coerce import Data.Default.Class import Data.Either@@ -154,7 +150,7 @@ import qualified Data.HashSet as HashSet import Data.IORef import Data.Int-import Data.List+import Data.List (delete, find, foldl', maximumBy, partition, sortBy) import Data.Maybe import Data.Ord import qualified Data.IntMap.Strict as IM@@ -163,7 +159,6 @@ import ToySolver.Internal.Data.IOURef import qualified ToySolver.Internal.Data.IndexedPriorityQueue as PQ import qualified ToySolver.Internal.Data.Vec as Vec-import Data.Typeable import System.Clock import qualified System.Random.MWC as Rand import Text.Printf@@ -1173,12 +1168,12 @@ Left m -> m data BudgetExceeded = BudgetExceeded- deriving (Show, Typeable)+ deriving (Show) instance Exception BudgetExceeded data Canceled = Canceled- deriving (Show, Typeable)+ deriving (Show) instance Exception Canceled @@ -1771,7 +1766,7 @@ incrementReasoned solver (IS.toList lits2) - xs <- liftM (sortBy (flip (comparing snd))) $+ xs <- liftM (sortBy (comparing (Down . snd))) $ forM (IS.toList lits2) $ \l -> do lv <- litLevel solver l return (l,lv)@@ -2474,7 +2469,7 @@ watchLit solver liti this assignBy solver lit0 this -- should always succeed else do -- CONFLICT- ls <- liftM (map fst . sortBy (flip (comparing snd))) $ forM [0..size-1] $ \l -> do+ ls <- liftM (map fst . sortBy (comparing (Down . snd))) $ forM [0..size-1] $ \l -> do lit <- readLitArray (claLits this2) l lv <- litLevel solver lit return (l,lv)@@ -2687,7 +2682,7 @@ else do -- CONFLICT -- We need to watch unassigned literals or most recently falsified literals.- do xs <- liftM (sortBy (flip (comparing snd))) $ forM [i..m-1] $ \l -> do+ do xs <- liftM (sortBy (comparing (Down . snd))) $ forM [i..m-1] $ \l -> do lit <- readLitArray a l val <- litValue solver lit if val == lFalse then do@@ -2918,7 +2913,7 @@ newPBHandlerCounter :: PBLinSum -> Integer -> Bool -> IO PBHandlerCounter newPBHandlerCounter ts degree learnt = do- let ts' = sortBy (flip compare `on` fst) ts+ let ts' = sortBy (comparing (Down . fst)) ts slack = sum (map fst ts) - degree m = IM.fromList [(l,c) | (c,l) <- ts] s <- newIORef slack@@ -3063,7 +3058,7 @@ newPBHandlerPueblo :: PBLinSum -> Integer -> Bool -> IO PBHandlerPueblo newPBHandlerPueblo ts degree learnt = do- let ts' = sortBy (flip compare `on` fst) ts+ let ts' = sortBy (comparing (Down . fst)) ts slack = sum [c | (c,_) <- ts'] - degree ws <- newIORef IS.empty wsum <- newIORef 0@@ -3321,7 +3316,7 @@ readIORef ref' assignBy solver (if y then litNot lit0 else lit0) this -- should always succeed else do- ls <- liftM (map fst . sortBy (flip (comparing snd))) $ forM [0..size-1] $ \l -> do+ ls <- liftM (map fst . sortBy (comparing (Down . snd))) $ forM [0..size-1] $ \l -> do lit <- readLitArray a l lv <- litLevel solver lit return (l,lv)@@ -3623,16 +3618,6 @@ (x:xs) <- readIORef ref writeIORef ref xs return x--#if !MIN_VERSION_hashable(1,4,3)--defaultHashWithSalt :: Hashable a => Int -> a -> Int-defaultHashWithSalt salt x = salt `combine` hash x- where- combine :: Int -> Int -> Int- combine h1 h2 = (h1 * 16777619) `xor` h2--#endif {-------------------------------------------------------------------- debug
src/ToySolver/SAT/Solver/SLS/ProbSAT.hs view
@@ -1,6 +1,4 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -Wall #-} {-# OPTIONS_HADDOCK show-extensions #-}@@ -58,7 +56,6 @@ import Data.Maybe import Data.Sequence ((|>)) import qualified Data.Sequence as Seq-import Data.Typeable import Data.Word import System.Clock import qualified System.Random.MWC as Rand@@ -375,7 +372,7 @@ return $ (a `shiftL` 32) .|. toInteger b data Finished = Finished- deriving (Show, Typeable)+ deriving (Show) instance Exception Finished @@ -528,16 +525,6 @@ return () -- ---------------------------------------------------------------------#if !MIN_VERSION_array(0,5,6)--{-# INLINE modifyArray #-}-modifyArray :: (MArray a e m, Ix i) => a i e -> i -> (e -> e) -> m ()-modifyArray a i f = do- e <- readArray a i- writeArray a i (f e)--#endif {-# INLINE forAssocsM_ #-} forAssocsM_ :: (IArray a e, Monad m) => a Int e -> ((Int,e) -> m ()) -> m ()
src/ToySolver/SAT/Solver/SLS/UBCSAT.hs view
@@ -29,7 +29,7 @@ import Data.Default import Data.Either import Data.Function-import Data.List+import Data.List (isSuffixOf, minimumBy) import Data.Void import System.Directory import System.IO
src/ToySolver/SAT/Types.hs view
@@ -119,7 +119,7 @@ import Control.Exception import Data.Array.Unboxed import Data.Ord-import Data.List+import Data.List (foldl', foldl1', sortBy) import Data.Int import Data.IntMap.Strict (IntMap) import qualified Data.IntMap.Strict as IntMap
src/ToySolver/SMT.hs view
@@ -1,5 +1,4 @@ {-# OPTIONS_HADDOCK show-extensions #-}-{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-}@@ -81,7 +80,7 @@ import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet import Data.IORef-import Data.List+import Data.List (foldl') import Data.Map (Map) import qualified Data.Map as Map import Data.Maybe (catMaybes)@@ -90,7 +89,6 @@ import qualified Data.Set as Set import Data.String import qualified Data.Text as T-import Data.Typeable import Data.VectorSpace import ToySolver.Data.Delta@@ -200,7 +198,7 @@ data Exception = Error String | Unsupported- deriving (Show, Typeable)+ deriving (Show) instance E.Exception Exception @@ -278,7 +276,7 @@ bvModelRef <- newIORef (undefined :: BV.Model) globalDeclarationsRef <- newIORef False- fdefs <- newIORef $ Map.singleton "_/0" (FEUFFun ([sReal], sReal) divByZero)+ fdefs <- newIORef $ Map.singleton "/0" (FEUFFun ([sReal], sReal) divByZero) conflictTheory <- newIORef undefined @@ -662,7 +660,7 @@ case LA.asConst y' of Nothing -> E.throwIO $ Error "division by non-constant is not supported" Just 0 -> do- lraExprFromTerm solver =<< exprToEUFTerm solver "_/0" [x]+ lraExprFromTerm solver =<< exprToEUFTerm solver "/0" [x] Just c -> do x' <- exprToLRAExpr solver x return $ (1/c) *^ x'@@ -1123,7 +1121,7 @@ eval m (EAp "-" [x,y]) = ValRational $ valToRational m (eval m x) - valToRational m (eval m y) eval m (EAp "*" xs) = ValRational $ product $ map (valToRational m . eval m) xs eval m (EAp "/" [x,y])- | y' == 0 = eval m (EAp "_/0" [x])+ | y' == 0 = eval m (EAp "/0" [x]) | otherwise = ValRational $ valToRational m (eval m x) / y' where y' = valToRational m (eval m y)@@ -1249,8 +1247,14 @@ Sort SSymBool _ -> ValBool False Sort (SSymBitVec w) _ -> ValBitVec (BV.nat2bv w 0) Sort (SSymUninterpreted _s _ar) _ -> ValUninterpreted (EUF.mUnspecified (mEUFModel m)) resultSort- in FunDef [ (zipWith (entityToValue m) args argsSorts, entityToValue m result resultSort)- | (args, result) <- Map.toList tbl ]+ in -- Since our EUF solver does not know function arity, a+ -- function symbol @f@ is treated as a constant if it has not+ -- been applied to any arguments and @EUF.mFunctions (mEUFModel m)@+ -- contains (f ↦ ([] ↦ e)) in such case. But we know @f@ is+ -- a proper function symbol, we can ignore such entry in the+ -- table.+ FunDef [ (zipWith (entityToValue m) args argsSorts, entityToValue m result resultSort)+ | (args, result) <- Map.toList tbl, not (null args) ] defaultVal Just _ -> FunDef [] $ eval m (EAp f []) -- constant symbol Nothing -> E.throw $ Error $ "unknown function symbol: " ++ show f@@ -1268,31 +1272,9 @@ ] , EValue (entityToValue m result sReal) ]- | let FEUFFun _ sym = mDefs m Map.! "_/0"+ | let FEUFFun _ sym = mDefs m Map.! "/0" , ([arg], result) <- Map.toList $ EUF.mFunctions (mEUFModel m) IntMap.! sym ]- ++- [ EAp "="- [ EAp "bvudiv"- [ EValue (ValBitVec s)- , EValue (ValBitVec (BV.nat2bv (BV.width s) 0))- ]- , EValue (ValBitVec t)- ]- | (s,t) <- Map.toList bvDivTable- ]- ++- [ EAp "="- [ EAp "bvurem"- [ EValue (ValBitVec s)- , EValue (ValBitVec (BV.nat2bv (BV.width s) 0))- ]- , EValue (ValBitVec t)- ]- | (s,t) <- Map.toList bvRemTable- ]- where- (_, bvDivTable, bvRemTable) = mBVModel m -- -------------------------------------------------------------------
+ src/ToySolver/SMT/SMTLIB2Solver.hs view
@@ -0,0 +1,896 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE OverloadedStrings #-}+-----------------------------------------------------------------------------+-- |+-- Module : ToySolver.SMT.SMTLIB2Solver+-- Copyright : (c) Masahiro Sakai 2015+-- License : BSD-style+--+-- Maintainer : masahiro.sakai@gmail.com+-- Stability : experimental+-- Portability : portable+--+-----------------------------------------------------------------------------+module ToySolver.SMT.SMTLIB2Solver+ ( module Language.SMTLIB.Syntax+ , showSL++ -- * The solver type+ , Solver+ , newSolver++ -- * High-level API+ , execCommand+ , execCommandString+ , runCommand+ , runCommandString+ , printResponse++ -- * Individual commands++ -- ** (Re)starting and terminating+ , reset+ , setLogic+ , setOption+ , exit++ -- ** Modifying the assertion stack+ , push+ , pop+ , resetAssertions++ -- ** Introducing new symbols+ , declareSort+ , defineSort+ , declareConst+ , declareFun+ , defineConst+ , defineFun+ , defineFunRec+ , defineFunsRec++ -- ** Asserting and inspecting formulas+ , assert+ , getAssertions++ -- ** Checking for satisfiability+ , checkSat+ , checkSatAssuming++ -- ** Inspecting models+ , getValue+ , getAssignment+ , getModel++ -- ** Inspecting proofs+ , getProof+ , getUnsatCore+ , getUnsatAssumptions++ -- ** Inspecting settings+ , getInfo+ , getOption++ -- ** Script information+ , setInfo+ , echo+ ) where++import qualified Control.Exception as E+import Control.Monad+import Data.Interned (unintern)+import Data.Interned.Text+import Data.IORef+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Maybe (catMaybes)+import Data.Ratio+import Data.String+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Version as V+import Numeric (readDec, readFloat, readHex)+import System.Exit+import System.IO++import qualified ToySolver.BitVector as BV+import qualified ToySolver.SMT as SMT+import ToySolver.Version+import Language.SMTLIB.Syntax+import Language.SMTLIB.Parser (parseCommand')+import Language.SMTLIB.Printer (Pretty, renderText)++-- | Render an SMT-LIB AST node back to its concrete syntax as a 'String'.+showSL :: Pretty a => a -> String+showSL = T.unpack . renderText++-- ----------------------------------------------------------------------++data Mode+ = ModeStart+ | ModeAssert+ | ModeSat+ | ModeUnsat+ deriving (Eq, Ord, Show)++type EEnv = Map String EEntry+type SortEnv = Map String SortEntry+type Env = (EEnv, SortEnv)++data EEntry+ = EFSymBuiltin InternedText+ | EFSymDeclared SMT.FSym [SMT.Sort] SMT.Sort+ | EExpr SMT.Expr Bool+ | EFunDef EEnv [(String, SMT.Sort)] SMT.Sort (Term ())++data SortEntry+ = SortSym SMT.SSym+ | SortExpr SMT.Sort+ | SortDef SortEnv [String] (Sort ())++interpretSort :: SortEnv -> Sort () -> SMT.Sort+interpretSort env (Sort ident args ()) =+ case ident of+ Identifier "BitVec" indexes ()+ | not (null args) -> E.throw $ SMT.Error (showSL ident ++ ": wrong number of arguments (" ++ show (length args) ++ " for 0)")+ | [IxNumeral n ()] <- indexes -> SMT.sBitVec (fromInteger n)+ | otherwise -> E.throw $ SMT.Error ("BitVec: wrong number of indexes (" ++ show (length indexes) ++ " for 1)")+ Identifier _ (_:_) () ->+ E.throw $ SMT.Error ("unknown sort: " ++ showSL ident)+ Identifier name [] () ->+ case Map.lookup (T.unpack name) env of+ Nothing -> E.throw $ SMT.Error ("unknown sort: " ++ showSL ident)+ Just (SortSym ssym)+ | SMT.ssymArity ssym == length args -> SMT.Sort ssym args'+ | otherwise -> E.throw $ SMT.Error (showSL ident ++ ": wrong number of arguments (" ++ show (length args) ++ " for " ++ show (SMT.ssymArity ssym) ++ ")")+ Just (SortExpr s')+ | null args -> s'+ | otherwise -> E.throw $ SMT.Error (showSL ident ++ ": wrong number of arguments (" ++ show (length args) ++ " for 0)")+ Just (SortDef env' params body) ->+ interpretSort (Map.fromList (zip params (map SortExpr args')) `Map.union` env') body+ where+ args' = map (interpretSort env) args++interpretFun :: Env -> Term () -> SMT.Expr+interpretFun (env,senv) t =+ case t of+ TConstant (SCNumeral n ()) () -> SMT.EValue $ SMT.ValRational $ fromInteger n+ TConstant (SCDecimal s ()) () -> SMT.EValue $ SMT.ValRational $ fst $ head $ readFloat $ T.unpack s+ TConstant (SCHexadecimal s ()) () ->+ let n = fst $ head $ readHex $ T.unpack s+ in SMT.EValue $ SMT.ValBitVec $ BV.nat2bv (T.length s * 4) n+ TConstant (SCBinary s ()) () ->+ SMT.EValue $ SMT.ValBitVec $ BV.fromDescBits [c == '1' | c <- T.unpack s]+ TConstant c@(SCString _s ()) () -> E.throw $ SMT.Error (show c)+ TQualIdent qid () -> f qid []+ TApp qid args () -> f qid args+ TLet bindings body () ->+ interpretFun (Map.fromList [(T.unpack v, EExpr (interpretFun (env,senv) t2) False) | VarBinding v t2 () <- bindings] `Map.union` env, senv) body+ TLambda _bindings _body () -> E.throw $ SMT.Error "lambda abstractions are not supported yet"+ TForall _bindings _body () -> E.throw $ SMT.Error "universal quantifiers are not supported yet"+ TExists _bindings _body () -> E.throw $ SMT.Error "existential quantifiers are not supported yet"+ TMatch _e _cases () -> E.throw $ SMT.Error "match expressions are not supported yet"+ TAnnot t2 _ () -> interpretFun (env,senv) t2 -- annotations are not supported yet+ where+ unIdentifier :: Identifier () -> (String, [Index ()])+ unIdentifier (Identifier name indexes ()) = (T.unpack name, indexes)++ f (QIdentifierAs ident sort ()) args =+ case ident of+ Identifier sym [] ()+ | Just s <- T.stripPrefix "@" sym, ((n,[]):_) <- reads (T.unpack s) ->+ SMT.EValue $ SMT.ValUninterpreted n (interpretSort senv sort)+ _ -> f (QIdentifier ident ()) args+ f (QIdentifier ident ()) args+ | ('b':'v':xs, [IxNumeral n ()]) <- unIdentifier ident+ , ((x,_):_) <- readDec xs+ , x < 2^n+ = if not (null args)+ then E.throw $ SMT.Error (showSL ident ++ " does not take indexes")+ else SMT.EValue $ SMT.ValBitVec $ BV.nat2bv (fromInteger n) x+ f qid@(QIdentifier ident ()) args =+ case Map.lookup name env of+ Nothing -> E.throw $ SMT.Error ("unknown function symbol: " ++ showSL qid)+ Just (EFSymBuiltin name') ->+ SMT.EAp (SMT.FSym name' indexes') (map (interpretFun (env,senv)) args)+ Just _ | not (null indexes) -> E.throw $ SMT.Error (showSL ident ++ " does not take indexes")+ Just (EExpr e _) -> e+ Just (EFSymDeclared fsym _ _) -> SMT.EAp fsym (map (interpretFun (env,senv)) args)+ Just (EFunDef env' params _y body) ->+ interpretFun (Map.fromList [(p,a) | ((p,_s),a) <- zip params (map (\u -> EExpr (interpretFun (env,senv) u) False) args) ] `Map.union` env', senv) body+ where+ (name, indexes) = unIdentifier ident+ indexes' = map g indexes+ g (IxNumeral n ()) = SMT.IndexNumeral (fromIntegral n)+ g (IxSymbol s ()) = SMT.IndexSymbol (fromString (T.unpack s))++valueToTerm :: SMT.Value -> Term ()+valueToTerm (SMT.ValRational v) =+ case v `compare` 0 of+ GT -> f v+ EQ -> TConstant (SCNumeral 0 ()) ()+ LT -> TApp (QIdentifier (simpleId "-") ()) [ f (negate v) ] ()+ where+ f w = TApp (QIdentifier (simpleId "/") ())+ [ TConstant (SCNumeral (numerator w) ()) ()+ , TConstant (SCNumeral (denominator w) ()) ()+ ] ()+valueToTerm (SMT.ValBool b) =+ TQualIdent (QIdentifier (simpleId (if b then "true" else "false")) ()) ()+valueToTerm (SMT.ValBitVec bv) =+ TConstant (SCBinary (T.pack [if b then '1' else '0' | b <- BV.toDescBits bv]) ()) ()+valueToTerm (SMT.ValUninterpreted n s) =+ TQualIdent (QIdentifierAs (simpleId (T.pack ("@" ++ show n))) (sortToSortTerm s) ()) ()++ssymToSymbol :: SMT.SSym -> Identifier ()+ssymToSymbol SMT.SSymBool = simpleId "Bool"+ssymToSymbol SMT.SSymReal = simpleId "Real"+ssymToSymbol (SMT.SSymBitVec n) = Identifier "BitVec" [IxNumeral (fromIntegral n) ()] ()+ssymToSymbol (SMT.SSymUninterpreted name _) = simpleId (unintern name)++sortToSortTerm :: SMT.Sort -> Sort ()+sortToSortTerm (SMT.Sort s xs) = Sort (ssymToSymbol s) (map sortToSortTerm xs) ()++-- | A simple (non-indexed) identifier with a unit annotation.+simpleId :: Text -> Identifier ()+simpleId name = Identifier name [] ()++-- ----------------------------------------------------------------------++data Solver+ = Solver+ { svSMTSolverRef :: !(IORef SMT.Solver)+ , svEnvRef :: !(IORef Env)+ , svModeRef :: !(IORef Mode)+ , svSavedContextsRef :: !(IORef [(Maybe (EEnv, SortEnv), [Term ()])])+ , svStatusRef :: IORef (Maybe Bool)+ , svAssertionsRef :: IORef [Term ()]+ , svRegularOutputChannelRef :: !(IORef (String, Handle))+ , svDiagnosticOutputChannelRef :: !(IORef (String, Handle))+ , svPrintSuccessRef :: !(IORef Bool)+ , svProduceAssertionsRef :: !(IORef Bool)+ , svProduceAssignmentRef :: !(IORef Bool)+ , svProduceModelsRef :: !(IORef Bool)+ , svProduceUnsatAssumptionsRef :: !(IORef Bool)+ , svProduceUnsatCoresRef :: !(IORef Bool)+ , svGlobalDeclarationsRef :: !(IORef Bool)+ , svUnsatAssumptionsRef :: !(IORef [Term ()])+ }++newSolver :: IO Solver+newSolver = do+ solverRef <- newIORef =<< SMT.newSolver+ envRef <- newIORef initialEnv+ modeRef <- newIORef ModeStart+ savedContextsRef <- newIORef []+ statusRef <- newIORef Nothing+ assertionsRef <- newIORef ([] :: [Term ()])+ regOutputRef <- newIORef ("stdout", stdout)+ diagOutputRef <- newIORef ("stderr", stderr)+ printSuccessRef <- newIORef True+ produceAssertionsRef <- newIORef False+ produceAssignmentRef <- newIORef False+ produceModelsRef <- newIORef False+ produceUnsatAssumptionsRef <- newIORef False+ produceUnsatCoresRef <- newIORef False+ globalDeclarationsRef <- newIORef False+ unsatAssumptionsRef <- newIORef undefined+ return $+ Solver+ { svSMTSolverRef = solverRef+ , svEnvRef = envRef+ , svModeRef = modeRef+ , svUnsatAssumptionsRef = unsatAssumptionsRef+ , svSavedContextsRef = savedContextsRef+ , svStatusRef = statusRef+ , svAssertionsRef = assertionsRef+ , svRegularOutputChannelRef = regOutputRef+ , svDiagnosticOutputChannelRef = diagOutputRef+ , svPrintSuccessRef = printSuccessRef+ , svProduceAssertionsRef = produceAssertionsRef+ , svProduceAssignmentRef = produceAssignmentRef+ , svProduceModelsRef = produceModelsRef+ , svProduceUnsatCoresRef = produceUnsatCoresRef+ , svProduceUnsatAssumptionsRef = produceUnsatAssumptionsRef+ , svGlobalDeclarationsRef = globalDeclarationsRef+ }++initialEnv :: Env+initialEnv = (fenv, senv)+ where+ fenv = Map.fromList+ [ (name, EFSymBuiltin (fromString name))+ | name <- ["=", "true", "false", "not", "and", "or", "xor", "ite", "=>", "distinct"+ , "+", "-", "*", "/", ">=", "<=", ">", "<"+ , "extract", "concat", "bvnot", "bvneg"+ , "repeat", "zero_extend", "sign_extend", "rotate_left", "rotate_right"+ , "bvcomp"+ , "bvand", "bvor", "bvxor", "bvnand", "bvnor", "bvxnor"+ , "bvadd", "bvsub", "bvmul", "bvudiv", "bvurem", "bvsdiv", "bvsrem", "bvsmod", "bvshl", "bvlshr", "bvashr"+ , "bvule", "bvult", "bvuge", "bvugt", "bvsle", "bvslt", "bvsge", "bvsgt"+ ]+ ]+ senv = Map.fromList+ [ ("Real", SortSym SMT.SSymReal)+ , ("Bool", SortSym SMT.SSymBool)+ ]++execCommand :: Solver -> Command () -> IO ()+execCommand solver cmd = do+ -- putStrLn $ showSL cmd+ printResponse solver =<< runCommand solver cmd++printResponse :: Solver -> CommandResponse () -> IO ()+printResponse solver rsp = do+ b <- readIORef (svPrintSuccessRef solver)+ unless (rsp == RSuccess && not b) $ do+ (_,h) <- readIORef (svRegularOutputChannelRef solver)+ hPutStrLn h (showSL rsp)++runCommand :: Solver -> Command () -> IO (CommandResponse ())+runCommand solver cmd = E.handle h $ do+ case cmd of+ SetLogic logic () -> const RSuccess <$> setLogic solver (T.unpack logic)+ SetOption opt () -> const RSuccess <$> setOption solver opt+ GetOption k () -> RGetOption <$> getOption solver (':' : T.unpack k)+ SetInfo attr () -> const RSuccess <$> setInfo solver attr+ GetInfo flags () -> RGetInfo <$> getInfo solver flags+ Push n () -> const RSuccess <$> push solver (fromInteger n)+ Pop n () -> const RSuccess <$> pop solver (fromInteger n)+ DeclareSort name arity () -> const RSuccess <$> declareSort solver (T.unpack name) (fromInteger arity)+ DefineSort name xs body () -> const RSuccess <$> defineSort solver (T.unpack name) (map T.unpack xs) body+ DeclareConst name y () -> const RSuccess <$> declareConst solver (T.unpack name) y+ DefineConst name y body () -> const RSuccess <$> defineConst solver (T.unpack name) y body+ DeclareFun name xs y () -> const RSuccess <$> declareFun solver (T.unpack name) xs y+ DefineFun (FunctionDef name xs y body ()) () -> const RSuccess <$> defineFun solver (T.unpack name) xs y body+ DefineFunRec (FunctionDef name xs y body ()) () -> const RSuccess <$> defineFunRec solver (T.unpack name) xs y body+ DefineFunsRec fundecs terms () -> const RSuccess <$> defineFunsRec solver fundecs terms+ Assert tm () -> const RSuccess <$> assert solver tm+ GetAssertions () -> RGetAssertions <$> getAssertions solver+ CheckSat () -> RCheckSat <$> checkSat solver+ CheckSatAssuming ts () -> RCheckSat <$> checkSatAssuming solver ts+ GetValue ts () -> RGetValue <$> getValue solver ts+ GetAssignment () -> RGetAssignment <$> getAssignment solver+ GetModel () -> RGetModel <$> getModel solver+ GetProof () -> RGetProof <$> getProof solver+ GetUnsatCore () -> RGetUnsatCore <$> getUnsatCore solver+ GetUnsatAssumptions () -> RGetUnsatAssumptions <$> getUnsatAssumptions solver+ Reset () -> const RSuccess <$> reset solver+ ResetAssertions () -> const RSuccess <$> resetAssertions solver+ Echo s () -> REcho <$> echo solver s+ Exit () -> const RSuccess <$> exit solver+ -- Commands without solver support+ DeclareDatatype _ _ () -> E.throwIO SMT.Unsupported+ DeclareDatatypes _ _ () -> E.throwIO SMT.Unsupported+ DeclareSortParameter _ () -> E.throwIO SMT.Unsupported+ UnknownCommand _ _ () -> E.throwIO SMT.Unsupported+ where+ h SMT.Unsupported = return RUnsupported+ h (SMT.Error s) = return $ RError $ T.pack s++execCommandString :: Solver -> String -> IO ()+execCommandString solver cmd = do+ printResponse solver =<< runCommandString solver cmd++runCommandString :: Solver -> String -> IO (CommandResponse ())+runCommandString solver cmd =+ case parseCommand' "<string>" (T.pack cmd) of+ Left err ->+ return $ RError $ T.pack $ show err+ Right cmd' ->+ runCommand solver cmd'++-- ----------------------------------------------------------------------++reset :: Solver -> IO ()+reset solver = do+ writeIORef (svSMTSolverRef solver) =<< SMT.newSolver+ writeIORef (svEnvRef solver) initialEnv+ writeIORef (svModeRef solver) ModeStart+ writeIORef (svSavedContextsRef solver) []+ writeIORef (svStatusRef solver) Nothing+ writeIORef (svRegularOutputChannelRef solver) ("stdout",stdout)+ writeIORef (svDiagnosticOutputChannelRef solver) ("stderr",stderr)+ writeIORef (svPrintSuccessRef solver) True+ writeIORef (svProduceAssertionsRef solver) False+ writeIORef (svProduceAssignmentRef solver) False+ writeIORef (svProduceModelsRef solver) False+ writeIORef (svProduceUnsatAssumptionsRef solver) False+ writeIORef (svProduceUnsatCoresRef solver) False+ writeIORef (svUnsatAssumptionsRef solver) undefined++setLogic :: Solver -> String -> IO ()+setLogic solver logic = do+ mode <- readIORef (svModeRef solver)+ if mode /= ModeStart then do+ E.throwIO $ SMT.Error "set-logic can only be used in start mode"+ else do+ writeIORef (svModeRef solver) ModeAssert+ case logic of+ "QF_UFLRA" -> return ()+ "QF_UFRDL" -> return ()+ "QF_UF" -> return ()+ "QF_RDL" -> return ()+ "QF_LRA" -> return ()+ "QF_BV" -> return ()+ "QF_UFBV" -> return ()+ "ALL" -> return ()+ "ALL_SUPPORTED" -> return ()+ _ -> E.throwIO SMT.Unsupported++setOption :: Solver -> Option () -> IO ()+setOption solver opt = do+ mode <- readIORef (svModeRef solver)+ case opt of+ PrintSuccess b () -> do+ writeIORef (svPrintSuccessRef solver) b+ InteractiveMode b () -> do+ -- interactive-mode is the old name for produce-assertions. Deprecated.+ unless (mode == ModeStart) $ do+ E.throwIO $ SMT.Error "interactive-mode option can be set only in start mode"+ writeIORef (svProduceAssertionsRef solver) b+ return ()+ ProduceProofs b () -> do+ if mode /= ModeStart then+ E.throwIO $ SMT.Error "produce-proofs option can be set only in start mode"+ else if b then+ E.throwIO SMT.Unsupported+ else+ return ()+ ProduceUnsatCores b () -> do+ unless (mode == ModeStart) $ do+ E.throwIO $ SMT.Error "produce-unsat-cores option can be set only in start mode"+ writeIORef (svProduceUnsatCoresRef solver) b+ return ()+ ProduceUnsatAssumptions b () -> do+ unless (mode == ModeStart) $ do+ E.throwIO $ SMT.Error "produce-unsat-assumptions option can be set only in start mode"+ writeIORef (svProduceUnsatAssumptionsRef solver) b+ return ()+ ProduceModels b () -> do+ unless (mode == ModeStart) $ do+ E.throwIO $ SMT.Error "produce-models option can be set only in start mode"+ writeIORef (svProduceModelsRef solver) b+ return ()+ ProduceAssignments b () -> do+ unless (mode == ModeStart) $ do+ E.throwIO $ SMT.Error "produce-assignments option can be set only in start mode"+ writeIORef (svProduceAssignmentRef solver) b+ return ()+ ProduceAssertions b () -> do+ unless (mode == ModeStart) $ do+ E.throwIO $ SMT.Error "produce-assertions option can be set only in start mode"+ writeIORef (svProduceAssertionsRef solver) b+ return ()+ GlobalDeclarations b () -> do+ unless (mode == ModeStart) $ do+ E.throwIO $ SMT.Error "global-declarations option can be set only in start mode"+ writeIORef (svGlobalDeclarationsRef solver) b+ smt <- readIORef (svSMTSolverRef solver)+ SMT.setGlobalDeclarations smt b+ RegularOutputChannel fname () -> do+ let fname' = T.unpack fname+ hdl <- if fname' == "stdout" then+ return stdout+ else+ openFile fname' AppendMode+ writeIORef (svRegularOutputChannelRef solver) (fname', hdl)+ return ()+ DiagnosticOutputChannel fname () -> do+ let fname' = T.unpack fname+ hdl <- if fname' == "stderr" then+ return stderr+ else+ openFile fname' AppendMode+ writeIORef (svDiagnosticOutputChannelRef solver) (fname', hdl)+ return ()+ RandomSeed _i () ->+ if mode /= ModeStart then+ E.throwIO $ SMT.Error "random-seed option can be set only in start mode"+ else+ E.throwIO SMT.Unsupported+ Verbosity _lv () -> E.throwIO SMT.Unsupported+ ReproducibleResourceLimit _val () -> do+ if mode /= ModeStart then+ E.throwIO $ SMT.Error "reproducible-resource-limit option can be set only in start mode"+ else+ E.throwIO SMT.Unsupported+ OptionAttribute _attr () -> E.throwIO SMT.Unsupported++getOption :: Solver -> String -> IO (AttributeValue ())+getOption solver opt =+ case opt of+ ":expand-definitions" -> do+ -- expand-definitions has been removed in SMT-LIB 2.5.+ return $ boolValue False+ ":global-declarations" -> do+ b <- readIORef (svGlobalDeclarationsRef solver)+ return $ boolValue b+ ":interactive-mode" -> do+ -- interactive-mode is the old name for produce-assertions. Deprecated.+ b <- readIORef (svProduceAssertionsRef solver)+ return $ boolValue b+ ":print-success" -> do+ b <- readIORef (svPrintSuccessRef solver)+ return $ boolValue b+ ":produce-assertions" -> do+ b <- readIORef (svProduceAssertionsRef solver)+ return $ boolValue b+ ":produce-assignments" -> do+ b <- readIORef (svProduceAssignmentRef solver)+ return $ boolValue b+ ":produce-models" -> do+ b <- readIORef (svProduceModelsRef solver)+ return $ boolValue b+ ":produce-proofs" -> do+ let b = False -- default value+ return $ boolValue b+ ":produce-unsat-cores" -> do+ b <- readIORef (svProduceUnsatCoresRef solver)+ return $ boolValue b+ ":produce-unsat-assumptions" -> do+ b <- readIORef (svProduceUnsatAssumptionsRef solver)+ return $ boolValue b+ ":regular-output-channel" -> do+ (fname,_) <- readIORef (svRegularOutputChannelRef solver)+ return $ AVConstant (SCString (T.pack fname) ()) ()+ ":diagnostic-output-channel" -> do+ (fname,_) <- readIORef (svDiagnosticOutputChannelRef solver)+ return $ AVConstant (SCString (T.pack fname) ()) ()+ ":random-seed" -> do+ return $ AVConstant (SCNumeral 0 ()) () -- default value+ ":reproducible-resource-limit" -> do+ return $ AVConstant (SCNumeral 0 ()) () -- default value+ ":verbosity" -> do+ return $ AVConstant (SCNumeral 0 ()) () -- default value+ _ -> do+ E.throwIO SMT.Unsupported+ where+ boolValue b = AVSymbol (if b then "true" else "false") ()++setInfo :: Solver -> Attribute () -> IO ()+setInfo solver (AttributeWith "status" (AVSymbol s ()) ()) = do+ v <- case s of+ "sat" -> return $ Just True+ "unsat" -> return $ Just False+ "unknown" -> return $ Nothing+ _ -> E.throwIO $ SMT.Error $ "invalid status value: " ++ T.unpack s+ writeIORef (svStatusRef solver) v+setInfo _solver _ = return ()++getInfo :: Solver -> InfoFlag () -> IO [InfoResponse ()]+getInfo solver flag = do+ mode <- readIORef (svModeRef solver)+ case flag of+ ErrorBehaviorFlag () -> return [IRErrorBehavior ContinuedExecution]+ InfoName () -> return [IRName "toysmt"]+ Authors () -> return [IRAuthors "Masahiro Sakai"]+ InfoVersion () -> return [IRVersion (T.pack (V.showVersion version))]+ ReasonUnknownFlag () -> do+ if mode /= ModeSat then+ E.throwIO $ SMT.Error "Executions of get-info with :reason-unknown are allowed only when the solver is in sat mode following a check command whose response was unknown."+ else+ return [IRReasonUnknown RUIncomplete]+ AllStatistics () -> do+ if not (mode == ModeSat || mode == ModeUnsat) then+ E.throwIO $ SMT.Error "Executions of get-info with :all-statistics are allowed only when the solver is in sat or unsat mode."+ else+ E.throwIO SMT.Unsupported+ AssertionStackLevels () -> do+ saved <- readIORef (svSavedContextsRef solver)+ let n = length saved+ n `seq` return [IRAssertionStackLevels (fromIntegral n)]+ InfoFlagKeyword _s () -> do+ E.throwIO SMT.Unsupported++push :: Solver -> Int -> IO ()+push solver n = do+ replicateM_ n $ do+ (env,senv) <- readIORef (svEnvRef solver)+ assertions <- readIORef (svAssertionsRef solver)+ globalDeclarations <- readIORef (svGlobalDeclarationsRef solver)+ if globalDeclarations then+ modifyIORef (svSavedContextsRef solver) ((Nothing, assertions) :)+ else+ modifyIORef (svSavedContextsRef solver) ((Just (env,senv), assertions) :)+ SMT.push =<< readIORef (svSMTSolverRef solver)+ writeIORef (svModeRef solver) ModeAssert++pop :: Solver -> Int -> IO ()+pop solver n = do+ replicateM_ n $ do+ cs <- readIORef (svSavedContextsRef solver)+ case cs of+ [] -> E.throwIO $ SMT.Error "pop from empty context"+ ((m,assertions) : cs') -> do+ case m of+ Just (env,senv) -> writeIORef (svEnvRef solver) (env,senv)+ Nothing -> return ()+ writeIORef (svAssertionsRef solver) assertions+ writeIORef (svSavedContextsRef solver) cs'+ SMT.pop =<< readIORef (svSMTSolverRef solver)+ writeIORef (svModeRef solver) ModeAssert++resetAssertions :: Solver -> IO ()+resetAssertions solver = do+ cs <- readIORef (svSavedContextsRef solver)+ pop solver (length cs)++echo :: Solver -> Text -> IO Text+echo _solver s = return s++declareSort :: Solver -> String -> Int -> IO ()+declareSort solver name arity = do+ smt <- readIORef (svSMTSolverRef solver)+ s <- SMT.declareSSym smt name arity+ insertSort solver name (SortSym s)+ writeIORef (svModeRef solver) ModeAssert++defineSort :: Solver -> String -> [String] -> Sort () -> IO ()+defineSort solver name xs body = do+ (_, senv) <- readIORef (svEnvRef solver)+ insertSort solver name (SortDef senv xs body)+ writeIORef (svModeRef solver) ModeAssert++declareConst :: Solver -> String -> Sort () -> IO ()+declareConst solver name y = declareFun solver name [] y++-- | @(define-const c σ t)@ is syntactic sugar for @(define-fun c () σ t)@.+defineConst :: Solver -> String -> Sort () -> Term () -> IO ()+defineConst solver name y body = defineFun solver name [] y body++declareFun :: Solver -> String -> [Sort ()] -> Sort () -> IO ()+declareFun solver name xs y = do+ smt <- readIORef (svSMTSolverRef solver)+ (_, senv) <- readIORef (svEnvRef solver)+ let argsSorts = map (interpretSort senv) xs+ resultSort = interpretSort senv y+ f <- SMT.declareFSym smt name argsSorts resultSort+ insertFun solver name (EFSymDeclared f argsSorts resultSort)+ writeIORef (svModeRef solver) ModeAssert++defineFun :: Solver -> String -> [SortedVar ()] -> Sort () -> Term () -> IO ()+defineFun solver name xs y body = do+ writeIORef (svModeRef solver) ModeAssert+ (_, senv) <- readIORef (svEnvRef solver)+ let xs' = map (\(SortedVar x s ()) -> (T.unpack x, interpretSort senv s)) xs+ y' = interpretSort senv y+ if null xs' then do+ body' <- processNamed solver body+ (fenv, _) <- readIORef (svEnvRef solver)+ -- use EExpr?+ insertFun solver name (EFunDef fenv [] y' body')+ else do+ (fenv, _) <- readIORef (svEnvRef solver)+ insertFun solver name (EFunDef fenv xs' y' body)+ writeIORef (svModeRef solver) ModeAssert++defineFunRec :: Solver -> String -> [SortedVar ()] -> Sort () -> Term () -> IO ()+defineFunRec _solver _name _xs _y _body = do+ E.throwIO SMT.Unsupported++defineFunsRec :: Solver -> [FunctionDec ()] -> [Term ()] -> IO ()+defineFunsRec _solver _fundecs _terms = do+ E.throwIO SMT.Unsupported++assert :: Solver -> Term () -> IO ()+assert solver tm = do+ let mname =+ case tm of+ TAnnot _body attrs ()+ | name:_ <- [name | AttributeWith "named" (AVSymbol name ()) () <- attrs] ->+ Just (T.unpack name)+ _ -> Nothing+ tm' <- processNamed solver tm+ smt <- readIORef (svSMTSolverRef solver)+ env <- readIORef (svEnvRef solver)+ case mname of+ Nothing -> SMT.assert smt (interpretFun env tm')+ Just name -> SMT.assertNamed smt name (interpretFun env tm')+ do b <- readIORef (svProduceAssertionsRef solver)+ when b $ modifyIORef (svAssertionsRef solver) (tm :)+ writeIORef (svModeRef solver) ModeAssert++getAssertions :: Solver -> IO [Term ()]+getAssertions solver = do+ mode <- readIORef (svModeRef solver)+ when (mode == ModeStart) $ do+ E.throwIO $ SMT.Error "get-assertions cannot be used in start mode"+ b <- readIORef (svProduceAssertionsRef solver)+ unless b $ do+ E.throwIO $ SMT.Error ":produce-assertions is not enabled"+ reverse <$> readIORef (svAssertionsRef solver)++checkSat :: Solver -> IO CheckSatResponse+checkSat solver = checkSatAssuming solver []++checkSatAssuming :: Solver -> [Term ()] -> IO CheckSatResponse+checkSatAssuming solver xs = do+ smt <- readIORef (svSMTSolverRef solver)++ env <- readIORef (svEnvRef solver)+ ref <- newIORef Map.empty+ ys <- forM xs $ \x -> do+ let y = interpretFun env x+ modifyIORef ref (Map.insert y x)+ return y++ ret <- SMT.checkSATAssuming smt ys++ do expected <- readIORef (svStatusRef solver)+ writeIORef (svStatusRef solver) Nothing -- I'm not sure if we should reset or not.+ h <- snd <$> readIORef (svDiagnosticOutputChannelRef solver)+ case expected of+ Just True | not ret -> hPutStrLn h "WARNING: unexpected unsat; expecting sat"+ Just False | ret -> hPutStrLn h "WARNING: unexpected sat; expecting unsat"+ _ -> return ()+ hFlush h++ if ret then do+ writeIORef (svModeRef solver) ModeSat+ return Sat+ else do+ writeIORef (svModeRef solver) ModeUnsat+ m <- readIORef ref+ es <- SMT.getUnsatAssumptions smt+ writeIORef (svUnsatAssumptionsRef solver) [m Map.! e | e <- es]+ return Unsat++getValue :: Solver -> [Term ()] -> IO [ValuationPair ()]+getValue solver ts = do+ ts' <- mapM (processNamed solver) ts+ mode <- readIORef (svModeRef solver)+ unless (mode == ModeSat) $ do+ E.throwIO $ SMT.Error "get-value can only be used in sat mode"+ smt <- readIORef (svSMTSolverRef solver)+ m <- SMT.getModel smt+ env <- readIORef (svEnvRef solver)+ forM ts' $ \t -> do+ let e = interpretFun env t+ let v = SMT.eval m e+ return $ ValuationPair t (valueToTerm v)++getAssignment :: Solver -> IO [(Symbol, Bool)]+getAssignment solver = do+ mode <- readIORef (svModeRef solver)+ unless (mode == ModeSat) $ do+ E.throwIO $ SMT.Error "get-assignment can only be used in sat mode"+ smt <- readIORef (svSMTSolverRef solver)+ m <- SMT.getModel smt+ (env, _) <- readIORef (svEnvRef solver)+ liftM concat $ forM (Map.toList env) $ \(name, entry) -> do+ case entry of+ EExpr e True -> do+ s <- SMT.exprSort smt e+ if s /= SMT.sBool then do+ return []+ else do+ let v = SMT.eval m e+ case v of+ (SMT.ValBool b) -> return [(T.pack name, b)]+ _ -> E.throwIO $ SMT.Error "get-assignment: should not happen"+ _ -> return []++getModel :: Solver -> IO [ModelResponse ()]+getModel solver = do+ mode <- readIORef (svModeRef solver)+ unless (mode == ModeSat) $ do+ E.throwIO $ SMT.Error "get-model can only be used in sat mode"+ smt <- readIORef (svSMTSolverRef solver)+ m <- SMT.getModel smt+ (env, _) <- readIORef (svEnvRef solver)++ let env2 =+ case SMT.evalFSym m "/0" of+ SMT.FunDef tbl _defaultVal | not (null tbl) -> Map.insert "/0" (EFSymDeclared "/0" [SMT.sReal] SMT.sReal) env+ _ -> env++ liftM catMaybes $ forM (Map.toList env2) $ \(name, entry) -> do+ case entry of+ EFSymDeclared sym argsSorts resultSort -> do+ case SMT.evalFSym m sym of+ SMT.FunDef [] val -> do -- constant+ return $ Just $ MRDefineFun (FunctionDef (T.pack name) [] (sortToSortTerm resultSort) (valueToTerm val) ())+ SMT.FunDef tbl defaultVal -> do -- proper function+ let argsSV :: [SortedVar ()]+ argsSV = [SortedVar (T.pack ("x!" ++ show i)) (sortToSortTerm s) () | (i,s) <- zip [(1::Int)..] argsSorts]+ args :: [Term ()]+ args = [TQualIdent (QIdentifier (simpleId x) ()) () | SortedVar x _ () <- argsSV]+ f :: ([SMT.Value], SMT.Value) -> Term () -> Term ()+ f (vals,val) tm =+ TApp (QIdentifier (simpleId "ite") ()) [cond, valueToTerm val, tm] ()+ where+ cond =+ case zipWith (\arg val' -> TApp (QIdentifier (simpleId "=") ()) [arg, valueToTerm val'] ()) args vals of+ [c] -> c+ cs -> TApp (QIdentifier (simpleId "and") ()) cs ()+ return $ Just $ MRDefineFun $ FunctionDef (T.pack name) argsSV (sortToSortTerm resultSort)+ (foldr f (valueToTerm defaultVal) tbl) ()+ _ -> return Nothing++getProof :: Solver -> IO (SExpr ())+getProof solver = do+ mode <- readIORef (svModeRef solver)+ if mode /= ModeUnsat then+ E.throwIO $ SMT.Error "get-proof can only be used in unsat mode"+ else+ E.throwIO SMT.Unsupported++getUnsatCore :: Solver -> IO [Symbol]+getUnsatCore solver = do+ smt <- readIORef (svSMTSolverRef solver)+ mode <- readIORef (svModeRef solver)+ unless (mode == ModeUnsat) $ do+ E.throwIO $ SMT.Error "get-unsat-core can only be used in unsat mode"+ map T.pack <$> SMT.getUnsatCore smt++getUnsatAssumptions :: Solver -> IO [Term ()]+getUnsatAssumptions solver = do+ mode <- readIORef (svModeRef solver)+ unless (mode == ModeUnsat) $ do+ E.throwIO $ SMT.Error "get-unsat-assumptions can only be used in unsat mode"+ readIORef (svUnsatAssumptionsRef solver)++exit :: Solver -> IO ()+exit _solver = exitSuccess++-- ----------------------------------------------------------------------++insertSort :: Solver -> String -> SortEntry -> IO ()+insertSort solver name sdef = do+ (fenv, senv) <- readIORef (svEnvRef solver)+ case Map.lookup name senv of+ Nothing -> writeIORef (svEnvRef solver) (fenv, Map.insert name sdef senv)+ Just _ -> E.throwIO $ SMT.Error (name ++ " is already used")++insertFun :: Solver -> String -> EEntry -> IO ()+insertFun solver name fdef = do+ (fenv, senv) <- readIORef (svEnvRef solver)+ case Map.lookup name fenv of+ Nothing -> writeIORef (svEnvRef solver) (Map.insert name fdef fenv, senv)+ Just _ -> E.throwIO $ SMT.Error (name ++ " is already used")++-- TODO: check closedness of terms+processNamed :: Solver -> Term () -> IO (Term ())+processNamed solver = f+ where+ f t@(TConstant _ ()) = return t+ f t@(TQualIdent _ ()) = return t+ f (TApp qid args ()) = do+ args' <- mapM f args+ return $ TApp qid args' ()+ f (TLet bindings body ()) = do+ body' <- f body+ return $ TLet bindings body' ()+ f (TLambda bindings body ()) = do+ body' <- f body+ return $ TLambda bindings body' ()+ f (TForall bindings body ()) = do+ body' <- f body+ return $ TForall bindings body' ()+ f (TExists bindings body ()) = do+ body' <- f body+ return $ TExists bindings body' ()+ f t@(TMatch _ _ ()) = return t+ f (TAnnot body attrs ()) = do+ body' <- f body+ forM_ attrs $ \attr -> do+ case attr of+ AttributeWith "named" val () ->+ case val of+ AVSymbol name () -> do+ env <- readIORef (svEnvRef solver)+ let e = interpretFun env body'+ -- smt <- readIORef (svSMTSolverRef solver)+ -- s <- SMT.exprSort smt e+ insertFun solver (T.unpack name) (EExpr e True)+ _ -> E.throwIO $ SMT.Error ":named attribute value should be a symbol"+ _ -> return ()+ let attrs' = [attr | attr <- attrs, attrName attr /= "named"]+ where+ attrName (Attribute s ()) = s+ attrName (AttributeWith s _v ()) = s+ if null attrs' then+ return body'+ else+ return $ TAnnot body' attrs' ()
src/ToySolver/Version.hs view
@@ -19,7 +19,7 @@ , compilationTime ) where -import Data.List+import Data.List (sort) import Data.Time import Data.Version import ToySolver.Version.TH
test/Test/AReal.hs view
@@ -286,6 +286,38 @@ intervals = Sturm.separate p vals = [-1.21465, -0.334734, 1.38879] +case_cauchysBounds_constant = do+ m @?= 0+ Sturm.numRoots p (Finite (-m) <=..<= Finite m) @?= 0+ where+ p = 1+ m = Sturm.cauchysBounds p++case_cauchysBounds_linear_1 = do+ m @?= (1 + 1/2)+ Sturm.numRoots p (Finite (-m) <=..<= Finite m) @?= 1+ where+ x = P.var X+ p = 2*x + 1+ m = Sturm.cauchysBounds p++case_cauchysBounds_linear_2 = do+ m @?= 1+ Sturm.numRoots p (Finite (-m) <=..<= Finite m) @?= 1+ where+ x = P.var X+ p = 2*x+ m = Sturm.cauchysBounds p++-- https://x.com/Pajoca_/status/1969404597845573723+case_cauchysBounds_pajoca = do+ m @?= 3+ Sturm.numRoots p (Finite (-m) <=..<= Finite m) @?= 1+ where+ x = P.var X+ p = 2*x^3 - 3*x^2 - 4+ m = Sturm.cauchysBounds p+ ------------------------------------------------------------------------ -- Test harness
test/Test/Arith.hs view
@@ -3,7 +3,6 @@ module Test.Arith (arithTestGroup) where import Control.Monad-import Data.List import Data.Default.Class import qualified Data.IntMap as IM import qualified Data.IntSet as IS
test/Test/BitVector.hs view
@@ -40,18 +40,19 @@ QM.monitor (counterexample $ show m) QM.assert $ and [BV.evalAtom m c | c <- cs] -case_division_by_zero_cong :: IO ()-case_division_by_zero_cong = do+-- Since SMT-LIB 2.6, the result of division by zero has been fixed to be a bit vector with all bits set to 1.+-- Before SMT-LIB 2.6, this was satisfiable.+case_division_by_zero :: IO ()+case_division_by_zero = do solver <- BV.newSolver v1 <- BV.newVar solver 8 v2 <- BV.newVar solver 8 let z = BV.nat2bv 8 0+ BV.assertAtom solver (BV.bvudiv v1 z .==. BV.nat2bv 8 255) Nothing+ BV.assertAtom solver (BV.bvurem v1 z .==. v1) Nothing BV.assertAtom solver (BV.bvudiv v1 z ./=. BV.bvudiv v2 z) Nothing ret <- BV.check solver- ret @?= True- BV.assertAtom solver (v1 .==. v2) Nothing- ret2 <- BV.check solver- ret2 @?= False+ ret @?= False -- ------------------------------------------------------------------------ -- Generators
test/Test/ContiTraverso.hs view
@@ -2,7 +2,6 @@ module Test.ContiTraverso (ctTestGroup) where import Control.Monad-import Data.List import qualified Data.IntMap as IM import qualified Data.IntSet as IS import qualified Data.Map as Map
test/Test/Converter.hs view
@@ -1,6 +1,7 @@ {-# OPTIONS_GHC -Wall #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} module Test.Converter (converterTestGroup) where@@ -614,9 +615,6 @@ let (opb, info) = wbo2pb wbo QM.monitor $ counterexample (show opb) - -- no constant terms in objective function- QM.assert $ all (\(_,ls) -> length ls > 0) $ fromMaybe [] (PBFile.pbObjectiveFunction opb)- solver1 <- arbitrarySolver solver2 <- arbitrarySolver method <- QM.pick arbitrary@@ -800,6 +798,30 @@ QM.assert $ bounds m1 == (1, PBFile.pbNumVars opb) QM.assert $ isJust $ SAT.evalPBFormula m1 opb +case_inequalitiesToEqualitiesPB_taut :: Assertion+case_inequalitiesToEqualitiesPB_taut = PBFile.pbNumConstraints opb2 @?= 0+ where+ opb =+ PBFile.Formula+ { PBFile.pbObjectiveFunction = Nothing+ , PBFile.pbConstraints = [([(1,[1]), (1,[])], PBFile.Ge, 0)] -- x1 + 1 >= 0+ , PBFile.pbNumVars = 1+ , PBFile.pbNumConstraints = 1+ }+ (opb2, _info) = inequalitiesToEqualitiesPB opb++case_inequalitiesToEqualitiesPB_num_surplus_vars :: Assertion+case_inequalitiesToEqualitiesPB_num_surplus_vars = (PBFile.pbNumVars opb2 @?= 3+2)+ where+ opb =+ PBFile.Formula+ { PBFile.pbObjectiveFunction = Nothing+ , PBFile.pbConstraints = [([(4,[1]), (4,[2]), (6,[3])], PBFile.Ge, 8)] -- 4 x1 + 4 x2 + 6 x3 >= 8+ , PBFile.pbNumVars = 3+ , PBFile.pbNumConstraints = 1+ }+ (opb2, _info) = inequalitiesToEqualitiesPB opb+ prop_inequalitiesToEqualitiesPB_json :: Property prop_inequalitiesToEqualitiesPB_json = forAll arbitraryPBFormula $ \opb -> let ret@(_, info) = inequalitiesToEqualitiesPB opb@@ -807,6 +829,113 @@ in counterexample (show ret) $ counterexample (show json) $ J.eitherDecode json == Right info +prop_normalizePB :: Property+prop_normalizePB = QM.monadicIO $ do+ opb <- QM.pick arbitraryPBFormula+ let (opb2, info) = normalizePB opb+ QM.monitor $ counterexample (show opb2)++ QM.assert $+ PBFile.pbNumVars opb2 == PBFile.pbNumVars opb ||+ PBFile.pbNumVars opb2 == PBFile.pbNumVars opb + 1+ QM.assert $ and+ [ case t of+ (_, []) -> False+ (_, [l]) -> l > 0+ _ -> True+ | s <- maybeToList (PBFile.pbObjectiveFunction opb2) ++ [lhs | (lhs,_,_) <- PBFile.pbConstraints opb2]+ , t <- s+ ]++ solver1 <- arbitrarySolver+ solver2 <- arbitrarySolver+ ret1 <- QM.run $ solvePBFormula solver1 opb+ ret2 <- QM.run $ solvePBFormula solver2 opb2+ QM.assert $ isJust ret1 == isJust ret2+ case ret1 of+ Nothing -> return ()+ Just m1 -> do+ let m2 = transformForward info m1+ QM.assert $ bounds m2 == (1, PBFile.pbNumVars opb2)+ QM.assert $ isJust $ SAT.evalPBFormula m2 opb2+ case ret2 of+ Nothing -> return ()+ Just m2 -> do+ let m1 = transformBackward info m2+ QM.assert $ bounds m1 == (1, PBFile.pbNumVars opb)+ QM.assert $ isJust $ SAT.evalPBFormula m1 opb++case_normalizePB_1 :: Assertion+case_normalizePB_1 = fst (normalizePB opb) @?= expected+ where+ opb =+ PBFile.Formula+ { PBFile.pbNumVars = 2+ , PBFile.pbNumConstraints = 1+ , PBFile.pbObjectiveFunction = Just [(1, [1,2]), (1, [-1]), (1, [])]+ , PBFile.pbConstraints =+ [ ([(1, [1,2]), (1, [-1]), (1, [])], PBFile.Ge, 2)+ ]+ }+ expected =+ PBFile.Formula+ { PBFile.pbNumVars = 3+ , PBFile.pbNumConstraints = 1+ , PBFile.pbObjectiveFunction = Just [(1, [1,2]), (-1, [1]), (2, [3])]+ , PBFile.pbConstraints =+ [ ([(1, [1,2]), (-1, [1])], PBFile.Ge, 0)+ , ([(1, [3])], PBFile.Ge, 1)+ ]+ }++case_normalizePB_2 :: Assertion+case_normalizePB_2 = fst (normalizePB opb) @?= expected+ where+ opb =+ PBFile.Formula+ { PBFile.pbNumVars = 2+ , PBFile.pbNumConstraints = 1+ , PBFile.pbObjectiveFunction = Just [(1, [1,2]), (1, [-1]), (1, [])]+ , PBFile.pbConstraints =+ [ ([(1, [1,2]), (1, [-1]), (1, [])], PBFile.Ge, 2)+ , ([(3, [2])], PBFile.Ge, 2)+ ]+ }+ expected =+ PBFile.Formula+ { PBFile.pbNumVars = 2+ , PBFile.pbNumConstraints = 1+ , PBFile.pbObjectiveFunction = Just [(1, [1,2]), (-1, [1]), (2, [2])]+ , PBFile.pbConstraints =+ [ ([(1, [1,2]), (-1, [1])], PBFile.Ge, 0)+ , ([(3, [2])], PBFile.Ge, 2)+ ]+ }++case_normalizePB_3 :: Assertion+case_normalizePB_3 = fst (normalizePB opb) @?= expected+ where+ opb =+ PBFile.Formula+ { PBFile.pbNumVars = 2+ , PBFile.pbNumConstraints = 1+ , PBFile.pbObjectiveFunction = Just [(1, [1,2]), (1, [-1]), (1, [])]+ , PBFile.pbConstraints =+ [ ([(1, [1,2]), (1, [-1]), (1, [])], PBFile.Ge, 2)+ , ([(-2, [-2])], PBFile.Ge, -1)+ ]+ }+ expected =+ PBFile.Formula+ { PBFile.pbNumVars = 2+ , PBFile.pbNumConstraints = 1+ , PBFile.pbObjectiveFunction = Just [(1, [1,2]), (-1, [1]), (2, [2])]+ , PBFile.pbConstraints =+ [ ([(1, [1,2]), (-1, [1])], PBFile.Ge, 0)+ , ([(2, [2])], PBFile.Ge, 1)+ ]+ }+ ------------------------------------------------------------------------ prop_pb2ip_forward :: Property@@ -920,6 +1049,110 @@ in counterexample (show ret) $ counterexample (show json) $ J.eitherDecode json === Right info +case_ip2pb_continuous_error :: Assertion+case_ip2pb_continuous_error =+ case ip2pb prob of+ Left _ -> return ()+ Right _ -> assertFailure "should be error"+ where+ prob :: MIP.Problem Rational+ prob =+ MIP.def+ { MIP.constraints =+ [ MIP.def+ { MIP.constrExpr = MIP.varExpr "x"+ , MIP.constrLB = 1/2+ }+ ]+ , MIP.varDomains = Map.fromList [("x", (MIP.ContinuousVariable, (0, 1)))]+ }++case_ip2pb_semi_continuous_error :: Assertion+case_ip2pb_semi_continuous_error =+ case ip2pb prob of+ Left _ -> return ()+ Right _ -> assertFailure "should be error"+ where+ prob :: MIP.Problem Rational+ prob =+ MIP.def+ { MIP.constraints =+ [ MIP.def+ { MIP.constrExpr = MIP.varExpr "x"+ , MIP.constrUB = 50+ }+ ]+ , MIP.varDomains = Map.fromList [("x", (MIP.SemiContinuousVariable, (10, 100)))]+ }++case_ip2pb_unbounded_error_1 :: Assertion+case_ip2pb_unbounded_error_1 =+ case ip2pb prob of+ Left _ -> return ()+ Right _ -> assertFailure "should be error"+ where+ prob :: MIP.Problem Rational+ prob =+ MIP.def+ { MIP.constraints =+ [ MIP.def+ { MIP.constrExpr = MIP.varExpr "x"+ , MIP.constrUB = 50+ }+ ]+ , MIP.varDomains = Map.fromList [("x", (MIP.IntegerVariable, (0, MIP.PosInf)))]+ }++case_ip2pb_unbounded_error_2 :: Assertion+case_ip2pb_unbounded_error_2 =+ case ip2pb prob of+ Left _ -> return ()+ Right _ -> assertFailure "should be error"+ where+ prob :: MIP.Problem Rational+ prob =+ MIP.def+ { MIP.constraints =+ [ MIP.def+ { MIP.constrExpr = MIP.varExpr "x"+ , MIP.constrUB = -50+ }+ ]+ , MIP.varDomains = Map.fromList [("x", (MIP.IntegerVariable, (MIP.NegInf, 0)))]+ }++prop_normalizeMIPObjective :: Property+prop_normalizeMIPObjective =+ forAll arbitraryBoundedIP $ \prob ->+ let ret@(prob', _) = normalizeMIPObjective prob+ in counterexample (show ret) $+ all (\(MIP.Term _ vs) -> not (null vs)) (MIP.terms (MIP.objExpr (MIP.objectiveFunction prob')))++prop_normalizeMIPObjective_round_trip :: Property+prop_normalizeMIPObjective_round_trip =+ forAll arbitraryBoundedIP $ \prob ->+ let ret@(prob', info) = normalizeMIPObjective prob+ in counterexample (show ret) $+ forAll (arbitraryAssignmentBoundedIP prob) $ \sol ->+ let result1 = evalMIP sol prob+ result2 = evalMIP (transformForward info sol) prob'+ result3 = fmap (transformObjValueForward info) result1+ result4 = fmap (transformObjValueBackward info . transformObjValueForward info) result1+ in conjoin+ [ sol === transformBackward info (transformForward info sol)+ , result1 === result2+ , result1 === result3+ , result1 === result4+ ]++prop_normalizeMIPObjective_json :: Property+prop_normalizeMIPObjective_json =+ forAll arbitraryBoundedIP $ \prob ->+ let ret@(_, info) = normalizeMIPObjective prob+ json = J.encode info+ in counterexample (show ret) $ counterexample (show json) $+ J.eitherDecode json === Right info+ arbitraryBoundedIP :: Gen (MIP.Problem Rational) arbitraryBoundedIP = do nv <- choose (0,10)@@ -927,14 +1160,16 @@ let v = fromString ("z" ++ show i) b <- arbitrary if b then- pure (v, (MIP.Finite 0, MIP.Finite 1))+ pure (v, (MIP.IntegerVariable, (MIP.Finite 0, MIP.Finite 1))) else do lb <- arbitrary NonNegative w <- arbitrary let ub = fromInteger (ceiling lb) + w- return (v, (MIP.Finite lb, MIP.Finite ub))+ b2 <- arbitrary+ return (v, (if b2 then MIP.IntegerVariable else MIP.SemiIntegerVariable, (MIP.Finite lb, MIP.Finite ub)))+ let vs = Map.keys bs- vs_bin = [v | (v, (MIP.Finite 0, MIP.Finite 1)) <- Map.toList bs]+ vs_bin = [v | (v, (MIP.IntegerVariable, (MIP.Finite 0, MIP.Finite 1))) <- Map.toList bs] dir <- elements [MIP.OptMin, MIP.OptMax] obj <- arbitraryMIPExpr vs@@ -978,7 +1213,7 @@ return $ MIP.def { MIP.objectiveFunction = MIP.def{ MIP.objDir = dir, MIP.objExpr = obj }- , MIP.varDomains = fmap (\b -> (MIP.IntegerVariable, b)) bs+ , MIP.varDomains = bs , MIP.constraints = cs , MIP.sosConstraints = sos }
test/Test/MIPSolver.hs view
@@ -2,7 +2,6 @@ module Test.MIPSolver (mipSolverTestGroup) where import Control.Monad-import Data.List import Data.Ratio import qualified Data.IntMap as IM import qualified Data.IntSet as IS
test/Test/Misc.hs view
@@ -1,9 +1,13 @@ {-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} module Test.Misc (miscTestGroup) where +import qualified Data.ByteString.Char8 as BS import Control.Monad+import System.IO+import System.IO.Temp import Test.Tasty import Test.Tasty.QuickCheck hiding ((.&&.), (.||.)) import Test.Tasty.HUnit@@ -129,6 +133,18 @@ x1, x2 :: BoolExpr Int x1 = Atom 1 x2 = Atom 2++------------------------------------------------------------------------+-- Test harness++-- We assume that bytestring IO does not convrert new lines even on text mode on Windows.+case_bytestring_newline :: Assertion+case_bytestring_newline = do+ withSystemTempDirectory "toysolver-test-" $ \dir -> do+ withFile (dir ++ "/test.txt") WriteMode $ \h -> do+ BS.hPutStr h "foo\nbar"+ s <- BS.readFile (dir ++ "/test.txt")+ s @?= "foo\nbar" ------------------------------------------------------------------------ -- Test harness
test/Test/QUBO.hs view
@@ -129,7 +129,7 @@ ] , forAll (arbitrarySolution (QUBO.quboNumVars qubo)) $ \sol -> let o = QUBO.eval sol qubo- in if (o <= th) then+ in if o <= th then (SAT.evalPBFormula (transformBackward info sol) formula === Just (transformObjValueBackward info o)) .&&. transformObjValueForward info (transformObjValueBackward info o) === o
test/Test/SAT.hs view
@@ -1,5 +1,6 @@ {-# OPTIONS_GHC -Wall #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} module Test.SAT (satTestGroup) where@@ -7,11 +8,13 @@ import Control.Exception import Control.Monad import Data.Array.IArray+import qualified Data.ByteString.Builder as Builder import Data.Default.Class import qualified Data.IntSet as IntSet import Data.IORef import qualified Data.Map.Strict as Map import qualified Data.Vector as V+import System.IO import qualified System.Random.MWC as Rand import Test.Tasty@@ -23,6 +26,7 @@ import ToySolver.Data.LBool import qualified ToySolver.FileFormat.CNF as CNF import qualified ToySolver.SAT as SAT+import qualified ToySolver.SAT.Printer as Printer import Test.SAT.Utils @@ -683,6 +687,53 @@ Nothing -> do forM_ (allAssignments (CNF.cnfNumVars cnf)) $ \m -> do QM.assert $ not (evalCNF m cnf && SAT.evalSOS2 m sos2)++------------------------------------------------------------------------+-- Printer++case_Printer_satModel :: Assertion+case_Printer_satModel = do+ let m1 = array (1,3) [(1, True), (2, False), (3, True)]+ Builder.toLazyByteString (Printer.satModel m1 0 LF ) @?= "v 1 -2 3\nv 0\n"+ Builder.toLazyByteString (Printer.satModel m1 0 CRLF) @?= "v 1 -2 3\r\nv 0\r\n"+ let m2 = array (1,11) (zip [1..11] (repeat True))+ Builder.toLazyByteString (Printer.satModel m2 0 LF ) @?= "v 1 2 3 4 5 6 7 8 9 10\nv 11\nv 0\n"+ Builder.toLazyByteString (Printer.satModel m2 3 LF ) @?= "v 1 2 3\nv 0\n"++case_Printer_maxsatModel :: Assertion+case_Printer_maxsatModel = do+ let m1 = array (1,3) [(1, True), (2, False), (3, True)]+ Builder.toLazyByteString (Printer.maxsatModel m1 0 LF ) @?= "v 1 -2 3\n"+ Builder.toLazyByteString (Printer.maxsatModel m1 0 CRLF) @?= "v 1 -2 3\r\n"+ let m2 = array (1,11) (zip [1..11] (repeat True))+ Builder.toLazyByteString (Printer.maxsatModel m2 0 LF ) @?= "v 1 2 3 4 5 6 7 8 9 10\nv 11\n"+ Builder.toLazyByteString (Printer.maxsatModel m2 3 LF ) @?= "v 1 2 3\n"++case_Printer_maxsatModelCompact :: Assertion+case_Printer_maxsatModelCompact = do+ let m1 = array (1,3) [(1, True), (2, False), (3, True)]+ Builder.toLazyByteString (Printer.maxsatModelCompact m1 0 LF ) @?= "v 101\n"+ Builder.toLazyByteString (Printer.maxsatModelCompact m1 0 CRLF) @?= "v 101\r\n"+ let m2 = array (1,11) (zip [1..11] (repeat True))+ Builder.toLazyByteString (Printer.maxsatModelCompact m2 0 LF ) @?= "v 11111111111\n"+ Builder.toLazyByteString (Printer.maxsatModelCompact m2 3 LF ) @?= "v 111\n"++case_Printer_pbModel :: Assertion+case_Printer_pbModel = do+ let m1 = array (1,3) [(1, True), (2, False), (3, True)]+ Builder.toLazyByteString (Printer.pbModel m1 0 LF ) @?= "v x1 -x2 x3\n"+ Builder.toLazyByteString (Printer.pbModel m1 0 CRLF) @?= "v x1 -x2 x3\r\n"+ let m2 = array (1,11) (zip [1..11] (repeat True))+ Builder.toLazyByteString (Printer.pbModel m2 0 LF ) @?= "v x1 x2 x3 x4 x5 x6 x7 x8 x9 x10\nv x11\n"+ Builder.toLazyByteString (Printer.pbModel m2 3 LF ) @?= "v x1 x2 x3\n"++case_Printer_musSol :: Assertion+case_Printer_musSol = do+ let is1 = [1, 5, 8]+ Builder.toLazyByteString (Printer.musSol is1 LF ) @?= "v 1 5 8\nv 0\n"+ Builder.toLazyByteString (Printer.musSol is1 CRLF) @?= "v 1 5 8\r\nv 0\r\n"+ let is2 = [1..11]+ Builder.toLazyByteString (Printer.musSol is2 LF ) @?= "v 1 2 3 4 5 6 7 8 9 10\nv 11\nv 0\n" ------------------------------------------------------------------------ -- Test harness
test/Test/SAT/Encoder.hs view
@@ -8,8 +8,9 @@ import Data.Array.IArray import qualified Data.IntMap.Strict as IntMap import Data.IORef-import Data.List+import Data.List (sort) import Data.Maybe+import qualified Data.PseudoBoolean as PBFile import qualified Data.Vector as V import System.IO.Unsafe @@ -19,6 +20,7 @@ import Test.Tasty.TH import qualified Test.QuickCheck.Monadic as QM +import qualified ToySolver.Combinatorial.SubsetSum as SubsetSum import ToySolver.Data.Boolean import ToySolver.Data.LBool import qualified ToySolver.FileFormat.CNF as CNF@@ -28,10 +30,12 @@ import ToySolver.SAT.Encoder.Tseitin (Formula (..)) import qualified ToySolver.SAT.Encoder.Cardinality as Cardinality import qualified ToySolver.SAT.Encoder.Cardinality.Internal.Totalizer as Totalizer+import qualified ToySolver.SAT.Encoder.Integer as Integer import qualified ToySolver.SAT.Encoder.PB as PB import qualified ToySolver.SAT.Encoder.PB.Internal.Sorter as PBEncSorter import qualified ToySolver.SAT.Encoder.PB.Internal.BCCNF as BCCNF import qualified ToySolver.SAT.Store.CNF as CNFStore+import qualified ToySolver.SAT.Store.PB as PBStore import Test.SAT.Utils @@ -534,6 +538,28 @@ ] where eval m = and . map (or . map (SAT.evalAtLeast m))++-- ------------------------------------------------------------------------++prop_Integer_newVar :: Property+prop_Integer_newVar =+ forAll arbitrary $ \lb ->+ forAll (fmap (\(NonNegative w) -> lb + w) arbitrary) $ \ub ->+ QM.monadicST $ do+ store <- QM.run $ PBStore.newPBStore+ e@(Integer.Expr s) <- QM.run $ Integer.newVar store lb ub+ QM.monitor (counterexample (show e))+ QM.assert (SAT.pbLowerBound s == lb)+ QM.assert (SAT.pbUpperBound s == ub)+ QM.assert (all (\(_,ls) -> length ls <= 1) s)++ formula <- QM.run $ PBStore.getPBFormula store+ QM.assert (null (PBFile.pbConstraints formula))++ val <- QM.pick $ choose (lb,ub)+ case SubsetSum.subsetSum (V.fromList [c | (c,[_]) <- s]) (val - sum [c | (c,[]) <- s]) of+ Just _ -> return ()+ Nothing -> fail "fail to find an assignment" -- ------------------------------------------------------------------------
+ test/Test/SAT/LogParser.hs view
@@ -0,0 +1,269 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+module Test.SAT.LogParser (satLogParserTestGroup) where++import Data.Array.IArray+import qualified Data.ByteString.Lazy.Char8 as BL+import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.TH++import ToySolver.SAT.LogParser++-- ------------------------------------------------------------------------++case_parseSATLog_SATISFIABLE :: Assertion+case_parseSATLog_SATISFIABLE = parseSATLog input @?= expected+ where+ input = BL.unlines+ [ "c foo"+ , "s SATISFIABLE"+ , "c bar"+ , "v -1 -2 3 4 -5"+ , "c baz"+ , "v 6 -7 8 9 -10"+ , "c quz"+ , "v 0"+ ]+ expected =+ ( "SATISFIABLE"+ , Just $ array (1, 10) [(1, False), (2, False), (3, True), (4, True), (5, False), (6, True), (7, False), (8, True), (9, True), (10, False)]+ )++case_parseSATLog_UNSATISFIABLE :: Assertion+case_parseSATLog_UNSATISFIABLE = parseSATLog input @?= expected+ where+ input = BL.unlines+ [ "c foo"+ , "s UNSATISFIABLE"+ , "c bar"+ ]+ expected =+ ( "UNSATISFIABLE"+ , Nothing+ )++case_parseSATLog_UNKNOWN :: Assertion+case_parseSATLog_UNKNOWN = parseSATLog input @?= expected+ where+ input = BL.unlines+ [ "c foo"+ , "s UNKNOWN"+ , "c bar"+ ]+ expected =+ ( "UNKNOWN"+ , Nothing+ )++case_parseSATLog_UNKNOWN_implicit :: Assertion+case_parseSATLog_UNKNOWN_implicit = parseSATLog input @?= expected+ where+ input = BL.unlines ["c foo"]+ expected =+ ( "UNKNOWN"+ , Nothing+ )++-- ------------------------------------------------------------------------++case_parseMaxSATLog_UNSATISFIABLE :: Assertion+case_parseMaxSATLog_UNSATISFIABLE = parseMaxSATLog input @?= expected+ where+ input = BL.unlines+ [ "c foo"+ , "s UNSATISFIABLE"+ , "c bar"+ ]+ expected =+ ( "UNSATISFIABLE"+ , Nothing+ , Nothing+ )++case_parseMaxSATLog_UNKNOWN :: Assertion+case_parseMaxSATLog_UNKNOWN = parseMaxSATLog input @?= expected+ where+ input = BL.unlines+ [ "c foo"+ , "s UNKNOWN"+ , "c bar"+ ]+ expected =+ ( "UNKNOWN"+ , Nothing+ , Nothing+ )++case_parseMaxSATLog_UNKNOWN_implicit :: Assertion+case_parseMaxSATLog_UNKNOWN_implicit = parsePBLog input @?= expected+ where+ input = BL.unlines ["c foo"]+ expected =+ ( "UNKNOWN"+ , Nothing+ , Nothing+ )++case_parseMaxSATLog_OPTIMUM_FOUND_old :: Assertion+case_parseMaxSATLog_OPTIMUM_FOUND_old = parseMaxSATLog input @?= expected+ where+ input = BL.unlines+ [ "c foo"+ , "o 4750"+ , "o 232"+ , "s OPTIMUM FOUND"+ , "c bar"+ , "v -1 -2 3 4 -5"+ , "c baz"+ , "v 6 -7 8 9 -10"+ , "c quz"+ ]+ expected =+ ( "OPTIMUM FOUND"+ , Just 232+ , Just $ array (1, 10) [(1, False), (2, False), (3, True), (4, True), (5, False), (6, True), (7, False), (8, True), (9, True), (10, False)]+ )++case_parseMaxSATLog_OPTIMUM_FOUND_new :: Assertion+case_parseMaxSATLog_OPTIMUM_FOUND_new = parseMaxSATLog input @?= expected+ where+ input = BL.unlines+ [ "c foo"+ , "o 4750"+ , "o 232"+ , "s OPTIMUM FOUND"+ , "c bar"+ , "v 00110"+ , "c baz"+ , "v 10110"+ , "c quz"+ ]+ expected =+ ( "OPTIMUM FOUND"+ , Just 232+ , Just $ array (1, 10) [(1, False), (2, False), (3, True), (4, True), (5, False), (6, True), (7, False), (8, True), (9, True), (10, False)]+ )++-- Special Track on Incomplete Solvers allowed multiple v-lines+-- http://maxsat.ia.udl.cat/requirements/+case_parseMaxSATLog_multiple_vlines :: Assertion+case_parseMaxSATLog_multiple_vlines = parseMaxSATLog input @?= expected+ where+ input = BL.unlines+ [ "c foo"+ , "o 4750"+ , "v 1 2 3 4 5 6 7 8 9 10"+ , "o 232"+ , "c bar"+ , "v -1 -2 3 4 -5 6 -7 8 9 -10"+ , "s SATISFIABLE"+ , "c quz"+ ]+ expected =+ ( "SATISFIABLE"+ , Just 232+ , Just $ array (1, 10) [(1, False), (2, False), (3, True), (4, True), (5, False), (6, True), (7, False), (8, True), (9, True), (10, False)]+ )++-- ------------------------------------------------------------------------++case_parsePBLog_OPTIMUM_FOUND :: Assertion+case_parsePBLog_OPTIMUM_FOUND = parsePBLog input @?= expected+ where+ input = BL.unlines+ [ "c foo"+ , "o 4750"+ , "o 232"+ , "s OPTIMUM FOUND"+ , "c bar"+ , "v -x1 -x2 x3 x4 -x5"+ , "c baz"+ , "v x6 -x7 x8 x9 -x10"+ , "c quz"+ ]+ expected =+ ( "OPTIMUM FOUND"+ , Just 232+ , Just $ array (1, 10) [(1, False), (2, False), (3, True), (4, True), (5, False), (6, True), (7, False), (8, True), (9, True), (10, False)]+ )++case_parsePBLog_SATISFIABLE :: Assertion+case_parsePBLog_SATISFIABLE = parsePBLog input @?= expected+ where+ input = BL.unlines+ [ "c foo"+ , "o 4750"+ , "o 232"+ , "s SATISFIABLE"+ , "c bar"+ , "v -x1 -x2 x3 x4 -x5"+ , "c baz"+ , "v x6 -x7 x8 x9 -x10"+ , "c quz"+ ]+ expected =+ ( "SATISFIABLE"+ , Just 232+ , Just $ array (1, 10) [(1, False), (2, False), (3, True), (4, True), (5, False), (6, True), (7, False), (8, True), (9, True), (10, False)]+ )++case_parsePBLog_UNSATISFIABLE :: Assertion+case_parsePBLog_UNSATISFIABLE = parsePBLog input @?= expected+ where+ input = BL.unlines+ [ "c foo"+ , "s UNSATISFIABLE"+ , "c bar"+ ]+ expected =+ ( "UNSATISFIABLE"+ , Nothing+ , Nothing+ )++case_parsePBLog_UNKNOWN :: Assertion+case_parsePBLog_UNKNOWN = parsePBLog input @?= expected+ where+ input = BL.unlines+ [ "c foo"+ , "s UNKNOWN"+ , "c bar"+ ]+ expected =+ ( "UNKNOWN"+ , Nothing+ , Nothing+ )++case_parsePBLog_UNKNOWN_implicit :: Assertion+case_parsePBLog_UNKNOWN_implicit = parsePBLog input @?= expected+ where+ input = BL.unlines ["c foo"]+ expected =+ ( "UNKNOWN"+ , Nothing+ , Nothing+ )++case_parsePBLog_UNSUPPORTED :: Assertion+case_parsePBLog_UNSUPPORTED = parsePBLog input @?= expected+ where+ input = BL.unlines+ [ "c foo"+ , "s UNSUPPORTED"+ , "c bar"+ ]+ expected =+ ( "UNSUPPORTED"+ , Nothing+ , Nothing+ )++-- ------------------------------------------------------------------------++satLogParserTestGroup :: TestTree+satLogParserTestGroup = $(testGroupGenerator)
test/Test/SAT/Types.hs view
@@ -6,7 +6,7 @@ import Control.Monad import Data.Array.IArray-import Data.List+import Data.List (sort) import Test.Tasty import Test.Tasty.QuickCheck
test/Test/SAT/Utils.hs view
@@ -9,7 +9,7 @@ import Data.Default.Class import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet-import Data.List+import Data.List (foldl') import Data.Maybe import qualified Data.Vector as V import qualified System.Random.MWC as Rand
test/Test/SDPFile.hs view
@@ -3,7 +3,6 @@ import Control.Monad import qualified Data.Aeson as J-import Data.List import Data.Maybe import Data.ByteString.Builder (toLazyByteString) import Test.Tasty
test/Test/SMT.hs view
@@ -362,6 +362,35 @@ evaluate $ force $ show $ SMT.evalFSym m f return () +case_getModel_evalFSym_case_1 :: Assertion+case_getModel_evalFSym_case_1 = do+ solver <- SMT.newSolver+ (sU :: SMT.Sort) <- SMT.declareSort solver "U" 0+ f <- SMT.declareFSym solver "f" [sU] sU+ c <- SMT.declareFSym solver "c" [] sU++ ret <- SMT.checkSAT solver+ ret @?= True+ m <- SMT.getModel solver+ case SMT.evalFSym m f of+ SMT.FunDef table _defaultValue -> table @?= []+ -- Table is always empty for constant symbol and defaultValue is used.+ case SMT.evalFSym m c of+ SMT.FunDef table _defaultValue -> table @?= []++ SMT.assert solver (SMT.EAp f [SMT.EAp c []] .==. SMT.EAp c [])+ ret <- SMT.checkSAT solver+ ret @?= True+ m <- SMT.getModel solver+ case SMT.evalFSym m f of+ fdef@(SMT.FunDef table _defaultValue) ->+ case table of+ [([arg], ret)] -> ret @?= arg+ _ -> assertFailure ("unexpected FunDef value: " ++ show fdef)+ -- Table is always empty for constant symbol and defaultValue is used.+ case SMT.evalFSym m c of+ SMT.FunDef table _defaultValue -> table @?= []+ -- https://github.com/msakai/toysolver/issues/21 case_issue21_32bit :: Assertion case_issue21_32bit = do
test/Test/SMTLIB2Solver.hs view
@@ -1,22 +1,18 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} module Test.SMTLIB2Solver (smtlib2SolverTestGroup) where -import Control.Applicative((<$>))-import Control.Exception (evaluate) import Control.Monad-import Control.Monad.State.Strict-import Data.List-import Data.Map (Map)+import Data.List (sort) import qualified Data.Map as Map-import Data.Set (Set) import qualified Data.Set as Set+import qualified Data.Text as T import Test.Tasty-import Test.Tasty.QuickCheck hiding ((.&&.), (.||.)) import Test.Tasty.HUnit import Test.Tasty.TH-import qualified Test.QuickCheck.Monadic as QM import ToySolver.SMT.SMTLIB2Solver as SMTLIB2 @@ -24,34 +20,33 @@ case_assertionStackLevels = do solver <- SMTLIB2.newSolver SMTLIB2.setLogic solver "QF_UF"- lv1 <- SMTLIB2.getInfo solver AssertionStackLevels- lv1 @?= [ResponseAssertionStackLevels 0]+ lv1 <- SMTLIB2.getInfo solver (AssertionStackLevels ())+ lv1 @?= [IRAssertionStackLevels 0] SMTLIB2.push solver 1- lv2 <- SMTLIB2.getInfo solver AssertionStackLevels- lv2 @?= [ResponseAssertionStackLevels 1]+ lv2 <- SMTLIB2.getInfo solver (AssertionStackLevels ())+ lv2 @?= [IRAssertionStackLevels 1] SMTLIB2.pop solver 1- lv3 <- SMTLIB2.getInfo solver AssertionStackLevels- lv3 @?= [ResponseAssertionStackLevels 0]+ lv3 <- SMTLIB2.getInfo solver (AssertionStackLevels ())+ lv3 @?= [IRAssertionStackLevels 0] case_getUnsatAssumptions :: Assertion case_getUnsatAssumptions = do solver <- SMTLIB2.newSolver- SMTLIB2.setOption solver (ProduceUnsatAssumptions True)+ SMTLIB2.setOption solver (ProduceUnsatAssumptions True ()) o <- SMTLIB2.getOption solver ":produce-unsat-assumptions"- o @?= AttrValueSymbol "true"+ o @?= AVSymbol "true" () SMTLIB2.setLogic solver "QF_UF"- SMTLIB2.declareFun solver "a" [] (SortId (ISymbol "Bool"))- SMTLIB2.declareFun solver "b" [] (SortId (ISymbol "Bool"))- SMTLIB2.runCommandString solver "(assert (or a b))"+ SMTLIB2.declareFun solver "a" [] (Sort (Symbol "Bool") [] ())+ SMTLIB2.declareFun solver "b" [] (Sort (Symbol "Bool") [] ())+ _ <- SMTLIB2.runCommandString solver "(assert (or a b))" r <- SMTLIB2.runCommandString solver "(check-sat-assuming ((not a) (not b)))"- r @?= CmdCheckSatResponse Unsat- r <- SMTLIB2.getUnsatAssumptions solver+ r @?= RCheckSat Unsat+ r2 <- SMTLIB2.getUnsatAssumptions solver let expected =- [ TermQualIdentifierT (QIdentifier (ISymbol "not")) [TermQualIdentifier (QIdentifier (ISymbol "a"))]- , TermQualIdentifierT (QIdentifier (ISymbol "not")) [TermQualIdentifier (QIdentifier (ISymbol "b"))]+ [ TApp (QIdentifier (Symbol "not") ()) [TQualIdent (QIdentifier (Symbol "a") ()) ()] ()+ , TApp (QIdentifier (Symbol "not") ()) [TQualIdent (QIdentifier (Symbol "b") ()) ()] () ]- -- XXX: Term type is not Hashable nor Ord.- Set.fromList (map showSL r) @?= Set.fromList (map showSL expected)+ Set.fromList r2 @?= Set.fromList expected case_declareConst :: Assertion case_declareConst = do@@ -61,10 +56,19 @@ assertSuccess =<< SMTLIB2.runCommandString solver "(declare-const x Bool)" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-const y Bool)" +case_defineConst :: Assertion+case_defineConst = do+ solver <- SMTLIB2.newSolver+ SMTLIB2.setLogic solver "QF_LRA"+ assertSuccess =<< SMTLIB2.runCommandString solver "(define-const x Real 3)"+ assertSuccess =<< SMTLIB2.runCommandString solver "(assert (not (= x 3)))"+ r <- SMTLIB2.checkSat solver+ r @?= Unsat+ case_divisionByZero :: Assertion case_divisionByZero = do solver <- SMTLIB2.newSolver- SMTLIB2.setOption solver (ProduceUnsatAssumptions True)+ SMTLIB2.setOption solver (ProduceUnsatAssumptions True ()) SMTLIB2.setLogic solver "QF_LRA" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-const x1 Real)" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-const x2 Real)"@@ -75,19 +79,19 @@ r @?= Sat assertSuccess =<< SMTLIB2.runCommandString solver "(assert (not (= y1 y2)))"- r <- SMTLIB2.checkSat solver- r @?= Sat+ r2 <- SMTLIB2.checkSat solver+ r2 @?= Sat assertSuccess =<< SMTLIB2.runCommandString solver "(assert (= x1 x2))"- r <- SMTLIB2.checkSat solver- r @?= Unsat+ r3 <- SMTLIB2.checkSat solver+ r3 @?= Unsat case_getAssertions :: Assertion case_getAssertions = do solver <- SMTLIB2.newSolver- SMTLIB2.setOption solver (ProduceAssertions True)+ SMTLIB2.setOption solver (ProduceAssertions True ()) o <- SMTLIB2.getOption solver ":produce-assertions"- o @?= AttrValueSymbol "true"+ o @?= AVSymbol "true" () SMTLIB2.setLogic solver "QF_UF" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-fun a () Bool)" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-fun b () Bool)"@@ -96,18 +100,18 @@ showSL r @?= "((or (! a :named aa) (! b :named bb)))" SMTLIB2.push solver 1 assertSuccess =<< SMTLIB2.runCommandString solver "(assert (not (and a bb)))"- r <- SMTLIB2.runCommandString solver "(get-assertions)"- showSL r @?= "((or (! a :named aa) (! b :named bb)) (not (and a bb)))"+ r2 <- SMTLIB2.runCommandString solver "(get-assertions)"+ showSL r2 @?= "((or (! a :named aa) (! b :named bb)) (not (and a bb)))" SMTLIB2.pop solver 1- r <- SMTLIB2.runCommandString solver "(get-assertions)"- showSL r @?= "((or (! a :named aa) (! b :named bb)))"+ r3 <- SMTLIB2.runCommandString solver "(get-assertions)"+ showSL r3 @?= "((or (! a :named aa) (! b :named bb)))" case_getAssignment :: Assertion case_getAssignment = do solver <- SMTLIB2.newSolver- SMTLIB2.setOption solver (ProduceAssignments True)+ SMTLIB2.setOption solver (ProduceAssignments True ()) o <- SMTLIB2.getOption solver ":produce-assignments"- o @?= AttrValueSymbol "true"+ o @?= AVSymbol "true" () SMTLIB2.setLogic solver "QF_UFLRA" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-fun a () Bool)" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-fun b () Bool)"@@ -115,36 +119,63 @@ assertSuccess =<< SMTLIB2.runCommandString solver "(assert (or (! a :named aa) (! b :named bb)))" assertSuccess =<< SMTLIB2.runCommandString solver "(assert (>= (! c :named cc) 0))" assertSuccess =<< SMTLIB2.runCommandString solver "(assert (not (and a bb)))"- SMTLIB2.checkSat solver+ _ <- SMTLIB2.checkSat solver r <- SMTLIB2.getAssignment solver- let m = Map.fromList [(s, b) | TValuationPair s b <- r]+ let m = Map.fromList r unless (m == Map.fromList [("aa",True), ("bb",False)] || m == Map.fromList [("aa",False), ("bb",True)]) $ do assertFailure (show r) case_getModel :: Assertion case_getModel = do solver <- SMTLIB2.newSolver- SMTLIB2.setOption solver (ProduceModels True)+ SMTLIB2.setOption solver (ProduceModels True ()) o <- SMTLIB2.getOption solver ":produce-models"- o @?= AttrValueSymbol "true"+ o @?= AVSymbol "true" () SMTLIB2.setLogic solver "QF_UF" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-fun a () Bool)" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-fun b () Bool)" assertSuccess =<< SMTLIB2.runCommandString solver "(assert (or a b))" assertSuccess =<< SMTLIB2.runCommandString solver "(assert (not (and a b)))"- SMTLIB2.checkSat solver+ _ <- SMTLIB2.checkSat solver r <- SMTLIB2.getModel solver let m = sort $ map showSL r unless (m == ["(define-fun a () Bool true)", "(define-fun b () Bool false)"] || m == ["(define-fun a () Bool false)", "(define-fun b () Bool true)"]) $ do assertFailure (show r) +case_getModel_division_by_zero :: Assertion+case_getModel_division_by_zero = do+ solver <- SMTLIB2.newSolver+ SMTLIB2.setOption solver (ProduceModels True ())+ SMTLIB2.setLogic solver "QF_LRA"++ assertSuccess =<< SMTLIB2.runCommandString solver "(declare-fun x1 () Real)"+ assertSuccess =<< SMTLIB2.runCommandString solver "(declare-fun x2 () Real)"+ status1 <- SMTLIB2.checkSat solver+ status1 @?= Sat+ RGetModel model1 <- SMTLIB2.runCommandString solver "(get-model)"+ assertBool ("/0 should not be in the model: " ++ showSL (RGetModel model1))+ (null [() | MRDefineFun (FunctionDef "/0" _ _ _ _) <- model1])++ assertSuccess =<< SMTLIB2.runCommandString solver "(define-fun y1 () Real (/ x1 0))"+ assertSuccess =<< SMTLIB2.runCommandString solver "(define-fun y2 () Real (/ x2 0))"+ assertSuccess =<< SMTLIB2.runCommandString solver "(assert (not (= y1 y2)))"+ status2 <- SMTLIB2.checkSat solver+ status2 @?= Sat+ RGetModel model2 <- SMTLIB2.runCommandString solver "(get-model)"+ assertBool ("/0 should be in the model: " ++ showSL (RGetModel model2))+ (not (null [() | MRDefineFun (FunctionDef "/0" _ _ _ _) <- model2]))++ assertSuccess =<< SMTLIB2.runCommandString solver "(assert (= x1 x2))"+ status3 <- SMTLIB2.checkSat solver+ status3 @?= Unsat+ case_getValue :: Assertion case_getValue = do solver <- SMTLIB2.newSolver- SMTLIB2.setOption solver (ProduceModels True)+ SMTLIB2.setOption solver (ProduceModels True ()) o <- SMTLIB2.getOption solver ":produce-models"- o @?= AttrValueSymbol "true"+ o @?= AVSymbol "true" () SMTLIB2.setLogic solver "QF_UF" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-sort U 0)" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-fun f (U) U)"@@ -152,19 +183,19 @@ assertSuccess =<< SMTLIB2.runCommandString solver "(declare-fun A () Bool)" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-fun x () U)" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-fun y () U)"- SMTLIB2.checkSat solver+ _ <- SMTLIB2.checkSat solver r <- SMTLIB2.runCommandString solver "(get-value (x A (f x) (g y)))" case r of- CmdGetValueResponse xs -> return () -- fixme+ RGetValue _xs -> return () -- fixme _ -> assertFailure (show r) case_GlobalDeclarations :: Assertion case_GlobalDeclarations = do solver <- SMTLIB2.newSolver - SMTLIB2.setOption solver (GlobalDeclarations False)+ SMTLIB2.setOption solver (GlobalDeclarations False ()) o <- SMTLIB2.getOption solver ":global-declarations"- o @?= AttrValueSymbol "false"+ o @?= AVSymbol "false" () SMTLIB2.setLogic solver "QF_UFLRA" SMTLIB2.push solver 1 assertSuccess =<< SMTLIB2.runCommandString solver "(declare-const x1 Bool)"@@ -173,15 +204,15 @@ SMTLIB2.reset solver - SMTLIB2.setOption solver (GlobalDeclarations True)- o <- SMTLIB2.getOption solver ":global-declarations"- o @?= AttrValueSymbol "true"+ SMTLIB2.setOption solver (GlobalDeclarations True ())+ o2 <- SMTLIB2.getOption solver ":global-declarations"+ o2 @?= AVSymbol "true" () SMTLIB2.setLogic solver "QF_UFLRA" SMTLIB2.push solver 1 assertSuccess =<< SMTLIB2.runCommandString solver "(define-fun x2 () Real 1.0)" SMTLIB2.pop solver 1 assertSuccess =<< SMTLIB2.runCommandString solver "(assert (= x2 1.0))"- SMTLIB2.checkSat solver+ _ <- SMTLIB2.checkSat solver return () @@ -215,8 +246,8 @@ SMTLIB2.reset solver - r <- SMTLIB2.checkSat solver- r @?= Sat+ r2 <- SMTLIB2.checkSat solver+ r2 @?= Sat case_resetAssertions :: Assertion case_resetAssertions = do@@ -239,8 +270,8 @@ SMTLIB2.resetAssertions solver - r <- SMTLIB2.checkSat solver- r @?= Sat+ r2 <- SMTLIB2.checkSat solver+ r2 @?= Sat -- http://sun.iwu.edu/~mliffito/publications/jar_liffiton_CAMUS.pdf -- φ= (x1) ∧ (¬x1) ∧ (¬x1∨x2) ∧ (¬x2) ∧ (¬x1∨x3) ∧ (¬x3)@@ -250,9 +281,9 @@ case_getUnsatCore = do solver <- SMTLIB2.newSolver - SMTLIB2.setOption solver (ProduceUnsatCores True)+ SMTLIB2.setOption solver (ProduceUnsatCores True ()) o <- SMTLIB2.getOption solver ":produce-unsat-cores"- o @?= AttrValueSymbol "true"+ o @?= AVSymbol "true" () SMTLIB2.setLogic solver "QF_UF" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-fun x1 () Bool)"@@ -266,9 +297,9 @@ assertSuccess =<< SMTLIB2.runCommandString solver "(assert (! (not x3) :named C6))" r <- SMTLIB2.checkSat solver r @?= Unsat- r <- SMTLIB2.getUnsatCore solver+ r2 <- SMTLIB2.getUnsatCore solver let expected = map Set.fromList [["C1", "C2"], ["C1", "C3", "C4"], ["C1", "C5", "C6"]]- Set.fromList r `elem` expected @?= True+ Set.fromList r2 `elem` expected @?= True case_echo :: Assertion case_echo = do@@ -305,7 +336,7 @@ case_defineFun :: Assertion case_defineFun = do solver <- SMTLIB2.newSolver- SMTLIB2.setOption solver (ProduceModels True)+ SMTLIB2.setOption solver (ProduceModels True ()) SMTLIB2.setLogic solver "QF_UFLRA" assertSuccess =<< SMTLIB2.runCommandString solver "(define-fun f ((b Bool) (x Real)) Bool (ite b (>= x 0) (>= 0 x)))" assertSuccess =<< SMTLIB2.runCommandString solver "(declare-const bb Bool)"@@ -314,16 +345,16 @@ assertSuccess =<< SMTLIB2.runCommandString solver "(assert (f bb xx))" r <- SMTLIB2.checkSat solver r @?= Sat- r <- SMTLIB2.runCommandString solver "(get-value (bb))"- showSL r @?= "((bb true))"+ r2 <- SMTLIB2.runCommandString solver "(get-value (bb))"+ showSL r2 @?= "((bb true))" case_getInfo :: Assertion case_getInfo = do solver <- SMTLIB2.newSolver- _ <- SMTLIB2.getInfo solver ErrorBehavior- _ <- SMTLIB2.getInfo solver Name- _ <- SMTLIB2.getInfo solver Authors- _ <- SMTLIB2.getInfo solver Version+ _ <- SMTLIB2.getInfo solver (ErrorBehaviorFlag ())+ _ <- SMTLIB2.getInfo solver (InfoName ())+ _ <- SMTLIB2.getInfo solver (Authors ())+ _ <- SMTLIB2.getInfo solver (InfoVersion ()) return () case_setInfo :: Assertion@@ -336,10 +367,11 @@ -- --------------------------------------------------------------------- -assertSuccess :: CmdResponse -> Assertion-assertSuccess (CmdGenResponse SMTLIB2.Success) = return ()-assertSuccess (CmdGenResponse Unsupported) = assertFailure "unsupported"-assertSuccess (CmdGenResponse (Error str)) = assertFailure ("(error " ++ str ++ ")")+assertSuccess :: CommandResponse () -> Assertion+assertSuccess RSuccess = return ()+assertSuccess RUnsupported = assertFailure "unsupported"+assertSuccess (RError str) = assertFailure ("(error " ++ T.unpack str ++ ")")+assertSuccess r = assertFailure (showSL r) -- --------------------------------------------------------------------- -- Test harness
test/Test/Simplex.hs view
@@ -3,7 +3,6 @@ import Control.Monad import Data.Default.Class-import Data.List import Data.Ratio import Data.VectorSpace import Test.Tasty
test/Test/SimplexTextbook.hs view
@@ -7,7 +7,6 @@ import qualified Data.IntMap as IntMap import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet-import Data.List import Data.Ratio import Test.Tasty import Test.Tasty.HUnit
− test/Test/Smtlib.hs
@@ -1,604 +0,0 @@-{-# OPTIONS_GHC -Wall -fno-warn-orphans #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-module Test.Smtlib (smtlibTestGroup) where--import Control.DeepSeq-import Control.Monad-import qualified Data.Set as Set--import Test.Tasty-import Test.Tasty.QuickCheck hiding (Success)-import Test.Tasty.HUnit-import Test.Tasty.TH--import Smtlib.Syntax.Syntax-import Smtlib.Syntax.ShowSL-import Smtlib.Parsers.CommonParsers-import Smtlib.Parsers.CommandsParsers-import Smtlib.Parsers.ResponseParsers-import Text.Parsec (parse)---prop_parseTerm :: Property-prop_parseTerm = forAll arbitrary $ \(t :: Term) ->- parse parseTerm "" (showSL t) == Right t--prop_parseAttribute :: Property-prop_parseAttribute = forAll arbitrary $ \a ->- parse parseAttribute "" (showSL a) == Right a--prop_parseSort :: Property-prop_parseSort = forAll arbitrary $ \s ->- parse parseSort "" (showSL s) == Right s--prop_parseIdentifier :: Property-prop_parseIdentifier = forAll arbitrary $ \a ->- parse parseIdentifier "" (showSL a) == Right a--prop_parseSexpr :: Property-prop_parseSexpr = forAll arbitrary $ \a ->- parse parseSexpr "" (showSL a) == Right a--prop_parseSpecConstant :: Property-prop_parseSpecConstant = forAll arbitrary $ \a ->- parse parseSpecConstant "" (showSL a) == Right a--prop_parseSource :: Property-prop_parseSource = forAll arbitrary $ \a ->- parse parseSource "" (joinA a) == Right a--prop_parseCommand :: Property-prop_parseCommand = forAll arbitrary $ \a ->- parse parseCommand "" (showSL a) == Right a--prop_parseOption :: Property-prop_parseOption = forAll arbitrary $ \a ->- parse parseOption "" (showSL a) == Right a--prop_parseInfoFlags :: Property-prop_parseInfoFlags = forAll arbitrary $ \a ->- parse parseOption "" (showSL a) == Right a--prop_parseCmdResult :: Property-prop_parseCmdResult = forAll arbitrary $ \(a :: CmdResponse) ->- case parse parseCmdResult "" (showSL a) of- Left err -> error (show err)- Right a' -> parse parseCmdResult "" (showSL a') == Right a'--prop_parseGenResponse :: Property-prop_parseGenResponse = forAll arbitrary $ \a ->- parse parseGenResponse "" (showSL a) == Right a--prop_parseGetInfoResponse :: Property-prop_parseGetInfoResponse = forAll arbitrary $ \a ->- parse parseGetInfoResponse "" ("(" ++ joinA a ++ ")") == Right a--prop_parseCheckSatResponse :: Property-prop_parseCheckSatResponse = forAll arbitrary $ \a ->- parse parseCheckSatResponse "" (showSL a) == Right a--prop_parseGetAssertionsResponse :: Property-prop_parseGetAssertionsResponse = forAll genGetAssertionsResponse $ \a ->- parse parseGetAssertionsResponse "" ("(" ++ joinA a ++ ")") == Right a--prop_parseGetAssignmentResp :: Property-prop_parseGetAssignmentResp = forAll arbitrary $ \a ->- parse parseGetAssignmentResp "" ("(" ++ joinA a ++ ")") == Right a--prop_parseGetProofResponse :: Property-prop_parseGetProofResponse = forAll arbitrary $ \a ->- parse parseGetProofResponse "" (showSL a) == Right a--prop_parseGetUnsatCoreResp :: Property-prop_parseGetUnsatCoreResp = forAll genGetUnsatCoreResponse $ \a ->- parse parseGetUnsatCoreResp "" ("(" ++ unwords (fmap showSymbol a) ++ ")") == Right a--prop_parseGetUnsatAssumptionsResp :: Property-prop_parseGetUnsatAssumptionsResp = forAll (listOf' genSymbol) $ \a ->- parse parseGetUnsatCoreResp "" ("(" ++ unwords (fmap showSymbol a) ++ ")") == Right a--prop_parseGetValueResponse :: Property-prop_parseGetValueResponse = forAll genGetValueResponse $ \a ->- parse parseGetValueResponse "" ("(" ++ joinA a ++ ")") == Right a--prop_parseGetModelResponse :: Property-prop_parseGetModelResponse = forAll genGetModelResponse $ \a ->- parse parseGetModelResponse "" ("(" ++ joinA a ++ ")") == Right a--prop_parseGetOptionResponse :: Property-prop_parseGetOptionResponse = forAll arbitrary $ \a ->- parse parseGetOptionResponse "" (showSL a) == Right a--prop_parseEchoResponse :: Property-prop_parseEchoResponse = forAll genEchoResponse $ \a ->- parse parseEchoResponse "" a == Right a--case_bug_1 :: Assertion-case_bug_1 = do- parse parseSort "" "(_a b)" @?= Right (SortIdentifiers (ISymbol "_a") [SortId (ISymbol "b")])- parse parseTerm "" "(_a b)" @?= Right (TermQualIdentifierT (QIdentifier (ISymbol "_a")) [TermQualIdentifier (QIdentifier (ISymbol "b"))])--case_bug_2 :: Assertion-case_bug_2 = do- parse parseTerm "" "(asX b)" @?= Right (TermQualIdentifierT (QIdentifier (ISymbol "asX")) [TermQualIdentifier (QIdentifier (ISymbol "b"))])--case_parse_string_literal_ascii :: Assertion-case_parse_string_literal_ascii = parse str "" s @?= Right s- where- s = showStringLiteral $ ['\t','\n','\r'] ++ [toEnum 32 .. toEnum 126]--prop_parse_string_literal :: Property-prop_parse_string_literal =- forAll genStringLiteral $ \s ->- parse str "" s == Right s--case_parseSexprKeyword_bug :: Assertion-case_parseSexprKeyword_bug =- parse parseSexprKeyword "" ":keyword" @?= Right (SexprKeyword ":keyword")--case_parseHexadecimal :: Assertion-case_parseHexadecimal = parse parseHexadecimal "" (showSL s) @?= Right s- where- s = SpecConstantHexadecimal "afbf00"--case_parseBinary :: Assertion-case_parseBinary = parse parseBinary "" (showSL s) @?= Right s- where- s = SpecConstantBinary "011001"--case_comment :: Assertion-case_comment = do- parse parseTerm "" "(f ; hogehoge\na;bbb\n)" @?=- Right (TermQualIdentifierT (QIdentifier (ISymbol "f")) [TermQualIdentifier (QIdentifier (ISymbol "a"))])---- -----------------------------------------------------------------------prop_Command_show :: Property-prop_Command_show = forAll arbitrary $ \(a :: Command) ->- show a `deepseq` True--prop_Option_show :: Property-prop_Option_show = forAll arbitrary $ \(a :: Option) ->- show a `deepseq` True--prop_InfoFlags_show :: Property-prop_InfoFlags_show = forAll arbitrary $ \(a :: InfoFlags) ->- show a `deepseq` True--prop_Term_show :: Property-prop_Term_show = forAll arbitrary $ \(a :: Term) ->- show a `deepseq` True--prop_VarBinding_show :: Property-prop_VarBinding_show = forAll arbitrary $ \(a :: VarBinding) ->- show a `deepseq` True--prop_SortedVar_show :: Property-prop_SortedVar_show = forAll arbitrary $ \(a :: VarBinding) ->- show a `deepseq` True--prop_QualIdentifier_show :: Property-prop_QualIdentifier_show = forAll arbitrary $ \(a :: QualIdentifier) ->- show a `deepseq` True--prop_FunDec_show :: Property-prop_FunDec_show = forAll arbitrary $ \(a :: FunDec) ->- show a `deepseq` True--prop_AttrValue_show :: Property-prop_AttrValue_show = forAll arbitrary $ \(a :: AttrValue) ->- show a `deepseq` True--prop_Attribute_show :: Property-prop_Attribute_show = forAll arbitrary $ \(a :: Attribute) ->- show a `deepseq` True--prop_Index_show :: Property-prop_Index_show = forAll arbitrary $ \(a :: Index) ->- show a `deepseq` True--prop_Identifier_show :: Property-prop_Identifier_show = forAll arbitrary $ \(a :: Identifier) ->- show a `deepseq` True--prop_Sort_show :: Property-prop_Sort_show = forAll arbitrary $ \(a :: Sort) ->- show a `deepseq` True--prop_SpecConstant_show :: Property-prop_SpecConstant_show = forAll arbitrary $ \(a :: SpecConstant) ->- show a `deepseq` True--prop_Sexpr_show :: Property-prop_Sexpr_show = forAll arbitrary $ \(a :: Sexpr) ->- show a `deepseq` True--prop_CmdResponse_show :: Property-prop_CmdResponse_show = forAll arbitrary $ \(a :: CmdResponse) ->- show a `deepseq` True--prop_GenResponse_show :: Property-prop_GenResponse_show = forAll arbitrary $ \(a :: GenResponse) ->- show a `deepseq` True--prop_ErrorBehavior_show :: Property-prop_ErrorBehavior_show = forAll arbitrary $ \(a :: ErrorBehavior) ->- show a `deepseq` True--prop_ReasonUnknown_show :: Property-prop_ReasonUnknown_show = forAll arbitrary $ \(a :: ReasonUnknown) ->- show a `deepseq` True--prop_CheckSatResponse_show :: Property-prop_CheckSatResponse_show = forAll arbitrary $ \(a :: CheckSatResponse) ->- show a `deepseq` True--prop_InfoResponse_show :: Property-prop_InfoResponse_show = forAll arbitrary $ \(a :: InfoResponse) ->- show a `deepseq` True--prop_ValuationPair_show :: Property-prop_ValuationPair_show = forAll arbitrary $ \(a :: ValuationPair) ->- show a `deepseq` True--prop_TValuationPair_show :: Property-prop_TValuationPair_show = forAll arbitrary $ \(a :: TValuationPair) ->- show a `deepseq` True---- -----------------------------------------------------------------------instance Arbitrary Term where- arbitrary = sized $ \n -> oneof $- [ TermSpecConstant <$> arbitrary- , TermQualIdentifier <$> arbitrary- ] ++ (if n > 0 then gs else [])- where- gs =- [ liftM2 TermQualIdentifierT arbitrary (listOf1' arbitrary')- , liftM2 TermLet (listOf1' arbitrary) arbitrary'- , liftM2 TermForall (listOf1' arbitrary) arbitrary'- , liftM2 TermExists (listOf1' arbitrary) arbitrary'- , liftM2 TermAnnot arbitrary' (listOf1' arbitrary)- ]--instance Arbitrary VarBinding where- arbitrary = liftM2 VB genSymbol arbitrary'--instance Arbitrary SortedVar where- arbitrary = liftM2 SV genSymbol arbitrary--instance Arbitrary AttrValue where- arbitrary = oneof- [ AttrValueConstant <$> arbitrary- , AttrValueSymbol <$> genSymbol- , AttrValueSexpr <$> listOf' arbitrary- ]--instance Arbitrary Attribute where- arbitrary = oneof- [ Attribute <$> genKeyword- , liftM2 AttributeVal genKeyword arbitrary- ]--instance Arbitrary QualIdentifier where- arbitrary = oneof- [ QIdentifier <$> arbitrary- , liftM2 QIdentifierAs arbitrary arbitrary- ]--instance Arbitrary Index where- arbitrary = oneof- [ IndexNumeral <$> abs <$> arbitrary- , IndexSymbol <$> genSymbol- ]--instance Arbitrary Identifier where- arbitrary = oneof- [ ISymbol <$> genSymbol- , liftM2 I_Symbol genSymbol (listOf1' arbitrary)- ]--instance Arbitrary Sort where- arbitrary = oneof- [ SortId <$> arbitrary- , liftM2 SortIdentifiers arbitrary (listOf1' arbitrary')- ]--instance Arbitrary SpecConstant where- arbitrary = oneof- [ SpecConstantNumeral <$> abs <$> arbitrary- , liftM SpecConstantDecimal $ do- a <- show <$> abs <$> (arbitrary :: Gen Int)- b <- listOf $ return '0'- c <- show <$> abs <$> (arbitrary :: Gen Int)- return $ a ++ "." ++ b ++ c- , SpecConstantHexadecimal <$> listOf1 (elements (['0'..'9'] ++ ['a'..'f'] ++ ['A'..'F']))- , SpecConstantBinary <$> listOf1 (elements ['0','1'])- , liftM SpecConstantString $ do- let p c = c `elem` ['\t','\n','\r'] || (32 <= fromEnum c && fromEnum c <= 126) || 128 <= fromEnum c- s <- listOf $ arbitrary `suchThat` p- return $ "\"" ++ concat [if c == '"' then "\"\"" else [c] | c <- s] ++ "\""- ]--instance Arbitrary Sexpr where- arbitrary = sized $ \n -> oneof $- [ SexprSpecConstant <$> arbitrary- , SexprSymbol <$> genSymbol- , SexprKeyword <$> genKeyword- ] ++- [ liftM SexprSxp $ listOf' arbitrary' | n > 0 ]--halve :: Gen a -> Gen a-halve g = sized (\n -> resize (n `div` 2) g)--arbitrary' :: Arbitrary a => Gen a-arbitrary' = halve arbitrary--listOf' :: Gen a -> Gen [a]-listOf' g = do- n <- frequency [(6, return 0), (3, return 1), (1, return 2)]- replicateM n g--listOf1' :: Gen a -> Gen [a]-listOf1' g = do- n <- frequency [(10, return 1), (4, return 2), (1, return 3)]- replicateM n g---- -----------------------------------------------------------------------type Symbol = String--genSymbol :: Gen Symbol-genSymbol = oneof [genSimpleSymbol, genQuotedSymbol]--genSimpleSymbol :: Gen Symbol-genSimpleSymbol = g `suchThat` (`Set.notMember` reserved)- where- xs = ['a'..'z']++['A'..'Z']++"~!@$%^&*_-+=<>.?/"- g = liftM2 (:) (elements xs) (listOf1 $ elements $ ['0'..'9'] ++ xs)- reserved = Set.fromList $- ["BINARY", "DECIMAL", "HEXADECIMAL", "NUMERAL", "STRING", "_", "!", "as", "let", "exists", "forall", "par"] ++- ["set-logic", "set-option", "set-info", "declare-sort", "define-sort", "declare-const", "declare-fun", "declare-fun-rec", "declare-funs-rec", "push", "pop", "reset", "reset-assertions", "assert", "check-sat", "check-sat-assuming", "get-assertions", "get-model", "get-proof", "get-unsat-core", "get-unsat-assumptions", "get-value", "get-assignment", "get-option", "get-info", "echo", "exit"]--genQuotedSymbol :: Gen Symbol-genQuotedSymbol = listOf1 g- where- g :: Gen Char- g = oneof [elements (Set.toList xs), choose (toEnum 128, maxBound)]- xs = Set.fromList (['\t','\n','\r'] ++ [' ' .. toEnum 126]) `Set.difference` Set.fromList ['\\', '|']--genKeyword :: Gen String-genKeyword = oneof- [ (':':) <$> genSimpleSymbol- , elements- [ ":print-success"- , ":expand-definitions"- , ":interactive-mode"- , ":produce-proofs"- , ":produce-unsat-cores"- , ":produce-unsat-assumptions"- , ":produce-models"- , ":produce-assignments"- , ":produce-assertions"- , ":global-declarations"- , ":regular-output-channel"- , ":diagnostic-output-channel"- , ":random-seed"- , ":verbosity"- , ":reproducible-resource-limit"-- , ":error-behavior"- , ":name"- , ":authors"- , ":version"- , ":status"- , ":reason-unknown"- , ":all-statistics"- , ":assertion-stack-levels"- ]- ]--genStringLiteral :: Gen String-genStringLiteral = showStringLiteral <$> listOf genStringChar--showStringLiteral :: String -> String-showStringLiteral s = "\"" ++ concat [if c == '"' then "\"\"" else [c] | c <- s] ++ "\""--genStringChar :: Gen Char-genStringChar = arbitrary `suchThat` p- where- p c = c `elem` ['\t','\n','\r'] || (32 <= fromEnum c && fromEnum c <= 126) || 128 <= fromEnum c---- -----------------------------------------------------------------------instance Arbitrary Command where- arbitrary = oneof- [ SetLogic <$> genSymbol- , SetOption <$> arbitrary- , SetInfo <$> arbitrary- , DeclareSort <$> genSymbol <*> (abs <$> arbitrary)- , DefineSort <$> genSymbol <*> listOf' genSymbol <*> arbitrary- , DeclareConst <$> genSymbol <*> arbitrary- , DeclareFun <$> genSymbol <*> listOf' arbitrary <*> arbitrary- , DefineFun <$> genSymbol <*> listOf' arbitrary <*> arbitrary <*> arbitrary- , DefineFunRec <$> genSymbol <*> listOf' arbitrary <*> arbitrary <*> arbitrary- , DefineFunsRec <$> listOf1' arbitrary <*> listOf1' arbitrary- , Push <$> (abs <$> arbitrary)- , Pop <$> (abs <$> arbitrary)- , return Reset- , return ResetAssertions- , Assert <$> arbitrary- , return CheckSat- , CheckSatAssuming <$> listOf' arbitrary- , return GetAssertions- , return GetModel- , return GetProof- , return GetUnsatCore- , return GetUnsatAssumptions- , GetValue <$> listOf1' arbitrary- , return GetAssignment- , GetOption <$> genKeyword- , GetInfo <$> arbitrary- , Echo <$> genStringLiteral- , return Exit- ]--instance Arbitrary Option where- arbitrary = oneof- [ PrintSuccess <$> arbitrary- , ExpandDefinitions <$> arbitrary- , InteractiveMode <$> arbitrary- , ProduceProofs <$> arbitrary- , ProduceUnsatCores <$> arbitrary- , ProduceUnsatAssumptions <$> arbitrary- , ProduceModels <$> arbitrary- , ProduceAssignments <$> arbitrary- , ProduceAssertions <$> arbitrary- , GlobalDeclarations <$> arbitrary- , RegularOutputChannel <$> genStringLiteral- , DiagnosticOutputChannel <$> genStringLiteral- , RandomSeed <$> (abs <$> arbitrary)- , Verbosity <$> abs <$> arbitrary- , ReproducibleResourceLimit <$> abs <$> arbitrary- , OptionAttr <$> (arbitrary `suchThat` p)- ]- where- p (Attribute kw) = kw `Set.notMember` reserved- p (AttributeVal kw _) = kw `Set.notMember` reserved- reserved = Set.fromList- [ ":print-success"- , ":expand-definitions"- , ":interactive-mode"- , ":produce-proofs"- , ":produce-unsat-cores"- , ":produce-unsat-assumptions"- , ":produce-models"- , ":produce-assignments"- , ":produce-assertions"- , ":global-declarations"- , ":regular-output-channel"- , ":diagnostic-output-channel"- , ":random-seed"- , ":verbosity"- , ":reproducible-resource-limit"- ]--instance Arbitrary InfoFlags where- arbitrary = oneof- [ return ErrorBehavior- , return Name- , return Authors- , return Version- , return Status- , return ReasonUnknown- , return AllStatistics- , return AssertionStackLevels- , InfoFlags <$> (genKeyword `suchThat` (`Set.notMember` reserved))- ]- where- reserved = Set.fromList- [ ":error-behavior"- , ":name"- , ":authors"- , ":version"- , ":status"- , ":reason-unknown"- , ":all-statistics"- , ":assertion-stack-levels"- ]--instance Arbitrary FunDec where- arbitrary = FunDec <$> genSymbol <*> listOf' arbitrary <*> arbitrary---- -----------------------------------------------------------------------instance Arbitrary CmdResponse where- arbitrary = oneof- [ CmdGenResponse <$> arbitrary- , CmdGetInfoResponse <$> genGetInfoResponse- , CmdCheckSatResponse <$> arbitrary- , CmdGetAssertionsResponse <$> genGetAssertionsResponse- , CmdGetAssignmentResponse <$> arbitrary- , CmdGetProofResponse <$> arbitrary- , CmdGetUnsatCoreResponse <$> genGetUnsatCoreResponse- , CmdGetUnsatAssumptionsResponse <$> arbitrary- , CmdGetValueResponse <$> genGetValueResponse- , CmdGetModelResponse <$> arbitrary- , CmdGetOptionResponse <$> arbitrary- , CmdEchoResponse <$> genEchoResponse- ]--instance Arbitrary GenResponse where- arbitrary = oneof- [ return Unsupported- , return Success- , Error <$> genStringLiteral- ]--instance Arbitrary ErrorBehavior where- arbitrary = elements [ImmediateExit, ContinuedExecution]--instance Arbitrary ReasonUnknown where- arbitrary = elements [Memout, Incomplete]--instance Arbitrary CheckSatResponse where- arbitrary = elements [Sat, Unsat, Unknown]--instance Arbitrary InfoResponse where- arbitrary = oneof- [ ResponseErrorBehavior <$> arbitrary- , ResponseName <$> genStringLiteral- , ResponseAuthors <$> genStringLiteral- , ResponseVersion <$> genStringLiteral- , ResponseReasonUnknown <$> arbitrary- , ResponseAssertionStackLevels <$> abs <$> arbitrary- , ResponseAttribute <$> (arbitrary `suchThat` p)- ]- where- p (Attribute kw) = kw `Set.notMember` reserved- p (AttributeVal kw _) = kw `Set.notMember` reserved- reserved = Set.fromList- [ ":error-behavior"- , ":name"- , ":authors"- , ":version"- , ":status"- , ":reason-unknown"- , ":all-statistics"- , ":assertion-stack-levels"- ]--genGetInfoResponse :: Gen [InfoResponse]-genGetInfoResponse = listOf' arbitrary--genGetAssertionsResponse :: Gen [Term]-genGetAssertionsResponse = listOf' arbitrary--genGetUnsatCoreResponse :: Gen [Symbol]-genGetUnsatCoreResponse = listOf' genSymbol--genGetValueResponse :: Gen [ValuationPair]-genGetValueResponse = listOf' arbitrary--genGetModelResponse :: Gen [Command]-genGetModelResponse = listOf1' $ oneof- [ DefineFun <$> genSymbol <*> listOf' arbitrary <*> arbitrary <*> arbitrary- , DefineFunRec <$> genSymbol <*> listOf' arbitrary <*> arbitrary <*> arbitrary- , DefineFunsRec <$> listOf1' arbitrary <*> listOf1' arbitrary- ]--genEchoResponse :: Gen String-genEchoResponse = genStringLiteral--instance Arbitrary ValuationPair where- arbitrary = ValuationPair <$> arbitrary <*> arbitrary--instance Arbitrary TValuationPair where- arbitrary = TValuationPair <$> genSymbol <*> arbitrary---- ------------------------------------------------------------------------ Test harness--smtlibTestGroup :: TestTree-smtlibTestGroup = $(testGroupGenerator)
+ test/Test/SolutionChecker.hs view
@@ -0,0 +1,576 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+module Test.SolutionChecker (solutionCheckerTestGroup) where++import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.TH++import Control.DeepSeq+import Control.Exception (evaluate)+import Control.Monad+import Data.Array.IArray+import Data.Default.Class+import qualified Data.Map.Lazy as Map+import qualified Data.PseudoBoolean as PBFile+import Data.Scientific (Scientific)+import qualified Numeric.Optimization.MIP as MIP++import qualified ToySolver.FileFormat.CNF as CNF+import ToySolver.Internal.SolutionChecker++-- ----------------------------------------------------------------------++checkOkAndEmpty :: HasCallStack => (Bool, [String]) -> Assertion+checkOkAndEmpty (ok, messages) = do+ _ <- evaluate $ force messages+ ok @?= True+ assertBool "messages should be empty" (null messages)++check :: HasCallStack => Bool -> (Bool, [String]) -> Assertion+check expected (ok, messages) = do+ _ <- evaluate $ force messages+ ok @?= expected+ unless ok $ assertBool "messages should not be empty" (not (null messages))++-- ----------------------------------------------------------------------++case_checkSATResult_SATISFIABLE :: Assertion+case_checkSATResult_SATISFIABLE = do+ checkOkAndEmpty $ checkSATResult cnf ("SATISFIABLE", Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkSATResult cnf ("SATISFIABLE", Just $ array (1, 2) [(1, False), (2, True)])+ check False $ checkSATResult cnf ("SATISFIABLE", Nothing)+ where+ cnf = CNF.CNF+ { CNF.cnfNumVars = 2+ , CNF.cnfNumClauses = 3+ , CNF.cnfClauses =+ [ [1, 2]+ , [1, -2]+ , [-1, -2]+ ]+ }++case_checkSATResult_UNSATISFIABLE :: Assertion+case_checkSATResult_UNSATISFIABLE = do+ checkOkAndEmpty $ checkSATResult cnf ("UNSATISFIABLE", Nothing)+ check False $ checkSATResult cnf ("UNSATISFIABLE", Just $ array (1, 2) [(1, True), (2, True)])+ where+ cnf = CNF.CNF+ { CNF.cnfNumVars = 2+ , CNF.cnfNumClauses = 3+ , CNF.cnfClauses =+ [ [1, 2]+ , [1, -2]+ , [-1, 2]+ , [-1, -2]+ ]+ }++case_checkSATResult_UNKNOWN :: Assertion+case_checkSATResult_UNKNOWN = do+ checkOkAndEmpty $ checkSATResult cnf ("UNKNOWN", Just $ array (1, 2) [(1, True), (2, False)])+ checkOkAndEmpty $ checkSATResult cnf ("UNKNOWN", Nothing)+ check False $ checkSATResult cnf ("UNKNOWN", Just $ array (1, 2) [(1, True), (2, True)])+ where+ cnf = CNF.CNF+ { CNF.cnfNumVars = 2+ , CNF.cnfNumClauses = 3+ , CNF.cnfClauses =+ [ [1, 2]+ , [1, -2]+ , [-1, -2]+ ]+ }++case_checkSATResult_bad_solution_status :: Assertion+case_checkSATResult_bad_solution_status =+ check False $ checkSATResult cnf ("FOO BAR", Just $ array (1, 2) [(1, True), (2, True)])+ where+ cnf = CNF.CNF+ { CNF.cnfNumVars = 2+ , CNF.cnfNumClauses = 3+ , CNF.cnfClauses =+ [ [1, 2]+ , [1, -2]+ , [-1, 2]+ ]+ }++-- ----------------------------------------------------------------------++case_checkMaxSATResult_SATISFIABLE :: Assertion+case_checkMaxSATResult_SATISFIABLE = do+ check True $ checkMaxSATResult wcnf ("SATISFIABLE", Just 1, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkMaxSATResult wcnf ("SATISFIABLE", Just 0, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkMaxSATResult wcnf ("SATISFIABLE", Just 0, Just $ array (1, 2) [(1, False), (2, False)])+ check False $ checkMaxSATResult wcnf ("SATISFIABLE", Nothing, Nothing)+ where+ wcnf = CNF.WCNF+ { CNF.wcnfNumVars = 2+ , CNF.wcnfNumClauses = 3+ , CNF.wcnfTopCost = 100+ , CNF.wcnfClauses =+ [ (100, [1, 2])+ , (2, [1, -2])+ , (1, [-1, 2])+ , (3, [-1, -2])+ ]+ }++case_checkMaxSATResult_OPTIMUM_FOUND :: Assertion+case_checkMaxSATResult_OPTIMUM_FOUND = do+ check True $ checkMaxSATResult wcnf ("OPTIMUM FOUND", Just 1, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkMaxSATResult wcnf ("OPTIMUM FOUND", Just 0, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkMaxSATResult wcnf ("OPTIMUM FOUND", Just 0, Just $ array (1, 2) [(1, False), (2, False)])+ check False $ checkMaxSATResult wcnf ("OPTIMUM FOUND", Nothing, Nothing)+ where+ wcnf = CNF.WCNF+ { CNF.wcnfNumVars = 2+ , CNF.wcnfNumClauses = 3+ , CNF.wcnfTopCost = 100+ , CNF.wcnfClauses =+ [ (100, [1, 2])+ , (2, [1, -2])+ , (1, [-1, 2])+ , (3, [-1, -2])+ ]+ }++case_checkMaxSATResult_UNSATISFIABLE :: Assertion+case_checkMaxSATResult_UNSATISFIABLE = do+ check True $ checkMaxSATResult wcnf ("UNSATISFIABLE", Nothing, Nothing)+ check False $ checkMaxSATResult wcnf ("UNSATISFIABLE", Just 3, Just $ array (1, 2) [(1, True), (2, True)])+ where+ wcnf = CNF.WCNF+ { CNF.wcnfNumVars = 2+ , CNF.wcnfNumClauses = 3+ , CNF.wcnfTopCost = 100+ , CNF.wcnfClauses =+ [ (100, [1, 2])+ , (2, [1, -2])+ , (1, [-1, 2])+ , (3, [-1, -2])+ ]+ }++case_checkMaxSATResult_UNKNOWN :: Assertion+case_checkMaxSATResult_UNKNOWN = do+ check True $ checkMaxSATResult wcnf ("UNKNOWN", Just 1, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkMaxSATResult wcnf ("UNKNOWN", Just 0, Just $ array (1, 2) [(1, True), (2, False)])+ check True $ checkMaxSATResult wcnf ("UNKNOWN", Nothing, Nothing)+ where+ wcnf = CNF.WCNF+ { CNF.wcnfNumVars = 2+ , CNF.wcnfNumClauses = 3+ , CNF.wcnfTopCost = 100+ , CNF.wcnfClauses =+ [ (100, [1, 2])+ , (2, [1, -2])+ , (1, [-1, 2])+ , (3, [-1, -2])+ ]+ }++case_checkMaxSATResult_bad_solution_status :: Assertion+case_checkMaxSATResult_bad_solution_status =+ check False $ checkMaxSATResult wcnf ("FOO BAR", Just 0, Just $ array (1, 2) [(1, True), (2, True)])+ where+ wcnf = CNF.WCNF+ { CNF.wcnfNumVars = 2+ , CNF.wcnfNumClauses = 3+ , CNF.wcnfTopCost = 100+ , CNF.wcnfClauses =+ [ (100, [1, 2])+ , (2, [1, -2])+ , (1, [-1, 2])+ , (3, [-1, -2])+ ]+ }++-- ----------------------------------------------------------------------++case_checkPBResult_SATISFIABLE :: Assertion+case_checkPBResult_SATISFIABLE = do+ check True $ checkPBResult opb ("SATISFIABLE", Just 1, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkPBResult opb ("SATISFIABLE", Just 0, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkPBResult opb ("SATISFIABLE", Just 2, Just $ array (1, 2) [(1, False), (2, True)])+ check False $ checkPBResult opb ("SATISFIABLE", Nothing, Nothing)+ where+ (x1,x2) = (1,2)+ opb = PBFile.Formula+ { PBFile.pbNumVars = 2+ , PBFile.pbNumConstraints = 3+ , PBFile.pbObjectiveFunction = Just [(1, [x1]), (2, [x2])]+ , PBFile.pbConstraints =+ [ ([(1, [ x1]), (1, [ x2])], PBFile.Ge, 1)+ , ([(1, [ x1]), (1, [-x2])], PBFile.Ge, 1)+ , ([(1, [-x1]), (1, [-x2])], PBFile.Ge, 1)+ ]+ }++case_checkPBResult_OPTIMUM_FOUND :: Assertion+case_checkPBResult_OPTIMUM_FOUND = do+ check True $ checkPBResult opb ("OPTIMUM FOUND", Just 1, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkPBResult opb ("OPTIMUM FOUND", Just 0, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkPBResult opb ("OPTIMUM FOUND", Just 2, Just $ array (1, 2) [(1, False), (2, True)])+ check False $ checkPBResult opb ("OPTIMUM FOUND", Nothing, Nothing)+ where+ (x1,x2) = (1,2)+ opb = PBFile.Formula+ { PBFile.pbNumVars = 2+ , PBFile.pbNumConstraints = 3+ , PBFile.pbObjectiveFunction = Just [(1, [x1]), (2, [x2])]+ , PBFile.pbConstraints =+ [ ([(1, [ x1]), (1, [ x2])], PBFile.Ge, 1)+ , ([(1, [ x1]), (1, [-x2])], PBFile.Ge, 1)+ , ([(1, [-x1]), (1, [-x2])], PBFile.Ge, 1)+ ]+ }++case_checkPBResult_UNSATISFIABLE :: Assertion+case_checkPBResult_UNSATISFIABLE = do+ check True $ checkPBResult opb ("UNSATISFIABLE", Nothing, Nothing)+ check False $ checkPBResult opb ("UNSATISFIABLE", Just 3, Just $ array (1, 2) [(1, True), (2, True)])+ where+ (x1,x2) = (1,2)+ opb = PBFile.Formula+ { PBFile.pbNumVars = 2+ , PBFile.pbNumConstraints = 3+ , PBFile.pbObjectiveFunction = Just [(1, [x1]), (2, [x2])]+ , PBFile.pbConstraints =+ [ ([(1, [ x1]), (1, [ x2])], PBFile.Ge, 1)+ , ([(1, [ x1]), (1, [-x2])], PBFile.Ge, 1)+ , ([(1, [-x1]), (1, [-x2])], PBFile.Ge, 1)+ ]+ }++case_checkPBResult_UNKNOWN :: Assertion+case_checkPBResult_UNKNOWN = do+ check True $ checkPBResult opb ("UNKNOWN", Just 1, Just $ array (1, 2) [(1, True), (2, False)])+ check True $ checkPBResult opb ("UNKNOWN", Nothing, Nothing)+ check False $ checkPBResult opb ("UNKNOWN", Just 3, Just $ array (1, 2) [(1, True), (2, True)])+ where+ (x1,x2) = (1,2)+ opb = PBFile.Formula+ { PBFile.pbNumVars = 2+ , PBFile.pbNumConstraints = 3+ , PBFile.pbObjectiveFunction = Just [(1, [x1]), (2, [x2])]+ , PBFile.pbConstraints =+ [ ([(1, [ x1]), (1, [ x2])], PBFile.Ge, 1)+ , ([(1, [ x1]), (1, [-x2])], PBFile.Ge, 1)+ , ([(1, [-x1]), (1, [-x2])], PBFile.Ge, 1)+ ]+ }++case_checkPBResult_UNSUPPORTED :: Assertion+case_checkPBResult_UNSUPPORTED = do+ check True $ checkPBResult opb ("UNSUPPORTED", Nothing, Nothing)+ where+ (x1,x2) = (1,2)+ opb = PBFile.Formula+ { PBFile.pbNumVars = 2+ , PBFile.pbNumConstraints = 3+ , PBFile.pbObjectiveFunction = Just [(1, [x1]), (2, [x2])]+ , PBFile.pbConstraints =+ [ ([(1, [ x1]), (1, [ x2])], PBFile.Ge, 1)+ , ([(1, [ x1]), (1, [-x2])], PBFile.Ge, 1)+ , ([(1, [-x1]), (1, [-x2])], PBFile.Ge, 1)+ ]+ }++case_checkPBResult_bad_solution_status :: Assertion+case_checkPBResult_bad_solution_status =+ check False $ checkPBResult opb ("FOO BAR", Just 3, Just $ array (1, 2) [(1, True), (2, True)])+ where+ (x1,x2) = (1,2)+ opb = PBFile.Formula+ { PBFile.pbNumVars = 2+ , PBFile.pbNumConstraints = 3+ , PBFile.pbObjectiveFunction = Just [(1, [x1]), (2, [x2])]+ , PBFile.pbConstraints =+ [ ([(1, [ x1]), (1, [ x2])], PBFile.Ge, 1)+ , ([(1, [ x1]), (1, [-x2])], PBFile.Ge, 1)+ , ([(1, [-x1]), (1, [-x2])], PBFile.Ge, 1)+ ]+ }++-- ----------------------------------------------------------------------++case_checkWBOResult_SATISFIABLE :: Assertion+case_checkWBOResult_SATISFIABLE = do+ check True $ checkWBOResult wbo ("SATISFIABLE", Just 1, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkWBOResult wbo ("SATISFIABLE", Just 0, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkWBOResult wbo ("SATISFIABLE", Just 0, Just $ array (1, 2) [(1, False), (2, False)])+ check False $ checkWBOResult wbo ("SATISFIABLE", Just 2, Just $ array (1, 2) [(1, False), (2, True)])+ check False $ checkWBOResult wbo ("SATISFIABLE", Nothing, Nothing)+ where+ (x1,x2) = (1,2)+ wbo = PBFile.SoftFormula+ { PBFile.wboNumVars = 2+ , PBFile.wboNumConstraints = 3+ , PBFile.wboTopCost = Just 2+ , PBFile.wboConstraints =+ [ (Nothing, ([(1, [ x1]), (1, [ x2])], PBFile.Ge, 1))+ , (Just 2, ([(1, [ x1]), (1, [-x2])], PBFile.Ge, 1))+ , (Just 1, ([(1, [-x1]), (1, [ x2])], PBFile.Ge, 1))+ , (Just 3, ([(1, [-x1]), (1, [-x2])], PBFile.Ge, 1))+ ]+ }++case_checkWBOResult_OPTIMUM_FOUND :: Assertion+case_checkWBOResult_OPTIMUM_FOUND = do+ check True $ checkWBOResult wbo ("OPTIMUM FOUND", Just 1, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkWBOResult wbo ("OPTIMUM FOUND", Just 0, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkWBOResult wbo ("OPTIMUM FOUND", Just 0, Just $ array (1, 2) [(1, False), (2, False)])+ check False $ checkWBOResult wbo ("OPTIMUM FOUND", Just 2, Just $ array (1, 2) [(1, False), (2, True)])+ check False $ checkWBOResult wbo ("OPTIMUM FOUND", Nothing, Nothing)+ where+ (x1,x2) = (1,2)+ wbo = PBFile.SoftFormula+ { PBFile.wboNumVars = 2+ , PBFile.wboNumConstraints = 3+ , PBFile.wboTopCost = Just 2+ , PBFile.wboConstraints =+ [ (Nothing, ([(1, [ x1]), (1, [ x2])], PBFile.Ge, 1))+ , (Just 2, ([(1, [ x1]), (1, [-x2])], PBFile.Ge, 1))+ , (Just 1, ([(1, [-x1]), (1, [ x2])], PBFile.Ge, 1))+ , (Just 3, ([(1, [-x1]), (1, [-x2])], PBFile.Ge, 1))+ ]+ }++case_checkWBOResult_UNSATISFIABLE :: Assertion+case_checkWBOResult_UNSATISFIABLE = do+ check True $ checkWBOResult wbo ("UNSATISFIABLE", Nothing, Nothing)+ check False $ checkWBOResult wbo ("UNSATISFIABLE", Just 3, Just $ array (1, 2) [(1, True), (2, True)])+ where+ (x1,x2) = (1,2)+ wbo = PBFile.SoftFormula+ { PBFile.wboNumVars = 2+ , PBFile.wboNumConstraints = 3+ , PBFile.wboTopCost = Just 2+ , PBFile.wboConstraints =+ [ (Nothing, ([(1, [ x1]), (1, [ x2])], PBFile.Ge, 1))+ , (Just 2, ([(1, [ x1]), (1, [-x2])], PBFile.Ge, 1))+ , (Just 1, ([(1, [-x1]), (1, [ x2])], PBFile.Ge, 1))+ , (Just 3, ([(1, [-x1]), (1, [-x2])], PBFile.Ge, 1))+ ]+ }++case_checkWBOResult_UNKNOWN :: Assertion+case_checkWBOResult_UNKNOWN = do+ check True $ checkWBOResult wbo ("UNKNOWN", Just 1, Just $ array (1, 2) [(1, True), (2, False)])+ check False $ checkWBOResult wbo ("UNKNOWN", Just 0, Just $ array (1, 2) [(1, True), (2, False)])+ check True $ checkWBOResult wbo ("UNKNOWN", Nothing, Nothing)+ where+ (x1,x2) = (1,2)+ wbo = PBFile.SoftFormula+ { PBFile.wboNumVars = 2+ , PBFile.wboNumConstraints = 3+ , PBFile.wboTopCost = Just 2+ , PBFile.wboConstraints =+ [ (Nothing, ([(1, [ x1]), (1, [ x2])], PBFile.Ge, 1))+ , (Just 2, ([(1, [ x1]), (1, [-x2])], PBFile.Ge, 1))+ , (Just 1, ([(1, [-x1]), (1, [ x2])], PBFile.Ge, 1))+ , (Just 3, ([(1, [-x1]), (1, [-x2])], PBFile.Ge, 1))+ ]+ }++case_checkWBOResult_UNSUPPORTED :: Assertion+case_checkWBOResult_UNSUPPORTED = do+ check True $ checkWBOResult wbo ("UNSUPPORTED", Nothing, Nothing)+ where+ (x1,x2) = (1,2)+ wbo = PBFile.SoftFormula+ { PBFile.wboNumVars = 2+ , PBFile.wboNumConstraints = 3+ , PBFile.wboTopCost = Just 2+ , PBFile.wboConstraints =+ [ (Nothing, ([(1, [ x1]), (1, [ x2])], PBFile.Ge, 1))+ , (Just 2, ([(1, [ x1]), (1, [-x2])], PBFile.Ge, 1))+ , (Just 1, ([(1, [-x1]), (1, [ x2])], PBFile.Ge, 1))+ , (Just 3, ([(1, [-x1]), (1, [-x2])], PBFile.Ge, 1))+ ]+ }++case_checkWBOResult_bad_solution_status :: Assertion+case_checkWBOResult_bad_solution_status =+ check False $ checkWBOResult wbo ("FOO BAR", Just 0, Just $ array (1, 2) [(1, True), (2, True)])+ where+ (x1,x2) = (1,2)+ wbo = PBFile.SoftFormula+ { PBFile.wboNumVars = 2+ , PBFile.wboNumConstraints = 3+ , PBFile.wboTopCost = Just 2+ , PBFile.wboConstraints =+ [ (Nothing, ([(1, [ x1]), (1, [ x2])], PBFile.Ge, 1))+ , (Just 2, ([(1, [ x1]), (1, [-x2])], PBFile.Ge, 1))+ , (Just 1, ([(1, [-x1]), (1, [ x2])], PBFile.Ge, 1))+ , (Just 3, ([(1, [-x1]), (1, [-x2])], PBFile.Ge, 1))+ ]+ }++-- ----------------------------------------------------------------------++case_checkMIPResult_objective_value :: Assertion+case_checkMIPResult_objective_value = do+ check True $ checkMIPResult def prob sol{ MIP.solObjectiveValue = Just (8 + 1e-6) }+ check False $ checkMIPResult def prob sol{ MIP.solObjectiveValue = Just (8 + 1e-5) }++ where+ (x1, x2) = (MIP.varExpr "x1", MIP.varExpr "x2")++ prob :: MIP.Problem Scientific+ prob = def+ { MIP.objectiveFunction = def{ MIP.objExpr = 2*x1 + 3*x2 }+ , MIP.varDomains = Map.fromList+ [ ("x1", (MIP.ContinuousVariable, MIP.defaultBounds))+ , ("x2", (MIP.ContinuousVariable, MIP.defaultBounds))+ ]+ }++ sol :: MIP.Solution Scientific+ sol = def+ { MIP.solStatus = MIP.StatusFeasible+ , MIP.solObjectiveValue = Just 8+ , MIP.solVariables = Map.fromList+ [ ("x1", 1)+ , ("x2", 2)+ ]+ }++case_checkMIPResult_variable_bounds :: Assertion+case_checkMIPResult_variable_bounds = do+ check False $ checkMIPResult def prob (sol 0)+ check False $ checkMIPResult def prob (sol (10 - 1e-5))+ check True $ checkMIPResult def prob (sol (10 - 1e-6))+ check True $ checkMIPResult def prob (sol 10)+ check True $ checkMIPResult def prob (sol 20)+ check True $ checkMIPResult def prob (sol (20 + 1e-6))+ check False $ checkMIPResult def prob (sol (20 + 1e-5))+ check False $ checkMIPResult def prob (sol 25)+ where+ prob :: MIP.Problem Scientific+ prob = def+ { MIP.varDomains = Map.singleton "x" (MIP.ContinuousVariable, (10, 20))+ }++ sol :: Scientific -> MIP.Solution Scientific+ sol val = def+ { MIP.solStatus = MIP.StatusFeasible+ , MIP.solObjectiveValue = Nothing+ , MIP.solVariables = Map.singleton "x" val+ }++case_checkMIPResult_integrality :: Assertion+case_checkMIPResult_integrality = do+ forM_ ([MIP.IntegerVariable, MIP.SemiIntegerVariable] :: [MIP.VarType]) $ \vt -> do+ check True $ checkMIPResult def{ MIP.integralityTol = 1e-5 } (prob vt) sol+ check False $ checkMIPResult def{ MIP.integralityTol = 1e-6 } (prob vt) sol++ where+ prob :: MIP.VarType -> MIP.Problem Scientific+ prob vt = def+ { MIP.varDomains = Map.singleton "x" (vt, (1, 2))+ }++ sol :: MIP.Solution Scientific+ sol = def+ { MIP.solStatus = MIP.StatusFeasible+ , MIP.solObjectiveValue = Nothing+ , MIP.solVariables = Map.singleton "x" (1 + 1e-5)+ }++case_checkMIPResult_semi :: Assertion+case_checkMIPResult_semi = do+ forM_ ([MIP.SemiContinuousVariable, MIP.SemiIntegerVariable] :: [MIP.VarType]) $ \vt -> do+ check True $ checkMIPResult def (prob vt) (sol 0)+ check False $ checkMIPResult def (prob vt) (sol 5)+ check True $ checkMIPResult def (prob vt) (sol 10)+ check False $ checkMIPResult def (prob vt) (sol 25)++ where+ prob :: MIP.VarType -> MIP.Problem Scientific+ prob vt = def+ { MIP.varDomains = Map.singleton "x" (vt, (10, 20))+ }++ sol :: Scientific -> MIP.Solution Scientific+ sol val = def+ { MIP.solStatus = MIP.StatusFeasible+ , MIP.solObjectiveValue = Nothing+ , MIP.solVariables = Map.singleton "x" val+ }++case_checkMIPResult_constraints :: Assertion+case_checkMIPResult_constraints = do+ check True $ checkMIPResult def prob sol+ check False $ checkMIPResult def{ MIP.feasibilityTol = 1e-7 } prob sol+ where+ (x1, x2) = (MIP.varExpr "x1", MIP.varExpr "x2")++ prob :: MIP.Problem Scientific+ prob = def+ { MIP.constraints =+ [ x1 - x2 MIP..<=. 0+ ]+ , MIP.varDomains = Map.fromList+ [ ("x1", (MIP.ContinuousVariable, MIP.defaultBounds))+ , ("x2", (MIP.ContinuousVariable, MIP.defaultBounds))+ ]+ }++ sol :: MIP.Solution Scientific+ sol = def+ { MIP.solStatus = MIP.StatusFeasible+ , MIP.solObjectiveValue = Nothing+ , MIP.solVariables = Map.fromList+ [ ("x1", 1)+ , ("x2", 1 - 1e-6)+ ]+ }++case_checkMIPResult_SOS_constraints :: Assertion+case_checkMIPResult_SOS_constraints = do+ check True $ checkMIPResult def (prob MIP.S1) (sol [0, 0, 0])+ check True $ checkMIPResult def (prob MIP.S1) (sol [0, 1, 0])+ check False $ checkMIPResult def (prob MIP.S1) (sol [1, 0, 1])++ check True $ checkMIPResult def (prob MIP.S2) (sol [0, 0, 0])+ check True $ checkMIPResult def (prob MIP.S2) (sol [0, 1, 0])+ check True $ checkMIPResult def (prob MIP.S2) (sol [1, 1, 0])+ check True $ checkMIPResult def (prob MIP.S2) (sol [0, 1, 1])+ check False $ checkMIPResult def (prob MIP.S2) (sol [1, 0, 1])+ check False $ checkMIPResult def (prob MIP.S2) (sol [1, 1, 1])++ where+ prob :: MIP.SOSType -> MIP.Problem Scientific+ prob t = def+ { MIP.varDomains = Map.fromList+ [ (x, (MIP.IntegerVariable, (0, 1)))+ | x <- ["x1", "x2", "x3"]+ ]+ , MIP.sosConstraints =+ [ MIP.SOSConstraint+ { MIP.sosLabel = Nothing+ , MIP.sosType = t+ , MIP.sosBody = [("x1", 1), ("x2", 2), ("x3", 3)]+ }+ ]+ }++ sol :: [Scientific] -> MIP.Solution Scientific+ sol xs = def+ { MIP.solStatus = MIP.StatusFeasible+ , MIP.solObjectiveValue = Nothing+ , MIP.solVariables = Map.fromList $ zip ["x1", "x2", "x3"] xs+ }++-- ----------------------------------------------------------------------+-- Test harness++solutionCheckerTestGroup :: TestTree+solutionCheckerTestGroup = $(testGroupGenerator)
test/TestPolynomial.hs view
@@ -7,7 +7,7 @@ import qualified Control.Exception as E import Control.Monad import qualified Data.FiniteField as FF-import Data.List+import Data.List (foldl', genericTake, sort, sortBy) import Data.Ratio import qualified Data.Set as Set import qualified Data.Map as Map@@ -563,7 +563,7 @@ size <- choose (0, 3) xs <- replicateM size $ do v <- choose (-5, 5)- e <- liftM ((+1) . abs) arbitrary+ e <- choose (1, 4) return $ P.var v `P.mpow` e return $ foldl' P.mmult P.mone xs
test/TestSuite.hs view
@@ -26,6 +26,7 @@ import Test.SAT import Test.SAT.Encoder import Test.SAT.ExistentialQuantification+import Test.SAT.LogParser import Test.SAT.MUS import Test.SAT.TheorySolver import Test.SAT.Types@@ -33,7 +34,7 @@ import Test.SimplexTextbook import Test.SMT import Test.SMTLIB2Solver-import Test.Smtlib+import Test.SolutionChecker import Test.SubsetSum import Test.BipartiteMatching @@ -62,6 +63,7 @@ , satTestGroup , satEncoderTestGroup , satExistentialQuantificationTestGroup+ , satLogParserTestGroup , satMUSTestGroup , satTheorySolverTestGroup , satTypesTestGroup@@ -70,7 +72,7 @@ , simplexTextbookTestGroup , smtTestGroup , smtlib2SolverTestGroup- , smtlibTestGroup+ , solutionCheckerTestGroup , subsetSumTestGroup , bipartiteMatchingTestGroup ]
toysolver.cabal view
@@ -1,6 +1,6 @@-cabal-version: 2.4+cabal-version: 3.0 Name: toysolver-Version: 0.9.0+Version: 0.10.0 License: BSD-3-Clause License-File: COPYING Author: Masahiro Sakai (masahiro.sakai@gmail.com)@@ -11,14 +11,10 @@ Homepage: https://github.com/msakai/toysolver/ Bug-Reports: https://github.com/msakai/toysolver/issues Tested-With:- GHC ==8.6.3- GHC ==8.8.4- GHC ==8.10.7- GHC ==9.0.2- GHC ==9.2.8- GHC ==9.4.8- GHC ==9.6.6- GHC ==9.8.2+ GHC ==9.6.7+ GHC ==9.8.4+ GHC ==9.10.3+ GHC ==9.12.4 Extra-Doc-Files: README.md INSTALL.md@@ -114,23 +110,35 @@ Manual: True Default: False -Flag optparse-applicative-018- Description: use optparse-applicative >=0.18- Manual: False- Default: False- source-repository head type: git- location: git://github.com/msakai/toysolver.git+ location: https://github.com/msakai/toysolver.git +Common common-options+ Default-Language: Haskell2010+ -- GHC-Prof-Options: -fprof-auto+ Build-Depends:+ -- GHC >=9.6 && <9.15+ base >=4.18 && <4.23++Common exe-options+ Import: common-options+ if flag(ForceChar8)+ CPP-OPtions: "-DFORCE_CHAR8"+ GHC-Options: -rtsopts+ if flag(LinuxStatic)+ GHC-Options: -static -optl-static -optl-pthread+ Other-Extensions: CPP+ Library+ Import: common-options Exposed: True Hs-source-dirs: src Build-Depends:- aeson >=1.4.2.0 && <2.3,- array >=0.5,- -- GHC >=8.6 && <9.11- base >=4.12 && <4.21,+ -- Data.Aeson.Key requires aeson >=2.0.0+ aeson >=2.0 && <2.3,+ -- modifyArray requires array >=0.5.6+ array >=0.5.6, bytestring >=0.9.2.1 && <0.13, bytestring-builder, bytestring-encoding >=0.1.1.0,@@ -146,11 +154,13 @@ extended-reals >=0.1 && <1.0, filepath, finite-field >=0.9.0 && <1.0.0,- -- hashUsing is available on hashable >=1.2- hashable >=1.2 && <1.6.0.0,+ -- defaultHashWithSalt requires hashable >=1.4.3+ hashable >=1.4.3 && <1.6.0.0, hashtables, heaps,+ integer-logarithms >=1.0.3.1 && <1.1, intern >=0.9.1.2 && <1.0.0.0,+ language-smtlib >=0.2.0.0 && <0.3.0.0, log-domain, -- numLoopState requires loop >=0.3.0 loop >=0.3.0 && < 1.0.0,@@ -167,7 +177,7 @@ primes, primitive >=0.6, process >=1.1.0.2,- pseudo-boolean >=0.1.3.0 && <0.2.0.0,+ pseudo-boolean >=0.1.12.0 && <0.2.0.0, queue, scientific, semigroups >=0.17,@@ -192,7 +202,6 @@ CPP-Options: "-DEXTRA_BOUNDS_CHECKING" if impl(ghc) Build-Depends: ghc-prim- Default-Language: Haskell2010 Other-Extensions: BangPatterns CPP@@ -330,6 +339,7 @@ ToySolver.SAT.Encoder.Tseitin ToySolver.SAT.ExistentialQuantification ToySolver.SAT.Formula+ ToySolver.SAT.LogParser ToySolver.SAT.MUS ToySolver.SAT.MUS.Enum ToySolver.SAT.MUS.Types@@ -352,6 +362,7 @@ ToySolver.SAT.Printer ToySolver.SDP ToySolver.SMT+ ToySolver.SMT.SMTLIB2Solver ToySolver.Text.SDPFile ToySolver.Internal.Data.IndexedPriorityQueue ToySolver.Internal.Data.IOURef@@ -359,6 +370,7 @@ ToySolver.Internal.Data.SeqQueue ToySolver.Internal.Data.Vec ToySolver.Internal.ProcessUtil+ ToySolver.Internal.SolutionChecker ToySolver.Internal.TextUtil ToySolver.Internal.Util ToySolver.Wang@@ -380,17 +392,15 @@ Paths_toysolver autogen-modules: Paths_toysolver- -- GHC-Prof-Options: -auto-all Executable toysolver+ Import: exe-options Main-is: toysolver.hs HS-Source-Dirs: app Build-Depends: array,- base >=4.12 && <4.21, containers, data-default-class,- filepath, MIP, OptDir, -- maybeReader is available on optparse-applicative >=0.13.0.0@@ -398,26 +408,18 @@ pseudo-boolean, scientific, toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts -threaded- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread- -- GHC-Prof-Options: -auto-all+ GHC-Options: -threaded Executable toysat+ Import: exe-options Main-is: toysat.hs HS-Source-Dirs: app/toysat Build-Depends: array,- base >=4.12 && <4.21, bytestring, containers, clock, data-default-class,- filepath, megaparsec, MIP, mwc-random,@@ -429,18 +431,11 @@ toysolver, unbounded-delays, vector- Default-Language: Haskell2010- Other-Extensions: ScopedTypeVariables, CPP- GHC-Options: -rtsopts -threaded- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(WithZlib)- CPP-Options: "-DWITH_ZLIB"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread+ Other-Extensions: ScopedTypeVariables+ GHC-Options: -threaded Foreign-Library toysat-ipasir+ import: common-options type: native-shared if !flag(BuildForeignLibraries) buildable: False@@ -450,7 +445,6 @@ if os(Linux) ld-options: -Wl,--version-script=app/toysat-ipasir/ipasir.map build-depends:- base >=4.12 && <4.21, containers, toysolver hs-source-dirs: app/toysat-ipasir@@ -463,282 +457,179 @@ default-language: Haskell2010 Executable toysmt- HS-Source-Dirs: app/toysmt, Smtlib+ Import: exe-options+ HS-Source-Dirs: app/toysmt Main-is: toysmt.hs- Other-Modules:- ToySolver.SMT.SMTLIB2Solver,- -- Following modules are copied from SmtLib package.- -- http://hackage.haskell.org/package/SmtLib- -- https://github.com/MfesGA/Smtlib- Smtlib.Parsers.CommonParsers,- Smtlib.Parsers.ResponseParsers,- Smtlib.Parsers.CommandsParsers,- Smtlib.Syntax.Syntax,- Smtlib.Syntax.ShowSL Build-Depends:- base >=4.12 && <4.21,- containers,- -- TODO: remove intern dependency- intern,- mtl,+ language-smtlib, optparse-applicative,- parsec >=3.1.2 && <4, toysolver,- text,- transformers,- transformers-compat+ text if flag(UseHaskeline) Build-Depends: haskeline >=0.7 && <0.9 CPP-Options: "-DUSE_HASKELINE_PACKAGE"- Default-Language: Haskell2010- Other-Extensions: ScopedTypeVariables, CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread+ Other-Extensions: ScopedTypeVariables Executable toyqbf+ Import: exe-options Main-is: toyqbf.hs HS-Source-Dirs: app Build-Depends:- base >=4.12 && <4.21, containers, data-default-class, optparse-applicative, toysolver- Default-Language: Haskell2010- Other-Extensions: ScopedTypeVariables, CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread+ Other-Extensions: ScopedTypeVariables Executable toyfmf+ Import: exe-options If !flag(BuildToyFMF) Buildable: False Main-is: toyfmf.hs HS-Source-Dirs: app If flag(BuildToyFMF) Build-Depends:- base >=4.12 && <4.21,- containers,+ containers, intern, logic-TPTP >=0.4.6.0 && <0.7, optparse-applicative, text, toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread- -- GHC-Prof-Options: -auto-all --- Converters- Executable toyconvert+ Import: exe-options Main-is: toyconvert.hs HS-Source-Dirs: app Build-Depends: aeson,- base >=4.12 && <4.21, bytestring, bytestring-builder, containers, data-default-class,- filepath, MIP,+ optparse-applicative >=0.18,+ prettyprinter >=1, pseudo-boolean, scientific, text, toysolver- if flag(optparse-applicative-018)- Build-Depends:- optparse-applicative >=0.18,- prettyprinter >=1- else- Build-Depends:- optparse-applicative <0.18,- ansi-wl-pprint- Default-Language: Haskell2010- Other-Extensions: CPP GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(WithZlib)- CPP-Options: "-DWITH_ZLIB"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread +Executable toysolver-check+ Import: exe-options+ Main-is: toysolver_check.hs+ HS-Source-Dirs: app+ Build-Depends:+ array,+ bytestring,+ containers,+ data-default-class,+ MIP,+ optparse-applicative,+ pseudo-boolean,+ scientific,+ text,+ toysolver+ -- Sample Programs Executable sudoku+ Import: exe-options If !flag(BuildSamplePrograms) Buildable: False Main-is: sudoku.hs HS-Source-Dirs: samples/programs/sudoku Build-Depends: array,- base >=4.12 && <4.21, toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread Executable nonogram+ Import: exe-options If !flag(BuildSamplePrograms) Buildable: False Main-is: nonogram.hs HS-Source-Dirs: samples/programs/nonogram Build-Depends: array,- base >=4.12 && <4.21, containers, toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread Executable nqueens+ Import: exe-options If !flag(BuildSamplePrograms) Buildable: False Main-is: nqueens.hs HS-Source-Dirs: samples/programs/nqueens Build-Depends: array,- base >=4.12 && <4.21, toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread Executable numberlink+ Import: exe-options If !flag(BuildSamplePrograms) Buildable: False Main-is: numberlink.hs HS-Source-Dirs: samples/programs/numberlink Build-Depends: array,- base >=4.12 && <4.21, bytestring, containers, data-default-class, parsec, pseudo-boolean, toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread Executable knapsack+ Import: exe-options If !flag(BuildSamplePrograms) Buildable: False Main-is: knapsack.hs HS-Source-Dirs: samples/programs/knapsack Build-Depends:- base >=4.12 && <4.21, toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread Executable assign+ Import: exe-options If !flag(BuildSamplePrograms) Buildable: False Main-is: assign.hs HS-Source-Dirs: samples/programs/assign Build-Depends: attoparsec,- base >=4.12 && <4.21, bytestring, containers, toysolver, vector- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread Executable shortest-path+ Import: exe-options If !flag(BuildSamplePrograms) Buildable: False Main-is: shortest-path.hs HS-Source-Dirs: samples/programs/shortest-path Build-Depends:- base >=4.12 && <4.21, bytestring, containers, unordered-containers, toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread Executable htc+ Import: exe-options If !flag(BuildSamplePrograms) Buildable: False Main-is: htc.hs HS-Source-Dirs: samples/programs/htc Build-Depends:- base >=4.12 && <4.21, containers, toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread Executable svm2lp+ Import: exe-options If !flag(BuildSamplePrograms) Buildable: False Main-is: svm2lp.hs HS-Source-Dirs: samples/programs/svm2lp Build-Depends:- base >=4.12 && <4.21, containers, data-default-class, MIP,@@ -746,122 +637,54 @@ split, text, toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread Executable survey-propagation+ Import: exe-options if !flag(BuildSamplePrograms) Buildable: False Main-is: survey-propagation.hs HS-Source-Dirs: samples/programs/survey-propagation Build-Depends:- base >=4.12 && <4.21, data-default-class, toysolver- Default-Language: Haskell2010- Other-Extensions: CPP GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-Options: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread Executable probsat+ Import: exe-options if !flag(BuildSamplePrograms) Buildable: False Main-is: probsat.hs HS-Source-Dirs: samples/programs/probsat Build-Depends:- base >=4.12 && <4.21, clock, data-default-class, mwc-random, optparse-applicative, vector, toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-Options: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread -- Misc Programs Executable pigeonhole+ Import: exe-options If !flag(BuildMiscPrograms) Buildable: False Main-is: pigeonhole.hs HS-Source-Dirs: app Build-Depends:- base >=4.12 && <4.21, bytestring, containers, pseudo-boolean, toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread -Executable maxsatverify- If !flag(BuildMiscPrograms)- Buildable: False- Main-is: maxsatverify.hs- HS-Source-Dirs: app- Build-Depends:- array,- base >=4.12 && <4.21,- toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread--Executable pbverify- Main-is: pbverify.hs- If !flag(BuildMiscPrograms)- Buildable: False- HS-Source-Dirs: app- Build-Depends:- array,- base >=4.12 && <4.21,- pseudo-boolean,- toysolver- Default-Language: Haskell2010- Other-Extensions: CPP- GHC-Options: -rtsopts- -- GHC-Prof-Options: -auto-all- if flag(ForceChar8)- CPP-OPtions: "-DFORCE_CHAR8"- if flag(LinuxStatic)- GHC-Options: -static -optl-static -optl-pthread- -- Test suites and benchmarks Test-suite TestPolynomial+ Import: common-options Type: exitcode-stdio-1.0 HS-Source-Dirs: test Main-is: TestPolynomial.hs Build-depends:- base >=4.12 && <4.21, containers, data-interval, finite-field >=0.7.0 && <1.0.0,@@ -871,14 +694,14 @@ tasty-quickcheck >=0.8 && <0.12, tasty-th, toysolver- Default-Language: Haskell2010 Other-Extensions: DataKinds TemplateHaskell Test-suite TestSuite+ Import: common-options Type: exitcode-stdio-1.0- HS-Source-Dirs: test Smtlib app/toysmt+ HS-Source-Dirs: test Main-is: TestSuite.hs Other-Modules: Test.AReal@@ -905,6 +728,7 @@ Test.SAT Test.SAT.Encoder Test.SAT.ExistentialQuantification+ Test.SAT.LogParser Test.SAT.MUS Test.SAT.TheorySolver Test.SAT.Types@@ -914,18 +738,11 @@ Test.SimplexTextbook Test.SMT Test.SMTLIB2Solver- Test.Smtlib+ Test.SolutionChecker Test.SubsetSum- ToySolver.SMT.SMTLIB2Solver- Smtlib.Parsers.CommonParsers- Smtlib.Parsers.ResponseParsers- Smtlib.Parsers.CommandsParsers- Smtlib.Syntax.Syntax- Smtlib.Syntax.ShowSL Build-depends: aeson, array,- base >=4.12 && <4.21, bytestring, bytestring-builder, containers,@@ -934,13 +751,13 @@ deepseq, hashable, intern,+ language-smtlib, lattices, megaparsec, MIP, mtl, mwc-random, OptDir,- parsec >=3.1.2 && <4, pseudo-boolean, -- sublistOf is available on QuickCheck >=2.8 QuickCheck >=2.8 && <3,@@ -949,6 +766,7 @@ tasty-hunit >=0.9 && <0.11, tasty-quickcheck >=0.8 && <0.12, tasty-th,+ temporary, text, toysolver, transformers,@@ -956,7 +774,6 @@ unordered-containers, vector, vector-space- Default-Language: Haskell2010 Other-Extensions: CPP DataKinds@@ -967,34 +784,31 @@ TupleSections Benchmark BenchmarkSATLIB+ Import: common-options type: exitcode-stdio-1.0 hs-source-dirs: benchmarks main-is: BenchmarkSATLIB.hs build-depends: array,- base >=4.12 && <4.21, criterion >=1.0 && <1.7, data-default-class, toysolver- Default-Language: Haskell2010 Benchmark BenchmarkKnapsack+ Import: common-options type: exitcode-stdio-1.0 hs-source-dirs: benchmarks main-is: BenchmarkKnapsack.hs build-depends:- base >=4.12 && <4.21, criterion >=1.0 && <1.7, toysolver- Default-Language: Haskell2010 Benchmark BenchmarkSubsetSum+ Import: common-options type: exitcode-stdio-1.0 hs-source-dirs: benchmarks main-is: BenchmarkSubsetSum.hs build-depends:- base >=4.12 && <4.21, criterion >=1.0 && <1.7, toysolver, vector- Default-Language: Haskell2010