{-# LANGUAGE TemplateHaskell #-}
module Language.Hasmtlib.Type.Solver
(
SolverConfig(..)
, debugging, timingout
, processConfig, mTimeout, mDebugger
, Solver, solver, solveWith
, interactiveWith
, solveMinimized
, solveMaximized
)
where
import Language.Hasmtlib.Internal.Render
import Language.Hasmtlib.Internal.Parser
import Language.Hasmtlib.Type.MonadSMT
import Language.Hasmtlib.Type.Debugger
import Language.Hasmtlib.Type.Expr
import Language.Hasmtlib.Type.SMTSort
import Language.Hasmtlib.Type.Solution
import Language.Hasmtlib.Type.Pipe
import Language.Hasmtlib.Codec
import Data.ByteString.Lazy hiding (singleton)
import qualified SMTLIB.Backends as Backend
import qualified SMTLIB.Backends.Process as Process
import Data.Default
import Data.Maybe
import Data.Attoparsec.ByteString (parseOnly)
import Control.Lens hiding (op)
import Control.Monad
import Control.Monad.State
import Control.Monad.Trans.Control
import System.Timeout.Lifted
type Solver s m = s -> m (Result, Solution)
data SolverConfig s = SolverConfig
{ forall s. SolverConfig s -> Config
_processConfig :: Process.Config
, forall s. SolverConfig s -> Maybe Int
_mTimeout :: Maybe Int
, forall s. SolverConfig s -> Maybe (Debugger s)
_mDebugger :: Maybe (Debugger s)
}
$(makeLenses ''SolverConfig)
solver :: (RenderProblem s, MonadIO m) => SolverConfig s -> Solver s m
solver :: forall s (m :: * -> *).
(RenderProblem s, MonadIO m) =>
SolverConfig s -> Solver s m
solver (SolverConfig Config
cfg Maybe Int
mTO Maybe (Debugger s)
debugger) s
s = do
Handle
handle <- IO Handle -> m Handle
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Handle -> m Handle) -> IO Handle -> m Handle
forall a b. (a -> b) -> a -> b
$ Config -> IO Handle
Process.new Config
cfg
let timingOut :: IO (ByteString, ByteString) -> IO (ByteString, ByteString)
timingOut IO (ByteString, ByteString)
io = case Maybe Int
mTO of
Maybe Int
Nothing -> IO (ByteString, ByteString)
io
Just Int
t -> (ByteString, ByteString)
-> Maybe (ByteString, ByteString) -> (ByteString, ByteString)
forall a. a -> Maybe a -> a
fromMaybe (ByteString
"unknown", ByteString
forall a. Monoid a => a
mempty) (Maybe (ByteString, ByteString) -> (ByteString, ByteString))
-> IO (Maybe (ByteString, ByteString))
-> IO (ByteString, ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int
-> IO (ByteString, ByteString)
-> IO (Maybe (ByteString, ByteString))
forall (m :: * -> *) a.
MonadBaseControl IO m =>
Int -> m a -> m (Maybe a)
timeout Int
t IO (ByteString, ByteString)
io
(ByteString
rawRes, ByteString
rawModel) <- IO (ByteString, ByteString) -> m (ByteString, ByteString)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (ByteString, ByteString) -> m (ByteString, ByteString))
-> IO (ByteString, ByteString) -> m (ByteString, ByteString)
forall a b. (a -> b) -> a -> b
$ IO (ByteString, ByteString) -> IO (ByteString, ByteString)
timingOut (IO (ByteString, ByteString) -> IO (ByteString, ByteString))
-> IO (ByteString, ByteString) -> IO (ByteString, ByteString)
forall a b. (a -> b) -> a -> b
$ do
IO () -> (Debugger s -> IO ()) -> Maybe (Debugger s) -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
forall a. Monoid a => a
mempty (Debugger s -> s -> IO ()
forall s. Debugger s -> s -> IO ()
`debugState` s
s) Maybe (Debugger s)
debugger
Solver
pSolver <- QueuingFlag -> Backend -> IO Solver
Backend.initSolver QueuingFlag
Backend.Queuing (Backend -> IO Solver) -> Backend -> IO Solver
forall a b. (a -> b) -> a -> b
$ Handle -> Backend
Process.toBackend Handle
handle
let os :: Seq Builder
os = s -> Seq Builder
forall s. RenderProblem s => s -> Seq Builder
renderOptions s
s
l :: Builder
l = s -> Builder
forall s. RenderProblem s => s -> Builder
renderLogic s
s
vs :: Seq Builder
vs = s -> Seq Builder
forall s. RenderProblem s => s -> Seq Builder
renderDeclareVars s
s
as :: Seq Builder
as = s -> Seq Builder
forall s. RenderProblem s => s -> Seq Builder
renderAssertions s
s
sas :: Seq Builder
sas = s -> Seq Builder
forall s. RenderProblem s => s -> Seq Builder
renderSoftAssertions s
s
mins :: Seq Builder
mins = s -> Seq Builder
forall s. RenderProblem s => s -> Seq Builder
renderMinimizations s
s
maxs :: Seq Builder
maxs = s -> Seq Builder
forall s. RenderProblem s => s -> Seq Builder
renderMaximizations s
s
IO () -> (Debugger s -> IO ()) -> Maybe (Debugger s) -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
forall a. Monoid a => a
mempty (Seq Builder -> (Builder -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Seq Builder
os ((Builder -> IO ()) -> IO ())
-> (Debugger s -> Builder -> IO ()) -> Debugger s -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Debugger s -> Builder -> IO ()
forall s. Debugger s -> Builder -> IO ()
debugOption) Maybe (Debugger s)
debugger
Seq Builder -> (Builder -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Seq Builder
os (Solver -> Builder -> IO ()
Backend.command_ Solver
pSolver)
IO () -> (Debugger s -> IO ()) -> Maybe (Debugger s) -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
forall a. Monoid a => a
mempty (Debugger s -> Builder -> IO ()
forall s. Debugger s -> Builder -> IO ()
`debugLogic` Builder
l) Maybe (Debugger s)
debugger
Solver -> Builder -> IO ()
Backend.command_ Solver
pSolver Builder
l
IO () -> (Debugger s -> IO ()) -> Maybe (Debugger s) -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
forall a. Monoid a => a
mempty (Seq Builder -> (Builder -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Seq Builder
vs ((Builder -> IO ()) -> IO ())
-> (Debugger s -> Builder -> IO ()) -> Debugger s -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Debugger s -> Builder -> IO ()
forall s. Debugger s -> Builder -> IO ()
debugVar) Maybe (Debugger s)
debugger
Seq Builder -> (Builder -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Seq Builder
vs (Solver -> Builder -> IO ()
Backend.command_ Solver
pSolver)
IO () -> (Debugger s -> IO ()) -> Maybe (Debugger s) -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
forall a. Monoid a => a
mempty (Seq Builder -> (Builder -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Seq Builder
as ((Builder -> IO ()) -> IO ())
-> (Debugger s -> Builder -> IO ()) -> Debugger s -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Debugger s -> Builder -> IO ()
forall s. Debugger s -> Builder -> IO ()
debugAssert) Maybe (Debugger s)
debugger
Seq Builder -> (Builder -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Seq Builder
as (Solver -> Builder -> IO ()
Backend.command_ Solver
pSolver)
IO () -> (Debugger s -> IO ()) -> Maybe (Debugger s) -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
forall a. Monoid a => a
mempty (Seq Builder -> (Builder -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Seq Builder
sas ((Builder -> IO ()) -> IO ())
-> (Debugger s -> Builder -> IO ()) -> Debugger s -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Debugger s -> Builder -> IO ()
forall s. Debugger s -> Builder -> IO ()
debugAssertSoft) Maybe (Debugger s)
debugger
Seq Builder -> (Builder -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Seq Builder
sas (Solver -> Builder -> IO ()
Backend.command_ Solver
pSolver)
IO () -> (Debugger s -> IO ()) -> Maybe (Debugger s) -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
forall a. Monoid a => a
mempty (Seq Builder -> (Builder -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Seq Builder
mins ((Builder -> IO ()) -> IO ())
-> (Debugger s -> Builder -> IO ()) -> Debugger s -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Debugger s -> Builder -> IO ()
forall s. Debugger s -> Builder -> IO ()
debugMinimize) Maybe (Debugger s)
debugger
Seq Builder -> (Builder -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Seq Builder
mins (Solver -> Builder -> IO ()
Backend.command_ Solver
pSolver)
IO () -> (Debugger s -> IO ()) -> Maybe (Debugger s) -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
forall a. Monoid a => a
mempty (Seq Builder -> (Builder -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Seq Builder
maxs ((Builder -> IO ()) -> IO ())
-> (Debugger s -> Builder -> IO ()) -> Debugger s -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Debugger s -> Builder -> IO ()
forall s. Debugger s -> Builder -> IO ()
debugMaximize) Maybe (Debugger s)
debugger
Seq Builder -> (Builder -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Seq Builder
maxs (Solver -> Builder -> IO ()
Backend.command_ Solver
pSolver)
IO () -> (Debugger s -> IO ()) -> Maybe (Debugger s) -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
forall a. Monoid a => a
mempty (Debugger s -> Builder -> IO ()
forall s. Debugger s -> Builder -> IO ()
`debugCheckSat` Builder
"(check-sat)") Maybe (Debugger s)
debugger
ByteString
resultResponse <- Solver -> Builder -> IO ByteString
Backend.command Solver
pSolver Builder
renderCheckSat
IO () -> (Debugger s -> IO ()) -> Maybe (Debugger s) -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
forall a. Monoid a => a
mempty (Debugger s -> ByteString -> IO ()
forall s. Debugger s -> ByteString -> IO ()
`debugResultResponse` ByteString
resultResponse) Maybe (Debugger s)
debugger
IO () -> (Debugger s -> IO ()) -> Maybe (Debugger s) -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
forall a. Monoid a => a
mempty (Debugger s -> Builder -> IO ()
forall s. Debugger s -> Builder -> IO ()
`debugGetModel` Builder
"(get-model)") Maybe (Debugger s)
debugger
ByteString
modelResponse <- Solver -> Builder -> IO ByteString
Backend.command Solver
pSolver Builder
renderGetModel
IO () -> (Debugger s -> IO ()) -> Maybe (Debugger s) -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
forall a. Monoid a => a
mempty (Debugger s -> ByteString -> IO ()
forall s. Debugger s -> ByteString -> IO ()
`debugModelResponse` ByteString
modelResponse) Maybe (Debugger s)
debugger
(ByteString, ByteString) -> IO (ByteString, ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString
resultResponse, ByteString
modelResponse)
IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Handle -> IO ()
Process.close Handle
handle
case Parser Result -> ByteString -> Either [Char] Result
forall a. Parser a -> ByteString -> Either [Char] a
parseOnly Parser Result
resultParser (ByteString -> ByteString
toStrict ByteString
rawRes) of
Left [Char]
e -> [Char] -> m (Result, Solution)
forall a. HasCallStack => [Char] -> a
error ([Char] -> m (Result, Solution)) -> [Char] -> m (Result, Solution)
forall a b. (a -> b) -> a -> b
$ [Char]
"Language.Hasmtlib.Type.Solver#solver: Error when paring (check-sat) response: "
[Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
e [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
" | This is probably an error in Hasmtlib."
Right Result
res -> case Result
res of
Result
Unsat -> (Result, Solution) -> m (Result, Solution)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result
res, Solution
forall a. Monoid a => a
mempty)
Result
_ -> case Parser Solution -> ByteString -> Either [Char] Solution
forall a. Parser a -> ByteString -> Either [Char] a
parseOnly Parser Solution
anyModelParser (ByteString -> ByteString
toStrict ByteString
rawModel) of
Left [Char]
e -> [Char] -> m (Result, Solution)
forall a. HasCallStack => [Char] -> a
error ([Char] -> m (Result, Solution)) -> [Char] -> m (Result, Solution)
forall a b. (a -> b) -> a -> b
$ [Char]
"Language.Hasmtlib.Type.Solver#solver: Error when paring (get-model) response: "
[Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
e [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
" | This is probably an error in Hasmtlib."
Right Solution
sol -> (Result, Solution) -> m (Result, Solution)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result
res, Solution
sol)
timingout :: Int -> SolverConfig s -> SolverConfig s
timingout :: forall s. Int -> SolverConfig s -> SolverConfig s
timingout Int
t SolverConfig s
cfg = SolverConfig s
cfg SolverConfig s
-> (SolverConfig s -> SolverConfig s) -> SolverConfig s
forall a b. a -> (a -> b) -> b
& (Maybe Int -> Identity (Maybe Int))
-> SolverConfig s -> Identity (SolverConfig s)
forall s (f :: * -> *).
Functor f =>
(Maybe Int -> f (Maybe Int))
-> SolverConfig s -> f (SolverConfig s)
mTimeout ((Maybe Int -> Identity (Maybe Int))
-> SolverConfig s -> Identity (SolverConfig s))
-> Int -> SolverConfig s -> SolverConfig s
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ Int
t
debugging :: Debugger s -> SolverConfig s -> SolverConfig s
debugging :: forall s. Debugger s -> SolverConfig s -> SolverConfig s
debugging Debugger s
debugger SolverConfig s
cfg = SolverConfig s
cfg SolverConfig s
-> (SolverConfig s -> SolverConfig s) -> SolverConfig s
forall a b. a -> (a -> b) -> b
& (Maybe (Debugger s) -> Identity (Maybe (Debugger s)))
-> SolverConfig s -> Identity (SolverConfig s)
forall s s (f :: * -> *).
Functor f =>
(Maybe (Debugger s) -> f (Maybe (Debugger s)))
-> SolverConfig s -> f (SolverConfig s)
mDebugger ((Maybe (Debugger s) -> Identity (Maybe (Debugger s)))
-> SolverConfig s -> Identity (SolverConfig s))
-> Debugger s -> SolverConfig s -> SolverConfig s
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ Debugger s
debugger
solveWith :: (Default s, Monad m, Codec a) => Solver s m -> StateT s m a -> m (Result, Maybe (Decoded a))
solveWith :: forall s (m :: * -> *) a.
(Default s, Monad m, Codec a) =>
Solver s m -> StateT s m a -> m (Result, Maybe (Decoded a))
solveWith Solver s m
solving StateT s m a
m = do
(a
a, s
problem) <- StateT s m a -> s -> m (a, s)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT StateT s m a
m s
forall a. Default a => a
def
(Result
result, Solution
solution) <- Solver s m
solving s
problem
(Result, Maybe (Decoded a)) -> m (Result, Maybe (Decoded a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result
result, Solution -> a -> Maybe (Decoded a)
forall a. Codec a => Solution -> a -> Maybe (Decoded a)
decode Solution
solution a
a)
interactiveWith :: (MonadIO m, MonadBaseControl IO m) => SolverConfig Pipe -> StateT Pipe m a -> m (Maybe a)
interactiveWith :: forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
SolverConfig Pipe -> StateT Pipe m a -> m (Maybe a)
interactiveWith SolverConfig Pipe
cfg StateT Pipe m a
m = do
Handle
handle <- IO Handle -> m Handle
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Handle -> m Handle) -> IO Handle -> m Handle
forall a b. (a -> b) -> a -> b
$ Config -> IO Handle
Process.new (Config -> IO Handle) -> Config -> IO Handle
forall a b. (a -> b) -> a -> b
$ SolverConfig Pipe
cfgSolverConfig Pipe
-> Getting Config (SolverConfig Pipe) Config -> Config
forall s a. s -> Getting a s a -> a
^.Getting Config (SolverConfig Pipe) Config
forall s (f :: * -> *).
Functor f =>
(Config -> f Config) -> SolverConfig s -> f (SolverConfig s)
processConfig
Solver
processSolver <- IO Solver -> m Solver
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Solver -> m Solver) -> IO Solver -> m Solver
forall a b. (a -> b) -> a -> b
$ QueuingFlag -> Backend -> IO Solver
Backend.initSolver QueuingFlag
Backend.Queuing (Backend -> IO Solver) -> Backend -> IO Solver
forall a b. (a -> b) -> a -> b
$ Handle -> Backend
Process.toBackend Handle
handle
let timingOut :: m (a, Pipe) -> m (Maybe (a, Pipe))
timingOut m (a, Pipe)
io = case SolverConfig Pipe
cfgSolverConfig Pipe
-> Getting (Maybe Int) (SolverConfig Pipe) (Maybe Int) -> Maybe Int
forall s a. s -> Getting a s a -> a
^.Getting (Maybe Int) (SolverConfig Pipe) (Maybe Int)
forall s (f :: * -> *).
Functor f =>
(Maybe Int -> f (Maybe Int))
-> SolverConfig s -> f (SolverConfig s)
mTimeout of
Maybe Int
Nothing -> (a, Pipe) -> Maybe (a, Pipe)
forall a. a -> Maybe a
Just ((a, Pipe) -> Maybe (a, Pipe))
-> m (a, Pipe) -> m (Maybe (a, Pipe))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (a, Pipe)
io
Just Int
t -> Int -> m (a, Pipe) -> m (Maybe (a, Pipe))
forall (m :: * -> *) a.
MonadBaseControl IO m =>
Int -> m a -> m (Maybe a)
timeout Int
t m (a, Pipe)
io
Maybe (a, Pipe)
ma <- m (a, Pipe) -> m (Maybe (a, Pipe))
timingOut (m (a, Pipe) -> m (Maybe (a, Pipe)))
-> m (a, Pipe) -> m (Maybe (a, Pipe))
forall a b. (a -> b) -> a -> b
$ StateT Pipe m a -> Pipe -> m (a, Pipe)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT StateT Pipe m a
m (Pipe -> m (a, Pipe)) -> Pipe -> m (a, Pipe)
forall a b. (a -> b) -> a -> b
$ Int
-> Maybe [Char]
-> SharingMode
-> HashMap (StableName ()) (SomeKnownSMTSort Expr)
-> Seq (Seq (StableName ()))
-> Solver
-> Maybe (Debugger Pipe)
-> Pipe
Pipe Int
0 Maybe [Char]
forall a. Maybe a
Nothing SharingMode
forall a. Default a => a
def HashMap (StableName ()) (SomeKnownSMTSort Expr)
forall a. Monoid a => a
mempty Seq (Seq (StableName ()))
forall a. Monoid a => a
mempty Solver
processSolver (SolverConfig Pipe
cfgSolverConfig Pipe
-> Getting
(Maybe (Debugger Pipe)) (SolverConfig Pipe) (Maybe (Debugger Pipe))
-> Maybe (Debugger Pipe)
forall s a. s -> Getting a s a -> a
^.Getting
(Maybe (Debugger Pipe)) (SolverConfig Pipe) (Maybe (Debugger Pipe))
forall s s (f :: * -> *).
Functor f =>
(Maybe (Debugger s) -> f (Maybe (Debugger s)))
-> SolverConfig s -> f (SolverConfig s)
mDebugger)
IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Handle -> IO ()
Process.close Handle
handle
Maybe a -> m (Maybe a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m (Maybe a)) -> Maybe a -> m (Maybe a)
forall a b. (a -> b) -> a -> b
$ ((a, Pipe) -> a) -> Maybe (a, Pipe) -> Maybe a
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, Pipe) -> a
forall a b. (a, b) -> a
fst Maybe (a, Pipe)
ma
solveMinimized :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t, Orderable (Expr t))
=> Expr t
-> Maybe (Expr t -> Expr t)
-> Maybe (Solution -> IO ())
-> m (Result, Solution)
solveMinimized :: forall (m :: * -> *) (t :: SMTSort).
(MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t,
Orderable (Expr t)) =>
Expr t
-> Maybe (Expr t -> Expr t)
-> Maybe (Solution -> IO ())
-> m (Result, Solution)
solveMinimized = (Expr t -> Expr t -> Expr 'BoolSort)
-> Expr t
-> Maybe (Expr t -> Expr t)
-> Maybe (Solution -> IO ())
-> m (Result, Solution)
forall (m :: * -> *) (t :: SMTSort).
(MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t) =>
(Expr t -> Expr t -> Expr 'BoolSort)
-> Expr t
-> Maybe (Expr t -> Expr t)
-> Maybe (Solution -> IO ())
-> m (Result, Solution)
solveOptimized Expr t -> Expr t -> Expr 'BoolSort
forall a. Orderable a => a -> a -> Expr 'BoolSort
(<?)
solveMaximized :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t, Orderable (Expr t))
=> Expr t
-> Maybe (Expr t -> Expr t)
-> Maybe (Solution -> IO ())
-> m (Result, Solution)
solveMaximized :: forall (m :: * -> *) (t :: SMTSort).
(MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t,
Orderable (Expr t)) =>
Expr t
-> Maybe (Expr t -> Expr t)
-> Maybe (Solution -> IO ())
-> m (Result, Solution)
solveMaximized = (Expr t -> Expr t -> Expr 'BoolSort)
-> Expr t
-> Maybe (Expr t -> Expr t)
-> Maybe (Solution -> IO ())
-> m (Result, Solution)
forall (m :: * -> *) (t :: SMTSort).
(MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t) =>
(Expr t -> Expr t -> Expr 'BoolSort)
-> Expr t
-> Maybe (Expr t -> Expr t)
-> Maybe (Solution -> IO ())
-> m (Result, Solution)
solveOptimized Expr t -> Expr t -> Expr 'BoolSort
forall a. Orderable a => a -> a -> Expr 'BoolSort
(>?)
solveOptimized :: (MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t)
=> (Expr t -> Expr t -> Expr BoolSort)
-> Expr t
-> Maybe (Expr t -> Expr t)
-> Maybe (Solution -> IO ())
-> m (Result, Solution)
solveOptimized :: forall (m :: * -> *) (t :: SMTSort).
(MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t) =>
(Expr t -> Expr t -> Expr 'BoolSort)
-> Expr t
-> Maybe (Expr t -> Expr t)
-> Maybe (Solution -> IO ())
-> m (Result, Solution)
solveOptimized Expr t -> Expr t -> Expr 'BoolSort
op Expr t
goal Maybe (Expr t -> Expr t)
mStep Maybe (Solution -> IO ())
mDebug = Result -> Solution -> Expr t -> Int -> m (Result, Solution)
refine Result
Unsat Solution
forall a. Monoid a => a
mempty Expr t
goal Int
0
where
refine :: Result -> Solution -> Expr t -> Int -> m (Result, Solution)
refine Result
oldRes Solution
oldSol Expr t
target Int
n_pushes = do
Result
res <- m Result
forall s (m :: * -> *). MonadIncrSMT s m => m Result
checkSat
case Result
res of
Result
Sat -> do
Solution
sol <- m Solution
forall s (m :: * -> *). MonadIncrSMT s m => m Solution
getModel
case Solution -> Expr t -> Maybe (Decoded (Expr t))
forall a. Codec a => Solution -> a -> Maybe (Decoded a)
decode Solution
sol Expr t
target of
Maybe (Decoded (Expr t))
Nothing -> (Result, Solution) -> m (Result, Solution)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result
Sat, Solution
forall a. Monoid a => a
mempty)
Just Decoded (Expr t)
targetSol -> do
case Maybe (Solution -> IO ())
mDebug of
Maybe (Solution -> IO ())
Nothing -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just Solution -> IO ()
debug -> IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Solution -> IO ()
debug Solution
sol
m ()
forall s (m :: * -> *). MonadIncrSMT s m => m ()
push
let step :: Expr t -> Expr t
step = (Expr t -> Expr t) -> Maybe (Expr t -> Expr t) -> Expr t -> Expr t
forall a. a -> Maybe a -> a
fromMaybe Expr t -> Expr t
forall a. a -> a
id Maybe (Expr t -> Expr t)
mStep
Expr 'BoolSort -> m ()
forall s (m :: * -> *). MonadSMT s m => Expr 'BoolSort -> m ()
assert (Expr 'BoolSort -> m ()) -> Expr 'BoolSort -> m ()
forall a b. (a -> b) -> a -> b
$ Expr t
target Expr t -> Expr t -> Expr 'BoolSort
`op` Expr t -> Expr t
step (Decoded (Expr t) -> Expr t
forall a. Codec a => Decoded a -> a
encode Decoded (Expr t)
targetSol)
Result -> Solution -> Expr t -> Int -> m (Result, Solution)
refine Result
res Solution
sol Expr t
target (Int
n_pushes Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
Result
r -> do
if Int
n_pushes Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
1
then (Result, Solution) -> m (Result, Solution)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result
r, Solution
forall a. Monoid a => a
mempty)
else case Maybe (Expr t -> Expr t)
mStep of
Maybe (Expr t -> Expr t)
Nothing -> do
Int -> m () -> m ()
forall (m :: * -> *) a. Applicative m => Int -> m a -> m ()
replicateM_ Int
n_pushes m ()
forall s (m :: * -> *). MonadIncrSMT s m => m ()
pop
(Result, Solution) -> m (Result, Solution)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result
oldRes, Solution
oldSol)
Just Expr t -> Expr t
_ -> do
m ()
forall s (m :: * -> *). MonadIncrSMT s m => m ()
pop
(Result, Solution)
opt <- (Expr t -> Expr t -> Expr 'BoolSort)
-> Expr t
-> Maybe (Expr t -> Expr t)
-> Maybe (Solution -> IO ())
-> m (Result, Solution)
forall (m :: * -> *) (t :: SMTSort).
(MonadIncrSMT Pipe m, MonadIO m, KnownSMTSort t) =>
(Expr t -> Expr t -> Expr 'BoolSort)
-> Expr t
-> Maybe (Expr t -> Expr t)
-> Maybe (Solution -> IO ())
-> m (Result, Solution)
solveOptimized Expr t -> Expr t -> Expr 'BoolSort
op Expr t
goal Maybe (Expr t -> Expr t)
forall a. Maybe a
Nothing Maybe (Solution -> IO ())
mDebug
Int -> m () -> m ()
forall (m :: * -> *) a. Applicative m => Int -> m a -> m ()
replicateM_ (Int
n_pushes Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) m ()
forall s (m :: * -> *). MonadIncrSMT s m => m ()
pop
(Result, Solution) -> m (Result, Solution)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result, Solution)
opt