src/Provers/order_tac.ML
changeset 82026 57b4e44f5bc4
parent 78095 bc42c074e58f
child 82027 9c33627cea18
equal deleted inserted replaced
82017:9a8d408492a7 82026:57b4e44f5bc4
    42   val de_Morgan_disj_conv : conv (* \<not> (P \<or> Q) \<equiv> \<not> P \<and> \<not> Q *)
    42   val de_Morgan_disj_conv : conv (* \<not> (P \<or> Q) \<equiv> \<not> P \<and> \<not> Q *)
    43   val conj_disj_distribL_conv : conv (* P \<and> (Q \<or> R) \<equiv> (P \<and> Q) \<or> (P \<and> R) *)
    43   val conj_disj_distribL_conv : conv (* P \<and> (Q \<or> R) \<equiv> (P \<and> Q) \<or> (P \<and> R) *)
    44   val conj_disj_distribR_conv : conv (* (Q \<or> R) \<and> P \<equiv> (Q \<and> P) \<or> (R \<and> P) *)
    44   val conj_disj_distribR_conv : conv (* (Q \<or> R) \<and> P \<equiv> (Q \<and> P) \<or> (R \<and> P) *)
    45 end
    45 end
    46 
    46 
    47 (* Control tracing output of the solver. *)
    47 signature BASE_ORDER_TAC_BASE =
    48 val order_trace_cfg = Attrib.setup_config_bool @{binding "order_trace"} (K false)
    48 sig
    49 (* In partial orders, literals of the form \<not> x < y will force the order solver to perform case
    49   
    50    distinctions, which leads to an exponential blowup of the runtime. The split limit controls
    50   val order_trace_cfg : bool Config.T
    51    the number of literals of this form that are passed to the solver. 
    51   val order_split_limit_cfg : int Config.T
    52  *)
    52   
    53 val order_split_limit_cfg = Attrib.setup_config_int @{binding "order_split_limit"} (K 8)
    53   datatype order_kind = Order | Linorder
    54 
    54   
    55 datatype order_kind = Order | Linorder
    55   type order_literal = (bool * Order_Procedure.order_atom)
    56 
    56   
    57 type order_literal = (bool * Order_Procedure.order_atom)
    57   type order_ops = { eq : term, le : term, lt : term }
    58 
    58   
    59 type order_context = {
    59   val map_order_ops : (term -> term) -> order_ops -> order_ops
    60     kind : order_kind,
    60   
    61     ops : term list, thms : (string * thm) list, conv_thms : (string * thm) list
    61   type order_context = {
    62   }
    62       kind : order_kind,
       
    63       ops : order_ops,
       
    64       thms : (string * thm) list, conv_thms : (string * thm) list
       
    65     }
       
    66 
       
    67 end
       
    68 
       
    69 structure Base_Order_Tac_Base : BASE_ORDER_TAC_BASE =
       
    70 struct
       
    71   
       
    72   (* Control tracing output of the solver. *)
       
    73   val order_trace_cfg = Attrib.setup_config_bool @{binding "order_trace"} (K false)
       
    74   (* In partial orders, literals of the form \<not> x < y will force the order solver to perform case
       
    75      distinctions, which leads to an exponential blowup of the runtime. The split limit controls
       
    76      the number of literals of this form that are passed to the solver. 
       
    77    *)
       
    78   val order_split_limit_cfg = Attrib.setup_config_int @{binding "order_split_limit"} (K 8)
       
    79   
       
    80   datatype order_kind = Order | Linorder
       
    81   
       
    82   type order_literal = (bool * Order_Procedure.order_atom)
       
    83   
       
    84   type order_ops = { eq : term, le : term, lt : term }
       
    85   
       
    86   fun map_order_ops f {eq, le, lt} = {eq = f eq, le = f le, lt = f lt}
       
    87   
       
    88   type order_context = {
       
    89       kind : order_kind,
       
    90       ops : order_ops,
       
    91       thms : (string * thm) list, conv_thms : (string * thm) list
       
    92     }
       
    93 
       
    94 end
    63 
    95 
    64 signature BASE_ORDER_TAC =
    96 signature BASE_ORDER_TAC =
    65 sig
    97 sig
       
    98   include BASE_ORDER_TAC_BASE
       
    99    
       
   100   type insert_prems_hook =
       
   101     order_kind -> order_ops -> Proof.context -> (thm * (bool * term * (term * term))) list
       
   102       -> thm list
       
   103 
       
   104   val declare_insert_prems_hook :
       
   105     (binding * insert_prems_hook) -> local_theory -> local_theory
       
   106 
       
   107   val insert_prems_hook_names : Proof.context -> binding list
    66 
   108 
    67   val tac :
   109   val tac :
    68         (order_literal Order_Procedure.fm -> Order_Procedure.prf_trm option)
   110     (order_literal Order_Procedure.fm -> Order_Procedure.prf_trm option)
    69         -> order_context -> thm list
   111       -> order_context -> thm list
    70         -> Proof.context -> int -> tactic
   112       -> Proof.context -> int -> tactic
    71 end
   113 end
    72 
   114 
    73 functor Base_Order_Tac(
   115 functor Base_Order_Tac(
    74   structure Logic_Sig : LOGIC_SIGNATURE; val excluded_types : typ list) : BASE_ORDER_TAC =
   116   structure Logic_Sig : LOGIC_SIGNATURE; val excluded_types : typ list) : BASE_ORDER_TAC =
    75 struct
   117 struct
       
   118   open Base_Order_Tac_Base
    76   open Order_Procedure
   119   open Order_Procedure
    77 
   120 
    78   fun expect _ (SOME x) = x
   121   fun expect _ (SOME x) = x
    79     | expect f NONE = f ()
   122     | expect f NONE = f ()
    80 
   123 
   196     end
   239     end
   197 
   240 
   198   fun strip_Not (nt $ t) = if nt = Logic_Sig.Not then t else nt $ t
   241   fun strip_Not (nt $ t) = if nt = Logic_Sig.Not then t else nt $ t
   199     | strip_Not t = t
   242     | strip_Not t = t
   200 
   243 
   201   fun limit_not_less [_, _, lt] ctxt decomp_prems =
   244   fun limit_not_less lt ctxt decomp_prems =
   202     let
   245     let
   203       val thy = Proof_Context.theory_of ctxt
       
   204       val trace = Config.get ctxt order_trace_cfg
   246       val trace = Config.get ctxt order_trace_cfg
   205       val limit = Config.get ctxt order_split_limit_cfg
   247       val limit = Config.get ctxt order_split_limit_cfg
   206 
   248 
   207       fun is_not_less_term t =
   249       fun is_not_less_term t =
   208         case try (strip_Not o Logic_Sig.dest_Trueprop) t of
   250         case try (strip_Not o Logic_Sig.dest_Trueprop) t of
   209           SOME (binop $ _ $ _) => Pattern.matches thy (lt, binop)
   251           SOME (binop $ _ $ _) => binop = lt
   210         | NONE => false
   252         | _ => false
   211 
   253 
   212       val not_less_prems = filter (is_not_less_term o Thm.prop_of o fst) decomp_prems
   254       val not_less_prems = filter (is_not_less_term o Thm.prop_of o fst) decomp_prems
   213       val _ = if trace andalso length not_less_prems > limit
   255       val _ = if trace andalso length not_less_prems > limit
   214                 then tracing "order split limit exceeded"
   256                 then tracing "order split limit exceeded"
   215                 else ()
   257                 else ()
   216      in
   258     in
   217       filter_out (is_not_less_term o Thm.prop_of o fst) decomp_prems @
   259       filter_out (is_not_less_term o Thm.prop_of o fst) decomp_prems @
   218       take limit not_less_prems
   260       take limit not_less_prems
   219      end
   261     end
   220 
   262 
   221   fun decomp [eq, le, lt] ctxt t =
   263   fun decomp {eq, le, lt} ctxt t =
   222     let
   264     let
   223       fun is_excluded t = exists (fn ty => ty = fastype_of t) excluded_types
       
   224 
       
   225       fun decomp'' (binop $ t1 $ t2) =
   265       fun decomp'' (binop $ t1 $ t2) =
   226             let
   266             let
       
   267               fun is_excluded t = exists (fn ty => ty = fastype_of t) excluded_types
       
   268 
   227               open Order_Procedure
   269               open Order_Procedure
   228               val thy = Proof_Context.theory_of ctxt
   270               val thy = Proof_Context.theory_of ctxt
   229               fun try_match pat = try (Pattern.match thy (pat, binop)) (Vartab.empty, Vartab.empty)
   271               fun try_match pat = try (Pattern.match thy (pat, binop)) (Vartab.empty, Vartab.empty)
   230             in if is_excluded t1 then NONE
   272             in if is_excluded t1 then NONE
   231                else case (try_match eq, try_match le, try_match lt) of
   273                else case (try_match eq, try_match le, try_match lt) of
   232                       (SOME env, _, _) => SOME (true, EQ, (t1, t2), env)
   274                       (SOME env, _, _) => SOME ((true, EQ, (t1, t2)), env)
   233                     | (_, SOME env, _) => SOME (true, LEQ, (t1, t2), env)
   275                     | (_, SOME env, _) => SOME ((true, LEQ, (t1, t2)), env)
   234                     | (_, _, SOME env) => SOME (true, LESS, (t1, t2), env)
   276                     | (_, _, SOME env) => SOME ((true, LESS, (t1, t2)), env)
   235                     | _ => NONE
   277                     | _ => NONE
   236             end
   278             end
   237         | decomp'' _ = NONE
   279         | decomp'' _ = NONE
   238 
   280 
   239         fun decomp' (nt $ t) =
   281         fun decomp' (nt $ t) =
   240               if nt = Logic_Sig.Not
   282               if nt = Logic_Sig.Not
   241                 then decomp'' t |> Option.map (fn (b, c, p, e) => (not b, c, p, e))
   283                 then decomp'' t |> Option.map (fn ((b, c, p), e) => ((not b, c, p), e))
   242                 else decomp'' (nt $ t)
   284                 else decomp'' (nt $ t)
   243           | decomp' t = decomp'' t
   285           | decomp' t = decomp'' t
   244 
       
   245     in
   286     in
   246       try Logic_Sig.dest_Trueprop t |> Option.mapPartial decomp'
   287       try Logic_Sig.dest_Trueprop t |> Option.mapPartial decomp'
   247     end
   288     end
   248 
   289 
   249   fun maximal_envs envs =
   290   fun maximal_envs envs =
   271       val maximals =
   312       val maximals =
   272         filter (fn comp => length comp = length (Int_Graph.all_succs graph comp)) strong_conns
   313         filter (fn comp => length comp = length (Int_Graph.all_succs graph comp)) strong_conns
   273     in
   314     in
   274       map (Int_Graph.all_preds graph) maximals
   315       map (Int_Graph.all_preds graph) maximals
   275     end
   316     end
       
   317 
       
   318   fun partition_prems octxt ctxt prems =
       
   319     let
       
   320       fun these' _ [] = []
       
   321         | these' f (x :: xs) = case f x of NONE => these' f xs | SOME y => (x, y) :: these' f xs
       
   322       
       
   323       val (decomp_prems, envs) =
       
   324         these' (decomp (#ops octxt) ctxt o Thm.prop_of) prems
       
   325         |> map_split (fn (thm, (l, env)) => ((thm, l), env))
       
   326           
       
   327       val env_groups = maximal_envs envs
       
   328     in
       
   329       map (fn is => (map (nth decomp_prems) is, nth envs (hd is))) env_groups
       
   330     end
       
   331 
       
   332   local
       
   333     fun pretty_term_list ctxt =
       
   334       Pretty.list "" "" o map (Syntax.pretty_term (Config.put show_types true ctxt))
       
   335     fun pretty_type_of ctxt t = Pretty.block
       
   336       [ Pretty.str "::", Pretty.brk 1
       
   337       , Pretty.quote (Syntax.pretty_typ ctxt (Term.fastype_of t)) ]
       
   338   in
       
   339     fun pretty_order_kind (okind : order_kind) = Pretty.str (@{make_string} okind)
       
   340     fun pretty_order_ops ctxt ({eq, le, lt} : order_ops) =
       
   341       Pretty.block [pretty_term_list ctxt [eq, le, lt], Pretty.brk 1, pretty_type_of ctxt le]
       
   342   end
       
   343 
       
   344   type insert_prems_hook =
       
   345     order_kind -> order_ops -> Proof.context -> (thm * (bool * term * (term * term))) list
       
   346       -> thm list
       
   347 
       
   348   structure Insert_Prems_Hook_Data = Generic_Data(
       
   349     type T = (binding * insert_prems_hook) list
       
   350     val empty = []
       
   351     val merge = Library.merge ((op =) o apply2 fst)
       
   352   )
       
   353 
       
   354   fun declare_insert_prems_hook (binding, hook) lthy =
       
   355     lthy |> Local_Theory.declaration {syntax = false, pervasive = false, pos = \<^here>}
       
   356       (fn phi => fn context =>
       
   357         let
       
   358           val binding = Morphism.binding phi binding
       
   359         in
       
   360           context
       
   361           |> Insert_Prems_Hook_Data.map (Library.insert ((op =) o apply2 fst) (binding, hook))
       
   362         end)
       
   363 
       
   364   val insert_prems_hook_names = Context.Proof #> Insert_Prems_Hook_Data.get #> map fst
       
   365 
       
   366   fun eval_insert_prems_hook kind order_ops ctxt decomp_prems (hookN, hook : insert_prems_hook) = 
       
   367     let
       
   368       fun dereify_order_op' (EQ _) = #eq order_ops
       
   369         | dereify_order_op' (LEQ _) = #le order_ops
       
   370         | dereify_order_op' (LESS _) = #lt order_ops
       
   371       fun dereify_order_op oop = (~1, ~1) |> apply2 Int_of_integer |> oop |> dereify_order_op'
       
   372       val decomp_prems =
       
   373         decomp_prems
       
   374         |> map (apsnd (fn (b, oop, (t1, t2)) => (b, dereify_order_op oop, (t1, t2))))
       
   375       fun unzip (acc1, acc2) [] = (rev acc1, rev acc2)
       
   376         | unzip (acc1, acc2) ((thm, NONE) :: ps) = unzip (acc1, thm :: acc2) ps
       
   377         | unzip (acc1, acc2) ((thm, SOME dp) :: ps) = unzip ((thm, dp) :: acc1, acc2) ps
       
   378       val (decomp_extra_prems, invalid_extra_prems) =
       
   379         hook kind order_ops ctxt decomp_prems
       
   380         |> map (swap o ` (decomp order_ops ctxt o Thm.prop_of))
       
   381         |> unzip ([], [])
       
   382 
       
   383       val pretty_thm_list = Pretty.list "" "" o map (Thm.pretty_thm ctxt)
       
   384       fun pretty_trace () = 
       
   385         [ ("order kind:", pretty_order_kind kind)
       
   386         , ("order operators:", pretty_order_ops ctxt order_ops)
       
   387         , ("inserted premises:", pretty_thm_list (map fst decomp_extra_prems))
       
   388         , ("invalid premises:", pretty_thm_list invalid_extra_prems)
       
   389         ]
       
   390         |> map (fn (t, pp) => Pretty.block [Pretty.str t, Pretty.brk 1, pp])
       
   391         |> Pretty.big_list ("insert premises hook " ^ Pretty.string_of (Binding.pretty hookN) 
       
   392             ^ " called with the parameters")
       
   393       val trace = Config.get ctxt order_trace_cfg
       
   394       val _ = if trace then tracing (Pretty.string_of (pretty_trace ())) else ()
       
   395     in
       
   396       map (apsnd fst) decomp_extra_prems
       
   397     end
   276       
   398       
   277   fun order_tac raw_order_proc octxt simp_prems =
   399   fun order_tac raw_order_proc octxt simp_prems =
   278     Subgoal.FOCUS (fn {prems=prems, context=ctxt, ...} =>
   400     Subgoal.FOCUS (fn {prems=prems, context=ctxt, ...} =>
   279       let
   401       let
   280         val trace = Config.get ctxt order_trace_cfg
   402         val trace = Config.get ctxt order_trace_cfg
   281 
       
   282         fun these' _ [] = []
       
   283           | these' f (x :: xs) = case f x of NONE => these' f xs | SOME y => (x, y) :: these' f xs
       
   284 
       
   285         val prems = simp_prems @ prems
       
   286                     |> filter (fn p => null (Term.add_vars (Thm.prop_of p) []))
       
   287                     |> map (Conv.fconv_rule Thm.eta_conversion)
       
   288         val decomp_prems = these' (decomp (#ops octxt) ctxt o Thm.prop_of) prems
       
   289 
       
   290         fun env_of (_, (_, _, _, env)) = env
       
   291         val env_groups = maximal_envs (map env_of decomp_prems)
       
   292         
   403         
   293         fun order_tac' (_, []) = no_tac
   404         fun order_tac' ([], _) = no_tac
   294           | order_tac' (env, decomp_prems) =
   405           | order_tac' (decomp_prems, env) =
   295             let
   406             let
   296               val [eq, le, lt] = #ops octxt |> map (Envir.eta_contract o Envir.subst_term env)
   407               val (order_ops as {eq, le, lt}) =
   297 
   408                 #ops octxt |> map_order_ops (Envir.eta_contract o Envir.subst_term env)
   298               val decomp_prems = case #kind octxt of
   409                 
   299                                    Order => limit_not_less (#ops octxt) ctxt decomp_prems
   410               val insert_prems_hooks = Insert_Prems_Hook_Data.get (Context.Proof ctxt)
   300                                  | _ => decomp_prems
   411               val inserted_decomp_prems =
       
   412                 insert_prems_hooks
       
   413                 |> maps (eval_insert_prems_hook (#kind octxt) order_ops ctxt decomp_prems)
       
   414 
       
   415               val decomp_prems = decomp_prems @ inserted_decomp_prems
       
   416               val decomp_prems =
       
   417                 case #kind octxt of
       
   418                   Order => limit_not_less lt ctxt decomp_prems
       
   419                 | _ => decomp_prems
   301       
   420       
   302               fun reify_prem (_, (b, ctor, (x, y), _)) (ps, reifytab) =
   421               fun reify_prem (_, (b, ctor, (x, y))) (ps, reifytab) =
   303                 (Reifytab.get_var x ##>> Reifytab.get_var y) reifytab
   422                 (Reifytab.get_var x ##>> Reifytab.get_var y) reifytab
   304                 |>> (fn vp => (b, ctor (apply2 Int_of_integer vp)) :: ps)
   423                 |>> (fn vp => (b, ctor (apply2 Int_of_integer vp)) :: ps)
   305               val (reified_prems, reifytab) = fold_rev reify_prem decomp_prems ([], Reifytab.empty)
   424               val (reified_prems, reifytab) = fold_rev reify_prem decomp_prems ([], Reifytab.empty)
   306 
   425 
   307               val reified_prems_conj = foldl1 (fn (x, a) => And (x, a)) (map Atom reified_prems)
   426               val reified_prems_conj = foldl1 (fn (x, a) => And (x, a)) (map Atom reified_prems)
   310                                    |> Conv.fconv_rule Thm.eta_conversion 
   429                                    |> Conv.fconv_rule Thm.eta_conversion 
   311               val prems_conj = prems_conj_thm |> Thm.prop_of
   430               val prems_conj = prems_conj_thm |> Thm.prop_of
   312               
   431               
   313               val proof = raw_order_proc reified_prems_conj
   432               val proof = raw_order_proc reified_prems_conj
   314 
   433 
   315               val pretty_term_list =
       
   316                 Pretty.list "" "" o map (Syntax.pretty_term (Config.put show_types true ctxt))
       
   317               val pretty_thm_list = Pretty.list "" "" o map (Thm.pretty_thm ctxt)
   434               val pretty_thm_list = Pretty.list "" "" o map (Thm.pretty_thm ctxt)
   318               fun pretty_type_of t = Pretty.block [ Pretty.str "::", Pretty.brk 1,
       
   319                     Pretty.quote (Syntax.pretty_typ ctxt (Term.fastype_of t)) ]
       
   320               fun pretty_trace () = 
   435               fun pretty_trace () = 
   321                 [ ("order kind:", Pretty.str (@{make_string} (#kind octxt)))
   436                 [ ("order kind:", pretty_order_kind (#kind octxt))
   322                 , ("order operators:", Pretty.block [ pretty_term_list [eq, le, lt], Pretty.brk 1
   437                 , ("order operators:", pretty_order_ops ctxt order_ops)
   323                                                      , pretty_type_of le ])
       
   324                 , ("premises:", pretty_thm_list prems)
   438                 , ("premises:", pretty_thm_list prems)
   325                 , ("selected premises:", pretty_thm_list (map fst decomp_prems))
   439                 , ("selected premises:", pretty_thm_list (map fst decomp_prems))
   326                 , ("reified premises:", Pretty.str (@{make_string} reified_prems))
   440                 , ("reified premises:", Pretty.str (@{make_string} reified_prems))
   327                 , ("contradiction:", Pretty.str (@{make_string} (Option.isSome proof)))
   441                 , ("contradiction:", Pretty.str (@{make_string} (Option.isSome proof)))
   328                 ] |> map (fn (t, pp) => Pretty.block [Pretty.str t, Pretty.brk 1, pp])
   442                 ] 
   329                   |> Pretty.big_list "order solver called with the parameters"
   443                 |> map (fn (t, pp) => Pretty.block [Pretty.str t, Pretty.brk 1, pp])
       
   444                 |> Pretty.big_list "order solver called with the parameters"
   330               val _ = if trace then tracing (Pretty.string_of (pretty_trace ())) else ()
   445               val _ = if trace then tracing (Pretty.string_of (pretty_trace ())) else ()
   331 
   446 
   332               val assmtab = Termtab.make [(prems_conj, prems_conj_thm)]
   447               val assmtab = Termtab.make [(prems_conj, prems_conj_thm)]
   333               val replay = replay_order_prf_trm (eq, le, lt) octxt ctxt reifytab assmtab
   448               val replay = replay_order_prf_trm (eq, le, lt) octxt ctxt reifytab assmtab
   334             in
   449             in
   335               case proof of
   450               case proof of
   336                 NONE => no_tac
   451                 NONE => no_tac
   337               | SOME p => SOLVED' (resolve_tac ctxt [replay p]) 1
   452               | SOME p => SOLVED' (resolve_tac ctxt [replay p]) 1
   338             end
   453             end
       
   454 
       
   455         val prems = simp_prems @ prems
       
   456                     |> filter (fn p => null (Term.add_vars (Thm.prop_of p) []))
       
   457                     |> map (Conv.fconv_rule Thm.eta_conversion)
   339      in
   458      in
   340        map (fn is => ` (env_of o hd) (map (nth decomp_prems) is) |> order_tac') env_groups
   459       partition_prems octxt ctxt prems |> map order_tac' |> FIRST
   341        |> FIRST
       
   342      end)
   460      end)
   343 
   461 
   344   val ad_absurdum_tac = SUBGOAL (fn (A, i) =>
   462   val ad_absurdum_tac = SUBGOAL (fn (A, i) =>
   345     case try (Logic_Sig.dest_Trueprop o Logic.strip_assums_concl) A of
   463     case try (Logic_Sig.dest_Trueprop o Logic.strip_assums_concl) A of
   346       SOME (nt $ _) =>
   464       SOME (nt $ _) =>
   353     ad_absurdum_tac THEN' order_tac raw_order_proc octxt simp_prems ctxt
   471     ad_absurdum_tac THEN' order_tac raw_order_proc octxt simp_prems ctxt
   354   
   472   
   355 end
   473 end
   356 
   474 
   357 functor Order_Tac(structure Base_Tac : BASE_ORDER_TAC) = struct
   475 functor Order_Tac(structure Base_Tac : BASE_ORDER_TAC) = struct
       
   476   open Base_Tac
   358 
   477 
   359   fun order_context_eq ({kind = kind1, ops = ops1, ...}, {kind = kind2, ops = ops2, ...}) =
   478   fun order_context_eq ({kind = kind1, ops = ops1, ...}, {kind = kind2, ops = ops2, ...}) =
   360     kind1 = kind2 andalso eq_list (op aconv) (ops1, ops2)
   479     let
   361 
   480       fun ops_list ops = [#eq ops, #le ops, #lt ops]
   362   fun order_data_eq (x, y) = order_context_eq (fst x, fst y)
   481     in
       
   482       kind1 = kind2 andalso eq_list (op aconv) (apply2 ops_list (ops1, ops2))
       
   483     end
       
   484   val order_data_eq = order_context_eq o apply2 fst
   363   
   485   
   364   structure Data = Generic_Data(
   486   structure Data = Generic_Data(
   365     type T = (order_context * (order_context -> thm list -> Proof.context -> int -> tactic)) list
   487     type T = (order_context * (order_context -> thm list -> Proof.context -> int -> tactic)) list
   366     val empty = []
   488     val empty = []
   367     fun merge data = Library.merge order_data_eq data
   489     fun merge data = Library.merge order_data_eq data
   369 
   491 
   370   fun declare (octxt as {kind = kind, raw_proc = raw_proc, ...}) lthy =
   492   fun declare (octxt as {kind = kind, raw_proc = raw_proc, ...}) lthy =
   371     lthy |> Local_Theory.declaration {syntax = false, pervasive = false, pos = \<^here>}
   493     lthy |> Local_Theory.declaration {syntax = false, pervasive = false, pos = \<^here>}
   372       (fn phi => fn context =>
   494       (fn phi => fn context =>
   373         let
   495         let
   374           val ops = map (Morphism.term phi) (#ops octxt)
   496           val ops = map_order_ops (Morphism.term phi) (#ops octxt)
   375           val thms = map (fn (s, thm) => (s, Morphism.thm phi thm)) (#thms octxt)
   497           val thms = map (fn (s, thm) => (s, Morphism.thm phi thm)) (#thms octxt)
   376           val conv_thms = map (fn (s, thm) => (s, Morphism.thm phi thm)) (#conv_thms octxt)
   498           val conv_thms = map (fn (s, thm) => (s, Morphism.thm phi thm)) (#conv_thms octxt)
   377           val octxt' = {kind = kind, ops = ops, thms = thms, conv_thms = conv_thms}
   499           val octxt' = {kind = kind, ops = ops, thms = thms, conv_thms = conv_thms}
   378         in
   500         in
   379           context |> Data.map (Library.insert order_data_eq (octxt', raw_proc))
   501           context |> Data.map (Library.insert order_data_eq (octxt', raw_proc))
   380         end)
   502         end)
   381 
   503 
   382   fun declare_order {
   504   fun declare_order {
   383       ops = {eq = eq, le = le, lt = lt},
   505       ops = ops,
   384       thms = {
   506       thms = {
   385         trans = trans, (* x \<le> y \<Longrightarrow> y \<le> z \<Longrightarrow> x \<le> z *)
   507         trans = trans, (* x \<le> y \<Longrightarrow> y \<le> z \<Longrightarrow> x \<le> z *)
   386         refl = refl, (* x \<le> x *)
   508         refl = refl, (* x \<le> x *)
   387         eqD1 = eqD1, (* x = y \<Longrightarrow> x \<le> y *)
   509         eqD1 = eqD1, (* x = y \<Longrightarrow> x \<le> y *)
   388         eqD2 = eqD2, (* x = y \<Longrightarrow> y \<le> x *)
   510         eqD2 = eqD2, (* x = y \<Longrightarrow> y \<le> x *)
   394         nless_le = nless_le (* \<not> a < b \<equiv> \<not> a \<le> b \<or> a = b *)
   516         nless_le = nless_le (* \<not> a < b \<equiv> \<not> a \<le> b \<or> a = b *)
   395       }
   517       }
   396     } =
   518     } =
   397     declare {
   519     declare {
   398       kind = Order,
   520       kind = Order,
   399       ops = [eq, le, lt],
   521       ops = ops,
   400       thms = [("trans", trans), ("refl", refl), ("eqD1", eqD1), ("eqD2", eqD2),
   522       thms = [("trans", trans), ("refl", refl), ("eqD1", eqD1), ("eqD2", eqD2),
   401               ("antisym", antisym), ("contr", contr)],
   523               ("antisym", antisym), ("contr", contr)],
   402       conv_thms = [("less_le", less_le), ("nless_le", nless_le)],
   524       conv_thms = [("less_le", less_le), ("nless_le", nless_le)],
   403       raw_proc = Base_Tac.tac Order_Procedure.po_contr_prf
   525       raw_proc = Base_Tac.tac Order_Procedure.po_contr_prf
   404      }                
   526      }                
   405 
   527 
   406   fun declare_linorder {
   528   fun declare_linorder {
   407       ops = {eq = eq, le = le, lt = lt},
   529       ops = ops,
   408       thms = {
   530       thms = {
   409         trans = trans, (* x \<le> y \<Longrightarrow> y \<le> z \<Longrightarrow> x \<le> z *)
   531         trans = trans, (* x \<le> y \<Longrightarrow> y \<le> z \<Longrightarrow> x \<le> z *)
   410         refl = refl, (* x \<le> x *)
   532         refl = refl, (* x \<le> x *)
   411         eqD1 = eqD1, (* x = y \<Longrightarrow> x \<le> y *)
   533         eqD1 = eqD1, (* x = y \<Longrightarrow> x \<le> y *)
   412         eqD2 = eqD2, (* x = y \<Longrightarrow> y \<le> x *)
   534         eqD2 = eqD2, (* x = y \<Longrightarrow> y \<le> x *)
   419         nle_le = nle_le (* \<not> a \<le> b \<equiv> b \<le> a \<and> b \<noteq> a *)
   541         nle_le = nle_le (* \<not> a \<le> b \<equiv> b \<le> a \<and> b \<noteq> a *)
   420       }
   542       }
   421     } =
   543     } =
   422     declare {
   544     declare {
   423       kind = Linorder,
   545       kind = Linorder,
   424       ops = [eq, le, lt],
   546       ops = ops,
   425       thms = [("trans", trans), ("refl", refl), ("eqD1", eqD1), ("eqD2", eqD2),
   547       thms = [("trans", trans), ("refl", refl), ("eqD1", eqD1), ("eqD2", eqD2),
   426               ("antisym", antisym), ("contr", contr)],
   548               ("antisym", antisym), ("contr", contr)],
   427       conv_thms = [("less_le", less_le), ("nless_le", nless_le), ("nle_le", nle_le)],
   549       conv_thms = [("less_le", less_le), ("nless_le", nless_le), ("nle_le", nle_le)],
   428       raw_proc = Base_Tac.tac Order_Procedure.lo_contr_prf
   550       raw_proc = Base_Tac.tac Order_Procedure.lo_contr_prf
   429      }
   551      }
   430   
   552 
   431   (* Try to solve the goal by calling the order solver with each of the declared orders. *)      
   553   (* Try to solve the goal by calling the order solver with each of the declared orders. *)      
   432   fun tac simp_prems ctxt =
   554   fun tac simp_prems ctxt =
   433     let fun app_tac (octxt, tac0) = CHANGED o tac0 octxt simp_prems ctxt
   555     let fun app_tac (octxt, tac0) = CHANGED o tac0 octxt simp_prems ctxt
   434     in FIRST' (map app_tac (Data.get (Context.Proof ctxt))) end
   556     in FIRST' (map app_tac (Data.get (Context.Proof ctxt))) end
   435 end
   557 end