{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module Data.SBV.Tools.Range (
Boundary(..), Range(..)
, ranges, rangesWith
) where
import Data.SBV
import Data.SBV.Control
import Data.SBV.Internals hiding (Range, free_)
data Boundary a = Unbounded
| Open a
| Closed a
isClosed :: Boundary a -> Bool
isClosed :: forall a. Boundary a -> Bool
isClosed Boundary a
Unbounded = Bool
False
isClosed (Open a
_) = Bool
False
isClosed (Closed a
_) = Bool
True
data Range a = Range (Boundary a) (Boundary a)
instance Show a => Show (Range a) where
show :: Range a -> String
show (Range Boundary a
l Boundary a
u) = forall {a}. Show a => Bool -> Boundary a -> String
sh Bool
True Boundary a
l forall a. [a] -> [a] -> [a]
++ String
"," forall a. [a] -> [a] -> [a]
++ forall {a}. Show a => Bool -> Boundary a -> String
sh Bool
False Boundary a
u
where sh :: Bool -> Boundary a -> String
sh Bool
onLeft Boundary a
b = case Boundary a
b of
Boundary a
Unbounded | Bool
onLeft -> String
"(-oo"
| Bool
True -> String
"oo)"
Open a
v | Bool
onLeft -> String
"(" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
v
| Bool
True -> forall a. Show a => a -> String
show a
v forall a. [a] -> [a] -> [a]
++ String
")"
Closed a
v | Bool
onLeft -> String
"[" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
v
| Bool
True -> forall a. Show a => a -> String
show a
v forall a. [a] -> [a] -> [a]
++ String
"]"
ranges :: forall a. (Ord a, Num a, SymVal a, SatModel a, Metric a, SymVal (MetricSpace a), SatModel (MetricSpace a)) => (SBV a -> SBool) -> IO [Range a]
ranges :: forall a.
(Ord a, Num a, SymVal a, SatModel a, Metric a,
SymVal (MetricSpace a), SatModel (MetricSpace a)) =>
(SBV a -> SBool) -> IO [Range a]
ranges = forall a.
(Ord a, Num a, SymVal a, SatModel a, Metric a,
SymVal (MetricSpace a), SatModel (MetricSpace a)) =>
SMTConfig -> (SBV a -> SBool) -> IO [Range a]
rangesWith SMTConfig
defaultSMTCfg
rangesWith :: forall a. (Ord a, Num a, SymVal a, SatModel a, Metric a, SymVal (MetricSpace a), SatModel (MetricSpace a)) => SMTConfig -> (SBV a -> SBool) -> IO [Range a]
rangesWith :: forall a.
(Ord a, Num a, SymVal a, SatModel a, Metric a,
SymVal (MetricSpace a), SatModel (MetricSpace a)) =>
SMTConfig -> (SBV a -> SBool) -> IO [Range a]
rangesWith SMTConfig
cfg SBV a -> SBool
prop = do Maybe (Range a)
mbBounds <- IO (Maybe (Range a))
getInitialBounds
case Maybe (Range a)
mbBounds of
Maybe (Range a)
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return []
Just Range a
r -> [Range a] -> [Range a] -> IO [Range a]
search [Range a
r] []
where getInitialBounds :: IO (Maybe (Range a))
getInitialBounds :: IO (Maybe (Range a))
getInitialBounds = do
let getGenVal :: GeneralizedCV -> Boundary a
getGenVal :: GeneralizedCV -> Boundary a
getGenVal (RegularCV CV
cv) = forall a. a -> Boundary a
Closed forall a b. (a -> b) -> a -> b
$ CV -> a
getRegVal CV
cv
getGenVal (ExtendedCV ExtCV
ecv) = ExtCV -> Boundary a
getExtVal ExtCV
ecv
getExtVal :: ExtCV -> Boundary a
getExtVal :: ExtCV -> Boundary a
getExtVal (Infinite Kind
_) = forall a. Boundary a
Unbounded
getExtVal (Epsilon Kind
k) = forall a. a -> Boundary a
Open forall a b. (a -> b) -> a -> b
$ CV -> a
getRegVal (forall a. Integral a => Kind -> a -> CV
mkConstCV Kind
k (Integer
0::Integer))
getExtVal i :: ExtCV
i@Interval{} = forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines [ String
"*** Data.SBV.ranges.getExtVal: Unexpected interval bounds!"
, String
"***"
, String
"*** Found bound: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show ExtCV
i
, String
"*** Please report this as a bug!"
]
getExtVal (BoundedCV CV
cv) = forall a. a -> Boundary a
Closed forall a b. (a -> b) -> a -> b
$ CV -> a
getRegVal CV
cv
getExtVal (AddExtCV ExtCV
a ExtCV
b) = ExtCV -> Boundary a
getExtVal ExtCV
a Boundary a -> Boundary a -> Boundary a
`addBound` ExtCV -> Boundary a
getExtVal ExtCV
b
getExtVal (MulExtCV ExtCV
a ExtCV
b) = ExtCV -> Boundary a
getExtVal ExtCV
a Boundary a -> Boundary a -> Boundary a
`mulBound` ExtCV -> Boundary a
getExtVal ExtCV
b
opBound :: (a -> a -> a) -> Boundary a -> Boundary a -> Boundary a
opBound :: (a -> a -> a) -> Boundary a -> Boundary a -> Boundary a
opBound a -> a -> a
f Boundary a
x Boundary a
y = case (forall {a}. Boundary a -> Maybe a
fromBound Boundary a
x, forall {a}. Boundary a -> Maybe a
fromBound Boundary a
y, forall a. Boundary a -> Bool
isClosed Boundary a
x Bool -> Bool -> Bool
&& forall a. Boundary a -> Bool
isClosed Boundary a
y) of
(Just a
a, Just a
b, Bool
True) -> forall a. a -> Boundary a
Closed forall a b. (a -> b) -> a -> b
$ a
a a -> a -> a
`f` a
b
(Just a
a, Just a
b, Bool
False) -> forall a. a -> Boundary a
Open forall a b. (a -> b) -> a -> b
$ a
a a -> a -> a
`f` a
b
(Maybe a, Maybe a, Bool)
_ -> forall a. Boundary a
Unbounded
where fromBound :: Boundary a -> Maybe a
fromBound Boundary a
Unbounded = forall a. Maybe a
Nothing
fromBound (Open a
a) = forall a. a -> Maybe a
Just a
a
fromBound (Closed a
a) = forall a. a -> Maybe a
Just a
a
addBound, mulBound :: Boundary a -> Boundary a -> Boundary a
addBound :: Boundary a -> Boundary a -> Boundary a
addBound = (a -> a -> a) -> Boundary a -> Boundary a -> Boundary a
opBound forall a. Num a => a -> a -> a
(+)
mulBound :: Boundary a -> Boundary a -> Boundary a
mulBound = (a -> a -> a) -> Boundary a -> Boundary a -> Boundary a
opBound forall a. Num a => a -> a -> a
(*)
getRegVal :: CV -> a
getRegVal :: CV -> a
getRegVal CV
cv = case forall a. SatModel a => [CV] -> Maybe (a, [CV])
parseCVs [CV
cv] of
Just (MetricSpace a
v :: MetricSpace a, []) -> case forall a. SymVal a => SBV a -> Maybe a
unliteral (forall a. Metric a => SBV (MetricSpace a) -> SBV a
fromMetricSpace (forall a. SymVal a => a -> SBV a
literal MetricSpace a
v)) of
Maybe a
Nothing -> forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ String
"Data.SBV.ranges.getRegVal: Cannot extract value from metric space equivalent: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show CV
cv
Just a
r -> a
r
Maybe (MetricSpace a, [CV])
_ -> forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ String
"Data.SBV.ranges.getRegVal: Cannot parse " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show CV
cv
getBound :: (String -> SBV a -> SymbolicT IO b) -> IO (Maybe GeneralizedCV)
getBound String -> SBV a -> SymbolicT IO b
cstr = do let objName :: String
objName = String
"boundValue"
res :: OptimizeResult
res@(LexicographicResult SMTResult
m) <- forall a.
Provable a =>
SMTConfig -> OptimizeStyle -> a -> IO OptimizeResult
optimizeWith SMTConfig
cfg OptimizeStyle
Lexicographic forall a b. (a -> b) -> a -> b
$ do SBV a
x <- forall a. SymVal a => Symbolic (SBV a)
free_
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain forall a b. (a -> b) -> a -> b
$ SBV a -> SBool
prop SBV a
x
String -> SBV a -> SymbolicT IO b
cstr String
objName SBV a
x
case SMTResult
m of
Unsatisfiable{} -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
Unknown{} -> forall a. HasCallStack => String -> a
error String
"Solver said Unknown!"
ProofError{} -> forall a. HasCallStack => String -> a
error (forall a. Show a => a -> String
show OptimizeResult
res)
SMTResult
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Modelable a => String -> a -> Maybe GeneralizedCV
getModelObjectiveValue String
objName SMTResult
m
Maybe GeneralizedCV
mi <- forall {b}.
MProvable IO (SymbolicT IO b) =>
(String -> SBV a -> SymbolicT IO b) -> IO (Maybe GeneralizedCV)
getBound forall a. Metric a => String -> SBV a -> SymbolicT IO ()
minimize
Maybe GeneralizedCV
ma <- forall {b}.
MProvable IO (SymbolicT IO b) =>
(String -> SBV a -> SymbolicT IO b) -> IO (Maybe GeneralizedCV)
getBound forall a. Metric a => String -> SBV a -> SymbolicT IO ()
maximize
case (Maybe GeneralizedCV
mi, Maybe GeneralizedCV
ma) of
(Just GeneralizedCV
minV, Just GeneralizedCV
maxV) -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. Boundary a -> Boundary a -> Range a
Range (GeneralizedCV -> Boundary a
getGenVal GeneralizedCV
minV) (GeneralizedCV -> Boundary a
getGenVal GeneralizedCV
maxV)
(Maybe GeneralizedCV, Maybe GeneralizedCV)
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
witness :: Range a -> Symbolic (SBV a)
witness :: Range a -> Symbolic (SBV a)
witness (Range Boundary a
lo Boundary a
hi) = do SBV a
x :: SBV a <- forall a. SymVal a => Symbolic (SBV a)
free_
let restrict :: Boundary a
-> (SBV a -> SBV a -> SBool) -> (SBV a -> SBV a -> SBool) -> SBool
restrict Boundary a
v SBV a -> SBV a -> SBool
open SBV a -> SBV a -> SBool
closed = case Boundary a
v of
Boundary a
Unbounded -> SBool
sTrue
Open a
a -> SBV a
x SBV a -> SBV a -> SBool
`open` forall a. SymVal a => a -> SBV a
literal a
a
Closed a
a -> SBV a
x SBV a -> SBV a -> SBool
`closed` forall a. SymVal a => a -> SBV a
literal a
a
lower :: SBool
lower = forall {a}.
SymVal a =>
Boundary a
-> (SBV a -> SBV a -> SBool) -> (SBV a -> SBV a -> SBool) -> SBool
restrict Boundary a
lo forall a. OrdSymbolic a => a -> a -> SBool
(.>) forall a. OrdSymbolic a => a -> a -> SBool
(.>=)
upper :: SBool
upper = forall {a}.
SymVal a =>
Boundary a
-> (SBV a -> SBV a -> SBool) -> (SBV a -> SBV a -> SBool) -> SBool
restrict Boundary a
hi forall a. OrdSymbolic a => a -> a -> SBool
(.<) forall a. OrdSymbolic a => a -> a -> SBool
(.<=)
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain forall a b. (a -> b) -> a -> b
$ SBool
lower SBool -> SBool -> SBool
.&& SBool
upper
forall (m :: * -> *) a. Monad m => a -> m a
return SBV a
x
isFeasible :: Range a -> IO Bool
isFeasible :: Range a -> IO Bool
isFeasible Range a
r = forall a. SMTConfig -> Symbolic a -> IO a
runSMTWith SMTConfig
cfg forall a b. (a -> b) -> a -> b
$ do SBV a
_ <- Range a -> Symbolic (SBV a)
witness Range a
r
forall a. Query a -> Symbolic a
query forall a b. (a -> b) -> a -> b
$ do CheckSatResult
cs <- Query CheckSatResult
checkSat
case CheckSatResult
cs of
CheckSatResult
Unsat -> forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
DSat{} -> forall a. HasCallStack => String -> a
error String
"Data.SBV.interval.isFeasible: Solver returned a delta-satisfiable result!"
CheckSatResult
Unk -> forall a. HasCallStack => String -> a
error String
"Data.SBV.interval.isFeasible: Solver said unknown!"
CheckSatResult
Sat -> forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
bisect :: Range a -> IO (Maybe [Range a])
bisect :: Range a -> IO (Maybe [Range a])
bisect r :: Range a
r@(Range Boundary a
lo Boundary a
hi) = forall a. SMTConfig -> Symbolic a -> IO a
runSMTWith SMTConfig
cfg forall a b. (a -> b) -> a -> b
$ do SBV a
x <- Range a -> Symbolic (SBV a)
witness Range a
r
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain forall a b. (a -> b) -> a -> b
$ SBool -> SBool
sNot (SBV a -> SBool
prop SBV a
x)
forall a. Query a -> Symbolic a
query forall a b. (a -> b) -> a -> b
$ do CheckSatResult
cs <- Query CheckSatResult
checkSat
case CheckSatResult
cs of
CheckSatResult
Unsat -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
DSat{} -> forall a. HasCallStack => String -> a
error String
"Data.SBV.interval.bisect: Solver returned a delta-satisfiable result!"
CheckSatResult
Unk -> forall a. HasCallStack => String -> a
error String
"Data.SBV.interval.bisect: Solver said unknown!"
CheckSatResult
Sat -> do Boundary a
midV <- forall a. a -> Boundary a
Open forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. SymVal a => SBV a -> Query a
getValue SBV a
x
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just [forall a. Boundary a -> Boundary a -> Range a
Range Boundary a
lo Boundary a
midV, forall a. Boundary a -> Boundary a -> Range a
Range Boundary a
midV Boundary a
hi]
search :: [Range a] -> [Range a] -> IO [Range a]
search :: [Range a] -> [Range a] -> IO [Range a]
search [] [Range a]
sofar = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [a]
reverse [Range a]
sofar
search (Range a
c:[Range a]
cs) [Range a]
sofar = do Bool
feasible <- Range a -> IO Bool
isFeasible Range a
c
if Bool
feasible
then do Maybe [Range a]
mbCS <- Range a -> IO (Maybe [Range a])
bisect Range a
c
case Maybe [Range a]
mbCS of
Maybe [Range a]
Nothing -> [Range a] -> [Range a] -> IO [Range a]
search [Range a]
cs (Range a
cforall a. a -> [a] -> [a]
:[Range a]
sofar)
Just [Range a]
xss -> [Range a] -> [Range a] -> IO [Range a]
search ([Range a]
xss forall a. [a] -> [a] -> [a]
++ [Range a]
cs) [Range a]
sofar
else [Range a] -> [Range a] -> IO [Range a]
search [Range a]
cs [Range a]
sofar
{-# ANN rangesWith ("HLint: ignore Use fromMaybe" :: String) #-}