The finish
family of tactics #
These tactics do straightforward things: they call the simplifier, split conjunctive assumptions, eliminate existential quantifiers on the left, and look for contradictions. They rely on ematching and congruence closure to try to finish off a goal at the end.
The procedures do split on disjunctions and recreate the smt state for each terminal call, so they are only meant to be used on small, straightforward problems.
Main definitions #
We provide the following tactics:
finish
-- solves the goal or failsclarify
-- makes as much progress as possible while not leaving more than one goalsafe
-- splits freely, finishes off whatever subgoals it can, and leaves the rest
All accept an optional list of simplifier rules, typically definitions that should be expanded. (The equations and identities should not refer to the local context.)
Utilities #
Configuration information for the auto tactics.
(use_simp := tt)
: call the simplifier(max_ematch_rounds := 20)
: for the "done" tactic
Instances for auto.auto_config
- auto.auto_config.has_sizeof_inst
- auto.auto_config.inhabited
Preprocess goal. #
We want to move everything to the left of the sequent arrow. For intuitionistic logic,
we replace the goal p
with ∀ f, (p → f) → f
and introduce.
Normalize hypotheses #
Bring conjunctions to the outside (for splitting),
bring universal quantifiers to the outside (for ematching). The classical normalizer
eliminates a → b
in favor of ¬ a ∨ b
.
For efficiency, we push negations inwards from the top down. (For example, consider
simplifying ¬ ¬ (p ∨ q)
.)
Equations
- auto.common_normalize_lemma_names = [name.mk_string "bex_def" name.anonymous, name.mk_string "forall_and_distrib" name.anonymous, name.mk_string "exists_imp_distrib" name.anonymous, name.mk_string "assoc" (name.mk_string "or" name.anonymous), name.mk_string "comm" (name.mk_string "or" name.anonymous), name.mk_string "left_comm" (name.mk_string "or" name.anonymous), name.mk_string "assoc" (name.mk_string "and" name.anonymous), name.mk_string "comm" (name.mk_string "and" name.anonymous), name.mk_string "left_comm" (name.mk_string "and" name.anonymous)]
Equations
- auto.classical_normalize_lemma_names = auto.common_normalize_lemma_names ++ [name.mk_string "implies_iff_not_or" (name.mk_string "classical" (name.mk_string "auto" name.anonymous))]
Eliminate existential quantifiers #
Substitute if there is a hypothesis x = t
or t = x
#
Split all conjunctions #
Eagerly apply all the preprocessing rules #
Terminal tactic #
Tactics that perform case splits #
- force : auto.case_option
- at_most_one : auto.case_option
- accept : auto.case_option
Instances for auto.case_option
- auto.case_option.has_sizeof_inst
- auto.case_option.inhabited
The main tactics #
interactive versions #
These tactics do straightforward things: they call the simplifier, split conjunctive assumptions, eliminate existential quantifiers on the left, and look for contradictions. They rely on ematching and congruence closure to try to finish off a goal at the end.
The procedures do split on disjunctions and recreate the smt state for each terminal call, so they are only meant to be used on small, straightforward problems.
finish
: solves the goal or failsclarify
: makes as much progress as possible while not leaving more than one goalsafe
: splits freely, finishes off whatever subgoals it can, and leaves the rest
All accept an optional list of simplifier rules, typically definitions that should be expanded.
(The equations and identities should not refer to the local context.) All also accept an optional
list of ematch
lemmas, which must be preceded by using
.