Applying abstraction to software systems always means, that some details about the original system get lost, or rather, become unknown. Thus, an intuitive way of characterising this loss of information in an abstract model is to introduce a third truth value unknown for predicates and transitions. Such a three-valued sematics for state space models was first proposed in [22], and since then has been used in many abstraction frameworks (e.g. [115, 4, 87]).
Three-valued abstractions moreover have the advantage that true as well as false results in verification can be preserved.
In our approach to the verification of concurrent systems, we also employ a three-valued abstraction. Similar to the boolean abstraction, we have predi-cates instead of concrete variables, and thus, abstract basic operations again take the form
bopa ≡ assume(pe) : p1:= pe1, . . . , pk:= pek.
But now, our predicates have a three-valued domain: the valuation of a predicate in an abstract state can be true, false or unknown. Unknown is in fact a valid truth value as we operate with the Kleene logic K3[62] (see Section 2.2). Three-valued expressions in abstract operations may again take the form choice(a, b), but now with the following semantics:
s(choice (a, b)) =
true if s(a) is true f alse if s(b) is true
⊥ else
Hence, non-deterministic choices are resolved in three-valued abstractions.
Instead, the third truth value unknown may be assigned to predicates, or may occur as a guard.
The derivation of a three-valued abstract system Sysafor a given concrete system Sys and a set of predicates Pred can be directly adopted from the boolean predicate abstraction (see Section 4.1.1). We only have to consider that predicate expressions are now evaluated under the Kleene logic, and that we have a new semantics for choice. Furthermore, the approximation relation for boolean abstractions can be straightforwardly extended to the three-valued setting. Three-valued abstractions naturally require three-valued state space models. As shown in Section 2.2, classical Kripke structures can be generalised to three-valued Kripke structures, which are tailored to model partially unknown systems. Using three-valued Kripke structures moreover gives rise to a new notion of correspondence between concrete and abstract states.
Definition 4.7 (Corresponding States in Three-Valued Abstractions).
Let Sys = kni=1Proci be a concurrent system over Var, and Sysa= kni=1Procai
4.1 Predicate Abstraction 59 a three-valued abstraction over Pred, with Sysa Sys. Moreover, let K = (S, R, L, F) be the Kripke structure representing Sys, and Ka= (Sa, Ra, La, Fa) the three-valued Kripke structure representing Sysawhere K and Kaare both defined over the same set of atomic predicates AP. Then a concrete state s ∈ S corresponds to an abstract state sa∈ Saiff
∀p ∈ AP : La(sa, p) ≤K3L(s, p)
Thus, if a predicate p ∈ AP has a definite value (true, false) in an abstract state sa, then p has the same value in a corresponding concrete state s. However, predicates that are valuated with unknown in samay be true or false in s. We also say, the labelling of the concrete state s is more definite than the labelling of a corresponding abstract state sa, abbreviated by La(sa) ≤K3L(s).
Applying three-valued predicate abstraction gives us a conservative ap-proximation in the sense that all definite behaviour in the abstract system is also feasible in the concrete one. Hence, all definite verification results, i.e.
true and false, obtained on the abstraction can be directly transferred to the original system. Only an unknown result tells us nothing about the concrete system. From [112] we get the following theorem:
Theorem 4.2.
Let Sys = kni=1Procibe a concurrent system over Var, and Sysa= kni=1Procai a three-valued abstraction over Pred, with Sysa Sys. Moreover, let K = (S, R, L, F) be the Kripke structure representing Sys, and Ka= (Sa, Ra, La, Fa) the three-valued Kripke structure representing Sysawhere K and Kaare both defined over the same set of atomic predicates AP. Then for any two corresponding states s ∈ S and sa∈ Saand for any CTL formula ψ over control locations or the predicates in Pred the following holds:
[Ka, sa|= ψ] ≤K3 [K, s |= ψ]
To illustrate the consequence of this theorem for our approach to verification, we take a look at the concurrent system Sys8in Figure 4.4.
x, y :integer where x = 1, y = 1
Proc1:: 1 : loop forever do
2 : x:= −x
k Proc2::
1 : while x > 0 do
2 : y:= y − 1 3 : end
Fig. 4.4 Concurrent system Sys8= Proc1k Proc2over Var = {x, y}.
We want to verify whether Proc2always eventually terminates, i.e. whether the CTL formula AF(pc2= 3) holds for the concurrent system. It is easy to see that this property is violated for Sys8; e.g. consider a computation where Proc1executes the loop body always twice in succession before Proc2
evaluates its while condition. However, for the purpose of formal verification we first construct a three-valued abstraction of our system over the set of predicates Pred = {(x > 0), (x > −1), (y > 0)}. Now, model checking the CTL formula on our abstract system Sysa8yields false, and additionally returns a counterexample. According to Theorem 4.2 we can straightforwardly deduce that the original system violatesAF(pc2= 3)as well. Moreover, we have the guarantee that the revealed counterexample corresponds to a real path in Sys8, and thus, no additional retracement step is required. – In contrast, for an analogous boolean abstraction (over the same set of predicates) model checking also returns false together with a counterexample; but this result has to validated by retracing the counterexample on the original system.
Naturally, for a fixed set of predicates a three-valued abstraction is always slightly larger than a boolean abstraction because now we have a three-valued (instead of a two-valued) domain for predicates. Nevertheless, for many real-life verification tasks it is more advantageous to have a slightly larger abstract model than to be forced to perform an additional retracement step. Remember that retracing counterexamples involves a partial exploration of the concrete state space, and thus, might suffer from the state explosion problem.
Three-valued abstractions give us more precision in temporal logic model checking because both true and false results are preserved. However, verifying a three-valued abstraction might also yield unknown, which tells us nothing about the concrete system. We e.g. get such a result when checking the CTL formula AG(y > 0) on our aforementioned abstraction (over Pred = {(x > 0), (x > −1), (y > 0)}). An unknown result always comes along with an unconfirmed counterexample – a potential error path in the abstract system with some unknown transitions and predicates. Now, we can directly conclude that our abstraction is too coarse for a definite result in verification. The abstraction can then be refined based on an analysis of the unconfirmed counterexample (see Chapter 5). – Contrary, verifying the formulaAG(y > 0) on an analogous boolean abstraction returns false together with an abstract counterexample. An additional retracement step is required, which reveals that the counterexample is spurious and that the abstraction is too coarse.
So far, we have seen that (boolean and three-valued) predicate abstraction is a powerful technique in cutting down the state space of software systems.
In particular, predicate abstraction enables us to restrict the large (or even infinite) domains of system variables to very small fragments, and thus, can improve the efficiency of formal verification by orders of magnitude. However, in concurrent systems the space complexity furthermore exponentially grows with the number of processes composed in parallel. In the next section, we introduce spotlight abstraction – a specific abstraction technique for concurrent systems that can be combined with predicate abstraction.