val requires_subproof_assms : stringlist -> string -> bool val requires_local_input: stringlist -> string -> bool
val string_of_verit_rule: verit_rule -> string
type lethe_tac_args = Proof.context -> thm list -> term list -> term -> thm type lethe_tac = Proof.context -> thm list -> term -> thm type lethe_tac2 = Proof.context -> thm list -> term list -> term Symtab.table -> term -> thm val bind: lethe_tac_args val and_rule: lethe_tac val and_neg_rule: lethe_tac val and_pos: lethe_tac val rewrite_and_simplify: lethe_tac val rewrite_bool_simplify: lethe_tac val rewrite_comp_simplify: lethe_tac val rewrite_minus_simplify: lethe_tac val rewrite_not_simplify: lethe_tac val rewrite_eq_simplify: lethe_tac val rewrite_equiv_simplify: lethe_tac val rewrite_implies_simplify: lethe_tac val rewrite_or_simplify: lethe_tac val cong: string -> lethe_tac val rewrite_connective_def: lethe_tac val duplicate_literals: lethe_tac val eq_congruent: lethe_tac val eq_congruent_pred: lethe_tac val eq_reflexive: lethe_tac val eq_transitive: lethe_tac val equiv1: lethe_tac val equiv2: lethe_tac val equiv_neg1: lethe_tac val equiv_neg2: lethe_tac val equiv_pos1: lethe_tac val equiv_pos2: lethe_tac val false_rule: lethe_tac val forall_inst: lethe_tac2 val implies_rules: lethe_tac val implies_neg1: lethe_tac val implies_neg2: lethe_tac val implies_pos: lethe_tac val ite1: lethe_tac val ite2: lethe_tac val ite_intro: lethe_tac val ite_neg1: lethe_tac val ite_neg2: lethe_tac val ite_pos1: lethe_tac val ite_pos2: lethe_tac val rewrite_ite_simplify: lethe_tac val la_disequality: lethe_tac val la_generic: lethe_tac_args val la_rw_eq: lethe_tac val lia_generic: lethe_tac val refl: string -> lethe_tac val normalized_input: lethe_tac val not_and_rule: lethe_tac val not_equiv1: lethe_tac val not_equiv2: lethe_tac val not_implies1: lethe_tac val not_implies2: lethe_tac val not_ite1: lethe_tac val not_ite2: lethe_tac val not_not: lethe_tac val not_or_rule: lethe_tac valor: lethe_tac val or_neg_rule: lethe_tac val or_pos_rule: lethe_tac val theory_resolution2: lethe_tac val prod_simplify: lethe_tac val qnt_join: lethe_tac val qnt_rm_unused: lethe_tac val onepoint: lethe_tac val qnt_simplify: lethe_tac val all_simplify: lethe_tac val unit_res: lethe_tac val skolem_ex: lethe_tac val skolem_forall: lethe_tac val subproof: lethe_tac val sum_simplify: lethe_tac val tautological_clause: lethe_tac val tmp_AC_rule: lethe_tac val bfun_elim: lethe_tac val qnt_cnf: lethe_tac val trans: lethe_tac val symm: lethe_tac val not_symm: lethe_tac val reordering: lethe_tac
(*Extension to declare new alethe rules*) val declare_alethe_rule: string -> lethe_tac_args -> Context.generic -> Context.generic val rm_alethe_rule: string -> Context.generic -> Context.generic val get_alethe_tac: string -> Context.generic -> lethe_tac_args option val print_alethe_tac: Context.generic -> Pretty.T
(*Useful lifting of tactics*) val REPEAT_CHANGED: ('a -> tactic) -> 'a -> tactic valTRY': ('a -> tactic) -> 'a -> tactic
val simplify_tac: Proof.context -> thm list -> int -> tactic val replay_error: Proof.context -> string -> verit_rule -> thm list -> term -> 'a
type lethe_tac_args = Proof.context -> thm list -> term list -> term -> thm type lethe_tac = Proof.context -> thm list -> term -> thm type lethe_tac2 = Proof.context -> thm list -> term list -> term Symtab.table -> term -> thm
(*Some general comments on the proof format: 1.Doublenegationsarenotalwaysremoved.Thismeansforexamplethattheequivalencerules cannotassumethatthedoublenegationshavealreadybeenremoved.Therefore,wematchthe term,instantiatethetheorem,thenusesimp(toremovedoublenegations),andfinallyuse assumption. 2.Thereconstructionforruleforall_instisbuggyandtendstobeveryfragile,becausetherule isdoingmuchmorethatissupposedtodo.Moreovertypescanmaketrivialgoals(forthe booleanstructure)impossibletoprove. 3.Duplicateliteralsaresometimesremoved,mostlybytheSATsolver.
(** Context Extension for Rules **) (*We currently do not distinguish between the extension required for each solver. Maybe later
it will be needed.*) type alethe_rule_ext = {rules: (string * lethe_tac_args) list}
fun mk_alethe_rule_ext rules : alethe_rule_ext =
{rules=rules}
structure Data = Generic_Data
( type T = alethe_rule_ext val empty = empty_data val merge = merge_data
)
fun declare_alethe_rule rule tac context = let val {rules} = Data.get context in
Data.map
(K (mk_alethe_rule_ext (AList.update (op =) (rule, tac) rules)))
context end
fun rm_alethe_rule stgy context = let val {rules} = Data.get context in
Data.map
(K (mk_alethe_rule_ext (AList.delete (op =) stgy rules)))
context end
fun get_alethe_tac rule context = let val {rules} = Data.get context in
AList.lookup (op =) rules rule end
fun print_alethe_tac context = let val {rules} = Data.get context in
rules
|> map (fn (a, b) => a ^ "->" ^ @{make_string} b)
|> map Pretty.str
|> Pretty.big_list "Declared alethe rules:\n" end
(** Tactics for Reconstruction **) (**) fun replay_error ctxt msg rule thms t =
SMT_Replay_Methods.replay_error ctxt msg (string_of_verit_rule rule) thms t
(* utility function *)
fun eqsubst_all ctxt thms =
K ((REPEAT o HEADGOAL) (EqSubst.eqsubst_asm_tac ctxt [0] thms)) THEN' K ((REPEAT o HEADGOAL) (EqSubst.eqsubst_tac ctxt [0] thms))
(* sko_forall requires the assumptions to be able to prove the equivalence in case of double
skolemization. See comment below. *) fun requires_subproof_assms _ t =
member (op =) ["refl", "sko_forall", "sko_ex", "cong"] t
fun requires_local_input _ t =
member (op =) [Lethe_Proof.local_input_rule] t
(*This is a weaker simplification form. It is weaker, but is also less likely to loop*) fun partial_simplify_tac ctxt thms =
ctxt
|> empty_simpset
|> put_simpset HOL_basic_ss
|> Simplifier.add_simps @{thms simp_thms}
|> Simplifier.add_simps thms
|> Simplifier.full_simp_tac
val try_provers = SMT_Replay_Methods.try_provers
funTRY' tac = fn i => TRY (tac i) fun REPEAT' tac = fn i => REPEAT (tac i) fun REPEAT_CHANGED tac = fn i => REPEAT (CHANGED (tac i))
(* Bind *)
(*The bind rule is non-obvious due to the handling of quantifiers: "\<And>xya.x=y==>(\<forall>b.Pabx)\<longleftrightarrow>(\<forall>b.P'aby)" ------------------------------------------------------ \<forall>a.(\<forall>bx.Pabx)\<longleftrightarrow>(\<forall>by.P'aby)
is a valid application.*)
val bind_thms =
[@{lemma \<open>(\<And>x x'. x = x' \<Longrightarrow> P x = Q x') \<Longrightarrow> (\<forall>x. P x) = (\<forall>y. Q y)\<close> by blast},
@{lemma \<open>(\<And>x x'. x = x' \<Longrightarrow> P x = Q x') \<Longrightarrow> (\<exists>x. P x) = (\<exists>y. Q y)\<close> by blast},
@{lemma \<open>(\<And>x x'. x = x' \<Longrightarrow> P x = Q x') \<Longrightarrow> (\<exists>x. P x = Q x)\<close> by blast},
@{lemma \<open>(\<And>x x'. x = x' \<Longrightarrow> P x = Q x') \<Longrightarrow> (\<forall>x. P x = Q x)\<close> by blast}]
val bind_thms_same_name =
[@{lemma \<open>(\<And>x. P x = Q x) \<Longrightarrow> (\<forall>x. P x) = (\<forall>y. Q y)\<close> by blast},
@{lemma \<open>(\<And>x. P x = Q x) \<Longrightarrow> (\<exists>x. P x) = (\<exists>y. Q y)\<close> by blast},
@{lemma \<open>(\<And>x. P x = Q x) \<Longrightarrow> (\<exists>x. P x = Q x)\<close> by blast},
@{lemma \<open>(\<And>x. P x = Q x) \<Longrightarrow> (\<forall>x. P x = Q x)\<close> by blast}]
fun bind_quants ctxt args t =
combine_quant ctxt (map extract_bind_names args) (extract_quantified_names t)
fun generalize_prems_q [] prems = prems
| generalize_prems_q (_ :: quants) prems =
generalize_prems_q quants (@{thm spec} OF [prems])
fun generalize_prems t = generalize_prems_q (fst (extract_quantified_names_ba t))
fun bind ctxt [prems] args t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
bind_quants ctxt args t THEN' TRY' (SOLVED' (resolve_tac ctxt [generalize_prems t prems]
THEN_ALL_NEW TRY' (assume_tac ctxt ORELSE' resolve_tac ctxt @{thms refl}))))
| bind ctxt thms _ t = replay_error ctxt "invalid bind application" Bind thms t
(* Congruence/Refl *)
fun cong name ctxt thms = try_provers name ctxt
(string_of_verit_rule Cong) [
("basic", SMT_Replay_Methods.cong_basic ctxt thms),
("unfolding then reflexivity", SMT_Replay_Methods.cong_unfolding_trivial ctxt thms),
("unfolding then auto", SMT_Replay_Methods.cong_unfolding_first ctxt thms),
("full", SMT_Replay_Methods.cong_full ctxt thms)] thms
fun refl name ctxt thm t =
(case find_first (fn thm => t = Thm.full_prop_of thm) thm of
SOME thm => thm
| NONE =>
(casetry (fn t => SMT_Replay_Methods.match_instantiate ctxt t @{thm refl}) t of
NONE => cong name ctxt thm t
| SOME thm => thm))
(* Instantiation *)
local fun dropWhile _ [] = []
| dropWhile f (x :: xs) = if f x then dropWhile f xs else x :: xs in
fun forall_inst ctxt _ _ insts t = let fun instantiate_and_solve i ({context = ctxt, prems = [prem], ...}: Subgoal.focus) = let val t = Thm.prop_of prem val quants = t
|> SMT_Replay_Methods.dest_prop
|> extract_forall_quantified_names_q val insts = map (Symtab.lookup insts o fst) (rev quants)
|> dropWhile (curry (op =) NONE)
|> rev fun option_map _ NONE = NONE
| option_map f (SOME a) = SOME (f a) fun instantiate_with inst prem =
Drule.infer_instantiate' ctxt [NONE, inst] @{thm spec} OF [prem] val inst_thm =
fold instantiate_with
(map (option_map (Thm.cterm_of ctxt)) insts)
prem in
(Method.insert_tac ctxt [inst_thm] THEN' TRY' (fn i => assume_tac ctxt i) THEN' TRY' (partial_simplify_tac ctxt @{thms eq_commute ac_simps}) THEN' TRY' (blast_tac ctxt)) i end
| instantiate_and_solve _ ({context = ctxt, prems = thms, ...}: Subgoal.focus) =
replay_error ctxt "invalid application" Forall_Inst thms t in
SMT_Replay_Methods.prove ctxt t (fn _ =>
match_tac ctxt [@{thm disj_not1} RSN (1, @{thm iffD2}) OF [@{thm impI}]] THEN' (fn i => Subgoal.FOCUS (instantiate_and_solve i) ctxt i)) end end
(* Or *)
funor _ (thm :: _) _ = thm
| or ctxt thms t = replay_error ctxt "invalid bind application"Or thms t
(* Implication *)
val implies_pos_thm =
[@{lemma \<open>\<not>(A \<longrightarrow> B) \<or> \<not>A \<or> B\<close> by blast},
@{lemma \<open>\<not>(\<not>A \<longrightarrow> B) \<or> A \<or> B\<close> by blast}]
fun implies_pos ctxt _ t = SMT_Replay_Methods.prove ctxt t (fn _ =>
resolve_tac ctxt implies_pos_thm)
(* Skolemization *)
local fun split _ [] = ([], [])
| split f (a :: xs) =
split f xs
|> (if f a then apfst (curry (op ::) a) else apsnd (curry (op ::) a)) in fun extract_rewrite_rule_assumption _ thms = let fun is_rewrite_rule thm =
(case Thm.prop_of thm of
\<^term>\<open>Trueprop\<close> $ (Const(\<^const_name>\<open>HOL.eq\<close>, _) $ _ $ Free(_, _)) => true
| _ => false) fun is_context_rule thm =
(case Thm.prop_of thm of
\<^term>\<open>Trueprop\<close> $ (Const(\<^const_name>\<open>HOL.eq\<close>, _) $ Free(_, _) $ Free(_, _)) => true
| _ => false) val (ctxt_eq, other) =
thms
|> split is_context_rule val (rew, other) =
other
|> split is_rewrite_rule in
(ctxt_eq, rew, other) end end (* Withoutcompression,wehavetorewriteskolemsonlyonce.However,itcanhappenthanthesame skolemconstantisusedmultipletimeswithadifferentnameundertheforall.
Forstrictness,weusethemultiplerewritingonlywhencompressingisactivated.
*)
local fun rewrite_all_skolems thm_indirect ctxt ((v,SOME thm) :: thms) = let val rewrite_sk_thms = List.mapPartial (fn tm => SOME (tm OF [thm]) handle THM _ => NONE) thm_indirect val multiple_rew = if SMT_Config.compress_verit_proofs ctxt then REPEAT_CHANGED else fn x => x in
multiple_rew (EqSubst.eqsubst_tac ctxt [0] rewrite_sk_thms THEN' SOLVED' (K (HEADGOAL (partial_simplify_tac ctxt (@{thms eq_commute}))))) THEN' rewrite_all_skolems thm_indirect ctxt thms end
| rewrite_all_skolems thm_indirect ctxt ((_,NONE) :: thms) = rewrite_all_skolems thm_indirect ctxt thms
| rewrite_all_skolems _ _ [] = K (all_tac)
fun extract_var_name (thm :: thms) = letval name = Thm.concl_of thm
|> SMT_Replay_Methods.dest_prop
|> HOLogic.dest_eq
|> fst
|> (fn Const(_,_) $ Abs(name, _, _) => [(name,@{thm sym} OF [thm])]
| _ => []) in name :: extract_var_name thms end
| extract_var_name [] = []
fun skolem_tac extractor thm1 thm2 ctxt thms t = let val (ctxt_eq, ts, other) = extract_rewrite_rule_assumption ctxt thms
fun ordered_definitions () = let val var_order = extractor t val thm_names_with_var = extract_var_name ts |> flat inmap (fn v => (v, AList.lookup (op =) thm_names_with_var v)) var_order end in
SMT_Replay_Methods.prove ctxt t (fn _ =>
K (unfold_tac ctxt ctxt_eq) THEN' rewrite_all_skolems thm2 ctxt (ordered_definitions ()) THEN' (eqsubst_all ctxt (map (fn thm => thm RS sym) other))
THEN_ALL_NEW TRY' (resolve_tac ctxt @{thms refl}) THEN' K (unfold_tac ctxt ctxt_eq) THEN' TRY' (partial_simplify_tac ctxt (@{thms eq_commute}))) end in
val skolem_forall =
skolem_tac extract_all_forall_exists_quantified_names_q @{thm verit_sko_forall_indirect}
@{thms verit_sko_forall_indirect2 verit_sko_ex_indirect2}
val skolem_ex =
skolem_tac extract_all_forall_exists_quantified_names_q @{thm verit_sko_ex_indirect}
@{thms verit_sko_ex_indirect2 verit_sko_forall_indirect2}
end
fun eq_reflexive ctxt _ t = SMT_Replay_Methods.match_instantiate ctxt t @{thm refl}
local fun not_not_prove ctxt _ =
K (unfold_tac ctxt @{thms not_not}) THEN' match_tac ctxt @{thms verit_or_simplify_1}
fun duplicate_literals_prove ctxt prems =
Method.insert_tac ctxt prems THEN' match_tac ctxt @{thms ccontr} THEN' K (unfold_tac ctxt @{thms de_Morgan_disj not_not}) THEN' TRY o CHANGED_PROP o REPEAT_ALL_NEW (ematch_tac ctxt @{thms conjE}) THEN' CHANGED_PROP o REPEAT_ALL_NEW (ematch_tac ctxt @{thms disjE}) THEN' REPEAT' (ematch_tac ctxt @{thms notE} THEN' TRY' (assume_tac ctxt))
val theory_resolution2_lemma = @{lemma \<open>a \<Longrightarrow> a = b \<Longrightarrow> b\<close> by blast}
in
fun prove_abstract abstracter tac ctxt thms t = let val thms = map (Conv.fconv_rule Thm.eta_long_conversion) thms val t' = Thm.eta_long_conversion (Object_Logic.dest_judgment ctxt (Thm.cterm_of ctxt t)) val (_, t2) = Logic.dest_equals (Thm.prop_of t') val thm =
SMT_Replay_Methods.prove_abstract ctxt thms t2 tac (
fold_map (abstracter o SMT_Replay_Methods.dest_thm) thms ##>>
abstracter (SMT_Replay_Methods.dest_prop t2)) in
@{thm verit_Pure_trans} OF [t', thm] end
val not_not = prove_abstract SMT_Replay_Methods.abstract_bool_shallow not_not_prove
val tautological_clause =
prove_abstract SMT_Replay_Methods.abstract_bool_shallow tautological_clause_prove
val duplicate_literals =
prove_abstract SMT_Replay_Methods.abstract_bool_shallow duplicate_literals_prove
val unit_res = prove_abstract SMT_Replay_Methods.abstract_bool_shallow SMT_Replay_Methods.prop_tac
(*match_instantiate does not work*) fun theory_resolution2 ctxt prems t =
SMT_Replay_Methods.prove ctxt t (fn _ => match_tac ctxt [theory_resolution2_lemma OF prems])
end
fun normalized_input ctxt prems t = SMT_Replay_Methods.prove ctxt t (fn _ =>
Method.insert_tac ctxt prems THEN' TRY' (K (unfold_tac ctxt @{thms SMT.trigger_def})) THEN' TRY' (partial_simplify_tac ctxt @{thms eq_commute}))
val false_rule_thm = @{lemma \<open>\<not>False\<close> by blast}
fun false_rule ctxt _ t = SMT_Replay_Methods.match_instantiate ctxt t false_rule_thm
(* Transitivity *)
val trans_bool_thm =
@{lemma \<open>P = Q \<Longrightarrow> Q \<Longrightarrow> P\<close> by blast}
fun trans ctxt thms t = let val prop_of = HOLogic.dest_Trueprop o Thm.full_prop_of fun combine_thms [thm1, thm2] =
(case (prop_of thm1, prop_of thm2) of
((Const(\<^const_name>\<open>HOL.eq\<close>, _) $ t1 $ t2),
(Const(\<^const_name>\<open>HOL.eq\<close>, _) $ t3 $ t4)) => if t2 aconv t3 then thm1 RSN (1, thm2 RSN (2, @{thm trans})) elseif t2 aconv t4 then thm1 RSN ((1, ((thm2 RS sym)) RSN (2, @{thm trans}))) elseif t1 aconv t4 then thm2 RSN (1, thm1 RSN (2, @{thm trans})) elseraise Fail "invalid trans theorem"
| _ => trans_bool_thm OF [thm1, thm2])
| combine_thms (thm1 :: thm2 :: thms) =
combine_thms (combine_thms [thm1, thm2] :: thms)
| combine_thms thms = replay_error ctxt "invalid bind application" Trans thms t val t' = Thm.eta_long_conversion (Object_Logic.dest_judgment ctxt (Thm.cterm_of ctxt t)) val (_, t2) = Logic.dest_equals (Thm.prop_of t') val thms = map (Conv.fconv_rule Thm.eta_long_conversion) thms val trans_thm = combine_thms thms in
(case (prop_of trans_thm, t2) of
((Const(\<^const_name>\<open>HOL.eq\<close>, _) $ t1 $ _),
(Const(\<^const_name>\<open>HOL.eq\<close>, _) $ t3 $ _)) => if t1 aconv t3 then trans_thm else trans_thm RS sym
| _ => trans_thm (*to be on the safe side*)) end
fun and_pos ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
REPEAT_CHANGED (resolve_tac ctxt @{thms verit_and_pos}) THEN' TRY' (assume_tac ctxt))
end
(* Equivalence Transformation *)
local fun prove_equiv equiv_thm ctxt [thm] t = SMT_Replay_Methods.prove ctxt t (fn _ =>
Method.insert_tac ctxt [equiv_thm OF [thm]] THEN' TRY' (assume_tac ctxt))
| prove_equiv _ ctxt thms t = replay_error ctxt "invalid application in some equiv rule" Unsupported thms t in
val not_equiv1 = prove_equiv @{lemma \<open>\<not>(A \<longleftrightarrow> B) \<Longrightarrow> A \<or> B\<close> by blast} val not_equiv2 = prove_equiv @{lemma \<open>\<not>(A \<longleftrightarrow> B) \<Longrightarrow> \<not>A \<or> \<not>B\<close> by blast} val equiv1 = prove_equiv @{lemma \<open>(A \<longleftrightarrow> B) \<Longrightarrow> \<not>A \<or> B\<close> by blast} val equiv2 = prove_equiv @{lemma \<open>(A \<longleftrightarrow> B) \<Longrightarrow> A \<or> \<not>B\<close> by blast} val not_implies1 = prove_equiv @{lemma \<open>\<not>(A \<longrightarrow> B) \<Longrightarrow> A\<close> by blast} val not_implies2 = prove_equiv @{lemma \<open>\<not>(A \<longrightarrow>B) \<Longrightarrow> \<not>B\<close> by blast}
end
(* Equivalence Lemma *) (*equiv_pos2 is very important for performance. We have tried various tactics, including aspecialisationofSMT_Replay_Methods.match_instantiate,butthereneverwasameasurable
and consistent gain.*)
local fun prove_equiv_pos_neg2 thm ctxt _ t =
SMT_Replay_Methods.match_instantiate ctxt t thm in
val equiv_pos1_thm = @{lemma \<open>\<not>(a \<longleftrightarrow> b) \<or> a \<or> \<not>b\<close> by blast+} val equiv_pos1 = prove_equiv_pos_neg2 equiv_pos1_thm
val equiv_pos2_thm = @{lemma \<open>\<And>a b. (a \<noteq> b) \<or> \<not>a \<or> b\<close> by blast+} val equiv_pos2 = prove_equiv_pos_neg2 equiv_pos2_thm
val equiv_neg1_thm = @{lemma \<open>(a \<longleftrightarrow> b) \<or> \<not>a \<or> \<not>b\<close> by blast+} val equiv_neg1 = prove_equiv_pos_neg2 equiv_neg1_thm
val equiv_neg2_thm = @{lemma \<open>(a \<longleftrightarrow> b) \<or> a \<or> b\<close> by blast} val equiv_neg2 = prove_equiv_pos_neg2 equiv_neg2_thm
end
local fun implies_pos_neg_term ctxt thm (\<^term>\<open>Trueprop\<close> $
(\<^term>\<open>HOL.disj\<close> $ (\<^term>\<open>HOL.implies\<close> $ a $ b) $ _)) =
Drule.infer_instantiate' ctxt (map (SOME o Thm.cterm_of ctxt) [a, b]) thm
| implies_pos_neg_term ctxt thm t =
replay_error ctxt "invalid application in Implies" Unsupported [thm] t
fun prove_implies_pos_neg thm ctxt _ t = letval thm = implies_pos_neg_term ctxt thm t in
SMT_Replay_Methods.prove ctxt t (fn _ =>
Method.insert_tac ctxt [thm] THEN' TRY' (assume_tac ctxt)) end in
val implies_neg1_thm = @{lemma \<open>(a \<longrightarrow> b) \<or> a\<close> by blast} val implies_neg1 = prove_implies_pos_neg implies_neg1_thm
val implies_neg2_thm = @{lemma \<open>(a \<longrightarrow> b) \<or> \<not>b\<close> by blast} val implies_neg2 = prove_implies_pos_neg implies_neg2_thm
val implies_thm = @{lemma \<open>(a \<longrightarrow> b) \<Longrightarrow> \<not>a \<or> b\<close> by blast} fun implies_rules ctxt prems t = SMT_Replay_Methods.prove ctxt t (fn _ =>
Method.insert_tac ctxt [implies_thm OF prems] THEN' TRY' (assume_tac ctxt))
end
(* BFun *)
local val bfun_theorems = @{thms verit_bfun_elim} in
fun bfun_elim ctxt prems t = SMT_Replay_Methods.prove ctxt t (fn _ =>
Method.insert_tac ctxt prems THEN' TRY' (eqsubst_all ctxt bfun_theorems) THEN' TRY' (simplify_tac ctxt @{thms eq_commute all_conj_distrib ex_disj_distrib}))
end
(* If-Then-Else *)
local fun prove_ite ite_thm thm ctxt =
resolve_tac ctxt [ite_thm OF [thm]] THEN' TRY' (assume_tac ctxt) in
val ite_pos1_thm =
@{lemma \<open>\<not>(if x then P else Q) \<or> x \<or> Q\<close> by auto}
fun ite_pos1 ctxt _ t = SMT_Replay_Methods.prove ctxt t (fn _ =>
resolve_tac ctxt [ite_pos1_thm])
val ite_pos2_thms =
@{lemma \<open>\<not>(if x then P else Q) \<or> \<not>x \<or> P\<close> \<open>\<not>(if \<not>x then P else Q) \<or> x \<or> P\<close> by auto}
fun ite_pos2 ctxt _ t = SMT_Replay_Methods.prove ctxt t (fn _ => resolve_tac ctxt ite_pos2_thms)
val ite_neg1_thms =
@{lemma \<open>(if x then P else Q) \<or> x \<or> \<not>Q\<close> \<open>(if x then P else \<not>Q) \<or> x \<or> Q\<close> by auto}
fun ite_neg1 ctxt _ t = SMT_Replay_Methods.prove ctxt t (fn _ => resolve_tac ctxt ite_neg1_thms)
val ite_neg2_thms =
@{lemma \<open>(if x then P else Q) \<or> \<not>x \<or> \<not>P\<close> \<open>(if \<not>x then P else Q) \<or> x \<or> \<not>P\<close>
\<open>(if x then \<not>P else Q) \<or> \<not>x \<or> P\<close> \<open>(if \<not>x then \<not>P else Q) \<or> x \<or> P\<close>
by auto}
fun ite_neg2 ctxt _ t = SMT_Replay_Methods.prove ctxt t (fn _ => resolve_tac ctxt ite_neg2_thms)
val ite1_thm =
@{lemma \<open>(if x then P else Q) \<Longrightarrow> x \<or> Q\<close> by (auto split: if_splits) }
fun ite1 ctxt [thm] t = SMT_Replay_Methods.prove ctxt t (fn _ => prove_ite ite1_thm thm ctxt)
val ite2_thm =
@{lemma \<open>(if x then P else Q) \<Longrightarrow> \<not>x \<or> P\<close> by (auto split: if_splits) }
fun ite2 ctxt [thm] t = SMT_Replay_Methods.prove ctxt t (fn _ => prove_ite ite2_thm thm ctxt)
val not_ite1_thm =
@{lemma \<open>\<not>(if x then P else Q) \<Longrightarrow> x \<or> \<not>Q\<close> by (auto split: if_splits) }
fun not_ite1 ctxt [thm] t = SMT_Replay_Methods.prove ctxt t (fn _ => prove_ite not_ite1_thm thm ctxt)
val not_ite2_thm =
@{lemma \<open>\<not>(if x then P else Q) \<Longrightarrow> \<not>x \<or> \<not>P\<close> by (auto split: if_splits) }
fun not_ite2 ctxt [thm] t = SMT_Replay_Methods.prove ctxt t (fn _ => prove_ite not_ite2_thm thm ctxt)
(*ite_intro can introduce new terms that are in the proof exactly the sames as the old one, but are
not internally, hence the possible reordering.*) fun ite_intro ctxt _ t = let fun simplify_ite ctxt thms =
ctxt
|> empty_simpset
|> put_simpset HOL_basic_ss
|> Simplifier.add_simps (thms @ @{thms if_True if_False refl simp_thms if_cancel})
|> Simplifier.add_eqcong @{thm verit_ite_if_cong}
|> Simplifier.full_simp_tac in
SMT_Replay_Methods.prove ctxt t (fn _ => simplify_ite ctxt [] THEN' TRY' (simplify_ite ctxt @{thms eq_commute})) end end
(* Quantifiers *)
local val rm_unused = @{lemma \<open>(\<forall>x. P) = P\<close> \<open>(\<exists>x. P) = P\<close> by blast+}
fun qnt_cnf_tac ctxt =
simplify_tac ctxt @{thms de_Morgan_conj de_Morgan_disj imp_conv_disj
iff_conv_conj_imp if_bool_eq_disj ex_simps all_simps ex_disj_distrib
verit_connective_def(3) all_conj_distrib} THEN' TRY' (Blast.blast_tac ctxt) in fun qnt_rm_unused ctxt _ t = SMT_Replay_Methods.prove ctxt t (fn _ =>
K (unfold_tac ctxt rm_unused))
fun qnt_join ctxt _ t = SMT_Replay_Methods.prove ctxt t Classical.fast_tac
fun qnt_cnf ctxt _ t = SMT_Replay_Methods.prove ctxt t qnt_cnf_tac
fun qnt_simplify ctxt _ t = SMT_Replay_Methods.prove ctxt t (fn _ =>
partial_simplify_tac ctxt [])
end
(* Equality *)
fun eq_transitive ctxt _ t = SMT_Replay_Methods.prove ctxt t (fn _ =>
REPEAT_CHANGED (resolve_tac ctxt [@{thm disj_not1} RSN (1, @{thm iffD2}) OF @{thms impI}]) THEN' REPEAT' (resolve_tac ctxt @{thms impI}) THEN' REPEAT' (eresolve_tac ctxt @{thms conjI}) THEN' REPEAT' (fn i => dresolve_tac ctxt @{thms verit_eq_transitive} i THEN assume_tac ctxt (i+1)) THEN' resolve_tac ctxt @{thms refl})
local fun find_rew rews t t' =
(case AList.lookup (op =) rews (t, t') of
SOME thm => SOME (thm COMP @{thm symmetric})
| NONE =>
(case AList.lookup (op =) rews (t', t) of
SOME thm => SOME thm
| NONE => NONE))
fun eq_pred_conv rews t ctxt ctrm =
(case find_rew rews t (Thm.term_of ctrm) of
SOME thm => Conv.rewr_conv thm ctrm
| NONE =>
(case t of
f $ arg =>
(Conv.fun_conv (eq_pred_conv rews f ctxt) then_conv
Conv.arg_conv (eq_pred_conv rews arg ctxt)) ctrm
| Abs (_, _, f) => Conv.abs_conv (eq_pred_conv rews f o snd) ctxt ctrm
| _ => Conv.all_conv ctrm))
fun eq_pred_rewrite_tac ({context = ctxt, prems, concl, ...}: Subgoal.focus) = let val rews = prems
|> map_filter (try (apfst (HOLogic.dest_eq o Thm.term_of o Object_Logic.dest_judgment ctxt o
Thm.cconcl_of) o `(fn x => x)))
|> map (apsnd (fn x => @{thm eq_reflection} OF [x])) fun conv_left conv = Conv.arg_conv (Conv.arg_conv conv) fun conv_left_neg conv = Conv.arg_conv (Conv.arg_conv (Conv.arg_conv conv)) val (t1, conv_term) =
(case Thm.term_of (Object_Logic.dest_judgment ctxt concl) of Const(_, _) $ (Const(\<^const_name>\<open>HOL.Not\<close>, _) $ t1) $ _ => (t1, conv_left)
| Const(_, _) $ t1 $ (Const(\<^const_name>\<open>HOL.Not\<close>, _) $ _) => (t1, conv_left_neg)
| Const(_, _) $ t1 $ _ => (t1, conv_left)
| t1 => (t1, conv_left)) fun throwing_CONVERSION cv i st = Seq.single (Conv.gconv_rule cv i st) in
throwing_CONVERSION (conv_term (eq_pred_conv rews t1 ctxt)) end in
fun subproof ctxt [prem] t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
(REPEAT' (resolve_tac ctxt [@{thm disj_not1} RSN (1, @{thm iffD2}) OF [@{thm impI}],
@{thm disj_not1[of \<open>\<not>_\<close>, unfolded not_not]} RSN (1, @{thm iffD2}) OF [@{thm impI}]]) THEN' resolve_tac ctxt [prem]
THEN_ALL_NEW assume_tac ctxt THEN' TRY' (assume_tac ctxt))
ORELSE' TRY' (Method.insert_tac ctxt [prem] THEN' Blast.blast_tac ctxt))
| subproof ctxt prems t =
replay_error ctxt "invalid application, only one assumption expected" Subproof prems t
(* Simplifying Steps *)
(* The reconstruction is a bit tricky: At first we only rewrite only based on the rules that are passedasargument.Thenwesimplyusesimp_thmstoreconstructalltheproofs(andthesetheorems coverallthesimplificationbelow).
*)
local fun rewrite_only_thms ctxt thms =
ctxt
|> empty_simpset
|> put_simpset HOL_basic_ss
|> Simplifier.add_simps thms
|> Simplifier.full_simp_tac fun rewrite_only_thms_tmp ctxt thms =
rewrite_only_thms ctxt thms THEN' TRY' (K (Clasimp.auto_tac ctxt)) (*TODO: TEMP until cvc5 produces fine grained simplification steps *)
val imp_refl = @{lemma \<open>(P \<longrightarrow> P) = True\<close> by blast}
in fun rewrite_bool_simplify ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
(chain_rewrite_thms ctxt @{thms verit_bool_simplify}))
fun rewrite_and_simplify ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
(chain_rewrite_two_step_with_ac_simps ctxt @{thms verit_and_simplify verit_and_simplify1}
@{thms verit_and_simplify}))
fun rewrite_or_simplify ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
(chain_rewrite_two_step_with_ac_simps ctxt @{thms verit_or_simplify verit_or_simplify_1}
@{thms verit_or_simplify}) THEN' TRY' (REPEAT' (match_tac ctxt @{thms verit_and_pos}) THEN' assume_tac ctxt))
fun rewrite_not_simplify ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
(rewrite_only_thms_tmp ctxt @{thms verit_not_simplify}))
fun rewrite_equiv_simplify ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
(rewrite_only_thms_tmp ctxt @{thms verit_equiv_simplify}))
fun rewrite_eq_simplify ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
(chain_rewrite_two_step_with_ac_simps ctxt
@{thms verit_eq_simplify}
(Named_Theorems.get ctxt @{named_theorems ac_simps})))
fun rewrite_implies_simplify ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
(rewrite_only_thms_tmp ctxt @{thms verit_implies_simplify}))
(* It is more efficient to first fold the implication symbols. Thatishowevernotenoughwhensymbolsappearswithin expressions,hencewealsounfoldimplicationsinthe
other direction. *) fun rewrite_connective_def ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
chain_rewrite_thms_two_step ctxt
(imp_refl :: @{thms not_not verit_connective_def[symmetric]})
(@{thms verit_connective_def[symmetric]})
(imp_refl :: @{thms not_not verit_connective_def})
(@{thms verit_connective_def}))
fun rewrite_minus_simplify ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
chain_rewrite_two_step_with_ac_simps ctxt
@{thms arith_simps verit_minus_simplify}
(Named_Theorems.get ctxt @{named_theorems ac_simps} @
@{thms numerals arith_simps arith_special
numeral_class.numeral.numeral_One}))
fun rewrite_comp_simplify ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
chain_rewrite_thms ctxt @{thms verit_comp_simplify})
fun rewrite_ite_simplify ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
(rewrite_only_thms_tmp ctxt @{thms verit_ite_simplify})) end
(* Simplifications *)
local fun simplify_arith ctxt thms = partial_simplify_tac ctxt
(thms @ Named_Theorems.get ctxt @{named_theorems ac_simps} @ @{thms arith_simps}) in
fun sum_simplify ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
simplify_arith ctxt @{thms verit_sum_simplify arith_special} THEN' TRY' (K (Clasimp.auto_tac ctxt))) (*TODO: TEMP until cvc5 produces fine grained simplification steps *)
fun prod_simplify ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ =>
simplify_arith ctxt @{thms verit_prod_simplify} THEN' TRY' (K (Clasimp.auto_tac ctxt))) (*TODO: TEMP until cvc5 produces fine grained simplification steps *) end
fun all_simplify ctxt _ t =
SMT_Replay_Methods.prove ctxt t (fn _ => TRY' (K (Clasimp.auto_tac ctxt))) (*TODO: TEMP until cvc5 produces fine grained simplification steps *)
(* Arithmetics *)
local
val la_rw_eq_thm = @{lemma \<open>(a :: nat) = b \<or> (a \<le> b) \<or> (a \<ge> b)\<close> by auto} in fun la_rw_eq ctxt _ t = SMT_Replay_Methods.match_instantiate ctxt t la_rw_eq_thm
fun la_generic_prove args ctxt _ = SMT_Replay_Arith.la_farkas args ctxt
fun lia_generic ctxt _ t =
SMT_Replay_Methods.prove_arith_rewrite SMT_Replay_Methods.abstract_neq ctxt t
fun la_disequality ctxt _ t =
SMT_Replay_Methods.match_instantiate ctxt t @{thm verit_la_disequality}
end
(* Symm and Not_Symm*)
local fun prove_symm symm_thm ctxt [thm] t = SMT_Replay_Methods.prove ctxt t (fn _ =>
Method.insert_tac ctxt [symm_thm OF [thm]] THEN' TRY' (assume_tac ctxt))
| prove_symm _ ctxt thms t = replay_error ctxt "invalid application in some symm rule" Unsupported thms t in val symm_thm =
@{lemma \<open>(B = A) \<Longrightarrow> A = B\<close> by blast } val symm = prove_symm symm_thm
val not_symm_thm =
@{lemma \<open>\<not>(B = A) \<Longrightarrow> \<not>(A = B)\<close> by blast } val not_symm = prove_symm not_symm_thm end
(* Reordering *)
local fun prove_reordering ctxt [thm] t = SMT_Replay_Methods.prove ctxt t (fn _ =>(
Method.insert_tac ctxt [thm] THEN' match_tac ctxt @{thms ccontr} THEN' K (unfold_tac ctxt @{thms de_Morgan_disj}) THEN' TRY o CHANGED_PROP o REPEAT_ALL_NEW (ematch_tac ctxt @{thms conjE}) THEN' CHANGED_PROP o REPEAT_ALL_NEW (ematch_tac ctxt @{thms disjE}) THEN' REPEAT'(ematch_tac ctxt @{thms notE} THEN' TRY' (assume_tac ctxt))
))
| prove_reordering ctxt thms t =
replay_error ctxt "invalid application in some reordering rule" Unsupported thms t in val reordering = prove_reordering end
end;
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet am 2026-06-10)
¤
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.