Skip to content

Commit b840598

Browse files
committed
chore(Tactic/GCongr): rewrite gcongr, rel tactic docstrings (#36260)
This PR (re)writes the docstrings for the `gcongr` and `rel` tactics to consistently match the official style guide, to make sure it is complete while not getting too long. The docstrings had a lot of examples and were information dense, which is very good! With the rewrite, the information should be easier to find given the consistent structure. Co-authored-by: Anne C.A. Baanen <vierkantor@vierkantor.com>
1 parent a56f92b commit b840598

File tree

1 file changed

+51
-43
lines changed

1 file changed

+51
-43
lines changed

Mathlib/Tactic/GCongr/Core.lean

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -703,46 +703,53 @@ partial def _root_.Lean.MVarId.gcongr
703703
throwTacticEx `gcongr g m!"none of the `@[gcongr]` lemmas were applicable to the goal {rel}.\
704704
\n attempted lemmas: {lemmas.map (·.declName)}"
705705

706-
/-- The `gcongr` tactic applies "generalized congruence" rules, reducing a relational goal
707-
between an LHS and RHS. For example,
706+
/-- `gcongr` applies "generalized congruence" rules to recursively reduce a goal of form
707+
`⊢ R (f a₁ ... aₙ) (f b₁ ... bₙ)` to (possibly multiple) goal(s) `⊢ Rᵢ aᵢ bᵢ`, keeping only the
708+
distinct pairs `aᵢ ≠ bᵢ`, where `Rᵢ` is a possibly different relation (depending on the
709+
precise rule). The relations `R`, `Rᵢ` can be any two-argument relation, including `· → ·`.
710+
711+
This tactic is extensible: to add a "generalized congruence" rule, tag a theorem with the attribute
712+
`@[gcongr]`.
713+
714+
If a "generalized congruence" lemma has a side goal, `gcongr` will try to discharge it using
715+
`gcongr_discharger`, which is an extensible tactic based on `positivity`. Side goals not discharged
716+
in this way are left for the user.
717+
718+
* `gcongr with x y ... z` names the variables that are introduced by descending into binders (for
719+
example sums or suprema).
720+
* `gcongr n`, where `n` is a natural number literal, limits the depth of the recursive applications.
721+
This is useful if `gcongr` is too aggressive in breaking down the goal.
722+
* `gcongr t`, where `t` is a term with `?_` holes, performs congruence up to the holes in `t`.
723+
In other words, `gcongr f ?_` turns a goal `⊢ R (f x) (f y)` into `⊢ R x y` (but no further).
724+
This is useful if `gcongr` is too aggressive in breaking down the goal.
725+
726+
Examples:
708727
```
709728
example {a b x c d : ℝ} (h1 : a + 1 ≤ b + 1) (h2 : c + 2 ≤ d + 2) :
710729
x ^ 2 * a + c ≤ x ^ 2 * b + d := by
730+
-- LHS and RHS both have the form x ^ 2 * ?_ + ?_
711731
gcongr
712-
· linarith
713-
· linarith
732+
· -- New goal: ⊢ a ≤ b
733+
linarith
734+
· -- ⊢ New goal: c ≤ d
735+
linarith
736+
-- Resulting proof term is:
737+
-- add_le_add (mul_le_mul_of_nonneg_left ?_ (Even.pow_nonneg (even_two_mul 1) x)) ?_
738+
-- where `add_le_add` and `mul_le_mul_of_nonneg_left` are generalized congruence lemmas
739+
-- and the side goal `0 ≤ x ^ 2` is discharged by `gcongr_discharger`.
714740
```
715-
This example has the goal of proving the relation `≤` between an LHS and RHS both of the pattern
716-
```
717-
x ^ 2 * ?_ + ?_
718-
```
719-
(with inputs `a`, `c` on the left and `b`, `d` on the right); after the use of
720-
`gcongr`, we have the simpler goals `a ≤ b` and `c ≤ d`.
721741
722-
A depth limit or a pattern can be provided explicitly;
723-
this is useful if a non-maximal match is desired:
724742
```
725743
example {a b c d x : ℝ} (h : a + c + 1 ≤ b + d + 1) :
726744
x ^ 2 * (a + c) + 5 ≤ x ^ 2 * (b + d) + 5 := by
745+
-- Using a pattern to limit the depth.
727746
gcongr x ^ 2 * ?_ + 5 -- or `gcongr 2`
747+
-- New goal: ⊢ a + c ≤ b + d
728748
linarith
729749
```
730750
731-
The "generalized congruence" rules are the library lemmas which have been tagged with the
732-
attribute `@[gcongr]`. For example, the first example constructs the proof term
733-
```
734-
add_le_add (mul_le_mul_of_nonneg_left ?_ (Even.pow_nonneg (even_two_mul 1) x)) ?_
735-
```
736-
using the generalized congruence lemmas `add_le_add` and `mul_le_mul_of_nonneg_left`.
737-
738-
The tactic attempts to discharge side goals to these "generalized congruence" lemmas (such as the
739-
side goal `0 ≤ x ^ 2` in the above application of `mul_le_mul_of_nonneg_left`) using the tactic
740-
`gcongr_discharger`, which wraps `positivity` but can also be extended. Side goals not discharged
741-
in this way are left for the user.
742-
743-
`gcongr` will descend into binders (for example sums or suprema). To name the bound variables,
744-
use `with`:
745751
```
752+
-- Descending into binders (here: ⨆).
746753
example {f g : ℕ → ℝ≥0∞} (h : ∀ n, f n ≤ g n) : ⨆ n, f n ≤ ⨆ n, g n := by
747754
gcongr with i
748755
exact h i
@@ -781,28 +788,29 @@ elab "gcongr" template:(ppSpace colGt term)?
781788
else
782789
throwError "gcongr did not make progress"
783790

784-
/-- The `rel` tactic applies "generalized congruence" rules to solve a relational goal by
785-
"substitution". For example,
791+
/-- `rel [h₁, ..., hₙ]` uses "generalized congruence" rules to solve a goal of form
792+
`⊢ R (f a₁ ... aₙ) (f b₁ ... bₙ)` by substituting with the terms `hᵢ : Rᵢ aᵢ bᵢ`. The relations
793+
`R`, `Rᵢ` can be any two-argument relation, including `· → ·`.
794+
795+
This tactic is extensible: to add a "generalized congruence" rule, tag a theorem with the attribute
796+
`@[gcongr]`.
797+
798+
If a "generalized congruence" lemma has a side goal, `rel` will try to discharge it using
799+
`gcongr_discharger`, which is an extensible tactic based on `positivity`. If side goals cannot be
800+
discharged, or the terms `h₁`, ..., `hₙ` cannot solve the goals, the tactic fails.
801+
802+
Examples:
786803
```
787804
example {a b x c d : ℝ} (h1 : a ≤ b) (h2 : c ≤ d) :
788805
x ^ 2 * a + c ≤ x ^ 2 * b + d := by
789806
rel [h1, h2]
807+
-- In this example we "substitute" the hypotheses `a ≤ b` and `c ≤ d` into the LHS `x ^ 2 * a + c`
808+
-- of the goal and obtain the RHS `x ^ 2 * b + d`, thus proving the goal.
809+
-- This constructs the proof term:
810+
-- add_le_add (mul_le_mul_of_nonneg_left h1 (pow_bit0_nonneg x 1)) h2
811+
-- using the generalized congruence lemmas `add_le_add` and `mul_le_mul_of_nonneg_left`.
790812
```
791-
In this example we "substitute" the hypotheses `a ≤ b` and `c ≤ d` into the LHS `x ^ 2 * a + c` of
792-
the goal and obtain the RHS `x ^ 2 * b + d`, thus proving the goal.
793-
794-
The "generalized congruence" rules used are the library lemmas which have been tagged with the
795-
attribute `@[gcongr]`. For example, the first example constructs the proof term
796-
```
797-
add_le_add (mul_le_mul_of_nonneg_left h1 (pow_bit0_nonneg x 1)) h2
798-
```
799-
using the generalized congruence lemmas `add_le_add` and `mul_le_mul_of_nonneg_left`. If there are
800-
no applicable generalized congruence lemmas, the tactic fails.
801-
802-
The tactic attempts to discharge side goals to these "generalized congruence" lemmas (such as the
803-
side goal `0 ≤ x ^ 2` in the above application of `mul_le_mul_of_nonneg_left`) using the tactic
804-
`gcongr_discharger`, which wraps `positivity` but can also be extended. If the side goals cannot
805-
be discharged in this way, the tactic fails. -/
813+
-/
806814
syntax "rel" " [" term,* "]" : tactic
807815

808816
elab_rules : tactic

0 commit comments

Comments
 (0)