File ‹Tools/SMT/alethe/rare_rewrites/alethe_replay_rare_simplify_methods.ML›
signature ALETHE_REPLAY_RARE_SIMPLIFY_METHODS =
sig
val rare_rewrite: Alethe_Replay_Methods.alethe_tac_step_args
val rare_rec_mode: int Config.T
exception RARE_REPLAY of string
end;
structure Alethe_Replay_RARE_Simplify_Methods: ALETHE_REPLAY_RARE_SIMPLIFY_METHODS =
struct
exception RARE_REPLAY of string
val rare_rec_mode = Attrib.setup_config_int \<^binding>‹rare_rec_mode› (K 0)
val TRY' = Alethe_Replay_Methods.TRY'
val simplify_tac = Alethe_Replay_Methods.simplify_tac
val low = SMT_Config.low
val middle = SMT_Config.middle
val high = SMT_Config.high
fun debug_msg ctxt = SMT_Config.alethe_debug_msg ctxt "alethe_replay_rare"
fun debug_msg_tac' ctxt verbosity str = K (SMT_Config.alethe_debug_msg_tac ctxt "alethe_replay_rare" verbosity str)
fun dest_prop (Const (\<^const_name>‹Trueprop›, _) $ t) = t
| dest_prop t = t
fun evaluate_tac ctxt _ =
debug_msg_tac' ctxt high "evaluate start" THEN'
TRY' (Code_Simp.dynamic_tac ctxt)
THEN' debug_msg_tac' ctxt high "evaluate after Code_Simp.dynamic_tac"
THEN' TRY' (Lin_Arith.tac ctxt)
THEN' debug_msg_tac' ctxt high "evaluate after Linarith"
THEN' TRY' (simplify_tac ctxt (
(Named_Theorems.get ctxt @{named_theorems cvc_evaluate})
@ (Named_Theorems.get ctxt @{named_theorems cvc_evaluate_bv})
))
THEN' debug_msg_tac' ctxt high "evaluate after unfolding cvc_evaluate lemmas"
fun try_evaluate ctxt t =
SMT_Replay_Methods.prove_abstract' ctxt t evaluate_tac
(SMT_Replay_Methods.abstract_for_code_eval ctxt (dest_prop t))
fun try_simp_tac thms ctxt =
TRY' (K (HEADGOAL (simplify_tac ctxt thms)))
THEN' debug_msg_tac' ctxt high "try_simp after (maybe) trying out a subset of lemmas"
THEN' TRY' (K (HEADGOAL (simplify_tac ctxt ((Named_Theorems.get ctxt @{named_theorems cvc_evaluate})))))
THEN' TRY' (K (HEADGOAL (simplify_tac ctxt ((Named_Theorems.get ctxt @{named_theorems rare_simplify_temp})))))
THEN' TRY' (K (HEADGOAL (simplify_tac ctxt @{thms arith_simps alethe_minus_simplify})))
THEN' TRY' (K (HEADGOAL (simplify_tac ctxt ((Named_Theorems.get ctxt @{named_theorems arith_simp_cvc5})))))
THEN' TRY' (K (Clasimp.auto_tac ctxt))
fun try_simp ctxt t thms = SMT_Replay_Methods.prove ctxt t (fn ctxt => try_simp_tac thms ctxt)
fun normalize_list_arg (Const (\<^const_name>‹Alethe_Rare_Nary_Ops.cvc_ListVar.ListVar›, _) $ Const (\<^const_name>‹List.Nil›, _)) t =
(case try hd (dest_Type t |> snd) of
NONE => @{term "ListVar (List.Nil::dummy List.list) :: dummy cvc_ListVar"} |
SOME (t') =>
Const (\<^const_name>‹ListVar›, Type(\<^type_name>‹List.list›, [t']) --> Type(\<^type_name>‹cvc_ListVar›, [t']))
$ Const (\<^const_name>‹List.Nil›, Type(\<^type_name>‹List.list›, [t']))
)
| normalize_list_arg a _ = a
fun rewrite_lemma_inst _ lemma [] [] = lemma
| rewrite_lemma_inst ctxt lemma (a :: args') (t :: typs') =
let
val rec_lemma = rewrite_lemma_inst ctxt lemma args' typs'
val a_normalized = normalize_list_arg a t |> Thm.cterm_of ctxt |> SOME |> single
val res = Drule.infer_instantiate' ctxt a_normalized rec_lemma
in res end
| rewrite_lemma_inst _ lemma _ _ = lemma
fun instantiate_lemma ctxt args lemma =
let
fun get_types lemma = map snd (rev (Term.add_vars (Thm.full_prop_of lemma) []))
val args_terms = rev (Const ("Groups.zero_class.zero", @{typ int}) :: args)
val all_types = rev (get_types lemma)
val args_types_from_lemma = drop (length all_types - length args_terms) all_types
val _ = debug_msg ctxt high (fn () => @{print} ("Argument types extracted from lemma", args_types_from_lemma));
val _ = debug_msg ctxt high (fn () => @{print} ("Arguments ", args_terms));
in rewrite_lemma_inst ctxt lemma args_terms args_types_from_lemma end
fun dsl_tac_initialize rewrite_name args ctxt t prems =
let
val rare_mode = (Config.get ctxt rare_rec_mode)
val _ = debug_msg ctxt high (fn () => @{print} ("rare_rec_mode " ^ Int.toString rare_mode))
in
if rare_mode = 2
then try_simp ctxt t prems
else
(case rewrite_name of
"bool_double_not_elim" => SMT_Replay_Methods.prove ctxt t (fn _ =>
match_tac ctxt [@{thm not_not}])
| "eq_refl" => SMT_Replay_Methods.prove ctxt t (fn _ =>
match_tac ctxt [@{lemma ‹(a=a) = True› by blast}])
| "eq_symm" => SMT_Replay_Methods.prove ctxt t (fn _ =>
match_tac ctxt @{thms eq_commute})
| "distinct_false" => SMT_Replay_Methods.prove ctxt t (fn _ =>
try_simp_tac [] ctxt)
| _ =>
(case CVC5_Rare.rare_lookup (Context.Proof ctxt) ("rewrite_" ^ rewrite_name) of
NONE =>
if rare_mode = 1 then
let
val _ = debug_msg ctxt high (fn () => @{print} ("undeclared RARE rule: " ^ rewrite_name ^ ". Use cvc5_rare \"full_name\"."))
in raise RARE_REPLAY("could not find lemma for rare rewrite " ^ rewrite_name) end
else try_simp ctxt t prems
| SOME rewrite_lemmas =>
let
val _ = debug_msg ctxt middle (fn () => @{print} ("Lemmas corresponding to the current rewrite rule", rewrite_lemmas));
val inst_lemmas = map_filter (try (instantiate_lemma ctxt args)) rewrite_lemmas
val _ = debug_msg ctxt middle (fn () => @{print} ("Instantiated lemmas", inst_lemmas));
val cvc_list_defs = @{thms cvc_list_right_Nil cvc_list_left_Nil cvc_list_both_Singleton
cvc_list_right_Cons cvc_list_left_Cons cvc_list_both_Cons
cvc_list_both_Cons_0 cvc_list_both_Cons_1 NO_MATCH_def}
val inst_lemmas_without_list =
map (Local_Defs.unfold ctxt (cvc_list_defs @ (Named_Theorems.get ctxt @{named_theorems smt_rewrite_lemma_simplify}))) inst_lemmas
val inst_lemmas_without_true
= map (Tactic.rule_by_tactic ctxt (resolve_tac ctxt [@{thm TrueI}] 1)) inst_lemmas_without_list
val _ = debug_msg ctxt middle (fn () => @{print} ("Instantiated lemmas without custom list operators", inst_lemmas_without_true));
val _ = debug_msg ctxt middle (fn () => @{print} ("nr of viable instantiated lemmas", length inst_lemmas_without_true));
val cvc_evaluate_thms = Named_Theorems.get ctxt @{named_theorems cvc_evaluate}
fun debug_msg_tac'' ctxt verbosity str = debug_msg_tac' ctxt verbosity ("rare_rewrite: " ^ str)
fun try_lemma_i _ =
(fn t => (SMT_Replay_Methods.prove ctxt t (fn ctxt =>
TRY' (debug_msg_tac'' ctxt high "reconstruct rewrite")
THEN'
((CHANGED_GOAL
(EqSubst.eqsubst_tac ctxt [0] [hd inst_lemmas_without_true] )
THEN' (TRY' (resolve_tac ctxt prems))
THEN' debug_msg_tac'' ctxt high "resolved premise if there was one"
THEN' TRY' (resolve_tac ctxt [@{thm refl}]))
ORELSE'
(fn i => fn st => (if rare_mode = 1
then
(let val _ = debug_msg ctxt middle (fn () => @{print}("lemma,goal", (hd inst_lemmas_without_true, Thm.cterm_of ctxt t)));in (K no_tac) end)
else try_simp_tac prems ctxt) i st))
THEN_ALL_NEW (
debug_msg_tac'' ctxt high "trying to discharge assumption of RARE lemma"
THEN' TRY' (resolve_tac ctxt prems THEN' TRY' (debug_msg_tac'' ctxt high "discharged via alethe premise"))
THEN' TRY' (simplify_tac ctxt cvc_evaluate_thms THEN' TRY' (debug_msg_tac'' ctxt high "simplified goal with cvc_evaluate"))
THEN' TRY'
(simplify_tac ctxt cvc_evaluate_thms
THEN' debug_msg_tac'' ctxt high "simplified goal with cvc_evaluate")
THEN' TRY' (Code_Simp.dynamic_tac ctxt THEN' TRY' (debug_msg_tac'' ctxt high "applied code evaluator")) )
THEN' (debug_msg_tac'' ctxt high "should be solved now")
))) t
in
if not (null inst_lemmas_without_true)
then (if rare_mode = 1 then raise ERROR("Rule could not be used") else try_lemma_i 0)
else (if rare_mode = 0 then try_simp ctxt t prems else raise ERROR("Rule could not be instantiated") )
end))
end
local
fun pretty tag lines = map Pretty.str lines |> Pretty.big_list tag |> Pretty.string_of
in
fun rare_rewrite ctxt (th : thm list) (x :: args) t =
let
val rewrite_name = String.map (fn #"-" => #"_" | x => x) (HOLogic.dest_string x)
in
(debug_msg ctxt low (fn () => @{print} "Found rare rewrite " ^ rewrite_name);
dsl_tac_initialize rewrite_name args ctxt t th)
handle (RARE_REPLAY msg) => raise (SMT_Failure.SMT (SMT_Failure.Replay("rare-rewrite", ERROR msg)))
end
| rare_rewrite ctxt _ args _ =
(SMT_Config.verbose_msg ctxt (pretty ("No dsl rule found, try to simplify" ^
List.foldr op^ "" (map ML_Syntax.print_term args))) [];
raise (SMT_Failure.SMT (SMT_Failure.Replay("rare-rewrite", ERROR "could not find lemma for rare rewrite"))))
fun evaluate ctxt _ _ = try_evaluate ctxt
end
val rules = [
("rare_rewrite", rare_rewrite),
("evaluate", evaluate)
]
val _ = Theory.setup (Context.theory_map (
fold (uncurry Alethe_Replay_Methods.declare_alethe_rule) rules))
end