src/HOL/Orderings.thy
changeset 24641 448edc627ee4
parent 24422 c0b5ff9e9e4d
child 24704 9a95634ab135
equal deleted inserted replaced
24640:85a6c200ecd3 24641:448edc627ee4
     6 header {* Syntactic and abstract orders *}
     6 header {* Syntactic and abstract orders *}
     7 
     7 
     8 theory Orderings
     8 theory Orderings
     9 imports Set Fun
     9 imports Set Fun
    10 uses
    10 uses
    11   (*"~~/src/Provers/quasi.ML"*)
       
    12   "~~/src/Provers/order.ML"
    11   "~~/src/Provers/order.ML"
    13 begin
    12 begin
    14 
    13 
    15 subsection {* Partial orders *}
    14 subsection {* Partial orders *}
    16 
    15 
   237 
   236 
   238 
   237 
   239 subsection {* Reasoning tools setup *}
   238 subsection {* Reasoning tools setup *}
   240 
   239 
   241 ML {*
   240 ML {*
   242 local
   241 
   243 
   242 signature ORDERS =
   244 fun decomp_gen sort thy (Trueprop $ t) =
   243 sig
       
   244   val print_structures: Proof.context -> unit
       
   245   val setup: theory -> theory
       
   246   val order_tac: Proof.context -> int -> tactic
       
   247 end;
       
   248 
       
   249 structure Orders: ORDERS =
       
   250 struct
       
   251 
       
   252 (** Theory and context data **)
       
   253 
       
   254 fun struct_eq ((s1: string, ts1), (s2, ts2)) =
       
   255   (s1 = s2) andalso eq_list (op aconv) (ts1, ts2);
       
   256 
       
   257 structure Data = GenericDataFun
       
   258 (
       
   259   type T = ((string * term list) * Order_Tac.less_arith) list;
       
   260     (* Order structures:
       
   261        identifier of the structure, list of operations and record of theorems
       
   262        needed to set up the transitivity reasoner,
       
   263        identifier and operations identify the structure uniquely. *)
       
   264   val empty = [];
       
   265   val extend = I;
       
   266   fun merge _ = AList.join struct_eq (K fst);
       
   267 );
       
   268 
       
   269 fun print_structures ctxt =
   245   let
   270   let
   246     fun of_sort t =
   271     val structs = Data.get (Context.Proof ctxt);
       
   272     fun pretty_term t = Pretty.block
       
   273       [Pretty.quote (ProofContext.pretty_term ctxt t), Pretty.brk 1,
       
   274         Pretty.str "::", Pretty.brk 1,
       
   275         Pretty.quote (ProofContext.pretty_typ ctxt (type_of t))];
       
   276     fun pretty_struct ((s, ts), _) = Pretty.block
       
   277       [Pretty.str s, Pretty.str ":", Pretty.brk 1,
       
   278        Pretty.enclose "(" ")" (Pretty.breaks (map pretty_term ts))];
       
   279   in
       
   280     Pretty.writeln (Pretty.big_list "Order structures:" (map pretty_struct structs))
       
   281   end;
       
   282 
       
   283 
       
   284 (** Method **)
       
   285 
       
   286 fun struct_tac ((s, [eq, le, less]), thms) =
       
   287   let
       
   288     fun decomp thy (Trueprop $ t) =
   247       let
   289       let
   248         val T = type_of t
   290         fun excluded t =
   249       in
   291           (* exclude numeric types: linear arithmetic subsumes transitivity *)
   250         (* exclude numeric types: linear arithmetic subsumes transitivity *)
   292           let val T = type_of t
   251         T <> HOLogic.natT andalso T <> HOLogic.intT
   293           in
   252           andalso T <> HOLogic.realT andalso Sign.of_sort thy (T, sort)
   294 	    T = HOLogic.natT orelse T = HOLogic.intT orelse T = HOLogic.realT
   253       end;
   295           end;
   254     fun dec (Const (@{const_name Not}, _) $ t) = (case dec t
   296 	fun dec (Const (@{const_name Not}, _) $ t) = (case dec t
   255           of NONE => NONE
   297 	      of NONE => NONE
   256            | SOME (t1, rel, t2) => SOME (t1, "~" ^ rel, t2))
   298 	       | SOME (t1, rel, t2) => SOME (t1, "~" ^ rel, t2))
   257       | dec (Const (@{const_name "op ="},  _) $ t1 $ t2) =
   299           | dec (bin_op $ t1 $ t2) =
   258           if of_sort t1
   300               if excluded t1 then NONE
   259           then SOME (t1, "=", t2)
   301               else if Pattern.matches thy (eq, bin_op) then SOME (t1, "=", t2)
   260           else NONE
   302               else if Pattern.matches thy (le, bin_op) then SOME (t1, "<=", t2)
   261       | dec (Const (@{const_name HOL.less_eq},  _) $ t1 $ t2) =
   303               else if Pattern.matches thy (less, bin_op) then SOME (t1, "<", t2)
   262           if of_sort t1
   304               else NONE
   263           then SOME (t1, "<=", t2)
   305 	  | dec _ = NONE;
   264           else NONE
   306       in dec t end;
   265       | dec (Const (@{const_name HOL.less},  _) $ t1 $ t2) =
   307   in
   266           if of_sort t1
   308     case s of
   267           then SOME (t1, "<", t2)
   309       "order" => Order_Tac.partial_tac decomp thms
   268           else NONE
   310     | "linorder" => Order_Tac.linear_tac decomp thms
   269       | dec _ = NONE;
   311     | _ => error ("Unknown kind of order `" ^ s ^ "' encountered in transitivity reasoner.")
   270   in dec t end;
   312   end
   271 
   313 
   272 in
   314 fun order_tac ctxt =
   273 
   315   FIRST' (map (fn s => CHANGED o struct_tac s) (Data.get (Context.Proof ctxt)));
   274 (* sorry - there is no preorder class
   316 
   275 structure Quasi_Tac = Quasi_Tac_Fun (
   317 
   276 struct
   318 (** Attribute **)
   277   val le_trans = thm "order_trans";
   319 
   278   val le_refl = thm "order_refl";
   320 fun add_struct_thm s tag =
   279   val eqD1 = thm "order_eq_refl";
   321   Thm.declaration_attribute
   280   val eqD2 = thm "sym" RS thm "order_eq_refl";
   322     (fn thm => Data.map (AList.map_default struct_eq (s, Order_Tac.empty TrueI) (Order_Tac.update tag thm)));
   281   val less_reflE = thm "order_less_irrefl" RS thm "notE";
   323 fun del_struct s =
   282   val less_imp_le = thm "order_less_imp_le";
   324   Thm.declaration_attribute
   283   val le_neq_trans = thm "order_le_neq_trans";
   325     (fn _ => Data.map (AList.delete struct_eq s));
   284   val neq_le_trans = thm "order_neq_le_trans";
   326 
   285   val less_imp_neq = thm "less_imp_neq";
   327 val attribute = Attrib.syntax
   286   val decomp_trans = decomp_gen ["Orderings.preorder"];
   328      (Scan.lift ((Args.add -- Args.name >> (fn (_, s) => SOME s) ||
   287   val decomp_quasi = decomp_gen ["Orderings.preorder"];
   329           Args.del >> K NONE) --| Args.colon (* FIXME ||
   288 end);*)
   330         Scan.succeed true *) ) -- Scan.lift Args.name --
   289 
   331       Scan.repeat Args.term
   290 structure Order_Tac = Order_Tac_Fun (
   332       >> (fn ((SOME tag, n), ts) => add_struct_thm (n, ts) tag
   291 struct
   333            | ((NONE, n), ts) => del_struct (n, ts)));
   292   val less_reflE = @{thm less_irrefl} RS @{thm notE};
   334 
   293   val le_refl = @{thm order_refl};
   335 
   294   val less_imp_le = @{thm less_imp_le};
   336 (** Diagnostic command **)
   295   val not_lessI = @{thm not_less} RS @{thm iffD2};
   337 
   296   val not_leI = @{thm not_le} RS @{thm iffD2};
   338 val print = Toplevel.unknown_context o
   297   val not_lessD = @{thm not_less} RS @{thm iffD1};
   339   Toplevel.keep (Toplevel.node_case
   298   val not_leD = @{thm not_le} RS @{thm iffD1};
   340     (Context.cases (print_structures o ProofContext.init) print_structures)
   299   val eqI = @{thm antisym};
   341     (print_structures o Proof.context_of));
   300   val eqD1 = @{thm eq_refl};
   342 
   301   val eqD2 = @{thm sym} RS @{thm eq_refl};
   343 val printP =
   302   val less_trans = @{thm less_trans};
   344   OuterSyntax.improper_command "print_orders"
   303   val less_le_trans = @{thm less_le_trans};
   345     "print order structures available to transitivity reasoner" OuterKeyword.diag
   304   val le_less_trans = @{thm le_less_trans};
   346     (Scan.succeed (Toplevel.no_timing o print));
   305   val le_trans = @{thm order_trans};
   347 
   306   val le_neq_trans = @{thm le_neq_trans};
   348 
   307   val neq_le_trans = @{thm neq_le_trans};
   349 (** Setup **)
   308   val less_imp_neq = @{thm less_imp_neq};
   350 
   309   val eq_neq_eq_imp_neq = @{thm eq_neq_eq_imp_neq};
   351 val setup = let val _ = OuterSyntax.add_parsers [printP] in
   310   val not_sym = @{thm not_sym};
   352     Method.add_methods [("order", Method.ctxt_args (Method.SIMPLE_METHOD' o order_tac),
   311   val decomp_part = decomp_gen ["Orderings.order"];
   353       "normalisation of algebraic structure")] #>
   312   val decomp_lin = decomp_gen ["Orderings.linorder"];
   354     Attrib.add_attributes [("order", attribute, "theorems controlling transitivity reasoner")]
   313 end);
   355   end;
   314 
   356 
   315 end;
   357 end;
       
   358 
   316 *}
   359 *}
       
   360 
       
   361 setup Orders.setup
       
   362 
       
   363 
       
   364 text {* Declarations to set up transitivity reasoner of partial and linear orders. *}
       
   365 
       
   366 (* The type constraint on @{term op =} below is necessary since the operation
       
   367    is not a parameter of the locale. *)
       
   368 lemmas (in order)
       
   369   [order add less_reflE: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   370   less_irrefl [THEN notE]
       
   371 lemmas (in order)
       
   372   [order add le_refl: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   373   order_refl
       
   374 lemmas (in order)
       
   375   [order add less_imp_le: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   376   less_imp_le
       
   377 lemmas (in order)
       
   378   [order add eqI: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   379   antisym
       
   380 lemmas (in order)
       
   381   [order add eqD1: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   382   eq_refl
       
   383 lemmas (in order)
       
   384   [order add eqD2: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   385   sym [THEN eq_refl]
       
   386 lemmas (in order)
       
   387   [order add less_trans: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   388   less_trans
       
   389 lemmas (in order)
       
   390   [order add less_le_trans: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   391   less_le_trans
       
   392 lemmas (in order)
       
   393   [order add le_less_trans: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   394   le_less_trans
       
   395 lemmas (in order)
       
   396   [order add le_trans: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   397   order_trans
       
   398 lemmas (in order)
       
   399   [order add le_neq_trans: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   400   le_neq_trans
       
   401 lemmas (in order)
       
   402   [order add neq_le_trans: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   403   neq_le_trans
       
   404 lemmas (in order)
       
   405   [order add less_imp_neq: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   406   less_imp_neq
       
   407 lemmas (in order)
       
   408   [order add eq_neq_eq_imp_neq: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   409    eq_neq_eq_imp_neq
       
   410 lemmas (in order)
       
   411   [order add not_sym: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   412   not_sym
       
   413 
       
   414 lemmas (in linorder) [order del: order "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] = _
       
   415 
       
   416 lemmas (in linorder)
       
   417   [order add less_reflE: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   418   less_irrefl [THEN notE]
       
   419 lemmas (in linorder)
       
   420   [order add le_refl: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   421   order_refl
       
   422 lemmas (in linorder)
       
   423   [order add less_imp_le: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   424   less_imp_le
       
   425 lemmas (in linorder)
       
   426   [order add not_lessI: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   427   not_less [THEN iffD2]
       
   428 lemmas (in linorder)
       
   429   [order add not_leI: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   430   not_le [THEN iffD2]
       
   431 lemmas (in linorder)
       
   432   [order add not_lessD: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   433   not_less [THEN iffD1]
       
   434 lemmas (in linorder)
       
   435   [order add not_leD: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   436   not_le [THEN iffD1]
       
   437 lemmas (in linorder)
       
   438   [order add eqI: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   439   antisym
       
   440 lemmas (in linorder)
       
   441   [order add eqD1: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   442   eq_refl
       
   443 lemmas (in linorder)
       
   444   [order add eqD2: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   445   sym [THEN eq_refl]
       
   446 lemmas (in linorder)
       
   447   [order add less_trans: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   448   less_trans
       
   449 lemmas (in linorder)
       
   450   [order add less_le_trans: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   451   less_le_trans
       
   452 lemmas (in linorder)
       
   453   [order add le_less_trans: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   454   le_less_trans
       
   455 lemmas (in linorder)
       
   456   [order add le_trans: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   457   order_trans
       
   458 lemmas (in linorder)
       
   459   [order add le_neq_trans: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   460   le_neq_trans
       
   461 lemmas (in linorder)
       
   462   [order add neq_le_trans: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   463   neq_le_trans
       
   464 lemmas (in linorder)
       
   465   [order add less_imp_neq: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   466   less_imp_neq
       
   467 lemmas (in linorder)
       
   468   [order add eq_neq_eq_imp_neq: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   469   eq_neq_eq_imp_neq
       
   470 lemmas (in linorder)
       
   471   [order add not_sym: linorder "op = :: 'a => 'a => bool" "op \<^loc><=" "op \<^loc><"] =
       
   472   not_sym
       
   473 
   317 
   474 
   318 setup {*
   475 setup {*
   319 let
   476 let
   320 
   477 
   321 fun prp t thm = (#prop (rep_thm thm) = t);
   478 fun prp t thm = (#prop (rep_thm thm) = t);
   354   (Simplifier.change_simpset_of thy (fn ss => ss
   511   (Simplifier.change_simpset_of thy (fn ss => ss
   355     addsimprocs (map (fn (name, raw_ts, proc) =>
   512     addsimprocs (map (fn (name, raw_ts, proc) =>
   356       Simplifier.simproc thy name raw_ts proc)) procs); thy);
   513       Simplifier.simproc thy name raw_ts proc)) procs); thy);
   357 fun add_solver name tac thy =
   514 fun add_solver name tac thy =
   358   (Simplifier.change_simpset_of thy (fn ss => ss addSolver
   515   (Simplifier.change_simpset_of thy (fn ss => ss addSolver
   359     (mk_solver name (K tac))); thy);
   516     (mk_solver' name (fn ss => tac (MetaSimplifier.the_context ss)))); thy);
   360 
   517 
   361 in
   518 in
   362   add_simprocs [
   519   add_simprocs [
   363        ("antisym le", ["(x::'a::order) <= y"], prove_antisym_le),
   520        ("antisym le", ["(x::'a::order) <= y"], prove_antisym_le),
   364        ("antisym less", ["~ (x::'a::linorder) < y"], prove_antisym_less)
   521        ("antisym less", ["~ (x::'a::linorder) < y"], prove_antisym_less)
   365      ]
   522      ]
   366   #> add_solver "Trans_linear" Order_Tac.linear_tac
   523   #> add_solver "Transitivity" Orders.order_tac
   367   #> add_solver "Trans_partial" Order_Tac.partial_tac
       
   368   (* Adding the transitivity reasoners also as safe solvers showed a slight
   524   (* Adding the transitivity reasoners also as safe solvers showed a slight
   369      speed up, but the reasoning strength appears to be not higher (at least
   525      speed up, but the reasoning strength appears to be not higher (at least
   370      no breaking of additional proofs in the entire HOL distribution, as
   526      no breaking of additional proofs in the entire HOL distribution, as
   371      of 5 March 2004, was observed). *)
   527      of 5 March 2004, was observed). *)
   372 end
   528 end
   378 class dense_linear_order = linorder + 
   534 class dense_linear_order = linorder + 
   379   assumes gt_ex: "\<exists>y. x \<sqsubset> y" 
   535   assumes gt_ex: "\<exists>y. x \<sqsubset> y" 
   380   and lt_ex: "\<exists>y. y \<sqsubset> x"
   536   and lt_ex: "\<exists>y. y \<sqsubset> x"
   381   and dense: "x \<sqsubset> y \<Longrightarrow> (\<exists>z. x \<sqsubset> z \<and> z \<sqsubset> y)"
   537   and dense: "x \<sqsubset> y \<Longrightarrow> (\<exists>z. x \<sqsubset> z \<and> z \<sqsubset> y)"
   382   (*see further theory Dense_Linear_Order*)
   538   (*see further theory Dense_Linear_Order*)
       
   539 
   383 
   540 
   384 lemma interval_empty_iff:
   541 lemma interval_empty_iff:
   385   fixes x y z :: "'a\<Colon>dense_linear_order"
   542   fixes x y z :: "'a\<Colon>dense_linear_order"
   386   shows "{y. x < y \<and> y < z} = {} \<longleftrightarrow> \<not> x < z"
   543   shows "{y. x < y \<and> y < z} = {} \<longleftrightarrow> \<not> x < z"
   387   by (auto dest: dense)
   544   by (auto dest: dense)