32 \<^cancel>\<open>apply(rename_tac ps')\<close> |
32 \<^cancel>\<open>apply(rename_tac ps')\<close> |
33 \<^cancel>\<open>apply(fastforce intro:notin_List_update[THEN iffD2])\<close> |
33 \<^cancel>\<open>apply(fastforce intro:notin_List_update[THEN iffD2])\<close> |
34 apply fastforce |
34 apply fastforce |
35 done |
35 done |
36 |
36 |
37 text\<open>And now with ghost variables @{term ps} and @{term qs}. Even |
37 text\<open>And now with ghost variables \<^term>\<open>ps\<close> and \<^term>\<open>qs\<close>. Even |
38 ``more automatic''.\<close> |
38 ``more automatic''.\<close> |
39 |
39 |
40 lemma "VARS next p ps q qs r |
40 lemma "VARS next p ps q qs r |
41 {List next p Ps \<and> List next q Qs \<and> set Ps \<inter> set Qs = {} \<and> |
41 {List next p Ps \<and> List next q Qs \<and> set Ps \<inter> set Qs = {} \<and> |
42 ps = Ps \<and> qs = Qs} |
42 ps = Ps \<and> qs = Qs} |
111 subsection "Searching in a list" |
111 subsection "Searching in a list" |
112 |
112 |
113 text\<open>What follows is a sequence of successively more intelligent proofs that |
113 text\<open>What follows is a sequence of successively more intelligent proofs that |
114 a simple loop finds an element in a linked list. |
114 a simple loop finds an element in a linked list. |
115 |
115 |
116 We start with a proof based on the @{term List} predicate. This means it only |
116 We start with a proof based on the \<^term>\<open>List\<close> predicate. This means it only |
117 works for acyclic lists.\<close> |
117 works for acyclic lists.\<close> |
118 |
118 |
119 lemma "VARS tl p |
119 lemma "VARS tl p |
120 {List tl p Ps \<and> X \<in> set Ps} |
120 {List tl p Ps \<and> X \<in> set Ps} |
121 WHILE p \<noteq> Null \<and> p \<noteq> Ref X |
121 WHILE p \<noteq> Null \<and> p \<noteq> Ref X |
143 apply clarsimp |
143 apply clarsimp |
144 done |
144 done |
145 |
145 |
146 text\<open>Now it dawns on us that we do not need the list witness at all --- it |
146 text\<open>Now it dawns on us that we do not need the list witness at all --- it |
147 suffices to talk about reachability, i.e.\ we can use relations directly. The |
147 suffices to talk about reachability, i.e.\ we can use relations directly. The |
148 first version uses a relation on @{typ"'a ref"}:\<close> |
148 first version uses a relation on \<^typ>\<open>'a ref\<close>:\<close> |
149 |
149 |
150 lemma "VARS tl p |
150 lemma "VARS tl p |
151 {(p,X) \<in> {(Ref x,tl x) |x. True}\<^sup>*} |
151 {(p,X) \<in> {(Ref x,tl x) |x. True}\<^sup>*} |
152 WHILE p \<noteq> Null \<and> p \<noteq> X |
152 WHILE p \<noteq> Null \<and> p \<noteq> X |
153 INV {(p,X) \<in> {(Ref x,tl x) |x. True}\<^sup>*} |
153 INV {(p,X) \<in> {(Ref x,tl x) |x. True}\<^sup>*} |
159 apply simp |
159 apply simp |
160 apply(clarsimp elim:converse_rtranclE) |
160 apply(clarsimp elim:converse_rtranclE) |
161 apply(fast elim:converse_rtranclE) |
161 apply(fast elim:converse_rtranclE) |
162 done |
162 done |
163 |
163 |
164 text\<open>Finally, a version based on a relation on type @{typ 'a}:\<close> |
164 text\<open>Finally, a version based on a relation on type \<^typ>\<open>'a\<close>:\<close> |
165 |
165 |
166 lemma "VARS tl p |
166 lemma "VARS tl p |
167 {p \<noteq> Null \<and> (addr p,X) \<in> {(x,y). tl x = Ref y}\<^sup>*} |
167 {p \<noteq> Null \<and> (addr p,X) \<in> {(x,y). tl x = Ref y}\<^sup>*} |
168 WHILE p \<noteq> Null \<and> p \<noteq> Ref X |
168 WHILE p \<noteq> Null \<and> p \<noteq> Ref X |
169 INV {p \<noteq> Null \<and> (addr p,X) \<in> {(x,y). tl x = Ref y}\<^sup>*} |
169 INV {p \<noteq> Null \<and> (addr p,X) \<in> {(x,y). tl x = Ref y}\<^sup>*} |
326 text\<open>More of the previous proof without ghost variables can be |
326 text\<open>More of the previous proof without ghost variables can be |
327 automated, but the runtime goes up drastically. In general it is |
327 automated, but the runtime goes up drastically. In general it is |
328 usually more efficient to give the witness directly than to have it |
328 usually more efficient to give the witness directly than to have it |
329 found by proof. |
329 found by proof. |
330 |
330 |
331 Now we try a functional version of the abstraction relation @{term |
331 Now we try a functional version of the abstraction relation \<^term>\<open>Path\<close>. Since the result is not that convincing, we do not prove any of |
332 Path}. Since the result is not that convincing, we do not prove any of |
|
333 the lemmas.\<close> |
332 the lemmas.\<close> |
334 |
333 |
335 axiomatization |
334 axiomatization |
336 ispath :: "('a \<Rightarrow> 'a ref) \<Rightarrow> 'a ref \<Rightarrow> 'a ref \<Rightarrow> bool" and |
335 ispath :: "('a \<Rightarrow> 'a ref) \<Rightarrow> 'a ref \<Rightarrow> 'a ref \<Rightarrow> bool" and |
337 path :: "('a \<Rightarrow> 'a ref) \<Rightarrow> 'a ref \<Rightarrow> 'a ref \<Rightarrow> 'a list" |
336 path :: "('a \<Rightarrow> 'a ref) \<Rightarrow> 'a ref \<Rightarrow> 'a ref \<Rightarrow> 'a list" |
421 apply clarsimp |
420 apply clarsimp |
422 apply(rule_tac x="a # ps" in exI) |
421 apply(rule_tac x="a # ps" in exI) |
423 apply clarsimp |
422 apply clarsimp |
424 done |
423 done |
425 |
424 |
426 text\<open>In the beginning, we are able to assert @{term"distPath next |
425 text\<open>In the beginning, we are able to assert \<^term>\<open>distPath next |
427 root as root"}, with @{term"as"} set to @{term"[]"} or |
426 root as root\<close>, with \<^term>\<open>as\<close> set to \<^term>\<open>[]\<close> or |
428 @{term"[r,a,b,c]"}. Note that @{term"Path next root as root"} would |
427 \<^term>\<open>[r,a,b,c]\<close>. Note that \<^term>\<open>Path next root as root\<close> would |
429 additionally give us an infinite number of lists with the recurring |
428 additionally give us an infinite number of lists with the recurring |
430 sequence @{term"[r,a,b,c]"}. |
429 sequence \<^term>\<open>[r,a,b,c]\<close>. |
431 |
430 |
432 The precondition states that there exists a non-empty non-repeating |
431 The precondition states that there exists a non-empty non-repeating |
433 path \mbox{@{term "r # Ps"}} from pointer @{term root} to itself, given that |
432 path \mbox{\<^term>\<open>r # Ps\<close>} from pointer \<^term>\<open>root\<close> to itself, given that |
434 @{term root} points to location @{term r}. Pointers @{term p} and |
433 \<^term>\<open>root\<close> points to location \<^term>\<open>r\<close>. Pointers \<^term>\<open>p\<close> and |
435 @{term q} are then set to @{term root} and the successor of @{term |
434 \<^term>\<open>q\<close> are then set to \<^term>\<open>root\<close> and the successor of \<^term>\<open>root\<close> respectively. If \<^term>\<open>q = root\<close>, we have circled the loop, |
436 root} respectively. If @{term "q = root"}, we have circled the loop, |
435 otherwise we set the \<^term>\<open>next\<close> pointer field of \<^term>\<open>q\<close> to point |
437 otherwise we set the @{term next} pointer field of @{term q} to point |
436 to \<^term>\<open>p\<close>, and shift \<^term>\<open>p\<close> and \<^term>\<open>q\<close> one step forward. The |
438 to @{term p}, and shift @{term p} and @{term q} one step forward. The |
437 invariant thus states that \<^term>\<open>p\<close> and \<^term>\<open>q\<close> point to two |
439 invariant thus states that @{term p} and @{term q} point to two |
438 disjoint lists \<^term>\<open>ps\<close> and \<^term>\<open>qs\<close>, such that \<^term>\<open>Ps = rev ps |
440 disjoint lists @{term ps} and @{term qs}, such that @{term"Ps = rev ps |
439 @ qs\<close>. After the loop terminates, one |
441 @ qs"}. After the loop terminates, one |
|
442 extra step is needed to close the loop. As expected, the postcondition |
440 extra step is needed to close the loop. As expected, the postcondition |
443 states that the @{term distPath} from @{term root} to itself is now |
441 states that the \<^term>\<open>distPath\<close> from \<^term>\<open>root\<close> to itself is now |
444 @{term "r # (rev Ps)"}. |
442 \<^term>\<open>r # (rev Ps)\<close>. |
445 |
443 |
446 It may come as a surprise to the reader that the simple algorithm for |
444 It may come as a surprise to the reader that the simple algorithm for |
447 acyclic list reversal, with modified annotations, works for cyclic |
445 acyclic list reversal, with modified annotations, works for cyclic |
448 lists as well:\<close> |
446 lists as well:\<close> |
449 |
447 |