{-# OPTIONS_GHC -Wall -Werror #-}
module Data.SBV.Tools.BVOptimize (
maxBV, maxBVWith
, minBV, minBVWith
) where
import Control.Monad
import Data.SBV
import Data.SBV.Control
maxBV :: SFiniteBits a
=> Bool
-> SBV a
-> Symbolic SatResult
maxBV :: forall a. SFiniteBits a => Bool -> SBV a -> Symbolic SatResult
maxBV = SMTConfig -> Bool -> SBV a -> Symbolic SatResult
forall a.
SFiniteBits a =>
SMTConfig -> Bool -> SBV a -> Symbolic SatResult
maxBVWith SMTConfig
defaultSMTCfg
maxBVWith :: SFiniteBits a => SMTConfig -> Bool-> SBV a -> Symbolic SatResult
maxBVWith :: forall a.
SFiniteBits a =>
SMTConfig -> Bool -> SBV a -> Symbolic SatResult
maxBVWith = Bool -> SMTConfig -> Bool -> SBV a -> Symbolic SatResult
forall a.
SFiniteBits a =>
Bool -> SMTConfig -> Bool -> SBV a -> Symbolic SatResult
minMaxBV Bool
True
minBV :: SFiniteBits a
=> Bool
-> SBV a
-> Symbolic SatResult
minBV :: forall a. SFiniteBits a => Bool -> SBV a -> Symbolic SatResult
minBV = SMTConfig -> Bool -> SBV a -> Symbolic SatResult
forall a.
SFiniteBits a =>
SMTConfig -> Bool -> SBV a -> Symbolic SatResult
minBVWith SMTConfig
defaultSMTCfg
minBVWith :: SFiniteBits a => SMTConfig -> Bool-> SBV a -> Symbolic SatResult
minBVWith :: forall a.
SFiniteBits a =>
SMTConfig -> Bool -> SBV a -> Symbolic SatResult
minBVWith = Bool -> SMTConfig -> Bool -> SBV a -> Symbolic SatResult
forall a.
SFiniteBits a =>
Bool -> SMTConfig -> Bool -> SBV a -> Symbolic SatResult
minMaxBV Bool
False
minMaxBV :: SFiniteBits a => Bool -> SMTConfig -> Bool -> SBV a -> Symbolic SatResult
minMaxBV :: forall a.
SFiniteBits a =>
Bool -> SMTConfig -> Bool -> SBV a -> Symbolic SatResult
minMaxBV Bool
isMax SMTConfig
cfg Bool
getUC SBV a
v
| SBV a -> Bool
forall a. HasKind a => a -> Bool
hasSign SBV a
v
= [Char] -> Symbolic SatResult
forall a. HasCallStack => [Char] -> a
error ([Char] -> Symbolic SatResult) -> [Char] -> Symbolic SatResult
forall a b. (a -> b) -> a -> b
$ [Char]
"minMaxBV works on unsigned bitvectors, received: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Kind -> [Char]
forall a. Show a => a -> [Char]
show (SBV a -> Kind
forall a. HasKind a => a -> Kind
kindOf SBV a
v)
| Bool
True
= do Bool -> SymbolicT IO () -> SymbolicT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
getUC (SymbolicT IO () -> SymbolicT IO ())
-> SymbolicT IO () -> SymbolicT IO ()
forall a b. (a -> b) -> a -> b
$ SMTOption -> SymbolicT IO ()
forall (m :: * -> *). SolverContext m => SMTOption -> m ()
setOption (SMTOption -> SymbolicT IO ()) -> SMTOption -> SymbolicT IO ()
forall a b. (a -> b) -> a -> b
$ Bool -> SMTOption
ProduceUnsatCores Bool
True
Query SatResult -> Symbolic SatResult
forall a. Query a -> Symbolic a
query (Query SatResult -> Symbolic SatResult)
-> Query SatResult -> Symbolic SatResult
forall a b. (a -> b) -> a -> b
$ [SBool] -> Query SatResult
go (SBV a -> [SBool]
forall a. SFiniteBits a => SBV a -> [SBool]
blastBE SBV a
v)
where uc :: QueryT IO (Maybe [[Char]])
uc | Bool
getUC = [[Char]] -> Maybe [[Char]]
forall a. a -> Maybe a
Just ([[Char]] -> Maybe [[Char]])
-> QueryT IO [[Char]] -> QueryT IO (Maybe [[Char]])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryT IO [[Char]]
getUnsatCore
| Bool
True = Maybe [[Char]] -> QueryT IO (Maybe [[Char]])
forall a. a -> QueryT IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe [[Char]]
forall a. Maybe a
Nothing
rSat :: Query SatResult
rSat = SMTResult -> SatResult
SatResult (SMTResult -> SatResult)
-> (SMTModel -> SMTResult) -> SMTModel -> SatResult
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SMTConfig -> SMTModel -> SMTResult
Satisfiable SMTConfig
cfg (SMTModel -> SatResult) -> QueryT IO SMTModel -> Query SatResult
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryT IO SMTModel
getModel
rUnk :: Query SatResult
rUnk = SMTResult -> SatResult
SatResult (SMTResult -> SatResult)
-> (SMTReasonUnknown -> SMTResult) -> SMTReasonUnknown -> SatResult
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SMTConfig -> SMTReasonUnknown -> SMTResult
Unknown SMTConfig
cfg (SMTReasonUnknown -> SatResult)
-> QueryT IO SMTReasonUnknown -> Query SatResult
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryT IO SMTReasonUnknown
getUnknownReason
rUnsat :: Query SatResult
rUnsat = SMTResult -> SatResult
SatResult (SMTResult -> SatResult)
-> (Maybe [[Char]] -> SMTResult) -> Maybe [[Char]] -> SatResult
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SMTConfig -> Maybe [[Char]] -> SMTResult
Unsatisfiable SMTConfig
cfg (Maybe [[Char]] -> SatResult)
-> QueryT IO (Maybe [[Char]]) -> Query SatResult
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryT IO (Maybe [[Char]])
uc
go :: [SBool] -> Query SatResult
go :: [SBool] -> Query SatResult
go [] = do r <- Query CheckSatResult
checkSat
case r of
CheckSatResult
Sat -> Query SatResult
rSat
CheckSatResult
Unsat -> Query SatResult
rUnsat
CheckSatResult
Unk -> Query SatResult
rUnk
DSat {} -> [Char] -> Query SatResult
forall a. HasCallStack => [Char] -> a
error [Char]
"minMaxBV: Unexpected DSat result"
go (SBool
b:[SBool]
bs) = do Int -> Query ()
push Int
1
if Bool
isMax then SBool -> Query ()
forall a. QuantifiedBool a => a -> Query ()
forall (m :: * -> *) a.
(SolverContext m, QuantifiedBool a) =>
a -> m ()
constrain SBool
b
else SBool -> Query ()
forall a. QuantifiedBool a => a -> Query ()
forall (m :: * -> *) a.
(SolverContext m, QuantifiedBool a) =>
a -> m ()
constrain (SBool -> Query ()) -> SBool -> Query ()
forall a b. (a -> b) -> a -> b
$ SBool -> SBool
sNot SBool
b
r <- Query CheckSatResult
checkSat
case r of
CheckSatResult
Sat -> [SBool] -> Query SatResult
go [SBool]
bs Query SatResult
-> (SatResult -> Query SatResult) -> Query SatResult
forall a b. QueryT IO a -> (a -> QueryT IO b) -> QueryT IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \SatResult
res -> Int -> Query ()
pop Int
1 Query () -> Query SatResult -> Query SatResult
forall a b. QueryT IO a -> QueryT IO b -> QueryT IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> SatResult -> Query SatResult
forall a. a -> QueryT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return SatResult
res
CheckSatResult
Unsat -> Int -> Query ()
pop Int
1 Query () -> Query SatResult -> Query SatResult
forall a b. QueryT IO a -> QueryT IO b -> QueryT IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [SBool] -> Query SatResult
go [SBool]
bs
CheckSatResult
Unk -> Int -> Query ()
pop Int
1 Query () -> Query SatResult -> Query SatResult
forall a b. QueryT IO a -> QueryT IO b -> QueryT IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Query SatResult
rUnk
DSat{} -> [Char] -> Query SatResult
forall a. HasCallStack => [Char] -> a
error [Char]
"minMaxBV: Unexpected DSat result"