author | wenzelm |
Wed, 12 Mar 2025 11:39:00 +0100 | |
changeset 82265 | 4b875a4c83b0 |
parent 81349 | d026fa14433b |
permissions | -rw-r--r-- |
22803 | 1 |
(* Title: HOL/Library/While_Combinator.thy |
10251 | 2 |
Author: Tobias Nipkow |
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
3 |
Author: Alexander Krauss |
10251 | 4 |
*) |
5 |
||
60500 | 6 |
section \<open>A general ``while'' combinator\<close> |
10251 | 7 |
|
15131 | 8 |
theory While_Combinator |
30738 | 9 |
imports Main |
15131 | 10 |
begin |
10251 | 11 |
|
60500 | 12 |
subsection \<open>Partial version\<close> |
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
13 |
|
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
14 |
definition while_option :: "('a \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> 'a) \<Rightarrow> 'a \<Rightarrow> 'a option" where |
67091 | 15 |
"while_option b c s = (if (\<exists>k. \<not> b ((c ^^ k) s)) |
16 |
then Some ((c ^^ (LEAST k. \<not> b ((c ^^ k) s))) s) |
|
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
17 |
else None)" |
10251 | 18 |
|
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
19 |
theorem while_option_unfold[code]: |
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
20 |
"while_option b c s = (if b s then while_option b c (c s) else Some s)" |
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
21 |
proof cases |
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
22 |
assume "b s" |
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
23 |
show ?thesis |
67091 | 24 |
proof (cases "\<exists>k. \<not> b ((c ^^ k) s)") |
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
25 |
case True |
67091 | 26 |
then obtain k where 1: "\<not> b ((c ^^ k) s)" .. |
60500 | 27 |
with \<open>b s\<close> obtain l where "k = Suc l" by (cases k) auto |
67091 | 28 |
with 1 have "\<not> b ((c ^^ l) (c s))" by (auto simp: funpow_swap1) |
29 |
then have 2: "\<exists>l. \<not> b ((c ^^ l) (c s))" .. |
|
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
30 |
from 1 |
67091 | 31 |
have "(LEAST k. \<not> b ((c ^^ k) s)) = Suc (LEAST l. \<not> b ((c ^^ Suc l) s))" |
60500 | 32 |
by (rule Least_Suc) (simp add: \<open>b s\<close>) |
67091 | 33 |
also have "... = Suc (LEAST l. \<not> b ((c ^^ l) (c s)))" |
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
34 |
by (simp add: funpow_swap1) |
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
35 |
finally |
81347 | 36 |
show ?thesis |
60500 | 37 |
using True 2 \<open>b s\<close> by (simp add: funpow_swap1 while_option_def) |
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
38 |
next |
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
39 |
case False |
67091 | 40 |
then have "\<not> (\<exists>l. \<not> b ((c ^^ Suc l) s))" by blast |
41 |
then have "\<not> (\<exists>l. \<not> b ((c ^^ l) (c s)))" |
|
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
42 |
by (simp add: funpow_swap1) |
60500 | 43 |
with False \<open>b s\<close> show ?thesis by (simp add: while_option_def) |
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
44 |
qed |
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
45 |
next |
67091 | 46 |
assume [simp]: "\<not> b s" |
47 |
have least: "(LEAST k. \<not> b ((c ^^ k) s)) = 0" |
|
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
48 |
by (rule Least_equality) auto |
81347 | 49 |
moreover |
67091 | 50 |
have "\<exists>k. \<not> b ((c ^^ k) s)" by (rule exI[of _ "0::nat"]) auto |
81347 | 51 |
ultimately show ?thesis unfolding while_option_def by auto |
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
52 |
qed |
10251 | 53 |
|
45834 | 54 |
lemma while_option_stop2: |
67091 | 55 |
"while_option b c s = Some t \<Longrightarrow> \<exists>k. t = (c^^k) s \<and> \<not> b t" |
45834 | 56 |
apply(simp add: while_option_def split: if_splits) |
46365 | 57 |
by (metis (lifting) LeastI_ex) |
45834 | 58 |
|
67091 | 59 |
lemma while_option_stop: "while_option b c s = Some t \<Longrightarrow> \<not> b t" |
45834 | 60 |
by(metis while_option_stop2) |
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
61 |
|
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
62 |
theorem while_option_rule: |
81347 | 63 |
assumes step: "\<And>s. P s \<Longrightarrow> b s \<Longrightarrow> P (c s)" |
63040 | 64 |
and result: "while_option b c s = Some t" |
65 |
and init: "P s" |
|
66 |
shows "P t" |
|
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
67 |
proof - |
67091 | 68 |
define k where "k = (LEAST k. \<not> b ((c ^^ k) s))" |
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
69 |
from assms have t: "t = (c ^^ k) s" |
81347 | 70 |
by (simp add: while_option_def k_def split: if_splits) |
67717 | 71 |
have 1: "\<forall>i<k. b ((c ^^ i) s)" |
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
72 |
by (auto simp: k_def dest: not_less_Least) |
81349 | 73 |
have "i \<le> k \<Longrightarrow> P ((c ^^ i) s)" for i |
74 |
by (induct i) (auto simp: init step 1) |
|
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
75 |
thus "P t" by (auto simp: t) |
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
76 |
qed |
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
77 |
|
81347 | 78 |
lemma funpow_commute: |
50577 | 79 |
"\<lbrakk>\<forall>k' < k. f (c ((c^^k') s)) = c' (f ((c^^k') s))\<rbrakk> \<Longrightarrow> f ((c^^k) s) = (c'^^k) (f s)" |
80 |
by (induct k arbitrary: s) auto |
|
81 |
||
54050 | 82 |
lemma while_option_commute_invariant: |
83 |
assumes Invariant: "\<And>s. P s \<Longrightarrow> b s \<Longrightarrow> P (c s)" |
|
84 |
assumes TestCommute: "\<And>s. P s \<Longrightarrow> b s = b' (f s)" |
|
85 |
assumes BodyCommute: "\<And>s. P s \<Longrightarrow> b s \<Longrightarrow> f (c s) = c' (f s)" |
|
86 |
assumes Initial: "P s" |
|
55466 | 87 |
shows "map_option f (while_option b c s) = while_option b' c' (f s)" |
50577 | 88 |
unfolding while_option_def |
89 |
proof (rule trans[OF if_distrib if_cong], safe, unfold option.inject) |
|
54050 | 90 |
fix k |
91 |
assume "\<not> b ((c ^^ k) s)" |
|
92 |
with Initial show "\<exists>k. \<not> b' ((c' ^^ k) (f s))" |
|
50577 | 93 |
proof (induction k arbitrary: s) |
54050 | 94 |
case 0 thus ?case by (auto simp: TestCommute intro: exI[of _ 0]) |
50577 | 95 |
next |
54050 | 96 |
case (Suc k) thus ?case |
97 |
proof (cases "b s") |
|
98 |
assume "b s" |
|
99 |
with Suc.IH[of "c s"] Suc.prems show ?thesis |
|
100 |
by (metis BodyCommute Invariant comp_apply funpow.simps(2) funpow_swap1) |
|
101 |
next |
|
102 |
assume "\<not> b s" |
|
103 |
with Suc show ?thesis by (auto simp: TestCommute intro: exI [of _ 0]) |
|
104 |
qed |
|
50577 | 105 |
qed |
106 |
next |
|
54050 | 107 |
fix k |
108 |
assume "\<not> b' ((c' ^^ k) (f s))" |
|
109 |
with Initial show "\<exists>k. \<not> b ((c ^^ k) s)" |
|
50577 | 110 |
proof (induction k arbitrary: s) |
54050 | 111 |
case 0 thus ?case by (auto simp: TestCommute intro: exI[of _ 0]) |
50577 | 112 |
next |
54050 | 113 |
case (Suc k) thus ?case |
50577 | 114 |
proof (cases "b s") |
54050 | 115 |
assume "b s" |
116 |
with Suc.IH[of "c s"] Suc.prems show ?thesis |
|
117 |
by (metis BodyCommute Invariant comp_apply funpow.simps(2) funpow_swap1) |
|
118 |
next |
|
119 |
assume "\<not> b s" |
|
120 |
with Suc show ?thesis by (auto simp: TestCommute intro: exI [of _ 0]) |
|
121 |
qed |
|
50577 | 122 |
qed |
123 |
next |
|
54050 | 124 |
fix k |
125 |
assume k: "\<not> b' ((c' ^^ k) (f s))" |
|
126 |
have *: "(LEAST k. \<not> b' ((c' ^^ k) (f s))) = (LEAST k. \<not> b ((c ^^ k) s))" |
|
127 |
(is "?k' = ?k") |
|
50577 | 128 |
proof (cases ?k') |
129 |
case 0 |
|
54050 | 130 |
have "\<not> b' ((c' ^^ 0) (f s))" |
131 |
unfolding 0[symmetric] by (rule LeastI[of _ k]) (rule k) |
|
132 |
hence "\<not> b s" by (auto simp: TestCommute Initial) |
|
50577 | 133 |
hence "?k = 0" by (intro Least_equality) auto |
134 |
with 0 show ?thesis by auto |
|
135 |
next |
|
136 |
case (Suc k') |
|
54050 | 137 |
have "\<not> b' ((c' ^^ Suc k') (f s))" |
138 |
unfolding Suc[symmetric] by (rule LeastI) (rule k) |
|
50577 | 139 |
moreover |
81349 | 140 |
have b': "b' ((c' ^^ k) (f s))" if asm: "k \<le> k'" for k |
81347 | 141 |
proof - |
81349 | 142 |
from asm have "k < ?k'" unfolding Suc by simp |
81347 | 143 |
thus ?thesis by (rule iffD1[OF not_not, OF not_less_Least]) |
144 |
qed |
|
145 |
have b: "b ((c ^^ k) s)" |
|
146 |
and body: "f ((c ^^ k) s) = (c' ^^ k) (f s)" |
|
147 |
and inv: "P ((c ^^ k) s)" |
|
81349 | 148 |
if asm: "k \<le> k'" for k |
81347 | 149 |
proof - |
81349 | 150 |
from asm have "f ((c ^^ k) s) = (c' ^^ k) (f s)" |
81347 | 151 |
and "b ((c ^^ k) s) = b' ((c' ^^ k) (f s))" |
152 |
and "P ((c ^^ k) s)" |
|
54050 | 153 |
by (induct k) (auto simp: b' assms) |
60500 | 154 |
with \<open>k \<le> k'\<close> |
81347 | 155 |
show "b ((c ^^ k) s)" |
156 |
and "f ((c ^^ k) s) = (c' ^^ k) (f s)" |
|
157 |
and "P ((c ^^ k) s)" |
|
54050 | 158 |
by (auto simp: b') |
81347 | 159 |
qed |
54050 | 160 |
hence k': "f ((c ^^ k') s) = (c' ^^ k') (f s)" by auto |
50577 | 161 |
ultimately show ?thesis unfolding Suc using b |
61166
5976fe402824
renamed method "goals" to "goal_cases" to emphasize its meaning;
wenzelm
parents:
61115
diff
changeset
|
162 |
proof (intro Least_equality[symmetric], goal_cases) |
60580 | 163 |
case 1 |
54050 | 164 |
hence Test: "\<not> b' (f ((c ^^ Suc k') s))" |
165 |
by (auto simp: BodyCommute inv b) |
|
166 |
have "P ((c ^^ Suc k') s)" by (auto simp: Invariant inv b) |
|
167 |
with Test show ?case by (auto simp: TestCommute) |
|
168 |
next |
|
60580 | 169 |
case 2 |
170 |
thus ?case by (metis not_less_eq_eq) |
|
54050 | 171 |
qed |
50577 | 172 |
qed |
173 |
have "f ((c ^^ ?k) s) = (c' ^^ ?k') (f s)" unfolding * |
|
54050 | 174 |
proof (rule funpow_commute, clarify) |
175 |
fix k assume "k < ?k" |
|
176 |
hence TestTrue: "b ((c ^^ k) s)" by (auto dest: not_less_Least) |
|
60500 | 177 |
from \<open>k < ?k\<close> have "P ((c ^^ k) s)" |
54050 | 178 |
proof (induct k) |
179 |
case 0 thus ?case by (auto simp: assms) |
|
180 |
next |
|
181 |
case (Suc h) |
|
182 |
hence "P ((c ^^ h) s)" by auto |
|
183 |
with Suc show ?case |
|
184 |
by (auto, metis (lifting, no_types) Invariant Suc_lessD not_less_Least) |
|
185 |
qed |
|
186 |
with TestTrue show "f (c ((c ^^ k) s)) = c' (f ((c ^^ k) s))" |
|
187 |
by (metis BodyCommute) |
|
188 |
qed |
|
50577 | 189 |
thus "\<exists>z. (c ^^ ?k) s = z \<and> f z = (c' ^^ ?k') (f s)" by blast |
190 |
qed |
|
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
191 |
|
54050 | 192 |
lemma while_option_commute: |
81347 | 193 |
assumes "\<And>s. b s = b' (f s)" "\<And>s. \<lbrakk>b s\<rbrakk> \<Longrightarrow> f (c s) = c' (f s)" |
55466 | 194 |
shows "map_option f (while_option b c s) = while_option b' c' (f s)" |
54050 | 195 |
by(rule while_option_commute_invariant[where P = "\<lambda>_. True"]) |
196 |
(auto simp add: assms) |
|
197 |
||
60500 | 198 |
subsection \<open>Total version\<close> |
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
199 |
|
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
200 |
definition while :: "('a \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> 'a) \<Rightarrow> 'a \<Rightarrow> 'a" |
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
201 |
where "while b c s = the (while_option b c s)" |
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
202 |
|
50008 | 203 |
lemma while_unfold [code]: |
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
204 |
"while b c s = (if b s then while b c (c s) else s)" |
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
205 |
unfolding while_def by (subst while_option_unfold) simp |
10984 | 206 |
|
18372 | 207 |
lemma def_while_unfold: |
208 |
assumes fdef: "f == while test do" |
|
209 |
shows "f x = (if test x then f(do x) else x)" |
|
37757
dc78d2d9e90a
added "while_option", which needs no well-foundedness; defined "while" in terms of "while_option"
krauss
parents:
30738
diff
changeset
|
210 |
unfolding fdef by (fact while_unfold) |
14300 | 211 |
|
212 |
||
60500 | 213 |
text \<open> |
69593 | 214 |
The proof rule for \<^term>\<open>while\<close>, where \<^term>\<open>P\<close> is the invariant. |
60500 | 215 |
\<close> |
10251 | 216 |
|
18372 | 217 |
theorem while_rule_lemma: |
81347 | 218 |
assumes invariant: "\<And>s. P s \<Longrightarrow> b s \<Longrightarrow> P (c s)" |
219 |
and terminate: "\<And>s. P s \<Longrightarrow> \<not> b s \<Longrightarrow> Q s" |
|
18372 | 220 |
and wf: "wf {(t, s). P s \<and> b s \<and> t = c s}" |
221 |
shows "P s \<Longrightarrow> Q (while b c s)" |
|
19736 | 222 |
using wf |
223 |
apply (induct s) |
|
18372 | 224 |
apply simp |
225 |
apply (subst while_unfold) |
|
226 |
apply (simp add: invariant terminate) |
|
227 |
done |
|
10251 | 228 |
|
10653 | 229 |
theorem while_rule: |
81347 | 230 |
"\<lbrakk>P s; |
231 |
\<And>s. \<lbrakk>P s; b s\<rbrakk> \<Longrightarrow> P (c s); |
|
232 |
\<And>s. \<lbrakk>P s; \<not> b s\<rbrakk> \<Longrightarrow> Q s; |
|
10997 | 233 |
wf r; |
81347 | 234 |
\<And>s. \<lbrakk>P s; b s\<rbrakk> \<Longrightarrow> (c s, s) \<in> r\<rbrakk> \<Longrightarrow> |
10984 | 235 |
Q (while b c s)" |
19736 | 236 |
apply (rule while_rule_lemma) |
237 |
prefer 4 apply assumption |
|
238 |
apply blast |
|
239 |
apply blast |
|
240 |
apply (erule wf_subset) |
|
241 |
apply blast |
|
242 |
done |
|
10653 | 243 |
|
74974 | 244 |
text \<open>Combine invariant preservation and variant decrease in one goal:\<close> |
245 |
theorem while_rule2: |
|
81347 | 246 |
"\<lbrakk>P s; |
247 |
\<And>s. \<lbrakk>P s; b s\<rbrakk> \<Longrightarrow> P (c s) \<and> (c s, s) \<in> r; |
|
248 |
\<And>s. \<lbrakk>P s; \<not> b s\<rbrakk> \<Longrightarrow> Q s; |
|
249 |
wf r\<rbrakk> \<Longrightarrow> |
|
74974 | 250 |
Q (while b c s)" |
251 |
using while_rule[of P] by metis |
|
252 |
||
60500 | 253 |
text\<open>Proving termination:\<close> |
41720 | 254 |
|
255 |
theorem wf_while_option_Some: |
|
41764 | 256 |
assumes "wf {(t, s). (P s \<and> b s) \<and> t = c s}" |
67091 | 257 |
and "\<And>s. P s \<Longrightarrow> b s \<Longrightarrow> P(c s)" and "P s" |
258 |
shows "\<exists>t. while_option b c s = Some t" |
|
41764 | 259 |
using assms(1,3) |
54050 | 260 |
proof (induction s) |
261 |
case less thus ?case using assms(2) |
|
262 |
by (subst while_option_unfold) simp |
|
263 |
qed |
|
264 |
||
265 |
lemma wf_rel_while_option_Some: |
|
266 |
assumes wf: "wf R" |
|
267 |
assumes smaller: "\<And>s. P s \<and> b s \<Longrightarrow> (c s, s) \<in> R" |
|
268 |
assumes inv: "\<And>s. P s \<and> b s \<Longrightarrow> P(c s)" |
|
269 |
assumes init: "P s" |
|
270 |
shows "\<exists>t. while_option b c s = Some t" |
|
271 |
proof - |
|
272 |
from smaller have "{(t,s). P s \<and> b s \<and> t = c s} \<subseteq> R" by auto |
|
273 |
with wf have "wf {(t,s). P s \<and> b s \<and> t = c s}" by (auto simp: wf_subset) |
|
274 |
with inv init show ?thesis by (auto simp: wf_while_option_Some) |
|
275 |
qed |
|
41720 | 276 |
|
277 |
theorem measure_while_option_Some: fixes f :: "'s \<Rightarrow> nat" |
|
67091 | 278 |
shows "(\<And>s. P s \<Longrightarrow> b s \<Longrightarrow> P(c s) \<and> f(c s) < f s) |
279 |
\<Longrightarrow> P s \<Longrightarrow> \<exists>t. while_option b c s = Some t" |
|
41764 | 280 |
by(blast intro: wf_while_option_Some[OF wf_if_measure, of P b f]) |
10251 | 281 |
|
60500 | 282 |
text\<open>Kleene iteration starting from the empty set and assuming some finite |
283 |
bounding set:\<close> |
|
45834 | 284 |
|
285 |
lemma while_option_finite_subset_Some: fixes C :: "'a set" |
|
81347 | 286 |
assumes "mono f" and "\<And>X. X \<subseteq> C \<Longrightarrow> f X \<subseteq> C" and "finite C" |
45834 | 287 |
shows "\<exists>P. while_option (\<lambda>A. f A \<noteq> A) f {} = Some P" |
288 |
proof(rule measure_while_option_Some[where |
|
289 |
f= "%A::'a set. card C - card A" and P= "%A. A \<subseteq> C \<and> A \<subseteq> f A" and s= "{}"]) |
|
290 |
fix A assume A: "A \<subseteq> C \<and> A \<subseteq> f A" "f A \<noteq> A" |
|
291 |
show "(f A \<subseteq> C \<and> f A \<subseteq> f (f A)) \<and> card C - card (f A) < card C - card A" |
|
292 |
(is "?L \<and> ?R") |
|
293 |
proof |
|
81347 | 294 |
show ?L by (metis A(1) assms(2) monoD[OF \<open>mono f\<close>]) |
45834 | 295 |
show ?R by (metis A assms(2,3) card_seteq diff_less_mono2 equalityI linorder_le_less_linear rev_finite_subset) |
296 |
qed |
|
297 |
qed simp |
|
298 |
||
299 |
lemma lfp_the_while_option: |
|
81347 | 300 |
assumes "mono f" and "\<And>X. X \<subseteq> C \<Longrightarrow> f X \<subseteq> C" and "finite C" |
45834 | 301 |
shows "lfp f = the(while_option (\<lambda>A. f A \<noteq> A) f {})" |
302 |
proof- |
|
303 |
obtain P where "while_option (\<lambda>A. f A \<noteq> A) f {} = Some P" |
|
304 |
using while_option_finite_subset_Some[OF assms] by blast |
|
305 |
with while_option_stop2[OF this] lfp_Kleene_iter[OF assms(1)] |
|
306 |
show ?thesis by auto |
|
307 |
qed |
|
308 |
||
50180 | 309 |
lemma lfp_while: |
81347 | 310 |
assumes "mono f" and "\<And>X. X \<subseteq> C \<Longrightarrow> f X \<subseteq> C" and "finite C" |
50180 | 311 |
shows "lfp f = while (\<lambda>A. f A \<noteq> A) f {}" |
312 |
unfolding while_def using assms by (rule lfp_the_while_option) blast |
|
313 |
||
63561
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
314 |
lemma wf_finite_less: |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
315 |
assumes "finite (C :: 'a::order set)" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
316 |
shows "wf {(x, y). {x, y} \<subseteq> C \<and> x < y}" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
317 |
by (rule wf_measure[where f="\<lambda>b. card {a. a \<in> C \<and> a < b}", THEN wf_subset]) |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
318 |
(fastforce simp: less_eq assms intro: psubset_card_mono) |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
319 |
|
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
320 |
lemma wf_finite_greater: |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
321 |
assumes "finite (C :: 'a::order set)" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
322 |
shows "wf {(x, y). {x, y} \<subseteq> C \<and> y < x}" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
323 |
by (rule wf_measure[where f="\<lambda>b. card {a. a \<in> C \<and> b < a}", THEN wf_subset]) |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
324 |
(fastforce simp: less_eq assms intro: psubset_card_mono) |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
325 |
|
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
326 |
lemma while_option_finite_increasing_Some: |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
327 |
fixes f :: "'a::order \<Rightarrow> 'a" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
328 |
assumes "mono f" and "finite (UNIV :: 'a set)" and "s \<le> f s" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
329 |
shows "\<exists>P. while_option (\<lambda>A. f A \<noteq> A) f s = Some P" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
330 |
by (rule wf_rel_while_option_Some[where R="{(x, y). y < x}" and P="\<lambda>A. A \<le> f A" and s="s"]) |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
331 |
(auto simp: assms monoD intro: wf_finite_greater[where C="UNIV::'a set", simplified]) |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
332 |
|
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
333 |
lemma lfp_the_while_option_lattice: |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
334 |
fixes f :: "'a::complete_lattice \<Rightarrow> 'a" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
335 |
assumes "mono f" and "finite (UNIV :: 'a set)" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
336 |
shows "lfp f = the (while_option (\<lambda>A. f A \<noteq> A) f bot)" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
337 |
proof - |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
338 |
obtain P where "while_option (\<lambda>A. f A \<noteq> A) f bot = Some P" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
339 |
using while_option_finite_increasing_Some[OF assms, where s=bot] by simp blast |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
340 |
with while_option_stop2[OF this] lfp_Kleene_iter[OF assms(1)] |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
341 |
show ?thesis by auto |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
342 |
qed |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
343 |
|
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
344 |
lemma lfp_while_lattice: |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
345 |
fixes f :: "'a::complete_lattice \<Rightarrow> 'a" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
346 |
assumes "mono f" and "finite (UNIV :: 'a set)" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
347 |
shows "lfp f = while (\<lambda>A. f A \<noteq> A) f bot" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
348 |
unfolding while_def using assms by (rule lfp_the_while_option_lattice) |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
349 |
|
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
350 |
lemma while_option_finite_decreasing_Some: |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
351 |
fixes f :: "'a::order \<Rightarrow> 'a" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
352 |
assumes "mono f" and "finite (UNIV :: 'a set)" and "f s \<le> s" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
353 |
shows "\<exists>P. while_option (\<lambda>A. f A \<noteq> A) f s = Some P" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
354 |
by (rule wf_rel_while_option_Some[where R="{(x, y). x < y}" and P="\<lambda>A. f A \<le> A" and s="s"]) |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
355 |
(auto simp add: assms monoD intro: wf_finite_less[where C="UNIV::'a set", simplified]) |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
356 |
|
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
357 |
lemma gfp_the_while_option_lattice: |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
358 |
fixes f :: "'a::complete_lattice \<Rightarrow> 'a" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
359 |
assumes "mono f" and "finite (UNIV :: 'a set)" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
360 |
shows "gfp f = the(while_option (\<lambda>A. f A \<noteq> A) f top)" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
361 |
proof - |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
362 |
obtain P where "while_option (\<lambda>A. f A \<noteq> A) f top = Some P" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
363 |
using while_option_finite_decreasing_Some[OF assms, where s=top] by simp blast |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
364 |
with while_option_stop2[OF this] gfp_Kleene_iter[OF assms(1)] |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
365 |
show ?thesis by auto |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
366 |
qed |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
367 |
|
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
368 |
lemma gfp_while_lattice: |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
369 |
fixes f :: "'a::complete_lattice \<Rightarrow> 'a" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
370 |
assumes "mono f" and "finite (UNIV :: 'a set)" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
371 |
shows "gfp f = while (\<lambda>A. f A \<noteq> A) f top" |
fba08009ff3e
add lemmas contributed by Peter Gammie
Andreas Lochbihler
parents:
63040
diff
changeset
|
372 |
unfolding while_def using assms by (rule gfp_the_while_option_lattice) |
53217 | 373 |
|
60500 | 374 |
text\<open>Computing the reflexive, transitive closure by iterating a successor |
53217 | 375 |
function. Stops when an element is found that dos not satisfy the test. |
376 |
||
377 |
More refined (and hence more efficient) versions can be found in ITP 2011 paper |
|
378 |
by Nipkow (the theories are in the AFP entry Flyspeck by Nipkow) |
|
60500 | 379 |
and the AFP article Executable Transitive Closures by René Thiemann.\<close> |
53217 | 380 |
|
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
381 |
context |
81347 | 382 |
fixes p :: "'a \<Rightarrow> bool" |
383 |
and f :: "'a \<Rightarrow> 'a list" |
|
384 |
and x :: 'a |
|
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
385 |
begin |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
386 |
|
61115
3a4400985780
modernized name space management -- more uniform qualification;
wenzelm
parents:
60580
diff
changeset
|
387 |
qualified fun rtrancl_while_test :: "'a list \<times> 'a set \<Rightarrow> bool" |
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
388 |
where "rtrancl_while_test (ws,_) = (ws \<noteq> [] \<and> p(hd ws))" |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
389 |
|
61115
3a4400985780
modernized name space management -- more uniform qualification;
wenzelm
parents:
60580
diff
changeset
|
390 |
qualified fun rtrancl_while_step :: "'a list \<times> 'a set \<Rightarrow> 'a list \<times> 'a set" |
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
391 |
where "rtrancl_while_step (ws, Z) = |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
392 |
(let x = hd ws; new = remdups (filter (\<lambda>y. y \<notin> Z) (f x)) |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
393 |
in (new @ tl ws, set new \<union> Z))" |
53217 | 394 |
|
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
395 |
definition rtrancl_while :: "('a list * 'a set) option" |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
396 |
where "rtrancl_while = while_option rtrancl_while_test rtrancl_while_step ([x],{x})" |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
397 |
|
61115
3a4400985780
modernized name space management -- more uniform qualification;
wenzelm
parents:
60580
diff
changeset
|
398 |
qualified fun rtrancl_while_invariant :: "'a list \<times> 'a set \<Rightarrow> bool" |
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
399 |
where "rtrancl_while_invariant (ws, Z) = |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
400 |
(x \<in> Z \<and> set ws \<subseteq> Z \<and> distinct ws \<and> {(x,y). y \<in> set(f x)} `` (Z - set ws) \<subseteq> Z \<and> |
67613 | 401 |
Z \<subseteq> {(x,y). y \<in> set(f x)}\<^sup>* `` {x} \<and> (\<forall>z\<in>Z - set ws. p z))" |
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
402 |
|
81347 | 403 |
qualified lemma rtrancl_while_invariant: |
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
404 |
assumes inv: "rtrancl_while_invariant st" and test: "rtrancl_while_test st" |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
405 |
shows "rtrancl_while_invariant (rtrancl_while_step st)" |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
406 |
proof (cases st) |
81347 | 407 |
fix ws Z |
408 |
assume st: "st = (ws, Z)" |
|
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
409 |
with test obtain h t where "ws = h # t" "p h" by (cases ws) auto |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
410 |
with inv st show ?thesis by (auto intro: rtrancl.rtrancl_into_rtrancl) |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
411 |
qed |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
412 |
|
81347 | 413 |
lemma rtrancl_while_Some: |
414 |
assumes "rtrancl_while = Some(ws,Z)" |
|
415 |
shows "if ws = [] |
|
416 |
then Z = {(x,y). y \<in> set(f x)}\<^sup>* `` {x} \<and> (\<forall>z\<in>Z. p z) |
|
417 |
else \<not>p(hd ws) \<and> hd ws \<in> {(x,y). y \<in> set(f x)}\<^sup>* `` {x}" |
|
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
418 |
proof - |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
419 |
have "rtrancl_while_invariant ([x],{x})" by simp |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
420 |
with rtrancl_while_invariant have I: "rtrancl_while_invariant (ws,Z)" |
53217 | 421 |
by (rule while_option_rule[OF _ assms[unfolded rtrancl_while_def]]) |
81347 | 422 |
show ?thesis |
423 |
proof (cases "ws = []") |
|
424 |
case True |
|
425 |
thus ?thesis using I |
|
61424
c3658c18b7bc
prod_case as canonical name for product type eliminator
haftmann
parents:
61166
diff
changeset
|
426 |
by (auto simp del:Image_Collect_case_prod dest: Image_closed_trancl) |
81347 | 427 |
next |
428 |
case False |
|
429 |
thus ?thesis using I while_option_stop[OF assms[unfolded rtrancl_while_def]] |
|
53217 | 430 |
by (simp add: subset_iff) |
81347 | 431 |
qed |
53217 | 432 |
qed |
433 |
||
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
434 |
lemma rtrancl_while_finite_Some: |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
435 |
assumes "finite ({(x, y). y \<in> set (f x)}\<^sup>* `` {x})" (is "finite ?Cl") |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
436 |
shows "\<exists>y. rtrancl_while = Some y" |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
437 |
proof - |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
438 |
let ?R = "(\<lambda>(_, Z). card (?Cl - Z)) <*mlex*> (\<lambda>(ws, _). length ws) <*mlex*> {}" |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
439 |
have "wf ?R" by (blast intro: wf_mlex) |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
440 |
then show ?thesis unfolding rtrancl_while_def |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
441 |
proof (rule wf_rel_while_option_Some[of ?R rtrancl_while_invariant]) |
81347 | 442 |
fix st |
443 |
assume *: "rtrancl_while_invariant st \<and> rtrancl_while_test st" |
|
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
444 |
hence I: "rtrancl_while_invariant (rtrancl_while_step st)" |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
445 |
by (blast intro: rtrancl_while_invariant) |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
446 |
show "(rtrancl_while_step st, st) \<in> ?R" |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
447 |
proof (cases st) |
81347 | 448 |
fix ws Z |
449 |
let ?ws = "fst (rtrancl_while_step st)" |
|
450 |
let ?Z = "snd (rtrancl_while_step st)" |
|
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
451 |
assume st: "st = (ws, Z)" |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
452 |
with * obtain h t where ws: "ws = h # t" "p h" by (cases ws) auto |
81347 | 453 |
show ?thesis |
454 |
proof (cases "remdups (filter (\<lambda>y. y \<notin> Z) (f h)) = []") |
|
455 |
case False |
|
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
456 |
then obtain z where "z \<in> set (remdups (filter (\<lambda>y. y \<notin> Z) (f h)))" by fastforce |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
457 |
with st ws I have "Z \<subset> ?Z" "Z \<subseteq> ?Cl" "?Z \<subseteq> ?Cl" by auto |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
458 |
with assms have "card (?Cl - ?Z) < card (?Cl - Z)" by (blast intro: psubset_card_mono) |
81347 | 459 |
with st ws show ?thesis unfolding mlex_prod_def by simp |
460 |
next |
|
461 |
case True |
|
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
462 |
with st ws have "?Z = Z" "?ws = t" by (auto simp: filter_empty_conv) |
81347 | 463 |
with st ws show ?thesis unfolding mlex_prod_def by simp |
464 |
qed |
|
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
465 |
qed |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
466 |
qed (simp_all add: rtrancl_while_invariant) |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
467 |
qed |
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
468 |
|
10251 | 469 |
end |
54196
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
470 |
|
0c188a3c671a
refactored rtrancl_while; prove termination for finite rtrancl
traytel
parents:
54050
diff
changeset
|
471 |
end |