{-# OPTIONS_GHC -Wall -Werror #-}
module Documentation.SBV.Examples.Queries.Concurrency where
import Data.SBV
import Data.SBV.Control
import Control.Concurrent
import Control.Monad.IO.Class (liftIO)
shared :: MVar (SInteger, SInteger) -> Symbolic ()
shared :: MVar (SInteger, SInteger) -> Symbolic ()
shared MVar (SInteger, SInteger)
v = do
x <- String -> Symbolic SInteger
sInteger String
"x"
y <- sInteger "y"
constrain $ y .<= 10
constrain $ x .<= 10
constrain $ x + y .== 10
liftIO $ putMVar v (x,y)
queryOne :: MVar (SInteger, SInteger) -> Query (Maybe Integer)
queryOne :: MVar (SInteger, SInteger) -> Query (Maybe Integer)
queryOne MVar (SInteger, SInteger)
v = do
IO () -> Query ()
forall a. IO a -> Query a
io (IO () -> Query ()) -> IO () -> Query ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn String
"[One]: Waiting"
IO () -> Query ()
forall a. IO a -> Query a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Query ()) -> IO () -> Query ()
forall a b. (a -> b) -> a -> b
$ Int -> IO ()
threadDelay Int
5000000
IO () -> Query ()
forall a. IO a -> Query a
io (IO () -> Query ()) -> IO () -> Query ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn String
"[One]: Done"
(x,y) <- IO (SInteger, SInteger) -> QueryT IO (SInteger, SInteger)
forall a. IO a -> Query a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (SInteger, SInteger) -> QueryT IO (SInteger, SInteger))
-> IO (SInteger, SInteger) -> QueryT IO (SInteger, SInteger)
forall a b. (a -> b) -> a -> b
$ MVar (SInteger, SInteger) -> IO (SInteger, SInteger)
forall a. MVar a -> IO a
takeMVar MVar (SInteger, SInteger)
v
constrain $ x .< y
cs <- checkSat
case cs of
CheckSatResult
Unk -> String -> Query (Maybe Integer)
forall a. HasCallStack => String -> a
error String
"Too bad, solver said unknown.."
DSat{} -> String -> Query (Maybe Integer)
forall a. HasCallStack => String -> a
error String
"Unexpected dsat result.."
CheckSatResult
Unsat -> do IO () -> Query ()
forall a. IO a -> Query a
io (IO () -> Query ()) -> IO () -> Query ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn String
"No other solution!"
Maybe Integer -> Query (Maybe Integer)
forall a. a -> QueryT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Integer
forall a. Maybe a
Nothing
CheckSatResult
Sat -> do xv <- SInteger -> Query Integer
forall a. SymVal a => SBV a -> Query a
getValue SInteger
x
yv <- getValue y
io $ putStrLn $ "[One]: Current solution is: " ++ show (xv, yv)
return $ Just (xv + yv)
queryTwo :: MVar (SInteger, SInteger) -> Query (Maybe Integer)
queryTwo :: MVar (SInteger, SInteger) -> Query (Maybe Integer)
queryTwo MVar (SInteger, SInteger)
v = do
(x,y) <- IO (SInteger, SInteger) -> QueryT IO (SInteger, SInteger)
forall a. IO a -> Query a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (SInteger, SInteger) -> QueryT IO (SInteger, SInteger))
-> IO (SInteger, SInteger) -> QueryT IO (SInteger, SInteger)
forall a b. (a -> b) -> a -> b
$ MVar (SInteger, SInteger) -> IO (SInteger, SInteger)
forall a. MVar a -> IO a
takeMVar MVar (SInteger, SInteger)
v
io $ putStrLn $ "[Two]: got values" ++ show (x,y)
constrain $ y .< x
cs <- checkSat
case cs of
CheckSatResult
Unk -> String -> Query (Maybe Integer)
forall a. HasCallStack => String -> a
error String
"Too bad, solver said unknown.."
DSat{} -> String -> Query (Maybe Integer)
forall a. HasCallStack => String -> a
error String
"Unexpected dsat result.."
CheckSatResult
Unsat -> do IO () -> Query ()
forall a. IO a -> Query a
io (IO () -> Query ()) -> IO () -> Query ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn String
"No other solution!"
Maybe Integer -> Query (Maybe Integer)
forall a. a -> QueryT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Integer
forall a. Maybe a
Nothing
CheckSatResult
Sat -> do yv <- SInteger -> Query Integer
forall a. SymVal a => SBV a -> Query a
getValue SInteger
y
xv <- getValue x
io $ putStrLn $ "[Two]: Current solution is: " ++ show (xv, yv)
return $ Just (xv * yv)
demo :: IO ()
demo :: IO ()
demo = do
v <- IO (MVar (SInteger, SInteger))
forall a. IO (MVar a)
newEmptyMVar
putStrLn "[Main]: Hello from main, kicking off children: "
results <- satConcurrentWithAll z3 [queryOne v, queryTwo v] (shared v)
putStrLn "[Main]: Children spawned, waiting for results"
putStrLn "[Main]: Here they are: "
print results
sharedDependent :: MVar (SInteger, SInteger) -> Symbolic ()
sharedDependent :: MVar (SInteger, SInteger) -> Symbolic ()
sharedDependent MVar (SInteger, SInteger)
v = do
x <- String -> Symbolic SInteger
sInteger String
"x"
y <- sInteger "y"
constrain $ y .<= 10
constrain $ x .<= 10
constrain $ x + y .== 10
liftIO $ putMVar v (x,y)
firstQuery :: MVar (SInteger, SInteger) -> MVar (SInteger , SInteger) -> Query (Maybe Integer)
firstQuery :: MVar (SInteger, SInteger)
-> MVar (SInteger, SInteger) -> Query (Maybe Integer)
firstQuery MVar (SInteger, SInteger)
v1 MVar (SInteger, SInteger)
v2 = do
(x,y) <- IO (SInteger, SInteger) -> QueryT IO (SInteger, SInteger)
forall a. IO a -> Query a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (SInteger, SInteger) -> QueryT IO (SInteger, SInteger))
-> IO (SInteger, SInteger) -> QueryT IO (SInteger, SInteger)
forall a b. (a -> b) -> a -> b
$ MVar (SInteger, SInteger) -> IO (SInteger, SInteger)
forall a. MVar a -> IO a
takeMVar MVar (SInteger, SInteger)
v1
io $ putStrLn "[One]: got vars...working..."
constrain $ x .< y
cs <- checkSat
case cs of
CheckSatResult
Unk -> String -> Query (Maybe Integer)
forall a. HasCallStack => String -> a
error String
"Too bad, solver said unknown.."
DSat{} -> String -> Query (Maybe Integer)
forall a. HasCallStack => String -> a
error String
"Unexpected dsat result.."
CheckSatResult
Unsat -> do IO () -> Query ()
forall a. IO a -> Query a
io (IO () -> Query ()) -> IO () -> Query ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn String
"No other solution!"
Maybe Integer -> Query (Maybe Integer)
forall a. a -> QueryT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Integer
forall a. Maybe a
Nothing
CheckSatResult
Sat -> do xv <- SInteger -> Query Integer
forall a. SymVal a => SBV a -> Query a
getValue SInteger
x
yv <- getValue y
io $ putStrLn $ "[One]: Current solution is: " ++ show (xv, yv)
io $ putStrLn "[One]: Place vars for [Two]"
liftIO $ putMVar v2 (literal (xv + yv), literal (xv * yv))
return $ Just (xv + yv)
secondQuery :: MVar (SInteger, SInteger) -> Query (Maybe Integer)
secondQuery :: MVar (SInteger, SInteger) -> Query (Maybe Integer)
secondQuery MVar (SInteger, SInteger)
v2 = do
(x,y) <- IO (SInteger, SInteger) -> QueryT IO (SInteger, SInteger)
forall a. IO a -> Query a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (SInteger, SInteger) -> QueryT IO (SInteger, SInteger))
-> IO (SInteger, SInteger) -> QueryT IO (SInteger, SInteger)
forall a b. (a -> b) -> a -> b
$ MVar (SInteger, SInteger) -> IO (SInteger, SInteger)
forall a. MVar a -> IO a
takeMVar MVar (SInteger, SInteger)
v2
io $ putStrLn $ "[Two]: got values" ++ show (x,y)
z <- freshVar "z"
constrain $ z .> x + y
cs <- checkSat
case cs of
CheckSatResult
Unk -> String -> Query (Maybe Integer)
forall a. HasCallStack => String -> a
error String
"Too bad, solver said unknown.."
DSat{} -> String -> Query (Maybe Integer)
forall a. HasCallStack => String -> a
error String
"Unexpected dsat result.."
CheckSatResult
Unsat -> do IO () -> Query ()
forall a. IO a -> Query a
io (IO () -> Query ()) -> IO () -> Query ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn String
"No other solution!"
Maybe Integer -> Query (Maybe Integer)
forall a. a -> QueryT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Integer
forall a. Maybe a
Nothing
CheckSatResult
Sat -> do yv <- SInteger -> Query Integer
forall a. SymVal a => SBV a -> Query a
getValue SInteger
y
xv <- getValue x
zv <- getValue z
io $ putStrLn $ "[Two]: My solution is: " ++ show (zv + xv, zv + yv)
return $ Just (zv * xv * yv)
demoDependent :: IO ()
demoDependent :: IO ()
demoDependent = do
v1 <- IO (MVar (SInteger, SInteger))
forall a. IO (MVar a)
newEmptyMVar
v2 <- newEmptyMVar
results <- satConcurrentWithAll z3 [firstQuery v1 v2, secondQuery v2] (sharedDependent v1)
print results