I am new to NuSMV and CTL and was trying simple Examples. I have 3 states A, B, and C and there is a transition from A-> B
I modeled it in NuSMV and want to check if there is any execution path from B to A. Eventhough I have not defined such transition, The Specification gives me counter example.
Module main
VAR
state:{a,b};
ASSIGN
init(state):=a;
next(state):=b;
SPEC !EF(state=a -> state=c)
SPEC !EF(state=b -> state=a)
Can anyone tell whats wrong in this?
how do i write specification for "is A reachable from B?" - this should return false as there is no transition defined
Note: your code example was not working on my machine, it reported some syntactic errors, so I have actually changed it to look like this:
MODULE main ()
VAR
state : {a,b,c};
ASSIGN
init(state):=a;
next(state):=b;
Comments on your approach.
The property SPEC !EF(state=a -> state=c)
can be read as:
it is not true that there exists a path starting from the initial state such that sooner or later the logic condition
state=a -> state=c
istrue
.
The condition state = a -> state = c
is true
for all states such that state != a
only, because there exists no state in which the conditions state = a
and state = c
can hold at the same time.
If you run NuSMV, you are given the following counter-example:
NuSMV > reset; read_model -i test.smv; go; check_property
-- specification !(EF (state = a -> state = c)) is false
-- as demonstrated by the following execution sequence
Trace Description: CTL Counterexample
Trace Type: Counterexample
-> State: 1.1 <-
state = a
-> State: 1.2 <-
state = b
In state 1.2
the variable state
is equal to b
, therefore state = a -> state = c
is true
and !EF(state = a -> state = c)
is violated.
Similar considerations hold for the property SPEC !EF(state=b -> state=a)
.
One-Step Reachability.
If you want to check that there exists no one-step transition from a state in which state = a
holds to a state in which state = c
holds, then you can use the following property:
SPEC AG (state = a -> AX state != c)
This reads:
for all states, that can be reached following all execution paths starting from all initial states, the CTL property
state = a -> AX state != c
is always verified. Such property says that, if in the current statestate = a
, then it is necessarily the case that in all possible immediate next states the value ofstate
is different fromc
.
If we check such property with NuSMV, we find out that it is verified:
NuSMV > reset; read_model -i test.smv; go; check_property
-- specification AG (state = a -> AX state != c) is true
A similar example holds for the other property that you want to encode.
Path Reachability. If you want to check that there exists no path, formed by an arbitrary and variable number of intermediate transitions, that reaches a state in which state = c
holds, starting from a state in which state = a
holds, then the encoding is slightly different:
SPEC AG (state = a -> AX AG state != c)
This reads:
for all states, that can be reached following all executions paths starting from all initial states, the CTL property
state = a -> AX AG state != c
is always verified. Such property istrue
for all statess'
s.t.
state != a
ins'
or
state = a
ins'
, andstate != c
for all reachable statess''
on all the outgoing paths that start ats'
If we check such property with NuSMV, we find that it is verified:
NuSMV > reset; read_model -i test.smv; go; check_property
-- specification AG (state = a -> AX (AG state != c)) is true
To better outline the difference among the two encodings, I'll drop here a model example on which the first property is false
but the second one is true
:
MODULE main ()
VAR
state : {a,b,c};
ASSIGN
init(state):=a;
next(state) := case
state = a : b;
state = b : c;
TRUE : state;
esac;
SPEC AG (state = a -> AX state != c)
SPEC AG (state = a -> AX AG state != c)
If you run NuSMV over this example, the output is the following one:
NuSMV > reset; read_model -i test.smv; go; check_property
-- specification AG (state = a -> AX state != c) is true
-- specification AG (state = a -> AX (AG state != c)) is false
-- as demonstrated by the following execution sequence
Trace Description: CTL Counterexample
Trace Type: Counterexample
-> State: 1.1 <-
state = a
-> State: 1.2 <-
state = b
-> State: 1.3 <-
state = c
Obviosly, if the first property is found to be false
, then the second property must necessarily be false
as well.
K-Steps Reachability.
The one-step reachability encoding can be generalised to reachability in exact k steps by increasing the number of AX
in the formula:
SPEC AG (state = a -> AX state != c) -- state != c after 1 transition
SPEC AG (state = a -> AX AX state != c) -- state != c after 2 transitions
SPEC AG (state = a -> AX AX AX state != c) -- state != c after 3 transitions
SPEC AG (state = a -> AX ... state != c) -- state != c after 1 + |...| transitions
ETA:
In this use-case scenario, the property
SPEC AG (state = a -> AX AG state != c)
could be simplified to
SPEC AG (state = a -> AG state != c)
and, apparently, it would still work.
However, there is a reason why I did not do it: there is a subtle semantic difference among the two encodings, and even though the latter can be used to verify a reachability property in some cases, the former encoding is more robust since it more closely matches the actual semantics of the reachability problem. e.g. the template B_COND_1 -> AG B_COND_2
fails miserably whenever B_COND_2 := !B_COND_1
, because for any state s'
that verifies the premise B_COND_1
the conclusion AG B_COND_2
--which can be rewritten as AG !B_COND_1
-- cannot possibly hold; prepending AX
to the conclusion adds one level of indirection, and it is more correct because the conclusion should only be required to hold starting from the next states in the execution tree.
ETA #2:
You write:
how do i write specification for "is A reachable from B?" - this should return false as there is no transition defined
A property that returns false
when there is no path from state = b
to state = a
, is the following:
SPEC AG (state = b -> EF state = a)
If you want to verify that it is never the case that state = a
is reachable from state = b
, then this is actually a bad idea for two reasons:
if the property is verified, you are not returned a witness counter-example for the execution trace s.t. state = a
is reachable from state = b
, and therefore you are left on your own to determine why this is the case on your model
if the property is false
, the tool would need to list all of the (possibly exponentially many) paths starting from state = b
such that state = a
can not be reached.
For these reasons I actually encoded the reachability problem the other way around, returning true
when state = a
is not reachable from state = b
and false
+ single counter-example otherwise.