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!? *) |