Documentation

Tactics

The tactic language is a special-purpose programming language for constructing proofs, indicated using the keyword by.

#adaptation_note

#adaptation_note /-- comment -/ adds an adaptation note to the current file. Adaptation notes are comments that are used to indicate that a piece of code has been changed to accommodate a change in Lean core. They typically require further action/maintenance to be taken in the future.

This syntax works as a command, or inline in tactic or term mode.

Tags:
Defined in module:
Mathlib.Tactic.AdaptationNote

#check

#check t elaborates the term t and then pretty prints it with its type as e : ty.

If t is an identifier, then it pretty prints a type declaration form for the global constant t instead. Use #check (t) to pretty print it as an elaborated expression.

Like the #check command, the #check tactic allows stuck typeclass instance problems. These become metavariables in the output.

Tags:
Defined in module:
Mathlib.Tactic.Check

#count_heartbeats

#count_heartbeats tac counts the heartbeats used by the tactic sequence tac and prints an info line with the number of heartbeats.

Example:

example : 1 + 1 = 2 := by
  -- The next line will print an info message of this format; the exact number may vary.
  -- info: 4646
  #count_heartbeats simp

example : 1 + 1 = 2 := by
  -- The next line will print an info message of this format; the exact numbers may vary.
  -- info: Min: 4 Max: 4 StdDev: 2%
  #count_heartbeats! 37 in simp

Tags:
Defined in module:
Mathlib.Util.CountHeartbeats

#find

#find t finds definitions and theorems whose result type matches the term t, and prints them as info lines. Use holes in t to indicate arbitrary subexpressions, for example #find _ ∧ _ will match any conjunction. #find is also available as a command. #find will not affect the goal by itself and should be removed from the finished proof.

There is also the find tactic which looks for lemmas which are applyable against the current goal.

Examples:

#find _ + _ = _ + _
#find ?n + _ = _ + ?n
#find (_ : Nat) + _ = _ + _
#find NatNat

Tags:
Defined in module:
Mathlib.Tactic.Find

abel

abel solves equations in the language of additive, commutative monoids and groups.

abel and its variants work as both tactics and conv tactics.

Examples:

example [AddCommMonoid α] (a b : α) : a + (b + a) = a + a + b := by abel
example [AddCommGroup α] (a : α) : (3 : ℤ) • a = a + (2 : ℤ) • a := by abel

Tags:
Defined in module:
Mathlib.Tactic.Abel

ac_change

ac_change t on a goal ⊢ t' changes the goal to ⊢ t and adds new goals for proving the equality t' = t using congruence, then tries proving these goals by associativity and commutativity. The goals are created like congr! would. In other words, ac_change t is like convert_to t followed by ac_refl.

Like refine e, any holes (?_ or ?x) in t that are not solved by unification are converted into new goals, using the hole's name, if any, as the goal case name. Like congr!, convert_to introduces variables while applying congruence rules. These can be pattern-matched, like rintro would, using the with keyword.

Example:

example (a b c d e f g N : ℕ) : (a + b) + (c + d) + (e + f) + g ≤ N := by
  ac_change a + d + e + f + c + g + b ≤ _
  -- ⊢ a + d + e + f + c + g + b ≤ N

Tags:
Defined in module:
Mathlib.Tactic.Convert

aesop_cat

A thin wrapper for aesop which adds the CategoryTheory rule set and allows aesop to look through semireducible definitions when calling intros. This tactic fails when it is unable to solve the goal, making it suitable for use in auto-params.

Tags:
Defined in module:
Mathlib.CategoryTheory.Category.Basic

aesop_cat?

We also use aesop_cat? to pass along a Try this suggestion when using aesop_cat

Tags:
Defined in module:
Mathlib.CategoryTheory.Category.Basic

aesop_cat_nonterminal

A variant of aesop_cat which does not fail when it is unable to solve the goal. Use this only for exploration! Nonterminal aesop is even worse than nonterminal simp.

Tags:
Defined in module:
Mathlib.CategoryTheory.Category.Basic

aesop_graph

A variant of the aesop tactic for use in the graph library. Changes relative to standard aesop:

Tags:
Defined in module:
Mathlib.Combinatorics.SimpleGraph.Basic

aesop_graph?

Use aesop_graph? to pass along a Try this suggestion when using aesop_graph

Tags:
Defined in module:
Mathlib.Combinatorics.SimpleGraph.Basic

aesop_graph_nonterminal

A variant of aesop_graph which does not fail if it is unable to solve the goal. Use this only for exploration! Nonterminal Aesop is even worse than nonterminal simp.

Tags:
Defined in module:
Mathlib.Combinatorics.SimpleGraph.Basic

aesop_mat

The aesop_mat tactic attempts to prove a set is contained in the ground set of a matroid. It uses a [Matroid] ruleset, and is allowed to fail.

Tags:
Defined in module:
Mathlib.Combinatorics.Matroid.Basic

algebraize

Tactic that, given RingHoms, adds the corresponding Algebra and (if possible) IsScalarTower instances, as well as Algebra corresponding to RingHom properties available as hypotheses.

Example: given f : A →+* B and g : B →+* C, and hf : f.FiniteType, algebraize [f, g] will add the instances Algebra A B, Algebra B C, and Algebra.FiniteType A B.

See the algebraize tag for instructions on what properties can be added.

The tactic also comes with a configuration option properties. If set to true (default), the tactic searches through the local context for RingHom properties that can be converted to Algebra properties. The macro algebraize_only calls algebraize -properties, so in other words it only adds Algebra and IsScalarTower instances.

Tags:
Defined in module:
Mathlib.Tactic.Algebraize

algebraize_only

Version of algebraize, which only adds Algebra instances and IsScalarTower instances, but does not try to add any instances about any properties tagged with @[algebraize], like for example Finite or IsIntegral.

Tags:
Defined in module:
Mathlib.Tactic.Algebraize

apply

apply t at i uses forward reasoning with t at the hypothesis i. Explicitly, if t : α₁ → ⋯ → αᵢ → ⋯ → αₙ and i has type αᵢ, then this tactic adds metavariables/goals for any terms of αⱼ for j = 1, …, i-1, then replaces the type of i with αᵢ₊₁ → ⋯ → αₙ by applying those metavariables and the original i.

Tags:
Defined in module:
Mathlib.Tactic.ApplyAt

apply_fun

Apply a function to an equality or inequality in either a local hypothesis or the goal.

Typical usage is:

open Function

example (X Y Z : Type) (f : X → Y) (g : Y → Z) (H : Injective <| g ∘ f) :
    Injective f := by
  intro x x' h
  apply_fun g at h
  exact H h

The function f is handled similarly to how it would be handled by refine in that f can contain placeholders. Named placeholders (like ?a or ?_) will produce new goals.

Tags:
Defined in module:
Mathlib.Tactic.ApplyFun

apply_gmonoid_gnpowRec_succ_tac

A tactic to for use as an optional value for GMonoid.gnpow_succ'.

Tags:
Defined in module:
Mathlib.Algebra.GradedMonoid

apply_gmonoid_gnpowRec_zero_tac

A tactic to for use as an optional value for GMonoid.gnpow_zero'.

Tags:
Defined in module:
Mathlib.Algebra.GradedMonoid

apply_rewrite

apply_rewrite [rules] is a shorthand for grewrite +implicationHyp [rules].

Tags:
Defined in module:
Mathlib.Tactic.GRewrite.Elab

apply_rw

apply_rw [rules] is a shorthand for grw +implicationHyp [rules].

Tags:
Defined in module:
Mathlib.Tactic.GRewrite.Elab

arith_mult

arith_mult solves goals of the form IsMultiplicative f for f : ArithmeticFunction R by applying lemmas tagged with the user attribute arith_mult.

Tags:
Defined in module:
Mathlib.Tactic.ArithMult

arith_mult?

arith_mult solves goals of the form IsMultiplicative f for f : ArithmeticFunction R by applying lemmas tagged with the user attribute arith_mult, and prints out the generated proof term.

Tags:
Defined in module:
Mathlib.Tactic.ArithMult

assumption'

Try calling assumption on all goals; succeeds if it closes at least one goal.

Tags:
Defined in module:
Mathlib.Tactic.Basic

aux_group₁

Auxiliary tactic for the group tactic. Calls the simplifier only.

Tags:
Defined in module:
Mathlib.Tactic.Group

aux_group₂

Auxiliary tactic for the group tactic. Calls ring_nf to normalize exponents.

Tags:
Defined in module:
Mathlib.Tactic.Group

bddDefault

Sets are automatically bounded or cobounded in complete lattices. To use the same statements in complete and conditionally complete lattices but let automation fill automatically the boundedness proofs in complete lattices, we use the tactic bddDefault in the statements, in the form (hA : BddAbove A := by bddDefault).

Tags:
Defined in module:
Mathlib.Order.Bounds.Basic

beta_reduce

beta_reduce at loc completely beta reduces the given location. This also exists as a conv-mode tactic.

This means that whenever there is an applied lambda expression such as (fun x => f x) y then the argument is substituted into the lambda expression yielding an expression such as f y.

Tags:
Defined in module:
Mathlib.Tactic.DefEqTransformations

bicategory

Use the coherence theorem for bicategories to solve equations in a bicategory, where the two sides only differ by replacing strings of bicategory structural morphisms (that is, associators, unitors, and identities) with different strings of structural morphisms with the same source and target.

That is, bicategory can handle goals of the form a ≫ f ≫ b ≫ g ≫ c = a' ≫ f ≫ b' ≫ g ≫ c' where a = a', b = b', and c = c' can be proved using bicategory_coherence.

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.Bicategory.Basic

bicategory_coherence

Close the goal of the form η.hom = θ.hom, where η and θ are 2-isomorphisms made up only of associators, unitors, and identities.

example {B : Type} [Bicategory B] {a : B} :
  (λ_ (𝟙 a)).hom = (ρ_ (𝟙 a)).hom := by
  bicategory_coherence

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.Bicategory.PureCoherence

bicategory_coherence

Coherence tactic for bicategories. Use pure_coherence instead, which is a frontend to this one.

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.BicategoryCoherence

bicategory_nf

Normalize the both sides of an equality.

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.Bicategory.Basic

bitwise_assoc_tac

Proving associativity of bitwise operations in general essentially boils down to a huge case distinction, so it is shorter to use this tactic instead of proving it in the general case.

Tags:
Defined in module:
Mathlib.Data.Nat.Bitwise

borelize

The behaviour of borelize α depends on the existing assumptions on α.

Finally, borelize α β γ runs borelize α; borelize β; borelize γ.

Tags:
Defined in module:
Mathlib.MeasureTheory.Constructions.BorelSpace.Basic

bound

bound tactic for proving inequalities via straightforward recursion on expression structure.

An example use case is

-- Calc example: A weak lower bound for `z ↦ z^2 + c`
lemma le_sqr_add (c z : ℝ) (cz : ‖c‖ ≤ ‖z‖) (z3 : 3 ≤ ‖z‖) :
    2 * ‖z‖ ≤ ‖z^2 + c‖ := by
  calc ‖z^2 + c‖
    _ ≥ ‖z^2‖ - ‖c‖ := by bound
    _ ≥ ‖z^2‖ - ‖z‖ := by  bound
    _ ≥ (‖z‖ - 1) * ‖z‖ := by
      rw [mul_comm, mul_sub_one, ← pow_two, ← norm_pow]
    _ ≥ 2 * ‖z‖ := by bound

bound is built on top of aesop, and uses

  1. Apply lemmas registered via the @[bound] attribute
  2. Forward lemmas registered via the @[bound_forward] attribute
  3. Local hypotheses from the context
  4. Optionally: additional hypotheses provided as bound [h₀, h₁] or similar. These are added to the context as if by have := hᵢ.

The functionality of bound overlaps with positivity and gcongr, but can jump back and forth between 0 ≤ x and x ≤ y-type inequalities. For example, bound proves 0 ≤ c → b ≤ a → 0 ≤ a * c - b * c by turning the goal into b * c ≤ a * c, then using mul_le_mul_of_nonneg_right. bound also contains lemmas for goals of the form 1 ≤ x, 1 < x, x ≤ 1, x < 1. Conversely, gcongr can prove inequalities for more types of relations, supports all positivity functionality, and is likely faster since it is more specialized (not built atop aesop).

Tags:
Defined in module:
Mathlib.Tactic.Bound

by_cases!

by_cases! h : p runs the by_cases h : p tactic, followed by push_neg at h in the second subgoal. For example,

Tags:
Defined in module:
Mathlib.Tactic.ByCases

by_contra!

If the target of the main goal is a proposition p, by_contra! reduces the goal to proving False using the additional hypothesis this : ¬ p. by_contra! h can be used to name the hypothesis h : ¬ p. The hypothesis ¬ p will be normalized using push_neg. For instance, ¬ a < b will be changed to b ≤ a. by_contra! can be used with rcases patterns. For instance, by_contra! rfl on ⊢ s.Nonempty will substitute the equality s = ∅, and by_contra! ⟨hp, hq⟩ on ⊢ ¬ p ∨ ¬ q will introduce hp : p and hq : q. by_contra! h : q will normalize negations in ¬ p, normalize negations in q, and then check that the two normalized forms are equal. The resulting hypothesis is the pre-normalized form, q. If the name h is not explicitly provided, then this will be used as name. This tactic uses classical reasoning. It is a variant on the tactic by_contra. Examples:

example : 1 < 2 := by
  by_contra! h
  -- h : 2 ≤ 1 ⊢ False

example : 1 < 2 := by
  by_contra! h : ¬ 1 < 2
  -- h : ¬ 1 < 2 ⊢ False

Tags:
Defined in module:
Mathlib.Tactic.ByContra

calc?

Create a calc proof.

Tags:
Defined in module:
Mathlib.Tactic.Widget.Calc

cancel_denoms

cancel_denoms attempts to remove numerals from the denominators of fractions. It works on propositions that are field-valued inequalities.

variable [LinearOrderedField α] (a b c : α)

example (h : a / 5 + b / 4 < c) : 4*a + 5*b < 20*c := by
  cancel_denoms at h
  exact h

example (h : a > 0) : a / 5 > 0 := by
  cancel_denoms
  exact h

Tags:
Defined in module:
Mathlib.Tactic.CancelDenoms.Core

cases'

cases' x, where the variable x has inductive type t, splits the main goal, producing one goal for each constructor of t, in which x is replaced by that constructor applied to newly introduced variables. This is a backwards-compatible variant of the cases tactic in Lean 4 core.

Prefer cases, rcases, or obtain when possible, because these tactics promote structured proofs.

Example:

example (h : p ∨ q) : q ∨ p := by
  cases' h with hp hq
  · exact Or.inr hp
  · exact Or.inl hq

-- Though the following equivalent spellings should be preferred
example (h : p ∨ q) : q ∨ p := by
  cases h with
  | inl hp => exact Or.inr hp
  | inr hq => exact Or.inl hq

example (h : p ∨ q) : q ∨ p := by
  rcases h with hp | hq
  · exact Or.inr hp
  · exact Or.inl hq

Tags:
Defined in module:
Mathlib.Tactic.Cases

cases_first_enat

Finds the first ENat in the context and applies the cases tactic to it. Then simplifies expressions involving using the enat_to_nat_top simp set.

Tags:
Defined in module:
Mathlib.Tactic.ENatToNat

cases_type

cases_type I searches for a hypothesis h : type where I has the form (I ...), and splits the main goal by cases on h. cases_type p fails if no hypothesis type has the identifier I as its head symbol.

Example:

example (h : a ∧ b ∨ c ∧ d) (h2 : e ∧ f) : True := by
  -- The following tactic destructs all conjunctions and disjunctions in the current context.
  cases_type* Or And
  · clear ‹a› ‹b› ‹e› ‹f›; (fail_if_success clear ‹c›); trivial
  · clear ‹c› ‹d› ‹e› ‹f›; trivial

Tags:
Defined in module:
Mathlib.Tactic.CasesM

casesm

casesm p searches for the first hypothesis h : type where type matches the term p, and splits the main goal by cases on h. Use holes in p to indicate arbitrary subexpressions, for example casesm _ ∧ _ will match any conjunction. casesm p fails if no hypothesis type matches p.

Example:

example (h : a ∧ b ∨ c ∧ d) (h2 : e ∧ f) : True := by
  -- The following tactic destructs all conjunctions and disjunctions in the current context.
  casesm* _∨_, _∧_
  · clear ‹a› ‹b› ‹e› ‹f›; (fail_if_success clear ‹c›); trivial
  · clear ‹c› ‹d› ‹e› ‹f›; trivial

Tags:
Defined in module:
Mathlib.Tactic.CasesM

cat_disch

A tactic for discharging easy category theory goals, widely used as an autoparameter. Currently this defaults to the aesop_cat wrapper around aesop, but by setting the option mathlib.tactic.category.grind to true, it will use the grind tactic instead.

Tags:
Defined in module:
Mathlib.CategoryTheory.Category.Basic

cfc_cont_tac

A tactic used to automatically discharge goals relating to the continuous functional calculus, specifically concerning continuity of the functions involved.

Tags:
Defined in module:
Mathlib.Tactic.ContinuousFunctionalCalculus

cfc_tac

A tactic used to automatically discharge goals relating to the continuous functional calculus, specifically whether the element satisfies the predicate.

Tags:
Defined in module:
Mathlib.Tactic.ContinuousFunctionalCalculus

cfc_zero_tac

A tactic used to automatically discharge goals relating to the non-unital continuous functional calculus, specifically concerning whether f 0 = 0.

Tags:
Defined in module:
Mathlib.Tactic.ContinuousFunctionalCalculus

change?

change? term unifies term with the current goal, then suggests explicit change syntax that uses the resulting unified term.

If term is not present, change? suggests the current goal itself. This is useful after tactics which transform the goal while maintaining definitional equality, such as dsimp; those preceding tactic calls can then be deleted.

example : (fun x : Nat => x) 0 = 1 := by
  change? 0 = _  -- `Try this: change 0 = 1`

Tags:
Defined in module:
Mathlib.Tactic.Change

check_compositions

For each composition f ≫ g in the goal, which internally is represented as CategoryStruct.comp C inst X Y Z f g, infer the types of f and g and check whether their sources and targets agree with X, Y, and Z at "instances and reducible" transparency, reporting any discrepancies.

An example:

example (j : J) :
    colimit.ι ((F ⋙ G) ⋙ H) j ≫ (preservesColimitIso (G ⋙ H) F).inv =
      H.map (G.map (colimit.ι F j)) := by

  -- We know which lemma we want to use, and it's even a simp lemma, but `rw`
  -- won't let us apply it
  fail_if_success rw [ι_preservesColimitIso_inv]
  fail_if_success rw [ι_preservesColimitIso_inv (G ⋙ H)]
  fail_if_success simp only [ι_preservesColimitIso_inv]

  -- This would work:
  -- erw [ι_preservesColimitIso_inv (G ⋙ H)]

  -- `check_compositions` checks if the two morphisms we're composing are
  -- composed by abusing defeq, and indeed it tells us that we are abusing
  -- definitional associativity of composition of functors here: it prints
  -- the following.

  -- info: In composition
  --   colimit.ι ((F ⋙ G) ⋙ H) j ≫ (preservesColimitIso (G ⋙ H) F).inv
  -- the source of
  --   (preservesColimitIso (G ⋙ H) F).inv
  -- is
  --   colimit (F ⋙ G ⋙ H)
  -- but should be
  --   colimit ((F ⋙ G) ⋙ H)

  check_compositions

  -- In this case, we can "fix" this by reassociating in the goal, but
  -- usually at this point the right thing to do is to back off and
  -- check how we ended up with a bad goal in the first place.
  dsimp only [Functor.assoc]

  -- This would work now, but it is not needed, because simp works as well
  -- rw [ι_preservesColimitIso_inv]

  simp

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.CheckCompositions

choose

The using hyp part can be omitted, which will effectively cause choose to start with an intro hyp.

Like intro, the choose tactic supports type annotations to specify the expected type of the introduced variables. This is useful for documentation and for catching mistakes early:

example (h : ∃ n : ℕ, n > 0) : True := by
  choose (n : ℕ) (hn : n > 0) using h
  trivial

If the provided type does not match the actual type, an error is raised.

Examples:

example (h : ∀ n m : ℕ, ∃ i j, m = n + i ∨ m + j = n) : True := by
  choose i j h using h
  guard_hyp i : ℕ → ℕ → ℕ
  guard_hyp j : ℕ → ℕ → ℕ
  guard_hyp h : ∀ (n m : ℕ), m = n + i n m ∨ m + j n m = n
  trivial
example (h : ∀ i : ℕ, i < 7 → ∃ j, i < j ∧ j < i+i) : True := by
  choose! f h h' using h
  guard_hyp f : ℕ → ℕ
  guard_hyp h : ∀ (i : ℕ), i < 7 → i < f i
  guard_hyp h' : ∀ (i : ℕ), i < 7 → f i < i + i
  trivial

Tags:
Defined in module:
Mathlib.Tactic.Choose

clean

(Deprecated) clean t is a macro for exact clean% t.

Tags:
Defined in module:
Mathlib.Tactic.Clean

clear

Clears all hypotheses it can, except those provided after a minus sign. Example:

  clear * - h₁ h₂

Tags:
Defined in module:
Mathlib.Tactic.ClearExcept

clear!

A variant of clear which clears not only the given hypotheses but also any other hypotheses depending on them

Tags:
Defined in module:
Mathlib.Tactic.ClearExclamation

clear_

Clear all hypotheses starting with _, like _match and _let_match.

Tags:
Defined in module:
Mathlib.Tactic.Clear_

clear_aux_decl

This tactic clears all auxiliary declarations from the context.

Tags:
Defined in module:
Mathlib.Tactic.Basic

coherence

Use the coherence theorem for monoidal categories to solve equations in a monoidal equation, where the two sides only differ by replacing strings of monoidal structural morphisms (that is, associators, unitors, and identities) with different strings of structural morphisms with the same source and target.

That is, coherence can handle goals of the form a ≫ f ≫ b ≫ g ≫ c = a' ≫ f ≫ b' ≫ g ≫ c' where a = a', b = b', and c = c' can be proved using pure_coherence.

(If you have very large equations on which coherence is unexpectedly failing, you may need to increase the typeclass search depth, using e.g. set_option synthInstance.maxSize 500.)

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.Coherence

compareOfLessAndEq_rfl

This attempts to prove that a given instance of compare is equal to compareOfLessAndEq by introducing the arguments and trying the following approaches in order:

  1. seeing if rfl works
  2. seeing if the compare at hand is nonetheless essentially compareOfLessAndEq, but, because of implicit arguments, requires us to unfold the defs and split the ifs in the definition of compareOfLessAndEq
  3. seeing if we can split by cases on the arguments, then see if the defs work themselves out (useful when compare is defined via a match statement, as it is for Bool)

Tags:
Defined in module:
Mathlib.Order.Defs.LinearOrder

compute_degree

compute_degree is a tactic to solve goals of the form

The tactic may leave goals of the form d' = d, d' ≤ d, d' < d, or r ≠ 0, where d' in or WithBot is the tactic's guess of the degree, and r is the coefficient's guess of the leading coefficient of f.

compute_degree applies norm_num to the left-hand side of all side goals, trying to close them.

The variant compute_degree! first applies compute_degree. Then it uses norm_num on all the remaining goals and tries assumption.

Tags:
Defined in module:
Mathlib.Tactic.ComputeDegree

congr!

congr! tries to prove the main goal by repeatedly applying congruence rules. For example, on a goal of the form ⊢ f a1 a2 ... = f b1 b2 ..., congr! will make new goals ⊢ a1 = b1, ⊢ a2 = b2, ...

congr! is a more powerful version of the congr tactic that uses congruence lemmas (tagged with @[congr]), reflexivity rules (tagged with @[refl]) and proof discharging strategies. The full list of congruence proof strategies is documented in the module Mathlib.Tactic.CongrExclamation. The congr! tactic is used by the convert and convert_to tactics.

Tags:
Defined in module:
Mathlib.Tactic.CongrExclamation

congrm

congrm e is a tactic for proving goals of the form lhs = rhs, lhs ↔ rhs, lhs ≍ rhs, or R lhs rhs when R is a reflexive relation. The expression e is a pattern containing placeholders ?_, and this pattern is matched against lhs and rhs simultaneously. These placeholders generate new goals that state that corresponding subexpressions in lhs and rhs are equal. If the placeholders have names, such as ?m, then the new goals are given tags with those names.

Examples:

example {a b c d : ℕ} :
    Nat.pred a.succ * (d + (c + a.pred)) = Nat.pred b.succ * (b + (c + d.pred)) := by
  congrm Nat.pred (Nat.succ ?h1) * (?h2 + ?h3)
  /-  Goals left:
  case h1 ⊢ a = b
  case h2 ⊢ d = b
  case h3 ⊢ c + a.pred = c + d.pred
  -/
  sorry
  sorry
  sorry

example {a b : ℕ} (h : a = b) : (fun y : ℕ => ∀ z, a + a = z) = (fun x => ∀ z, b + a = z) := by
  congrm fun x => ∀ w, ?_ + a = w
  -- ⊢ a = b
  exact h

The congrm command is a convenient frontend to congr(...) congruence quotations. If the goal is an equality, congrm e is equivalent to refine congr(e') where e' is built from e by replacing each placeholder ?m by $(?m). The pattern e is allowed to contain $(...) expressions to immediately substitute equality proofs into the congruence, just like for congruence quotations.

Tags:
Defined in module:
Mathlib.Tactic.CongrM

congrm?

Display a widget panel allowing to generate a congrm call with holes specified by selecting subexpressions in the goal.

Tags:
Defined in module:
Mathlib.Tactic.Widget.CongrM

constructorm

constructorm p_1, ..., p_n, where the main goal has type type, applies the first matching constructor for type, if type matches one of the given patterns. If type does not match any of the patterns, constructorm fails.

Examples:

example : True ∧ (True ∨ True) := by
  constructorm* _ ∨ _, _ ∧ _, True

Tags:
Defined in module:
Mathlib.Tactic.CasesM

continuity

The tactic continuity solves goals of the form Continuous f by applying lemmas tagged with the continuity user attribute.

fun_prop is a (usually more powerful) alternative to continuity.

Tags:
Defined in module:
Mathlib.Tactic.Continuity

continuity?

The tactic continuity solves goals of the form Continuous f by applying lemmas tagged with the continuity user attribute.

Tags:
Defined in module:
Mathlib.Tactic.Continuity

contrapose

Transforms the goal into its contrapositive.

Tags:
Defined in module:
Mathlib.Tactic.Contrapose

contrapose!

Transforms the goal into its contrapositive and pushes negations in the result. Usage matches contrapose

Tags:
Defined in module:
Mathlib.Tactic.Contrapose

conv?

Display a widget panel allowing to generate a conv call zooming to the subexpression selected in the goal or in the type of a local hypothesis or let-decl.

Tags:
Defined in module:
Mathlib.Tactic.Widget.Conv

conv_lhs

conv_lhs => cs runs the conv tactic sequence cs on the left hand side of the target.

In general, for an n-ary operator as the target, it traverses into the second to last argument. It is a synonym for conv => arg -2; cs.

Tags:
Defined in module:
Mathlib.Tactic.Conv

conv_rhs

conv_rhs => cs runs the conv tactic sequence cs on the right hand side of the target.

In general, for an n-ary operator as the target, it traverses into the last argument. It is a synonym for conv => arg -1; cs.

Tags:
Defined in module:
Mathlib.Tactic.Conv

convert

convert e, where the term e is inferred to have type t, replaces the main goal ⊢ t' with new goals for proving the equality t' = t using congruence. The goals are created like congr! would. Like refine e, any holes (?_ or ?x) in e that are not solved by unification are converted into new goals, using the hole's name, if any, as the goal case name. Like congr!, convert introduces variables while applying congruence rules. These can be pattern-matched, like rintro would, using the with keyword.

See also convert_to t, where t specifies the expected type, instead of a proof term of type t. In other words, convert_to t works like convert (?_ : t). Both tactics use the same options.

Examples:

-- `convert using` controls the depth of congruence.
example {n : ℕ} (e : Prime (2 * n + 1)) :
    Prime (n + n + 1) := by
  convert e using 2
  -- One goal: ⊢ n + n = 2 * n
  ring
-- `convert` can fail where `exact` succeeds.
example (h : p 0) : p 1 := by
  fail_if_success
    convert h -- fails, left-over goal 1 = 0
    done
  exact h -- succeeds

```lean
-- `convert with` names introduced variables.
example (p q : Nat → Prop) (h : ∀ ε > 0, p ε) :
    ∀ ε > 0, q ε := by
  convert h using 2 with ε hε
  -- Goal now looks like:
  -- hε : ε > 0
  -- ⊢ q ε ↔ p ε
  sorry


Tags:
Defined in module:
Mathlib.Tactic.Convert

convert_to

convert_to t on a goal ⊢ t' changes the goal to ⊢ t and adds new goals for proving the equality t' = t using congruence. The goals are created like congr! would. Any remaining congruence goals come before the main goal. Like refine e, any holes (?_ or ?x) in t that are not solved by unification are converted into new goals, using the hole's name, if any, as the goal case name. Like congr!, convert_to introduces variables while applying congruence rules. These can be pattern-matched, like rintro would, using the with keyword.

convert e, where e is a term of type t, uses e to close the new main goal. In other words, convert e works like convert_to t; refine e. Both tactics use the same options.

Tags:
Defined in module:
Mathlib.Tactic.Convert

discrete_cases

A simple tactic to run cases on any Discrete α hypotheses.

Tags:
Defined in module:
Mathlib.CategoryTheory.Discrete.Basic

econstructor

econstructor is like constructor (it calls apply using the first matching constructor of an inductive datatype) except only non-dependent premises are added as new goals.

Tags:
Defined in module:
Mathlib.Tactic.Constructor

enat_to_nat

enat_to_nat shifts all ENats in the context to Nat, rewriting propositions about them. A typical use case is enat_to_nat; lia.

Tags:
Defined in module:
Mathlib.Tactic.ENatToNat

erw?

erw? [r, ...] calls erw [r, ...] (at hypothesis h if written erw [r, ...] at h), and then attempts to identify any subexpression which would block the use of rw instead. It does so by identifying subexpressions which are defeq, but not at reducible transparency.

Tags:
Defined in module:
Mathlib.Tactic.ErwQuestion

eta_expand

eta_expand at loc eta expands all sub-expressions at the given location. It also beta reduces any applications of eta expanded terms, so it puts it into an eta-expanded "normal form." This also exists as a conv-mode tactic.

For example, if f takes two arguments, then f becomes fun x y => f x y and f x becomes fun y => f x y.

This can be useful to turn, for example, a raw HAdd.hAdd into fun x y => x + y.

Tags:
Defined in module:
Mathlib.Tactic.DefEqTransformations

eta_reduce

eta_reduce at loc eta reduces all sub-expressions at the given location. This also exists as a conv-mode tactic.

For example, fun x y => f x y becomes f after eta reduction.

Tags:
Defined in module:
Mathlib.Tactic.DefEqTransformations

eta_struct

eta_struct at loc transforms structure constructor applications such as S.mk x.1 ... x.n (pretty printed as, for example, {a := x.a, b := x.b, ...}) into x. This also exists as a conv-mode tactic.

The transformation is known as eta reduction for structures, and it yields definitionally equal expressions.

For example, given x : α × β, then (x.1, x.2) becomes x after this transformation.

Tags:
Defined in module:
Mathlib.Tactic.DefEqTransformations

existsi

existsi e₁, e₂, ⋯ applies the tactic refine ⟨e₁, e₂, ⋯, ?_⟩. It's purpose is to instantiate existential quantifiers.

Examples:

example : ∃ x : Nat, x = x := by
  existsi 42
  rfl

example : ∃ x : Nat, ∃ y : Nat, x = y := by
  existsi 42, 42
  rfl

Tags:
Defined in module:
Mathlib.Tactic.ExistsI

extract_goal

The tactic tries to produce an output that can be copy-pasted and just work, but its success depends on whether the expressions are amenable to being unambiguously pretty printed.

The tactic responds to pretty printing options. For example, set_option pp.all true in extract_goal gives the pp.all form.

Tags:
Defined in module:
Mathlib.Tactic.ExtractGoal

fail_if_no_progress

fail_if_no_progress tacs evaluates tacs, and fails if no progress is made on the main goal or the local context at reducible transparency.

Tags:
Defined in module:
Mathlib.Tactic.FailIfNoProgress

fconstructor

fconstructor is like constructor (it calls apply using the first matching constructor of an inductive datatype) except that it does not reorder goals.

Tags:
Defined in module:
Mathlib.Tactic.Constructor

field

The field tactic proves equality goals in (semi-)fields. For example:

example {x y : ℚ} (hx : x + y ≠ 0) : x / (x + y) + y / (x + y) = 1 := by
  field
example {a b : ℝ} (ha : a ≠ 0) : a / (a * b) - 1 / b = 0 := by field

The scope of the tactic is equality goals which are universal, in the sense that they are true in any field in which the appropriate denominators don't vanish. (That is, they are consequences purely of the field axioms.)

Checking the nonvanishing of the necessary denominators is done using a variety of tricks -- in particular this part of the reasoning is non-universal, i.e. can be specific to the field at hand (order properties, explicit ≠ 0 hypotheses, CharZero if that is known, etc). The user can also provide additional terms to help with the nonzeroness proofs. For example:

example {K : Type*} [Field K] (hK : ∀ x : K, x ^ 2 + 1 ≠ 0) (x : K) :
    1 / (x ^ 2 + 1) + x ^ 2 / (x ^ 2 + 1) = 1 := by
  field [hK]

The field tactic is built from the tactics field_simp (which clears the denominators) and ring (which proves equality goals universally true in commutative (semi-)rings). If field fails to prove your goal, you may still be able to prove your goal by running the field_simp and ring_nf normalizations in some order. For example, this statement:

example {a b : ℚ} (H : b + a ≠ 0) : a / (a + b) + b / (b + a) = 1

is not proved by field but is proved by ring_nf at *; field.

Tags:
Defined in module:
Mathlib.Tactic.Field

field_simp

The goal of field_simp is to bring expressions in (semi-)fields over a common denominator, i.e. to reduce them to expressions of the form n / d where neither n nor d contains any division symbol. For example, x / (1 - y) / (1 + y / (1 - y)) is reduced to x / (1 - y + y):

example (x y z : ℚ) (hy : 1 - y ≠ 0) :
    ⌊x / (1 - y) / (1 + y / (1 - y))⌋ < 3 := by
  field_simp
  -- new goal: `⊢ ⌊x / (1 - y + y)⌋ < 3`

The field_simp tactic will also clear denominators in field (in)equalities, by cross-multiplying. For example, field_simp will clear the x denominators in the following equation:

example {K : Type*} [Field K] {x : K} (hx0 : x ≠ 0) :
    (x + 1 / x) ^ 2 + (x + 1 / x) = 1 := by
  field_simp
  -- new goal: `⊢ (x ^ 2 + 1) * (x ^ 2 + 1 + x) = x ^ 2`

A very common pattern is field_simp; ring (clear denominators, then the resulting goal is solvable by the axioms of a commutative ring). The finishing tactic field is a shorthand for this pattern.

Cancelling and combining denominators will generally require checking "nonzeroness"/"positivity" side conditions. The field_simp tactic attempts to discharge these, and will omit such steps if it cannot discharge the corresponding side conditions. The discharger will try, among other things, positivity and norm_num, and will also use any nonzeroness/positivity proofs included explicitly (e.g. field_simp [hx]). If your expression is not completely reduced by field_simp, check the denominators of the resulting expression and provide proofs that they are nonzero/positive to enable further progress.

Tags:
Defined in module:
Mathlib.Tactic.FieldSimp

field_simp_discharge

Discharge strategy for the field_simp tactic.

Tags:
Defined in module:
Mathlib.Tactic.FieldSimp.Discharger

filter_upwards

filter_upwards [h₁, ⋯, hₙ] replaces a goal of the form s ∈ f and terms h₁ : t₁ ∈ f, ⋯, hₙ : tₙ ∈ f with ∀ x, x ∈ t₁ → ⋯ → x ∈ tₙ → x ∈ s. The list is an optional parameter, [] being its default value.

filter_upwards [h₁, ⋯, hₙ] with a₁ a₂ ⋯ aₖ is a short form for { filter_upwards [h₁, ⋯, hₙ], intro a₁ a₂ ⋯ aₖ }.

filter_upwards [h₁, ⋯, hₙ] using e is a short form for { filter_upwards [h1, ⋯, hn], exact e }.

Combining both shortcuts is done by writing filter_upwards [h₁, ⋯, hₙ] with a₁ a₂ ⋯ aₖ using e. Note that in this case, the aᵢ terms can be used in e.

Tags:
Defined in module:
Mathlib.Order.Filter.Defs

fin_cases

fin_cases h performs case analysis on a hypothesis of the form h : A, where [Fintype A] is available, or h : a ∈ A, where A : Finset X, A : Multiset X or A : List X.

As an example, in

example (f : ℕ → Prop) (p : Fin 3) (h0 : f 0) (h1 : f 1) (h2 : f 2) : f p.val := by
  fin_cases p; simp
  all_goals assumption

after fin_cases p; simp, there are three goals, f 0, f 1, and f 2.

Tags:
Defined in module:
Mathlib.Tactic.FinCases

fin_omega

Preprocessor for omega to handle inequalities in Fin. Note that this involves a lot of case splitting, so may be slow.

Tags:
Defined in module:
Mathlib.Data.Fin.Basic

find

find finds definitions and theorems whose result type matches the current goal exactly, and prints them as info lines. In other words, find lists definitions and theorems that are applyable against the current goal. find will not affect the goal by itself and should be removed from the finished proof.

For a command or tactic that takes the type to search for as an argument, see #find.

Example:

example : True := by
  find
  -- True.intro: True
  -- trivial: True
  -- ...

Tags:
Defined in module:
Mathlib.Tactic.Find

finiteness

finiteness proves goals of the form *** < ∞ and (equivalently) *** ≠ ∞ in the extended nonnegative reals (ℝ≥0∞). Supports passing additional expressions as local hypotheses.

Tags:
Defined in module:
Mathlib.Tactic.Finiteness

frac_tac

Solve equations for RatFunc K by working in FractionRing K[X].

Tags:
Defined in module:
Mathlib.FieldTheory.RatFunc.Basic

fun_prop

fun_prop solves a goal of the form P f, where P is a predicate and f is a function, by decomposing f into a composition of elementary functions, and proving P on each of those by matching against a set of @[fun_prop] lemmas.

If fun_prop fails to solve a goal with the error "No theorems found", you can solve this issue by importing or adding new theorems tagged with the @[fun_prop] attribute. See the module documentation for Mathlib/Tactic/FunProp.lean for a detailed explanation.

Examples:

example : Continuous (fun x : ℝ ↦ x * sin x) := by fun_prop
-- Specify a discharger to solve `ContinuousAt`/`Within`/`On` goals:
example (y : ℝ) (hy : y ≠ 0) : ContinuousAt (fun x : ℝ ↦ 1/x) y := by
  fun_prop (disch := assumption)

example (y : ℝ) (hy : y ≠ 0) : ContinuousAt (fun x => x * (Real.log x) ^ 2 - Real.exp x / x) y := by
  fun_prop (disch := aesop)

Tags:
Defined in module:
Mathlib.Tactic.FunProp.Elab

gcongr

The gcongr tactic applies "generalized congruence" rules, reducing a relational goal between an LHS and RHS. For example,

example {a b x c d : ℝ} (h1 : a + 1 ≤ b + 1) (h2 : c + 2 ≤ d + 2) :
    x ^ 2 * a + c ≤ x ^ 2 * b + d := by
  gcongr
  · linarith
  · linarith

This example has the goal of proving the relation between an LHS and RHS both of the pattern

x ^ 2 * ?_ + ?_

(with inputs a, c on the left and b, d on the right); after the use of gcongr, we have the simpler goals a ≤ b and c ≤ d.

A depth limit or a pattern can be provided explicitly; this is useful if a non-maximal match is desired:

example {a b c d x : ℝ} (h : a + c + 1 ≤ b + d + 1) :
    x ^ 2 * (a + c) + 5 ≤ x ^ 2 * (b + d) + 5 := by
  gcongr x ^ 2 * ?_ + 5 -- or `gcongr 2`
  linarith

The "generalized congruence" rules are the library lemmas which have been tagged with the attribute @[gcongr]. For example, the first example constructs the proof term

add_le_add (mul_le_mul_of_nonneg_left ?_ (Even.pow_nonneg (even_two_mul 1) x)) ?_

using the generalized congruence lemmas add_le_add and mul_le_mul_of_nonneg_left.

The tactic attempts to discharge side goals to these "generalized congruence" lemmas (such as the side goal 0 ≤ x ^ 2 in the above application of mul_le_mul_of_nonneg_left) using the tactic gcongr_discharger, which wraps positivity but can also be extended. Side goals not discharged in this way are left for the user.

gcongr will descend into binders (for example sums or suprema). To name the bound variables, use with:

example {f g : ℕ → ℝ≥0∞} (h : ∀ n, f n ≤ g n) : ⨆ n, f n ≤ ⨆ n, g n := by
  gcongr with i
  exact h i

Tags:
Defined in module:
Mathlib.Tactic.GCongr.Core

gcongr?

Display a widget panel allowing to generate a gcongr call with holes specified by selecting subexpressions in the goal.

Tags:
Defined in module:
Mathlib.Tactic.Widget.GCongr

gcongr_discharger

gcongr_discharger is used by gcongr to discharge side goals.

This is an extensible tactic using macro_rules. By default it calls positivity (after importing the positivity tactic). Example: macro_rules | `(tactic| gcongr_discharger) => `(tactic| positivity).

Tags:
Defined in module:
Mathlib.Tactic.GCongr.Core

generalize'

Backwards compatibility shim for generalize.

Tags:
Defined in module:
Mathlib.Tactic.Generalize

ghost_calc

ghost_calc is a tactic for proving identities between polynomial functions. Typically, when faced with a goal like

∀ (x y : 𝕎 R), verschiebung (x * frobenius y) = verschiebung x * y

you can

  1. call ghost_calc
  2. do a small amount of manual work -- maybe nothing, maybe rintro, etc
  3. call ghost_simp

and this will close the goal.

ghost_calc cannot detect whether you are dealing with unary or binary polynomial functions. You must give it arguments to determine this. If you are proving a universally quantified goal like the above, call ghost_calc _ _. If the variables are introduced already, call ghost_calc x y. In the unary case, use ghost_calc _ or ghost_calc x.

ghost_calc is a light wrapper around type class inference. All it does is apply the appropriate extensionality lemma and try to infer the resulting goals. This is subtle and Lean's elaborator doesn't like it because of the HO unification involved, so it is easier (and prettier) to put it in a tactic script.

Tags:
Defined in module:
Mathlib.RingTheory.WittVector.IsPoly

ghost_fun_tac

An auxiliary tactic for proving that ghostFun respects the ring operations.

Tags:
Defined in module:
Mathlib.RingTheory.WittVector.Basic

ghost_simp

A macro for a common simplification when rewriting with ghost component equations.

Tags:
Defined in module:
Mathlib.RingTheory.WittVector.IsPoly

grewrite

grewrite [e] is like grw [e], but it doesn't try to close the goal with rfl. This is analogous to rw and rewrite, where rewrite doesn't try to close the goal with rfl.

Tags:
Defined in module:
Mathlib.Tactic.GRewrite.Elab

group

Tactic for normalizing expressions in multiplicative groups, without assuming commutativity, using only the group axioms without any information about which group is manipulated.

(For additive commutative groups, use the abel tactic instead.)

Example:

example {G : Type} [Group G] (a b c d : G) (h : c = (a*b^2)*((b*b)⁻¹*a⁻¹)*d) : a*c*d⁻¹ = a := by
  group at h -- normalizes `h` which becomes `h : c = d`
  rw [h]     -- the goal is now `a*d*d⁻¹ = a`
  group      -- which then normalized and closed

Tags:
Defined in module:
Mathlib.Tactic.Group

grw

grw [e] works just like rw [e], but e can be a relation other than = or .

For example:

variable {a b c d n : ℤ}

example (h₁ : a < b) (h₂ : b ≤ c) : a + d ≤ c + d := by
  grw [h₁, h₂]

example (h : a ≡ b [ZMOD n]) : a ^ 2 ≡ b ^ 2 [ZMOD n] := by
  grw [h]

example (h₁ : a ∣ b) (h₂ : b ∣ a ^ 2 * c) : a ∣ b ^ 2 * c := by
  grw [h₁] at *
  exact h₂

To replace the RHS with the LHS of the given relation, use the notation (just like in rw):

example (h₁ : a < b) (h₂ : b ≤ c) : a + d ≤ c + d := by
  grw [← h₂, ← h₁]

The strict inequality a < b is turned into the non-strict inequality a ≤ b to rewrite with it. A future version of grw may get special support for making better use of strict inequalities.

To rewrite only in the n-th position, use nth_grw n. This is useful when grw tries to rewrite in a position that is not valid for the given relation.

To be able to use grw, the relevant lemmas need to be tagged with @[gcongr]. To rewrite inside a transitive relation, you can also give it an IsTrans instance.

To let grw unfold more aggressively, as in erw, use grw (transparency := default).

Tags:
Defined in module:
Mathlib.Tactic.GRewrite.Elab

guard_goal_nums

guard_goal_nums n succeeds if there are exactly n goals and fails otherwise.

Tags:
Defined in module:
Mathlib.Tactic.GuardGoalNums

guard_hyp_nums

guard_hyp_nums n succeeds if there are exactly n hypotheses and fails otherwise.

Note that, depending on what options are set, some hypotheses in the local context might not be printed in the goal view. This tactic computes the total number of hypotheses, not the number of visible hypotheses.

Tags:
Defined in module:
Mathlib.Tactic.GuardHypNums

hint

The hint tactic tries every tactic registered using register_hint <prio> tac, and reports any that succeed.

Tags:
Defined in module:
Mathlib.Tactic.Hint

induction'

induction' x applies induction on the variable x of the inductive type t to the main goal, producing one goal for each constructor of t, in which x is replaced by that constructor applied to newly introduced variables. induction' adds an inductive hypothesis for each recursive argument to the constructor. This is a backwards-compatible variant of the induction tactic in Lean 4 core.

Prefer induction when possible, because it promotes structured proofs.

Example:

open Nat

example (n : ℕ) : 0 < factorial n := by
  induction' n with n ih
  · rw [factorial_zero]
    simp
  · rw [factorial_succ]
    apply mul_pos (succ_pos n) ih

-- Though the following equivalent spellings should be preferred
example (n : ℕ) : 0 < factorial n := by
  induction n
  case zero =>
    rw [factorial_zero]
    simp
  case succ n ih =>
    rw [factorial_succ]
    apply mul_pos (succ_pos n) ih

Tags:
Defined in module:
Mathlib.Tactic.Cases

infer_param

Close a goal of the form optParam α a or autoParam α stx by using a.

Tags:
Defined in module:
Mathlib.Tactic.InferParam

inhabit

inhabit α tries to derive a Nonempty α instance and then uses it to make an Inhabited α instance. If the target is a Prop, this is done constructively. Otherwise, it uses Classical.choice.

Tags:
Defined in module:
Mathlib.Tactic.Inhabit

init_ring

init_ring is an auxiliary tactic that discharges goals factoring init over ring operations.

Tags:
Defined in module:
Mathlib.RingTheory.WittVector.InitTail

interval_cases

interval_cases n searches for upper and lower bounds on a variable n, and if bounds are found, splits into separate cases for each possible value of n.

As an example, in

example (n : ℕ) (w₁ : n ≥ 3) (w₂ : n < 5) : n = 3 ∨ n = 4 := by
  interval_cases n
  all_goals simp

after interval_cases n, the goals are 3 = 3 ∨ 3 = 4 and 4 = 3 ∨ 4 = 4.

You can also explicitly specify a lower and upper bound to use, as interval_cases using hl, hu. The hypotheses should be in the form hl : a ≤ n and hu : n < b, in which case interval_cases calls fin_cases on the resulting fact n ∈ Set.Ico a b.

You can specify a name h for the new hypothesis, as interval_cases h : n or interval_cases h : n using hl, hu.

Tags:
Defined in module:
Mathlib.Tactic.IntervalCases

introv

The tactic introv allows the user to automatically introduce the variables of a theorem and explicitly name the non-dependent hypotheses. Any dependent hypotheses are assigned their default names.

Examples:

example : ∀ a b : Nat, a = b → b = a := by
  introv h,
  exact h.symm

The state after introv h is

a b : ℕ,
h : a = b
⊢ b = a
example : ∀ a b : Nat, a = b → ∀ c, b = c → a = c := by
  introv h₁ h₂,
  exact h₁.trans h₂

The state after introv h₁ h₂ is

a b : ℕ,
h₁ : a = b,
c : ℕ,
h₂ : b = c
⊢ a = c

Tags:
Defined in module:
Mathlib.Tactic.Basic

isBoundedDefault

Filters are automatically bounded or cobounded in complete lattices. To use the same statements in complete and conditionally complete lattices but let automation fill automatically the boundedness proofs in complete lattices, we use the tactic isBoundedDefault in the statements, in the form (hf : f.IsBounded (≥) := by isBoundedDefault).

Tags:
Defined in module:
Mathlib.Order.Filter.IsBounded

itauto

itauto solves the main goal when it is a tautology of intuitionistic propositional logic. Unlike grind and tauto! this tactic never uses the law of excluded middle (without the ! option), and the proof search is tailored for this use case. itauto is complete for intuitionistic propositional logic: it will solve any goal that is provable in this logic.

Example:

example (p : Prop) : ¬ (p ↔ ¬ p) := by itauto

Tags:
Defined in module:
Mathlib.Tactic.ITauto

lift

Lift an expression to another type.

lift is in some sense dual to the zify tactic. lift (z : ℤ) to ℕ will change the type of an integer z (in the supertype) to (the subtype), given a proof that z ≥ 0; propositions concerning z will still be over . zify changes propositions about (the subtype) to propositions about (the supertype), without changing the type of any variable.

The norm_cast tactic can be used after lift to normalize introduced casts.

Tags:
Defined in module:
Mathlib.Tactic.Lift

liftable_prefixes

Internal tactic used in coherence.

Rewrites an equation f = g as f₀ ≫ f₁ = g₀ ≫ g₁, where f₀ and g₀ are maximal prefixes of f and g (possibly after reassociating) which are "liftable" (i.e. expressible as compositions of unitors and associators).

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.Coherence

linarith

linarith attempts to find a contradiction between hypotheses that are linear (in)equalities. Equivalently, it can prove a linear inequality by assuming its negation and proving False.

In theory, linarith should prove any goal that is true in the theory of linear arithmetic over the rationals. While there is some special handling for non-dense orders like Nat and Int, this tactic is not complete for these theories and will not prove every true goal. It will solve goals over arbitrary types that instantiate CommRing, LinearOrder and IsStrictOrderedRing.

An example:

example (x y z : ℚ) (h1 : 2*x < 3*y) (h2 : -4*x + 2*z < 0)
        (h3 : 12*y - 4* z < 0) : False := by
  linarith

linarith will use all appropriate hypotheses and the negation of the goal, if applicable. Disequality hypotheses require case splitting and are not normally considered (see the splitNe option below).

linarith [t1, t2, t3] will additionally use proof terms t1, t2, t3.

linarith only [h1, h2, h3, t1, t2, t3] will use only the goal (if relevant), local hypotheses h1, h2, h3, and proofs t1, t2, t3. It will ignore the rest of the local context.

linarith! will use a stronger reducibility setting to try to identify atoms. For example,

example (x : ℚ) : id x ≥ x := by
  linarith

will fail, because linarith will not identify x and id x. linarith! will. This can sometimes be expensive.

linarith (config := { .. }) takes a config object with five optional arguments:

A variant, nlinarith, does some basic preprocessing to handle some nonlinear goals.

The option set_option trace.linarith true will trace certain intermediate stages of the linarith routine.

Tags:
Defined in module:
Mathlib.Tactic.Linarith.Frontend

linarith?

linarith? behaves like linarith but, on success, it prints a suggestion of the form linarith only [...] listing a minimized set of hypotheses used in the final proof. Use linarith?! for the higher-reducibility variant and set the minimize flag in the configuration to control whether greedy minimization is performed.

Tags:
Defined in module:
Mathlib.Tactic.Linarith.Frontend

linear_combination

The linear_combination tactic attempts to prove an (in)equality goal by exhibiting it as a specified linear combination of (in)equality hypotheses, or other (in)equality proof terms, modulo (A) moving terms between the LHS and RHS of the (in)equalities, and (B) a normalization tactic which by default is ring-normalization.

Example usage:

example {a b : ℚ} (h1 : a = 1) (h2 : b = 3) : (a + b) / 2 = 2 := by
  linear_combination (h1 + h2) / 2

example {a b : ℚ} (h1 : a ≤ 1) (h2 : b ≤ 3) : (a + b) / 2 ≤ 2 := by
  linear_combination (h1 + h2) / 2

example {a b : ℚ} : 2 * a * b ≤ a ^ 2 + b ^ 2 := by
  linear_combination sq_nonneg (a - b)

example {x y z w : ℤ} (h₁ : x * z = y ^ 2) (h₂ : y * w = z ^ 2) :
    z * (x * w - y * z) = 0 := by
  linear_combination w * h₁ + y * h₂

example {x : ℚ} (h : x ≥ 5) : x ^ 2 > 2 * x + 11 := by
  linear_combination (x + 3) * h

example {R : Type*} [CommRing R] {a b : R} (h : a = b) : a ^ 2 = b ^ 2 := by
  linear_combination (a + b) * h

example {A : Type*} [AddCommGroup A]
    {x y z : A} (h1 : x + y = 10 • z) (h2 : x - y = 6 • z) :
    2 • x = 2 • (8 • z) := by
  linear_combination (norm := abel) h1 + h2

example (x y : ℤ) (h1 : x * y + 2 * x = 1) (h2 : x = y) :
    x * y = -2 * y + 1 := by
  linear_combination (norm := ring_nf) -2 * h2
  -- leaves goal `⊢ x * y + x * 2 - 1 = 0`

The input e in linear_combination e is a linear combination of proofs of (in)equalities, given as a sum/difference of coefficients multiplied by expressions. The coefficients may be arbitrary expressions (with nonnegativity constraints in the case of inequalities). The expressions can be arbitrary proof terms proving (in)equalities; most commonly they are hypothesis names h1, h2, ....

The left and right sides of all the (in)equalities should have the same type α, and the coefficients should also have type α. For full functionality α should be a commutative ring -- strictly speaking, a commutative semiring with "cancellative" addition (in the semiring case, negation and subtraction will be handled "formally" as if operating in the enveloping ring). If a nonstandard normalization is used (for example abel or skip), the tactic will work over types α with less algebraic structure: for equalities, the minimum is instances of [Add α] [IsRightCancelAdd α] together with instances of whatever operations are used in the tactic call.

The variant linear_combination (norm := tac) e specifies explicitly the "normalization tactic" tac to be run on the subgoal(s) after constructing the linear combination.

The variant linear_combination (exp := n) e will take the goal to the nth power before subtracting the combination e. In other words, if the goal is t1 = t2, linear_combination (exp := n) e will change the goal to (t1 - t2)^n = 0 before proceeding as above. This variant is implemented only for linear combinations of equalities (i.e., not for inequalities).

Tags:
Defined in module:
Mathlib.Tactic.LinearCombination

linear_combination'

linear_combination' attempts to simplify the target by creating a linear combination of a list of equalities and subtracting it from the target. The tactic will create a linear combination by adding the equalities together from left to right, so the order of the input hypotheses does matter. If the norm field of the tactic is set to skip, then the tactic will simply set the user up to prove their target using the linear combination instead of normalizing the subtraction.

Note: There is also a similar tactic linear_combination (no prime); this version is provided for backward compatibility. Compared to this tactic, linear_combination:

Note: The left and right sides of all the equalities should have the same type, and the coefficients should also have this type. There must be instances of Mul and AddGroup for this type.

Example Usage:

example (x y : ℤ) (h1 : x*y + 2*x = 1) (h2 : x = y) : x*y = -2*y + 1 := by
  linear_combination' 1*h1 - 2*h2

example (x y : ℤ) (h1 : x*y + 2*x = 1) (h2 : x = y) : x*y = -2*y + 1 := by
  linear_combination' h1 - 2*h2

example (x y : ℤ) (h1 : x*y + 2*x = 1) (h2 : x = y) : x*y = -2*y + 1 := by
  linear_combination' (norm := ring_nf) -2*h2
  /- Goal: x * y + x * 2 - 1 = 0 -/

example (x y z : ℝ) (ha : x + 2*y - z = 4) (hb : 2*x + y + z = -2)
    (hc : x + 2*y + z = 2) :
    -3*x - 3*y - 4*z = 2 := by
  linear_combination' ha - hb - 2*hc

example (x y : ℚ) (h1 : x + y = 3) (h2 : 3*x = 7) :
    x*x*y + y*x*y + 6*x = 3*x*y + 14 := by
  linear_combination' x*y*h1 + 2*h2

example (x y : ℤ) (h1 : x = -3) (h2 : y = 10) : 2*x = -6 := by
  linear_combination' (norm := skip) 2*h1
  simp

axiom qc : ℚ
axiom hqc : qc = 2*qc

example (a b : ℚ) (h : ∀ p q : ℚ, p = q) : 3*a + qc = 3*b + 2*qc := by
  linear_combination' 3 * h a b + hqc

Tags:
Defined in module:
Mathlib.Tactic.LinearCombination'

map_fun_tac

Auxiliary tactic for showing that mapFun respects the ring operations.

Tags:
Defined in module:
Mathlib.RingTheory.WittVector.Basic

match_scalars

Given a goal which is an equality in a type M (with M an AddCommMonoid), parse the LHS and RHS of the goal as linear combinations of M-atoms over some semiring R, and reduce the goal to the respective equalities of the R-coefficients of each atom.

For example, this produces the goal ⊢ a * 1 + b * 1 = (b + a) * 1:

example [AddCommMonoid M] [Semiring R] [Module R M] (a b : R) (x : M) :
    a • x + b • x = (b + a) • x := by
  match_scalars

This produces the two goals ⊢ a * (a * 1) + b * (b * 1) = 1 (from the x atom) and ⊢ a * -(b * 1) + b * (a * 1) = 0 (from the y atom):

example [AddCommGroup M] [Ring R] [Module R M] (a b : R) (x : M) :
    a • (a • x - b • y) + (b • a • y + b • b • x) = x := by
  match_scalars

This produces the goal ⊢ -2 * (a * 1) = a * (-2 * 1):

example [AddCommGroup M] [Ring R] [Module R M] (a : R) (x : M) :
    -(2:R) • a • x = a • (-2:ℤ) • x  := by
  match_scalars

The scalar type for the goals produced by the match_scalars tactic is the largest scalar type encountered; for example, if , and a characteristic-zero field K all occur as scalars, then the goals produced are equalities in K. A variant of push_cast is used internally in match_scalars to interpret scalars from the other types in this largest type.

If the set of scalar types encountered is not totally ordered (in the sense that for all rings R, S encountered, it holds that either Algebra R S or Algebra S R), then the match_scalars tactic fails.

Tags:
Defined in module:
Mathlib.Tactic.Module

match_target

Deprecated: use guard_target =~ t instead.

Tags:
Defined in module:
Mathlib.Tactic.Basic

measurability

The tactic measurability solves goals of the form Measurable f, AEMeasurable f, StronglyMeasurable f, AEStronglyMeasurable f μ, or MeasurableSet s by applying lemmas tagged with the measurability user attribute.

Note that measurability uses fun_prop for solving measurability of functions, so statements about Measurable, AEMeasurable, StronglyMeasurable and AEStronglyMeasurable should be tagged with fun_prop rather that measurability. The measurability attribute is equivalent to fun_prop in these cases for backward compatibility with the earlier implementation.

Tags:
Defined in module:
Mathlib.Tactic.Measurability

measurability?

The tactic measurability? solves goals of the form Measurable f, AEMeasurable f, StronglyMeasurable f, AEStronglyMeasurable f μ, or MeasurableSet s by applying lemmas tagged with the measurability user attribute, and suggests a faster proof script that can be substituted for the tactic call in case of success.

Tags:
Defined in module:
Mathlib.Tactic.Measurability

mem_tac

mem_tac tries to prove goals of the form x ∈ 𝒜 i when x has the form of:

Tags:
Defined in module:
Mathlib.AlgebraicGeometry.ProjectiveSpectrum.Scheme

mfld_set_tac

A very basic tactic to show that sets showing up in manifolds coincide or are included in one another.

Tags:
Defined in module:
Mathlib.Logic.Equiv.PartialEquiv

mod_cases

Tags:
Defined in module:
Mathlib.Tactic.ModCases

module

Given a goal which is an equality in a type M (with M an AddCommMonoid), parse the LHS and RHS of the goal as linear combinations of M-atoms over some commutative semiring R, and prove the goal by checking that the LHS- and RHS-coefficients of each atom are the same up to ring-normalization in R.

(If the proofs of coefficient-wise equality will require more reasoning than just ring-normalization, use the tactic match_scalars instead, and then prove coefficient-wise equality by hand.)

Example uses of the module tactic:

example [AddCommMonoid M] [CommSemiring R] [Module R M] (a b : R) (x : M) :
    a • x + b • x = (b + a) • x := by
  module

example [AddCommMonoid M] [Field K] [CharZero K] [Module K M] (x : M) :
    (2:K)⁻¹ • x + (3:K)⁻¹ • x + (6:K)⁻¹ • x = x := by
  module

example [AddCommGroup M] [CommRing R] [Module R M] (a : R) (v w : M) :
    (1 + a ^ 2) • (v + w) - a • (a • v - w) = v + (1 + a + a ^ 2) • w := by
  module

example [AddCommGroup M] [CommRing R] [Module R M] (a b μ ν : R) (x y : M) :
    (μ - ν) • a • x = (a • μ • x + b • ν • y) - ν • (a • x + b • y) := by
  module

Tags:
Defined in module:
Mathlib.Tactic.Module

monicity

monicity tries to solve a goal of the form Monic f. It converts the goal into a goal of the form natDegree f ≤ n and one of the form f.coeff n = 1 and calls compute_degree on those two goals.

The variant monicity! starts like monicity, but calls compute_degree! on the two side-goals.

Tags:
Defined in module:
Mathlib.Tactic.ComputeDegree

mono

mono applies monotonicity rules and local hypotheses repetitively. For example,

example (x y z k : ℤ)
    (h : 3 ≤ (4 : ℤ))
    (h' : z ≤ y) :
    (k + 3 + x) - y ≤ (k + 4 + x) - z := by
  mono

Tags:
Defined in module:
Mathlib.Tactic.Monotonicity.Basic

monoidal

Use the coherence theorem for monoidal categories to solve equations in a monoidal category, where the two sides only differ by replacing strings of monoidal structural morphisms (that is, associators, unitors, and identities) with different strings of structural morphisms with the same source and target.

That is, monoidal can handle goals of the form a ≫ f ≫ b ≫ g ≫ c = a' ≫ f ≫ b' ≫ g ≫ c' where a = a', b = b', and c = c' can be proved using monoidal_coherence.

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.Monoidal.Basic

monoidal_coherence

Coherence tactic for monoidal categories. Use pure_coherence instead, which is a frontend to this one.

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.Coherence

monoidal_coherence

Close the goal of the form η = θ, where η and θ are 2-isomorphisms made up only of associators, unitors, and identities.

example {C : Type} [Category* C] [MonoidalCategory C] :
  (λ_ (𝟙_ C)).hom = (ρ_ (𝟙_ C)).hom := by
  monoidal_coherence

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.Monoidal.PureCoherence

monoidal_nf

Normalize the both sides of an equality.

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.Monoidal.Basic

monoidal_simps

Simp lemmas for rewriting a hom in monoidal categories into a normal form.

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.Coherence

move_oper

The tactic move_add rearranges summands of expressions. Calling move_add [a, ← b, ...] matches a, b,... with summands in the main goal. It then moves a to the far right and b to the far left of each addition in which they appear. The side to which the summands are moved is determined by the presence or absence of the arrow .

The inputs a, b,... can be any terms, also with underscores. The tactic uses the first "new" summand that unifies with each one of the given inputs.

There is a multiplicative variant, called move_mul.

There is also a general tactic for a "binary associative commutative operation": move_oper. In this case the syntax requires providing first a term whose head symbol is the operation. E.g. move_oper HAdd.hAdd [...] is the same as move_add, while move_oper Max.max [...] rearranges maxs.

Tags:
Defined in module:
Mathlib.Tactic.MoveAdd

mv_bisim

tactic for proof by bisimulation

Tags:
Defined in module:
Mathlib.Data.QPF.Multivariate.Constructions.Cofix

nlinarith

An extension of linarith with some preprocessing to allow it to solve some nonlinear arithmetic problems. (Based on Coq's nra tactic.) See linarith for the available syntax of options, which are inherited by nlinarith; that is, nlinarith! and nlinarith only [h1, h2] all work as in linarith. The preprocessing is as follows:

Tags:
Defined in module:
Mathlib.Tactic.Linarith.Frontend

noncomm_ring

A tactic for simplifying identities in not-necessarily-commutative rings.

An example:

example {R : Type*} [Ring R] (a b c : R) : a * (b + c + c - b) = 2 * a * c := by
  noncomm_ring

You can use noncomm_ring [h] to also simplify using h.

Tags:
Defined in module:
Mathlib.Tactic.NoncommRing

nontriviality

Attempts to generate a Nontrivial α hypothesis.

The tactic first checks to see that there is not already a Nontrivial α instance before trying to synthesize one using other techniques.

If the goal is an (in)equality, the type α is inferred from the goal. Otherwise, the type needs to be specified in the tactic invocation, as nontriviality α.

The nontriviality tactic will first look for strict inequalities amongst the hypotheses, and use these to derive the Nontrivial instance directly.

Otherwise, it will perform a case split on Subsingleton α ∨ Nontrivial α, and attempt to discharge the Subsingleton goal using simp [h₁, h₂, ..., hₙ, nontriviality], where [h₁, h₂, ..., hₙ] is a list of additional simp lemmas that can be passed to nontriviality using the syntax nontriviality α using h₁, h₂, ..., hₙ.

example {R : Type} [OrderedRing R] {a : R} (h : 0 < a) : 0 < a := by
  nontriviality -- There is now a `Nontrivial R` hypothesis available.
  assumption
example {R : Type} [CommRing R] {r s : R} : r * s = s * r := by
  nontriviality -- There is now a `Nontrivial R` hypothesis available.
  apply mul_comm
example {R : Type} [OrderedRing R] {a : R} (h : 0 < a) : (2 : ℕ) ∣ 4 := by
  nontriviality R -- there is now a `Nontrivial R` hypothesis available.
  dec_trivial
def myeq {α : Type} (a b : α) : Prop := a = b

example {α : Type} (a b : α) (h : a = b) : myeq a b := by
  success_if_fail nontriviality α -- Fails
  nontriviality α using myeq -- There is now a `Nontrivial α` hypothesis available
  assumption

Tags:
Defined in module:
Mathlib.Tactic.Nontriviality.Core

norm_num

norm_num normalizes numerical expressions in the goal. By default, it supports the operations + - * / ⁻¹ ^ and % over types with (at least) an AddMonoidWithOne instance, such as , , , , . In addition to evaluating numerical expressions, norm_num will use simp to simplify the goal. If the goal has the form A = B, A ≠ B, A < B or A ≤ B, where A and B are numerical expressions, norm_num will try to close it. It also has a relatively simple primality prover.

This tactic is extensible. Extensions can allow norm_num to evaluate more kinds of expressions, or to prove more kinds of propositions. See the @[norm_num] attribute for further information on extending norm_num.

Examples:

example : 43 ≤ 74 + (33 : ℤ) := by norm_num
example : ¬ (7-2)/(2*3) ≥ (1:ℝ) + 2/(3^2) := by norm_num

Tags:
Defined in module:
Mathlib.Tactic.NormNum.Core

norm_num1

norm_num1 normalizes numerical expressions in the goal. It is a basic version of norm_num that does not call simp.

By default, it supports the operations + - * / ⁻¹ ^ and % over types with (at least) an AddMonoidWithOne instance, such as , , , , . If the goal has the form A = B, A ≠ B, A < B or A ≤ B, where A and B are numerical expressions, norm_num1 will try to close it. It also has a relatively simple primality prover. :e This tactic is extensible. Extensions can allow norm_num1 to evaluate more kinds of expressions, or to prove more kinds of propositions. See the @[norm_num] attribute for further information on extending norm_num1.

Examples:

example : 43 ≤ 74 + (33 : ℤ) := by norm_num1
example : ¬ (7-2)/(2*3) ≥ (1:ℝ) + 2/(3^2) := by norm_num1

Tags:
Defined in module:
Mathlib.Tactic.NormNum.Core

nth_grewrite

nth_grewrite is just like nth_rewrite, but for grewrite.

Tags:
Defined in module:
Mathlib.Tactic.GRewrite.Elab

nth_grw

nth_grw is just like nth_rw, but for grw.

Tags:
Defined in module:
Mathlib.Tactic.GRewrite.Elab

nth_rewrite

nth_rewrite is a variant of rewrite that only changes the n₁, ..., nₖᵗʰ occurrence of the expression to be rewritten. nth_rewrite n₁ ... nₖ [eq₁, eq₂,..., eqₘ] will rewrite the n₁, ..., nₖᵗʰ occurrence of each of the m equalities eqᵢin that order. Occurrences are counted beginning with 1 in order of precedence.

For example,

example (h : a = 1) : a + a + a + a + a = 5 := by
  nth_rewrite 2 3 [h]
/-
a: ℕ
h: a = 1
⊢ a + 1 + 1 + a + a = 5
-/

Notice that the second and third occurrences of a from the left have been rewritten by nth_rewrite.

To understand the importance of order of precedence, consider the example below

example (a b c : Nat) : (a + b) + c = (b + a) + c := by
  nth_rewrite 2 [Nat.add_comm] -- ⊢ (b + a) + c = (b + a) + c

Here, although the occurrence parameter is 2, (a + b) is rewritten to (b + a). This happens because in order of precedence, the first occurrence of _ + _ is the one that adds a + b to c. The occurrence in a + b counts as the second occurrence.

If a term t is introduced by rewriting with eqᵢ, then this instance of t will be counted as an occurrence of t for all subsequent rewrites of t with eqⱼ for j > i. This behaviour is illustrated by the example below

example (h : a = a + b) : a + a + a + a + a = 0 := by
  nth_rewrite 3 [h, h]
/-
a b: ℕ
h: a = a + b
⊢ a + a + (a + b + b) + a + a = 0
-/

Here, the first nth_rewrite with h introduces an additional occurrence of a in the goal. That is, the goal state after the first rewrite looks like below

/-
a b: ℕ
h: a = a + b
⊢ a + a + (a + b) + a + a = 0
-/

This new instance of a also turns out to be the third occurrence of a. Therefore, the next nth_rewrite with h rewrites this a.

Tags:
Defined in module:
Mathlib.Tactic.NthRewrite

nth_rw

nth_rw is a variant of rw that only changes the n₁, ..., nₖᵗʰ occurrence of the expression to be rewritten. Like rw, and unlike nth_rewrite, it will try to close the goal by trying rfl afterwards. nth_rw n₁ ... nₖ [eq₁, eq₂,..., eqₘ] will rewrite the n₁, ..., nₖᵗʰ occurrence of each of the m equalities eqᵢin that order. Occurrences are counted beginning with 1 in order of precedence. For example,

example (h : a = 1) : a + a + a + a + a = 5 := by
  nth_rw 2 3 [h]
/-
a: ℕ
h: a = 1
⊢ a + 1 + 1 + a + a = 5
-/

Notice that the second and third occurrences of a from the left have been rewritten by nth_rw.

To understand the importance of order of precedence, consider the example below

example (a b c : Nat) : (a + b) + c = (b + a) + c := by
  nth_rewrite 2 [Nat.add_comm] -- ⊢ (b + a) + c = (b + a) + c

Here, although the occurrence parameter is 2, (a + b) is rewritten to (b + a). This happens because in order of precedence, the first occurrence of _ + _ is the one that adds a + b to c. The occurrence in a + b counts as the second occurrence.

If a term t is introduced by rewriting with eqᵢ, then this instance of t will be counted as an occurrence of t for all subsequent rewrites of t with eqⱼ for j > i. This behaviour is illustrated by the example below

example (h : a = a + b) : a + a + a + a + a = 0 := by
  nth_rw 3 [h, h]
/-
a b: ℕ
h: a = a + b
⊢ a + a + (a + b + b) + a + a = 0
-/

Here, the first nth_rw with h introduces an additional occurrence of a in the goal. That is, the goal state after the first rewrite looks like below

/-
a b: ℕ
h: a = a + b
⊢ a + a + (a + b) + a + a = 0
-/

This new instance of a also turns out to be the third occurrence of a. Therefore, the next nth_rw with h rewrites this a.

Further, nth_rw will close the remaining goal with rfl if possible.

Tags:
Defined in module:
Mathlib.Tactic.NthRewrite

observe

observe hp : p asserts the proposition p as a hypothesis named hp, and tries to prove it using exact?. If no proof is found, the tactic fails. In other words, this tactic is equivalent to have hp : p := by exact?.

Tags:
Defined in module:
Mathlib.Tactic.Observe

order

A finishing tactic for solving goals in arbitrary Preorder, PartialOrder, or LinearOrder. Supports , , and lattice operations.

Tags:
Defined in module:
Mathlib.Tactic.Order

order_core

order_core is the part of the order tactic that tries to find a contradiction.

Tags:
Defined in module:
Mathlib.Tactic.Order

peel

Peels matching quantifiers off of a given term and the goal and introduces the relevant variables.

There are also variants that apply to an iff in the goal:

Given p q : ℕ → Prop, h : ∀ x, p x, and a goal ⊢ : ∀ x, q x, the tactic peel h with x h' will introduce x : ℕ, h' : p x into the context and the new goal will be ⊢ q x. This works with , as well as ∀ᶠ and ∃ᶠ, and it can even be applied to a sequence of quantifiers. Note that this is a logically weaker setup, so using this tactic is not always feasible.

For a more complex example, given a hypothesis and a goal:

h : ∀ ε > (0 : ℝ), ∃ N : ℕ, ∀ n ≥ N, 1 / (n + 1 : ℝ) < ε
⊢ ∀ ε > (0 : ℝ), ∃ N : ℕ, ∀ n ≥ N, 1 / (n + 1 : ℝ) ≤ ε

(which differ only in </), applying peel h with ε hε N n hn h_peel will yield a tactic state:

h : ∀ ε > (0 : ℝ), ∃ N : ℕ, ∀ n ≥ N, 1 / (n + 1 : ℝ) < ε
ε : ℝ
hε : 0 < ε
N n : ℕ
hn : N ≤ n
h_peel : 1 / (n + 1 : ℝ) < ε
⊢ 1 / (n + 1 : ℝ) ≤ ε

and the goal can be closed with exact h_peel.le. Note that in this example, h and the goal are logically equivalent statements, but peel cannot be immediately applied to show that the goal implies h.

In addition, peel supports goals of the form (∀ x, p x) ↔ ∀ x, q x, or likewise for any other quantifier. In this case, there is no hypothesis or term to supply, but otherwise the syntax is the same. So for such goals, the syntax is peel 1 or peel with x, and after which the resulting goal is p x ↔ q x. The congr! tactic can also be applied to goals of this form using congr! 1 with x. While congr! applies congruence lemmas in general, peel can be relied upon to only apply to outermost quantifiers.

Finally, the user may supply a term e via ... using e in order to close the goal immediately. In particular, peel h using e is equivalent to peel h; exact e. The using syntax may be paired with any of the other features of peel.

This tactic works by repeatedly applying lemmas such as forall_imp, Exists.imp, Filter.Eventually.mp, Filter.Frequently.mp, and Filter.Eventually.of_forall.

Tags:
Defined in module:
Mathlib.Tactic.Peel

pgame_wf_tac

Discharges proof obligations of the form ⊢ Subsequent .. arising in termination proofs of definitions using well-founded recursion on PGame.

Tags:
Defined in module:
Mathlib.SetTheory.PGame.Basic

pi_lower_bound

Create a proof of a < π for a fixed rational number a, given a witness, which is a sequence of rational numbers √2 < r 1 < r 2 < ... < r n < 2 satisfying the property that √(2 + r i) ≤ r(i+1), where r 0 = 0 and √(2 - r n) ≥ a/2^(n+1).

Tags:
Defined in module:
Mathlib.Analysis.Real.Pi.Bounds

pi_upper_bound

Create a proof of π < a for a fixed rational number a, given a witness, which is a sequence of rational numbers √2 < r 1 < r 2 < ... < r n < 2 satisfying the property that √(2 + r i) ≥ r(i+1), where r 0 = 0 and √(2 - r n) ≤ (a - 1/4^n) / 2^(n+1).

Tags:
Defined in module:
Mathlib.Analysis.Real.Pi.Bounds

pnat_positivity

For each x : PNat in the context, add the hypothesis 0 < (↑x : ℕ).

Tags:
Defined in module:
Mathlib.Tactic.PNatToNat

pnat_to_nat

pnat_to_nat shifts all PNats in the context to Nat, rewriting propositions about them. A typical use case is pnat_to_nat; lia.

Tags:
Defined in module:
Mathlib.Tactic.PNatToNat

polyrith

The polyrith tactic is no longer supported in Mathlib, because it relied on a defunct external service.


Attempts to prove polynomial equality goals through polynomial arithmetic on the hypotheses (and additional proof terms if the user specifies them). It proves the goal by generating an appropriate call to the tactic linear_combination. If this call succeeds, the call to linear_combination is suggested to the user.

Notes:

Tags:
Defined in module:
Mathlib.Tactic.Polyrith

positivity

Tactic solving goals of the form 0 ≤ x, 0 < x and x ≠ 0. The tactic works recursively according to the syntax of the expression x, if the atoms composing the expression all have numeric lower bounds which can be proved positive/nonnegative/nonzero by norm_num. This tactic either closes the goal or fails.

positivity [t₁, …, tₙ] first executes have := t₁; …; have := tₙ in the current goal, then runs positivity. This is useful when positivity needs derived premises such as 0 < y for division/reciprocal, or 0 ≤ x for real powers.

Examples:

example {a : ℤ} (ha : 3 < a) : 0 ≤ a ^ 3 + a := by positivity

example {a : ℤ} (ha : 1 < a) : 0 < |(3:ℤ) + a| := by positivity

example {b : ℤ} : 0 ≤ max (-3) (b ^ 2) := by positivity

example {a b c d : ℝ} (hab : 0 < a * b) (hb : 0 ≤ b) (hcd : c < d) :
    0 < a ^ c + 1 / (d - c) := by
  positivity [sub_pos_of_lt hcd, pos_of_mul_pos_left hab hb]

Tags:
Defined in module:
Mathlib.Tactic.Positivity.Core

pull

pull c rewrites the goal by pulling the constant c closer to the head of the expression. For instance, pull _ ∈ _ rewrites x ∈ y ∨ ¬ x ∈ z into x ∈ y ∪ zᶜ. More precisely, the pull tactic repeatedly rewrites an expression by applying lemmas of the form ... (c ...) = c ... (where c can appear 1 or more times on the left hand side). pull is the inverse tactic to push. To extend the pull tactic, you can tag a lemma with the @[push] attribute. pull works as both a tactic and a conv tactic.

A lemma is considered a pull lemma if its reverse direction is a push lemma that actually moves the given constant away from the head. For example

TODO: define a @[pull] attribute for tagging pull lemmas that are not push lemmas.

Examples:

Tags:
Defined in module:
Mathlib.Tactic.Push

pure_coherence

pure_coherence uses the coherence theorem for monoidal categories to prove the goal. It can prove any equality made up only of associators, unitors, and identities.

example {C : Type} [Category* C] [MonoidalCategory C] :
  (λ_ (𝟙_ C)).hom = (ρ_ (𝟙_ C)).hom := by
  pure_coherence

Users will typically just use the coherence tactic, which can also cope with identities of the form a ≫ f ≫ b ≫ g ≫ c = a' ≫ f ≫ b' ≫ g ≫ c' where a = a', b = b', and c = c' can be proved using pure_coherence

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.Coherence

push

push c rewrites the goal by pushing the constant c deeper into an expression. For instance, push _ ∈ _ rewrites x ∈ {y} ∪ zᶜ into x = y ∨ ¬ x ∈ z. More precisely, the push tactic repeatedly rewrites an expression by applying lemmas of the form c ... = ... (c ...) (where c can appear 0 or more times on the right hand side). To extend the push tactic, you can tag a lemma of this form with the @[push] attribute.

To instead move a constant closer to the head of the expression, use the pull tactic.

push works as both a tactic and a conv tactic.

Examples:

Tags:
Defined in module:
Mathlib.Tactic.Push

push_neg

push_neg rewrites the goal by pushing negations deeper into an expression. For instance, the goal ¬ ∀ x, ∃ y, x ≤ y will be transformed by push_neg into ∃ x, ∀ y, y < x. Binder names are preserved (contrary to what would happen with simp using the relevant lemmas). push_neg works as both a tactic and a conv tactic.

push_neg is a special case of the more general push tactic, namely push Not. The push tactic can be extended using the @[push] attribute. push has special-casing built in for push Not.

Tactics that introduce a negation usually have a version that automatically calls push_neg on that negation. These include by_cases!, contrapose! and by_contra!.

Example:

example (h : ¬ ∀ ε > 0, ∃ δ > 0, ∀ x, |x - x₀| ≤ δ → |f x - y₀| ≤ ε) :
    ∃ ε > 0, ∀ δ > 0, ∃ x, |x - x₀| ≤ δ ∧ ε < |f x - y₀| := by
  push_neg at h
  -- Now we have the hypothesis `h : ∃ ε > 0, ∀ δ > 0, ∃ x, |x - x₀| ≤ δ ∧ ε < |f x - y₀|`
  exact h

Tags:
Defined in module:
Mathlib.Tactic.Push

qify

The qify tactic is used to shift propositions from or to . This is often useful since has well-behaved division.

example (a b c x y z : ℕ) (h : ¬ x*y*z < 0) : c < a + 3*b := by
  qify
  qify at h
  /-
  h : ¬↑x * ↑y * ↑z < 0
  ⊢ ↑c < ↑a + 3 * ↑b
  -/
  sorry

qify can be given extra lemmas to use in simplification. This is especially useful in the presence of nat subtraction: passing arguments will allow push_cast to do more work.

example (a b c : ℤ) (h : a / b = c) (hab : b ∣ a) (hb : b ≠ 0) : a = c * b := by
  qify [hab] at h hb ⊢
  exact (div_eq_iff hb).1 h

qify makes use of the @[zify_simps] and @[qify_simps] attributes to move propositions, and the push_cast tactic to simplify the -valued expressions.

Tags:
Defined in module:
Mathlib.Tactic.Qify

recover

recover tacs applies the tactic (sequence) tacs and then re-adds goals that were incorrectly marked as closed. This helps to debug issues where a tactic closes goals without solving them (i.e. goals were removed from the MetaM state without the metavariable being assigned), resulting in the error "(kernel) declaration has metavariables".

Tags:
Defined in module:
Mathlib.Tactic.Recover

reduce

reduce at loc completely reduces the given location. This also exists as a conv-mode tactic.

This does the same transformation as the #reduce command.

Tags:
Defined in module:
Mathlib.Tactic.DefEqTransformations

reduce_mod_char

The tactic reduce_mod_char looks for numeric expressions in characteristic p and reduces these to lie between 0 and p.

For example:

example : (5 : ZMod 4) = 1 := by reduce_mod_char
example : (X ^ 2 - 3 * X + 4 : (ZMod 4)[X]) = X ^ 2 + X := by reduce_mod_char

It also handles negation, turning it into multiplication by p - 1, and similarly subtraction.

This tactic uses the type of the subexpression to figure out if it is indeed of positive characteristic, for improved performance compared to trying to synthesise a CharP instance. The variant reduce_mod_char! also tries to use CharP R n hypotheses in the context. (Limitations of the typeclass system mean the tactic can't search for a CharP R n instance if n is not yet known; use have : CharP R n := inferInstance; reduce_mod_char! as a workaround.)

Tags:
Defined in module:
Mathlib.Tactic.ReduceModChar

refold_let

refold_let x y z at loc looks for the bodies of local definitions x, y, and z at the given location and replaces them with x, y, or z. This is the inverse of "zeta reduction." This also exists as a conv-mode tactic.

Tags:
Defined in module:
Mathlib.Tactic.DefEqTransformations

rel

The rel tactic applies "generalized congruence" rules to solve a relational goal by "substitution". For example,

example {a b x c d : ℝ} (h1 : a ≤ b) (h2 : c ≤ d) :
    x ^ 2 * a + c ≤ x ^ 2 * b + d := by
  rel [h1, h2]

In this example we "substitute" the hypotheses a ≤ b and c ≤ d into the LHS x ^ 2 * a + c of the goal and obtain the RHS x ^ 2 * b + d, thus proving the goal.

The "generalized congruence" rules used are the library lemmas which have been tagged with the attribute @[gcongr]. For example, the first example constructs the proof term

add_le_add (mul_le_mul_of_nonneg_left h1 (pow_bit0_nonneg x 1)) h2

using the generalized congruence lemmas add_le_add and mul_le_mul_of_nonneg_left. If there are no applicable generalized congruence lemmas, the tactic fails.

The tactic attempts to discharge side goals to these "generalized congruence" lemmas (such as the side goal 0 ≤ x ^ 2 in the above application of mul_le_mul_of_nonneg_left) using the tactic gcongr_discharger, which wraps positivity but can also be extended. If the side goals cannot be discharged in this way, the tactic fails.

Tags:
Defined in module:
Mathlib.Tactic.GCongr.Core

rename'

rename' h => hnew renames the hypothesis named h to hnew. To rename several hypothesis, use rename' h₁ => h₁new, h₂ => h₂new. You can use rename' a => b, b => a to swap two variables.

Tags:
Defined in module:
Mathlib.Tactic.Rename

rename_bvar

example (P : ℕ → ℕ → Prop) (h : ∀ n, ∃ m, P n m) : ∀ l, ∃ m, P l m := by
  rename_bvar n → q at h -- h is now ∀ (q : ℕ), ∃ (m : ℕ), P q m,
  rename_bvar m → n -- target is now ∀ (l : ℕ), ∃ (n : ℕ), P k n,
  exact h -- Lean does not care about those bound variable names

Note: name clashes are resolved automatically.

Tags:
Defined in module:
Mathlib.Tactic.RenameBVar

repeat1

repeat1 tac applies tac to main goal at least once. If the application succeeds, the tactic is applied recursively to the generated subgoals until it eventually fails.

Tags:
Defined in module:
Mathlib.Tactic.Core

replace

Acts like have, but removes a hypothesis with the same name as this one if possible. For example, if the state is:

Then after replace h : β the state will be:

case h
f : α → β
h : α
⊢ β

f : α → β
h : β
⊢ goal

whereas have h : β would result in:

case h
f : α → β
h : α
⊢ β

f : α → β
h✝ : α
h : β
⊢ goal

Tags:
Defined in module:
Mathlib.Tactic.Replace

restrict_tac

restrict_tac solves relations among subsets (copied from aesop cat)

Tags:
Defined in module:
Mathlib.Topology.Sheaves.Presheaf

restrict_tac?

restrict_tac? passes along Try this from aesop

Tags:
Defined in module:
Mathlib.Topology.Sheaves.Presheaf

rewrite!

rewrite! is like rewrite, but can also insert casts to adjust types that depend on the LHS of a rewrite. It is available as an ordinary tactic and a conv tactic.

The sort of casts that are inserted is controlled by the castMode configuration option. By default, only proof terms are casted; by proof irrelevance, this adds no observable complexity.

With rewrite! +letAbs (castMode := .all), casts are inserted whenever necessary. This means that the 'motive is not type correct' error never occurs, at the expense of creating potentially complicated terms.

Tags:
Defined in module:
Mathlib.Tactic.DepRewrite

rfl_cat

rfl_cat is a macro for intros; rfl which is attempted in aesop_cat before doing the more expensive aesop tactic.

This gives a speedup because simp (called by aesop) can be very slow. https://github.com/leanprover-community/mathlib4/pull/25475 contains measurements from June 2025.

Implementation notes:

Tags:
Defined in module:
Mathlib.CategoryTheory.Category.Basic

rify

The rify tactic is used to shift propositions from , or to . Although less useful than its cousins zify and qify, it can be useful when your goal or context already involves real numbers.

In the example below, assumption hn is about natural numbers, hk is about integers and involves casting a natural number to , and the conclusion is about real numbers. The proof uses rify to lift both assumptions to before calling linarith.

example {n : ℕ} {k : ℤ} (hn : 8 ≤ n) (hk : 2 * k ≤ n + 2) :
    (0 : ℝ) < n - k - 1 := by
  rify at hn hk /- Now have hn : 8 ≤ (n : ℝ)   hk : 2 * (k : ℝ) ≤ (n : ℝ) + 2 -/
  linarith

rify makes use of the @[zify_simps], @[qify_simps] and @[rify_simps] attributes to move propositions, and the push_cast tactic to simplify the -valued expressions.

rify can be given extra lemmas to use in simplification. This is especially useful in the presence of nat subtraction: passing arguments will allow push_cast to do more work.

example (a b c : ℕ) (h : a - b < c) (hab : b ≤ a) : a < b + c := by
  rify [hab] at h ⊢
  linarith

Note that zify or qify would work just as well in the above example (and zify is the natural choice since it is enough to get rid of the pathological subtraction).

Tags:
Defined in module:
Mathlib.Tactic.Rify

ring

ring solves equations in commutative (semi)rings, allowing for variables in the exponent. If the goal is not appropriate for ring (e.g. not an equality) ring_nf will be suggested. See also ring1, which fails if the goal is not an equality.

Examples:

example (n : ℕ) (m : ℤ) : 2^(n+1) * m = 2 * 2^n * m := by ring
example (a b : ℤ) (n : ℕ) : (a + b)^(n + 2) = (a^2 + b^2 + a * b + b * a) * (a + b)^n := by ring
example (x y : ℕ) : x + id y = y + id x := by ring!
example (x : ℕ) (h : x * 2 > 5): x + x > 5 := by ring; assumption -- suggests ring_nf

Tags:
Defined in module:
Mathlib.Tactic.Ring.RingNF

ring1

ring1 solves the goal when it is an equality in commutative (semi)rings, allowing variables in the exponent.

This version of ring fails if the target is not an equality.

Extensions:

Tags:
Defined in module:
Mathlib.Tactic.Ring.Basic

ring_nf

ring_nf simplifies expressions in the language of commutative (semi)rings, which rewrites all ring expressions into a normal form, allowing variables in the exponents.

ring_nf works as both a tactic and a conv tactic.

See also the ring tactic for solving a goal which is an equation in the language of commutative (semi)rings.

Examples: This can be used non-terminally to normalize ring expressions in the goal such as ⊢ P (x + x + x) ~> ⊢ P (x * 3), as well as being able to prove some equations that ring cannot because they involve ring reasoning inside a subterm, such as sin (x + y) + sin (y + x) = 2 * sin (x + y).

Tags:
Defined in module:
Mathlib.Tactic.Ring.RingNF

rsuffices

The rsuffices tactic is an alternative version of suffices, that allows the usage of any syntax that would be valid in an obtain block. This tactic just calls obtain on the expression, and then rotate_left.

Tags:
Defined in module:
Mathlib.Tactic.RSuffices

rw!

rw! is like rewrite!, but also cleans up introduced refl-casts after every substitution. It is available as an ordinary tactic and a conv tactic.

Tags:
Defined in module:
Mathlib.Tactic.DepRewrite

rw??

rw?? is an interactive tactic that suggests rewrites for any expression selected by the user. To use it, shift-click an expression in the goal or a hypothesis that you want to rewrite. Clicking on one of the rewrite suggestions will paste the relevant rewrite tactic into the editor.

The rewrite suggestions are grouped and sorted by the pattern that the rewrite lemmas match with. Rewrites that don't change the goal and rewrites that create the same goal as another rewrite are filtered out, as well as rewrites that have new metavariables in the replacement expression. To see all suggestions, click on the filter button (▼) in the top right.

Tags:
Defined in module:
Mathlib.Tactic.Widget.LibraryRewrite

rw_search

rw_search has been removed from Mathlib.

Tags:
Defined in module:
Mathlib.Tactic.RewriteSearch

says

If you write X says, where X is a tactic that produces a "Try this: Y" message, then you will get a message "Try this: X says Y". Once you've clicked to replace X says with X says Y, afterwards X says Y will only run Y.

The typical usage case is:

simp? [X] says simp only [X, Y, Z]

If you use set_option says.verify true (set automatically during CI) then X says Y runs X and verifies that it still prints "Try this: Y".

Tags:
Defined in module:
Mathlib.Tactic.Says

set

set a := t with h is a variant of let a := t. It adds the hypothesis h : a = t to the local context and replaces t with a everywhere it can.

set a := t with ← h will add h : t = a instead.

set! a := t with h does not do any replacing.

example (x : Nat) (h : x + x - x = 3) : x + x - x = 3 := by
  set y := x with ← h2
  sorry
/-
x : Nat
y : Nat := x
h : y + y - y = 3
h2 : x = y
⊢ y + y - y = 3
-/

Tags:
Defined in module:
Mathlib.Tactic.Set

simp_intro

The simp_intro tactic is a combination of simp and intro: it will simplify the types of variables as it introduces them and uses the new variables to simplify later arguments and the goal.

example : x + 0 = y → x = z := by
  simp_intro h
  -- h: x = y ⊢ y = z
  sorry

Tags:
Defined in module:
Mathlib.Tactic.SimpIntro

simp_rw

simp_rw functions as a mix of simp and rw. Like rw, it applies each rewrite rule in the given order, but like simp it repeatedly applies these rules and also under binders like ∀ x, ..., ∃ x, ... and fun x ↦.... Usage:

Lemmas passed to simp_rw must be expressions that are valid arguments to simp. For example, neither simp nor rw can solve the following, but simp_rw can:

example {a : ℕ}
    (h1 : ∀ a b : ℕ, a - 1 ≤ b ↔ a ≤ b + 1)
    (h2 : ∀ a b : ℕ, a ≤ b ↔ ∀ c, c < a → c < b) :
    (∀ b, a - 1 ≤ b) = ∀ b c : ℕ, c < a → c < b + 1 := by
  simp_rw [h1, h2]

Tags:
Defined in module:
Mathlib.Tactic.SimpRw

sleep_heartbeats

do nothing for at least n heartbeats

Tags:
Defined in module:
Mathlib.Util.SleepHeartbeats

slice_lhs

slice_lhs a b => tac zooms to the left-hand side, uses associativity for categorical composition as needed, zooms in on the a-th through b-th morphisms, and invokes tac.

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.Slice

slice_rhs

slice_rhs a b => tac zooms to the right-hand side, uses associativity for categorical composition as needed, zooms in on the a-th through b-th morphisms, and invokes tac.

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.Slice

smul_tac

Solve equations for RatFunc K by applying RatFunc.induction_on.

Tags:
Defined in module:
Mathlib.FieldTheory.RatFunc.Basic

sorry_if_sorry

Close the main goal with sorry if its type contains sorry, and fail otherwise.

Tags:
Defined in module:
Mathlib.CategoryTheory.Category.Basic

specialize_all

specialize_all x runs specialize h x for all hypotheses h where this tactic succeeds.

Tags:
Defined in module:
Mathlib.Tactic.TautoSet

split_ifs

Splits all if-then-else-expressions into multiple goals. Given a goal of the form g (if p then x else y), split_ifs will produce two goals: p ⊢ g x and ¬p ⊢ g y. If there are multiple ite-expressions, then split_ifs will split them all, starting with a top-most one whose condition does not contain another ite-expression. split_ifs at * splits all ite-expressions in all hypotheses as well as the goal. split_ifs with h₁ h₂ h₃ overrides the default names for the hypotheses.

Tags:
Defined in module:
Mathlib.Tactic.SplitIfs

subsingleton

The subsingleton tactic tries to prove a goal of the form x = y or x ≍ y using the fact that the types involved are subsingletons (a type with exactly zero or one terms). To a first approximation, it does apply Subsingleton.elim. As a nicety, subsingleton first runs the intros tactic.

Techniques the subsingleton tactic can apply:

Properties #

The tactic is careful not to accidentally specialize Sort _ to Prop, avoiding the following surprising behavior of apply Subsingleton.elim:

example (α : Sort _) (x y : α) : x = y := by apply Subsingleton.elim

The reason this example goes through is that it applies the ∀ (p : Prop), Subsingleton p instance, specializing the universe level metavariable in Sort _ to 0.

Tags:
Defined in module:
Mathlib.Tactic.Subsingleton

subst_hom_lift

subst_hom_lift p f φ tries to substitute f with p(φ) by using p.IsHomLift f φ

Tags:
Defined in module:
Mathlib.CategoryTheory.FiberedCategory.HomLift

substs

Applies the subst tactic to all given hypotheses from left to right.

Tags:
Defined in module:
Mathlib.Tactic.Substs

success_if_fail_with_msg

success_if_fail_with_msg msg tacs runs tacs and succeeds only if they fail with the message msg.

msg can be any term that evaluates to an explicit String.

Tags:
Defined in module:
Mathlib.Tactic.SuccessIfFailWithMsg

swap_var

swap_var swap_rule₁, swap_rule₂, ⋯ applies swap_rule₁ then swap_rule₂ then .

A swap_rule is of the form x y or x ↔ y, and "applying it" means swapping the variable name x by y and vice-versa on all hypotheses and the goal.

example {P Q : Prop} (q : P) (p : Q) : P ∧ Q := by
  swap_var p ↔ q
  exact ⟨p, q⟩

Tags:
Defined in module:
Mathlib.Tactic.SwapVar

tauto

tauto breaks down assumptions of the form _ ∧ _, _ ∨ _, _ ↔ _ and ∃ _, _ and splits a goal of the form _ ∧ _, _ ↔ _ or ∃ _, _ until it can be discharged using rfl or solve_by_elim. This is a finishing tactic: it either closes the goal or raises an error.

The Lean 3 version of this tactic by default attempted to avoid classical reasoning where possible. This Lean 4 version makes no such attempt. The itauto tactic is designed for that purpose.

Tags:
Defined in module:
Mathlib.Tactic.Tauto

tauto_set

tauto_set attempts to prove tautologies involving hypotheses and goals of the form X ⊆ Y or X = Y, where X, Y are expressions built using ∪, ∩, , and ᶜ from finitely many variables of type Set α. It also unfolds expressions of the form Disjoint A B and symmDiff A B.

Examples:

example {α} (A B C D : Set α) (h1 : A ⊆ B) (h2 : C ⊆ D) : C \ B ⊆ D \ A := by
  tauto_set

example {α} (A B C : Set α) (h1 : A ⊆ B ∪ C) : (A ∩ B) ∪ (A ∩ C) = A := by
  tauto_set

Tags:
Defined in module:
Mathlib.Tactic.TautoSet

tfae_finish

tfae_finish closes goals of the form TFAE [P₁, P₂, ...] once a sufficient collection of hypotheses of the form Pᵢ → Pⱼ or Pᵢ ↔ Pⱼ have been introduced to the local context.

tfae_have can be used to conveniently introduce these hypotheses; see tfae_have.

Example:

example : TFAE [P, Q, R] := by
  tfae_have 1 → 2 := sorry /- proof of P → Q -/
  tfae_have 2 → 1 := sorry /- proof of Q → P -/
  tfae_have 2 ↔ 3 := sorry /- proof of Q ↔ R -/
  tfae_finish

Tags:
Defined in module:
Mathlib.Tactic.TFAE

tfae_have

tfae_have i → j := t, where the goal is TFAE [P₁, P₂, ...] introduces a hypothesis tfae_i_to_j : Pᵢ → Pⱼ and proof t to the local context. Note that i and j are natural number literals (beginning at 1) used as indices to specify the propositions P₁, P₂, ... that appear in the goal.

Once sufficient hypotheses have been introduced by tfae_have, tfae_finish can be used to close the goal.

All features of have are supported by tfae_have, including naming, matching, destructuring, and goal creation.

Examples:

example (h : P → R) : TFAE [P, Q, R] := by
  tfae_have 1 → 3 := h
  -- The resulting context now includes `tfae_1_to_3 : P → R`.
  sorry
-- An example of `tfae_have` and `tfae_finish`:
example : TFAE [P, Q, R] := by
  tfae_have 1 → 2 := sorry /- proof of P → Q -/
  tfae_have 2 → 1 := sorry /- proof of Q → P -/
  tfae_have 2 ↔ 3 := sorry /- proof of Q ↔ R -/
  tfae_finish
-- All features of `have` are supported by `tfae_have`:
example : TFAE [P, Q] := by
  -- assert `tfae_1_to_2 : P → Q`:
  tfae_have 1 → 2 := sorry

  -- assert `hpq : P → Q`:
  tfae_have hpq : 1 → 2 := sorry

  -- match on `p : P` and prove `Q` via `f p`:
  tfae_have 1 → 2
  | p => f p

  -- assert `pq : P → Q`, `qp : Q → P`:
  tfae_have ⟨pq, qp⟩ : 1 ↔ 2 := sorry

  -- assert `h : P → Q`; `?a` is a new goal:
  tfae_have h : 1 → 2 := f ?a

  sorry

Tags:
Defined in module:
Mathlib.Tactic.TFAE

toFinite_tac

A tactic (for use in default params) that applies Set.toFinite to synthesize a Set.Finite term.

Tags:
Defined in module:
Mathlib.Data.Set.Card

to_encard_tac

A tactic useful for transferring proofs for encard to their corresponding card statements

Tags:
Defined in module:
Mathlib.Data.Set.Card

trace

Evaluates a term to a string (when possible), and prints it as a trace message.

Tags:
Defined in module:
Mathlib.Tactic.Trace

try_this

Produces the text Try this: <tac> with the given tactic, and then executes it.

Tags:
Defined in module:
Mathlib.Tactic.TryThis

type_check

Type check the given expression, and trace its type.

Tags:
Defined in module:
Mathlib.Tactic.TypeCheck

unfold?

Replace the selected expression with a definitional unfolding.

To use unfold?, shift-click an expression in the tactic state. This gives a list of rewrite suggestions for the selected expression. Click on a suggestion to replace unfold? by a tactic that performs this rewrite.

Tags:
Defined in module:
Mathlib.Tactic.Widget.InteractiveUnfold

unfold_projs

unfold_projs at loc unfolds projections of class instances at the given location. This also exists as a conv-mode tactic.

Tags:
Defined in module:
Mathlib.Tactic.DefEqTransformations

uniqueDiffWithinAt_Ici_Iic_univ

An auxiliary tactic closing goals UniqueDiffWithinAt ℝ s a where s ∈ {Iic a, Ici a, univ}.

Tags:
Defined in module:
Mathlib.MeasureTheory.Integral.IntervalIntegral.FundThmCalculus

unit_interval

A tactic that solves 0 ≤ ↑x, 0 ≤ 1 - ↑x, ↑x ≤ 1, and 1 - ↑x ≤ 1 for x : I.

Tags:
Defined in module:
Mathlib.Topology.UnitInterval

use

use e₁, e₂, ⋯ is similar to exists, but unlike exists it is equivalent to applying the tactic refine ⟨e₁, e₂, ⋯, ?_, ⋯, ?_⟩ with any number of placeholders (rather than just one) and then trying to close goals associated to the placeholders with a configurable discharger (rather than just try trivial).

Examples:

example : ∃ x : Nat, x = x := by use 42

example : ∃ x : Nat, ∃ y : Nat, x = y := by use 42, 42

example : Nonempty Nat := by use 5

example : Nonempty (PNat ≃ Nat) := by
  use PNat.natPred, Nat.succPNat
  · exact PNat.succPNat_natPred
  · intro; rfl

use! e₁, e₂, ⋯ is similar but it applies constructors everywhere rather than just for goals that correspond to the last argument of a constructor. This gives the effect that nested constructors are being flattened out, with the supplied values being used along the leaves and nodes of the tree of constructors. With use! one can feed in each 42 one at a time:

example : ∃ n : {n : Nat // n % 2 = 0}, n.val > 10 := by use! 20; simp

example : ∃ p : Nat × Nat, p.1 = p.2 := by use! (42, 42)

The second line makes use of the fact that use! tries refining with the argument before applying a constructor. Also note that use/use! by default uses a tactic called use_discharger to discharge goals, so use! 42 will close the goal in this example since use_discharger applies rfl, which as a consequence solves for the other Nat metavariable.

These tactics take an optional discharger to handle remaining explicit Prop constructor arguments. By default it is use (discharger := try with_reducible use_discharger) e₁, e₂, ⋯. To turn off the discharger and keep all goals, use (discharger := skip). To allow "heavy refls", use (discharger := try use_discharger).

Tags:
Defined in module:
Mathlib.Tactic.Use

use_discharger

Default discharger to try to use for the use and use! tactics. This is similar to the trivial tactic but doesn't do things like contradiction or decide.

Tags:
Defined in module:
Mathlib.Tactic.Use

use_finite_instance

Try using Set.toFinite to dispatch a Set.Finite goal.

Tags:
Defined in module:
Mathlib.LinearAlgebra.Dual.Basis

valid

A wrapper for omega which prefaces it with some quick and useful attempts

Tags:
Defined in module:
Mathlib.CategoryTheory.ComposableArrows.Basic

volume_tac

The tactic exact volume, to be used in optional (autoParam) arguments.

Tags:
Defined in module:
Mathlib.MeasureTheory.Measure.MeasureSpaceDef

whisker_simps

Simp lemmas for rewriting a 2-morphism into a normal form.

Tags:
Defined in module:
Mathlib.Tactic.CategoryTheory.BicategoryCoherence

whnf

whnf at loc puts the given location into weak-head normal form. This also exists as a conv-mode tactic.

Weak-head normal form is when the outer-most expression has been fully reduced, the expression may contain subexpressions which have not been reduced.

Tags:
Defined in module:
Mathlib.Tactic.DefEqTransformations

witt_truncateFun_tac

A macro tactic used to prove that truncateFun respects ring operations.

Tags:
Defined in module:
Mathlib.RingTheory.WittVector.Truncated

wlog

wlog h : P adds an assumption h : P to the main goal, and adds a side goal that requires showing that the case h : ¬ P can be reduced to the case where P holds (typically by symmetry). The side goal will be at the top of the stack. In this side goal, there will be two additional assumptions:

Tags:
Defined in module:
Mathlib.Tactic.WLOG

zify

The zify tactic is used to shift propositions from Nat to Int. This is often useful since Int has well-behaved subtraction.

example (a b c x y z : Nat) (h : ¬ x*y*z < 0) : c < a + 3*b := by
  zify
  zify at h
  /-
  h : ¬↑x * ↑y * ↑z < 0
  ⊢ ↑c < ↑a + 3 * ↑b
  -/

zify can be given extra lemmas to use in simplification. This is especially useful in the presence of nat subtraction: passing arguments will allow push_cast to do more work.

example (a b c : Nat) (h : a - b < c) (hab : b ≤ a) : false := by
  zify [hab] at h
  /- h : ↑a - ↑b < ↑c -/

zify makes use of the @[zify_simps] attribute to move propositions, and the push_cast tactic to simplify the Int-valued expressions. zify is in some sense dual to the lift tactic. lift (z : Int) to Nat will change the type of an integer z (in the supertype) to Nat (the subtype), given a proof that z ≥ 0; propositions concerning z will still be over Int. zify changes propositions about Nat (the subtype) to propositions about Int (the supertype), without changing the type of any variable.

Tags:
Defined in module:
Mathlib.Tactic.Zify