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 $ _) => |
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 |