View abstraction to enumerate counterexamples #827
konnov
started this conversation in
Show and tell
Replies: 1 comment
-
Automatic enumeration of counterexamples with the view abstraction is implemented in #833 |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
This discussion is inspired by the demand for enumeration of counterexamples, e.g., in model-based testing, as discussed in #542. In a nutshell, we want to enumerate multiple counterexamples to a property, instead of producing just one example. The important question is how to enumerate essentially different counterexamples instead of enumerating similar counterexamples. As the notion of similarity depends on the specification and the user, we let the user decide what it means for states to be similar.
TLC has the VIEW configuration option that forces the model checker to search over abstract states instead of concrete states. As many abstractions, the view abstraction is usually an overapproximation. We can borrow the idea of the view abstraction and use it to partition the space of counterexamples. For example:
We can run apalache in the standard safety-checking mode:
Apalache will find a counterexample, e.g.,
x=10
andy=0
after firing actionA
. However, if we want to find another counterexample to this property, e.g., for testing, it will be hard to do so. We can set the random seed in z3 and try our luck again:However, the use of the random seed is up to z3, so it may return the same model. In principle, we would like to exclude the execution that resulted in a counterexample, that is, we could add a trace invariant like this:
Note that we had to embed
Inv
right intoTraceInv1
. Let's run apalache again:This time it finds another counterexample:
x = 11
andy = 0
after firing actionA
. That's a bit disappointing. Intuitively, it is not the most interesting test, as the solver has found yet another data point. We can see that the solver can just keep enumerating the valuesx=11, 12, 13, ...
Now let's write the trace invariant differently:
Intuitively, we are using the view abstraction, as defined with the operator
View1
, to exclude the whole set of executions that have non-negative components in the second state. If we checkTraceInv2
, the model checker produces another counterexample:As you can see, the solver is playing a little game here. It produces a very similar counterexample, but at different depth. We can go on and exclude this new set of counterexamples:
By checking
TraceInv3
, we finally get a new interesting counterexample:As you can see, we can partition the execution space to exclude the examples that we have seen before. It is up to us how to do this partitioning. In the above example, we have been essentially using the operator
View1
to exclude equivalence classes of executions. Alternatively, we could useView2
to exclude the same sequence of actions, independently of the values ofx
andy
. If you know CEGAR, our approach is a very simple implementation of it.We propose to implement this approach in the model checker, in order to enumerate classes of counterexamples instead of presenting just one example.
Beta Was this translation helpful? Give feedback.
All reactions