Replies: 4 comments 2 replies
-
Can you remove What does the Insert function do? Does it only modify the Node on which it is called, or can it change any node accessible from the current one? |
Beta Was this translation helpful? Give feedback.
-
Without access to your code, I can only make guesses, but I do not think that the solution to your problem should involve using triggers or existential activation. In my limited experience, when I find myself wondering thinking that I need to state that "everything reachable in the set Repr stays unchanged", it is a sign that the invariant that captures the structure of the Repr is not precise enough. I think it can be very difficult to define an invariant appropriately when your Repr is a set of objects, and I would suggest defining a Repr that explicitly captures the structure of your objects. Here's an example for concreteness. Say that I want to define a linked list. I could define it starting with something like: class LL<T(!new)> ... {
ghost var Repr: set<object>
ghost predicate Invariant()
reads this, Repr
decreases Repr
{
&& (this in Repr)
&& (next != null ==> next in Repr
&& this !in next.Repr
&& next.Repr < Repr
&& next.Invariant())
}
} but is is easy for me to miss on subtle aliasing that make my mental model of the data structure differ from the possible layouts (for example with cycles I did not think about). To make my life simpler, I would instead define my linked list as: class Cell<T(!new)> {
var next: Cell?<T>
var value: T
constructor(value: T)
ensures this.value == value
ensures this.next == null
{
this.value := value;
next := null;
}
} and class LL<T(!new)> {
var length: nat
ghost var Repr: seq<Cell<T>> // <-- Using seq
var hd: Cell?<T>
ghost predicate Invariant()
reads this, Repr
{
&& (length == |Repr|)
&& (length == 0 <==> hd == null)
&& (length > 0 ==> Repr[0] == hd)
&& (length > 0 ==> Repr[length-1].next == null)
&& (forall idx: nat :: idx < length - 1 ==>
Repr[idx].next != null
&& Repr[idx].next == Repr[idx+1]
)
}
} Note that I defined my Repr as a sequence of objects, rather than a set, because it is the intended layout of my data structures. In your case, you cannot simply use a seq, but since the data structure you are implementing is meant to behave as if it In conclusion, I doubt that refining triggers or diving deeper into Z3 will help. The data structure that you are trying to |
Beta Was this translation helpful? Give feedback.
-
Let me suggest you the following:
Not sure how much it is relevant but also:
|
Beta Was this translation helpful? Give feedback.
-
a more concrete suggestion (although I'm sure the original problem must be long solved). function allTheEnvsSet(s : Region) : set<Object>
{
if (s.Frame?)
then {s.env} + allTheEnvsSet(s.prev)
else {}
} and then I can use that in reads or modifies clauses directly: reads allTheEnvsSet(s) |
Beta Was this translation helpful? Give feedback.
-
I am working on a semester project and have got stuck at verifying a method for over a month now. After trying all the tricks mentioned in this post and this section, I still encountered timeouts (> 5min). So I did some literature review, particularly reading this paper multiples times. The subsection "Existential Activation" could be the reason why I encountered timeouts, but I am not sure yet because I don't know how to inspect Z3 model efficiently.
Let me first briefly describe the problem I am encountering.
Consider a class
Node
with the following field:The specification predicates are rather sophisticated, so I'll just post what I considered relevant here for now.
There are three properties in total.
BasicProp()
contains some unquantified formulas and defines whatRepr
contains (standard definition, containing all reachable objects throughlefts
andright
recursively and including itself). There are two other recursive predicates, let's call themProp1()
andProp2()
, which have the structure below:This specification was validated for all
function
s, but hit timeouts when I tried to verify the methodInsert
. I first putassume false
in all branches except one, i.e.,After inspection, I realized I cannot verify the recursive calls from
Prop1
(and similarly fromProp2
)However, since they hold before calling the function, and the modification in this method (in this branch at least) should make this property hold still. To validate this statement, I wrote a
twostate lemma
which has the following predicate as the precondition:Then in the twostate lemama, I used the predicate above and asserted what is changed and what is not on the heap as follows
If I put this lemma in the branch above, i.e.,
This branch gets verified now. However, the problem is that the two assumptions above cannot be turned into assertions, because they are defined recursively, and
twostate predicate
cannot be used in the precondition ofInsert
.Other trials I did:
Asserting
old(Repr) == Repr
does not assert "everything reachable in the setRepr
stays unchanged" according to my experiment. It simply says the fieldRepr
stays unchanged.Asserting
forall node <- Repr :: node == old(node)
also does not work, because it will sayArgument to 'old' does not dereference the mutable heap, so this use of 'old' has no effect
.Even after changing the
modifies
clause tothis
(this branch does not involve recursive call toInsert
so it is fine), the recursive calls toProp1
orProp2
still cannot be verified.My question now is: how can I state the fact that "everything that was on the heap stays unchanged" for a recursive data structure in Dafny?
My more advanced question would be: Would the timeout have to do with a similar situation that is described in the "Existential Activation" part mentioned in this paper? That is, in reasoning about the heap, there is a new skolem constant introduced by Z3, but a term involving this new skolem constant is not selected as part of the trigger by Z3 (but it should). As a user, I cannot add such a trigger myself, because I would not know what skolem constant is introduced. Are there any workarounds in Dafny when we encounter such a situation?
Beta Was this translation helpful? Give feedback.
All reactions