positivity tactic #
The positivity tactic in this file solves goals of the form 0 ≤ x and 0 < x. The tactic works
recursively according to the syntax of the expression x. For example, a goal of the form
0 ≤ 3 * a ^ 2 + b * c can be solved either
- by a hypothesis such as
5 ≤ 3 * a ^ 2 + b * cwhich directly implies the nonegativity of3 * a ^ 2 + b * c; or, - by the application of the lemma
add_nonnegand the success of thepositivitytactic on the two sub-expressions3 * a ^ 2andb * c.
For each supported operation, one must write a small tactic, tagged with the attribute
@[positivity], which operates only on goals whose leading function application is that operation.
Typically, this small tactic will run the full positivity tactic on one or more of the function's
arguments (which is where the recursion comes in), and if successful will combine this with an
appropriate lemma to give positivity of the full expression.
This file contains the core positivity logic and the small tactics handling the basic operations:
min, max, +, *, /, ⁻¹, raising to natural powers, and taking absolute values. Further
extensions, e.g. to handle real.sqrt and norms, can be found in the files of the library which
introduce these operations.
Main declarations #
tactic.norm_num.positivitytries to prove positivity of an expression by runningnorm_numon it. This is one of the base cases of the recursion.tactic.positivity.compare_hyptries to prove positivity of an expression by comparing with a provided hypothesis. If the hypothesis is of the forma ≤ bor similar, withbmatching the expression whose proof of positivity is desired, then it will check whetheracan be proved positive viatactic.norm_num.positivityand if so apply a transitivity lemma. This is the other base case of the recursion.tactic.positivity.attrcreates thepositivityuser attribute for tagging the extension tactics handling specific operations, and specifies the behaviour for a single step of the recursiontactic.positivity.corecollects the list of tactics with the@[positivity]attribute and calls the first recursion step as specified intactic.positivity.attr. Its input ise : exprand its output (if it succeeds) is a term of a custom inductive typetactic.positivity.strictness, containing anexprwhich is a proof of the strict-positivity/nonnegativity ofeas well as an indication of whether what could be proved was strict-positivity or nonnegativitytactic.interactive.positivityis the user-facing tactic. It parses the goal and, if it is of one of the forms0 ≤ e,0 < e,e > 0,e ≥ 0, it sendsetotactic.positivity.core.
TODO #
Implement extensions for other operations (raising to non-numeral powers, exp, log, coercions
from ℕ and ℝ≥0).
Core logic of the positivity tactic #
Tactic solving goals of the form 0 ≤ x and 0 < x. 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 by norm_num. This tactic either closes the goal
or fails.
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
```