{-# LANGUAGE CPP #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
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, runSymbolic, State, getPathCondition, extendPathCondition
, inSMTMode, SBVRunMode(..), Kind(..), Outputtable(..), Result(..)
, SolverContext(..), internalVariable, internalConstraint, isCodeGenMode
, SBVType(..), newUninterpreted, addAxiom
, Quantifier(..), needsExistentials
, SMTLibPgm(..), SMTLibVersion(..), smtLibVersionExtension, smtLibReservedNames
, SolverCapabilities(..)
, extractSymbolicSimulationState
, SMTScript(..), Solver(..), SMTSolver(..), SMTResult(..), SMTModel(..), SMTConfig(..)
, declNewSArray, declNewSFunArray
, OptimizeStyle(..), Penalty(..), Objective(..)
, QueryState(..), Query(..), SMTProblem(..)
) where
import GHC.Generics (Generic)
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)
import qualified Data.Generics as G (Data(..))
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.Core.Operations
import Data.SBV.Control.Types
import Data.SBV.SMT.SMTLibNames
import Data.SBV.Utils.Lib
import Data.SBV.Utils.Boolean
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 }
deriving (Generic, NFData)
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 Boolean SBool where
true = SBV (svBool True)
false = SBV (svBool False)
bnot (SBV b) = SBV (svNot b)
SBV a &&& SBV b = SBV (svAnd a b)
SBV a ||| SBV b = SBV (svOr a b)
SBV a <+> SBV b = SBV (svXOr a b)
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 = SBV <$> (ask >>= liftIO . svMkSymVar mbQ k mbNm)
sbvToSymSW :: SBV a -> Symbolic SW
sbvToSymSW sbv = do
st <- ask
liftIO $ sbvToSW st sbv
class SolverContext m where
constrain :: SBool -> m ()
namedConstraint :: String -> SBool -> m ()
setInfo :: String -> [String] -> m ()
setOption :: SMTOption -> m ()
setLogic :: Logic -> m ()
setTimeOut :: Integer -> m ()
setTimeOut t = setOption $ OptionKeyword ":timeout" [show t]
setLogic = setOption . SetLogic
setInfo k = setOption . SetInfo k
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 <$> (ask >>= liftIO . svMkSymVar mbQ k 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) => Symbolic (array a b)
newArray :: (HasKind a, HasKind b) => String -> Symbolic (array a b)
readArray :: array a b -> SBV a -> SBV 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)
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) -> Symbolic (SArray a b)
declNewSArray mkNm = do
let aknd = kindOf (undefined :: a)
bknd = kindOf (undefined :: b)
arr <- newSArr (aknd, bknd) mkNm
return (SArray arr)
declNewSFunArray :: forall a b. (HasKind a, HasKind b) => Maybe String -> Symbolic (SFunArray a b)
declNewSFunArray mbNm = return $ SFunArray $ error . msg mbNm
where msg Nothing i = "Reading from an uninitialized array entry, index: " ++ show i
msg (Just nm) i = "Array " ++ show nm ++ ": Reading from an uninitialized array entry, index: " ++ show i
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
newtype SMTProblem = SMTProblem {smtLibPgm :: SMTConfig -> SMTLibPgm}