@@ -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```
709728example {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```
725743example {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: ⨆).
746753example {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```
787804example {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+ -/
806814syntax " rel" " [" term,* " ]" : tactic
807815
808816elab_rules : tactic
0 commit comments