• No results found

Completion as an alternative for breadth-first search

4.6 Comparison with other tools

4.6.3 Completion as an alternative for breadth-first search

For “positive” reachability analysis, i.e. proving that s →R∗t, rewrite tools like Maude (Clavel

et al., 2009) or Tom (Tom, 2009) generally give the fastest answer. For instance the searchcommand in Maude is able to solve this problem even for non terminating TRSs. Given an initial problem of the form reach s =>* t, Maude rewrites s by R using a breadth-first search strategy and tables every obtained term. Tabling is used to avoid loop- ing rewriting on a term. If a term u is in the table and if u is encountered again during rewriting then u will not be rewritten. If the term t is obtained then it is signaled by Maude. Timbuk is able to achieve such “positive” proofs on left-linear TRSs. First, recall that using the exact normalization strategy (Definition 113 of Section 3.3.1) the produced ab- straction function is injective. Then, using Corollary 77, we get that if R is left-linear,

L(A0

) = {s} and there exists n ∈ N such that t ∈ L(AnR,α) then s →∗R t. Besides to

this, we can remark that the completion algorithm is, by definition, also tabling all reach- able terms. Each term is stored in the completed tree automaton structure. Furthermore, the tabling operation is even more advanced in Timbuk than in Maude since, because of normalization of tree automata transitions, every subterm of every reachable term is tabled. We can also note that the exact normalization strategy normalize each new term in a deter- ministic way, i.e. each term is tabled once. This guarantees a tabling strategy with maximal sharing. We here give an example illustrating all those aspects.

Example 135 Let R = {a → f (a, b), b → f (b, a)} and the reachability problem be a →R∗ f (f (a, b), f (b, a)). Let A0 be the initial automaton withQ0f = {q0} and ∆0 =

{a → q0}. We now consider, on one side, what would be the table constructed by Maude

and what are the completed automaton produced byTimbuk.

0 a 1 f(a,b) 2 f(f(a,b),b) f(a,f(b,a)) 3 f(f(f(a,b),b),b) f(f(a,f(b,a)),b) f(f(a,b),f(b,a)) f(a,f(f(b,a),a)) f(a,f(b,f(a,b))) 4 . . . A0 a → q 0 A1 R f (q0, q1) → q2 b → q1 q2→ q0 A2 R f (q1, q0) → q3 q3→ q1

As we can see, in both cases, after 3 rewritings on the Maude side and after 2 com- pletion steps on Timbuk side, we can prove that a →R∗ f (f (a, b), f (b, a)). On the Tim-

buk side we have f (f (a, b), f (b, a)) →∗A2 R f (f (q0, q1), f (q1, q0)) →∗A2 R f (q2, q3) →∗A2 R f (q0, q1) →∗A2

R q0and q0is a final state of A

2

R. We thus have similar results. However, on

Timbuk side we can see that the term a occurs only once, it is then replaced by the state q0 which can be seen as its tabling index. Moreover, all terms that can be reached from

a will also be recognized by q0. In other words, q0 represents all reachable terms from

a. Hence, with regards to what Maude is doing, in the term f (a, b) it is not necessary to explicitly consider the possible rewritings of a into f (a, b), f (f (a, b), b), . . . since in the tree automaton a has been replaced by q0in the term f (a, b) and q0will recognize all terms

reachable from a. Finally, note that the above example is in the G class of Section 2.1.1 and that completion ends on the A2

Rtree automaton, i.e. every possible reachable by rewriting

a with R is recognized by A2 R.

In spite of the sophisticated tree automata data structure of Timbuk, Maude is at least 10 times faster than Timbuk to prove reachability on examples where the TRS has a narrow rewriting tree. This difference is less important on TRSs which are more combinatorial and, thus, having a wider rewriting tree. For instance on the TRS encoding the readers- writers protocol of Section 4.6.4, which is only a bit more non-deterministic, Timbuk is only 3 times slower for reachability problems on big terms. Finally, we also experimented with TRSs automatically generated from Java byte code programs with Threads (see Sec- tion 5.2). Those TRS are huge and manipulate big terms. For instance, the following Java

program can be compiled into bytecode and then into a TRS of around 2000 rules. class T extends java.lang.Thread{

Object lock;

public T(Object lock){ this.lock = lock; }

public void action(){ System.out.println(1); }

public void run(){ synchronized(lock){ this.action(); } } } class ExThreads1{

public static void main(String[] argv){ Object lock = new Object();

T thread = new T(lock); T thread2 = new T(lock); thread.start();

thread2.start(); try{

thread.join();

} catch (InterruptedException e){} System.out.println(2);

System.out.println(3); }

}

Using the Copster tool (see Section 5.2), we can export both Timbuk and Maude spec- ifications. In our encoding of Java programs into TRS, outputs are lists of terms stored as a parameter of the term representing the Java program state. On the above example, we can check that any output list [2, 3, 1, 1] is unreachable. This can be automatically proved using Timbuk and the exact completion strategy in less than a minute and 300 Mb of memory. On the same example Maude is not able to answer: it has to be stopped since it exhausted the memory (1 Gb) in less than 3 minutes. Moreover, the fixpoint automaton, computed by Timbuk and used to prove unreachability, was certified using the checker (of Section 4.5) within seconds.