| author | haftmann | 
| Tue, 19 Sep 2006 15:22:35 +0200 | |
| changeset 20604 | 9dba9c7872c9 | 
| parent 20588 | c847c56edf0c | 
| child 20714 | 6a122dba034c | 
| permissions | -rw-r--r-- | 
| 15524 | 1 | (* Title: HOL/Orderings.thy | 
| 2 | ID: $Id$ | |
| 3 | Author: Tobias Nipkow, Markus Wenzel, and Larry Paulson | |
| 4 | ||
| 5 | FIXME: derive more of the min/max laws generically via semilattices | |
| 6 | *) | |
| 7 | ||
| 8 | header {* Type classes for $\le$ *}
 | |
| 9 | ||
| 10 | theory Orderings | |
| 20588 | 11 | imports OperationalEquality Lattice_Locales | 
| 16417 | 12 | uses ("antisym_setup.ML")
 | 
| 15524 | 13 | begin | 
| 14 | ||
| 15 | subsection {* Order signatures and orders *}
 | |
| 16 | ||
| 20588 | 17 | class ord = eq + | 
| 18 | constrains eq :: "'a \<Rightarrow> 'a \<Rightarrow> bool" | |
| 19 | fixes less_eq :: "'a \<Rightarrow> 'a \<Rightarrow> bool" | |
| 20 | fixes less :: "'a \<Rightarrow> 'a \<Rightarrow> bool" | |
| 15524 | 21 | |
| 19656 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 22 | const_syntax | 
| 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 23 |   less  ("op <")
 | 
| 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 24 |   less  ("(_/ < _)"  [50, 51] 50)
 | 
| 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 25 |   less_eq  ("op <=")
 | 
| 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 26 |   less_eq  ("(_/ <= _)" [50, 51] 50)
 | 
| 15524 | 27 | |
| 19656 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 28 | const_syntax (xsymbols) | 
| 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 29 |   less_eq  ("op \<le>")
 | 
| 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 30 |   less_eq  ("(_/ \<le> _)"  [50, 51] 50)
 | 
| 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 31 | |
| 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 32 | const_syntax (HTML output) | 
| 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 33 |   less_eq  ("op \<le>")
 | 
| 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 34 |   less_eq  ("(_/ \<le> _)"  [50, 51] 50)
 | 
| 15524 | 35 | |
| 19536 | 36 | abbreviation (input) | 
| 37 | greater (infixl ">" 50) | |
| 38 | "x > y == y < x" | |
| 39 | greater_eq (infixl ">=" 50) | |
| 40 | "x >= y == y <= x" | |
| 15524 | 41 | |
| 19656 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 42 | const_syntax (xsymbols) | 
| 
09be06943252
tuned concrete syntax -- abbreviation/const_syntax;
 wenzelm parents: 
19637diff
changeset | 43 | greater_eq (infixl "\<ge>" 50) | 
| 15524 | 44 | |
| 45 | ||
| 46 | subsection {* Monotonicity *}
 | |
| 47 | ||
| 48 | locale mono = | |
| 49 | fixes f | |
| 50 | assumes mono: "A <= B ==> f A <= f B" | |
| 51 | ||
| 52 | lemmas monoI [intro?] = mono.intro | |
| 53 | and monoD [dest?] = mono.mono | |
| 54 | ||
| 55 | constdefs | |
| 56 | min :: "['a::ord, 'a] => 'a" | |
| 57 | "min a b == (if a <= b then a else b)" | |
| 58 | max :: "['a::ord, 'a] => 'a" | |
| 59 | "max a b == (if a <= b then b else a)" | |
| 60 | ||
| 61 | lemma min_leastL: "(!!x. least <= x) ==> min least x = least" | |
| 62 | by (simp add: min_def) | |
| 63 | ||
| 64 | lemma min_of_mono: | |
| 19527 | 65 | "(!!x y. (f x <= f y) = (x <= y)) ==> min (f m) (f n) = f (min m n)" | 
| 15524 | 66 | by (simp add: min_def) | 
| 67 | ||
| 68 | lemma max_leastL: "(!!x. least <= x) ==> max least x = x" | |
| 69 | by (simp add: max_def) | |
| 70 | ||
| 71 | lemma max_of_mono: | |
| 19527 | 72 | "(!!x y. (f x <= f y) = (x <= y)) ==> max (f m) (f n) = f (max m n)" | 
| 15524 | 73 | by (simp add: max_def) | 
| 74 | ||
| 75 | ||
| 76 | subsection "Orders" | |
| 77 | ||
| 78 | axclass order < ord | |
| 79 | order_refl [iff]: "x <= x" | |
| 80 | order_trans: "x <= y ==> y <= z ==> x <= z" | |
| 81 | order_antisym: "x <= y ==> y <= x ==> x = y" | |
| 82 | order_less_le: "(x < y) = (x <= y & x ~= y)" | |
| 83 | ||
| 84 | text{* Connection to locale: *}
 | |
| 85 | ||
| 15837 | 86 | interpretation order: | 
| 15780 | 87 | partial_order["op \<le> :: 'a::order \<Rightarrow> 'a \<Rightarrow> bool"] | 
| 15524 | 88 | apply(rule partial_order.intro) | 
| 89 | apply(rule order_refl, erule (1) order_trans, erule (1) order_antisym) | |
| 90 | done | |
| 91 | ||
| 92 | text {* Reflexivity. *}
 | |
| 93 | ||
| 94 | lemma order_eq_refl: "!!x::'a::order. x = y ==> x <= y" | |
| 95 |     -- {* This form is useful with the classical reasoner. *}
 | |
| 96 | apply (erule ssubst) | |
| 97 | apply (rule order_refl) | |
| 98 | done | |
| 99 | ||
| 100 | lemma order_less_irrefl [iff]: "~ x < (x::'a::order)" | |
| 101 | by (simp add: order_less_le) | |
| 102 | ||
| 103 | lemma order_le_less: "((x::'a::order) <= y) = (x < y | x = y)" | |
| 104 |     -- {* NOT suitable for iff, since it can cause PROOF FAILED. *}
 | |
| 105 | apply (simp add: order_less_le, blast) | |
| 106 | done | |
| 107 | ||
| 108 | lemmas order_le_imp_less_or_eq = order_le_less [THEN iffD1, standard] | |
| 109 | ||
| 110 | lemma order_less_imp_le: "!!x::'a::order. x < y ==> x <= y" | |
| 111 | by (simp add: order_less_le) | |
| 112 | ||
| 113 | ||
| 114 | text {* Asymmetry. *}
 | |
| 115 | ||
| 116 | lemma order_less_not_sym: "(x::'a::order) < y ==> ~ (y < x)" | |
| 117 | by (simp add: order_less_le order_antisym) | |
| 118 | ||
| 119 | lemma order_less_asym: "x < (y::'a::order) ==> (~P ==> y < x) ==> P" | |
| 120 | apply (drule order_less_not_sym) | |
| 121 | apply (erule contrapos_np, simp) | |
| 122 | done | |
| 123 | ||
| 124 | lemma order_eq_iff: "!!x::'a::order. (x = y) = (x \<le> y & y \<le> x)" | |
| 125 | by (blast intro: order_antisym) | |
| 126 | ||
| 127 | lemma order_antisym_conv: "(y::'a::order) <= x ==> (x <= y) = (x = y)" | |
| 128 | by(blast intro:order_antisym) | |
| 129 | ||
| 130 | text {* Transitivity. *}
 | |
| 131 | ||
| 132 | lemma order_less_trans: "!!x::'a::order. [| x < y; y < z |] ==> x < z" | |
| 133 | apply (simp add: order_less_le) | |
| 134 | apply (blast intro: order_trans order_antisym) | |
| 135 | done | |
| 136 | ||
| 137 | lemma order_le_less_trans: "!!x::'a::order. [| x <= y; y < z |] ==> x < z" | |
| 138 | apply (simp add: order_less_le) | |
| 139 | apply (blast intro: order_trans order_antisym) | |
| 140 | done | |
| 141 | ||
| 142 | lemma order_less_le_trans: "!!x::'a::order. [| x < y; y <= z |] ==> x < z" | |
| 143 | apply (simp add: order_less_le) | |
| 144 | apply (blast intro: order_trans order_antisym) | |
| 145 | done | |
| 146 | ||
| 147 | ||
| 148 | text {* Useful for simplification, but too risky to include by default. *}
 | |
| 149 | ||
| 150 | lemma order_less_imp_not_less: "(x::'a::order) < y ==> (~ y < x) = True" | |
| 151 | by (blast elim: order_less_asym) | |
| 152 | ||
| 153 | lemma order_less_imp_triv: "(x::'a::order) < y ==> (y < x --> P) = True" | |
| 154 | by (blast elim: order_less_asym) | |
| 155 | ||
| 156 | lemma order_less_imp_not_eq: "(x::'a::order) < y ==> (x = y) = False" | |
| 157 | by auto | |
| 158 | ||
| 159 | lemma order_less_imp_not_eq2: "(x::'a::order) < y ==> (y = x) = False" | |
| 160 | by auto | |
| 161 | ||
| 162 | ||
| 163 | text {* Other operators. *}
 | |
| 164 | ||
| 165 | lemma min_leastR: "(!!x::'a::order. least <= x) ==> min x least = least" | |
| 166 | apply (simp add: min_def) | |
| 167 | apply (blast intro: order_antisym) | |
| 168 | done | |
| 169 | ||
| 170 | lemma max_leastR: "(!!x::'a::order. least <= x) ==> max x least = x" | |
| 171 | apply (simp add: max_def) | |
| 172 | apply (blast intro: order_antisym) | |
| 173 | done | |
| 174 | ||
| 175 | ||
| 176 | subsection {* Transitivity rules for calculational reasoning *}
 | |
| 177 | ||
| 178 | ||
| 179 | lemma order_neq_le_trans: "a ~= b ==> (a::'a::order) <= b ==> a < b" | |
| 180 | by (simp add: order_less_le) | |
| 181 | ||
| 182 | lemma order_le_neq_trans: "(a::'a::order) <= b ==> a ~= b ==> a < b" | |
| 183 | by (simp add: order_less_le) | |
| 184 | ||
| 185 | lemma order_less_asym': "(a::'a::order) < b ==> b < a ==> P" | |
| 186 | by (rule order_less_asym) | |
| 187 | ||
| 188 | ||
| 189 | subsection {* Least value operator *}
 | |
| 190 | ||
| 191 | constdefs | |
| 192 |   Least :: "('a::ord => bool) => 'a"               (binder "LEAST " 10)
 | |
| 193 | "Least P == THE x. P x & (ALL y. P y --> x <= y)" | |
| 194 |     -- {* We can no longer use LeastM because the latter requires Hilbert-AC. *}
 | |
| 195 | ||
| 15950 | 196 | lemma LeastI2_order: | 
| 15524 | 197 | "[| P (x::'a::order); | 
| 198 | !!y. P y ==> x <= y; | |
| 199 | !!x. [| P x; ALL y. P y --> x \<le> y |] ==> Q x |] | |
| 200 | ==> Q (Least P)" | |
| 201 | apply (unfold Least_def) | |
| 202 | apply (rule theI2) | |
| 203 | apply (blast intro: order_antisym)+ | |
| 204 | done | |
| 205 | ||
| 206 | lemma Least_equality: | |
| 207 | "[| P (k::'a::order); !!x. P x ==> k <= x |] ==> (LEAST x. P x) = k" | |
| 208 | apply (simp add: Least_def) | |
| 209 | apply (rule the_equality) | |
| 210 | apply (auto intro!: order_antisym) | |
| 211 | done | |
| 212 | ||
| 213 | ||
| 214 | subsection "Linear / total orders" | |
| 215 | ||
| 216 | axclass linorder < order | |
| 217 | linorder_linear: "x <= y | y <= x" | |
| 218 | ||
| 219 | lemma linorder_less_linear: "!!x::'a::linorder. x<y | x=y | y<x" | |
| 220 | apply (simp add: order_less_le) | |
| 221 | apply (insert linorder_linear, blast) | |
| 222 | done | |
| 223 | ||
| 224 | lemma linorder_le_less_linear: "!!x::'a::linorder. x\<le>y | y<x" | |
| 225 | by (simp add: order_le_less linorder_less_linear) | |
| 226 | ||
| 227 | lemma linorder_le_cases [case_names le ge]: | |
| 228 | "((x::'a::linorder) \<le> y ==> P) ==> (y \<le> x ==> P) ==> P" | |
| 229 | by (insert linorder_linear, blast) | |
| 230 | ||
| 231 | lemma linorder_cases [case_names less equal greater]: | |
| 232 | "((x::'a::linorder) < y ==> P) ==> (x = y ==> P) ==> (y < x ==> P) ==> P" | |
| 233 | by (insert linorder_less_linear, blast) | |
| 234 | ||
| 235 | lemma linorder_not_less: "!!x::'a::linorder. (~ x < y) = (y <= x)" | |
| 236 | apply (simp add: order_less_le) | |
| 237 | apply (insert linorder_linear) | |
| 238 | apply (blast intro: order_antisym) | |
| 239 | done | |
| 240 | ||
| 241 | lemma linorder_not_le: "!!x::'a::linorder. (~ x <= y) = (y < x)" | |
| 242 | apply (simp add: order_less_le) | |
| 243 | apply (insert linorder_linear) | |
| 244 | apply (blast intro: order_antisym) | |
| 245 | done | |
| 246 | ||
| 247 | lemma linorder_neq_iff: "!!x::'a::linorder. (x ~= y) = (x<y | y<x)" | |
| 248 | by (cut_tac x = x and y = y in linorder_less_linear, auto) | |
| 249 | ||
| 250 | lemma linorder_neqE: "x ~= (y::'a::linorder) ==> (x < y ==> R) ==> (y < x ==> R) ==> R" | |
| 251 | by (simp add: linorder_neq_iff, blast) | |
| 252 | ||
| 253 | lemma linorder_antisym_conv1: "~ (x::'a::linorder) < y ==> (x <= y) = (x = y)" | |
| 254 | by(blast intro:order_antisym dest:linorder_not_less[THEN iffD1]) | |
| 255 | ||
| 256 | lemma linorder_antisym_conv2: "(x::'a::linorder) <= y ==> (~ x < y) = (x = y)" | |
| 257 | by(blast intro:order_antisym dest:linorder_not_less[THEN iffD1]) | |
| 258 | ||
| 259 | lemma linorder_antisym_conv3: "~ (y::'a::linorder) < x ==> (~ x < y) = (x = y)" | |
| 260 | by(blast intro:order_antisym dest:linorder_not_less[THEN iffD1]) | |
| 261 | ||
| 16796 | 262 | text{*Replacing the old Nat.leI*}
 | 
| 263 | lemma leI: "~ x < y ==> y <= (x::'a::linorder)" | |
| 264 | by (simp only: linorder_not_less) | |
| 265 | ||
| 266 | lemma leD: "y <= (x::'a::linorder) ==> ~ x < y" | |
| 267 | by (simp only: linorder_not_less) | |
| 268 | ||
| 269 | (*FIXME inappropriate name (or delete altogether)*) | |
| 270 | lemma not_leE: "~ y <= (x::'a::linorder) ==> x < y" | |
| 271 | by (simp only: linorder_not_le) | |
| 272 | ||
| 15524 | 273 | use "antisym_setup.ML"; | 
| 274 | setup antisym_setup | |
| 275 | ||
| 276 | subsection {* Setup of transitivity reasoner as Solver *}
 | |
| 277 | ||
| 278 | lemma less_imp_neq: "[| (x::'a::order) < y |] ==> x ~= y" | |
| 279 | by (erule contrapos_pn, erule subst, rule order_less_irrefl) | |
| 280 | ||
| 281 | lemma eq_neq_eq_imp_neq: "[| x = a ; a ~= b; b = y |] ==> x ~= y" | |
| 282 | by (erule subst, erule ssubst, assumption) | |
| 283 | ||
| 284 | ML_setup {*
 | |
| 285 | ||
| 286 | (* The setting up of Quasi_Tac serves as a demo. Since there is no | |
| 287 | class for quasi orders, the tactics Quasi_Tac.trans_tac and | |
| 288 | Quasi_Tac.quasi_tac are not of much use. *) | |
| 289 | ||
| 290 | fun decomp_gen sort sign (Trueprop $ t) = | |
| 15622 
4723248c982b
Transitivity reasoner ignores types amenable to linear arithmetic.
 ballarin parents: 
15531diff
changeset | 291 | let fun of_sort t = let val T = type_of t in | 
| 
4723248c982b
Transitivity reasoner ignores types amenable to linear arithmetic.
 ballarin parents: 
15531diff
changeset | 292 | (* exclude numeric types: linear arithmetic subsumes transitivity *) | 
| 
4723248c982b
Transitivity reasoner ignores types amenable to linear arithmetic.
 ballarin parents: 
15531diff
changeset | 293 | T <> HOLogic.natT andalso T <> HOLogic.intT andalso | 
| 
4723248c982b
Transitivity reasoner ignores types amenable to linear arithmetic.
 ballarin parents: 
15531diff
changeset | 294 | T <> HOLogic.realT andalso Sign.of_sort sign (T, sort) end | 
| 15524 | 295 |   fun dec (Const ("Not", _) $ t) = (
 | 
| 296 | case dec t of | |
| 15531 | 297 | NONE => NONE | 
| 298 | | SOME (t1, rel, t2) => SOME (t1, "~" ^ rel, t2)) | |
| 15524 | 299 | 	| dec (Const ("op =",  _) $ t1 $ t2) =
 | 
| 300 | if of_sort t1 | |
| 15531 | 301 | then SOME (t1, "=", t2) | 
| 302 | else NONE | |
| 19277 | 303 | 	| dec (Const ("Orderings.less_eq",  _) $ t1 $ t2) =
 | 
| 15524 | 304 | if of_sort t1 | 
| 15531 | 305 | then SOME (t1, "<=", t2) | 
| 306 | else NONE | |
| 19277 | 307 | 	| dec (Const ("Orderings.less",  _) $ t1 $ t2) =
 | 
| 15524 | 308 | if of_sort t1 | 
| 15531 | 309 | then SOME (t1, "<", t2) | 
| 310 | else NONE | |
| 311 | | dec _ = NONE | |
| 15524 | 312 | in dec t end; | 
| 313 | ||
| 314 | structure Quasi_Tac = Quasi_Tac_Fun ( | |
| 315 | struct | |
| 316 | val le_trans = thm "order_trans"; | |
| 317 | val le_refl = thm "order_refl"; | |
| 318 | val eqD1 = thm "order_eq_refl"; | |
| 319 | val eqD2 = thm "sym" RS thm "order_eq_refl"; | |
| 320 | val less_reflE = thm "order_less_irrefl" RS thm "notE"; | |
| 321 | val less_imp_le = thm "order_less_imp_le"; | |
| 322 | val le_neq_trans = thm "order_le_neq_trans"; | |
| 323 | val neq_le_trans = thm "order_neq_le_trans"; | |
| 324 | val less_imp_neq = thm "less_imp_neq"; | |
| 325 | val decomp_trans = decomp_gen ["Orderings.order"]; | |
| 326 | val decomp_quasi = decomp_gen ["Orderings.order"]; | |
| 327 | ||
| 328 | end); (* struct *) | |
| 329 | ||
| 330 | structure Order_Tac = Order_Tac_Fun ( | |
| 331 | struct | |
| 332 | val less_reflE = thm "order_less_irrefl" RS thm "notE"; | |
| 333 | val le_refl = thm "order_refl"; | |
| 334 | val less_imp_le = thm "order_less_imp_le"; | |
| 335 | val not_lessI = thm "linorder_not_less" RS thm "iffD2"; | |
| 336 | val not_leI = thm "linorder_not_le" RS thm "iffD2"; | |
| 337 | val not_lessD = thm "linorder_not_less" RS thm "iffD1"; | |
| 338 | val not_leD = thm "linorder_not_le" RS thm "iffD1"; | |
| 339 | val eqI = thm "order_antisym"; | |
| 340 | val eqD1 = thm "order_eq_refl"; | |
| 341 | val eqD2 = thm "sym" RS thm "order_eq_refl"; | |
| 342 | val less_trans = thm "order_less_trans"; | |
| 343 | val less_le_trans = thm "order_less_le_trans"; | |
| 344 | val le_less_trans = thm "order_le_less_trans"; | |
| 345 | val le_trans = thm "order_trans"; | |
| 346 | val le_neq_trans = thm "order_le_neq_trans"; | |
| 347 | val neq_le_trans = thm "order_neq_le_trans"; | |
| 348 | val less_imp_neq = thm "less_imp_neq"; | |
| 349 | val eq_neq_eq_imp_neq = thm "eq_neq_eq_imp_neq"; | |
| 16743 
21dbff595bf6
1) all theorems in Orderings can now be given as a parameter
 obua parents: 
16417diff
changeset | 350 | val not_sym = thm "not_sym"; | 
| 15524 | 351 | val decomp_part = decomp_gen ["Orderings.order"]; | 
| 352 | val decomp_lin = decomp_gen ["Orderings.linorder"]; | |
| 353 | ||
| 354 | end); (* struct *) | |
| 355 | ||
| 17876 | 356 | change_simpset (fn ss => ss | 
| 15524 | 357 | addSolver (mk_solver "Trans_linear" (fn _ => Order_Tac.linear_tac)) | 
| 17876 | 358 | addSolver (mk_solver "Trans_partial" (fn _ => Order_Tac.partial_tac))); | 
| 15524 | 359 | (* Adding the transitivity reasoners also as safe solvers showed a slight | 
| 360 | speed up, but the reasoning strength appears to be not higher (at least | |
| 361 | no breaking of additional proofs in the entire HOL distribution, as | |
| 362 | of 5 March 2004, was observed). *) | |
| 363 | *} | |
| 364 | ||
| 365 | (* Optional setup of methods *) | |
| 366 | ||
| 367 | (* | |
| 368 | method_setup trans_partial = | |
| 369 |   {* Method.no_args (Method.SIMPLE_METHOD' HEADGOAL (Order_Tac.partial_tac)) *}
 | |
| 370 |   {* transitivity reasoner for partial orders *}	
 | |
| 371 | method_setup trans_linear = | |
| 372 |   {* Method.no_args (Method.SIMPLE_METHOD' HEADGOAL (Order_Tac.linear_tac)) *}
 | |
| 373 |   {* transitivity reasoner for linear orders *}
 | |
| 374 | *) | |
| 375 | ||
| 376 | (* | |
| 377 | declare order.order_refl [simp del] order_less_irrefl [simp del] | |
| 378 | ||
| 379 | can currently not be removed, abel_cancel relies on it. | |
| 380 | *) | |
| 381 | ||
| 382 | ||
| 383 | subsection "Min and max on (linear) orders" | |
| 384 | ||
| 385 | text{* Instantiate locales: *}
 | |
| 386 | ||
| 15837 | 387 | interpretation min_max: | 
| 15780 | 388 | lower_semilattice["op \<le>" "min :: 'a::linorder \<Rightarrow> 'a \<Rightarrow> 'a"] | 
| 19984 
29bb4659f80a
Method intro_locales replaced by intro_locales and unfold_locales.
 ballarin parents: 
19931diff
changeset | 389 | apply unfold_locales | 
| 15524 | 390 | apply(simp add:min_def linorder_not_le order_less_imp_le) | 
| 391 | apply(simp add:min_def linorder_not_le order_less_imp_le) | |
| 392 | apply(simp add:min_def linorder_not_le order_less_imp_le) | |
| 393 | done | |
| 394 | ||
| 15837 | 395 | interpretation min_max: | 
| 15780 | 396 | upper_semilattice["op \<le>" "max :: 'a::linorder \<Rightarrow> 'a \<Rightarrow> 'a"] | 
| 19984 
29bb4659f80a
Method intro_locales replaced by intro_locales and unfold_locales.
 ballarin parents: 
19931diff
changeset | 397 | apply unfold_locales | 
| 15524 | 398 | apply(simp add: max_def linorder_not_le order_less_imp_le) | 
| 399 | apply(simp add: max_def linorder_not_le order_less_imp_le) | |
| 400 | apply(simp add: max_def linorder_not_le order_less_imp_le) | |
| 401 | done | |
| 402 | ||
| 15837 | 403 | interpretation min_max: | 
| 15780 | 404 | lattice["op \<le>" "min :: 'a::linorder \<Rightarrow> 'a \<Rightarrow> 'a" "max"] | 
| 19984 
29bb4659f80a
Method intro_locales replaced by intro_locales and unfold_locales.
 ballarin parents: 
19931diff
changeset | 405 | by unfold_locales | 
| 15524 | 406 | |
| 15837 | 407 | interpretation min_max: | 
| 15780 | 408 | distrib_lattice["op \<le>" "min :: 'a::linorder \<Rightarrow> 'a \<Rightarrow> 'a" "max"] | 
| 19984 
29bb4659f80a
Method intro_locales replaced by intro_locales and unfold_locales.
 ballarin parents: 
19931diff
changeset | 409 | apply unfold_locales | 
| 15524 | 410 | apply(rule_tac x=x and y=y in linorder_le_cases) | 
| 411 | apply(rule_tac x=x and y=z in linorder_le_cases) | |
| 412 | apply(rule_tac x=y and y=z in linorder_le_cases) | |
| 413 | apply(simp add:min_def max_def) | |
| 414 | apply(simp add:min_def max_def) | |
| 415 | apply(rule_tac x=y and y=z in linorder_le_cases) | |
| 416 | apply(simp add:min_def max_def) | |
| 417 | apply(simp add:min_def max_def) | |
| 418 | apply(rule_tac x=x and y=z in linorder_le_cases) | |
| 419 | apply(rule_tac x=y and y=z in linorder_le_cases) | |
| 420 | apply(simp add:min_def max_def) | |
| 421 | apply(simp add:min_def max_def) | |
| 422 | apply(rule_tac x=y and y=z in linorder_le_cases) | |
| 423 | apply(simp add:min_def max_def) | |
| 424 | apply(simp add:min_def max_def) | |
| 425 | done | |
| 426 | ||
| 427 | lemma le_max_iff_disj: "!!z::'a::linorder. (z <= max x y) = (z <= x | z <= y)" | |
| 428 | apply(simp add:max_def) | |
| 429 | apply (insert linorder_linear) | |
| 430 | apply (blast intro: order_trans) | |
| 431 | done | |
| 432 | ||
| 15780 | 433 | lemmas le_maxI1 = min_max.sup_ge1 | 
| 434 | lemmas le_maxI2 = min_max.sup_ge2 | |
| 15524 | 435 | |
| 436 | lemma less_max_iff_disj: "!!z::'a::linorder. (z < max x y) = (z < x | z < y)" | |
| 437 | apply (simp add: max_def order_le_less) | |
| 438 | apply (insert linorder_less_linear) | |
| 439 | apply (blast intro: order_less_trans) | |
| 440 | done | |
| 441 | ||
| 442 | lemma max_less_iff_conj [simp]: | |
| 443 | "!!z::'a::linorder. (max x y < z) = (x < z & y < z)" | |
| 444 | apply (simp add: order_le_less max_def) | |
| 445 | apply (insert linorder_less_linear) | |
| 446 | apply (blast intro: order_less_trans) | |
| 447 | done | |
| 15791 | 448 | |
| 15524 | 449 | lemma min_less_iff_conj [simp]: | 
| 450 | "!!z::'a::linorder. (z < min x y) = (z < x & z < y)" | |
| 451 | apply (simp add: order_le_less min_def) | |
| 452 | apply (insert linorder_less_linear) | |
| 453 | apply (blast intro: order_less_trans) | |
| 454 | done | |
| 455 | ||
| 456 | lemma min_le_iff_disj: "!!z::'a::linorder. (min x y <= z) = (x <= z | y <= z)" | |
| 457 | apply (simp add: min_def) | |
| 458 | apply (insert linorder_linear) | |
| 459 | apply (blast intro: order_trans) | |
| 460 | done | |
| 461 | ||
| 462 | lemma min_less_iff_disj: "!!z::'a::linorder. (min x y < z) = (x < z | y < z)" | |
| 463 | apply (simp add: min_def order_le_less) | |
| 464 | apply (insert linorder_less_linear) | |
| 465 | apply (blast intro: order_less_trans) | |
| 466 | done | |
| 467 | ||
| 15780 | 468 | lemmas max_ac = min_max.sup_assoc min_max.sup_commute | 
| 469 | mk_left_commute[of max,OF min_max.sup_assoc min_max.sup_commute] | |
| 15524 | 470 | |
| 15780 | 471 | lemmas min_ac = min_max.inf_assoc min_max.inf_commute | 
| 472 | mk_left_commute[of min,OF min_max.inf_assoc min_max.inf_commute] | |
| 15524 | 473 | |
| 474 | lemma split_min: | |
| 475 | "P (min (i::'a::linorder) j) = ((i <= j --> P(i)) & (~ i <= j --> P(j)))" | |
| 476 | by (simp add: min_def) | |
| 477 | ||
| 478 | lemma split_max: | |
| 479 | "P (max (i::'a::linorder) j) = ((i <= j --> P(j)) & (~ i <= j --> P(i)))" | |
| 480 | by (simp add: max_def) | |
| 481 | ||
| 482 | ||
| 483 | subsection "Bounded quantifiers" | |
| 484 | ||
| 485 | syntax | |
| 486 |   "_lessAll" :: "[idt, 'a, bool] => bool"   ("(3ALL _<_./ _)"  [0, 0, 10] 10)
 | |
| 487 |   "_lessEx"  :: "[idt, 'a, bool] => bool"   ("(3EX _<_./ _)"  [0, 0, 10] 10)
 | |
| 488 |   "_leAll"   :: "[idt, 'a, bool] => bool"   ("(3ALL _<=_./ _)" [0, 0, 10] 10)
 | |
| 489 |   "_leEx"    :: "[idt, 'a, bool] => bool"   ("(3EX _<=_./ _)" [0, 0, 10] 10)
 | |
| 490 | ||
| 491 |   "_gtAll" :: "[idt, 'a, bool] => bool"   ("(3ALL _>_./ _)"  [0, 0, 10] 10)
 | |
| 492 |   "_gtEx"  :: "[idt, 'a, bool] => bool"   ("(3EX _>_./ _)"  [0, 0, 10] 10)
 | |
| 493 |   "_geAll"   :: "[idt, 'a, bool] => bool"   ("(3ALL _>=_./ _)" [0, 0, 10] 10)
 | |
| 494 |   "_geEx"    :: "[idt, 'a, bool] => bool"   ("(3EX _>=_./ _)" [0, 0, 10] 10)
 | |
| 495 | ||
| 496 | syntax (xsymbols) | |
| 497 |   "_lessAll" :: "[idt, 'a, bool] => bool"   ("(3\<forall>_<_./ _)"  [0, 0, 10] 10)
 | |
| 498 |   "_lessEx"  :: "[idt, 'a, bool] => bool"   ("(3\<exists>_<_./ _)"  [0, 0, 10] 10)
 | |
| 499 |   "_leAll"   :: "[idt, 'a, bool] => bool"   ("(3\<forall>_\<le>_./ _)" [0, 0, 10] 10)
 | |
| 500 |   "_leEx"    :: "[idt, 'a, bool] => bool"   ("(3\<exists>_\<le>_./ _)" [0, 0, 10] 10)
 | |
| 501 | ||
| 502 |   "_gtAll" :: "[idt, 'a, bool] => bool"   ("(3\<forall>_>_./ _)"  [0, 0, 10] 10)
 | |
| 503 |   "_gtEx"  :: "[idt, 'a, bool] => bool"   ("(3\<exists>_>_./ _)"  [0, 0, 10] 10)
 | |
| 504 |   "_geAll"   :: "[idt, 'a, bool] => bool"   ("(3\<forall>_\<ge>_./ _)" [0, 0, 10] 10)
 | |
| 505 |   "_geEx"    :: "[idt, 'a, bool] => bool"   ("(3\<exists>_\<ge>_./ _)" [0, 0, 10] 10)
 | |
| 506 | ||
| 507 | syntax (HOL) | |
| 508 |   "_lessAll" :: "[idt, 'a, bool] => bool"   ("(3! _<_./ _)"  [0, 0, 10] 10)
 | |
| 509 |   "_lessEx"  :: "[idt, 'a, bool] => bool"   ("(3? _<_./ _)"  [0, 0, 10] 10)
 | |
| 510 |   "_leAll"   :: "[idt, 'a, bool] => bool"   ("(3! _<=_./ _)" [0, 0, 10] 10)
 | |
| 511 |   "_leEx"    :: "[idt, 'a, bool] => bool"   ("(3? _<=_./ _)" [0, 0, 10] 10)
 | |
| 512 | ||
| 513 | syntax (HTML output) | |
| 514 |   "_lessAll" :: "[idt, 'a, bool] => bool"   ("(3\<forall>_<_./ _)"  [0, 0, 10] 10)
 | |
| 515 |   "_lessEx"  :: "[idt, 'a, bool] => bool"   ("(3\<exists>_<_./ _)"  [0, 0, 10] 10)
 | |
| 516 |   "_leAll"   :: "[idt, 'a, bool] => bool"   ("(3\<forall>_\<le>_./ _)" [0, 0, 10] 10)
 | |
| 517 |   "_leEx"    :: "[idt, 'a, bool] => bool"   ("(3\<exists>_\<le>_./ _)" [0, 0, 10] 10)
 | |
| 518 | ||
| 519 |   "_gtAll" :: "[idt, 'a, bool] => bool"   ("(3\<forall>_>_./ _)"  [0, 0, 10] 10)
 | |
| 520 |   "_gtEx"  :: "[idt, 'a, bool] => bool"   ("(3\<exists>_>_./ _)"  [0, 0, 10] 10)
 | |
| 521 |   "_geAll"   :: "[idt, 'a, bool] => bool"   ("(3\<forall>_\<ge>_./ _)" [0, 0, 10] 10)
 | |
| 522 |   "_geEx"    :: "[idt, 'a, bool] => bool"   ("(3\<exists>_\<ge>_./ _)" [0, 0, 10] 10)
 | |
| 523 | ||
| 524 | translations | |
| 525 | "ALL x<y. P" => "ALL x. x < y --> P" | |
| 526 | "EX x<y. P" => "EX x. x < y & P" | |
| 527 | "ALL x<=y. P" => "ALL x. x <= y --> P" | |
| 528 | "EX x<=y. P" => "EX x. x <= y & P" | |
| 529 | "ALL x>y. P" => "ALL x. x > y --> P" | |
| 530 | "EX x>y. P" => "EX x. x > y & P" | |
| 531 | "ALL x>=y. P" => "ALL x. x >= y --> P" | |
| 532 | "EX x>=y. P" => "EX x. x >= y & P" | |
| 533 | ||
| 534 | print_translation {*
 | |
| 535 | let | |
| 536 | fun mk v v' q n P = | |
| 16861 | 537 | if v=v' andalso not (v mem (map fst (Term.add_frees n []))) | 
| 15524 | 538 | then Syntax.const q $ Syntax.mark_bound v' $ n $ P else raise Match; | 
| 539 |   fun all_tr' [Const ("_bound",_) $ Free (v,_),
 | |
| 19637 | 540 |                Const("op -->",_) $ (Const ("less",_) $ (Const ("_bound",_) $ Free (v',_)) $ n ) $ P] =
 | 
| 15524 | 541 | mk v v' "_lessAll" n P | 
| 542 | ||
| 543 |   | all_tr' [Const ("_bound",_) $ Free (v,_),
 | |
| 19637 | 544 |                Const("op -->",_) $ (Const ("less_eq",_) $ (Const ("_bound",_) $ Free (v',_)) $ n ) $ P] =
 | 
| 15524 | 545 | mk v v' "_leAll" n P | 
| 546 | ||
| 547 |   | all_tr' [Const ("_bound",_) $ Free (v,_),
 | |
| 19637 | 548 |                Const("op -->",_) $ (Const ("less",_) $ n $ (Const ("_bound",_) $ Free (v',_))) $ P] =
 | 
| 15524 | 549 | mk v v' "_gtAll" n P | 
| 550 | ||
| 551 |   | all_tr' [Const ("_bound",_) $ Free (v,_),
 | |
| 19637 | 552 |                Const("op -->",_) $ (Const ("less_eq",_) $ n $ (Const ("_bound",_) $ Free (v',_))) $ P] =
 | 
| 15524 | 553 | mk v v' "_geAll" n P; | 
| 554 | ||
| 555 |   fun ex_tr' [Const ("_bound",_) $ Free (v,_),
 | |
| 19637 | 556 |                Const("op &",_) $ (Const ("less",_) $ (Const ("_bound",_) $ Free (v',_)) $ n ) $ P] =
 | 
| 15524 | 557 | mk v v' "_lessEx" n P | 
| 558 | ||
| 559 |   | ex_tr' [Const ("_bound",_) $ Free (v,_),
 | |
| 19637 | 560 |                Const("op &",_) $ (Const ("less_eq",_) $ (Const ("_bound",_) $ Free (v',_)) $ n ) $ P] =
 | 
| 15524 | 561 | mk v v' "_leEx" n P | 
| 562 | ||
| 563 |   | ex_tr' [Const ("_bound",_) $ Free (v,_),
 | |
| 19637 | 564 |                Const("op &",_) $ (Const ("less",_) $ n $ (Const ("_bound",_) $ Free (v',_))) $ P] =
 | 
| 15524 | 565 | mk v v' "_gtEx" n P | 
| 566 | ||
| 567 |   | ex_tr' [Const ("_bound",_) $ Free (v,_),
 | |
| 19637 | 568 |                Const("op &",_) $ (Const ("less_eq",_) $ n $ (Const ("_bound",_) $ Free (v',_))) $ P] =
 | 
| 15524 | 569 | mk v v' "_geEx" n P | 
| 570 | in | |
| 571 | [("ALL ", all_tr'), ("EX ", ex_tr')]
 | |
| 572 | end | |
| 573 | *} | |
| 574 | ||
| 17012 | 575 | subsection {* Extra transitivity rules *}
 | 
| 576 | ||
| 577 | text {* These support proving chains of decreasing inequalities
 | |
| 578 | a >= b >= c ... in Isar proofs. *} | |
| 579 | ||
| 580 | lemma xt1: "a = b ==> b > c ==> a > c" | |
| 581 | by simp | |
| 582 | ||
| 583 | lemma xt2: "a > b ==> b = c ==> a > c" | |
| 584 | by simp | |
| 585 | ||
| 586 | lemma xt3: "a = b ==> b >= c ==> a >= c" | |
| 587 | by simp | |
| 588 | ||
| 589 | lemma xt4: "a >= b ==> b = c ==> a >= c" | |
| 590 | by simp | |
| 591 | ||
| 592 | lemma xt5: "(x::'a::order) >= y ==> y >= x ==> x = y" | |
| 593 | by simp | |
| 594 | ||
| 595 | lemma xt6: "(x::'a::order) >= y ==> y >= z ==> x >= z" | |
| 596 | by simp | |
| 597 | ||
| 598 | lemma xt7: "(x::'a::order) > y ==> y >= z ==> x > z" | |
| 599 | by simp | |
| 600 | ||
| 601 | lemma xt8: "(x::'a::order) >= y ==> y > z ==> x > z" | |
| 602 | by simp | |
| 603 | ||
| 604 | lemma xt9: "(a::'a::order) > b ==> b > a ==> ?P" | |
| 605 | by simp | |
| 606 | ||
| 607 | lemma xt10: "(x::'a::order) > y ==> y > z ==> x > z" | |
| 608 | by simp | |
| 609 | ||
| 610 | lemma xt11: "(a::'a::order) >= b ==> a ~= b ==> a > b" | |
| 611 | by simp | |
| 612 | ||
| 613 | lemma xt12: "(a::'a::order) ~= b ==> a >= b ==> a > b" | |
| 614 | by simp | |
| 615 | ||
| 616 | lemma xt13: "a = f b ==> b > c ==> (!!x y. x > y ==> f x > f y) ==> | |
| 617 | a > f c" | |
| 618 | by simp | |
| 619 | ||
| 620 | lemma xt14: "a > b ==> f b = c ==> (!!x y. x > y ==> f x > f y) ==> | |
| 621 | f a > c" | |
| 622 | by auto | |
| 623 | ||
| 624 | lemma xt15: "a = f b ==> b >= c ==> (!!x y. x >= y ==> f x >= f y) ==> | |
| 625 | a >= f c" | |
| 626 | by simp | |
| 627 | ||
| 628 | lemma xt16: "a >= b ==> f b = c ==> (!! x y. x >= y ==> f x >= f y) ==> | |
| 629 | f a >= c" | |
| 630 | by auto | |
| 631 | ||
| 632 | lemma xt17: "(a::'a::order) >= f b ==> b >= c ==> | |
| 633 | (!!x y. x >= y ==> f x >= f y) ==> a >= f c" | |
| 634 | by (subgoal_tac "f b >= f c", force, force) | |
| 635 | ||
| 636 | lemma xt18: "(a::'a::order) >= b ==> (f b::'b::order) >= c ==> | |
| 637 | (!!x y. x >= y ==> f x >= f y) ==> f a >= c" | |
| 638 | by (subgoal_tac "f a >= f b", force, force) | |
| 639 | ||
| 640 | lemma xt19: "(a::'a::order) > f b ==> (b::'b::order) >= c ==> | |
| 641 | (!!x y. x >= y ==> f x >= f y) ==> a > f c" | |
| 642 | by (subgoal_tac "f b >= f c", force, force) | |
| 643 | ||
| 644 | lemma xt20: "(a::'a::order) > b ==> (f b::'b::order) >= c==> | |
| 645 | (!!x y. x > y ==> f x > f y) ==> f a > c" | |
| 646 | by (subgoal_tac "f a > f b", force, force) | |
| 647 | ||
| 648 | lemma xt21: "(a::'a::order) >= f b ==> b > c ==> | |
| 649 | (!!x y. x > y ==> f x > f y) ==> a > f c" | |
| 650 | by (subgoal_tac "f b > f c", force, force) | |
| 651 | ||
| 652 | lemma xt22: "(a::'a::order) >= b ==> (f b::'b::order) > c ==> | |
| 653 | (!!x y. x >= y ==> f x >= f y) ==> f a > c" | |
| 654 | by (subgoal_tac "f a >= f b", force, force) | |
| 655 | ||
| 656 | lemma xt23: "(a::'a::order) > f b ==> (b::'b::order) > c ==> | |
| 657 | (!!x y. x > y ==> f x > f y) ==> a > f c" | |
| 658 | by (subgoal_tac "f b > f c", force, force) | |
| 659 | ||
| 660 | lemma xt24: "(a::'a::order) > b ==> (f b::'b::order) > c ==> | |
| 661 | (!!x y. x > y ==> f x > f y) ==> f a > c" | |
| 662 | by (subgoal_tac "f a > f b", force, force) | |
| 663 | ||
| 664 | ||
| 665 | lemmas xtrans = xt1 xt2 xt3 xt4 xt5 xt6 xt7 xt8 xt9 xt10 xt11 xt12 | |
| 666 | xt13 xt14 xt15 xt15 xt17 xt18 xt19 xt20 xt21 xt22 xt23 xt24 | |
| 667 | ||
| 668 | (* | |
| 669 | Since "a >= b" abbreviates "b <= a", the abbreviation "..." stands | |
| 670 | for the wrong thing in an Isar proof. | |
| 671 | ||
| 672 | The extra transitivity rules can be used as follows: | |
| 673 | ||
| 674 | lemma "(a::'a::order) > z" | |
| 675 | proof - | |
| 676 | have "a >= b" (is "_ >= ?rhs") | |
| 677 | sorry | |
| 678 | also have "?rhs >= c" (is "_ >= ?rhs") | |
| 679 | sorry | |
| 680 | also (xtrans) have "?rhs = d" (is "_ = ?rhs") | |
| 681 | sorry | |
| 682 | also (xtrans) have "?rhs >= e" (is "_ >= ?rhs") | |
| 683 | sorry | |
| 684 | also (xtrans) have "?rhs > f" (is "_ > ?rhs") | |
| 685 | sorry | |
| 686 | also (xtrans) have "?rhs > z" | |
| 687 | sorry | |
| 688 | finally (xtrans) show ?thesis . | |
| 689 | qed | |
| 690 | ||
| 691 | Alternatively, one can use "declare xtrans [trans]" and then | |
| 692 | leave out the "(xtrans)" above. | |
| 693 | *) | |
| 694 | ||
| 15524 | 695 | end |