Skip to content

Commit db1186d

Browse files
committed
chore(Tactic): rewrite positivity tactic and @[positivity] attr docstrings (leanprover-community#37107)
This PR rewrites the docstrings for the `positivity` tactic and `@[positivity]` attribute, to consistently match the official style guide, to make sure they are complete while not getting too long. The goal was to make it clearer what an extension does exactly, and document how to write one in the `@[positivity]` docstring. Co-authored-by: Anne C.A. Baanen <vierkantor@vierkantor.com>
1 parent 02f5ba4 commit db1186d

1 file changed

Lines changed: 39 additions & 8 deletions

File tree

Mathlib/Tactic/Positivity/Core.lean

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,29 @@ public meta section
2525
open Lean
2626
open Lean.Meta Qq Lean.Elab Term
2727

28-
/-- Attribute for identifying `positivity` extensions. -/
28+
/-- A definition of type `PositivityExt` tagged `@[positivity t]` extends the `positivity` tactic.
29+
The term (with underscores) `t` indicates which expressions this extension accepts.
30+
An extension will be given an expression `e : α`, together with hypotheses
31+
`[Zero α] [PartialOrder α]` and attempts to prove `e > 0`, `e ≥ 0`, or `e ≠ 0`.
32+
33+
When `Positivity.core` calls this extension on an expression `e`, it does not guarantee that `e`
34+
matches `t` perfectly: validate the form of the expression (using e.g.
35+
`match_expr (← withReducible (whnf e))`) before building a proof. See also the
36+
`let .app ... ← withReducible (whnf e) | throwError ...` lines in the example below.
37+
38+
An extension can call `Mathlib.Meta.Positivity.core` to recursively solve subgoals.
39+
40+
Example:
41+
```lean
42+
@[positivity ite _ _ _] def evalIte : PositivityExt where eval {u α} zα pα e := do
43+
let .app (.app (.app (.app f (p : Q(Prop))) (_ : Q(Decidable $p))) (a : Q($α))) (b : Q($α))
44+
← withReducible (whnf e) | throwError "not ite"
45+
haveI' : $e =Q ite $p $a $b := ⟨⟩
46+
guard <| ← withDefault <| withNewMCtxDepth <| isDefEq f q(ite (α := $α))
47+
let ra ← core zα pα a; let rb ← core zα pα b
48+
...
49+
```
50+
-/
2951
syntax (name := positivity) "positivity " term,+ : attr
3052

3153
lemma ne_of_ne_of_eq' {α : Sort*} {a c b : α} (hab : (a : α) ≠ c) (hbc : a = b) : b ≠ c := hbc ▸ hab
@@ -490,14 +512,23 @@ namespace Tactic.Positivity
490512

491513
open Tactic
492514

493-
/-- Tactic solving goals of the form `0 ≤ x`, `0 < x` and `x ≠ 0`. The tactic works recursively
494-
according to the syntax of the expression `x`, if the atoms composing the expression all have
495-
numeric lower bounds which can be proved positive/nonnegative/nonzero by `norm_num`. This tactic
496-
either closes the goal or fails.
515+
/-- `positivity` solves goals of the form `0 ≤ x`, `0 < x` and `x ≠ 0`. The tactic works recursively
516+
according to the syntax of the expression `x`, by attempting to prove subexpressions are
517+
positive/nonnegative/nonzero and combining this into a final proof. This tactic either closes the
518+
goal or fails.
519+
520+
For each subexpression `e`, `positivity` will try to:
521+
* try `@[positivity]`-tagged extensions to recursively prove `e` is positive/nonnegative/nonzero
522+
based on its subexpressions (see the `positivity` attribute for more details), or
523+
* try the `norm_num` tactic to prove `e` is positive/nonnegative/nonzero, or
524+
* try showing `e : t` is nonnegative because there is a `CanonicallyOrderedAdd t` instance, or
525+
* use a local hypothesis of the form `0 ≤ e`, `0 < e` or `e ≠ 0`.
526+
527+
This tactic is extensible. See the `positivity` attribute documentation for more details.
497528
498-
`positivity [t₁, …, tₙ]` first executes `have := t₁; …; have := tₙ` in the current goal,
499-
then runs `positivity`. This is useful when `positivity` needs derived premises such as `0 < y`
500-
for division/reciprocal, or `0 ≤ x` for real powers.
529+
* `positivity [t₁, …, tₙ]` first executes `have := t₁; …; have := tₙ` in the current goal,
530+
then runs `positivity`. This is useful when `positivity` needs derived premises such as `0 < y`
531+
for division/reciprocal, or `0 ≤ x` for real powers.
501532
502533
Examples:
503534
```

0 commit comments

Comments
 (0)