packages feed

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 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 @@  [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![Join the chat at https://gitter.im/msakai/toysolver](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/msakai/toysolver)+[![DeepWiki](https://img.shields.io/badge/DeepWiki-msakai%2Ftoysolver-blue.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAyCAYAAAAnWDnqAAAAAXNSR0IArs4c6QAAA05JREFUaEPtmUtyEzEQhtWTQyQLHNak2AB7ZnyXZMEjXMGeK/AIi+QuHrMnbChYY7MIh8g01fJoopFb0uhhEqqcbWTp06/uv1saEDv4O3n3dV60RfP947Mm9/SQc0ICFQgzfc4CYZoTPAswgSJCCUJUnAAoRHOAUOcATwbmVLWdGoH//PB8mnKqScAhsD0kYP3j/Yt5LPQe2KvcXmGvRHcDnpxfL2zOYJ1mFwrryWTz0advv1Ut4CJgf5uhDuDj5eUcAUoahrdY/56ebRWeraTjMt/00Sh3UDtjgHtQNHwcRGOC98BJEAEymycmYcWwOprTgcB6VZ5JK5TAJ+fXGLBm3FDAmn6oPPjR4rKCAoJCal2eAiQp2x0vxTPB3ALO2CRkwmDy5WohzBDwSEFKRwPbknEggCPB/imwrycgxX2NzoMCHhPkDwqYMr9tRcP5qNrMZHkVnOjRMWwLCcr8ohBVb1OMjxLwGCvjTikrsBOiA6fNyCrm8V1rP93iVPpwaE+gO0SsWmPiXB+jikdf6SizrT5qKasx5j8ABbHpFTx+vFXp9EnYQmLx02h1QTTrl6eDqxLnGjporxl3NL3agEvXdT0WmEost648sQOYAeJS9Q7bfUVoMGnjo4AZdUMQku50McDcMWcBPvr0SzbTAFDfvJqwLzgxwATnCgnp4wDl6Aa+Ax283gghmj+vj7feE2KBBRMW3FzOpLOADl0Isb5587h/U4gGvkt5v60Z1VLG8BhYjbzRwyQZemwAd6cCR5/XFWLYZRIMpX39AR0tjaGGiGzLVyhse5C9RKC6ai42ppWPKiBagOvaYk8lO7DajerabOZP46Lby5wKjw1HCRx7p9sVMOWGzb/vA1hwiWc6jm3MvQDTogQkiqIhJV0nBQBTU+3okKCFDy9WwferkHjtxib7t3xIUQtHxnIwtx4mpg26/HfwVNVDb4oI9RHmx5WGelRVlrtiw43zboCLaxv46AZeB3IlTkwouebTr1y2NjSpHz68WNFjHvupy3q8TFn3Hos2IAk4Ju5dCo8B3wP7VPr/FGaKiG+T+v+TQqIrOqMTL1VdWV1DdmcbO8KXBz6esmYWYKPwDL5b5FA1a0hwapHiom0r/cKaoqr+27/XcrS5UwSMbQAAAABJRU5ErkJggg==)](https://deepwiki.com/msakai/toysolver)  Hackage: [![Hackage](https://img.shields.io/hackage/v/toysolver.svg)](https://hackage.haskell.org/package/toysolver)@@ -11,9 +12,9 @@ [![Build Status](https://github.com/msakai/toysolver/workflows/build/badge.svg)](https://github.com/msakai/toysolver/actions) [![Coverage Status](https://coveralls.io/repos/msakai/toysolver/badge.svg)](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