Closed bts closed 6 years ago
I think you can do something simpler:
{-# LANGUAGE OverloadedStrings #-}
import Data.SBV
type A = SFunArray String Integer
aread :: String -> A -> SString -> Symbolic SInteger
aread tag a k = do v <- free tag
let val = readArray a k
constrain $ v .== val
return val
q :: Predicate
q = do let a :: A
a = mkSFunArray (uninterpret "a")
v <- aread "a[\"k\"]" a "k"
return $ v .== 2
If I try to prove q
, I get:
*Main> prove q
Falsifiable. Counter-example:
a["k"] = 0 :: Integer
Or, if I try to satisfy it:
*Main> sat q
Satisfiable. Model:
a["k"] = 2 :: Integer
Is this what you're trying to achieve?
You beat me to it -- I was just typing up some text describing this same approach as an alternative :)
I shied away from this at first because I've been trying to do as much work outside Symbolic
as possible, but I guess I should be reconsidering that assumption.
Indeed I think this is probably the better route to go. Thank you again!
This is a common trick actually; used when you want to have some extra constraints on "fresh" variables. Note that the aread
function can impose further constraints on the value read easily; for instance they are all greater than zero, etc.; keeps the code modular and much simpler to work with:
aread :: String -> A -> SString -> Symbolic SInteger
aread tag a k = do v <- free tag
let val = readArray a k
constrain $ v .== val
constrain $ v .> 0 -- or add other constraints as you see fit, any predicate would do
return val
Great -- thanks!
Hi Levent,
The combination of
uninterpret
andSFunArray
that you mentioned in #378 works very well, but a noticeable drawback ofuninterpret
is that falsifying models contain no information about the data in those arrays (indeed this was also the case forSArray
.) To that end, I've been trying my hand at an adaptation ofSFunArray
that allows for a combination of free values in an array and the ability to report back assignments to those values inmodelAssocs
.The approach I've taken results from the observation that every uninitialized read of an array (let's say this happens
n
times) could pertain to a different key, and that ifn
is small, we can simply explicitly provide a (free) "default value" for each of these reads. If these default values are allocated inSymbolic
, they're included in the model. In order for repeated reads to the same key to return the same value, we keep track of the default values we've issued so far (vs the static initialization function inSFunArray
.) A notable upshot is that this construction is unfortunately not aSymArray
becausereadArray
doesn't produce an updated array likewriteArray
does, and this new read needs to take the default value as well.Here's what I currently have:
Is this overkill, and have I missed another approach that can more simply allow for access to/control over these uninitialized reads?
If this is something that might be useful to SBV users generally, I would be happy to put together a pull request taking any suggestions you have into account. Also naturally this
Arr
would need a new name if it were to live in SBV.Thanks again! Brian