I have a stateful process that is modelled as an i -> RWS r w s a
. I want to feed it an input cmds :: [i]
; currently I do that wholesale:
let play = runGame theGame . go
where
go [] = finished
go ((v, n):cmds) = do
end1 <- stepWorld
end2 <- ite (SBV.isJust end1) (return end1) $ stepPlayer (v, n)
ite (SBV.isJust end2) (return end2) $ go cmds
I can try searching for an input of a predetermined size like this:
result <- satWith z3{ verbose = True } $ do
cmds <- mapM sCmd [1..inputLength]
return $ SBV.fromMaybe sFalse $ fst $ play cmds
However, this gives me horrible performance in SBV itself, i.e. before Z3 is called (I can see that this is the case because the verbose
output shows me the all the time is spent before the (check-sat)
call). This is even with inputLength
set to something small like 4.
However, with inputLength
set to 1 or 2, the whole process is very snappy. So this makes me hope that there is a way to run SBV to get the model of the behaviour of a single step i -> s -> (s, a)
, and then tell the SMT solver to keep iterating that model for n
different i
s.
So that is my question: in a stateful computation like this, where I want to feed SMT variables as input into the stateful computation, is there a way to let the SMT solver turn its crank to avoid the bad performance of SBV?
I guess a simplified "model question" would be if I have a function f :: St -> St
, and a predicate p :: St -> SBool
, and I want to solve for n :: SInt
such that p (iterateN n f x0)
, what is the recommended way of doing that with SBV, supposing Mergeable St
?
EDIT: I've uploaded the whole code to Github but bear in mind it is not a minimalized example; in fact it isn't even very nice Haskell code yet.