packages feed

hasmtlib 2.6.2 → 2.6.3

raw patch · 6 files changed

+123/−40 lines, 6 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Language.Hasmtlib.Type.Solver: solveMaximizedDebug :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t, Orderable (Expr t)) => (Solution -> IO ()) -> Expr t -> m (Result, Solution)
- Language.Hasmtlib.Type.Solver: solveMinimizedDebug :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t, Orderable (Expr t)) => (Solution -> IO ()) -> Expr t -> m (Result, Solution)
+ Language.Hasmtlib.Solver.Bitwuzla: bitwuzlaKissat :: Config
- Language.Hasmtlib.Type.ArrayMap: arrConst :: forall k_aeOA v_aeOB. Lens' (ConstArray k_aeOA v_aeOB) v_aeOB
+ Language.Hasmtlib.Type.ArrayMap: arrConst :: forall k_aeP4 v_aeP5. Lens' (ConstArray k_aeP4 v_aeP5) v_aeP5
- Language.Hasmtlib.Type.ArrayMap: stored :: forall k_aeOA v_aeOB k_agmZ. Lens (ConstArray k_aeOA v_aeOB) (ConstArray k_agmZ v_aeOB) (Map k_aeOA v_aeOB) (Map k_agmZ v_aeOB)
+ Language.Hasmtlib.Type.ArrayMap: stored :: forall k_aeP4 v_aeP5 k_agnt. Lens (ConstArray k_aeP4 v_aeP5) (ConstArray k_agnt v_aeP5) (Map k_aeP4 v_aeP5) (Map k_agnt v_aeP5)
- Language.Hasmtlib.Type.Expr: varId :: forall t_awiz t_axe5. Iso (SMTVar t_awiz) (SMTVar t_axe5) Int Int
+ Language.Hasmtlib.Type.Expr: varId :: forall t_awj3 t_axez. Iso (SMTVar t_awj3) (SMTVar t_axez) Int Int
- Language.Hasmtlib.Type.Solution: solVal :: forall t_a1dHH. Lens' (SMTVarSol t_a1dHH) (Value t_a1dHH)
+ Language.Hasmtlib.Type.Solution: solVal :: forall t_a1dIb. Lens' (SMTVarSol t_a1dIb) (Value t_a1dIb)
- Language.Hasmtlib.Type.Solution: solVar :: forall t_a1dHH. Lens' (SMTVarSol t_a1dHH) (SMTVar t_a1dHH)
+ Language.Hasmtlib.Type.Solution: solVar :: forall t_a1dIb. Lens' (SMTVarSol t_a1dIb) (SMTVar t_a1dIb)
- Language.Hasmtlib.Type.Solver: solveMaximized :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t, Orderable (Expr t)) => Expr t -> m (Result, Solution)
+ Language.Hasmtlib.Type.Solver: solveMaximized :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t, Orderable (Expr t)) => Expr t -> Maybe (Expr t -> Expr t) -> Maybe (Solution -> IO ()) -> m (Result, Solution)
- Language.Hasmtlib.Type.Solver: solveMinimized :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t, Orderable (Expr t)) => Expr t -> m (Result, Solution)
+ Language.Hasmtlib.Type.Solver: solveMinimized :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t, Orderable (Expr t)) => Expr t -> Maybe (Expr t -> Expr t) -> Maybe (Solution -> IO ()) -> m (Result, Solution)

Files

CHANGELOG.md view
@@ -6,6 +6,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [PVP versioning](https://pvp.haskell.org/). +## v2.6.3 _(2024-09-07)_++### Added+- Added a solver configuration `bitwuzlaKissat` for `Bitwuzla` with underlying SAT-Solver `Kissat`.++### Changed+- Removed `solveMinimizedDebug` & `solveMaximizedDebug`. Use the modified `solveMinimized` & `solveMaximized` instead.+You can also provide a step-size now.+- Fixed a bug where `MonadOMT#solve` would run `get-model` although the solver did not necessarily respond with `Sat`.+- `SharingMode` for sharing common (sub-)expressions now defaults to `None`.+The previous default `StableNames` in general is only worth using, when your program can benefit a lot from sharing.+Otherwise it may drastically downgrade solver performance due to abundance of sharing-variables.+If you still want to use it, run `setSharingMode StableNames` within the problems monad.+ ## v2.6.2 _(2024-09-04)_  ### Changed
hasmtlib.cabal view
@@ -1,7 +1,7 @@ cabal-version:         3.0  name:                  hasmtlib-version:               2.6.2+version:               2.6.3 synopsis:              A monad for interfacing with external SMT solvers description:           Hasmtlib is a library for generating SMTLib2-problems using a monad.   It takes care of encoding your problem, marshaling the data to an external solver and parsing and interpreting the result into Haskell types.
src/Language/Hasmtlib/Internal/Sharing.hs view
@@ -28,7 +28,7 @@   deriving Show  instance Default SharingMode where-  def = StableNames+  def = None  -- | States that can share expressions by comparing their 'StableName's. class Sharing s where
src/Language/Hasmtlib/Solver/Bitwuzla.hs view
@@ -9,3 +9,13 @@ --   Make sure it's default SAT-Solver binary - probably @cadical@ - is in path too. bitwuzla :: Config bitwuzla = defaultConfig { exe = "bitwuzla", args = [] }+++-- | A 'Config' for Bitwuzla with Kissat as underlying sat-solver.+--+--   Requires binary @bitwuzla@ and to be in path.+--   Will use the @kissat@ shipped with @bitwuzla@.+--+--   It is recommended to build @bitwuzla@ from source for this to work as expected.+bitwuzlaKissat :: Config+bitwuzlaKissat = defaultConfig { exe = "bitwuzla", args = ["--sat-solver=kissat"] }
src/Language/Hasmtlib/Type/MonadSMT.hs view
@@ -36,7 +36,6 @@ import Language.Hasmtlib.Codec import Data.Proxy import Control.Lens-import Control.Monad import Control.Monad.State  -- | A 'MonadState' that holds an SMT-Problem.@@ -235,12 +234,17 @@ -- (res, sol) <- solve -- case res of --   Sat -> do---     x' <- getValue x --     liftIO $ print $ decode sol x --   r -> print r -- @ solve :: (MonadIncrSMT s m, MonadIO m) => m (Result, Solution)-solve = liftM2 (,) checkSat getModel+solve = do+  res <- checkSat+  case res of+    Sat -> do+      sol <- getModel+      return (Sat, sol)+    r -> return (r, mempty)  -- | A 'MonadSMT' that addtionally allows optimization targets. --
src/Language/Hasmtlib/Type/Solver.hs view
@@ -13,14 +13,13 @@   , interactiveWith, debugInteractiveWith    -- ** Minimzation-  , solveMinimized, solveMinimizedDebug+  , solveMinimized    -- ** Maximization-  , solveMaximized, solveMaximizedDebug+  , solveMaximized   ) where -import Language.Hasmtlib.Internal.Sharing import Language.Hasmtlib.Type.MonadSMT import Language.Hasmtlib.Type.Expr import Language.Hasmtlib.Type.SMTSort@@ -30,6 +29,7 @@ import qualified SMTLIB.Backends as Backend import qualified SMTLIB.Backends.Process as Process import Data.Default+import Data.Maybe import Control.Monad.State  -- | Data that can have a 'Backend.Solver' which may be debugged.@@ -38,7 +38,7 @@   withSolver :: Backend.Solver -> Bool -> a  instance WithSolver Pipe where-  withSolver = Pipe 0 Nothing StableNames mempty mempty+  withSolver = Pipe 0 Nothing def mempty mempty  -- | @'solveWith' solver prob@ solves a SMT problem @prob@ with the given -- @solver@. It returns a pair consisting of:@@ -130,56 +130,111 @@  -- | Solves the current problem with respect to a minimal solution for a given numerical expression. -----   Uses iterative refinement.+--   This is done by incrementally refining the upper bound for a given target.+--   Terminates, when setting the last intermediate result as new upper bound results in 'Unsat'.+--   Then removes that last assertion and returns the previous (now confirmed minimal) result. -----   If you want access to intermediate results, use 'solveMinimizedDebug' instead.+--   You can also provide a step-size. You do not have to worry about stepping over the optimal result.+--   This implementation takes care of it.+--+--   Access to intermediate results is also possible via an 'IO'-Action.+--+-- ==== __Examples__+--+-- @+-- x <- var \@IntSort+-- assert $ x >? 4+-- solveMinimized x Nothing Nothing+-- @+--+-- The solver will return @x := 5@.+--+-- The first 'Nothing' indicates that each intermediate result will be set as next upper bound.+-- The second 'Nothing' shows that we do not care about intermediate, but only the final (minimal) result.+--+-- @+-- x <- var \@IntSort+-- assert $ x >? 4+-- solveMinimized x (Just (\\r -> r-1)) (Just print)+-- @+--+-- The solver will still return @x := 5@.+--+-- However, here we want the next bound of each refinement to be @lastResult - 1@.+-- Also, every intermediate result is printed. solveMinimized :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t, Orderable (Expr t))-  => Expr t-  -> m (Result, Solution)-solveMinimized = solveOptimized Nothing (<?)---- | Like 'solveMinimized' but with access to intermediate results.-solveMinimizedDebug :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t, Orderable (Expr t))-  => (Solution -> IO ())-  -> Expr t+  => Expr t                             -- ^ Target to minimize+  -> Maybe (Expr t -> Expr t)           -- ^ Step-size: Lambda is given last result as argument, producing the next upper bound+  -> Maybe (Solution -> IO ())          -- ^ Accessor to intermediate results   -> m (Result, Solution)-solveMinimizedDebug debug = solveOptimized (Just debug) (<?)+solveMinimized = solveOptimized (<?)  -- | Solves the current problem with respect to a maximal solution for a given numerical expression. -----   Uses iterative refinement.+--   This is done by incrementally refining the lower bound for a given target.+--   Terminates, when setting the last intermediate result as new lower bound results in 'Unsat'.+--   Then removes that last assertion and returns the previous (now confirmed maximal) result. -----   If you want access to intermediate results, use 'solveMaximizedDebug' instead.+--   You can also provide a step-size. You do not have to worry about stepping over the optimal result.+--   This implementation takes care of it.+--+--   Access to intermediate results is also possible via an 'IO'-Action.+--+-- ==== __Examples__+--+-- @+-- x <- var \@IntSort+-- assert $ x <? 4+-- solveMaximized x Nothing Nothing+-- @+--+-- The solver will return @x := 3@.+--+-- The first 'Nothing' indicates that each intermediate result will be set as next lower bound.+-- The second 'Nothing' shows that we do not care about intermediate, but only the final (maximal) result.+--+-- @+-- x <- var \@IntSort+-- assert $ x <? 4+-- solveMinimized x (Just (+1)) (Just print)+-- @+--+-- The solver will still return @x := 3@.+--+-- However, here we want the next bound of each refinement to be @lastResult + 1@.+-- Also, every intermediate result is printed. solveMaximized :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t, Orderable (Expr t))-  => Expr t-  -> m (Result, Solution)-solveMaximized = solveOptimized Nothing (>?)---- | Like 'solveMaximized' but with access to intermediate results.-solveMaximizedDebug :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t, Orderable (Expr t))-  => (Solution -> IO ())-  -> Expr t+  => Expr t                             -- ^ Target to maximize+  -> Maybe (Expr t -> Expr t)           -- ^ Step-size: Lambda is given last result as argument, producing the next lower bound+  -> Maybe (Solution -> IO ())          -- ^ Accessor to intermediate results   -> m (Result, Solution)-solveMaximizedDebug debug = solveOptimized (Just debug) (>?)+solveMaximized = solveOptimized (>?)  solveOptimized :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t)-  => Maybe (Solution -> IO ())-  -> (Expr t -> Expr t -> Expr BoolSort)+  => (Expr t -> Expr t -> Expr BoolSort)   -> Expr t+  -> Maybe (Expr t -> Expr t)+  -> Maybe (Solution -> IO ())   -> m (Result, Solution)-solveOptimized mDebug op = go Unknown mempty+solveOptimized op goal mStep mDebug = refine Unknown mempty goal   where-    go oldRes oldSol target = do-      push-      (res, sol) <- solve+    refine oldRes oldSol target = do+      res <- checkSat       case res of         Sat   -> do+          sol <- getModel           case decode sol target of             Nothing        -> return (Sat, mempty)             Just targetSol -> do               case mDebug of                 Nothing    -> pure ()                 Just debug -> liftIO $ debug sol-              assert $ target `op` encode targetSol-              go res sol target-        _ -> pop >> return (oldRes, oldSol)+              push+              let step = fromMaybe id mStep+              assert $ target `op` step (encode targetSol)+              refine res sol target+        _ -> do+          pop+          case mStep of+            Nothing -> return (oldRes, oldSol)+            Just _  -> solveOptimized op goal Nothing mDebug -- make sure the very last step did not skip the optimal result