signature CLA = sig type pack val empty_pack: pack val get_pack: Proof.context -> pack val put_pack: pack -> Proof.context -> Proof.context val pretty_pack: Proof.context -> Pretty.T val add_safe: thm -> Proof.context -> Proof.context val add_unsafe: thm -> Proof.context -> Proof.context val safe_add: attribute val unsafe_add: attribute val method: (Proof.context -> int -> tactic) -> (Proof.context -> Proof.method) context_parser val trace: bool Config.T val forms_of_seq: term -> term list val safe_tac: Proof.context -> int -> tactic val step_tac: Proof.context -> int -> tactic val pc_tac: Proof.context -> int -> tactic val fast_tac: Proof.context -> int -> tactic val best_tac: Proof.context -> int -> tactic end;
structure Cla: CLA = struct
(** rule declarations **)
(*A theorem pack has the form (safe rules, unsafe rules) Anunsaferuleisincompleteorintroducesvariablesinsubgoals,
and is tried only when the safe rules are not applicable. *)
fun less (rl1, rl2) = Thm.nprems_of rl1 < Thm.nprems_of rl2; val sort_rules = sort (make_ord less);
datatype pack = Pack of thm list * thm list;
val empty_pack = Pack ([], []);
structure Pack = Generic_Data
( type T = pack; val empty = empty_pack; fun merge (Pack (safes, unsafes), Pack (safes', unsafes')) =
Pack
(sort_rules (Thm.merge_thms (safes, safes')),
sort_rules (Thm.merge_thms (unsafes, unsafes')));
);
val put_pack = Context.proof_map o Pack.put; val get_pack = Pack.get o Context.Proof; fun get_rules ctxt = letval Pack rules = get_pack ctxt in rules end;
val _ =
Outer_Syntax.command \<^command_keyword>\<open>print_pack\<close> "print pack of classical rules"
(Scan.succeed (Toplevel.keep (Pretty.writeln o pretty_pack o Toplevel.context_of)));
(* declare rules *)
fun add_rule which th context = context |> Pack.map (fn Pack rules =>
Pack (rules |> which (fn ths => if member Thm.eq_thm_prop ths th then let val _ =
(case context of
Context.Proof ctxt => if Context_Position.is_really_visible ctxt then
warning ("Ignoring duplicate theorems:\n" ^ Thm.string_of_thm ctxt th) else ()
| _ => ()); in ths end else sort_rules (th :: ths))));
val add_safe = Context.proof_map o add_rule apfst; val add_unsafe = Context.proof_map o add_rule apsnd;
(* attributes *)
val safe_add = Thm.declaration_attribute (add_rule apfst); val unsafe_add = Thm.declaration_attribute (add_rule apsnd);
fun method tac =
Method.sections
[Args.$$$ "add" -- Args.bang_colon >> K (Method.modifier safe_add \<^here>),
Args.$$$ "add" -- Args.colon >> K (Method.modifier unsafe_add \<^here>)]
>> K (SIMPLE_METHOD' o tac);
(** tactics **)
val trace = Attrib.setup_config_bool \<^binding>\<open>cla_trace\<close> (K false);
(*Returns the list of all formulas in the sequent*) fun forms_of_seq \<^Const_>\<open>SeqO' for P u\<close> = P :: forms_of_seq u
| forms_of_seq (H $ u) = forms_of_seq u
| forms_of_seq _ = [];
(*Tests whether two sequences (left or right sides) could be resolved. seqpisapremise(subgoal),seqcisaconclusionofanobject-rule. Assumeseachformulainseqcissurroundedbysequencevariables --checksthateachconclformulalookslikesomesubgoalformula.
It SHOULD check order as well, using recursion rather than forall/exists*) fun could_res (seqp,seqc) =
forall (fn Qc => exists (fn Qp => Term.could_unify (Qp,Qc))
(forms_of_seq seqp))
(forms_of_seq seqc);
(*Tests whether two sequents or pairs of sequents could be resolved*) fun could_resolve_seq (prem,conc) = case (prem,conc) of
(_ $ Abs(_,_,leftp) $ Abs(_,_,rightp),
_ $ Abs(_,_,leftc) $ Abs(_,_,rightc)) =>
could_res (leftp,leftc) andalso could_res (rightp,rightc)
| (_ $ Abs(_,_,leftp) $ rightp,
_ $ Abs(_,_,leftc) $ rightc) =>
could_res (leftp,leftc) andalso Term.could_unify (rightp,rightc)
| _ => false;
(*Like filt_resolve_tac, using could_resolve_seq Muchfasterthanresolve_tacwhentherearemanyrules.
Resolve subgoal i using the rules, unless more than maxr are compatible. *) fun filseq_resolve_tac ctxt rules maxr = SUBGOAL(fn (prem,i) => letval rls = filter_thms could_resolve_seq (maxr+1, prem, rules) inif length rls > maxr then no_tac else(*((rtac derelict 1 THEN rtac impl 1 THEN(rtacidentity2ORELSErtacll_mp2) THENrtaccontext11)
ORELSE *) resolve_tac ctxt rls i end);
(*Predicate: does the rule have n premises? *) fun has_prems n rule = (Thm.nprems_of rule = n);
(*Continuation-style tactical for resolution. Thelistofrulesispartitionedinto0,1,2premises. Theresultingtactic,gtac,triestoresolvewithrules. Ifsuccessful,itrecursivelyappliesnextactothenewsubgoalsonly. Elsefails.(TreatmentofgoalsduetoPh.deGroote)
Bind (RESOLVE_THEN rules) to a variable: it preprocesses the rules. *)
(*Takes rule lists separated in to 0, 1, 2, >2 premises. Theabstractionoverstatepreventsneedlessdivergenceinrecursion.
The 9999 should be a parameter, to delay treatment of flexible goals. *)
fun RESOLVE_THEN ctxt rules = letval [rls0,rls1,rls2] = partition_list has_prems 02 rules; fun tac nextac i state = state |>
(filseq_resolve_tac ctxt rls0 9999 i
ORELSE
(DETERM(filseq_resolve_tac ctxt rls1 9999 i) THENTRY(nextac i))
ORELSE
(DETERM(filseq_resolve_tac ctxt rls2 9999 i) THENTRY(nextac(i+1)) THENTRY(nextac i))) in tac end;
(*repeated resolution applied to the designated goal*) fun reresolve_tac ctxt rules = let val restac = RESOLVE_THEN ctxt rules; (*preprocessing done now*) fun gtac i = restac gtac i; in gtac end;
(*tries the safe rules repeatedly before the unsafe rules. *) fun repeat_goal_tac ctxt = let val (safes, unsafes) = get_rules ctxt; val restac = RESOLVE_THEN ctxt safes; val lastrestac = RESOLVE_THEN ctxt unsafes; fun gtac i =
restac gtac i ORELSE
(if Config.get ctxt trace then print_tac ctxt ""THEN lastrestac gtac i else lastrestac gtac i) in gtac end;
(*Tries a safe rule or else a unsafe rule. Single-step for tracing. *) fun step_tac ctxt =
safe_tac ctxt ORELSE' filseq_resolve_tac ctxt (#2 (get_rules ctxt)) 9999;
(* Tactic for reducing a goal, using Predicate Calculus rules. AdecisionprocedureforPropositionalCalculus,itisincomplete forPredicate-CalculusbecauseofallL_thinandexR_thin.
Fails if it can do nothing. *) fun pc_tac ctxt = SELECT_GOAL (DEPTH_SOLVE (repeat_goal_tac ctxt 1));
(*The following two tactics are analogous to those provided by
Provers/classical. In fact, pc_tac is usually FASTER than fast_tac!*) fun fast_tac ctxt =
SELECT_GOAL (DEPTH_SOLVE (step_tac ctxt 1));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.