Skip to content

Choosing the Right Tactic

Quick reference for picking the right LeanCert tactic for a direct automation goal. For the overall proof-shape chooser, start with Choosing A Proof Shape.

Having issues? See the Troubleshooting Guide for common errors and solutions.

For ordinary mathematical statements, start with leancert. The dedicated tactics below remain useful when you want to force a particular solver, select engine-specific parameters, or control the verification path.

Decision Flowchart

What do you want to prove?
├─► A recognized bound, root, extremum, finite-sum, or integral theorem?
│   └─► leancert
│       └─► Need to inspect the selected solver? ──► leancert?
├─► Need explicit control for "∀ x ∈ I, f(x) ≤ c" or "∀ x ∈ I, f(x) ≥ c"?
│   │
│   ├─► Single variable? ──► certify_bound
│   │                        (add `(trust := kernel)` for kernel-only trust)
│   │
│   └─► Multiple variables? ──► multivariate_bound
├─► "∀ x ∈ I, f(x) ≠ 0"
│   └─► root_bound
├─► "∃ x ∈ I, f(x) = 0"
│   └─► interval_roots
├─► "∃! x ∈ I, f(x) = 0"
│   └─► interval_unique_root
├─► "∃ m, ∀ x ∈ I, f(x) ≥ m" (certify a global lower bound)
│   │
│   ├─► Single variable? ──► interval_minimize
│   └─► Multiple variables? ──► interval_minimize_mv
├─► "∃ M, ∀ x ∈ I, f(x) ≤ M" (certify a global upper bound)
│   │
│   ├─► Single variable? ──► interval_maximize
│   └─► Multiple variables? ──► interval_maximize_mv
├─► "∃ x ∈ I, ∀ y ∈ I, f(x) ≤ f(y)" (find argmin)
│   └─► interval_argmin
├─► "∃ x ∈ I, ∀ y ∈ I, f(y) ≤ f(x)" (find argmax)
│   └─► interval_argmax
├─► Point inequality (π < 3.15, etc.)
│   └─► interval_decide
├─► Integral bound
│   └─► leancert
├─► "∀ n ≥ N, q / n^k ≤ c" or "∃ N, ∀ n ≥ N, q / n^k ≤ c"
│   └─► leancert
│       └─► Need an explicit cutoff? ──► eventual_bound using N
├─► Simplify vector/matrix indexing (![a,b,c] ⟨1,h⟩ → b)
│   └─► vec_simp
└─► Expand finite sum (∑ k ∈ Icc 1 3, f k → f 1 + f 2 + f 3)
    └─► finsum_expand

Quick Reference Table

I want to prove... Tactic Example
Any recognized mathematical goal leancert Bounds, roots, extrema, sums, and integrals
Upper bound on interval leancert ∀ x ∈ Set.Icc 0 1, exp x ≤ 3
Lower bound on interval leancert ∀ x ∈ Set.Icc 0 1, 0 ≤ exp x
Bound with explicit Taylor depth certify_bound Same goals, direct interval-engine control
Bound with kernel-only trust certify_bound (trust := kernel) Same solver, kernel-only certificate verification
Multivariate bound leancert ∀ x ∈ I, ∀ y ∈ J, x + y ≤ 2
Function has no roots leancert ∀ x ∈ I, x² + 1 ≠ 0
Root exists leancert ∃ x ∈ I, x² - 2 = 0
Unique root exists leancert ∃! x ∈ I, x² - 2 = 0
Global lower or upper bound exists leancert Existential bound theorem
Find the minimizer or maximizer leancert Argmin or argmax theorem
Point inequality leancert π < 3.15
Disprove a bound interval_refute Find counterexample
Simplify vector indexing vec_simp ![a,b,c] ⟨1, h⟩ = b
Expand finite sums finsum_expand ∑ k ∈ Icc 1 3, f k = f 1 + f 2 + f 3
Integral equality or inequality leancert (∫ x in a..b, f x) ≤ c
Eventual reciprocal-power bound leancert ∃ N, ∀ n ≥ N, 3 / n^2 ≤ 1/1000

Trust Levels

Solver choice and certificate-verification trust are independent. Most proof-producing tactics accept the same per-invocation trust item:

Mode Example Verification
native (repository default) certify_bound (trust := native) native_decide; trusts the compiler/runtime
kernel certify_bound (trust := kernel) decide +kernel; never silently falls back
auto certify_bound (trust := auto) Kernel first for suitably sized certificates; reported native fallback

The effective default is the scoped leancert.trust option, whose repository default is native. Use set_option leancert.trust "kernel" to select a mode for a whole section or file. A per-invocation (trust := ...) item takes precedence.

Common Patterns

"My bound is too tight and fails"

-- Try 1: Increase Taylor depth
example :  x  Set.Icc (0 : ) 1, Real.exp x  3 := by certify_bound 20

-- Try 2: Use subdivision
example :  x  Set.Icc (0 : ) 1, Real.exp x  3 := by interval_bound_subdiv 15 3

-- Try 3: Increase depth while requiring kernel-only certificate verification
example :  x  Set.Icc (0 : ) 1, Real.exp x  3 := by
  certify_bound 20 (trust := kernel)

"I don't know what bound to use"

Use discovery tactics to find bounds first:

-- Discover and certify global lower/upper bounds
example :  m : ,  x  Set.Icc (0 : ) 1, x ^ 2 + Real.sin x  m := by
  interval_minimize
example :  M : ,  x  Set.Icc (0 : ) 1, x ^ 2 + Real.sin x  M := by
  interval_maximize

Or use interactive commands:

import LeanCert.Discovery.Commands

#find_min (fun x => x^2 + Real.sin x) on [0, 1]
#find_max (fun x => x^2 + Real.sin x) on [0, 1]

"I want to prove both upper and lower bounds"

Prove them separately and combine:

theorem exp_lower :  x  Set.Icc (0:) 1, 1  Real.exp x := by leancert
theorem exp_upper :  x  Set.Icc (0:) 1, Real.exp x  3 := by leancert

theorem exp_bounded :  x  Set.Icc (0:) 1, 1  Real.exp x  Real.exp x  3 :=
  fun x hx => exp_lower x hx, exp_upper x hx

"Dedicated tactic syntax vs Expr AST"

When selecting a dedicated tactic directly, most support native syntax, but some also expose or require the reflected Expr AST:

Tactic Native Syntax Expr AST
certify_bound ✓ Recommended ✓ Supported
multivariate_bound ✓ Recommended ✓ Supported
interval_minimize/maximize ✓ Recommended ✓ Supported
interval_roots ✓ Supported ✓ Works well
root_bound ✓ Supported ✓ Works well
interval_le/ge (low-level) ✓ Required

Native syntax (recommended when it works):

example :  x  Set.Icc (0:) 1, x * x  1 := by certify_bound
example :  x  Set.Icc (0:) 1, Real.exp x  3 := by certify_bound 15

Expr AST syntax (more control, always works):

open LeanCert.Core in
def I01 : IntervalRat := 0, 1, by norm_num

open LeanCert.Core in
example :  x  I01, Expr.eval (fun _ => x) (Expr.mul (Expr.var 0) (Expr.var 0))  (1 : ) := by
  certify_bound

When native syntax fails: If you get unification errors with complex expressions (especially with numeric coefficients like 2 * x * x), switch to Expr AST. See Troubleshooting for details.

"I have a sum over vectors/matrices"

Chain simplification tactics to reduce structured expressions before proving bounds:

-- Expand finite sum, simplify vector indexing, then close with ring
example (a : Fin 3  ) :
     k : Fin 3, (![a 0, a 1, a 2] : Fin 3  ) k =
    a 0 + a 1 + a 2 := by
  finsum_expand

Common combinations: - finsum_expand; ring — expand sum, simplify arithmetic - finsum_expand; vec_simp; ring — expand sum, reduce vector indexing, simplify - vec_simp; leancert — simplify indexing, then prove the resulting mathematical goal