The bound tactic #
bound is an aesop wrapper that proves inequalities by straightforward recursion on structure,
assuming that intermediate terms are nonnegative or positive as needed. It also has some support
for guessing where it is unclear where to recurse, such as which side of a min or max to use
as the bound or whether to assume a power is less than or greater than one.
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
uses specialized lemmas for goals of the form 1 ≤ x, 1 < x, x ≤ 1, x < 1.
Additional hypotheses can be passed as bound [h0, h1 n, ...]. This is equivalent to declaring
them via have before calling bound.
See MathlibTest/Bound/bound.lean for tests.
Calc usage #
Since bound requires the inequality proof to exactly match the structure of the expression, it is
often useful to iterate between bound and rw / simp using calc. Here is an example:
-- Calc example: A weak lower bound for `z ↦ z^2 + c`
lemma le_sqr_add {c z : ℂ} (cz : abs c ≤ abs z) (z3 : 3 ≤ abs z) :
2 * abs z ≤ abs (z^2 + c) := by
calc abs (z^2 + c)
_ ≥ abs (z^2) - abs c := by bound
_ ≥ abs (z^2) - abs z := by bound
_ ≥ (abs z - 1) * abs z := by rw [mul_comm, mul_sub_one, ← pow_two, ← abs.map_pow]
_ ≥ 2 * abs z := by bound
Aesop rules #
bound uses threes types of aesop rules: apply, forward, and closing tactics. To register a
lemma as an apply rule, tag it with @[bound]. It will be automatically converted into either a
norm apply or safe apply rule depending on the number and type of its hypotheses:
- Nonnegativity/positivity/nonpositivity/negativity hypotheses get score 1 (those involving
0). - Other inequalities get score 10.
- Disjunctions
a ∨ bget score 100, plus the score ofaandb.
Score 0 lemmas turn into norm apply rules, and score 0 < s lemmas turn into safe apply s
rules. The score is roughly lexicographic ordering on the counts of the three type (guessing,
general, involving-zero), and tries to minimize the complexity of hypotheses we have to prove.
See Mathlib/Tactic/Bound/Attribute.lean for the full algorithm.
To register a lemma as a forward rule, tag it with @[bound_forward]. The most important
builtin forward rule is le_of_lt, so that strict inequalities can be used to prove weak
inequalities. Another example is HasFPowerSeriesOnBall.r_pos, so that bound knows that any
power series present in the context have positive radius of convergence. Custom @[bound_forward]
rules that similarly expose inequalities inside structures are often useful.
Guessing apply rules #
There are several cases where there are two standard ways to recurse down an inequality, and it is
not obvious which is correct without more information. For example, a ≤ min b c is registered as
a safe apply 4 rule, since we always need to prove a ≤ b ∧ a ≤ c. But if we see min a b ≤ c,
either a ≤ c or b ≤ c suffices, and we don't know which.
In these cases we declare a new lemma with an ∨ hypotheses that covers the two cases. Tagging
it as @[bound] will add a +100 penalty to the score, so that it will be used only if necessary.
Aesop will then try both ways by splitting on the resulting ∨ hypothesis.
Currently the two types of guessing rules are
minandmaxrules, for both≤and<powandrpowmonotonicity rules which branch on1 ≤ aora ≤ 1.
Closing tactics #
We close numerical goals with norm_num and linarith.
.mpr lemmas of iff statements for use as Aesop apply rules #
Once Aesop can do general terms directly, we can remove these:
Apply rules for bound #
Most bound lemmas are registered in-place where the lemma is declared. These are only the lemmas
that do not require additional imports within this file.
Forward rules for bound #
Guessing rules: when we don't know how to recurse #
Closing tactics #
TODO: Kim Morrison noted that we could check for ℕ or ℤ and try omega as well.
Close numerical goals with norm_num
Equations
- One or more equations did not get rendered due to their size.
Instances For
Close numerical and other goals with linarith
Equations
- One or more equations did not get rendered due to their size.
Instances For
bound tactic implementation #
Aesop configuration for bound
Equations
- Mathlib.Tactic.Bound.boundConfig = { enableSimp := false }
Instances For
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
- Apply lemmas registered via the
@[bound]attribute - Forward lemmas registered via the
@[bound_forward]attribute - Local hypotheses from the context
- Optionally: additional hypotheses provided as
bound [h₀, h₁]or similar. These are added to the context as if byhave := 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).
Equations
- One or more equations did not get rendered due to their size.
Instances For
We register bound with the hint tactic.