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); |