59 section "The heap" |
59 section "The heap" |
60 |
60 |
61 subsection "Paths in the heap" |
61 subsection "Paths in the heap" |
62 |
62 |
63 consts |
63 consts |
64 path :: "('a \<leadsto> 'a) \<Rightarrow> 'a ref \<Rightarrow> 'a list \<Rightarrow> 'a ref \<Rightarrow> bool" |
64 Path :: "('a \<leadsto> 'a) \<Rightarrow> 'a ref \<Rightarrow> 'a list \<Rightarrow> 'a ref \<Rightarrow> bool" |
65 primrec |
65 primrec |
66 "path h x [] y = (x = y)" |
66 "Path h x [] y = (x = y)" |
67 "path h x (a#as) y = (x = Ref a \<and> path h (h a) as y)" |
67 "Path h x (a#as) y = (x = Ref a \<and> Path h (h a) as y)" |
68 |
68 |
69 lemma [iff]: "path h Null xs y = (xs = [] \<and> y = Null)" |
69 lemma [iff]: "Path h Null xs y = (xs = [] \<and> y = Null)" |
70 apply(case_tac xs) |
70 apply(case_tac xs) |
71 apply fastsimp |
71 apply fastsimp |
72 apply fastsimp |
72 apply fastsimp |
73 done |
73 done |
74 |
74 |
75 lemma [simp]: "path h (Ref a) as z = |
75 lemma [simp]: "Path h (Ref a) as z = |
76 (as = [] \<and> z = Ref a \<or> (\<exists>bs. as = a#bs \<and> path h (h a) bs z))" |
76 (as = [] \<and> z = Ref a \<or> (\<exists>bs. as = a#bs \<and> Path h (h a) bs z))" |
77 apply(case_tac as) |
77 apply(case_tac as) |
78 apply fastsimp |
78 apply fastsimp |
79 apply fastsimp |
79 apply fastsimp |
80 done |
80 done |
81 |
81 |
82 lemma [simp]: "\<And>x. path f x (as@bs) z = (\<exists>y. path f x as y \<and> path f y bs z)" |
82 lemma [simp]: "\<And>x. Path f x (as@bs) z = (\<exists>y. Path f x as y \<and> Path f y bs z)" |
83 by(induct as, simp+) |
83 by(induct as, simp+) |
84 |
84 |
85 lemma [simp]: "\<And>x. u \<notin> set as \<Longrightarrow> path (f(u\<mapsto>v)) x as y = path f x as y" |
85 lemma [simp]: "\<And>x. u \<notin> set as \<Longrightarrow> Path (f(u\<mapsto>v)) x as y = Path f x as y" |
86 by(induct as, simp, simp add:eq_sym_conv) |
86 by(induct as, simp, simp add:eq_sym_conv) |
87 |
87 |
88 subsection "Lists on the heap" |
88 subsection "Lists on the heap" |
89 |
89 |
90 subsubsection "Relational abstraction" |
90 subsubsection "Relational abstraction" |
91 |
91 |
92 constdefs |
92 constdefs |
93 list :: "('a \<leadsto> 'a) \<Rightarrow> 'a option \<Rightarrow> 'a list \<Rightarrow> bool" |
93 List :: "('a \<leadsto> 'a) \<Rightarrow> 'a option \<Rightarrow> 'a list \<Rightarrow> bool" |
94 "list h x as == path h x as Null" |
94 "List h x as == Path h x as Null" |
95 |
95 |
96 lemma [simp]: "list h x [] = (x = Null)" |
96 lemma [simp]: "List h x [] = (x = Null)" |
97 by(simp add:list_def) |
97 by(simp add:List_def) |
98 |
98 |
99 lemma [simp]: "list h x (a#as) = (x = Ref a \<and> list h (h a) as)" |
99 lemma [simp]: "List h x (a#as) = (x = Ref a \<and> List h (h a) as)" |
100 by(simp add:list_def) |
100 by(simp add:List_def) |
101 |
101 |
102 lemma [simp]: "list h Null as = (as = [])" |
102 lemma [simp]: "List h Null as = (as = [])" |
103 by(case_tac as, simp_all) |
103 by(case_tac as, simp_all) |
104 |
104 |
105 lemma list_Ref[simp]: "list h (Ref a) as = (\<exists>bs. as = a#bs \<and> list h (h a) bs)" |
105 lemma List_Ref[simp]: "List h (Ref a) as = (\<exists>bs. as = a#bs \<and> List h (h a) bs)" |
106 by(case_tac as, simp_all, fast) |
106 by(case_tac as, simp_all, fast) |
107 |
107 |
108 |
108 |
109 declare fun_upd_apply[simp del]fun_upd_same[simp] fun_upd_other[simp] |
109 declare fun_upd_apply[simp del]fun_upd_same[simp] fun_upd_other[simp] |
110 |
110 |
111 lemma list_unique: "\<And>x bs. list h x as \<Longrightarrow> list h x bs \<Longrightarrow> as = bs" |
111 lemma List_unique: "\<And>x bs. List h x as \<Longrightarrow> List h x bs \<Longrightarrow> as = bs" |
112 by(induct as, simp, clarsimp) |
112 by(induct as, simp, clarsimp) |
113 |
113 |
114 lemma list_unique1: "list h p as \<Longrightarrow> \<exists>!as. list h p as" |
114 lemma List_unique1: "List h p as \<Longrightarrow> \<exists>!as. List h p as" |
115 by(blast intro:list_unique) |
115 by(blast intro:List_unique) |
116 |
116 |
117 lemma list_app: "\<And>x. list h x (as@bs) = (\<exists>y. path h x as y \<and> list h y bs)" |
117 lemma List_app: "\<And>x. List h x (as@bs) = (\<exists>y. Path h x as y \<and> List h y bs)" |
118 by(induct as, simp, clarsimp) |
118 by(induct as, simp, clarsimp) |
119 |
119 |
120 lemma list_hd_not_in_tl[simp]: "list h (h a) as \<Longrightarrow> a \<notin> set as" |
120 lemma List_hd_not_in_tl[simp]: "List h (h a) as \<Longrightarrow> a \<notin> set as" |
121 apply (clarsimp simp add:in_set_conv_decomp) |
121 apply (clarsimp simp add:in_set_conv_decomp) |
122 apply(frule list_app[THEN iffD1]) |
122 apply(frule List_app[THEN iffD1]) |
123 apply(fastsimp dest: list_unique) |
123 apply(fastsimp dest: List_unique) |
124 done |
124 done |
125 |
125 |
126 lemma list_distinct[simp]: "\<And>x. list h x as \<Longrightarrow> distinct as" |
126 lemma List_distinct[simp]: "\<And>x. List h x as \<Longrightarrow> distinct as" |
127 apply(induct as, simp) |
127 apply(induct as, simp) |
128 apply(fastsimp dest:list_hd_not_in_tl) |
128 apply(fastsimp dest:List_hd_not_in_tl) |
129 done |
129 done |
130 |
130 |
131 theorem notin_list_update[simp]: |
131 theorem notin_List_update[simp]: |
132 "\<And>x. a \<notin> set as \<Longrightarrow> list (h(a := y)) x as = list h x as" |
132 "\<And>x. a \<notin> set as \<Longrightarrow> List (h(a := y)) x as = List h x as" |
133 apply(induct as) |
133 apply(induct as) |
134 apply simp |
134 apply simp |
135 apply(clarsimp simp add:fun_upd_apply) |
135 apply(clarsimp simp add:fun_upd_apply) |
136 done |
136 done |
137 |
137 |
138 subsection "Functional abstraction" |
138 subsection "Functional abstraction" |
139 |
139 |
140 constdefs |
140 constdefs |
141 islist :: "('a \<Rightarrow> 'a ref) \<Rightarrow> 'a ref \<Rightarrow> bool" |
141 islist :: "('a \<Rightarrow> 'a ref) \<Rightarrow> 'a ref \<Rightarrow> bool" |
142 "islist h p == \<exists>as. list h p as" |
142 "islist h p == \<exists>as. List h p as" |
143 mklist :: "('a \<Rightarrow> 'a ref) \<Rightarrow> 'a ref \<Rightarrow> 'a list" |
143 list :: "('a \<Rightarrow> 'a ref) \<Rightarrow> 'a ref \<Rightarrow> 'a list" |
144 "mklist h p == SOME as. list h p as" |
144 "list h p == SOME as. List h p as" |
145 |
145 |
146 lemma list_conv_islist_mklist: "list h p as = (islist h p \<and> as = mklist h p)" |
146 lemma List_conv_islist_list: "List h p as = (islist h p \<and> as = list h p)" |
147 apply(simp add:islist_def mklist_def) |
147 apply(simp add:islist_def list_def) |
148 apply(rule iffI) |
148 apply(rule iffI) |
149 apply(rule conjI) |
149 apply(rule conjI) |
150 apply blast |
150 apply blast |
151 apply(subst some1_equality) |
151 apply(subst some1_equality) |
152 apply(erule list_unique1) |
152 apply(erule List_unique1) |
153 apply assumption |
153 apply assumption |
154 apply(rule refl) |
154 apply(rule refl) |
155 apply simp |
155 apply simp |
156 apply(rule someI_ex) |
156 apply(rule someI_ex) |
157 apply fast |
157 apply fast |
161 by(simp add:islist_def) |
161 by(simp add:islist_def) |
162 |
162 |
163 lemma [simp]: "islist h (Some a) = islist h (h a)" |
163 lemma [simp]: "islist h (Some a) = islist h (h a)" |
164 by(simp add:islist_def) |
164 by(simp add:islist_def) |
165 |
165 |
166 lemma [simp]: "mklist h None = []" |
166 lemma [simp]: "list h None = []" |
167 by(simp add:mklist_def) |
167 by(simp add:list_def) |
168 |
168 |
169 lemma [simp]: "islist h (h a) \<Longrightarrow> mklist h (Some a) = a # mklist h (h a)" |
169 lemma [simp]: "islist h (h a) \<Longrightarrow> list h (Some a) = a # list h (h a)" |
170 apply(insert list_Ref[of h]) |
170 apply(insert List_Ref[of h]) |
171 apply(fastsimp simp:list_conv_islist_mklist) |
171 apply(fastsimp simp:List_conv_islist_list) |
172 done |
172 done |
173 |
173 |
174 lemma [simp]: "islist h (h a) \<Longrightarrow> a \<notin> set(mklist h (h a))" |
174 lemma [simp]: "islist h (h a) \<Longrightarrow> a \<notin> set(list h (h a))" |
175 apply(insert list_hd_not_in_tl[of h]) |
175 apply(insert List_hd_not_in_tl[of h]) |
176 apply(simp add:list_conv_islist_mklist) |
176 apply(simp add:List_conv_islist_list) |
177 done |
177 done |
178 |
178 |
179 lemma [simp]: |
179 lemma [simp]: |
180 "islist h p \<Longrightarrow> y \<notin> set(mklist h p) \<Longrightarrow> mklist (h(y := q)) p = mklist h p" |
180 "islist h p \<Longrightarrow> y \<notin> set(list h p) \<Longrightarrow> list (h(y := q)) p = list h p" |
181 apply(drule notin_list_update[of _ _ h q p]) |
181 apply(drule notin_List_update[of _ _ h q p]) |
182 apply(simp add:list_conv_islist_mklist) |
182 apply(simp add:List_conv_islist_list) |
183 done |
183 done |
184 |
184 |
185 lemma [simp]: |
185 lemma [simp]: |
186 "islist h p \<Longrightarrow> y \<notin> set(mklist h p) \<Longrightarrow> islist (h(y := q)) p" |
186 "islist h p \<Longrightarrow> y \<notin> set(list h p) \<Longrightarrow> islist (h(y := q)) p" |
187 apply(frule notin_list_update[of _ _ h q p]) |
187 apply(frule notin_List_update[of _ _ h q p]) |
188 apply(simp add:list_conv_islist_mklist) |
188 apply(simp add:List_conv_islist_list) |
189 done |
189 done |
190 |
190 |
191 |
191 |
192 section "Verifications" |
192 section "Verifications" |
193 |
193 |
194 subsection "List reversal" |
194 subsection "List reversal" |
195 |
195 |
196 text "A short but unreadable proof:" |
196 text "A short but unreadable proof:" |
197 |
197 |
198 lemma "|- VARS tl p q r. |
198 lemma "|- VARS tl p q r. |
199 {list tl p Ps \<and> list tl q Qs \<and> set Ps \<inter> set Qs = {}} |
199 {List tl p Ps \<and> List tl q Qs \<and> set Ps \<inter> set Qs = {}} |
200 WHILE p \<noteq> Null |
200 WHILE p \<noteq> Null |
201 INV {\<exists>ps qs. list tl p ps \<and> list tl q qs \<and> set ps \<inter> set qs = {} \<and> |
201 INV {\<exists>ps qs. List tl p ps \<and> List tl q qs \<and> set ps \<inter> set qs = {} \<and> |
202 rev ps @ qs = rev Ps @ Qs} |
202 rev ps @ qs = rev Ps @ Qs} |
203 DO r := p; p := p^.tl; r^.tl := q; q := r OD |
203 DO r := p; p := p^.tl; r^.tl := q; q := r OD |
204 {list tl q (rev Ps @ Qs)}" |
204 {List tl q (rev Ps @ Qs)}" |
205 apply vcg_simp |
205 apply vcg_simp |
206 apply fastsimp |
206 apply fastsimp |
207 apply clarify |
207 apply clarify |
208 apply(rename_tac ps b qs) |
208 apply(rename_tac ps b qs) |
209 apply clarsimp |
209 apply clarsimp |
217 |
217 |
218 |
218 |
219 text "A longer readable version:" |
219 text "A longer readable version:" |
220 |
220 |
221 lemma "|- VARS tl p q r. |
221 lemma "|- VARS tl p q r. |
222 {list tl p Ps \<and> list tl q Qs \<and> set Ps \<inter> set Qs = {}} |
222 {List tl p Ps \<and> List tl q Qs \<and> set Ps \<inter> set Qs = {}} |
223 WHILE p \<noteq> Null |
223 WHILE p \<noteq> Null |
224 INV {\<exists>ps qs. list tl p ps \<and> list tl q qs \<and> set ps \<inter> set qs = {} \<and> |
224 INV {\<exists>ps qs. List tl p ps \<and> List tl q qs \<and> set ps \<inter> set qs = {} \<and> |
225 rev ps @ qs = rev Ps @ Qs} |
225 rev ps @ qs = rev Ps @ Qs} |
226 DO r := p; p := p^.tl; r^.tl := q; q := r OD |
226 DO r := p; p := p^.tl; r^.tl := q; q := r OD |
227 {list tl q (rev Ps @ Qs)}" |
227 {List tl q (rev Ps @ Qs)}" |
228 proof vcg |
228 proof vcg |
229 fix tl p q r |
229 fix tl p q r |
230 assume "list tl p Ps \<and> list tl q Qs \<and> set Ps \<inter> set Qs = {}" |
230 assume "List tl p Ps \<and> List tl q Qs \<and> set Ps \<inter> set Qs = {}" |
231 thus "\<exists>ps qs. list tl p ps \<and> list tl q qs \<and> set ps \<inter> set qs = {} \<and> |
231 thus "\<exists>ps qs. List tl p ps \<and> List tl q qs \<and> set ps \<inter> set qs = {} \<and> |
232 rev ps @ qs = rev Ps @ Qs" by fastsimp |
232 rev ps @ qs = rev Ps @ Qs" by fastsimp |
233 next |
233 next |
234 fix tl p q r |
234 fix tl p q r |
235 assume "(\<exists>ps qs. list tl p ps \<and> list tl q qs \<and> set ps \<inter> set qs = {} \<and> |
235 assume "(\<exists>ps qs. List tl p ps \<and> List tl q qs \<and> set ps \<inter> set qs = {} \<and> |
236 rev ps @ qs = rev Ps @ Qs) \<and> p \<noteq> Null" |
236 rev ps @ qs = rev Ps @ Qs) \<and> p \<noteq> Null" |
237 (is "(\<exists>ps qs. ?I ps qs) \<and> _") |
237 (is "(\<exists>ps qs. ?I ps qs) \<and> _") |
238 then obtain ps qs a where I: "?I ps qs \<and> p = Ref a" |
238 then obtain ps qs a where I: "?I ps qs \<and> p = Ref a" |
239 by fast |
239 by fast |
240 then obtain ps' where "ps = a # ps'" by fastsimp |
240 then obtain ps' where "ps = a # ps'" by fastsimp |
241 hence "list (tl(p \<rightarrow> q)) (p^.tl) ps' \<and> |
241 hence "List (tl(p \<rightarrow> q)) (p^.tl) ps' \<and> |
242 list (tl(p \<rightarrow> q)) p (a#qs) \<and> |
242 List (tl(p \<rightarrow> q)) p (a#qs) \<and> |
243 set ps' \<inter> set (a#qs) = {} \<and> |
243 set ps' \<inter> set (a#qs) = {} \<and> |
244 rev ps' @ (a#qs) = rev Ps @ Qs" |
244 rev ps' @ (a#qs) = rev Ps @ Qs" |
245 using I by fastsimp |
245 using I by fastsimp |
246 thus "\<exists>ps' qs'. list (tl(p \<rightarrow> q)) (p^.tl) ps' \<and> |
246 thus "\<exists>ps' qs'. List (tl(p \<rightarrow> q)) (p^.tl) ps' \<and> |
247 list (tl(p \<rightarrow> q)) p qs' \<and> |
247 List (tl(p \<rightarrow> q)) p qs' \<and> |
248 set ps' \<inter> set qs' = {} \<and> |
248 set ps' \<inter> set qs' = {} \<and> |
249 rev ps' @ qs' = rev Ps @ Qs" by fast |
249 rev ps' @ qs' = rev Ps @ Qs" by fast |
250 next |
250 next |
251 fix tl p q r |
251 fix tl p q r |
252 assume "(\<exists>ps qs. list tl p ps \<and> list tl q qs \<and> set ps \<inter> set qs = {} \<and> |
252 assume "(\<exists>ps qs. List tl p ps \<and> List tl q qs \<and> set ps \<inter> set qs = {} \<and> |
253 rev ps @ qs = rev Ps @ Qs) \<and> \<not> p \<noteq> Null" |
253 rev ps @ qs = rev Ps @ Qs) \<and> \<not> p \<noteq> Null" |
254 thus "list tl q (rev Ps @ Qs)" by fastsimp |
254 thus "List tl q (rev Ps @ Qs)" by fastsimp |
255 qed |
255 qed |
256 |
256 |
257 |
257 |
258 text{* Finaly, the functional version. A bit more verbose, but automatic! *} |
258 text{* Finaly, the functional version. A bit more verbose, but automatic! *} |
259 |
259 |
260 lemma "|- VARS tl p q r. |
260 lemma "|- VARS tl p q r. |
261 {islist tl p \<and> islist tl q \<and> |
261 {islist tl p \<and> islist tl q \<and> |
262 Ps = mklist tl p \<and> Qs = mklist tl q \<and> set Ps \<inter> set Qs = {}} |
262 Ps = list tl p \<and> Qs = list tl q \<and> set Ps \<inter> set Qs = {}} |
263 WHILE p \<noteq> Null |
263 WHILE p \<noteq> Null |
264 INV {islist tl p \<and> islist tl q \<and> |
264 INV {islist tl p \<and> islist tl q \<and> |
265 set(mklist tl p) \<inter> set(mklist tl q) = {} \<and> |
265 set(list tl p) \<inter> set(list tl q) = {} \<and> |
266 rev(mklist tl p) @ (mklist tl q) = rev Ps @ Qs} |
266 rev(list tl p) @ (list tl q) = rev Ps @ Qs} |
267 DO r := p; p := p^.tl; r^.tl := q; q := r OD |
267 DO r := p; p := p^.tl; r^.tl := q; q := r OD |
268 {islist tl q \<and> mklist tl q = rev Ps @ Qs}" |
268 {islist tl q \<and> list tl q = rev Ps @ Qs}" |
269 apply vcg_simp |
269 apply vcg_simp |
270 apply clarsimp |
270 apply clarsimp |
271 apply clarsimp |
271 apply clarsimp |
272 apply clarsimp |
272 apply clarsimp |
273 done |
273 done |
380 by blast |
380 by blast |
381 |
381 |
382 declare imp_disjL[simp del] imp_disjCL[simp] |
382 declare imp_disjL[simp del] imp_disjCL[simp] |
383 |
383 |
384 lemma "|- VARS hd tl p q r s. |
384 lemma "|- VARS hd tl p q r s. |
385 {list tl p Ps \<and> list tl q Qs \<and> set Ps \<inter> set Qs = {} \<and> |
385 {List tl p Ps \<and> List tl q Qs \<and> set Ps \<inter> set Qs = {} \<and> |
386 (p \<noteq> Null \<or> q \<noteq> Null)} |
386 (p \<noteq> Null \<or> q \<noteq> Null)} |
387 IF if q = Null then True else p \<noteq> Null \<and> p^.hd \<le> q^.hd |
387 IF if q = Null then True else p \<noteq> Null \<and> p^.hd \<le> q^.hd |
388 THEN r := p; p := p^.tl ELSE r := q; q := q^.tl FI; |
388 THEN r := p; p := p^.tl ELSE r := q; q := q^.tl FI; |
389 s := r; |
389 s := r; |
390 WHILE p \<noteq> Null \<or> q \<noteq> Null |
390 WHILE p \<noteq> Null \<or> q \<noteq> Null |
391 INV {EX rs ps qs a. path tl r rs s \<and> list tl p ps \<and> list tl q qs \<and> |
391 INV {EX rs ps qs a. Path tl r rs s \<and> List tl p ps \<and> List tl q qs \<and> |
392 distinct(a # ps @ qs @ rs) \<and> s = Ref a \<and> |
392 distinct(a # ps @ qs @ rs) \<and> s = Ref a \<and> |
393 merge(Ps,Qs,\<lambda>x y. hd x \<le> hd y) = |
393 merge(Ps,Qs,\<lambda>x y. hd x \<le> hd y) = |
394 rs @ a # merge(ps,qs,\<lambda>x y. hd x \<le> hd y) \<and> |
394 rs @ a # merge(ps,qs,\<lambda>x y. hd x \<le> hd y) \<and> |
395 (tl a = p \<or> tl a = q)} |
395 (tl a = p \<or> tl a = q)} |
396 DO IF if q = Null then True else p \<noteq> Null \<and> p^.hd \<le> q^.hd |
396 DO IF if q = Null then True else p \<noteq> Null \<and> p^.hd \<le> q^.hd |
397 THEN s^.tl := p; p := p^.tl ELSE s^.tl := q; q := q^.tl FI; |
397 THEN s^.tl := p; p := p^.tl ELSE s^.tl := q; q := q^.tl FI; |
398 s := s^.tl |
398 s := s^.tl |
399 OD |
399 OD |
400 {list tl r (merge(Ps,Qs,\<lambda>x y. hd x \<le> hd y))}" |
400 {List tl r (merge(Ps,Qs,\<lambda>x y. hd x \<le> hd y))}" |
401 apply vcg_simp |
401 apply vcg_simp |
402 |
402 |
403 apply (fastsimp) |
403 apply (fastsimp) |
404 |
404 |
405 apply clarsimp |
405 apply clarsimp |