{-# LANGUAGE CPP #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module Data.SBV.Core.Data
( SBool, SWord8, SWord16, SWord32, SWord64
, SInt8, SInt16, SInt32, SInt64, SInteger, SReal, SFloat, SDouble, SChar, SString, SList
, SEither, SMaybe
, STuple, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7, STuple8
, RCSet(..), SSet
, nan, infinity, sNaN, sInfinity, RoundingMode(..), SRoundingMode
, sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero
, sRNE, sRNA, sRTP, sRTN, sRTZ
, SymVal(..)
, CV(..), CVal(..), AlgReal(..), AlgRealPoly(..), ExtCV(..), GeneralizedCV(..), isRegularCV, cvSameType, cvToBool
, mkConstCV ,liftCV2, mapCV, mapCV2
, SV(..), trueSV, falseSV, trueCV, falseCV, normCV
, SVal(..)
, sTrue, sFalse, sNot, (.&&), (.||), (.<+>), (.~&), (.~|), (.=>), (.<=>), sAnd, sOr, sAny, sAll, fromBool
, SBV(..), NodeId(..), mkSymSBV
, ArrayContext(..), ArrayInfo, SymArray(..), SFunArray(..), SArray(..)
, sbvToSV, sbvToSymSV, forceSVArg
, SBVExpr(..), newExpr
, cache, Cached, uncache, uncacheAI, HasKind(..)
, Op(..), PBOp(..), FPOp(..), StrOp(..), SeqOp(..), RegExp(..), 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(..)
, OptimizeStyle(..), Penalty(..), Objective(..)
, QueryState(..), QueryT(..), SMTProblem(..)
) where
import GHC.Generics (Generic)
import GHC.Exts (IsList(..))
import Control.DeepSeq (NFData(..))
import Control.Monad.Trans (liftIO)
import Data.Int (Int8, Int16, Int32, Int64)
import Data.Word (Word8, Word16, Word32, Word64)
import Data.List (elemIndex)
import Data.Maybe (fromMaybe)
import Data.Proxy
import Data.Typeable (Typeable)
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
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
type SChar = SBV Char
type SString = SBV String
type SList a = SBV [a]
type SEither a b = SBV (Either a b)
type SMaybe a = SBV (Maybe a)
type SSet a = SBV (RCSet a)
type STuple a b = SBV (a, b)
type STuple2 a b = SBV (a, b)
type STuple3 a b c = SBV (a, b, c)
type STuple4 a b c d = SBV (a, b, c, d)
type STuple5 a b c d e = SBV (a, b, c, d, e)
type STuple6 a b c d e f = SBV (a, b, c, d, e, f)
type STuple7 a b c d e f g = SBV (a, b, c, d, e, f, g)
type STuple8 a b c d e f g h = SBV (a, b, c, d, e, f, g, h)
instance SymVal [a] => IsList (SList a) where
type Item (SList a) = a
fromList = literal
toList x = fromMaybe (error "IsList.toList used in a symbolic context!") (unliteral x)
nan :: Floating a => a
nan = 0/0
infinity :: Floating a => a
infinity = 1/0
sNaN :: (Floating a, SymVal a) => SBV a
sNaN = literal nan
sInfinity :: (Floating a, SymVal a) => SBV a
sInfinity = literal infinity
newtype SMTProblem = SMTProblem {smtLibPgm :: SMTConfig -> SMTLibPgm}
sTrue :: SBool
sTrue = SBV (svBool True)
sFalse :: SBool
sFalse = SBV (svBool False)
sNot :: SBool -> SBool
sNot (SBV b) = SBV (svNot b)
infixr 3 .&&
(.&&) :: SBool -> SBool -> SBool
SBV x .&& SBV y = SBV (x `svAnd` y)
infixr 2 .||
(.||) :: SBool -> SBool -> SBool
SBV x .|| SBV y = SBV (x `svOr` y)
infixl 6 .<+>
(.<+>) :: SBool -> SBool -> SBool
SBV x .<+> SBV y = SBV (x `svXOr` y)
infixr 3 .~&
(.~&) :: SBool -> SBool -> SBool
x .~& y = sNot (x .&& y)
infixr 2 .~|
(.~|) :: SBool -> SBool -> SBool
x .~| y = sNot (x .|| y)
infixr 1 .=>
(.=>) :: SBool -> SBool -> SBool
x .=> y = sNot x .|| y
infixr 1 .<=>
(.<=>) :: SBool -> SBool -> SBool
x .<=> y = (x .&& y) .|| (sNot x .&& sNot y)
fromBool :: Bool -> SBool
fromBool True = sTrue
fromBool False = sFalse
sAnd :: [SBool] -> SBool
sAnd = foldr (.&&) sTrue
sOr :: [SBool] -> SBool
sOr = foldr (.||) sFalse
sAny :: (a -> SBool) -> [a] -> SBool
sAny f = sOr . map f
sAll :: (a -> SBool) -> [a] -> SBool
sAll f = sAnd . map f
instance SymVal 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 a => HasKind (SBV a) where
kindOf _ = kindOf (Proxy @a)
sbvToSV :: State -> SBV a -> IO SV
sbvToSV st (SBV s) = svToSV st s
mkSymSBV :: forall a m. MonadSymbolic m => Maybe Quantifier -> Kind -> Maybe String -> m (SBV a)
mkSymSBV mbQ k mbNm = SBV <$> (symbolicEnv >>= liftIO . svMkSymVar mbQ k mbNm)
sbvToSymSV :: MonadSymbolic m => SBV a -> m SV
sbvToSymSV sbv = do
st <- symbolicEnv
liftIO $ sbvToSV st sbv
class SolverContext m where
constrain :: SBool -> m ()
softConstrain :: SBool -> m ()
namedConstraint :: String -> SBool -> m ()
constrainWithAttribute :: [(String, String)] -> SBool -> m ()
setInfo :: String -> [String] -> m ()
setOption :: SMTOption -> m ()
setLogic :: Logic -> m ()
setTimeOut :: Integer -> m ()
contextState :: m State
{-# MINIMAL constrain, softConstrain, namedConstraint, constrainWithAttribute, setOption, contextState #-}
setTimeOut t = setOption $ OptionKeyword ":timeout" [show t]
setLogic = setOption . SetLogic
setInfo k = setOption . SetInfo k
class Outputtable a where
output :: MonadSymbolic m => a -> m 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, Typeable a) => SymVal a where
mkSymVal :: MonadSymbolic m => Maybe Quantifier -> Maybe String -> m (SBV a)
literal :: a -> SBV a
fromCV :: CV -> a
isConcretely :: SBV a -> (a -> Bool) -> Bool
default mkSymVal :: (MonadSymbolic m, Read a, G.Data a) => Maybe Quantifier -> Maybe String -> m (SBV a)
mkSymVal mbQ mbNm = SBV <$> (symbolicEnv >>= liftIO . svMkSymVar mbQ k mbNm)
where
k = constructUKind (undefined :: a)
default literal :: Show a => a -> SBV a
literal x = let k@(KUninterpreted _ conts) = kindOf x
sx = show x
mbIdx = case conts of
Right xs -> sx `elemIndex` xs
_ -> Nothing
in SBV $ SVal k (Left (CV k (CUserSort (mbIdx, sx))))
default fromCV :: Read a => CV -> a
fromCV (CV _ (CUserSort (_, s))) = read s
fromCV cv = error $ "Cannot convert CV " ++ show cv ++ " to kind " ++ show (kindOf (Proxy @a))
isConcretely s p
| Just i <- unliteral s = p i
| True = False
forall :: MonadSymbolic m => String -> m (SBV a)
forall = mkSymVal (Just ALL) . Just
forall_ :: MonadSymbolic m => m (SBV a)
forall_ = mkSymVal (Just ALL) Nothing
mkForallVars :: MonadSymbolic m => Int -> m [SBV a]
mkForallVars n = mapM (const forall_) [1 .. n]
exists :: MonadSymbolic m => String -> m (SBV a)
exists = mkSymVal (Just EX) . Just
exists_ :: MonadSymbolic m => m (SBV a)
exists_ = mkSymVal (Just EX) Nothing
mkExistVars :: MonadSymbolic m => Int -> m [SBV a]
mkExistVars n = mapM (const exists_) [1 .. n]
free :: MonadSymbolic m => String -> m (SBV a)
free = mkSymVal Nothing . Just
free_ :: MonadSymbolic m => m (SBV a)
free_ = mkSymVal Nothing Nothing
mkFreeVars :: MonadSymbolic m => Int -> m [SBV a]
mkFreeVars n = mapM (const free_) [1 .. n]
symbolic :: MonadSymbolic m => String -> m (SBV a)
symbolic = free
symbolics :: MonadSymbolic m => [String] -> m [SBV a]
symbolics = mapM symbolic
unliteral :: SBV a -> Maybe a
unliteral (SBV (SVal _ (Left c))) = Just $ fromCV c
unliteral _ = Nothing
isConcrete :: SBV a -> Bool
isConcrete (SBV (SVal _ (Left _))) = True
isConcrete _ = False
isSymbolic :: SBV a -> Bool
isSymbolic = not . isConcrete
instance (Random a, SymVal 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_ :: (MonadSymbolic m, HasKind a, HasKind b) => Maybe (SBV b) -> m (array a b)
newArray :: (MonadSymbolic m, HasKind a, HasKind b) => String -> Maybe (SBV b) -> m (array a b)
readArray :: array a b -> SBV a -> SBV b
writeArray :: SymVal b => array a b -> SBV a -> SBV b -> array a b
mergeArrays :: SymVal b => SBV Bool -> array a b -> array a b -> array a b
newArrayInState :: (HasKind a, HasKind b) => Maybe String -> Maybe (SBV b) -> State -> IO (array a b)
{-# MINIMAL readArray, writeArray, mergeArrays, ((newArray_, newArray) | newArrayInState) #-}
newArray_ mbVal = symbolicEnv >>= liftIO . newArrayInState Nothing mbVal
newArray nm mbVal = symbolicEnv >>= liftIO . newArrayInState (Just nm) mbVal
newArrayInState = error "undefined: newArrayInState"
newtype SArray a b = SArray { unSArray :: SArr }
instance (HasKind a, HasKind b) => Show (SArray a b) where
show SArray{} = "SArray<" ++ showType (Proxy @a) ++ ":" ++ showType (Proxy @b) ++ ">"
instance SymArray SArray where
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)
newArrayInState :: forall a b. (HasKind a, HasKind b) => Maybe String -> Maybe (SBV b) -> State -> IO (SArray a b)
newArrayInState mbNm mbVal st = do mapM_ (registerKind st) [aknd, bknd]
SArray <$> newSArr st (aknd, bknd) (mkNm mbNm) (unSBV <$> mbVal)
where mkNm Nothing t = "array_" ++ show t
mkNm (Just nm) _ = nm
aknd = kindOf (Proxy @a)
bknd = kindOf (Proxy @b)
newtype SFunArray a b = SFunArray { unSFunArray :: SFunArr }
instance (HasKind a, HasKind b) => Show (SFunArray a b) where
show SFunArray{} = "SFunArray<" ++ showType (Proxy @a) ++ ":" ++ showType (Proxy @b) ++ ">"
instance SymArray SFunArray where
readArray (SFunArray arr) (SBV a) = SBV (readSFunArr arr a)
writeArray (SFunArray arr) (SBV a) (SBV b) = SFunArray (writeSFunArr arr a b)
mergeArrays (SBV t) (SFunArray a) (SFunArray b) = SFunArray (mergeSFunArr t a b)
newArrayInState :: forall a b. (HasKind a, HasKind b) => Maybe String -> Maybe (SBV b) -> State -> IO (SFunArray a b)
newArrayInState mbNm mbVal st = do mapM_ (registerKind st) [aknd, bknd]
SFunArray <$> newSFunArr st (aknd, bknd) (mkNm mbNm) (unSBV <$> mbVal)
where mkNm Nothing t = "funArray_" ++ show t
mkNm (Just nm) _ = nm
aknd = kindOf (Proxy @a)
bknd = kindOf (Proxy @b)