(*higher precedence than := facilitates use of references*)
infix 4 addSIs addSEs addSDs addIs addEs addDs delrules
addSWrapper delSWrapper addWrapper delWrapper
addSbefore addSafter addbefore addafter
addD2 addE2 addSD2 addSE2;
signature CLASSICAL_DATA = sig val imp_elim: thm (* P \<longrightarrow> Q \<Longrightarrow> (\<not> R \<Longrightarrow> P) \<Longrightarrow> (Q \<Longrightarrow> R) \<Longrightarrow> R *) val not_elim: thm (* \<not> P \<Longrightarrow> P \<Longrightarrow> R *) val swap: thm (* \<not> P \<Longrightarrow> (\<not> R \<Longrightarrow> P) \<Longrightarrow> R *) val classical: thm (* (\<not> P \<Longrightarrow> P) \<Longrightarrow> P *) val sizef: thm -> int (*size function for BEST_FIRST, typically size_of_thm*) val hyp_subst_tacs: (Proof.context -> int -> tactic) list (*optional tactics for substitution in the hypotheses; assumed to be safe!*) end;
signature BASIC_CLASSICAL = sig type wrapper = (int -> tactic) -> int -> tactic type claset val addDs: Proof.context * thm list -> Proof.context val addEs: Proof.context * thm list -> Proof.context val addIs: Proof.context * thm list -> Proof.context val addSDs: Proof.context * thm list -> Proof.context val addSEs: Proof.context * thm list -> Proof.context val addSIs: Proof.context * thm list -> Proof.context val delrules: Proof.context * thm list -> Proof.context val addSWrapper: Proof.context * (string * (Proof.context -> wrapper)) -> Proof.context val delSWrapper: Proof.context * string -> Proof.context val addWrapper: Proof.context * (string * (Proof.context -> wrapper)) -> Proof.context val delWrapper: Proof.context * string -> Proof.context val addSbefore: Proof.context * (string * (Proof.context -> int -> tactic)) -> Proof.context val addSafter: Proof.context * (string * (Proof.context -> int -> tactic)) -> Proof.context val addbefore: Proof.context * (string * (Proof.context -> int -> tactic)) -> Proof.context val addafter: Proof.context * (string * (Proof.context -> int -> tactic)) -> Proof.context val addD2: Proof.context * (string * thm) -> Proof.context val addE2: Proof.context * (string * thm) -> Proof.context val addSD2: Proof.context * (string * thm) -> Proof.context val addSE2: Proof.context * (string * thm) -> Proof.context val appSWrappers: Proof.context -> wrapper val appWrappers: Proof.context -> wrapper
val claset_of: Proof.context -> claset val put_claset: claset -> Proof.context -> Proof.context
val map_theory_claset: (Proof.context -> Proof.context) -> theory -> theory
val fast_tac: Proof.context -> int -> tactic val slow_tac: Proof.context -> int -> tactic val astar_tac: Proof.context -> int -> tactic val slow_astar_tac: Proof.context -> int -> tactic val best_tac: Proof.context -> int -> tactic val first_best_tac: Proof.context -> int -> tactic val slow_best_tac: Proof.context -> int -> tactic val depth_tac: Proof.context -> int -> int -> tactic val deepen_tac: Proof.context -> int -> int -> tactic
val contr_tac: Proof.context -> int -> tactic val dup_elim: Proof.context -> thm -> thm val dup_intr: thm -> thm val dup_step_tac: Proof.context -> int -> tactic val eq_mp_tac: Proof.context -> int -> tactic val unsafe_step_tac: Proof.context -> int -> tactic val mp_tac: Proof.context -> int -> tactic val safe_tac: Proof.context -> tactic val safe_steps_tac: Proof.context -> int -> tactic val safe_step_tac: Proof.context -> int -> tactic val clarify_tac: Proof.context -> int -> tactic val clarify_step_tac: Proof.context -> int -> tactic val step_tac: Proof.context -> int -> tactic val slow_step_tac: Proof.context -> int -> tactic val swap_res_tac: Proof.context -> thm list -> int -> tactic val inst_step_tac: Proof.context -> int -> tactic val inst0_step_tac: Proof.context -> int -> tactic val instp_step_tac: Proof.context -> int -> tactic
val print_claset: Proof.context -> unit end;
signature CLASSICAL = sig
include BASIC_CLASSICAL val classical_rule: Proof.context -> thm -> thm type rl = thm * thm option type info = {rl: rl, dup_rl: rl, plain: thm} type decl = info Bires.decl type decls = info Bires.decls val safe0_netpair_of: Proof.context -> Bires.netpair val safep_netpair_of: Proof.context -> Bires.netpair val unsafe_netpair_of: Proof.context -> Bires.netpair val dup_netpair_of: Proof.context -> Bires.netpair val extra_netpair_of: Proof.context -> Bires.netpair val dest_decls: Proof.context -> ((thm * decl) -> bool) -> (thm * decl) list val get_cs: Context.generic -> claset val map_cs: (claset -> claset) -> Context.generic -> Context.generic val safe_dest: int option -> attribute val safe_elim: int option -> attribute val safe_intro: int option -> attribute val unsafe_dest: int option -> attribute val unsafe_elim: int option -> attribute val unsafe_intro: int option -> attribute val rule_del: attribute val rule_tac: Proof.context -> thm list -> thm list -> int -> tactic val standard_tac: Proof.context -> thm list -> tactic val cla_modifiers: Method.modifier parser list val cla_method:
(Proof.context -> tactic) -> (Proof.context -> Proof.method) context_parser val cla_method':
(Proof.context -> int -> tactic) -> (Proof.context -> Proof.method) context_parser end;
fun classical_rule ctxt rule = if is_some (Object_Logic.elim_concl ctxt rule) then let val thy = Proof_Context.theory_of ctxt; val rule' = rule RS Data.classical; val concl' = Thm.concl_of rule'; fun redundant_hyp goal =
concl' aconv Logic.strip_assums_concl goal orelse
(case Logic.strip_assums_hyp goal of
hyp :: hyps => exists (fn t => t aconv hyp) hyps
| _ => false); val rule'' =
rule' |> ALLGOALS (SUBGOAL (fn (goal, i) => if i = 1 orelse redundant_hyp goal then eresolve_tac ctxt [thin_rl] i else all_tac))
|> Seq.hd
|> Drule.zero_var_indexes; inif Thm.equiv_thm thy (rule, rule'') then rule else rule''end else rule;
(* flatten nested meta connectives in prems *)
fun flat_rule ctxt =
Conv.fconv_rule (Conv.prems_conv ~1 (Object_Logic.atomize_prems ctxt));
(* Useful tactics for classical reasoning *)
(*Prove goal that assumes both P and \<not> P. Nobacktrackingifitfindsanequalassumption.Perhapsshouldcall
ematch_tac instead of eresolve_tac, but then cannot prove ZF/cantor.*) fun contr_tac ctxt =
eresolve_tac ctxt [Data.not_elim] THEN' (eq_assume_tac ORELSE' assume_tac ctxt);
(*Finds P \<longrightarrow> Q and P in the assumptions, replaces implication by Q.
Could do the same thing for P \<longleftrightarrow> Q and P.*) fun mp_tac ctxt i =
eresolve_tac ctxt [Data.not_elim, Data.imp_elim] i THEN assume_tac ctxt i;
(*Like mp_tac but instantiates no variables*) fun eq_mp_tac ctxt i = ematch_tac ctxt [Data.not_elim, Data.imp_elim] i THEN eq_assume_tac i;
(*Creates rules to eliminate \<not> A, from rules to introduce A*) fun maybe_swap_rule th =
(case [th] RLN (2, [Data.swap]) of
[] => NONE
| [res] => SOME res
| _ => raise THM ("RSN: multiple unifiers", 2, [th, Data.swap]));
fun swap_rule intr = intr RSN (2, Data.swap); val swapped = Thm.rule_attribute [] (K swap_rule);
(*Uses introduction rules in the normal way, or on negated assumptions,
trying rules in order. *) fun swap_res_tac ctxt rls = let fun addrl rl brls = (false, rl) :: (true, swap_rule rl) :: brls; in
assume_tac ctxt ORELSE'
contr_tac ctxt ORELSE'
biresolve_tac ctxt (fold_rev (addrl o Thm.transfer' ctxt) rls []) end;
(*Duplication of unsafe rules, for complete provers*) fun dup_intr th = zero_var_indexes (th RS Data.classical);
fun insert_brl i brl =
Bires.insert_tagged_rule ({weight = Bires.subgoals_of brl, index = i}, brl);
fun insert_rl kind k ((th, swapped): rl) =
insert_brl (2 * k + 1) (Bires.kind_rule kind th) #>
(case swapped of NONE => I | SOME th' => insert_brl (2 * k) (true, th'));
fun delete_rl k ((th, swapped): rl) =
Bires.delete_tagged_rule (2 * k + 1, th) #>
(case swapped of NONE => I | SOME th' => Bires.delete_tagged_rule (2 * k, th'));
fun insert_plain_rule ({kind, tag, info = {plain = th, ...}}: decl) =
Bires.insert_tagged_rule (tag, (Bires.kind_rule kind th));
fun delete_plain_rule ({tag = {index, ...}, info = {plain = th, ...}, ...}: decl) =
Bires.delete_tagged_rule (index, th);
type netpairs = (Bires.netpair * Bires.netpair) * (Bires.netpair * Bires.netpair);
fun add_safe_rule (decl: decl) (netpairs: netpairs) = let val {kind, tag = {index, ...}, info = {rl, ...}} = decl; val no_subgoals = Bires.no_subgoals (Bires.kind_rule kind (#1 rl)); in (apfst o (if no_subgoals then apfst else apsnd)) (insert_rl kind index rl) netpairs end;
fun add_unsafe_rule (decl: decl) ((safe_netpairs, (unsafe_netpair, dup_netpair)): netpairs) = let val {kind, tag = {index, ...}, info = {rl, dup_rl, ...}} = decl; val unsafe_netpair' = insert_rl kind index rl unsafe_netpair; val dup_netpair' = insert_rl kind index dup_rl dup_netpair; in (safe_netpairs, (unsafe_netpair', dup_netpair')) end;
fun add_rule (decl as {kind, ...}: decl) = if Bires.kind_safe kind then add_safe_rule decl elseif Bires.kind_unsafe kind then add_unsafe_rule decl elseraise Fail "Bad rule kind";
fun trim_context_rl (th1, opt_th2) =
(Thm.trim_context th1, Option.map Thm.trim_context opt_th2);
fun trim_context_info {rl, dup_rl, plain} : info =
{rl = trim_context_rl rl, dup_rl = trim_context_rl dup_rl, plain = Thm.trim_context plain};
fun ext_info ctxt kind th = if kind = Bires.intro_bang_kind then
make_info1 (maybe_swapped_rl (flat_rule ctxt th)) th elseif kind = Bires.elim_bang_kind orelse kind = Bires.dest_bang_kind then let val _ = Thm.no_prems th andalso err_thm_illformed ctxt kind th; val elim = Bires.kind_make_elim kind th; in make_info1 (no_swapped_rl (classical_rule ctxt (flat_rule ctxt elim))) elim end elseif kind = Bires.intro_kind then let val th' = flat_rule ctxt th; val dup_th' = dup_intr th'handle THM _ => err_thm_illformed ctxt kind th; in make_info (maybe_swapped_rl th') (maybe_swapped_rl dup_th') th end elseif kind = Bires.elim_kind orelse kind = Bires.dest_kind then let val _ = Thm.no_prems th andalso err_thm_illformed ctxt kind th; val elim = Bires.kind_make_elim kind th; val th' = classical_rule ctxt (flat_rule ctxt elim); val dup_th' = dup_elim ctxt th'handle THM _ => err_thm_illformed ctxt kind th; in make_info (no_swapped_rl th') (no_swapped_rl dup_th') elim end elseraise Fail "Bad rule kind";
in
fun extend_rules ctxt kind opt_weight th cs = let val th' = Thm.trim_context th; val decl' = init_decl kind opt_weight (trim_context_info (ext_info ctxt kind th)); val CS {decls, swrappers, uwrappers, safe0_netpair, safep_netpair,
unsafe_netpair, dup_netpair, extra_netpair} = cs; in
(case Bires.extend_decls (th', decl') decls of
(NONE, _) => (warn_kind ctxt "Ignoring duplicate" th kind; cs)
| (SOME new_decl, decls') => let val _ = warn_other_kinds ctxt decls th; val ((safe0_netpair', safep_netpair'), (unsafe_netpair', dup_netpair')) =
add_rule new_decl ((safe0_netpair, safep_netpair), (unsafe_netpair, dup_netpair)); val extra_netpair' = insert_plain_rule new_decl extra_netpair; in
CS {
decls = decls',
swrappers = swrappers,
uwrappers = uwrappers,
safe0_netpair = safe0_netpair',
safep_netpair = safep_netpair',
unsafe_netpair = unsafe_netpair',
dup_netpair = dup_netpair',
extra_netpair = extra_netpair'} end) end;
fun merge_cs (cs, cs2) = if pointer_eq (cs, cs2) then cs else let val CS {decls, swrappers, uwrappers, safe0_netpair, safep_netpair,
unsafe_netpair, dup_netpair, extra_netpair} = cs; val CS {decls = decls2, swrappers = swrappers2, uwrappers = uwrappers2, ...} = cs2;
fun delrule ctxt warn th cs = let val CS {decls, swrappers, uwrappers,
safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair} = cs; val (old_decls, decls') = Bires.remove_decls th decls; val _ = if Bires.has_decls decls (Tactic.make_elim th) then
warn_thm ctxt
(fn () => "Not deleting elim format --- need to to declare proper dest rule") th else (); in if null old_decls then
(if warn then warn_thm ctxt (fn () => "Undeclared classical rule") th else (); cs) else let fun del which ({tag = {index, ...}, info, ...}: decl) = delete_rl index (which info); val safe0_netpair' = fold (del #rl) old_decls safe0_netpair; val safep_netpair' = fold (del #rl) old_decls safep_netpair; val unsafe_netpair' = fold (del #rl) old_decls unsafe_netpair; val dup_netpair' = fold (del #dup_rl) old_decls dup_netpair; val extra_netpair' = fold delete_plain_rule old_decls extra_netpair; in
CS {
decls = decls',
swrappers = swrappers,
uwrappers = uwrappers,
safe0_netpair = safe0_netpair',
safep_netpair = safep_netpair',
unsafe_netpair = unsafe_netpair',
dup_netpair = dup_netpair',
extra_netpair = extra_netpair'} end end;
(* Claset context data *)
structure Claset = Generic_Data
( type T = claset; val empty = empty_cs; val merge = merge_cs;
);
val claset_of = Claset.get o Context.Proof; val rep_claset_of = rep_cs o claset_of;
val dest_decls = Bires.dest_decls o #decls o rep_claset_of;
val safe0_netpair_of = #safe0_netpair o rep_claset_of; val safep_netpair_of = #safep_netpair o rep_claset_of; val unsafe_netpair_of = #unsafe_netpair o rep_claset_of; val dup_netpair_of = #dup_netpair o rep_claset_of; val extra_netpair_of = #extra_netpair o rep_claset_of;
val get_cs = Claset.get; val map_cs = Claset.map;
fun map_theory_claset f thy = let val ctxt' = f (Proof_Context.init_global thy); val thy' = Proof_Context.theory_of ctxt'; in Context.theory_map (Claset.map (K (claset_of ctxt'))) thy'end;
fun map_claset f = Context.proof_map (map_cs f); fun put_claset cs = map_claset (K cs);
val op addSIs = ml_decl Bires.intro_bang_kind; val op addSEs = ml_decl Bires.elim_bang_kind; val op addSDs = ml_decl Bires.dest_bang_kind; val op addIs = ml_decl Bires.intro_kind; val op addEs = ml_decl Bires.elim_kind; val op addDs = ml_decl Bires.dest_kind;
(*Remove a safe wrapper*) fun ctxt delSWrapper name = ctxt |> map_claset
(map_swrappers (delete_warn ("No such safe wrapper in claset: " ^ name) name));
(*Remove an unsafe wrapper*) fun ctxt delWrapper name = ctxt |> map_claset
(map_uwrappers (delete_warn ("No such unsafe wrapper in claset: " ^ name) name));
(*Repeatedly attack a subgoal using safe inferences -- it's deterministic!*) fun safe_steps_tac ctxt =
REPEAT_DETERM1 o (fn i => COND (has_fewer_prems i) no_tac (safe_step_tac ctxt i));
(*Repeatedly attack subgoals using safe inferences -- it's deterministic!*) fun safe_tac ctxt = REPEAT_DETERM1 (FIRSTGOAL (safe_steps_tac ctxt));
(** Clarify_tac: do safe steps without causing branching **)
(*version of Bires.bimatch_from_nets_tac that only applies rules that
create precisely n subgoals.*) fun n_bimatch_from_nets_tac ctxt n =
Bires.biresolution_from_nets_tac ctxt Bires.tag_ord
(SOME (fn rl => Bires.subgoals_of rl = n)) true;
fun eq_contr_tac ctxt i = ematch_tac ctxt [Data.not_elim] i THEN eq_assume_tac i; fun eq_assume_contr_tac ctxt = eq_assume_tac ORELSE' eq_contr_tac ctxt;
(*Two-way branching is allowed only if one of the branches immediately closes*) fun bimatch2_tac ctxt netpair i =
n_bimatch_from_nets_tac ctxt 2 netpair i THEN
(eq_assume_contr_tac ctxt i ORELSE eq_assume_contr_tac ctxt (i + 1));
fun clarify_tac ctxt = SELECT_GOAL (REPEAT_DETERM (clarify_step_tac ctxt 1));
(** Unsafe steps instantiate variables or lose information **)
(*Backtracking is allowed among the various these unsafe ways of
proving a subgoal. *) fun inst0_step_tac ctxt =
assume_tac ctxt APPEND'
contr_tac ctxt APPEND'
Bires.biresolve_from_nets_tac ctxt (safe0_netpair_of ctxt);
(*These unsafe steps could generate more subgoals.*) fun instp_step_tac ctxt =
Bires.biresolve_from_nets_tac ctxt (safep_netpair_of ctxt);
(*These steps could instantiate variables and are therefore unsafe.*) fun inst_step_tac ctxt = inst0_step_tac ctxt APPEND' instp_step_tac ctxt;
fun unsafe_step_tac ctxt =
Bires.biresolve_from_nets_tac ctxt (unsafe_netpair_of ctxt);
(*Single step for the prover. FAILS unless it makes progress. *) fun step_tac ctxt i =
safe_tac ctxt ORELSE appWrappers ctxt (inst_step_tac ctxt ORELSE' unsafe_step_tac ctxt) i;
(*Using a "safe" rule to instantiate variables is unsafe. This tactic
allows backtracking from "safe" rules to "unsafe" rules here.*) fun slow_step_tac ctxt i =
safe_tac ctxt ORELSE appWrappers ctxt (inst_step_tac ctxt APPEND' unsafe_step_tac ctxt) i;
(** The following tactics all fail unless they solve one goal **)
(*Dumb but fast*) fun fast_tac ctxt =
Object_Logic.atomize_prems_tac ctxt THEN' SELECT_GOAL (DEPTH_SOLVE (step_tac ctxt 1));
(*Slower but smarter than fast_tac*) fun best_tac ctxt =
Object_Logic.atomize_prems_tac ctxt THEN'
SELECT_GOAL (BEST_FIRST (Thm.no_prems, Data.sizef) (step_tac ctxt 1));
(*even a bit smarter than best_tac*) fun first_best_tac ctxt =
Object_Logic.atomize_prems_tac ctxt THEN'
SELECT_GOAL (BEST_FIRST (Thm.no_prems, Data.sizef) (FIRSTGOAL (step_tac ctxt)));
(** Complete tactic, loosely based upon LeanTaP. This tactic is the outcome ofmuchexperimentation!ChangingAPPENDtoORELSEbelowwouldprove easytheoremsfaster,butlosescompleteness--andmanyoftheharder
theorems such as 43. **)
(*Non-deterministic! Could always expand the first unsafe connective. That'shardtoimplementanddidnotperformbetterinexperiments,dueto
greater search depth required.*) fun dup_step_tac ctxt =
Bires.biresolve_from_nets_tac ctxt (dup_netpair_of ctxt);
(*Searching to depth m. A variant called nodup_depth_tac appears in clasimp.ML*)
local fun slow_step_tac' ctxt = appWrappers ctxt (instp_step_tac ctxt APPEND' dup_step_tac ctxt); in fun depth_tac ctxt m i state = SELECT_GOAL
(safe_steps_tac ctxt 1 THEN_ELSE
(DEPTH_SOLVE (depth_tac ctxt m 1),
inst0_step_tac ctxt 1 APPEND COND (K (m = 0)) no_tac
(slow_step_tac' ctxt 1 THEN DEPTH_SOLVE (depth_tac ctxt (m - 1) 1)))) i state; end;
(*Search, with depth bound m.
This is the "entry point", which does safe inferences first.*) fun safe_depth_tac ctxt m = SUBGOAL (fn (prem, i) => let val deti = (*No Vars in the goal? No need to backtrack between goals.*) if exists_subterm (fn Var _ => true | _ => false) prem then DETERM else I; in
SELECT_GOAL (TRY (safe_tac ctxt) THEN DEPTH_SOLVE (deti (depth_tac ctxt m 1))) i end);
fun deepen_tac ctxt = DEEPEN (2, 10) (safe_depth_tac ctxt);
(** attributes **)
(* declarations *)
fun attrib kind w =
Thm.declaration_attribute (fn th => fn context =>
map_cs (extend_rules (Context.proof_of context) kind w th) context);
val safe_intro = attrib Bires.intro_bang_kind; val safe_elim = attrib Bires.elim_bang_kind; val safe_dest = attrib Bires.dest_bang_kind; val unsafe_intro = attrib Bires.intro_kind; val unsafe_elim = attrib Bires.elim_kind; val unsafe_dest = attrib Bires.dest_kind;
val cla_modifiers =
[Args.$$$ destN -- Args.bang_colon >> K (Method.modifier (safe_dest NONE) \<^here>),
Args.$$$ destN -- Args.colon >> K (Method.modifier (unsafe_dest NONE) \<^here>),
Args.$$$ elimN -- Args.bang_colon >> K (Method.modifier (safe_elim NONE) \<^here>),
Args.$$$ elimN -- Args.colon >> K (Method.modifier (unsafe_elim NONE) \<^here>),
Args.$$$ introN -- Args.bang_colon >> K (Method.modifier (safe_intro NONE) \<^here>),
Args.$$$ introN -- Args.colon >> K (Method.modifier (unsafe_intro NONE) \<^here>),
Args.del -- Args.colon >> K (Method.modifier rule_del \<^here>)];
fun cla_method tac = Method.sections cla_modifiers >> K (SIMPLE_METHOD o tac); fun cla_method' tac = Method.sections cla_modifiers >> K (SIMPLE_METHOD' o tac);
fun print_claset ctxt = let val {decls, swrappers, uwrappers, ...} = rep_claset_of ctxt; val prt_wrappers =
[Pretty.strs ("safe wrappers:" :: map #1 swrappers),
Pretty.strs ("unsafe wrappers:" :: map #1 uwrappers)]; in Pretty.writeln (Pretty.chunks (Bires.pretty_decls ctxt decls @ prt_wrappers)) end;
val _ =
Outer_Syntax.command \<^command_keyword>\<open>print_claset\<close> "print context of Classical Reasoner"
(Scan.succeed (Toplevel.keep (print_claset o Toplevel.context_of)));
end;
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.65 Sekunden
(vorverarbeitet am 2026-06-09)
¤
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.