Tactics
This page provides an index of the tactics we use in CS 22. It will update over the course of the semester as new tactics are introduced.
Introduction & Elimination Rules
apply
We generally recommend using have, not apply, for implication elimination.
apply h makes use of some hypothesis h (this can be any named hypothesis in your context) and tries to match the current goal against the conclusion (consequent) of h. If it does, then it updates the goal to be the antecedent of h. Note that apply always requires an argument: writing just apply in your proof will produce a syntax error.
For example, if h : p → q, and the goal is q, then apply h changes the goal to p. In other words, apply uses h to "reason" that in order to show q, it suffices to show p.
Note that the proposition q could be complex: as long as it matches the consequent of h, then apply h will succeed. Be sure to be on the lookout for an if-then hypothesis whose consequent matches the conclusion—if its antecedent looks easier to prove than the current goal, then apply is likely a good tactic to try.
assume
The assume tactic applies the introduction rule for implication: given a goal of the form P → Q (where P and Q could be any propositions), writing assume hp will add the hypothesis hp : P to your context and update your goal to be Q. (Recall that this is how we prove implications: we assume the antecedent, then, from that assumption, show the consequent.) On paper, the step taken by assume hp above would probably appear as something like "assume that P is true" or simply "suppose P." Note that names of hypotheses should begin with h (unless they are an inductive hypothesis in an induction proof, in which case they may begin with ih) per our naming conventions.
We also use assume to prove negations via proof by contradiction.1 Given a goal of the form ¬P, executing assume hp will add the hypothesis hp : P to your context and update your goal to be False. In other words, we want to show that supposing P to be true entails an absurd state of affairs (where "an absurd state of affairs" is formalized as "being able to prove False, something we should not be able to prove"), so that P must be false. This mirrors how we prove negations on paper: to show that "P is false," we'll usually write something like, "Assume for the sake of contradiction that P is true. Then [more steps here]. But now we've reached a contradiction, so P must be false." (Notice that we don't explicitly say that we've "proved False;" instead, this is implicit in our arrival at a contradiction. Similarly, in order to prove False in Lean, you'll want to obtain a context that's contradictory, then use the contradiction tactic.)
assumption
If a hypothesis in your context matches the goal exactly, assumption will solve the goal. This tactic can only be used to close a goal, i.e., as the last step in a proof of a given goal. It roughly corresponds to a phrase like "as we've already assumed/shown" in a written proof.
contradiction
The contradiction tactic applies the principle of explosion (sometimes also known by the Latin ex falso quodlibet—roughly, "from falsehood, anything [follows]"): if your context contains "obviously" impossible or contradictory claims, then contradiction can prove any goal (even one that's false). (This step is sometimes implicit in a paper proof, as when one considers some situation, shows that it entails a contradiction, and then deduces that the situation "is impossible"—implicitly discharging one's proof obligation—without explicitly invoking "explosion.") Note that this is implicitly using the elimination rule for falsehood: from contradictory claims, we can derive False; the elimination rule for False then allows us to prove anything. (contradiction combines all of this into a single step.)
Examples of contradictory contexts include any context in which you have hypotheses P and ¬P for some proposition P, as well as hypotheses like 0 = 1 and other definitional impossibilities. Note that contradiction cannot do sophisticated reasoning to deduce a contradiction from existing hypotheses: for instance, if you have hypotheses a > b and a ≤ b, contradiction will not close the goal (since a ≤ b is not syntactically the negation of a > b, even though they are logically equivalent).
eliminate
eliminate applies elimination rules to existing hypotheses in your context. (Recall that elimination rules tell us how we can "use" or "destruct" an existing piece of knowledge of a given form.) The syntax of eliminate is eliminate h with ... where h is the hypothesis you want to "destruct" and the ... is filled in with names to be assigned to any variables or hypotheses generated by the elimination rule (the number and kind of names you supply here is determined by which elimination rule is being applied). Here is a list of common elimination rules that eliminate can apply:
- Conjunction elimination: given a hypothesis
h : p ∧ q,eliminate h with hp hqwill "split apart"hinto hypotheseshp : pandhq : qin your context. - Disjunction elimination ("proof by cases"): given a hypothesis
h : p ∨ q,eliminate h with h1 h2generates two goals, one with a hypothesishp : pand one with a hypothesishq : q. You'll then need to separately show that your original goal holds in each case. - Existential-quantification elimination ("extracting a witness"): if
Tis a type (likeℕorℤ) andPis a predicate, then given a hypothesishex : ∃ x : T, P x,eliminate h with w hwwill replacehexin your context with a valuew : Tand a hypothesishw : P w. Intuitively,hexsays that there's some value out there with propertyP, but you don't know what it is; the elimination rule applied byeliminateallows you to "get your hands on" a specific such valuew(wherehwreflects the fact thatPdoes in fact hold ofw).
Note that eliminate is not used for implication elimination or universal-quantification elimination: for those rules, see the have tactic.
have
The have tactic allows you to add new hypotheses to your context. There are two main usages we'll see in this course:
-
havecan be used to apply the elimination rules for universal quantification and implication, adding the resulting hypothesis to the context.The syntax for implication elimination (also known as modus ponens) is as follows: if your context contains hypotheses
hpq : P → Qandhp : P, thenhave hq : Q := hpq hpwill add the hypothesishq : Qto your context. (On paper, this is analogous to writing "we know that P implies Q, and we also know P, so we can conclude Q by modus ponens.")The syntax for universal-quantification elimination (which corresponds to "instantiating" a universal claim at some particular value) is similar: if
Tis a type (likeℕorℤ) and you have in your context a hypothesishp : ∀ n : T, P nand a valuek : T, thenhave hk : P k := hp kadds the hypothesishk : P kto your context. (This corresponds to an argument like, "we know that property P holds of any (rational/natural/integer) number, so since k is a (rational/natural/integer) number, we know P holds of k.") -
havecan also be used to create a new goal that, once discharged, will be added as a hypothesis to your context. This is a useful way of proving an ancillary result that you want to make use of later in your primary proof. The syntax for this is as follows: writehave hp : P(note the lack of a:=sign); this will create a new topmost goalP. Then use the{ }syntax to focus that goal and prove it. Once you've finished (i.e., after your closing}), you'll now have a new hypothesishp : Pin your context.
left and right
left and right apply the introduction rules for disjunction ("or"). Intuitively, they are used to "target" one side of a disjunctive (∨) proposition in the goal. When presented with a disjunction in your goal, your first instinct should generally be to use left or right to isolate one of the two propositions, then prove that selected goal.
For example, given a goal of p ∨ q, left would make the goal p, while right would make the goal q. This corresponds in a paper proof to reasoning along the lines of, "we need to show that either P holds or Q holds; we'll show that P [or, respectively, Q] holds." When deciding which of left or right to use, look at the two sides of your goal and what hypotheses you have in your context: if one side looks easier to prove than the other, try to prove that side!
split_goal
The split_goal tactic applies the introduction rule for conjunction: if your goal is of the form p ∧ q, then split_goal will turn that into two separate goals p and q. split_goal also applies the introduction rule for bi-implication, turning a goal of p ↔ q into two goals p → q and q → p. (You can think of bi-implication as behaving like the conjunction of these two implications; thus, we use the same tactic for its introduction rule.) split_goal does not apply introduction rules for other connectives (such as disjunction or implication) because those connectives' introduction rules don't correspond to "splitting the goal!"
Working with Numbers
Rewriting and Simplifying
Set Theory
Induction
Footnotes
-
Note that we are using this term slightly differently from what you may see in a logic class. ↩