src/HOL/Hoare/Pointer_Examples.thy
changeset 69597 ff784d5a5bfb
parent 67613 ce654b0e6d69
child 71989 bad75618fb82
equal deleted inserted replaced
69596:c8a2755bf220 69597:ff784d5a5bfb
    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
   126   apply blast
   126   apply blast
   127  apply clarsimp
   127  apply clarsimp
   128 apply clarsimp
   128 apply clarsimp
   129 done
   129 done
   130 
   130 
   131 text\<open>Using @{term Path} instead of @{term List} generalizes the correctness
   131 text\<open>Using \<^term>\<open>Path\<close> instead of \<^term>\<open>List\<close> generalizes the correctness
   132 statement to cyclic lists as well:\<close>
   132 statement to cyclic lists as well:\<close>
   133 
   133 
   134 lemma "VARS tl p
   134 lemma "VARS tl p
   135   {Path tl p Ps X}
   135   {Path tl p Ps X}
   136   WHILE p \<noteq> Null \<and> p \<noteq> X
   136   WHILE p \<noteq> Null \<and> p \<noteq> 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