# HG changeset patch # User nipkow # Date 1041946324 -3600 # Node ID 58dc4ab362d0b9eed3b46d39006497e08b08876d # Parent 73d041cc6a667a69d75366c1dd5599d6342195e1 new versions of merge-example diff -r 73d041cc6a66 -r 58dc4ab362d0 src/HOL/Hoare/Pointer_Examples.thy --- a/src/HOL/Hoare/Pointer_Examples.thy Mon Jan 06 11:22:54 2003 +0100 +++ b/src/HOL/Hoare/Pointer_Examples.thy Tue Jan 07 14:32:04 2003 +0100 @@ -170,6 +170,12 @@ text"This is still a bit rough, especially the proof." +constdefs + cor :: "bool \ bool \ bool" +"cor P Q == if P then True else Q" + cand :: "bool \ bool \ bool" +"cand P Q == if P then Q else False" + consts merge :: "'a list * 'a list * ('a \ 'a \ bool) \ 'a list" recdef merge "measure(%(xs,ys,f). size xs + size ys)" @@ -179,15 +185,19 @@ "merge([],y#ys,f) = y # merge([],ys,f)" "merge([],[],f) = []" -lemma imp_disjCL: "(P|Q \ R) = ((P \ R) \ (~P \ Q \ R))" +text{* Simplifies the proof a little: *} + +lemma [simp]: "({} = insert a A \ B) = (a \ B & {} = A \ B)" by blast - -declare imp_disjL[simp del] imp_disjCL[simp] +lemma [simp]: "({} = A \ insert b B) = (b \ A & {} = A \ B)" +by blast +lemma [simp]: "({} = A \ (B \ C)) = ({} = A \ B & {} = A \ C)" +by blast lemma "VARS hd tl p q r s {List tl p Ps \ List tl q Qs \ set Ps \ set Qs = {} \ (p \ Null \ q \ Null)} - IF if q = Null then True else p \ Null \ p^.hd \ q^.hd + IF cor (q = Null) (cand (p \ Null) (p^.hd \ q^.hd)) THEN r := p; p := p^.tl ELSE r := q; q := q^.tl FI; s := r; WHILE p \ Null \ q \ Null @@ -196,28 +206,116 @@ merge(Ps,Qs,\x y. hd x \ hd y) = rs @ a # merge(ps,qs,\x y. hd x \ hd y) \ (tl a = p \ tl a = q)} - DO IF if q = Null then True else p \ Null \ p^.hd \ q^.hd + DO IF cor (q = Null) (cand (p \ Null) (p^.hd \ q^.hd)) THEN s^.tl := p; p := p^.tl ELSE s^.tl := q; q := q^.tl FI; s := s^.tl OD {List tl r (merge(Ps,Qs,\x y. hd x \ hd y))}" apply vcg_simp +apply (simp_all add: cand_def cor_def) apply (fastsimp) -(* One big fastsimp does not seem to converge: *) +apply clarsimp +apply(rule conjI) apply clarsimp apply(rule conjI) apply (fastsimp intro!:Path_snoc intro:Path_upd[THEN iffD2] notin_List_update[THEN iffD2] simp:eq_sym_conv) apply clarsimp apply(rule conjI) -apply (fastsimp intro!:Path_snoc intro:Path_upd[THEN iffD2] notin_List_update[THEN iffD2] simp:eq_sym_conv) +apply (clarsimp) +apply(rule_tac x = "rs @ [a]" in exI) +apply(clarsimp simp:eq_sym_conv) +apply(rule_tac x = "bs" in exI) +apply(clarsimp simp:eq_sym_conv) +apply(rule_tac x = "ya#bsa" in exI) +apply(simp) +apply(clarsimp simp:eq_sym_conv) +apply(rule_tac x = "rs @ [a]" in exI) +apply(clarsimp simp:eq_sym_conv) +apply(rule_tac x = "y#bs" in exI) +apply(clarsimp simp:eq_sym_conv) +apply(rule_tac x = "bsa" in exI) +apply(simp) apply (fastsimp intro!:Path_snoc intro:Path_upd[THEN iffD2] notin_List_update[THEN iffD2] simp:eq_sym_conv) apply(clarsimp simp add:List_app) done -(* merging with islist/list instead of List? Unlikely to be simpler *) + +text{* More of the proof can be automated, but the runtime goes up +drastically. In general it is usually more efficient to give the +witness directly than to have it found by proof. + +Now we try a functional version of the abstraction relation @{term +Path}. Since the result is not that convincing, we do not prove any of +the lemmas.*} + +consts ispath:: "('a \ 'a ref) \ 'a ref \ 'a ref \ bool" + path:: "('a \ 'a ref) \ 'a ref \ 'a ref \ 'a list" + +ML"set quick_and_dirty" + +text"First some basic lemmas:" + +lemma [simp]: "ispath f p p" +sorry +lemma [simp]: "path f p p = []" +sorry +lemma [simp]: "ispath f p q \ a \ set(path f p q) \ ispath (f(a := r)) p q" +sorry +lemma [simp]: "ispath f p q \ a \ set(path f p q) \ + path (f(a := r)) p q = path f p q" +sorry + +text"Some more specific lemmas needed by the example:" + +lemma [simp]: "ispath (f(a := q)) p (Ref a) \ ispath (f(a := q)) p q" +sorry +lemma [simp]: "ispath (f(a := q)) p (Ref a) \ + path (f(a := q)) p q = path (f(a := q)) p (Ref a) @ [a]" +sorry +lemma [simp]: "ispath f p (Ref a) \ f a = Ref b \ + b \ set (path f p (Ref a))" +sorry +lemma [simp]: "ispath f p (Ref a) \ f a = Null \ islist f p" +sorry +lemma [simp]: "ispath f p (Ref a) \ f a = Null \ list f p = path f p (Ref a) @ [a]" +sorry + +lemma [simp]: "islist f p \ distinct (list f p)" +sorry +ML"reset quick_and_dirty" + +lemma "VARS hd tl p q r s + {islist tl p & Ps = list tl p \ islist tl q & Qs = list tl q \ + set Ps \ set Qs = {} \ + (p \ Null \ q \ Null)} + IF cor (q = Null) (cand (p \ Null) (p^.hd \ q^.hd)) + THEN r := p; p := p^.tl ELSE r := q; q := q^.tl FI; + s := r; + WHILE p \ Null \ q \ Null + INV {EX rs ps qs a. ispath tl r s & rs = path tl r s \ + islist tl p & ps = list tl p \ islist tl q & qs = list tl q \ + distinct(a # ps @ qs @ rs) \ s = Ref a \ + merge(Ps,Qs,\x y. hd x \ hd y) = + rs @ a # merge(ps,qs,\x y. hd x \ hd y) \ + (tl a = p \ tl a = q)} + DO IF cor (q = Null) (cand (p \ Null) (p^.hd \ q^.hd)) + THEN s^.tl := p; p := p^.tl ELSE s^.tl := q; q := q^.tl FI; + s := s^.tl + OD + {islist tl r & list tl r = (merge(Ps,Qs,\x y. hd x \ hd y))}" +apply vcg_simp + +apply (simp_all add: cand_def cor_def) + apply (fastsimp) + apply (fastsimp simp: eq_sym_conv) +apply(clarsimp) +done + +text"The proof is automatic, but requires a numbet of special lemmas." + subsection "Storage allocation"