{-# LANGUAGE CPP #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE NamedFieldPuns #-}
module Data.SBV.Core.Data
( SBool, SWord8, SWord16, SWord32, SWord64
, SInt8, SInt16, SInt32, SInt64, SInteger, SReal, SFloat, SDouble
, nan, infinity, sNaN, sInfinity, RoundingMode(..), SRoundingMode
, sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero
, sRNE, sRNA, sRTP, sRTN, sRTZ
, SymWord(..)
, CW(..), CWVal(..), AlgReal(..), ExtCW(..), GeneralizedCW(..), isRegularCW, cwSameType, cwToBool
, mkConstCW ,liftCW2, mapCW, mapCW2
, SW(..), trueSW, falseSW, trueCW, falseCW, normCW
, SVal(..)
, SBV(..), NodeId(..), mkSymSBV
, ArrayContext(..), ArrayInfo, SymArray(..), SFunArray(..), mkSFunArray, SArray(..)
, sbvToSW, sbvToSymSW, forceSWArg
, SBVExpr(..), newExpr
, cache, Cached, uncache, uncacheAI, HasKind(..)
, Op(..), PBOp(..), FPOp(..), NamedSymVar, getTableIndex
, SBVPgm(..), Symbolic, SExecutable(..), runSymbolic, runSymbolic', State, getPathCondition, extendPathCondition
, inProofMode, SBVRunMode(..), Kind(..), Outputtable(..), Result(..)
, Logic(..), SMTLibLogic(..)
, addConstraint, internalVariable, internalConstraint, isCodeGenMode
, SBVType(..), newUninterpreted, addAxiom
, Quantifier(..), needsExistentials
, SMTLibPgm(..), SMTLibVersion(..), smtLibVersionExtension, smtLibReservedNames
, SolverCapabilities(..)
, extractSymbolicSimulationState
, SMTScript(..), Solver(..), SMTSolver(..), SMTResult(..), SMTModel(..), SMTConfig(..), getSBranchRunConfig
, declNewSArray, declNewSFunArray
, OptimizeStyle(..), Penalty(..), Objective(..)
, Tactic(..), CaseCond(..), SMTProblem(..), isParallelCaseAnywhere
) where
import Control.DeepSeq (NFData(..))
import Control.Monad.Reader (ask)
import Control.Monad.Trans (liftIO)
import Data.Int (Int8, Int16, Int32, Int64)
import Data.Word (Word8, Word16, Word32, Word64)
import Data.List (elemIndex, intercalate)
import Data.Maybe (fromMaybe)
import qualified Data.Set as Set (Set)
import qualified Data.Generics as G (Data(..))
import GHC.Stack.Compat
#if !MIN_VERSION_base(4,9,0)
import GHC.SrcLoc.Compat
#endif
import System.Random
import Data.SBV.Core.AlgReals
import Data.SBV.Core.Kind
import Data.SBV.Core.Concrete
import Data.SBV.Core.Symbolic
import Data.SBV.SMT.SMTLibNames
import Data.SBV.Utils.Lib
import Prelude ()
import Prelude.Compat
getPathCondition :: State -> SBool
getPathCondition st = SBV (getSValPathCondition st)
extendPathCondition :: State -> (SBool -> SBool) -> State
extendPathCondition st f = extendSValPathCondition st (unSBV . f . SBV)
newtype SBV a = SBV { unSBV :: SVal }
type SBool = SBV Bool
type SWord8 = SBV Word8
type SWord16 = SBV Word16
type SWord32 = SBV Word32
type SWord64 = SBV Word64
type SInt8 = SBV Int8
type SInt16 = SBV Int16
type SInt32 = SBV Int32
type SInt64 = SBV Int64
type SInteger = SBV Integer
type SReal = SBV AlgReal
type SFloat = SBV Float
type SDouble = SBV Double
nan :: Floating a => a
nan = 0/0
infinity :: Floating a => a
infinity = 1/0
sNaN :: (Floating a, SymWord a) => SBV a
sNaN = literal nan
sInfinity :: (Floating a, SymWord a) => SBV a
sInfinity = literal infinity
instance SymWord RoundingMode
type SRoundingMode = SBV RoundingMode
sRoundNearestTiesToEven :: SRoundingMode
sRoundNearestTiesToEven = literal RoundNearestTiesToEven
sRoundNearestTiesToAway :: SRoundingMode
sRoundNearestTiesToAway = literal RoundNearestTiesToAway
sRoundTowardPositive :: SRoundingMode
sRoundTowardPositive = literal RoundTowardPositive
sRoundTowardNegative :: SRoundingMode
sRoundTowardNegative = literal RoundTowardNegative
sRoundTowardZero :: SRoundingMode
sRoundTowardZero = literal RoundTowardZero
sRNE :: SRoundingMode
sRNE = sRoundNearestTiesToEven
sRNA :: SRoundingMode
sRNA = sRoundNearestTiesToAway
sRTP :: SRoundingMode
sRTP = sRoundTowardPositive
sRTN :: SRoundingMode
sRTN = sRoundTowardNegative
sRTZ :: SRoundingMode
sRTZ = sRoundTowardZero
instance Show (SBV a) where
show (SBV sv) = show sv
instance Eq (SBV a) where
SBV a == SBV b = a == b
SBV a /= SBV b = a /= b
instance HasKind (SBV a) where
kindOf (SBV (SVal k _)) = k
sbvToSW :: State -> SBV a -> IO SW
sbvToSW st (SBV s) = svToSW st s
mkSymSBV :: forall a. Maybe Quantifier -> Kind -> Maybe String -> Symbolic (SBV a)
mkSymSBV mbQ k mbNm = fmap SBV (svMkSymVar mbQ k mbNm)
sbvToSymSW :: SBV a -> Symbolic SW
sbvToSymSW sbv = do
st <- ask
liftIO $ sbvToSW st sbv
class Outputtable a where
output :: a -> Symbolic a
instance Outputtable (SBV a) where
output i = do
outputSVal (unSBV i)
return i
instance Outputtable a => Outputtable [a] where
output = mapM output
instance Outputtable () where
output = return
instance (Outputtable a, Outputtable b) => Outputtable (a, b) where
output = mlift2 (,) output output
instance (Outputtable a, Outputtable b, Outputtable c) => Outputtable (a, b, c) where
output = mlift3 (,,) output output output
instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d) => Outputtable (a, b, c, d) where
output = mlift4 (,,,) output output output output
instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d, Outputtable e) => Outputtable (a, b, c, d, e) where
output = mlift5 (,,,,) output output output output output
instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d, Outputtable e, Outputtable f) => Outputtable (a, b, c, d, e, f) where
output = mlift6 (,,,,,) output output output output output output
instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d, Outputtable e, Outputtable f, Outputtable g) => Outputtable (a, b, c, d, e, f, g) where
output = mlift7 (,,,,,,) output output output output output output output
instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d, Outputtable e, Outputtable f, Outputtable g, Outputtable h) => Outputtable (a, b, c, d, e, f, g, h) where
output = mlift8 (,,,,,,,) output output output output output output output output
class (HasKind a, Ord a) => SymWord a where
forall :: String -> Symbolic (SBV a)
forall_ :: Symbolic (SBV a)
mkForallVars :: Int -> Symbolic [SBV a]
exists :: String -> Symbolic (SBV a)
exists_ :: Symbolic (SBV a)
mkExistVars :: Int -> Symbolic [SBV a]
free :: String -> Symbolic (SBV a)
free_ :: Symbolic (SBV a)
mkFreeVars :: Int -> Symbolic [SBV a]
symbolic :: String -> Symbolic (SBV a)
symbolics :: [String] -> Symbolic [SBV a]
literal :: a -> SBV a
unliteral :: SBV a -> Maybe a
fromCW :: CW -> a
isConcrete :: SBV a -> Bool
isSymbolic :: SBV a -> Bool
isConcretely :: SBV a -> (a -> Bool) -> Bool
mkSymWord :: Maybe Quantifier -> Maybe String -> Symbolic (SBV a)
forall = mkSymWord (Just ALL) . Just
forall_ = mkSymWord (Just ALL) Nothing
exists = mkSymWord (Just EX) . Just
exists_ = mkSymWord (Just EX) Nothing
free = mkSymWord Nothing . Just
free_ = mkSymWord Nothing Nothing
mkForallVars n = mapM (const forall_) [1 .. n]
mkExistVars n = mapM (const exists_) [1 .. n]
mkFreeVars n = mapM (const free_) [1 .. n]
symbolic = free
symbolics = mapM symbolic
unliteral (SBV (SVal _ (Left c))) = Just $ fromCW c
unliteral _ = Nothing
isConcrete (SBV (SVal _ (Left _))) = True
isConcrete _ = False
isSymbolic = not . isConcrete
isConcretely s p
| Just i <- unliteral s = p i
| True = False
default literal :: Show a => a -> SBV a
literal x = let k@(KUserSort _ conts) = kindOf x
sx = show x
mbIdx = case conts of
Right xs -> sx `elemIndex` xs
_ -> Nothing
in SBV $ SVal k (Left (CW k (CWUserSort (mbIdx, sx))))
default fromCW :: Read a => CW -> a
fromCW (CW _ (CWUserSort (_, s))) = read s
fromCW cw = error $ "Cannot convert CW " ++ show cw ++ " to kind " ++ show (kindOf (undefined :: a))
default mkSymWord :: (Read a, G.Data a) => Maybe Quantifier -> Maybe String -> Symbolic (SBV a)
mkSymWord mbQ mbNm = SBV <$> mkSValUserSort k mbQ mbNm
where k = constructUKind (undefined :: a)
instance (Random a, SymWord a) => Random (SBV a) where
randomR (l, h) g = case (unliteral l, unliteral h) of
(Just lb, Just hb) -> let (v, g') = randomR (lb, hb) g in (literal (v :: a), g')
_ -> error "SBV.Random: Cannot generate random values with symbolic bounds"
random g = let (v, g') = random g in (literal (v :: a) , g')
class SymArray array where
newArray_ :: (HasKind a, HasKind b) => Maybe (SBV b) -> Symbolic (array a b)
newArray :: (HasKind a, HasKind b) => String -> Maybe (SBV b) -> Symbolic (array a b)
readArray :: array a b -> SBV a -> SBV b
resetArray :: SymWord b => array a b -> SBV b -> array a b
writeArray :: SymWord b => array a b -> SBV a -> SBV b -> array a b
mergeArrays :: SymWord b => SBV Bool -> array a b -> array a b -> array a b
newtype SArray a b = SArray { unSArray :: SArr }
instance (HasKind a, HasKind b) => Show (SArray a b) where
show SArray{} = "SArray<" ++ showType (undefined :: a) ++ ":" ++ showType (undefined :: b) ++ ">"
instance SymArray SArray where
newArray_ = declNewSArray (\t -> "array_" ++ show t)
newArray n = declNewSArray (const n)
readArray (SArray arr) (SBV a) = SBV (readSArr arr a)
resetArray (SArray arr) (SBV b) = SArray (resetSArr arr b)
writeArray (SArray arr) (SBV a) (SBV b) = SArray (writeSArr arr a b)
mergeArrays (SBV t) (SArray a) (SArray b) = SArray (mergeSArr t a b)
declNewSArray :: forall a b. (HasKind a, HasKind b) => (Int -> String) -> Maybe (SBV b) -> Symbolic (SArray a b)
declNewSArray mkNm mbInit = do
let aknd = kindOf (undefined :: a)
bknd = kindOf (undefined :: b)
arr <- newSArr (aknd, bknd) mkNm (fmap unSBV mbInit)
return (SArray arr)
declNewSFunArray :: forall a b. (HasKind a, HasKind b) => Maybe (SBV b) -> Symbolic (SFunArray a b)
declNewSFunArray mbiVal = return $ SFunArray $ const $ fromMaybe (error "Reading from an uninitialized array entry") mbiVal
newtype SFunArray a b = SFunArray (SBV a -> SBV b)
instance (HasKind a, HasKind b) => Show (SFunArray a b) where
show (SFunArray _) = "SFunArray<" ++ showType (undefined :: a) ++ ":" ++ showType (undefined :: b) ++ ">"
mkSFunArray :: (SBV a -> SBV b) -> SFunArray a b
mkSFunArray = SFunArray
addConstraint :: Maybe String -> Maybe Double -> SBool -> SBool -> Symbolic ()
addConstraint mn mt (SBV c) (SBV c') = addSValConstraint mn mt c c'
data CaseCond = NoCase
| CasePath [SW]
| CaseVac [SW] SW
| CaseCov [SW] [SW]
| CstrVac
| Opt [Objective (SW, SW)]
instance NFData CaseCond where
rnf NoCase = ()
rnf (CasePath ps) = rnf ps
rnf (CaseVac ps q) = rnf ps `seq` rnf q `seq` ()
rnf (CaseCov ps qs) = rnf ps `seq` rnf qs `seq` ()
rnf CstrVac = ()
rnf (Opt os) = rnf os `seq` ()
data SMTProblem = SMTProblem { smtInputs :: [(Quantifier, NamedSymVar)]
, smtSkolemMap :: [Either SW (SW, [SW])]
, kindsUsed :: Set.Set Kind
, smtAsserts :: [(String, Maybe CallStack, SW)]
, tactics :: [Tactic SW]
, objectives :: [Objective (SW, SW)]
, smtLibPgm :: SMTConfig -> CaseCond -> SMTLibPgm
}
instance NFData SMTProblem where
rnf (SMTProblem i m k a t o p) = rnf i `seq` rnf m `seq` rnf k `seq` rnf a `seq` rnf t `seq` rnf o `seq` rnf p `seq` ()
instance NFData (SBV a) where
rnf (SBV x) = rnf x `seq` ()
class SExecutable a where
sName_ :: a -> Symbolic ()
sName :: [String] -> a -> Symbolic ()
instance NFData a => SExecutable (Symbolic a) where
sName_ a = a >>= \r -> rnf r `seq` return ()
sName [] = sName_
sName xs = error $ "SBV.SExecutable.sName: Extra unmapped name(s): " ++ intercalate ", " xs
instance SExecutable (SBV a) where
sName_ v = sName_ (output v)
sName xs v = sName xs (output v)
instance SExecutable () where
sName_ () = sName_ (output ())
sName xs () = sName xs (output ())
instance SExecutable [SBV a] where
sName_ vs = sName_ (output vs)
sName xs vs = sName xs (output vs)
instance (NFData a, SymWord a, NFData b, SymWord b) => SExecutable (SBV a, SBV b) where
sName_ (a, b) = sName_ (output a >> output b)
sName _ = sName_
instance (NFData a, SymWord a, NFData b, SymWord b, NFData c, SymWord c) => SExecutable (SBV a, SBV b, SBV c) where
sName_ (a, b, c) = sName_ (output a >> output b >> output c)
sName _ = sName_
instance (NFData a, SymWord a, NFData b, SymWord b, NFData c, SymWord c, NFData d, SymWord d) => SExecutable (SBV a, SBV b, SBV c, SBV d) where
sName_ (a, b, c, d) = sName_ (output a >> output b >> output c >> output c >> output d)
sName _ = sName_
instance (NFData a, SymWord a, NFData b, SymWord b, NFData c, SymWord c, NFData d, SymWord d, NFData e, SymWord e) => SExecutable (SBV a, SBV b, SBV c, SBV d, SBV e) where
sName_ (a, b, c, d, e) = sName_ (output a >> output b >> output c >> output d >> output e)
sName _ = sName_
instance (NFData a, SymWord a, NFData b, SymWord b, NFData c, SymWord c, NFData d, SymWord d, NFData e, SymWord e, NFData f, SymWord f) => SExecutable (SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) where
sName_ (a, b, c, d, e, f) = sName_ (output a >> output b >> output c >> output d >> output e >> output f)
sName _ = sName_
instance (NFData a, SymWord a, NFData b, SymWord b, NFData c, SymWord c, NFData d, SymWord d, NFData e, SymWord e, NFData f, SymWord f, NFData g, SymWord g) => SExecutable (SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) where
sName_ (a, b, c, d, e, f, g) = sName_ (output a >> output b >> output c >> output d >> output e >> output f >> output g)
sName _ = sName_
instance (SymWord a, SExecutable p) => SExecutable (SBV a -> p) where
sName_ k = forall_ >>= \a -> sName_ $ k a
sName (s:ss) k = forall s >>= \a -> sName ss $ k a
sName [] k = sName_ k
instance (SymWord a, SymWord b, SExecutable p) => SExecutable ((SBV a, SBV b) -> p) where
sName_ k = forall_ >>= \a -> sName_ $ \b -> k (a, b)
sName (s:ss) k = forall s >>= \a -> sName ss $ \b -> k (a, b)
sName [] k = sName_ k
instance (SymWord a, SymWord b, SymWord c, SExecutable p) => SExecutable ((SBV a, SBV b, SBV c) -> p) where
sName_ k = forall_ >>= \a -> sName_ $ \b c -> k (a, b, c)
sName (s:ss) k = forall s >>= \a -> sName ss $ \b c -> k (a, b, c)
sName [] k = sName_ k
instance (SymWord a, SymWord b, SymWord c, SymWord d, SExecutable p) => SExecutable ((SBV a, SBV b, SBV c, SBV d) -> p) where
sName_ k = forall_ >>= \a -> sName_ $ \b c d -> k (a, b, c, d)
sName (s:ss) k = forall s >>= \a -> sName ss $ \b c d -> k (a, b, c, d)
sName [] k = sName_ k
instance (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, SExecutable p) => SExecutable ((SBV a, SBV b, SBV c, SBV d, SBV e) -> p) where
sName_ k = forall_ >>= \a -> sName_ $ \b c d e -> k (a, b, c, d, e)
sName (s:ss) k = forall s >>= \a -> sName ss $ \b c d e -> k (a, b, c, d, e)
sName [] k = sName_ k
instance (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, SymWord f, SExecutable p) => SExecutable ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) -> p) where
sName_ k = forall_ >>= \a -> sName_ $ \b c d e f -> k (a, b, c, d, e, f)
sName (s:ss) k = forall s >>= \a -> sName ss $ \b c d e f -> k (a, b, c, d, e, f)
sName [] k = sName_ k
instance (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, SymWord f, SymWord g, SExecutable p) => SExecutable ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) -> p) where
sName_ k = forall_ >>= \a -> sName_ $ \b c d e f g -> k (a, b, c, d, e, f, g)
sName (s:ss) k = forall s >>= \a -> sName ss $ \b c d e f g -> k (a, b, c, d, e, f, g)
sName [] k = sName_ k