| author | nipkow | 
| Mon, 22 Nov 2004 11:53:56 +0100 | |
| changeset 15305 | 0bd9eedaa301 | 
| parent 13671 | eec2582923f6 | 
| child 16417 | 9bc16273c2d4 | 
| permissions | -rw-r--r-- | 
| 13405 | 1 | (* Title: HOL/Extraction/Warshall.thy | 
| 2 | ID: $Id$ | |
| 3 | Author: Stefan Berghofer, TU Muenchen | |
| 4 | *) | |
| 5 | ||
| 6 | header {* Warshall's algorithm *}
 | |
| 7 | ||
| 8 | theory Warshall = Main: | |
| 9 | ||
| 10 | text {*
 | |
| 11 | Derivation of Warshall's algorithm using program extraction, | |
| 12 |   based on Berger, Schwichtenberg and Seisenberger \cite{Berger-JAR-2001}.
 | |
| 13 | *} | |
| 14 | ||
| 15 | datatype b = T | F | |
| 16 | ||
| 17 | consts | |
| 18 |   is_path' :: "('a \<Rightarrow> 'a \<Rightarrow> b) \<Rightarrow> 'a \<Rightarrow> 'a list \<Rightarrow> 'a \<Rightarrow> bool"
 | |
| 19 | ||
| 20 | primrec | |
| 21 | "is_path' r x [] z = (r x z = T)" | |
| 22 | "is_path' r x (y # ys) z = (r x y = T \<and> is_path' r y ys z)" | |
| 23 | ||
| 24 | constdefs | |
| 25 | is_path :: "(nat \<Rightarrow> nat \<Rightarrow> b) \<Rightarrow> (nat * nat list * nat) \<Rightarrow> | |
| 26 | nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" | |
| 27 | "is_path r p i j k == fst p = j \<and> snd (snd p) = k \<and> | |
| 28 | list_all (\<lambda>x. x < i) (fst (snd p)) \<and> | |
| 29 | is_path' r (fst p) (fst (snd p)) (snd (snd p))" | |
| 30 | ||
| 31 |   conc :: "('a * 'a list * 'a) \<Rightarrow> ('a * 'a list * 'a) \<Rightarrow> ('a * 'a list * 'a)"
 | |
| 32 | "conc p q == (fst p, fst (snd p) @ fst q # fst (snd q), snd (snd q))" | |
| 33 | ||
| 34 | theorem is_path'_snoc [simp]: | |
| 35 | "\<And>x. is_path' r x (ys @ [y]) z = (is_path' r x ys y \<and> r y z = T)" | |
| 36 | by (induct ys) simp+ | |
| 37 | ||
| 38 | theorem list_all_scoc [simp]: "list_all P (xs @ [x]) = (P x \<and> list_all P xs)" | |
| 39 | by (induct xs, simp+, rules) | |
| 40 | ||
| 41 | theorem list_all_lemma: | |
| 42 | "list_all P xs \<Longrightarrow> (\<And>x. P x \<Longrightarrow> Q x) \<Longrightarrow> list_all Q xs" | |
| 43 | proof - | |
| 44 | assume PQ: "\<And>x. P x \<Longrightarrow> Q x" | |
| 45 | show "list_all P xs \<Longrightarrow> list_all Q xs" | |
| 46 | proof (induct xs) | |
| 47 | case Nil | |
| 48 | show ?case by simp | |
| 49 | next | |
| 50 | case (Cons y ys) | |
| 51 | hence Py: "P y" by simp | |
| 52 | from Cons have Pys: "list_all P ys" by simp | |
| 53 | show ?case | |
| 54 | by simp (rule conjI PQ Py Cons Pys)+ | |
| 55 | qed | |
| 56 | qed | |
| 57 | ||
| 58 | theorem lemma1: "\<And>p. is_path r p i j k \<Longrightarrow> is_path r p (Suc i) j k" | |
| 59 | apply (unfold is_path_def) | |
| 60 | apply (simp cong add: conj_cong add: split_paired_all) | |
| 61 | apply (erule conjE)+ | |
| 62 | apply (erule list_all_lemma) | |
| 63 | apply simp | |
| 64 | done | |
| 65 | ||
| 66 | theorem lemma2: "\<And>p. is_path r p 0 j k \<Longrightarrow> r j k = T" | |
| 67 | apply (unfold is_path_def) | |
| 68 | apply (simp cong add: conj_cong add: split_paired_all) | |
| 69 | apply (case_tac "aa") | |
| 70 | apply simp+ | |
| 71 | done | |
| 72 | ||
| 73 | theorem is_path'_conc: "is_path' r j xs i \<Longrightarrow> is_path' r i ys k \<Longrightarrow> | |
| 74 | is_path' r j (xs @ i # ys) k" | |
| 75 | proof - | |
| 76 | assume pys: "is_path' r i ys k" | |
| 77 | show "\<And>j. is_path' r j xs i \<Longrightarrow> is_path' r j (xs @ i # ys) k" | |
| 78 | proof (induct xs) | |
| 79 | case (Nil j) | |
| 80 | hence "r j i = T" by simp | |
| 81 | with pys show ?case by simp | |
| 82 | next | |
| 83 | case (Cons z zs j) | |
| 84 | hence jzr: "r j z = T" by simp | |
| 85 | from Cons have pzs: "is_path' r z zs i" by simp | |
| 86 | show ?case | |
| 87 | by simp (rule conjI jzr Cons pzs)+ | |
| 88 | qed | |
| 89 | qed | |
| 90 | ||
| 91 | theorem lemma3: | |
| 92 | "\<And>p q. is_path r p i j i \<Longrightarrow> is_path r q i i k \<Longrightarrow> | |
| 93 | is_path r (conc p q) (Suc i) j k" | |
| 94 | apply (unfold is_path_def conc_def) | |
| 95 | apply (simp cong add: conj_cong add: split_paired_all) | |
| 96 | apply (erule conjE)+ | |
| 97 | apply (rule conjI) | |
| 98 | apply (erule list_all_lemma) | |
| 99 | apply simp | |
| 100 | apply (rule conjI) | |
| 101 | apply (erule list_all_lemma) | |
| 102 | apply simp | |
| 103 | apply (rule is_path'_conc) | |
| 104 | apply assumption+ | |
| 105 | done | |
| 106 | ||
| 107 | theorem lemma5: | |
| 108 | "\<And>p. is_path r p (Suc i) j k \<Longrightarrow> ~ is_path r p i j k \<Longrightarrow> | |
| 109 | (\<exists>q. is_path r q i j i) \<and> (\<exists>q'. is_path r q' i i k)" | |
| 110 | proof (simp cong add: conj_cong add: split_paired_all is_path_def, (erule conjE)+) | |
| 111 | fix xs | |
| 112 | assume "list_all (\<lambda>x. x < Suc i) xs" | |
| 113 | assume "is_path' r j xs k" | |
| 114 | assume "\<not> list_all (\<lambda>x. x < i) xs" | |
| 115 | show "(\<exists>ys. list_all (\<lambda>x. x < i) ys \<and> is_path' r j ys i) \<and> | |
| 116 | (\<exists>ys. list_all (\<lambda>x. x < i) ys \<and> is_path' r i ys k)" | |
| 117 | proof | |
| 118 | show "\<And>j. list_all (\<lambda>x. x < Suc i) xs \<Longrightarrow> is_path' r j xs k \<Longrightarrow> | |
| 119 | \<not> list_all (\<lambda>x. x < i) xs \<Longrightarrow> | |
| 120 | \<exists>ys. list_all (\<lambda>x. x < i) ys \<and> is_path' r j ys i" (is "PROP ?ih xs") | |
| 121 | proof (induct xs) | |
| 122 | case Nil | |
| 123 | thus ?case by simp | |
| 124 | next | |
| 125 | case (Cons a as j) | |
| 126 | show ?case | |
| 127 | proof (cases "a=i") | |
| 128 | case True | |
| 129 | show ?thesis | |
| 130 | proof | |
| 131 | from True and Cons have "r j i = T" by simp | |
| 132 | thus "list_all (\<lambda>x. x < i) [] \<and> is_path' r j [] i" by simp | |
| 133 | qed | |
| 134 | next | |
| 135 | case False | |
| 136 | have "PROP ?ih as" by (rule Cons) | |
| 137 | then obtain ys where ys: "list_all (\<lambda>x. x < i) ys \<and> is_path' r a ys i" | |
| 138 | proof | |
| 139 | from Cons show "list_all (\<lambda>x. x < Suc i) as" by simp | |
| 140 | from Cons show "is_path' r a as k" by simp | |
| 141 | from Cons and False show "\<not> list_all (\<lambda>x. x < i) as" | |
| 142 | by (simp, arith) | |
| 143 | qed | |
| 144 | show ?thesis | |
| 145 | proof | |
| 146 | from Cons False ys | |
| 147 | show "list_all (\<lambda>x. x < i) (a # ys) \<and> is_path' r j (a # ys) i" | |
| 148 | by (simp, arith) | |
| 149 | qed | |
| 150 | qed | |
| 151 | qed | |
| 152 | show "\<And>k. list_all (\<lambda>x. x < Suc i) xs \<Longrightarrow> is_path' r j xs k \<Longrightarrow> | |
| 153 | \<not> list_all (\<lambda>x. x < i) xs \<Longrightarrow> | |
| 154 | \<exists>ys. list_all (\<lambda>x. x < i) ys \<and> is_path' r i ys k" (is "PROP ?ih xs") | |
| 155 | proof (induct xs rule: rev_induct) | |
| 156 | case Nil | |
| 157 | thus ?case by simp | |
| 158 | next | |
| 159 | case (snoc a as k) | |
| 160 | show ?case | |
| 161 | proof (cases "a=i") | |
| 162 | case True | |
| 163 | show ?thesis | |
| 164 | proof | |
| 165 | from True and snoc have "r i k = T" by simp | |
| 166 | thus "list_all (\<lambda>x. x < i) [] \<and> is_path' r i [] k" by simp | |
| 167 | qed | |
| 168 | next | |
| 169 | case False | |
| 170 | have "PROP ?ih as" by (rule snoc) | |
| 171 | then obtain ys where ys: "list_all (\<lambda>x. x < i) ys \<and> is_path' r i ys a" | |
| 172 | proof | |
| 173 | from snoc show "list_all (\<lambda>x. x < Suc i) as" by simp | |
| 174 | from snoc show "is_path' r j as a" by simp | |
| 175 | from snoc and False show "\<not> list_all (\<lambda>x. x < i) as" | |
| 176 | by (simp, arith) | |
| 177 | qed | |
| 178 | show ?thesis | |
| 179 | proof | |
| 180 | from snoc False ys | |
| 181 | show "list_all (\<lambda>x. x < i) (ys @ [a]) \<and> is_path' r i (ys @ [a]) k" | |
| 182 | by (simp, arith) | |
| 183 | qed | |
| 184 | qed | |
| 185 | qed | |
| 186 | qed | |
| 187 | qed | |
| 188 | ||
| 189 | theorem lemma5': | |
| 190 | "\<And>p. is_path r p (Suc i) j k \<Longrightarrow> \<not> is_path r p i j k \<Longrightarrow> | |
| 191 | \<not> (\<forall>q. \<not> is_path r q i j i) \<and> \<not> (\<forall>q'. \<not> is_path r q' i i k)" | |
| 192 | by (rules dest: lemma5) | |
| 193 | ||
| 194 | theorem warshall: | |
| 195 | "\<And>j k. \<not> (\<exists>p. is_path r p i j k) \<or> (\<exists>p. is_path r p i j k)" | |
| 196 | proof (induct i) | |
| 197 | case (0 j k) | |
| 198 | show ?case | |
| 199 | proof (cases "r j k") | |
| 200 | assume "r j k = T" | |
| 201 | hence "is_path r (j, [], k) 0 j k" | |
| 202 | by (simp add: is_path_def) | |
| 203 | hence "\<exists>p. is_path r p 0 j k" .. | |
| 204 | thus ?thesis .. | |
| 205 | next | |
| 206 | assume "r j k = F" | |
| 207 | hence "r j k ~= T" by simp | |
| 208 | hence "\<not> (\<exists>p. is_path r p 0 j k)" | |
| 209 | by (rules dest: lemma2) | |
| 210 | thus ?thesis .. | |
| 211 | qed | |
| 212 | next | |
| 213 | case (Suc i j k) | |
| 214 | thus ?case | |
| 215 | proof | |
| 216 | assume h1: "\<not> (\<exists>p. is_path r p i j k)" | |
| 217 | from Suc show ?case | |
| 218 | proof | |
| 219 | assume "\<not> (\<exists>p. is_path r p i j i)" | |
| 220 | with h1 have "\<not> (\<exists>p. is_path r p (Suc i) j k)" | |
| 221 | by (rules dest: lemma5') | |
| 222 | thus ?case .. | |
| 223 | next | |
| 224 | assume "\<exists>p. is_path r p i j i" | |
| 225 | then obtain p where h2: "is_path r p i j i" .. | |
| 226 | from Suc show ?case | |
| 227 | proof | |
| 228 | assume "\<not> (\<exists>p. is_path r p i i k)" | |
| 229 | with h1 have "\<not> (\<exists>p. is_path r p (Suc i) j k)" | |
| 230 | by (rules dest: lemma5') | |
| 231 | thus ?case .. | |
| 232 | next | |
| 233 | assume "\<exists>q. is_path r q i i k" | |
| 234 | then obtain q where "is_path r q i i k" .. | |
| 235 | with h2 have "is_path r (conc p q) (Suc i) j k" | |
| 236 | by (rule lemma3) | |
| 237 | hence "\<exists>pq. is_path r pq (Suc i) j k" .. | |
| 238 | thus ?case .. | |
| 239 | qed | |
| 240 | qed | |
| 241 | next | |
| 242 | assume "\<exists>p. is_path r p i j k" | |
| 243 | hence "\<exists>p. is_path r p (Suc i) j k" | |
| 244 | by (rules intro: lemma1) | |
| 245 | thus ?case .. | |
| 246 | qed | |
| 247 | qed | |
| 248 | ||
| 249 | extract warshall | |
| 250 | ||
| 251 | text {*
 | |
| 252 | The program extracted from the above proof looks as follows | |
| 13671 
eec2582923f6
Eta contraction is now switched off when printing extracted program.
 berghofe parents: 
13471diff
changeset | 253 |   @{thm [display, eta_contract=false] warshall_def [no_vars]}
 | 
| 13405 | 254 | The corresponding correctness theorem is | 
| 255 |   @{thm [display] warshall_correctness [no_vars]}
 | |
| 256 | *} | |
| 257 | ||
| 258 | end | |
| 259 |