File: Mathlib/Tactic/LinearCombination.lean

full_name: Mathlib.Tactic.LinearCombination.pf_add_c
code: theorem pf_add_c [Add α] (p : a = b) (c : α) : a + c = b + c 
goal: a + c = b + c

full_name: Mathlib.Tactic.LinearCombination.c_add_pf
code: theorem c_add_pf [Add α] (p : b = c) (a : α) : a + b = a + c 
goal: a + b = a + c

full_name: Mathlib.Tactic.LinearCombination.add_pf
code: theorem add_pf [Add α] (p₁ : (a₁:α) = b₁) (p₂ : a₂ = b₂) : a₁ + a₂ = b₁ + b₂ 
goal: a₁ + a₂ = b₁ + b₂

full_name: Mathlib.Tactic.LinearCombination.pf_sub_c
code: theorem pf_sub_c [Sub α] (p : a = b) (c : α) : a - c = b - c 
goal: a - c = b - c

full_name: Mathlib.Tactic.LinearCombination.c_sub_pf
code: theorem c_sub_pf [Sub α] (p : b = c) (a : α) : a - b = a - c 
goal: a - b = a - c

full_name: Mathlib.Tactic.LinearCombination.sub_pf
code: theorem sub_pf [Sub α] (p₁ : (a₁:α) = b₁) (p₂ : a₂ = b₂) : a₁ - a₂ = b₁ - b₂ 
goal: a₁ - a₂ = b₁ - b₂

full_name: Mathlib.Tactic.LinearCombination.neg_pf
code: theorem neg_pf [Neg α] (p : (a:α) = b) : -a = -b 
goal: -a = -b

full_name: Mathlib.Tactic.LinearCombination.pf_mul_c
code: theorem pf_mul_c [Mul α] (p : a = b) (c : α) : a * c = b * c 
goal: a * c = b * c

full_name: Mathlib.Tactic.LinearCombination.c_mul_pf
code: theorem c_mul_pf [Mul α] (p : b = c) (a : α) : a * b = a * c 
goal: a * b = a * c

full_name: Mathlib.Tactic.LinearCombination.mul_pf
code: theorem mul_pf [Mul α] (p₁ : (a₁:α) = b₁) (p₂ : a₂ = b₂) : a₁ * a₂ = b₁ * b₂ 
goal: a₁ * a₂ = b₁ * b₂

full_name: Mathlib.Tactic.LinearCombination.inv_pf
code: theorem inv_pf [Inv α] (p : (a:α) = b) : a⁻¹ = b⁻¹ 
goal: a⁻¹ = b⁻¹

full_name: Mathlib.Tactic.LinearCombination.pf_div_c
code: theorem pf_div_c [Div α] (p : a = b) (c : α) : a / c = b / c 
goal: a / c = b / c

full_name: Mathlib.Tactic.LinearCombination.c_div_pf
code: theorem c_div_pf [Div α] (p : b = c) (a : α) : a / b = a / c 
goal: a / b = a / c

full_name: Mathlib.Tactic.LinearCombination.div_pf
code: theorem div_pf [Div α] (p₁ : (a₁:α) = b₁) (p₂ : a₂ = b₂) : a₁ / a₂ = b₁ / b₂ 
goal: a₁ / a₂ = b₁ / b₂

full_name: Mathlib.Tactic.LinearCombination.expandLinearCombo
code: /--
Performs macro expansion of a linear combination expression,
using `+`/`-`/`*`/`/` on equations and values.
* `some p` means that `p` is a syntax corresponding to a proof of an equation.
  For example, if `h : a = b` then `expandLinearCombo (2 * h)` returns `some (c_add_pf 2 h)`
  which is a proof of `2 * a = 2 * b`.
* `none` means that the input expression is not an equation but a value;
  the input syntax itself is used in this case.
-/
partial def expandLinearCombo (stx : Syntax.Term) : TermElabM (Option Syntax.Term) 
goal: Lean.Elab.TermElabM (Option Lean.Term)

full_name: Mathlib.Tactic.LinearCombination.eq_trans₃
code: theorem eq_trans₃ (p : (a:α) = b) (p₁ : a = a') (p₂ : b = b') : a' = b' 
goal: a' = b'

full_name: Mathlib.Tactic.LinearCombination.eq_of_add
code: theorem eq_of_add [AddGroup α] (p : (a:α) = b) (H : (a' - b') - (a - b) = 0) : a' = b' 
goal: a' = b'

full_name: Mathlib.Tactic.LinearCombination.eq_of_add_pow
code: theorem eq_of_add_pow [Ring α] [NoZeroDivisors α] (n : ℕ) (p : (a:α) = b)
    (H : (a' - b')^n - (a - b) = 0) : a' = b' 
goal: a' = b'

full_name: Mathlib.Tactic.LinearCombination.elabLinearCombination
code: /-- Implementation of `linear_combination` and `linear_combination2`. -/
def elabLinearCombination
    (norm? : Option Syntax.Tactic) (exp? : Option Syntax.NumLit) (input : Option Syntax.Term)
    (twoGoals := false) : Tactic.TacticM Unit 
goal: Lean.Elab.Tactic.TacticM Unit

full_name: Mathlib.Tactic.LinearCombination.normStx
code: /--
The `(norm := $tac)` syntax says to use `tac` as a normalization postprocessor for
`linear_combination`. The default normalizer is `ring1`, but you can override it with `ring_nf`
to get subgoals from `linear_combination` or with `skip` to disable normalization.
-/
syntax normStx := atomic(" (" &"norm" " := ") withoutPosition(tactic) ")"
goal: Lean.ParserDescr

full_name: Mathlib.Tactic.LinearCombination.expStx
code: /--
The `(exp := n)` syntax for `linear_combination` says to take the goal to the `n`th power before
subtracting the given combination of hypotheses.
-/
syntax expStx := atomic(" (" &"exp" " := ") withoutPosition(num) ")"
goal: Lean.ParserDescr

full_name: Mathlib.Tactic.LinearCombination.linearCombination
code: /--
`linear_combination` attempts to simplify the target by creating a linear combination
  of a list of equalities and subtracting it from the target.
  The tactic will create a linear
  combination by adding the equalities together from left to right, so the order
  of the input hypotheses does matter.  If the `normalize` field of the
  configuration is set to false, then the tactic will simply set the user up to
  prove their target using the linear combination instead of normalizing the subtraction.

Note: The left and right sides of all the equalities should have the same
  type, and the coefficients should also have this type.  There must be
  instances of `Mul` and `AddGroup` for this type.

* The input `e` in `linear_combination e` is a linear combination of proofs of equalities,
  given as a sum/difference of coefficients multiplied by expressions.
  The coefficients may be arbitrary expressions.
  The expressions can be arbitrary proof terms proving equalities.
  Most commonly they are hypothesis names `h1, h2, ...`.
* `linear_combination (norm := tac) e` runs the "normalization tactic" `tac`
  on the subgoal(s) after constructing the linear combination.
  * The default normalization tactic is `ring1`, which closes the goal or fails.
  * To get a subgoal in the case that it is not immediately provable, use
    `ring_nf` as the normalization tactic.
  * To avoid normalization entirely, use `skip` as the normalization tactic.
* `linear_combination (exp := n) e` will take the goal to the `n`th power before subtracting the
  combination `e`. In other words, if the goal is `t1 = t2`, `linear_combination (exp := n) e`
  will change the goal to `(t1 - t2)^n = 0` before proceeding as above.
  This feature is not supported for `linear_combination2`.
* `linear_combination2 e` is the same as `linear_combination e` but it produces two
  subgoals instead of one: rather than proving that `(a - b) - (a' - b') = 0` where
  `a' = b'` is the linear combination from `e` and `a = b` is the goal,
  it instead attempts to prove `a = a'` and `b = b'`.
  Because it does not use subtraction, this form is applicable also to semirings.
  * Note that a goal which is provable by `linear_combination e` may not be provable
    by `linear_combination2 e`; in general you may need to add a coefficient to `e`
    to make both sides match, as in `linear_combination2 e + c`.
  * You can also reverse equalities using `← h`, so for example if `h₁ : a = b`
    then `2 * (← h)` is a proof of `2 * b = 2 * a`.

Example Usage:
```
example (x y : ℤ) (h1 : x*y + 2*x = 1) (h2 : x = y) : x*y = -2*y + 1 := by
  linear_combination 1*h1 - 2*h2

example (x y : ℤ) (h1 : x*y + 2*x = 1) (h2 : x = y) : x*y = -2*y + 1 := by
  linear_combination h1 - 2*h2

example (x y : ℤ) (h1 : x*y + 2*x = 1) (h2 : x = y) : x*y = -2*y + 1 := by
  linear_combination (norm := ring_nf) -2*h2
  /- Goal: x * y + x * 2 - 1 = 0 -/

example (x y z : ℝ) (ha : x + 2*y - z = 4) (hb : 2*x + y + z = -2)
    (hc : x + 2*y + z = 2) :
    -3*x - 3*y - 4*z = 2 := by
  linear_combination ha - hb - 2*hc

example (x y : ℚ) (h1 : x + y = 3) (h2 : 3*x = 7) :
    x*x*y + y*x*y + 6*x = 3*x*y + 14 := by
  linear_combination x*y*h1 + 2*h2

example (x y : ℤ) (h1 : x = -3) (h2 : y = 10) : 2*x = -6 := by
  linear_combination (norm := skip) 2*h1
  simp

axiom qc : ℚ
axiom hqc : qc = 2*qc

example (a b : ℚ) (h : ∀ p q : ℚ, p = q) : 3*a + qc = 3*b + 2*qc := by
  linear_combination 3 * h a b + hqc
```
-/
syntax (name := linearCombination) "linear_combination"
  (normStx)? (expStx)? (ppSpace colGt term)? : tactic
goal: Lean.ParserDescr

full_name: Mathlib.Tactic.LinearCombination._aux_Mathlib_Tactic_LinearCombination___elabRules_Mathlib_Tactic_LinearCombination_linearCombination_1
code: elab_rules : tactic
  | `(tactic| linear_combination $[(norm := $tac)]? $[(exp := $n)]? $(e)?) =>
    elabLinearCombination tac n e
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.LinearCombination.tacticLinear_combination2____
code: @[inherit_doc linearCombination]
syntax "linear_combination2" (normStx)? (ppSpace colGt term)? : tactic
goal: Lean.ParserDescr

full_name: Mathlib.Tactic.LinearCombination._aux_Mathlib_Tactic_LinearCombination___elabRules_Mathlib_Tactic_LinearCombination_tacticLinear_combination2_____1
code: elab_rules : tactic
  | `(tactic| linear_combination2 $[(norm := $tac)]? $(e)?) => elabLinearCombination tac none e true
goal: Lean.Elab.Tactic.Tactic