src/HOL/Orderings.thy
changeset 73526 a3cc9fa1295d
parent 73411 1f1366966296
child 73794 e75635a0bafd
equal deleted inserted replaced
73517:d3f2038198ae 73526:a3cc9fa1295d
     7 theory Orderings
     7 theory Orderings
     8 imports HOL
     8 imports HOL
     9 keywords "print_orders" :: diag
     9 keywords "print_orders" :: diag
    10 begin
    10 begin
    11 
    11 
    12 ML_file \<open>~~/src/Provers/order.ML\<close>
    12 ML_file \<open>~~/src/Provers/order_procedure.ML\<close>
       
    13 ML_file \<open>~~/src/Provers/order_tac.ML\<close>
    13 
    14 
    14 subsection \<open>Abstract ordering\<close>
    15 subsection \<open>Abstract ordering\<close>
    15 
    16 
    16 locale partial_preordering =
    17 locale partial_preordering =
    17   fixes less_eq :: \<open>'a \<Rightarrow> 'a \<Rightarrow> bool\<close> (infix \<open>\<^bold>\<le>\<close> 50)
    18   fixes less_eq :: \<open>'a \<Rightarrow> 'a \<Rightarrow> bool\<close> (infix \<open>\<^bold>\<le>\<close> 50)
   518 
   519 
   519 
   520 
   520 subsection \<open>Reasoning tools setup\<close>
   521 subsection \<open>Reasoning tools setup\<close>
   521 
   522 
   522 ML \<open>
   523 ML \<open>
   523 signature ORDERS =
   524 structure Logic_Signature : LOGIC_SIGNATURE = struct
   524 sig
   525   val mk_Trueprop = HOLogic.mk_Trueprop
   525   val print_structures: Proof.context -> unit
   526   val dest_Trueprop = HOLogic.dest_Trueprop
   526   val order_tac: Proof.context -> thm list -> int -> tactic
   527   val Trueprop_conv = HOLogic.Trueprop_conv
   527   val add_struct: string * term list -> string -> attribute
   528   val Not = HOLogic.Not
   528   val del_struct: string * term list -> attribute
   529   val conj = HOLogic.conj
   529 end;
   530   val disj = HOLogic.disj
   530 
   531   
   531 structure Orders: ORDERS =
   532   val notI = @{thm notI}
   532 struct
   533   val ccontr = @{thm ccontr}
   533 
   534   val conjI = @{thm conjI}  
   534 (* context data *)
   535   val conjE = @{thm conjE}
   535 
   536   val disjE = @{thm disjE}
   536 fun struct_eq ((s1: string, ts1), (s2, ts2)) =
   537 
   537   s1 = s2 andalso eq_list (op aconv) (ts1, ts2);
   538   val not_not_conv = Conv.rewr_conv @{thm eq_reflection[OF not_not]}
   538 
   539   val de_Morgan_conj_conv = Conv.rewr_conv @{thm eq_reflection[OF de_Morgan_conj]}
   539 structure Data = Generic_Data
   540   val de_Morgan_disj_conv = Conv.rewr_conv @{thm eq_reflection[OF de_Morgan_disj]}
   540 (
   541   val conj_disj_distribL_conv = Conv.rewr_conv @{thm eq_reflection[OF conj_disj_distribL]}
   541   type T = ((string * term list) * Order_Tac.less_arith) list;
   542   val conj_disj_distribR_conv = Conv.rewr_conv @{thm eq_reflection[OF conj_disj_distribR]}
   542     (* Order structures:
   543 end
   543        identifier of the structure, list of operations and record of theorems
   544 
   544        needed to set up the transitivity reasoner,
   545 structure HOL_Base_Order_Tac = Base_Order_Tac(
   545        identifier and operations identify the structure uniquely. *)
   546   structure Logic_Sig = Logic_Signature;
   546   val empty = [];
   547   (* Exclude types with specialised solvers. *)
   547   val extend = I;
   548   val excluded_types = [HOLogic.natT, HOLogic.intT, HOLogic.realT]
   548   fun merge data = AList.join struct_eq (K fst) data;
   549 )
   549 );
   550 
   550 
   551 structure HOL_Order_Tac = Order_Tac(structure Base_Tac = HOL_Base_Order_Tac)
   551 fun print_structures ctxt =
   552 
       
   553 fun print_orders ctxt0 =
   552   let
   554   let
   553     val structs = Data.get (Context.Proof ctxt);
   555     val ctxt = Config.put show_sorts true ctxt0
       
   556     val orders = HOL_Order_Tac.Data.get (Context.Proof ctxt)
   554     fun pretty_term t = Pretty.block
   557     fun pretty_term t = Pretty.block
   555       [Pretty.quote (Syntax.pretty_term ctxt t), Pretty.brk 1,
   558       [Pretty.quote (Syntax.pretty_term ctxt t), Pretty.brk 1,
   556         Pretty.str "::", Pretty.brk 1,
   559         Pretty.str "::", Pretty.brk 1,
   557         Pretty.quote (Syntax.pretty_typ ctxt (type_of t))];
   560         Pretty.quote (Syntax.pretty_typ ctxt (type_of t)), Pretty.brk 1]
   558     fun pretty_struct ((s, ts), _) = Pretty.block
   561     fun pretty_order ({kind = kind, ops = ops, ...}, _) =
   559       [Pretty.str s, Pretty.str ":", Pretty.brk 1,
   562       Pretty.block ([Pretty.str (@{make_string} kind), Pretty.str ":", Pretty.brk 1]
   560        Pretty.enclose "(" ")" (Pretty.breaks (map pretty_term ts))];
   563                     @ map pretty_term ops)
   561   in
   564   in
   562     Pretty.writeln (Pretty.big_list "order structures:" (map pretty_struct structs))
   565     Pretty.writeln (Pretty.big_list "order structures:" (map pretty_order orders))
   563   end;
   566   end
   564 
   567 
   565 val _ =
   568 val _ =
   566   Outer_Syntax.command \<^command_keyword>\<open>print_orders\<close>
   569   Outer_Syntax.command \<^command_keyword>\<open>print_orders\<close>
   567     "print order structures available to transitivity reasoner"
   570     "print order structures available to transitivity reasoner"
   568     (Scan.succeed (Toplevel.keep (print_structures o Toplevel.context_of)));
   571     (Scan.succeed (Toplevel.keep (print_orders o Toplevel.context_of)))
   569 
   572 
   570 
       
   571 (* tactics *)
       
   572 
       
   573 fun struct_tac ((s, ops), thms) ctxt facts =
       
   574   let
       
   575     val [eq, le, less] = ops;
       
   576     fun decomp thy (\<^const>\<open>Trueprop\<close> $ t) =
       
   577           let
       
   578             fun excluded t =
       
   579               (* exclude numeric types: linear arithmetic subsumes transitivity *)
       
   580               let val T = type_of t
       
   581               in
       
   582                 T = HOLogic.natT orelse T = HOLogic.intT orelse T = HOLogic.realT
       
   583               end;
       
   584             fun rel (bin_op $ t1 $ t2) =
       
   585                   if excluded t1 then NONE
       
   586                   else if Pattern.matches thy (eq, bin_op) then SOME (t1, "=", t2)
       
   587                   else if Pattern.matches thy (le, bin_op) then SOME (t1, "<=", t2)
       
   588                   else if Pattern.matches thy (less, bin_op) then SOME (t1, "<", t2)
       
   589                   else NONE
       
   590               | rel _ = NONE;
       
   591             fun dec (Const (\<^const_name>\<open>Not\<close>, _) $ t) =
       
   592                   (case rel t of NONE =>
       
   593                     NONE
       
   594                   | SOME (t1, rel, t2) => SOME (t1, "~" ^ rel, t2))
       
   595               | dec x = rel x;
       
   596           in dec t end
       
   597       | decomp _ _ = NONE;
       
   598   in
       
   599     (case s of
       
   600       "order" => Order_Tac.partial_tac decomp thms ctxt facts
       
   601     | "linorder" => Order_Tac.linear_tac decomp thms ctxt facts
       
   602     | _ => error ("Unknown order kind " ^ quote s ^ " encountered in transitivity reasoner"))
       
   603   end
       
   604 
       
   605 fun order_tac ctxt facts =
       
   606   FIRST' (map (fn s => CHANGED o struct_tac s ctxt facts) (Data.get (Context.Proof ctxt)));
       
   607 
       
   608 
       
   609 (* attributes *)
       
   610 
       
   611 fun add_struct s tag =
       
   612   Thm.declaration_attribute
       
   613     (fn thm => Data.map (AList.map_default struct_eq (s, Order_Tac.empty TrueI) (Order_Tac.update tag thm)));
       
   614 fun del_struct s =
       
   615   Thm.declaration_attribute
       
   616     (fn _ => Data.map (AList.delete struct_eq s));
       
   617 
       
   618 end;
       
   619 \<close>
   573 \<close>
   620 
   574 
   621 attribute_setup order = \<open>
       
   622   Scan.lift ((Args.add -- Args.name >> (fn (_, s) => SOME s) || Args.del >> K NONE) --|
       
   623     Args.colon (* FIXME || Scan.succeed true *) ) -- Scan.lift Args.name --
       
   624     Scan.repeat Args.term
       
   625     >> (fn ((SOME tag, n), ts) => Orders.add_struct (n, ts) tag
       
   626          | ((NONE, n), ts) => Orders.del_struct (n, ts))
       
   627 \<close> "theorems controlling transitivity reasoner"
       
   628 
       
   629 method_setup order = \<open>
   575 method_setup order = \<open>
   630   Scan.succeed (fn ctxt => SIMPLE_METHOD' (Orders.order_tac ctxt []))
   576   Scan.succeed (fn ctxt => SIMPLE_METHOD' (HOL_Order_Tac.tac [] ctxt))
   631 \<close> "transitivity reasoner"
   577 \<close> "transitivity reasoner"
   632 
   578 
   633 
   579 
   634 text \<open>Declarations to set up transitivity reasoner of partial and linear orders.\<close>
   580 text \<open>Declarations to set up transitivity reasoner of partial and linear orders.\<close>
   635 
   581 
   636 context order
   582 context order
   637 begin
   583 begin
   638 
   584 
   639 (* The type constraint on @{term (=}) below is necessary since the operation
   585 lemma nless_le: "(\<not> a < b) \<longleftrightarrow> (\<not> a \<le> b) \<or> a = b"
   640    is not a parameter of the locale. *)
   586   using local.dual_order.order_iff_strict by blast
   641 
   587 
   642 declare less_irrefl [THEN notE, order add less_reflE: order "(=) :: 'a \<Rightarrow> 'a \<Rightarrow> bool" "(<=)" "(<)"]
   588 local_setup \<open>
   643 
   589   HOL_Order_Tac.declare_order {
   644 declare order_refl  [order add le_refl: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
   590     ops = {eq = @{term \<open>(=) :: 'a \<Rightarrow> 'a \<Rightarrow> bool\<close>}, le = @{term \<open>(\<le>)\<close>}, lt = @{term \<open>(<)\<close>}},
   645 
   591     thms = {trans = @{thm order_trans}, refl = @{thm order_refl}, eqD1 = @{thm eq_refl},
   646 declare less_imp_le [order add less_imp_le: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
   592             eqD2 = @{thm eq_refl[OF sym]}, antisym = @{thm order_antisym}, contr = @{thm notE}},
   647 
   593     conv_thms = {less_le = @{thm eq_reflection[OF less_le]},
   648 declare order.antisym [order add eqI: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
   594                  nless_le = @{thm eq_reflection[OF nless_le]}}
   649 
   595   }
   650 declare eq_refl [order add eqD1: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
   596 \<close>
   651 
       
   652 declare sym [THEN eq_refl, order add eqD2: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   653 
       
   654 declare less_trans [order add less_trans: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   655 
       
   656 declare less_le_trans [order add less_le_trans: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   657 
       
   658 declare le_less_trans [order add le_less_trans: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   659 
       
   660 declare order_trans [order add le_trans: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   661 
       
   662 declare le_neq_trans [order add le_neq_trans: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   663 
       
   664 declare neq_le_trans [order add neq_le_trans: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   665 
       
   666 declare less_imp_neq [order add less_imp_neq: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   667 
       
   668 declare eq_neq_eq_imp_neq [order add eq_neq_eq_imp_neq: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   669 
       
   670 declare not_sym [order add not_sym: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   671 
   597 
   672 end
   598 end
   673 
   599 
   674 context linorder
   600 context linorder
   675 begin
   601 begin
   676 
   602 
   677 declare [[order del: order "(=) :: 'a => 'a => bool" "(<=)" "(<)"]]
   603 lemma nle_le: "(\<not> a \<le> b) \<longleftrightarrow> b \<le> a \<and> b \<noteq> a"
   678 
   604   using not_le less_le by simp
   679 declare less_irrefl [THEN notE, order add less_reflE: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
   605 
   680 
   606 local_setup \<open>
   681 declare order_refl [order add le_refl: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
   607   HOL_Order_Tac.declare_linorder {
   682 
   608     ops = {eq = @{term \<open>(=) :: 'a \<Rightarrow> 'a \<Rightarrow> bool\<close>}, le = @{term \<open>(\<le>)\<close>}, lt = @{term \<open>(<)\<close>}},
   683 declare less_imp_le [order add less_imp_le: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
   609     thms = {trans = @{thm order_trans}, refl = @{thm order_refl}, eqD1 = @{thm eq_refl},
   684 
   610             eqD2 = @{thm eq_refl[OF sym]}, antisym = @{thm order_antisym}, contr = @{thm notE}},
   685 declare not_less [THEN iffD2, order add not_lessI: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
   611     conv_thms = {less_le = @{thm eq_reflection[OF less_le]},
   686 
   612                  nless_le = @{thm eq_reflection[OF not_less]},
   687 declare not_le [THEN iffD2, order add not_leI: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
   613                  nle_le = @{thm eq_reflection[OF nle_le]}}
   688 
   614   }
   689 declare not_less [THEN iffD1, order add not_lessD: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
   615 \<close>
   690 
       
   691 declare not_le [THEN iffD1, order add not_leD: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   692 
       
   693 declare order.antisym [order add eqI: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   694 
       
   695 declare eq_refl [order add eqD1: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   696 
       
   697 declare sym [THEN eq_refl, order add eqD2: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   698 
       
   699 declare less_trans [order add less_trans: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   700 
       
   701 declare less_le_trans [order add less_le_trans: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   702 
       
   703 declare le_less_trans [order add le_less_trans: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   704 
       
   705 declare order_trans [order add le_trans: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   706 
       
   707 declare le_neq_trans [order add le_neq_trans: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   708 
       
   709 declare neq_le_trans [order add neq_le_trans: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   710 
       
   711 declare less_imp_neq [order add less_imp_neq: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   712 
       
   713 declare eq_neq_eq_imp_neq [order add eq_neq_eq_imp_neq: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   714 
       
   715 declare not_sym [order add not_sym: linorder "(=) :: 'a => 'a => bool" "(<=)" "(<)"]
       
   716 
   616 
   717 end
   617 end
   718 
   618 
   719 setup \<open>
   619 setup \<open>
   720   map_theory_simpset (fn ctxt0 => ctxt0 addSolver
   620   map_theory_simpset (fn ctxt0 => ctxt0 addSolver
   721     mk_solver "Transitivity" (fn ctxt => Orders.order_tac ctxt (Simplifier.prems_of ctxt)))
   621     mk_solver "Transitivity" (fn ctxt => HOL_Order_Tac.tac (Simplifier.prems_of ctxt) ctxt))
   722   (*Adding the transitivity reasoners also as safe solvers showed a slight
       
   723     speed up, but the reasoning strength appears to be not higher (at least
       
   724     no breaking of additional proofs in the entire HOL distribution, as
       
   725     of 5 March 2004, was observed).*)
       
   726 \<close>
   622 \<close>
   727 
   623 
   728 ML \<open>
   624 ML \<open>
   729 local
   625 local
   730   fun prp t thm = Thm.prop_of thm = t;  (* FIXME proper aconv!? *)
   626   fun prp t thm = Thm.prop_of thm = t;  (* FIXME proper aconv!? *)
   763               (case find_first (prp t) prems of
   659               (case find_first (prp t) prems of
   764                 NONE => NONE
   660                 NONE => NONE
   765               | SOME thm => SOME (mk_meta_eq(thm RS @{thm linorder_class.antisym_conv3})))
   661               | SOME thm => SOME (mk_meta_eq(thm RS @{thm linorder_class.antisym_conv3})))
   766             end
   662             end
   767         | SOME thm => SOME (mk_meta_eq (thm RS @{thm antisym_conv2})))
   663         | SOME thm => SOME (mk_meta_eq (thm RS @{thm antisym_conv2})))
   768       end handle THM _ => NONE)
   664       end handle THM _ => NONE)                           
   769   | _ => NONE);
   665   | _ => NONE);
   770 
   666 
   771 end;
   667 end;
   772 \<close>
   668 \<close>
   773 
   669 
  1224     case True then show ?thesis by simp
  1120     case True then show ?thesis by simp
  1225   next
  1121   next
  1226     case False with \<open>x \<le> y\<close> have "x < y" by simp
  1122     case False with \<open>x \<le> y\<close> have "x < y" by simp
  1227     with assms strict_monoD have "f x < f y" by auto
  1123     with assms strict_monoD have "f x < f y" by auto
  1228     then show ?thesis by simp
  1124     then show ?thesis by simp
       
  1125 
  1229   qed
  1126   qed
  1230 qed
  1127 qed
  1231 
  1128 
  1232 end
  1129 end
  1233 
  1130