Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/leanprover-community/mathlib4/llms.txt

Use this file to discover all available pages before exploring further.

Beyond arithmetic and simplification, Mathlib offers a collection of automation tactics that can close whole classes of goals with minimal user input. These range from complete decision procedures for finite computations (decide, native_decide) through propositional logic solvers (tauto) and general proof search (aesop) to domain-specific provers for positivity, continuity, measurability, and other function properties. Knowing which tool fits a given goal can make the difference between a one-line proof and a lengthy manual argument.

decide and native_decide

decide proves any goal whose type is a Decidable proposition by running the kernel’s evaluator on the decision procedure. It is complete for decidable goals but can be very slow for large computations because the Lean kernel performs each reduction step in the type theory. native_decide works identically but compiles the decision procedure to native code before running it. This makes it orders of magnitude faster for computationally intensive goals, such as primality tests or large finite-set membership checks.
example : 2 + 2 = 4 := by decide

example : ¬ (3 = 5) := by decide

-- Works on finite types and decidable predicates
example : ∀ b : Bool, b || true = true := by decide

example : (10 : Fin 100).val < 50 := by decide
native_decide generates a proof that invokes compiled native code, which is not re-checked by the Lean kernel at verification time. Unlike sorry, it does produce a genuine certificate — but correctness depends on the native compiler and runtime producing the right answer. The proof is accepted without kernel-level reduction, so it adds a trusted-code dependency to your proof. Use it only when decide is too slow and the goal is clearly decidable.

tauto

tauto (also written itauto for the intuitionistic version) proves propositional tautologies in classical logic. It handles goals built from , , , ¬, , True, and False by exhaustive case analysis.
example (p q : Prop) : p ∧ q → q ∧ p := by tauto

example (p q r : Prop) : (p → q) → (q → r) → p → r := by tauto

example (p : Prop) : p ∨ ¬ p := by tauto

-- tauto handles longer tautologies automatically
example (a b c d : Prop) : ((a → b) ∧ (c → d)) → (a ∨ c) → (b ∨ d) := by tauto
tauto works on propositional goals only — it does not understand quantifiers or arithmetic. For goals mixing logic and arithmetic, use aesop or a manual decomposition.

aesop

aesop is Mathlib’s general-purpose proof search tactic. It combines forward reasoning, backward chaining, and simp-based normalization to explore a search tree of possible proof steps. It is extensible: users and library authors can tag lemmas with @[aesop] to register them as search rules.
-- aesop can close many structural goals
example (s t : Set α) (h : s ⊆ t) (x : α) (hx : x ∈ s) : x ∈ t := by
  aesop

-- Works well on goals involving membership, subsets, and basic logic
example (p q : Prop) (hp : p) (hq : q) : p ∧ q := by aesop

-- aesop? prints the proof it found
example (h : α → β) (ha : α) : β := by aesop
You can register your own lemmas as aesop rules using the @[aesop] attribute:
-- Register as a forward rule (apply when preconditions are met)
@[aesop forward]
theorem myLemma (h : P x) : Q x := ...

-- Register as a safe rule (always apply without branching)
@[aesop safe apply]
theorem trivialStep : P → P := id

-- Register as a norm rule (used for normalization, like simp)
@[aesop norm simp]
theorem mySimp : f (g x) = x := ...
See the Mathlib.Tactic.Aesop documentation for the full rule syntax.
aesop is best used when other tactics don’t quite apply and the goal has a structural feel. For purely arithmetic goals, prefer linarith, omega, or norm_num. For goals involving coercions, use norm_cast first.

positivity

positivity proves goals of the form 0 ≤ e, 0 < e, or e ≠ 0 by decomposing the expression e and applying positivity/nonnegativity lemmas for each operation. It understands:
  • Arithmetic: +, *, ^, /, |·| (absolute value)
  • Special functions: Real.sqrt, n ! (factorial), Nat.choose
  • Sums and products: ,
  • Conditional expressions: ite, max, min
example (x : ℝ) : 0 ≤ x ^ 2 := by positivity

example (n : ℕ) : 0 < n.factorial := by positivity

example (x y : ℝ) (hx : 0 < x) (hy : 0 < y) : 0 < x * y := by positivity

example (x : ℝ) : 0 ≤ |x| := by positivity

-- Works on sums and products when each term is nonneg
example (f : ℕ → ℝ) (hf : ∀ i, 0 ≤ f i) (s : Finset ℕ) :
    0 ≤ ∑ i ∈ s, f i := by positivity
-- positivity handles Real.sqrt
example (x : ℝ) : 0 ≤ Real.sqrt x := by positivity

-- positivity handles NNReal and ENNReal
example (x : ℝ≥0) : (0 : ℝ≥0) ≤ x := by positivity

-- positivity handles norms
example (v : EuclideanSpace ℝ (Fin 3)) : 0 ≤ ‖v‖ := by positivity
positivity is extensible via the @[positivity] attribute. Mathlib uses this to teach it about Real.sqrt, Nat.factorial, abs, and many other functions. You can write your own positivity extensions for custom operations.

continuity

continuity proves goals of the form Continuous f, ContinuousAt f x, or ContinuousOn f s by composing continuity lemmas. It works by breaking down the function into primitive components (arithmetic operations, polynomials, standard functions) and applying the corresponding lemmas.
example : Continuous (fun x : ℝ => x ^ 2 + 1) := by continuity

example : Continuous (fun x : ℝ => Real.exp x + Real.sin x) := by continuity

example : ContinuousOn (fun x : ℝ => 1 / x) {x | x ≠ 0} := by
  apply ContinuousOn.div continuousOn_const continuousOn_id
  intro x hx
  exact hx
continuity has largely been superseded by fun_prop in recent Mathlib. For new code, prefer fun_prop, which handles continuity as one of several function properties and is more extensible.

fun_prop

fun_prop is the general-purpose tactic for proving function property goals. It subsumes continuity and measurability and can prove goals about:
  • Continuous, ContinuousAt, ContinuousOn
  • Measurable, MeasurableSet, AEMeasurable
  • Differentiable, DifferentiableAt, DifferentiableOn
  • HasFDerivAt, HasDerivAt
  • Integrable, AEStronglyMeasurable
  • Any property registered with @[fun_prop]
example : Continuous (fun x : ℝ => x ^ 2 + Real.exp x) := by fun_prop

example : Measurable (fun x : ℝ => x + 1) := by fun_prop

example : Differentiable ℝ (fun x : ℝ => x ^ 3 - 2 * x) := by fun_prop

-- fun_prop handles compositions automatically
example : Continuous (fun x : ℝ => Real.sin (x ^ 2 + 1)) := by fun_prop
To make fun_prop aware of a new property MyProp, register it with the @[fun_prop] attribute:
-- Mark the property type as a fun_prop target
attribute [fun_prop] MyProp

-- Register lemmas for specific operations
@[fun_prop]
theorem myProp_add (hf : MyProp f) (hg : MyProp g) : MyProp (fun x => f x + g x) := ...

@[fun_prop]
theorem myProp_comp (hf : MyProp f) (hg : MyProp g) : MyProp (f ∘ g) := ...
When fun_prop fails, it may output a trace showing which subgoal it got stuck on. Enable tracing with set_option trace.Meta.Tactic.fun_prop true to diagnose the issue.

measurability

measurability proves Measurable f and MeasurableSet s goals by composing measurability lemmas. Like continuity, it has been largely superseded by fun_prop, but it remains available and still works for many standard goals.
example : Measurable (fun x : ℝ => x + 1) := by measurability

example : MeasurableSet {x : ℝ | x > 0} := by measurability

example (f g : ℝ → ℝ) (hf : Measurable f) (hg : Measurable g) :
    Measurable (fun x => f x + g x) := by measurability
For complex measurability goals, especially those involving integrals or advanced measure theory, fun_prop is the preferred tactic in current Mathlib.

Build docs developers (and LLMs) love