[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.LinearAlgebra.BilinearForm.Properties).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
theorem restrict {B : BilinForm R M} (b : B.IsSymm) (W : Submodule R M) :
    (B.restrict W).IsSymm
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.IsRefl (L59-L62)
def IsRefl (B : BilinForm R M) : Prop := LinearMap.IsRefl B
namespace IsRefl
```

-- snippet 2
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.eq_zero (L63-L79)
theorem eq_zero (H : B.IsRefl) : ∀ {x y : M}, B x y = 0 → B y x = 0 := fun {x y} => H x y
protected theorem neg {B : BilinForm R₁ M₁} (hB : B.IsRefl) : (-B).IsRefl := fun x y =>
  neg_eq_zero.mpr ∘ hB x y ∘ neg_eq_zero.mp

protected theorem smul {α : Type*} [Semiring α] [IsDomain α] [Module α R] [SMulCommClass R α R]
    [IsTorsionFree α R] (a : α) {B : BilinForm R M} (hB : B.IsRefl) :
    (a • B).IsRefl := fun _ _ h =>
  (smul_eq_zero.mp h).elim (fun ha => smul_eq_zero_of_left ha _) fun hBz =>
    smul_eq_zero_of_right _ (hB _ _ hBz)

protected theorem groupSMul {α} [Group α] [DistribMulAction α R] [SMulCommClass R α R] (a : α)
    {B : BilinForm R M} (hB : B.IsRefl) : (a • B).IsRefl := fun x y =>
  (smul_eq_zero_iff_eq _).mpr ∘ hB x y ∘ (smul_eq_zero_iff_eq _).mp

end IsRefl
```

-- snippet 3
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isRefl_zero (L81-L82)
theorem isRefl_zero : (0 : BilinForm R M).IsRefl := fun _ _ _ => rfl
```

-- snippet 4
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isRefl_neg (L84-L90)
theorem isRefl_neg {B : BilinForm R₁ M₁} : (-B).IsRefl ↔ B.IsRefl :=
⟨fun h => neg_neg B ▸ h.neg, IsRefl.neg⟩

/-- The proposition that a bilinear form is symmetric -/
structure IsSymm (B : BilinForm R M) : Prop where
  protected eq : ∀ x y, B x y = B y x
```

-- snippet 5
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isSymm_def (L91-L94)
theorem isSymm_def : IsSymm B ↔ ∀ x y, B x y = B y x where
  mp := fun ⟨h⟩ ↦ h
mpr h := ⟨h⟩
```

-- snippet 6
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isSymm_iff (L95-L99)
theorem isSymm_iff : IsSymm B ↔ LinearMap.IsSymm B := by
simp [isSymm_def, LinearMap.isSymm_def]

namespace IsSymm
```

-- snippet 7
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isRefl (L100-L115)
theorem isRefl (H : B.IsSymm) : B.IsRefl := fun x y H1 => H.eq x y ▸ H1
protected theorem add {B₁ B₂ : BilinForm R M} (hB₁ : B₁.IsSymm) (hB₂ : B₂.IsSymm) :
    (B₁ + B₂).IsSymm := ⟨fun x y => (congr_arg₂ (· + ·) (hB₁.eq x y) (hB₂.eq x y) :)⟩

protected theorem sub {B₁ B₂ : BilinForm R₁ M₁} (hB₁ : B₁.IsSymm) (hB₂ : B₂.IsSymm) :
    (B₁ - B₂).IsSymm := ⟨fun x y => (congr_arg₂ Sub.sub (hB₁.eq x y) (hB₂.eq x y) :)⟩

protected theorem neg {B : BilinForm R₁ M₁} (hB : B.IsSymm) : (-B).IsSymm := ⟨fun x y =>
  congr_arg Neg.neg (hB.eq x y)⟩

protected theorem smul {α} [Monoid α] [DistribMulAction α R] [SMulCommClass R α R] (a : α)
    {B : BilinForm R M} (hB : B.IsSymm) : (a • B).IsSymm := ⟨fun x y =>
  congr_arg (a • ·) (hB.eq x y)⟩

/-- The restriction of a symmetric bilinear form on a submodule is also symmetric. -/
```

-- snippet 8
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isSymm_zero (L122-L123)
theorem isSymm_zero : (0 : BilinForm R M).IsSymm := ⟨fun _ _ => rfl⟩
```

-- snippet 9
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isSymm_neg (L125-L127)
theorem isSymm_neg {B : BilinForm R₁ M₁} : (-B).IsSymm ↔ B.IsSymm :=
⟨fun h => neg_neg B ▸ h.neg, IsSymm.neg⟩
```

-- snippet 10
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isSymm_iff_flip (L128-L137)
theorem isSymm_iff_flip : B.IsSymm ↔ flipHom B = B where
  mp := fun ⟨h⟩ ↦ by ext; simp [h]
mpr h := ⟨fun x y ↦ by rw [← flip_apply, h]⟩

section polarization

variable {R : Type*} [Field R] [NeZero (2 : R)] [Module R M] {B C : BilinForm R M}

/-- Polarization identity: a symmetric bilinear form can be expressed through the values
it takes on the diagonal. -/
```

-- snippet 11
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.IsSymm (L138-L145)
lemma IsSymm.polarization (x y : M) (hB : B.IsSymm) :
    B x y = (B (x + y) (x + y) - B x x - B y y) / 2 := by
simp only [map_add, LinearMap.add_apply]
  rw [hB.eq y x]
  ring_nf
  rw [mul_assoc, inv_mul_cancel₀ two_ne_zero, mul_one]

/-- A symmetric bilinear form is characterized by the values it takes on the diagonal. -/
```

-- snippet 12
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.ext_of_isSymm (L146-L152)
lemma ext_of_isSymm (hB : IsSymm B) (hC : IsSymm C)
    (h : ∀ x, B x x = C x x) : B = C := by
ext x y
  rw [hB.polarization, hC.polarization]
  simp_rw [h]

/-- A symmetric bilinear form is characterized by the values it takes on the diagonal. -/
```

-- snippet 13
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.ext_iff_of_isSymm (L153-L159)
lemma ext_iff_of_isSymm (hB : IsSymm B) (hC : IsSymm C) :
    B = C ↔ ∀ x, B x x = C x x where
  mp h := by simp [h]
mpr := ext_of_isSymm hB hC

end polarization
```

-- snippet 14
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isSymm_iff_basis (L160-L186)
lemma isSymm_iff_basis {ι : Type*} (b : Basis ι R M) :
    IsSymm B ↔ ∀ i j, B (b i) (b j) = B (b j) (b i) where
  mp := fun ⟨h⟩ i j ↦ h _ _
mpr := by
    refine fun h ↦ ⟨fun x y ↦ ?_⟩
    obtain ⟨fx, tx, ix, -, hx⟩ := Submodule.mem_span_iff_exists_finset_subset.1
      (by simp : x ∈ Submodule.span R (Set.range b))
    obtain ⟨fy, ty, iy, -, hy⟩ := Submodule.mem_span_iff_exists_finset_subset.1
      (by simp : y ∈ Submodule.span R (Set.range b))
    rw [← hx, ← hy]
    simp only [map_sum, map_smul, coe_sum, Finset.sum_apply, smul_apply, smul_eq_mul,
      Finset.mul_sum]
    rw [Finset.sum_comm]
    refine Finset.sum_congr rfl (fun b₁ h₁ ↦ Finset.sum_congr rfl fun b₂ h₂ ↦ ?_)
    rw [mul_left_comm]
    obtain ⟨i, rfl⟩ := ix h₁
    obtain ⟨j, rfl⟩ := iy h₂
    rw [h]

/-! ### Positive semidefinite bilinear forms -/

section PositiveSemidefinite

/-- A bilinear form `B` is **nonnegative** if for any `x` we have `0 ≤ B x x`. -/
structure IsNonneg [LE R] (B : BilinForm R M) where
  nonneg : ∀ x, 0 ≤ B x x
```

-- snippet 15
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isNonneg_def (L187-L190)
lemma isNonneg_def [LE R] {B : BilinForm R M} : B.IsNonneg ↔ ∀ x, 0 ≤ B x x :=
⟨fun ⟨h⟩ ↦ h, fun h ↦ ⟨h⟩⟩

/-- A bilinear form is nonnegative if and only if it is nonnegative as a sesquilinear form. -/
```

-- snippet 16
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.add_left (L65-L66)
theorem add_left (x y z : M) : B (x + y) z = B x z + B y z := map_add₂ _ _ _ _
```

-- snippet 17
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.add_apply (L111-L113)
theorem add_apply (x y : M) : (B + D) x y = B x y + D x y :=
rfl
```

-- snippet 18
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.coeFnAddMonoidHom (L124-L131)
def coeFnAddMonoidHom : BilinForm R M →+ M → M → R where
  toFun := fun B x y => B x y
map_zero' := rfl
  map_add' _ _ := rfl

section flip

/-- The flip of a bilinear form, obtained by exchanging the left and right arguments. -/
```

-- snippet 19
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.zero_right (L75-L76)
theorem zero_right (x : M) : B x 0 = 0 := map_zero _
```

-- snippet 20
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.lsmul_flip_apply (L158-L160)
theorem lsmul_flip_apply (m : M) : (lsmul R M).flip m = toSpanSingleton R M m := rfl
end LinearMap
```

-- snippet 21
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.coe_injective (L94-L98)
theorem coe_injective : Function.Injective ((fun B x y => B x y) : BilinForm R M → M → M → R) :=
fun B D h => by
    ext x y
    apply congrFun₂ h
```

-- snippet 22
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.neg_left (L77-L78)
theorem neg_left (x y : M₁) : B₁ (-x) y = -B₁ x y := map_neg₂ _ _ _
```

-- snippet 23
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_left_of_tower (L85-L87)
lemma smul_left_of_tower (r : S) (x y : M) : B (r • x) y = r • B x y := by
rw [← IsScalarTower.algebraMap_smul R r, smul_left, Algebra.smul_def]
```

-- snippet 24
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.flip_apply (L135-L137)
theorem flip_apply (A : BilinForm R M) (x y : M) : flipHom A x y = A y x :=
rfl
```

-- snippet 25
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_left (L67-L68)
theorem smul_left (a : R) (x y : M) : B (a • x) y = a * B x y := map_smul₂ _ _ _ _
```

-- snippet 26
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.add_right (L69-L70)
theorem add_right (x y z : M) : B x (y + z) = B x y + B x z := map_add _ _ _
```

-- snippet 27
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.flipHom (L132-L133)
def flipHom : BilinForm R M ≃ₗ[R] BilinForm R M := LinearMap.lflip
```

-- snippet 28
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.zero_apply (L105-L109)
theorem zero_apply (x y : M) : (0 : BilinForm R M) x y = 0 :=
rfl

variable (B D B₁ D₁)
```

-- snippet 29
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.sub_apply (L119-L122)
theorem sub_apply (x y : M₁) : (B₁ - D₁) x y = B₁ x y - D₁ x y :=
rfl

/-- `coeFn` as an `AddMonoidHom` -/
```

-- snippet 30
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.neg_right (L79-L80)
theorem neg_right (x y : M₁) : B₁ x (-y) = -B₁ x y := map_neg _ _
```

-- snippet 31
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.sub_left (L81-L82)
theorem sub_left (x y z : M₁) : B₁ (x - y) z = B₁ x z - B₁ y z := map_sub₂ _ _ _ _
```

-- snippet 32
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.flip_flip (L138-L144)
theorem flip_flip :
    flipHom.trans flipHom = LinearEquiv.refl R (BilinForm R M) := by
ext A
  simp

/-- The `flip` of a bilinear form over a commutative ring, obtained by exchanging the left and
right arguments. -/
```

-- snippet 33
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.zero_left (L73-L74)
theorem zero_left (x : M) : B 0 x = 0 := map_zero₂ _ _
```

-- snippet 34
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.neg_apply (L115-L117)
theorem neg_apply (x y : M₁) : (-B₁) x y = -B₁ x y :=
rfl
```

-- snippet 35
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_right (L71-L72)
theorem smul_right (a : R) (x y : M) : B x (a • y) = a * B x y := map_smul _ _ _
```

-- snippet 36
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.congr_fun (L102-L103)
theorem congr_fun (h : B = D) (x y : M) : B x y = D x y := congr_fun₂ h _ _
```

-- snippet 37
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.ext (L100-L101)
theorem ext (H : ∀ x y : M, B x y = D x y) : B = D := ext₂ H
```

-- snippet 38
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_right_of_tower (L88-L93)
lemma smul_right_of_tower (r : S) (x y : M) : B x (r • y) = r • B x y := by
rw [← IsScalarTower.algebraMap_smul R r, smul_right, Algebra.smul_def]

variable {D : BilinForm R M} {D₁ : BilinForm R₁ M₁}

-- TODO: instantiate `FunLike`
```

-- snippet 39
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.sub_right (L83-L84)
theorem sub_right (x y z : M₁) : B₁ x (y - z) = B₁ x y - B₁ x z := map_sub _ _ _
```

-- snippet 40
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.flip (L145-L150)
abbrev flip (B : BilinForm R M) :=
flipHom B

end flip

/-- The restriction of a bilinear form on a submodule. -/
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.LinearAlgebra.BilinearForm.Properties).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
theorem restrict {B : BilinForm R M} (b : B.IsSymm) (W : Submodule R M) :
    (B.restrict W).IsSymm
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.IsRefl (L59-L62)
def IsRefl (B : BilinForm R M) : Prop := LinearMap.IsRefl B
namespace IsRefl
```

-- snippet 2
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.eq_zero (L63-L79)
theorem eq_zero (H : B.IsRefl) : ∀ {x y : M}, B x y = 0 → B y x = 0 := fun {x y} => H x y
protected theorem neg {B : BilinForm R₁ M₁} (hB : B.IsRefl) : (-B).IsRefl := fun x y =>
  neg_eq_zero.mpr ∘ hB x y ∘ neg_eq_zero.mp

protected theorem smul {α : Type*} [Semiring α] [IsDomain α] [Module α R] [SMulCommClass R α R]
    [IsTorsionFree α R] (a : α) {B : BilinForm R M} (hB : B.IsRefl) :
    (a • B).IsRefl := fun _ _ h =>
  (smul_eq_zero.mp h).elim (fun ha => smul_eq_zero_of_left ha _) fun hBz =>
    smul_eq_zero_of_right _ (hB _ _ hBz)

protected theorem groupSMul {α} [Group α] [DistribMulAction α R] [SMulCommClass R α R] (a : α)
    {B : BilinForm R M} (hB : B.IsRefl) : (a • B).IsRefl := fun x y =>
  (smul_eq_zero_iff_eq _).mpr ∘ hB x y ∘ (smul_eq_zero_iff_eq _).mp

end IsRefl
```

-- snippet 3
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isRefl_zero (L81-L82)
theorem isRefl_zero : (0 : BilinForm R M).IsRefl := fun _ _ _ => rfl
```

-- snippet 4
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isRefl_neg (L84-L90)
theorem isRefl_neg {B : BilinForm R₁ M₁} : (-B).IsRefl ↔ B.IsRefl :=
⟨fun h => neg_neg B ▸ h.neg, IsRefl.neg⟩

/-- The proposition that a bilinear form is symmetric -/
structure IsSymm (B : BilinForm R M) : Prop where
  protected eq : ∀ x y, B x y = B y x
```

-- snippet 5
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isSymm_def (L91-L94)
theorem isSymm_def : IsSymm B ↔ ∀ x y, B x y = B y x where
  mp := fun ⟨h⟩ ↦ h
mpr h := ⟨h⟩
```

-- snippet 6
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isSymm_iff (L95-L99)
theorem isSymm_iff : IsSymm B ↔ LinearMap.IsSymm B := by
simp [isSymm_def, LinearMap.isSymm_def]

namespace IsSymm
```

-- snippet 7
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isRefl (L100-L115)
theorem isRefl (H : B.IsSymm) : B.IsRefl := fun x y H1 => H.eq x y ▸ H1
protected theorem add {B₁ B₂ : BilinForm R M} (hB₁ : B₁.IsSymm) (hB₂ : B₂.IsSymm) :
    (B₁ + B₂).IsSymm := ⟨fun x y => (congr_arg₂ (· + ·) (hB₁.eq x y) (hB₂.eq x y) :)⟩

protected theorem sub {B₁ B₂ : BilinForm R₁ M₁} (hB₁ : B₁.IsSymm) (hB₂ : B₂.IsSymm) :
    (B₁ - B₂).IsSymm := ⟨fun x y => (congr_arg₂ Sub.sub (hB₁.eq x y) (hB₂.eq x y) :)⟩

protected theorem neg {B : BilinForm R₁ M₁} (hB : B.IsSymm) : (-B).IsSymm := ⟨fun x y =>
  congr_arg Neg.neg (hB.eq x y)⟩

protected theorem smul {α} [Monoid α] [DistribMulAction α R] [SMulCommClass R α R] (a : α)
    {B : BilinForm R M} (hB : B.IsSymm) : (a • B).IsSymm := ⟨fun x y =>
  congr_arg (a • ·) (hB.eq x y)⟩

/-- The restriction of a symmetric bilinear form on a submodule is also symmetric. -/
```

-- snippet 8
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isSymm_zero (L122-L123)
theorem isSymm_zero : (0 : BilinForm R M).IsSymm := ⟨fun _ _ => rfl⟩
```

-- snippet 9
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isSymm_neg (L125-L127)
theorem isSymm_neg {B : BilinForm R₁ M₁} : (-B).IsSymm ↔ B.IsSymm :=
⟨fun h => neg_neg B ▸ h.neg, IsSymm.neg⟩
```

-- snippet 10
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isSymm_iff_flip (L128-L137)
theorem isSymm_iff_flip : B.IsSymm ↔ flipHom B = B where
  mp := fun ⟨h⟩ ↦ by ext; simp [h]
mpr h := ⟨fun x y ↦ by rw [← flip_apply, h]⟩

section polarization

variable {R : Type*} [Field R] [NeZero (2 : R)] [Module R M] {B C : BilinForm R M}

/-- Polarization identity: a symmetric bilinear form can be expressed through the values
it takes on the diagonal. -/
```

-- snippet 11
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.IsSymm (L138-L145)
lemma IsSymm.polarization (x y : M) (hB : B.IsSymm) :
    B x y = (B (x + y) (x + y) - B x x - B y y) / 2 := by
simp only [map_add, LinearMap.add_apply]
  rw [hB.eq y x]
  ring_nf
  rw [mul_assoc, inv_mul_cancel₀ two_ne_zero, mul_one]

/-- A symmetric bilinear form is characterized by the values it takes on the diagonal. -/
```

-- snippet 12
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.ext_of_isSymm (L146-L152)
lemma ext_of_isSymm (hB : IsSymm B) (hC : IsSymm C)
    (h : ∀ x, B x x = C x x) : B = C := by
ext x y
  rw [hB.polarization, hC.polarization]
  simp_rw [h]

/-- A symmetric bilinear form is characterized by the values it takes on the diagonal. -/
```

-- snippet 13
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.ext_iff_of_isSymm (L153-L159)
lemma ext_iff_of_isSymm (hB : IsSymm B) (hC : IsSymm C) :
    B = C ↔ ∀ x, B x x = C x x where
  mp h := by simp [h]
mpr := ext_of_isSymm hB hC

end polarization
```

-- snippet 14
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isSymm_iff_basis (L160-L186)
lemma isSymm_iff_basis {ι : Type*} (b : Basis ι R M) :
    IsSymm B ↔ ∀ i j, B (b i) (b j) = B (b j) (b i) where
  mp := fun ⟨h⟩ i j ↦ h _ _
mpr := by
    refine fun h ↦ ⟨fun x y ↦ ?_⟩
    obtain ⟨fx, tx, ix, -, hx⟩ := Submodule.mem_span_iff_exists_finset_subset.1
      (by simp : x ∈ Submodule.span R (Set.range b))
    obtain ⟨fy, ty, iy, -, hy⟩ := Submodule.mem_span_iff_exists_finset_subset.1
      (by simp : y ∈ Submodule.span R (Set.range b))
    rw [← hx, ← hy]
    simp only [map_sum, map_smul, coe_sum, Finset.sum_apply, smul_apply, smul_eq_mul,
      Finset.mul_sum]
    rw [Finset.sum_comm]
    refine Finset.sum_congr rfl (fun b₁ h₁ ↦ Finset.sum_congr rfl fun b₂ h₂ ↦ ?_)
    rw [mul_left_comm]
    obtain ⟨i, rfl⟩ := ix h₁
    obtain ⟨j, rfl⟩ := iy h₂
    rw [h]

/-! ### Positive semidefinite bilinear forms -/

section PositiveSemidefinite

/-- A bilinear form `B` is **nonnegative** if for any `x` we have `0 ≤ B x x`. -/
structure IsNonneg [LE R] (B : BilinForm R M) where
  nonneg : ∀ x, 0 ≤ B x x
```

-- snippet 15
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Properties.isNonneg_def (L187-L190)
lemma isNonneg_def [LE R] {B : BilinForm R M} : B.IsNonneg ↔ ∀ x, 0 ≤ B x x :=
⟨fun ⟨h⟩ ↦ h, fun h ↦ ⟨h⟩⟩

/-- A bilinear form is nonnegative if and only if it is nonnegative as a sesquilinear form. -/
```

-- snippet 16
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.add_left (L65-L66)
theorem add_left (x y z : M) : B (x + y) z = B x z + B y z := map_add₂ _ _ _ _
```

-- snippet 17
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.add_apply (L111-L113)
theorem add_apply (x y : M) : (B + D) x y = B x y + D x y :=
rfl
```

-- snippet 18
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.coeFnAddMonoidHom (L124-L131)
def coeFnAddMonoidHom : BilinForm R M →+ M → M → R where
  toFun := fun B x y => B x y
map_zero' := rfl
  map_add' _ _ := rfl

section flip

/-- The flip of a bilinear form, obtained by exchanging the left and right arguments. -/
```

-- snippet 19
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.zero_right (L75-L76)
theorem zero_right (x : M) : B x 0 = 0 := map_zero _
```

-- snippet 20
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.lsmul_flip_apply (L158-L160)
theorem lsmul_flip_apply (m : M) : (lsmul R M).flip m = toSpanSingleton R M m := rfl
end LinearMap
```

-- snippet 21
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.coe_injective (L94-L98)
theorem coe_injective : Function.Injective ((fun B x y => B x y) : BilinForm R M → M → M → R) :=
fun B D h => by
    ext x y
    apply congrFun₂ h
```

-- snippet 22
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.neg_left (L77-L78)
theorem neg_left (x y : M₁) : B₁ (-x) y = -B₁ x y := map_neg₂ _ _ _
```

-- snippet 23
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_left_of_tower (L85-L87)
lemma smul_left_of_tower (r : S) (x y : M) : B (r • x) y = r • B x y := by
rw [← IsScalarTower.algebraMap_smul R r, smul_left, Algebra.smul_def]
```

-- snippet 24
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.flip_apply (L135-L137)
theorem flip_apply (A : BilinForm R M) (x y : M) : flipHom A x y = A y x :=
rfl
```

-- snippet 25
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_left (L67-L68)
theorem smul_left (a : R) (x y : M) : B (a • x) y = a * B x y := map_smul₂ _ _ _ _
```

-- snippet 26
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.add_right (L69-L70)
theorem add_right (x y z : M) : B x (y + z) = B x y + B x z := map_add _ _ _
```

-- snippet 27
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.flipHom (L132-L133)
def flipHom : BilinForm R M ≃ₗ[R] BilinForm R M := LinearMap.lflip
```

-- snippet 28
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.zero_apply (L105-L109)
theorem zero_apply (x y : M) : (0 : BilinForm R M) x y = 0 :=
rfl

variable (B D B₁ D₁)
```

-- snippet 29
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.sub_apply (L119-L122)
theorem sub_apply (x y : M₁) : (B₁ - D₁) x y = B₁ x y - D₁ x y :=
rfl

/-- `coeFn` as an `AddMonoidHom` -/
```

-- snippet 30
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.neg_right (L79-L80)
theorem neg_right (x y : M₁) : B₁ x (-y) = -B₁ x y := map_neg _ _
```

-- snippet 31
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.sub_left (L81-L82)
theorem sub_left (x y z : M₁) : B₁ (x - y) z = B₁ x z - B₁ y z := map_sub₂ _ _ _ _
```

-- snippet 32
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.flip_flip (L138-L144)
theorem flip_flip :
    flipHom.trans flipHom = LinearEquiv.refl R (BilinForm R M) := by
ext A
  simp

/-- The `flip` of a bilinear form over a commutative ring, obtained by exchanging the left and
right arguments. -/
```

-- snippet 33
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.zero_left (L73-L74)
theorem zero_left (x : M) : B 0 x = 0 := map_zero₂ _ _
```

-- snippet 34
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.neg_apply (L115-L117)
theorem neg_apply (x y : M₁) : (-B₁) x y = -B₁ x y :=
rfl
```

-- snippet 35
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_right (L71-L72)
theorem smul_right (a : R) (x y : M) : B x (a • y) = a * B x y := map_smul _ _ _
```

-- snippet 36
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.congr_fun (L102-L103)
theorem congr_fun (h : B = D) (x y : M) : B x y = D x y := congr_fun₂ h _ _
```

-- snippet 37
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.ext (L100-L101)
theorem ext (H : ∀ x y : M, B x y = D x y) : B = D := ext₂ H
```

-- snippet 38
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_right_of_tower (L88-L93)
lemma smul_right_of_tower (r : S) (x y : M) : B x (r • y) = r • B x y := by
rw [← IsScalarTower.algebraMap_smul R r, smul_right, Algebra.smul_def]

variable {D : BilinForm R M} {D₁ : BilinForm R₁ M₁}

-- TODO: instantiate `FunLike`
```

-- snippet 39
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.sub_right (L83-L84)
theorem sub_right (x y z : M₁) : B₁ x (y - z) = B₁ x y - B₁ x z := map_sub _ _ _
```

-- snippet 40
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.flip (L145-L150)
abbrev flip (B : BilinForm R M) :=
flipHom B

end flip

/-- The restriction of a bilinear form on a submodule. -/
```
[/INST]


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Analysis.MeanInequalitiesPow).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
theorem arith_mean_le_rpow_mean (w z : ι → ℝ≥0) (hw' : ∑ i ∈ s, w i = 1) {p : ℝ} (hp : 1 ≤ p) :
    ∑ i ∈ s, w i * z i ≤ (∑ i ∈ s, w i * z i ^ p) ^ (1 / p)
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.pow_arith_mean_le_arith_mean_pow (L58-L62)
theorem pow_arith_mean_le_arith_mean_pow (w z : ι → ℝ) (hw : ∀ i ∈ s, 0 ≤ w i)
    (hw' : ∑ i ∈ s, w i = 1) (hz : ∀ i ∈ s, 0 ≤ z i) (n : ℕ) :
    (∑ i ∈ s, w i * z i) ^ n ≤ ∑ i ∈ s, w i * z i ^ n :=
(convexOn_pow n).map_sum_le hw hw' hz
```

-- snippet 2
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.pow_arith_mean_le_arith_mean_pow_of_even (L63-L67)
theorem pow_arith_mean_le_arith_mean_pow_of_even (w z : ι → ℝ) (hw : ∀ i ∈ s, 0 ≤ w i)
    (hw' : ∑ i ∈ s, w i = 1) {n : ℕ} (hn : Even n) :
    (∑ i ∈ s, w i * z i) ^ n ≤ ∑ i ∈ s, w i * z i ^ n :=
hn.convexOn_pow.map_sum_le hw hw' fun _ _ => Set.mem_univ _
```

-- snippet 3
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.zpow_arith_mean_le_arith_mean_zpow (L68-L72)
theorem zpow_arith_mean_le_arith_mean_zpow (w z : ι → ℝ) (hw : ∀ i ∈ s, 0 ≤ w i)
    (hw' : ∑ i ∈ s, w i = 1) (hz : ∀ i ∈ s, 0 < z i) (m : ℤ) :
    (∑ i ∈ s, w i * z i) ^ m ≤ ∑ i ∈ s, w i * z i ^ m :=
(convexOn_zpow m).map_sum_le hw hw' hz
```

-- snippet 4
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_arith_mean_le_arith_mean_rpow (L73-L77)
theorem rpow_arith_mean_le_arith_mean_rpow (w z : ι → ℝ) (hw : ∀ i ∈ s, 0 ≤ w i)
    (hw' : ∑ i ∈ s, w i = 1) (hz : ∀ i ∈ s, 0 ≤ z i) {p : ℝ} (hp : 1 ≤ p) :
    (∑ i ∈ s, w i * z i) ^ p ≤ ∑ i ∈ s, w i * z i ^ p :=
(convexOn_rpow hp).map_sum_le hw hw' hz
```

-- snippet 5
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.pow_arith_mean_le_arith_mean_pow (L95-L102)
theorem pow_arith_mean_le_arith_mean_pow (w z : ι → ℝ≥0) (hw' : ∑ i ∈ s, w i = 1) (n : ℕ) :
    (∑ i ∈ s, w i * z i) ^ n ≤ ∑ i ∈ s, w i * z i ^ n :=
mod_cast
    Real.pow_arith_mean_le_arith_mean_pow s _ _ (fun i _ => (w i).coe_nonneg)
      (mod_cast hw') (fun i _ => (z i).coe_nonneg) n

/-- Weighted generalized mean inequality, version for sums over finite sets, with `ℝ≥0`-valued
functions and real exponents. -/
```

-- snippet 6
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_arith_mean_le_arith_mean_rpow (L103-L109)
theorem rpow_arith_mean_le_arith_mean_rpow (w z : ι → ℝ≥0) (hw' : ∑ i ∈ s, w i = 1) {p : ℝ}
    (hp : 1 ≤ p) : (∑ i ∈ s, w i * z i) ^ p ≤ ∑ i ∈ s, w i * z i ^ p :=
mod_cast
    Real.rpow_arith_mean_le_arith_mean_rpow s _ _ (fun i _ => (w i).coe_nonneg)
      (mod_cast hw') (fun i _ => (z i).coe_nonneg) hp

/-- Weighted generalized mean inequality, version for two elements of `ℝ≥0` and real exponents. -/
```

-- snippet 7
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_arith_mean_le_arith_mean2_rpow (L110-L116)
theorem rpow_arith_mean_le_arith_mean2_rpow (w₁ w₂ z₁ z₂ : ℝ≥0) (hw' : w₁ + w₂ = 1) {p : ℝ}
    (hp : 1 ≤ p) : (w₁ * z₁ + w₂ * z₂) ^ p ≤ w₁ * z₁ ^ p + w₂ * z₂ ^ p := by
have h := rpow_arith_mean_le_arith_mean_rpow univ ![w₁, w₂] ![z₁, z₂] ?_ hp
  · simpa [Fin.sum_univ_succ] using h
  · simp [hw', Fin.sum_univ_succ]

/-- Unweighted mean inequality, version for two elements of `ℝ≥0` and real exponents. -/
```

-- snippet 8
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_add_le_mul_rpow_add_rpow (L117-L130)
theorem rpow_add_le_mul_rpow_add_rpow (z₁ z₂ : ℝ≥0) {p : ℝ} (hp : 1 ≤ p) :
    (z₁ + z₂) ^ p ≤ (2 : ℝ≥0) ^ (p - 1) * (z₁ ^ p + z₂ ^ p) := by
rcases eq_or_lt_of_le hp with (rfl | h'p)
  · simp only [rpow_one, sub_self, rpow_zero, one_mul]; rfl
  convert rpow_arith_mean_le_arith_mean2_rpow (1 / 2) (1 / 2) (2 * z₁) (2 * z₂) (add_halves 1) hp
    using 1
  · simp only [one_div, inv_mul_cancel_left₀, Ne, two_ne_zero,
      not_false_iff]
  · have A : p - 1 ≠ 0 := ne_of_gt (sub_pos.2 h'p)
    simp only [mul_rpow, rpow_sub' A, rpow_one]
    ring

/-- Weighted generalized mean inequality, version for sums over finite sets, with `ℝ≥0`-valued
functions and real exponents. -/
```

-- snippet 9
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.add_rpow_le_rpow_add (L144-L157)
theorem add_rpow_le_rpow_add {p : ℝ} (a b : ℝ≥0) (hp1 : 1 ≤ p) : a ^ p + b ^ p ≤ (a + b) ^ p := by
have hp_pos : 0 < p := by positivity
  by_cases h_zero : a + b = 0
  · simp [add_eq_zero.mp h_zero, hp_pos.ne']
  have h_nonzero : ¬(a = 0 ∧ b = 0) := by rwa [add_eq_zero] at h_zero
  have h_add : a / (a + b) + b / (a + b) = 1 := by rw [← add_div, div_self h_zero]
  have h := add_rpow_le_one_of_add_le_one (a / (a + b)) (b / (a + b)) h_add.le hp1
  rw [div_rpow a (a + b), div_rpow b (a + b)] at h
  have hab_0 : (a + b) ^ p ≠ 0 := by simp [h_nonzero]
  have h_mul : (a + b) ^ p * (a ^ p / (a + b) ^ p + b ^ p / (a + b) ^ p) ≤ (a + b) ^ p := by
    nth_rw 4 [← mul_one ((a + b) ^ p)]; gcongr
  rwa [div_eq_mul_inv, div_eq_mul_inv, mul_add, mul_comm (a ^ p), mul_comm (b ^ p), ← mul_assoc, ←
    mul_assoc, mul_inv_cancel₀ hab_0, one_mul, one_mul] at h_mul
```

-- snippet 10
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_add_rpow_le_add (L158-L164)
theorem rpow_add_rpow_le_add {p : ℝ} (a b : ℝ≥0) (hp1 : 1 ≤ p) :
    (a ^ p + b ^ p) ^ (1 / p) ≤ a + b := by
rw [one_div]
  rw [← @NNReal.le_rpow_inv_iff _ _ p⁻¹ (by simp [lt_of_lt_of_le zero_lt_one hp1])]
  rw [inv_inv]
  exact add_rpow_le_rpow_add _ _ hp1
```

-- snippet 11
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_add_rpow_le (L165-L177)
theorem rpow_add_rpow_le {p q : ℝ} (a b : ℝ≥0) (hp_pos : 0 < p) (hpq : p ≤ q) :
    (a ^ q + b ^ q) ^ (1 / q) ≤ (a ^ p + b ^ p) ^ (1 / p) := by
have h_rpow : ∀ a : ℝ≥0, a ^ q = (a ^ p) ^ (q / p) := fun a => by
    rw [← NNReal.rpow_mul, div_eq_inv_mul, ← mul_assoc, mul_inv_cancel₀ hp_pos.ne.symm,
      one_mul]
  have h_rpow_add_rpow_le_add :
    ((a ^ p) ^ (q / p) + (b ^ p) ^ (q / p)) ^ (1 / (q / p)) ≤ a ^ p + b ^ p := by
    refine rpow_add_rpow_le_add (a ^ p) (b ^ p) ?_
    rwa [one_le_div hp_pos]
  rw [h_rpow a, h_rpow b, one_div p, NNReal.le_rpow_inv_iff hp_pos, ← NNReal.rpow_mul, mul_comm,
    mul_one_div]
  rwa [one_div_div] at h_rpow_add_rpow_le_add
```

-- snippet 12
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_add_le_add_rpow (L178-L190)
theorem rpow_add_le_add_rpow {p : ℝ} (a b : ℝ≥0) (hp : 0 ≤ p) (hp1 : p ≤ 1) :
    (a + b) ^ p ≤ a ^ p + b ^ p := by
rcases hp.eq_or_lt with (rfl | hp_pos)
  · simp
  have h := rpow_add_rpow_le a b hp_pos hp1
  rw [one_div_one, one_div] at h
  repeat' rw [NNReal.rpow_one] at h
  exact (NNReal.le_rpow_inv_iff hp_pos).mp h

end NNReal

namespace Real
```

-- snippet 13
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.add_rpow_le_rpow_add (L191-L196)
lemma add_rpow_le_rpow_add {p : ℝ} {a b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hp1 : 1 ≤ p) :
     a ^ p + b ^ p ≤ (a + b) ^ p := by
lift a to NNReal using ha
  lift b to NNReal using hb
  exact_mod_cast NNReal.add_rpow_le_rpow_add a b hp1
```

-- snippet 14
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_add_rpow_le_add (L197-L202)
lemma rpow_add_rpow_le_add {p : ℝ} {a b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hp1 : 1 ≤ p) :
    (a ^ p + b ^ p) ^ (1 / p) ≤ a + b := by
lift a to NNReal using ha
  lift b to NNReal using hb
  exact_mod_cast NNReal.rpow_add_rpow_le_add a b hp1
```

-- snippet 15
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_add_rpow_le (L203-L209)
lemma rpow_add_rpow_le {p q : ℝ} {a b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hp_pos : 0 < p)
    (hpq : p ≤ q) :
    (a ^ q + b ^ q) ^ (1 / q) ≤ (a ^ p + b ^ p) ^ (1 / p) := by
lift a to NNReal using ha
  lift b to NNReal using hb
  exact_mod_cast NNReal.rpow_add_rpow_le a b hp_pos hpq
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Analysis.MeanInequalitiesPow).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
theorem arith_mean_le_rpow_mean (w z : ι → ℝ≥0) (hw' : ∑ i ∈ s, w i = 1) {p : ℝ} (hp : 1 ≤ p) :
    ∑ i ∈ s, w i * z i ≤ (∑ i ∈ s, w i * z i ^ p) ^ (1 / p)
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.pow_arith_mean_le_arith_mean_pow (L58-L62)
theorem pow_arith_mean_le_arith_mean_pow (w z : ι → ℝ) (hw : ∀ i ∈ s, 0 ≤ w i)
    (hw' : ∑ i ∈ s, w i = 1) (hz : ∀ i ∈ s, 0 ≤ z i) (n : ℕ) :
    (∑ i ∈ s, w i * z i) ^ n ≤ ∑ i ∈ s, w i * z i ^ n :=
(convexOn_pow n).map_sum_le hw hw' hz
```

-- snippet 2
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.pow_arith_mean_le_arith_mean_pow_of_even (L63-L67)
theorem pow_arith_mean_le_arith_mean_pow_of_even (w z : ι → ℝ) (hw : ∀ i ∈ s, 0 ≤ w i)
    (hw' : ∑ i ∈ s, w i = 1) {n : ℕ} (hn : Even n) :
    (∑ i ∈ s, w i * z i) ^ n ≤ ∑ i ∈ s, w i * z i ^ n :=
hn.convexOn_pow.map_sum_le hw hw' fun _ _ => Set.mem_univ _
```

-- snippet 3
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.zpow_arith_mean_le_arith_mean_zpow (L68-L72)
theorem zpow_arith_mean_le_arith_mean_zpow (w z : ι → ℝ) (hw : ∀ i ∈ s, 0 ≤ w i)
    (hw' : ∑ i ∈ s, w i = 1) (hz : ∀ i ∈ s, 0 < z i) (m : ℤ) :
    (∑ i ∈ s, w i * z i) ^ m ≤ ∑ i ∈ s, w i * z i ^ m :=
(convexOn_zpow m).map_sum_le hw hw' hz
```

-- snippet 4
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_arith_mean_le_arith_mean_rpow (L73-L77)
theorem rpow_arith_mean_le_arith_mean_rpow (w z : ι → ℝ) (hw : ∀ i ∈ s, 0 ≤ w i)
    (hw' : ∑ i ∈ s, w i = 1) (hz : ∀ i ∈ s, 0 ≤ z i) {p : ℝ} (hp : 1 ≤ p) :
    (∑ i ∈ s, w i * z i) ^ p ≤ ∑ i ∈ s, w i * z i ^ p :=
(convexOn_rpow hp).map_sum_le hw hw' hz
```

-- snippet 5
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.pow_arith_mean_le_arith_mean_pow (L95-L102)
theorem pow_arith_mean_le_arith_mean_pow (w z : ι → ℝ≥0) (hw' : ∑ i ∈ s, w i = 1) (n : ℕ) :
    (∑ i ∈ s, w i * z i) ^ n ≤ ∑ i ∈ s, w i * z i ^ n :=
mod_cast
    Real.pow_arith_mean_le_arith_mean_pow s _ _ (fun i _ => (w i).coe_nonneg)
      (mod_cast hw') (fun i _ => (z i).coe_nonneg) n

/-- Weighted generalized mean inequality, version for sums over finite sets, with `ℝ≥0`-valued
functions and real exponents. -/
```

-- snippet 6
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_arith_mean_le_arith_mean_rpow (L103-L109)
theorem rpow_arith_mean_le_arith_mean_rpow (w z : ι → ℝ≥0) (hw' : ∑ i ∈ s, w i = 1) {p : ℝ}
    (hp : 1 ≤ p) : (∑ i ∈ s, w i * z i) ^ p ≤ ∑ i ∈ s, w i * z i ^ p :=
mod_cast
    Real.rpow_arith_mean_le_arith_mean_rpow s _ _ (fun i _ => (w i).coe_nonneg)
      (mod_cast hw') (fun i _ => (z i).coe_nonneg) hp

/-- Weighted generalized mean inequality, version for two elements of `ℝ≥0` and real exponents. -/
```

-- snippet 7
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_arith_mean_le_arith_mean2_rpow (L110-L116)
theorem rpow_arith_mean_le_arith_mean2_rpow (w₁ w₂ z₁ z₂ : ℝ≥0) (hw' : w₁ + w₂ = 1) {p : ℝ}
    (hp : 1 ≤ p) : (w₁ * z₁ + w₂ * z₂) ^ p ≤ w₁ * z₁ ^ p + w₂ * z₂ ^ p := by
have h := rpow_arith_mean_le_arith_mean_rpow univ ![w₁, w₂] ![z₁, z₂] ?_ hp
  · simpa [Fin.sum_univ_succ] using h
  · simp [hw', Fin.sum_univ_succ]

/-- Unweighted mean inequality, version for two elements of `ℝ≥0` and real exponents. -/
```

-- snippet 8
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_add_le_mul_rpow_add_rpow (L117-L130)
theorem rpow_add_le_mul_rpow_add_rpow (z₁ z₂ : ℝ≥0) {p : ℝ} (hp : 1 ≤ p) :
    (z₁ + z₂) ^ p ≤ (2 : ℝ≥0) ^ (p - 1) * (z₁ ^ p + z₂ ^ p) := by
rcases eq_or_lt_of_le hp with (rfl | h'p)
  · simp only [rpow_one, sub_self, rpow_zero, one_mul]; rfl
  convert rpow_arith_mean_le_arith_mean2_rpow (1 / 2) (1 / 2) (2 * z₁) (2 * z₂) (add_halves 1) hp
    using 1
  · simp only [one_div, inv_mul_cancel_left₀, Ne, two_ne_zero,
      not_false_iff]
  · have A : p - 1 ≠ 0 := ne_of_gt (sub_pos.2 h'p)
    simp only [mul_rpow, rpow_sub' A, rpow_one]
    ring

/-- Weighted generalized mean inequality, version for sums over finite sets, with `ℝ≥0`-valued
functions and real exponents. -/
```

-- snippet 9
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.add_rpow_le_rpow_add (L144-L157)
theorem add_rpow_le_rpow_add {p : ℝ} (a b : ℝ≥0) (hp1 : 1 ≤ p) : a ^ p + b ^ p ≤ (a + b) ^ p := by
have hp_pos : 0 < p := by positivity
  by_cases h_zero : a + b = 0
  · simp [add_eq_zero.mp h_zero, hp_pos.ne']
  have h_nonzero : ¬(a = 0 ∧ b = 0) := by rwa [add_eq_zero] at h_zero
  have h_add : a / (a + b) + b / (a + b) = 1 := by rw [← add_div, div_self h_zero]
  have h := add_rpow_le_one_of_add_le_one (a / (a + b)) (b / (a + b)) h_add.le hp1
  rw [div_rpow a (a + b), div_rpow b (a + b)] at h
  have hab_0 : (a + b) ^ p ≠ 0 := by simp [h_nonzero]
  have h_mul : (a + b) ^ p * (a ^ p / (a + b) ^ p + b ^ p / (a + b) ^ p) ≤ (a + b) ^ p := by
    nth_rw 4 [← mul_one ((a + b) ^ p)]; gcongr
  rwa [div_eq_mul_inv, div_eq_mul_inv, mul_add, mul_comm (a ^ p), mul_comm (b ^ p), ← mul_assoc, ←
    mul_assoc, mul_inv_cancel₀ hab_0, one_mul, one_mul] at h_mul
```

-- snippet 10
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_add_rpow_le_add (L158-L164)
theorem rpow_add_rpow_le_add {p : ℝ} (a b : ℝ≥0) (hp1 : 1 ≤ p) :
    (a ^ p + b ^ p) ^ (1 / p) ≤ a + b := by
rw [one_div]
  rw [← @NNReal.le_rpow_inv_iff _ _ p⁻¹ (by simp [lt_of_lt_of_le zero_lt_one hp1])]
  rw [inv_inv]
  exact add_rpow_le_rpow_add _ _ hp1
```

-- snippet 11
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_add_rpow_le (L165-L177)
theorem rpow_add_rpow_le {p q : ℝ} (a b : ℝ≥0) (hp_pos : 0 < p) (hpq : p ≤ q) :
    (a ^ q + b ^ q) ^ (1 / q) ≤ (a ^ p + b ^ p) ^ (1 / p) := by
have h_rpow : ∀ a : ℝ≥0, a ^ q = (a ^ p) ^ (q / p) := fun a => by
    rw [← NNReal.rpow_mul, div_eq_inv_mul, ← mul_assoc, mul_inv_cancel₀ hp_pos.ne.symm,
      one_mul]
  have h_rpow_add_rpow_le_add :
    ((a ^ p) ^ (q / p) + (b ^ p) ^ (q / p)) ^ (1 / (q / p)) ≤ a ^ p + b ^ p := by
    refine rpow_add_rpow_le_add (a ^ p) (b ^ p) ?_
    rwa [one_le_div hp_pos]
  rw [h_rpow a, h_rpow b, one_div p, NNReal.le_rpow_inv_iff hp_pos, ← NNReal.rpow_mul, mul_comm,
    mul_one_div]
  rwa [one_div_div] at h_rpow_add_rpow_le_add
```

-- snippet 12
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_add_le_add_rpow (L178-L190)
theorem rpow_add_le_add_rpow {p : ℝ} (a b : ℝ≥0) (hp : 0 ≤ p) (hp1 : p ≤ 1) :
    (a + b) ^ p ≤ a ^ p + b ^ p := by
rcases hp.eq_or_lt with (rfl | hp_pos)
  · simp
  have h := rpow_add_rpow_le a b hp_pos hp1
  rw [one_div_one, one_div] at h
  repeat' rw [NNReal.rpow_one] at h
  exact (NNReal.le_rpow_inv_iff hp_pos).mp h

end NNReal

namespace Real
```

-- snippet 13
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.add_rpow_le_rpow_add (L191-L196)
lemma add_rpow_le_rpow_add {p : ℝ} {a b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hp1 : 1 ≤ p) :
     a ^ p + b ^ p ≤ (a + b) ^ p := by
lift a to NNReal using ha
  lift b to NNReal using hb
  exact_mod_cast NNReal.add_rpow_le_rpow_add a b hp1
```

-- snippet 14
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_add_rpow_le_add (L197-L202)
lemma rpow_add_rpow_le_add {p : ℝ} {a b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hp1 : 1 ≤ p) :
    (a ^ p + b ^ p) ^ (1 / p) ≤ a + b := by
lift a to NNReal using ha
  lift b to NNReal using hb
  exact_mod_cast NNReal.rpow_add_rpow_le_add a b hp1
```

-- snippet 15
```lean
-- Mathlib.Analysis.MeanInequalitiesPow.rpow_add_rpow_le (L203-L209)
lemma rpow_add_rpow_le {p q : ℝ} {a b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hp_pos : 0 < p)
    (hpq : p ≤ q) :
    (a ^ q + b ^ q) ^ (1 / q) ≤ (a ^ p + b ^ p) ^ (1 / p) := by
lift a to NNReal using ha
  lift b to NNReal using hb
  exact_mod_cast NNReal.rpow_add_rpow_le a b hp_pos hpq
```
[/INST]

mistral-common:Tekken v15 (Mistral chat template, [INST]/[SYSTEM_PROMPT])


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Order.CompleteLattice.Lemmas).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
theorem iSup_bool_eq {f : Bool → α} : ⨆ b : Bool, f b = f true ⊔ f false
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iInf_bool_eq (L56-L58)
theorem iInf_bool_eq {f : Bool → α} : ⨅ b : Bool, f b = f true ⊓ f false :=
@iSup_bool_eq αᵒᵈ _ _
```

-- snippet 2
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.sup_eq_iSup (L59-L61)
theorem sup_eq_iSup (x y : α) : x ⊔ y = ⨆ b : Bool, cond b x y := by
rw [iSup_bool_eq, Bool.cond_true, Bool.cond_false]
```

-- snippet 3
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.inf_eq_iInf (L62-L69)
theorem inf_eq_iInf (x y : α) : x ⊓ y = ⨅ b : Bool, cond b x y :=
@sup_eq_iSup αᵒᵈ _ _ _

/-!
### `iSup` and `iInf` under `ℕ`
-/
```

-- snippet 4
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iSup_ge_eq_iSup_nat_add (L70-L76)
theorem iSup_ge_eq_iSup_nat_add (u : ℕ → α) (n : ℕ) : ⨆ i ≥ n, u i = ⨆ i, u (i + n) := by
apply le_antisymm <;> simp only [iSup_le_iff]
  · refine fun i hi => le_sSup ⟨i - n, ?_⟩
    dsimp only
    rw [Nat.sub_add_cancel hi]
  · exact fun i => le_sSup ⟨i + n, iSup_pos (Nat.le_add_left _ _)⟩
```

-- snippet 5
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iInf_ge_eq_iInf_nat_add (L77-L79)
theorem iInf_ge_eq_iInf_nat_add (u : ℕ → α) (n : ℕ) : ⨅ i ≥ n, u i = ⨅ i, u (i + n) :=
@iSup_ge_eq_iSup_nat_add αᵒᵈ _ _ _
```

-- snippet 6
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.Monotone (L80-L82)
theorem Monotone.iSup_nat_add {f : ℕ → α} (hf : Monotone f) (k : ℕ) : ⨆ n, f (n + k) = ⨆ n, f n :=
le_antisymm (iSup_le fun i => le_iSup _ (i + k)) <| iSup_mono fun i => hf <| Nat.le_add_right i k
```

-- snippet 7
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.Antitone (L83-L88)
theorem Antitone.iInf_nat_add {f : ℕ → α} (hf : Antitone f) (k : ℕ) : ⨅ n, f (n + k) = ⨅ n, f n :=
hf.dual_right.iSup_nat_add k

-- Not `@[simp]` since the subterm `?f (i + ?k)` produces an ugly higher-order unification problem.
-- (Although the `simpNF` linter does not complain.)
-- See: https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/complete_lattice.20and.20has_sup/near/316497982
```

-- snippet 8
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iSup_iInf_ge_nat_add (L89-L97)
theorem iSup_iInf_ge_nat_add (f : ℕ → α) (k : ℕ) :
    ⨆ n, ⨅ i ≥ n, f (i + k) = ⨆ n, ⨅ i ≥ n, f i := by
have hf : Monotone fun n => ⨅ i ≥ n, f i := fun n m h => biInf_mono fun i => h.trans
  rw [← Monotone.iSup_nat_add hf k]
  · simp_rw [iInf_ge_eq_iInf_nat_add, ← Nat.add_assoc]

-- Not `@[simp]` since the subterm `?f (i + ?k)` produces an ugly higher-order unification problem.
-- (Although the `simpNF` linter does not complain.)
-- See: https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/complete_lattice.20and.20has_sup/near/316497982
```

-- snippet 9
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iInf_iSup_ge_nat_add (L98-L101)
theorem iInf_iSup_ge_nat_add :
    ∀ (f : ℕ → α) (k : ℕ), ⨅ n, ⨆ i ≥ n, f (i + k) = ⨅ n, ⨆ i ≥ n, f i :=
@iSup_iInf_ge_nat_add αᵒᵈ _
```

-- snippet 10
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.sup_iSup_nat_succ (L102-L107)
theorem sup_iSup_nat_succ (u : ℕ → α) : (u 0 ⊔ ⨆ i, u (i + 1)) = ⨆ i, u i :=
calc
    (u 0 ⊔ ⨆ i, u (i + 1)) = ⨆ x ∈ {0} ∪ range Nat.succ, u x := by
      { rw [iSup_union, iSup_singleton, iSup_range] }
    _ = ⨆ i, u i := by rw [Nat.zero_union_range_succ, iSup_univ]
```

-- snippet 11
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.inf_iInf_nat_succ (L108-L110)
theorem inf_iInf_nat_succ (u : ℕ → α) : (u 0 ⊓ ⨅ i, u (i + 1)) = ⨅ i, u i :=
@sup_iSup_nat_succ αᵒᵈ _ u
```

-- snippet 12
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iInf_nat_gt_zero_eq (L111-L114)
theorem iInf_nat_gt_zero_eq (f : ℕ → α) : ⨅ i > 0, f i = ⨅ i, f (i + 1) := by
rw [← iInf_range, Nat.range_succ]
  simp
```

-- snippet 13
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iSup_nat_gt_zero_eq (L115-L117)
theorem iSup_nat_gt_zero_eq (f : ℕ → α) : ⨆ i > 0, f i = ⨆ i, f (i + 1) :=
@iInf_nat_gt_zero_eq αᵒᵈ _ f
```

-- snippet 14
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.sup_sInf_le_iInf_sup (L129-L132)
theorem sup_sInf_le_iInf_sup : a ⊔ sInf s ≤ ⨅ b ∈ s, a ⊔ b :=
le_iInf₂ fun _ h => sup_le_sup_left (sInf_le h) _

/-- This is a weaker version of `inf_sSup_eq` -/
```

-- snippet 15
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iSup_inf_le_inf_sSup (L133-L136)
theorem iSup_inf_le_inf_sSup : ⨆ b ∈ s, a ⊓ b ≤ a ⊓ sSup s :=
@sup_sInf_le_iInf_sup αᵒᵈ _ _ _

/-- This is a weaker version of `sInf_sup_eq` -/
```

-- snippet 16
```lean
-- Mathlib.Order.CompleteLattice.Basic.biSup_congr (L161-L164)
theorem biSup_congr {p : ι → Prop} (h : ∀ i, p i → f i = g i) :
    ⨆ (i) (_ : p i), f i = ⨆ (i) (_ : p i), g i :=
iSup_congr fun i ↦ iSup_congr (h i)
```

-- snippet 17
```lean
-- Mathlib.Order.CompleteLattice.Basic.iSup_congr (L157-L159)
theorem iSup_congr (h : ∀ i, f i = g i) : ⨆ i, f i = ⨆ i, g i :=
congr_arg _ <| funext h
```

-- snippet 18
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_le_sSup_of_subset_insert_bot (L97-L99)
theorem sSup_le_sSup_of_subset_insert_bot (h : s ⊆ insert ⊥ t) : sSup s ≤ sSup t :=
(sSup_le_sSup h).trans_eq (sSup_insert.trans (bot_sup_eq _))
```

-- snippet 19
```lean
-- Mathlib.Order.CompleteLattice.Basic.eq_singleton_bot_of_sSup_eq_bot_of_nonempty (L119-L128)
theorem eq_singleton_bot_of_sSup_eq_bot_of_nonempty {s : Set α} (h_sup : sSup s = ⊥)
    (hne : s.Nonempty) : s = {⊥} := by
rw [Set.eq_singleton_iff_nonempty_unique_mem]
  rw [sSup_eq_bot] at h_sup
  exact ⟨hne, h_sup⟩

/-- Introduction rule to prove that `b` is the supremum of `s`: it suffices to check that `b`
is larger than all elements of `s`, and that this is not the case of any `w < b`.
See `csSup_eq_of_forall_le_of_forall_lt_exists_gt` for a version in conditionally complete
lattices. -/
```

-- snippet 20
```lean
-- Mathlib.Order.CompleteLattice.Basic.Function (L172-L177)
theorem Function.Surjective.iSup_comp {f : ι → ι'} (hf : Surjective f) (g : ι' → α) :
    ⨆ x, g (f x) = ⨆ y, g y := by
simp only [iSup.eq_1]
  congr
  exact hf.range_comp g
```

-- snippet 21
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_insert (L93-L95)
theorem sSup_insert {a : α} {s : Set α} : sSup (insert a s) = a ⊔ sSup s :=
((isLUB_sSup s).insert a).sSup_eq
```

-- snippet 22
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_diff_singleton_bot (L101-L104)
theorem sSup_diff_singleton_bot (s : Set α) : sSup (s \ {⊥}) = sSup s :=
(sSup_le_sSup diff_subset).antisymm <|
    sSup_le_sSup_of_subset_insert_bot <| subset_insert_diff_singleton _ _
```

-- snippet 23
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_eq_of_forall_le_of_forall_lt_exists_gt (L134-L139)
theorem sSup_eq_of_forall_le_of_forall_lt_exists_gt (h₁ : ∀ a ∈ s, a ≤ b)
    (h₂ : ∀ w, w < b → ∃ a ∈ s, w < a) : sSup s = b :=
(sSup_le h₁).eq_of_not_lt fun h =>
    let ⟨_, ha, ha'⟩ := h₂ _ h
    ((le_sSup ha).trans_lt ha').false
```

-- snippet 24
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_univ (L88-L91)
theorem sSup_univ : sSup univ = (⊤ : α) :=
(@isLUB_univ α _ _).sSup_eq

-- TODO(Jeremy): get this automatically
```

-- snippet 25
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_le_sSup_of_isCofinalFor (L53-L56)
theorem sSup_le_sSup_of_isCofinalFor (h : IsCofinalFor s t) : sSup s ≤ sSup t :=
IsLeast.mono (isLUB_sSup t) (isLUB_sSup s) <| upperBounds_mono_of_isCofinalFor h

-- We will generalize this to conditionally complete lattices in `csSup_singleton`.
```

-- snippet 26
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_empty (L84-L86)
theorem sSup_empty : sSup ∅ = (⊥ : α) :=
(@isLUB_empty α _ _).sSup_eq
```

-- snippet 27
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_eq_iSup' (L154-L155)
theorem sSup_eq_iSup' (s : Set α) : sSup s = ⨆ a : s, (a : α) := by rw [iSup, Subtype.range_coe]
```

-- snippet 28
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_range (L150-L152)
theorem sSup_range : sSup (range f) = iSup f :=
rfl
```

-- snippet 29
```lean
-- Mathlib.Order.CompleteLattice.Basic.sInf_le_sSup_of_nonempty_inter (L72-L74)
theorem sInf_le_sSup_of_nonempty_inter (h : (s ∩ t).Nonempty) : sInf s ≤ sSup t :=
isGLB_le_isLUB_of_nonempty_inter h (isGLB_sInf s) (isLUB_sSup t)
```

-- snippet 30
```lean
-- Mathlib.Order.CompleteLattice.Basic.iSup_congr_Prop (L194-L199)
theorem iSup_congr_Prop {p q : Prop} {f₁ : p → α} {f₂ : q → α} (pq : p ↔ q)
    (f : ∀ x, f₁ (pq.mpr x) = f₂ x) : iSup f₁ = iSup f₂ := by
obtain rfl := propext pq
  congr with x
  apply f
```

-- snippet 31
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_eq_bot' (L115-L117)
lemma sSup_eq_bot' {s : Set α} : sSup s = ⊥ ↔ s = ∅ ∨ s = {⊥} := by
rw [sSup_eq_bot, ← subset_singleton_iff_eq, subset_singleton_iff]
```

-- snippet 32
```lean
-- Mathlib.Order.CompleteLattice.Basic.sInf_le_sSup (L69-L71)
theorem sInf_le_sSup (hs : s.Nonempty) : sInf s ≤ sSup s :=
isGLB_le_isLUB (isGLB_sInf s) (isLUB_sSup s) hs
```

-- snippet 33
```lean
-- Mathlib.Order.CompleteLattice.Basic.iSup_plift_up (L201-L203)
theorem iSup_plift_up (f : PLift ι → α) : ⨆ i, f (PLift.up i) = ⨆ i, f i :=
(PLift.up_surjective.iSup_congr _) fun _ => rfl
```

-- snippet 34
```lean
-- Mathlib.Order.CompleteLattice.Basic.Equiv (L179-L181)
theorem Equiv.iSup_comp {g : ι' → α} (e : ι ≃ ι') : ⨆ x, g (e x) = ⨆ y, g y :=
e.surjective.iSup_comp _
```

-- snippet 35
```lean
-- Mathlib.Order.CompleteLattice.Basic.biSup_congr' (L166-L170)
theorem biSup_congr' {p : ι → Prop} {f g : (i : ι) → p i → α}
    (h : ∀ i (hi : p i), f i hi = g i hi) :
    ⨆ i, ⨆ (hi : p i), f i hi = ⨆ i, ⨆ (hi : p i), g i hi := by
grind
```

-- snippet 36
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_eq_bot (L110-L113)
theorem sSup_eq_bot : sSup s = ⊥ ↔ ∀ a ∈ s, a = ⊥ :=
⟨fun h _ ha => bot_unique <| h ▸ le_sSup ha, fun h =>
    bot_unique <| sSup_le fun a ha => le_bot_iff.2 <| h a ha⟩
```

-- snippet 37
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_inter_le (L80-L82)
theorem sSup_inter_le {s t : Set α} : sSup (s ∩ t) ≤ sSup s ⊓ sSup t :=
sSup_le fun _ hb => le_inf (le_sSup hb.1) (le_sSup hb.2)
```

-- snippet 38
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_union (L76-L78)
theorem sSup_union {s t : Set α} : sSup (s ∪ t) = sSup s ⊔ sSup t :=
((isLUB_sSup s).union (isLUB_sSup t)).sSup_eq
```

-- snippet 39
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_singleton (L58-L60)
theorem sSup_singleton {a : α} : sSup {a} = a :=
isLUB_singleton.sSup_eq
```

-- snippet 40
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_pair (L106-L108)
theorem sSup_pair {a b : α} : sSup {a, b} = a ⊔ b :=
(@isLUB_pair α _ a b).sSup_eq
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Order.CompleteLattice.Lemmas).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
theorem iSup_bool_eq {f : Bool → α} : ⨆ b : Bool, f b = f true ⊔ f false
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iInf_bool_eq (L56-L58)
theorem iInf_bool_eq {f : Bool → α} : ⨅ b : Bool, f b = f true ⊓ f false :=
@iSup_bool_eq αᵒᵈ _ _
```

-- snippet 2
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.sup_eq_iSup (L59-L61)
theorem sup_eq_iSup (x y : α) : x ⊔ y = ⨆ b : Bool, cond b x y := by
rw [iSup_bool_eq, Bool.cond_true, Bool.cond_false]
```

-- snippet 3
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.inf_eq_iInf (L62-L69)
theorem inf_eq_iInf (x y : α) : x ⊓ y = ⨅ b : Bool, cond b x y :=
@sup_eq_iSup αᵒᵈ _ _ _

/-!
### `iSup` and `iInf` under `ℕ`
-/
```

-- snippet 4
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iSup_ge_eq_iSup_nat_add (L70-L76)
theorem iSup_ge_eq_iSup_nat_add (u : ℕ → α) (n : ℕ) : ⨆ i ≥ n, u i = ⨆ i, u (i + n) := by
apply le_antisymm <;> simp only [iSup_le_iff]
  · refine fun i hi => le_sSup ⟨i - n, ?_⟩
    dsimp only
    rw [Nat.sub_add_cancel hi]
  · exact fun i => le_sSup ⟨i + n, iSup_pos (Nat.le_add_left _ _)⟩
```

-- snippet 5
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iInf_ge_eq_iInf_nat_add (L77-L79)
theorem iInf_ge_eq_iInf_nat_add (u : ℕ → α) (n : ℕ) : ⨅ i ≥ n, u i = ⨅ i, u (i + n) :=
@iSup_ge_eq_iSup_nat_add αᵒᵈ _ _ _
```

-- snippet 6
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.Monotone (L80-L82)
theorem Monotone.iSup_nat_add {f : ℕ → α} (hf : Monotone f) (k : ℕ) : ⨆ n, f (n + k) = ⨆ n, f n :=
le_antisymm (iSup_le fun i => le_iSup _ (i + k)) <| iSup_mono fun i => hf <| Nat.le_add_right i k
```

-- snippet 7
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.Antitone (L83-L88)
theorem Antitone.iInf_nat_add {f : ℕ → α} (hf : Antitone f) (k : ℕ) : ⨅ n, f (n + k) = ⨅ n, f n :=
hf.dual_right.iSup_nat_add k

-- Not `@[simp]` since the subterm `?f (i + ?k)` produces an ugly higher-order unification problem.
-- (Although the `simpNF` linter does not complain.)
-- See: https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/complete_lattice.20and.20has_sup/near/316497982
```

-- snippet 8
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iSup_iInf_ge_nat_add (L89-L97)
theorem iSup_iInf_ge_nat_add (f : ℕ → α) (k : ℕ) :
    ⨆ n, ⨅ i ≥ n, f (i + k) = ⨆ n, ⨅ i ≥ n, f i := by
have hf : Monotone fun n => ⨅ i ≥ n, f i := fun n m h => biInf_mono fun i => h.trans
  rw [← Monotone.iSup_nat_add hf k]
  · simp_rw [iInf_ge_eq_iInf_nat_add, ← Nat.add_assoc]

-- Not `@[simp]` since the subterm `?f (i + ?k)` produces an ugly higher-order unification problem.
-- (Although the `simpNF` linter does not complain.)
-- See: https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/complete_lattice.20and.20has_sup/near/316497982
```

-- snippet 9
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iInf_iSup_ge_nat_add (L98-L101)
theorem iInf_iSup_ge_nat_add :
    ∀ (f : ℕ → α) (k : ℕ), ⨅ n, ⨆ i ≥ n, f (i + k) = ⨅ n, ⨆ i ≥ n, f i :=
@iSup_iInf_ge_nat_add αᵒᵈ _
```

-- snippet 10
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.sup_iSup_nat_succ (L102-L107)
theorem sup_iSup_nat_succ (u : ℕ → α) : (u 0 ⊔ ⨆ i, u (i + 1)) = ⨆ i, u i :=
calc
    (u 0 ⊔ ⨆ i, u (i + 1)) = ⨆ x ∈ {0} ∪ range Nat.succ, u x := by
      { rw [iSup_union, iSup_singleton, iSup_range] }
    _ = ⨆ i, u i := by rw [Nat.zero_union_range_succ, iSup_univ]
```

-- snippet 11
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.inf_iInf_nat_succ (L108-L110)
theorem inf_iInf_nat_succ (u : ℕ → α) : (u 0 ⊓ ⨅ i, u (i + 1)) = ⨅ i, u i :=
@sup_iSup_nat_succ αᵒᵈ _ u
```

-- snippet 12
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iInf_nat_gt_zero_eq (L111-L114)
theorem iInf_nat_gt_zero_eq (f : ℕ → α) : ⨅ i > 0, f i = ⨅ i, f (i + 1) := by
rw [← iInf_range, Nat.range_succ]
  simp
```

-- snippet 13
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iSup_nat_gt_zero_eq (L115-L117)
theorem iSup_nat_gt_zero_eq (f : ℕ → α) : ⨆ i > 0, f i = ⨆ i, f (i + 1) :=
@iInf_nat_gt_zero_eq αᵒᵈ _ f
```

-- snippet 14
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.sup_sInf_le_iInf_sup (L129-L132)
theorem sup_sInf_le_iInf_sup : a ⊔ sInf s ≤ ⨅ b ∈ s, a ⊔ b :=
le_iInf₂ fun _ h => sup_le_sup_left (sInf_le h) _

/-- This is a weaker version of `inf_sSup_eq` -/
```

-- snippet 15
```lean
-- Mathlib.Order.CompleteLattice.Lemmas.iSup_inf_le_inf_sSup (L133-L136)
theorem iSup_inf_le_inf_sSup : ⨆ b ∈ s, a ⊓ b ≤ a ⊓ sSup s :=
@sup_sInf_le_iInf_sup αᵒᵈ _ _ _

/-- This is a weaker version of `sInf_sup_eq` -/
```

-- snippet 16
```lean
-- Mathlib.Order.CompleteLattice.Basic.biSup_congr (L161-L164)
theorem biSup_congr {p : ι → Prop} (h : ∀ i, p i → f i = g i) :
    ⨆ (i) (_ : p i), f i = ⨆ (i) (_ : p i), g i :=
iSup_congr fun i ↦ iSup_congr (h i)
```

-- snippet 17
```lean
-- Mathlib.Order.CompleteLattice.Basic.iSup_congr (L157-L159)
theorem iSup_congr (h : ∀ i, f i = g i) : ⨆ i, f i = ⨆ i, g i :=
congr_arg _ <| funext h
```

-- snippet 18
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_le_sSup_of_subset_insert_bot (L97-L99)
theorem sSup_le_sSup_of_subset_insert_bot (h : s ⊆ insert ⊥ t) : sSup s ≤ sSup t :=
(sSup_le_sSup h).trans_eq (sSup_insert.trans (bot_sup_eq _))
```

-- snippet 19
```lean
-- Mathlib.Order.CompleteLattice.Basic.eq_singleton_bot_of_sSup_eq_bot_of_nonempty (L119-L128)
theorem eq_singleton_bot_of_sSup_eq_bot_of_nonempty {s : Set α} (h_sup : sSup s = ⊥)
    (hne : s.Nonempty) : s = {⊥} := by
rw [Set.eq_singleton_iff_nonempty_unique_mem]
  rw [sSup_eq_bot] at h_sup
  exact ⟨hne, h_sup⟩

/-- Introduction rule to prove that `b` is the supremum of `s`: it suffices to check that `b`
is larger than all elements of `s`, and that this is not the case of any `w < b`.
See `csSup_eq_of_forall_le_of_forall_lt_exists_gt` for a version in conditionally complete
lattices. -/
```

-- snippet 20
```lean
-- Mathlib.Order.CompleteLattice.Basic.Function (L172-L177)
theorem Function.Surjective.iSup_comp {f : ι → ι'} (hf : Surjective f) (g : ι' → α) :
    ⨆ x, g (f x) = ⨆ y, g y := by
simp only [iSup.eq_1]
  congr
  exact hf.range_comp g
```

-- snippet 21
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_insert (L93-L95)
theorem sSup_insert {a : α} {s : Set α} : sSup (insert a s) = a ⊔ sSup s :=
((isLUB_sSup s).insert a).sSup_eq
```

-- snippet 22
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_diff_singleton_bot (L101-L104)
theorem sSup_diff_singleton_bot (s : Set α) : sSup (s \ {⊥}) = sSup s :=
(sSup_le_sSup diff_subset).antisymm <|
    sSup_le_sSup_of_subset_insert_bot <| subset_insert_diff_singleton _ _
```

-- snippet 23
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_eq_of_forall_le_of_forall_lt_exists_gt (L134-L139)
theorem sSup_eq_of_forall_le_of_forall_lt_exists_gt (h₁ : ∀ a ∈ s, a ≤ b)
    (h₂ : ∀ w, w < b → ∃ a ∈ s, w < a) : sSup s = b :=
(sSup_le h₁).eq_of_not_lt fun h =>
    let ⟨_, ha, ha'⟩ := h₂ _ h
    ((le_sSup ha).trans_lt ha').false
```

-- snippet 24
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_univ (L88-L91)
theorem sSup_univ : sSup univ = (⊤ : α) :=
(@isLUB_univ α _ _).sSup_eq

-- TODO(Jeremy): get this automatically
```

-- snippet 25
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_le_sSup_of_isCofinalFor (L53-L56)
theorem sSup_le_sSup_of_isCofinalFor (h : IsCofinalFor s t) : sSup s ≤ sSup t :=
IsLeast.mono (isLUB_sSup t) (isLUB_sSup s) <| upperBounds_mono_of_isCofinalFor h

-- We will generalize this to conditionally complete lattices in `csSup_singleton`.
```

-- snippet 26
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_empty (L84-L86)
theorem sSup_empty : sSup ∅ = (⊥ : α) :=
(@isLUB_empty α _ _).sSup_eq
```

-- snippet 27
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_eq_iSup' (L154-L155)
theorem sSup_eq_iSup' (s : Set α) : sSup s = ⨆ a : s, (a : α) := by rw [iSup, Subtype.range_coe]
```

-- snippet 28
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_range (L150-L152)
theorem sSup_range : sSup (range f) = iSup f :=
rfl
```

-- snippet 29
```lean
-- Mathlib.Order.CompleteLattice.Basic.sInf_le_sSup_of_nonempty_inter (L72-L74)
theorem sInf_le_sSup_of_nonempty_inter (h : (s ∩ t).Nonempty) : sInf s ≤ sSup t :=
isGLB_le_isLUB_of_nonempty_inter h (isGLB_sInf s) (isLUB_sSup t)
```

-- snippet 30
```lean
-- Mathlib.Order.CompleteLattice.Basic.iSup_congr_Prop (L194-L199)
theorem iSup_congr_Prop {p q : Prop} {f₁ : p → α} {f₂ : q → α} (pq : p ↔ q)
    (f : ∀ x, f₁ (pq.mpr x) = f₂ x) : iSup f₁ = iSup f₂ := by
obtain rfl := propext pq
  congr with x
  apply f
```

-- snippet 31
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_eq_bot' (L115-L117)
lemma sSup_eq_bot' {s : Set α} : sSup s = ⊥ ↔ s = ∅ ∨ s = {⊥} := by
rw [sSup_eq_bot, ← subset_singleton_iff_eq, subset_singleton_iff]
```

-- snippet 32
```lean
-- Mathlib.Order.CompleteLattice.Basic.sInf_le_sSup (L69-L71)
theorem sInf_le_sSup (hs : s.Nonempty) : sInf s ≤ sSup s :=
isGLB_le_isLUB (isGLB_sInf s) (isLUB_sSup s) hs
```

-- snippet 33
```lean
-- Mathlib.Order.CompleteLattice.Basic.iSup_plift_up (L201-L203)
theorem iSup_plift_up (f : PLift ι → α) : ⨆ i, f (PLift.up i) = ⨆ i, f i :=
(PLift.up_surjective.iSup_congr _) fun _ => rfl
```

-- snippet 34
```lean
-- Mathlib.Order.CompleteLattice.Basic.Equiv (L179-L181)
theorem Equiv.iSup_comp {g : ι' → α} (e : ι ≃ ι') : ⨆ x, g (e x) = ⨆ y, g y :=
e.surjective.iSup_comp _
```

-- snippet 35
```lean
-- Mathlib.Order.CompleteLattice.Basic.biSup_congr' (L166-L170)
theorem biSup_congr' {p : ι → Prop} {f g : (i : ι) → p i → α}
    (h : ∀ i (hi : p i), f i hi = g i hi) :
    ⨆ i, ⨆ (hi : p i), f i hi = ⨆ i, ⨆ (hi : p i), g i hi := by
grind
```

-- snippet 36
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_eq_bot (L110-L113)
theorem sSup_eq_bot : sSup s = ⊥ ↔ ∀ a ∈ s, a = ⊥ :=
⟨fun h _ ha => bot_unique <| h ▸ le_sSup ha, fun h =>
    bot_unique <| sSup_le fun a ha => le_bot_iff.2 <| h a ha⟩
```

-- snippet 37
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_inter_le (L80-L82)
theorem sSup_inter_le {s t : Set α} : sSup (s ∩ t) ≤ sSup s ⊓ sSup t :=
sSup_le fun _ hb => le_inf (le_sSup hb.1) (le_sSup hb.2)
```

-- snippet 38
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_union (L76-L78)
theorem sSup_union {s t : Set α} : sSup (s ∪ t) = sSup s ⊔ sSup t :=
((isLUB_sSup s).union (isLUB_sSup t)).sSup_eq
```

-- snippet 39
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_singleton (L58-L60)
theorem sSup_singleton {a : α} : sSup {a} = a :=
isLUB_singleton.sSup_eq
```

-- snippet 40
```lean
-- Mathlib.Order.CompleteLattice.Basic.sSup_pair (L106-L108)
theorem sSup_pair {a b : α} : sSup {a, b} = a ⊔ b :=
(@isLUB_pair α _ a b).sSup_eq
```
[/INST]


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.RingTheory.Derivation.Basic).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
theorem leibniz_inv (a : K) : D a⁻¹ = -a⁻¹ ^ 2 • D a
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.RingTheory.Derivation.Basic.toFun_eq_coe (L75-L78)
theorem toFun_eq_coe : D.toFun = ⇑D :=
rfl

/-- See Note [custom simps projection] -/
```

-- snippet 2
```lean
-- Mathlib.RingTheory.Derivation.Basic.Simps (L79-L82)
def Simps.apply (D : Derivation R A M) : A → M := D
initialize_simps_projections Derivation (toFun → apply)
```

-- snippet 3
```lean
-- Mathlib.RingTheory.Derivation.Basic.hasCoeToLinearMap (L85-L87)
instance hasCoeToLinearMap : Coe (Derivation R A M) (A →ₗ[R] M) :=
⟨fun D => D.toLinearMap⟩
```

-- snippet 4
```lean
-- Mathlib.RingTheory.Derivation.Basic.mk_coe (L89-L91)
theorem mk_coe (f : A →ₗ[R] M) (h₁ h₂) : ((⟨f, h₁, h₂⟩ : Derivation R A M) : A → M) = f :=
rfl
```

-- snippet 5
```lean
-- Mathlib.RingTheory.Derivation.Basic.coeFn_coe (L93-L95)
theorem coeFn_coe (f : Derivation R A M) : ⇑(f : A →ₗ[R] M) = f :=
rfl
```

-- snippet 6
```lean
-- Mathlib.RingTheory.Derivation.Basic.coe_injective (L96-L98)
theorem coe_injective : @Function.Injective (Derivation R A M) (A → M) DFunLike.coe :=
DFunLike.coe_injective
```

-- snippet 7
```lean
-- Mathlib.RingTheory.Derivation.Basic.ext (L100-L102)
theorem ext (H : ∀ a, D1 a = D2 a) : D1 = D2 :=
DFunLike.ext _ _ H
```

-- snippet 8
```lean
-- Mathlib.RingTheory.Derivation.Basic.congr_fun (L103-L111)
theorem congr_fun (h : D1 = D2) (a : A) : D1 a = D2 a :=
DFunLike.congr_fun h a

protected theorem map_add : D (a + b) = D a + D b :=
  map_add D a b

protected theorem map_zero : D 0 = 0 :=
  map_zero D
```

-- snippet 9
```lean
-- Mathlib.RingTheory.Derivation.Basic.map_smul (L113-L115)
theorem map_smul : D (r • a) = r • D a :=
D.toLinearMap.map_smul r a
```

-- snippet 10
```lean
-- Mathlib.RingTheory.Derivation.Basic.leibniz (L117-L119)
theorem leibniz : D (a * b) = a • D b + b • D a :=
D.leibniz' _ _
```

-- snippet 11
```lean
-- Mathlib.RingTheory.Derivation.Basic.map_smul_of_tower (L121-L124)
theorem map_smul_of_tower {S : Type*} [SMul S A] [SMul S M] [LinearMap.CompatibleSMul A M S R]
    (D : Derivation R A M) (r : S) (a : A) : D (r • a) = r • D a :=
D.toLinearMap.map_smul_of_tower r a
```

-- snippet 12
```lean
-- Mathlib.RingTheory.Derivation.Basic.map_one_eq_zero (L126-L128)
theorem map_one_eq_zero : D 1 = 0 :=
D.map_one_eq_zero'
```

-- snippet 13
```lean
-- Mathlib.RingTheory.Derivation.Basic.map_algebraMap (L130-L132)
theorem map_algebraMap : D (algebraMap R A r) = 0 := by
rw [← mul_one r, map_mul, map_one, ← smul_def, map_smul, map_one_eq_zero, smul_zero]
```

-- snippet 14
```lean
-- Mathlib.RingTheory.Derivation.Basic.map_natCast (L134-L136)
theorem map_natCast (n : ℕ) : D (n : A) = 0 := by
rw [← nsmul_one, D.map_smul_of_tower n, map_one_eq_zero, smul_zero]
```

-- snippet 15
```lean
-- Mathlib.RingTheory.Derivation.Basic.leibniz_pow (L138-L148)
theorem leibniz_pow (n : ℕ) : D (a ^ n) = n • a ^ (n - 1) • D a := by
induction n with
  | zero => rw [pow_zero, map_one_eq_zero, zero_smul]
  | succ n ihn =>
    rcases (zero_le n).eq_or_lt with (rfl | hpos)
    · simp
    · have : a * a ^ (n - 1) = a ^ n := by rw [← pow_succ', Nat.sub_add_cancel hpos]
      simp only [pow_succ', leibniz, ihn, smul_comm a n (_ : M), smul_smul a, add_smul, this,
        Nat.add_succ_sub_one, add_zero, one_nsmul]

open Polynomial in
```

-- snippet 16
```lean
-- Mathlib.RingTheory.Derivation.Lie.mk (L102-L105)
def mk (x : Derivation R A' A') (y : Derivation R A A)
  (h : x ∘ (Algebra.ofId A A') = (Algebra.ofId A A') ∘ y) : couple R A A' :=
⟨(x, y), (Compatible.mem _).mpr h⟩
```

-- snippet 17
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.mapCoeffs_monomial (L70-L73)
lemma mapCoeffs_monomial (n : ℕ) (x : A) :
    d.mapCoeffs (monomial n x) = .single A n (d x) := Finsupp.ext fun _ ↦ by
simp [coeff_monomial, apply_ite d, PolynomialModule.single_apply]
```

-- snippet 18
```lean
-- Mathlib.RingTheory.Derivation.DifferentialRing.Differential (L80-L87)
def Differential.equiv {R R₂ : Type*} [CommRing R] [CommRing R₂] [Differential R₂]
    (h : R ≃+* R₂) : Differential R :=
⟨Derivation.mk' (h.symm.toAddMonoidHom.toIntLinearMap ∘ₗ
    Differential.deriv.toLinearMap ∘ₗ h.toAddMonoidHom.toIntLinearMap) (by simp)⟩

/--
Transfer a `DifferentialAlgebra` instance across a `AlgEquiv`.
-/
```

-- snippet 19
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.coeff_mapCoeffs (L127-L129)
lemma coeff_mapCoeffs (p : A[X]) (i) :
    coeff (mapCoeffs p) i = (coeff p i)′ := rfl
```

-- snippet 20
```lean
-- Mathlib.RingTheory.Derivation.Lie.mk_right (L109-L111)
lemma mk_right (x : Derivation R A' A') (y : Derivation R A A)
    (h : x ∘ (Algebra.ofId A A') = (Algebra.ofId A A') ∘ y) : (mk x y h).1.2 = y := rfl
```

-- snippet 21
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.mapCoeffs_C (L79-L84)
lemma mapCoeffs_C (x : A) :
    d.mapCoeffs (C x) = .single A 0 (d x) := by simp [← monomial_zero_left]
variable {B M' : Type*} [CommRing B] [Algebra R B] [Algebra A B]
    [AddCommGroup M'] [Module B M'] [Module R M'] [Module A M']
```

-- snippet 22
```lean
-- Mathlib.RingTheory.Derivation.Lie.bracket_eq_fun (L73-L81)
lemma bracket_eq_fun (X : Derivation R A A) (a : A) : ⁅X, a⁆ = X a := rfl
section CompatibleDerivations
variable {A' : Type*} [CommRing A'] [Algebra R A'] [Algebra A A'] [IsScalarTower R A A']

variable (R A A') in
/-- Let `σ : A → A'` be a an homomorphism. A derivation `d : A → A` and a derivation
`d' : A' → A'` are called compatible if `d' ∘ σ = σ ∘ d`. Couples of derivations
with this property form a Lie subalgebra of all couples of derivations. -/
```

-- snippet 23
```lean
-- Mathlib.RingTheory.Derivation.Lie.mem (L95-L101)
lemma mem (x : (Derivation R A' A') × (Derivation R A A)) :
    x ∈ couple R A A' ↔ x.1 ∘ Algebra.ofId A A' = Algebra.ofId A A' ∘ x.2 := by
constructor
  · intro hx; ext a; exact congrArg (· a) hx
  · intro hx; ext a; exact congrArg (· a) hx

/-- Generate an element of `couple` from `x y` satisfying the compatibility equation. -/
```

-- snippet 24
```lean
-- Mathlib.RingTheory.Derivation.Lie.commutator_apply (L48-L50)
theorem commutator_apply : ⁅D1, D2⁆ a = D1 (D2 a) - D2 (D1 a) :=
rfl
```

-- snippet 25
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.mapCoeffs_X (L75-L77)
lemma mapCoeffs_X :
    d.mapCoeffs (X : A[X]) = 0 := by simp [← monomial_one_one_eq_X]
```

-- snippet 26
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.mapCoeffs_apply (L66-L68)
lemma mapCoeffs_apply (p : A[X]) (i) :
    d.mapCoeffs p i = d (coeff p i) := rfl
```

-- snippet 27
```lean
-- Mathlib.RingTheory.Derivation.DifferentialRing.mem_range_of_deriv_eq_zero (L67-L71)
lemma mem_range_of_deriv_eq_zero (A : Type*) {B : Type*} [CommRing A] [CommRing B] [Algebra A B]
    [Differential B] [Differential.ContainConstants A B] {x : B} (h : x′ = 0) :
    x ∈ (algebraMap A B).range :=
Differential.ContainConstants.mem_range_of_deriv_eq_zero h
```

-- snippet 28
```lean
-- Mathlib.RingTheory.Derivation.DifferentialRing.algebraMap (L53-L66)
lemma algebraMap.coe_deriv {A : Type*} {B : Type*} [CommRing A] [CommRing B] [Algebra A B]
    [Differential A] [Differential B] [DifferentialAlgebra A B] (a : A) :
    (a′ : A) = (a : B)′ :=
(DifferentialAlgebra.deriv_algebraMap _).symm

/--
A differential ring `A` and an algebra over it `B` share constants if all
constants in B are in the range of `algebraMap A B`.
-/
class Differential.ContainConstants (A B : Type*) [CommRing A] [CommRing B]
    [Algebra A B] [Differential B] : Prop where
  /-- If the derivative of x is 0, then it's in the range of `algebraMap A B`. -/
  protected mem_range_of_deriv_eq_zero {x : B} (h : x′ = 0) : x ∈ (algebraMap A B).range
```

-- snippet 29
```lean
-- Mathlib.RingTheory.Derivation.DifferentialRing.DifferentialAlgebra (L88-L100)
lemma DifferentialAlgebra.equiv {A : Type*} [CommRing A] [Differential A]
    {R R₂ : Type*} [CommRing R] [CommRing R₂] [Differential R₂] [Algebra A R]
    [Algebra A R₂] [DifferentialAlgebra A R₂] (h : R ≃ₐ[A] R₂) :
    letI := Differential.equiv h.toRingEquiv
DifferentialAlgebra A R :=
  letI := Differential.equiv h.toRingEquiv
  ⟨fun a ↦ by
    change (LinearMap.comp ..) _ = _
    simp only [AlgEquiv.toRingEquiv_eq_coe, RingHom.toAddMonoidHom_eq_coe,
      RingEquiv.toRingHom_eq_coe, AlgEquiv.toRingEquiv_toRingHom, LinearMap.coe_comp,
      AddMonoidHom.coe_toIntLinearMap, AddMonoidHom.coe_coe, RingHom.coe_coe, Derivation.coeFn_coe,
      Function.comp_apply, AlgEquiv.commutes, deriv_algebraMap]
    apply h.symm.commutes⟩
```

-- snippet 30
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.deriv_aeval_eq (L145-L154)
theorem deriv_aeval_eq (x : R) (p : A[X]) :
    (aeval x p)′ = aeval x (mapCoeffs p) + aeval x (derivative p) * x′ := by
convert Derivation.apply_aeval_eq' Differential.deriv _ (Algebra.linearMap A R) ..
  · simp [mapCoeffs]
  · simp [deriv_algebraMap]

/--
The unique derivation which can be made to a `DifferentialAlgebra` on `A[X]` with
`X′ = v`.
-/
```

-- snippet 31
```lean
-- Mathlib.RingTheory.Derivation.Lie.mk_left (L106-L108)
lemma mk_left (x : Derivation R A' A') (y : Derivation R A A)
    (h : x ∘ (Algebra.ofId A A') = (Algebra.ofId A A') ∘ y) : (mk x y h).1.1 = x := rfl
```

-- snippet 32
```lean
-- Mathlib.RingTheory.Derivation.Lie.apply (L112-L122)
lemma apply (x : couple R A A') (a : A) :
    x.1.1 (Algebra.ofId A A' a) = (Algebra.ofId A A')  (x.1.2 a) := by
exact congrArg (· a) x.2

end Compatible

end CompatibleDerivations

end LieStructures

end Derivation
```

-- snippet 33
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.apply_eval_eq (L109-L122)
theorem apply_eval_eq (x : A) (p : A[X]) :
    d (eval x p) = PolynomialModule.eval x (d.mapCoeffs p) + eval x (derivative p) • d x :=
apply_aeval_eq d x p

end Derivation

namespace Differential

variable {A : Type*} [CommRing A] [Differential A]

set_option backward.isDefEq.respectTransparency false in
/--
A specialization of `Derivation.mapCoeffs` for the case of a differential ring.
-/
```

-- snippet 34
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.apply_aeval_eq' (L85-L97)
theorem apply_aeval_eq' (d' : Derivation R B M') (f : M →ₗ[A] M')
    (h : ∀ a, f (d a) = d' (algebraMap A B a)) (x : B) (p : A[X]) :
    d' (aeval x p) = PolynomialModule.eval x (PolynomialModule.map B f (d.mapCoeffs p)) +
      aeval x (derivative p) • d' x := by
induction p using Polynomial.induction_on' with
  | add => simp_all only [map_add, add_smul]; abel
  | monomial =>
    simp only [aeval_monomial, leibniz, leibniz_pow, mapCoeffs_monomial,
      PolynomialModule.map_single, PolynomialModule.eval_single, derivative_monomial, map_mul,
      _root_.map_natCast, h]
    rw [add_comm, ← smul_smul, ← smul_smul, Nat.cast_smul_eq_nsmul]
```

-- snippet 35
```lean
-- Mathlib.RingTheory.Derivation.Lie.commutator_coe_linear_map (L45-L47)
theorem commutator_coe_linear_map : ↑⁅D1, D2⁆ = ⁅(D1 : Module.End R A), (D2 : Module.End R A)⁆ :=
rfl
```

-- snippet 36
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.apply_aeval_eq (L98-L108)
theorem apply_aeval_eq [IsScalarTower R A B] [IsScalarTower A B M'] (d : Derivation R B M')
    (x : B) (p : A[X]) :
    d (aeval x p) = PolynomialModule.eval x ((d.compAlgebraMap A).mapCoeffs p) +
      aeval x (derivative p) • d x := by
convert apply_aeval_eq' (d.compAlgebraMap A) d LinearMap.id _ x p
  · apply Finsupp.ext
    intro x
    rfl
  · intro a
    rfl
```

-- snippet 37
```lean
-- Mathlib.RingTheory.Derivation.Lie.instLieAlgebra (L57-L61)
instance instLieAlgebra : LieAlgebra R (Derivation R A A) :=
{ Derivation.instModule with
    lie_smul := fun r d e => by
      ext a; simp only [commutator_apply, map_smul, smul_sub, smul_apply] }
```

-- snippet 38
```lean
-- Mathlib.RingTheory.Derivation.Lie.couple (L82-L94)
def couple : LieSubalgebra R  (Derivation R A' A' × Derivation R A A) where
  carrier := { x | x.fst.compAlgebraMapL R A A' A' = (Algebra.ofId A A').toLinearMap.compDer x.snd }
add_mem' := by simp_all
  zero_mem' := by simp
  smul_mem' := by simp_all
  lie_mem' {x y} hx hy := by
    have hxx (a : A) := congrArg (fun f => f a) hx
    have hyy (a : A) := congrArg (fun f => f a) hy
    ext z
    simp at hxx hyy
    simp [Derivation.commutator_apply, hxx, hyy]

namespace Compatible
```

-- snippet 39
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.mapCoeffs (L38-L64)
def mapCoeffs : Derivation R A[X] (PolynomialModule A M) where
  __ := (PolynomialModule.map A d.toLinearMap).comp
PolynomialModule.equivPolynomial.symm.toLinearMap
  map_one_eq_zero' := show (Finsupp.single 0 1).mapRange (d : A → M) d.map_zero = 0 by simp
  leibniz' p q := by
    dsimp
    induction p using Polynomial.induction_on' with
    | add => simp only [add_mul, map_add, add_smul, smul_add, add_add_add_comm, *]
    | monomial n a =>
      induction q using Polynomial.induction_on' with
      | add => simp only [mul_add, map_add, add_smul, smul_add, add_add_add_comm, *]
      | monomial m b =>
        refine Finsupp.ext fun i ↦ ?_
        dsimp [PolynomialModule.equivPolynomial, PolynomialModule.map]
        simp only [toFinsupp_mul, toFinsupp_monomial, AddMonoidAlgebra.single_mul_single]
        change d _ = _ + _
        -- TODO: copy more `Finsupp` API to `PolynomialModule`.
        -- We have to do a bit of work to go through the identification
        -- `PolynomialModule A M = ℕ →₀ M`...
        dsimp only [PolynomialModule, Finsupp.mapRange.linearMap_apply, coeFn_coe]
        rw [Finsupp.mapRange_single, Finsupp.mapRange_single]
        -- ... and here we go back through the identification.
        change _ = (_ • PolynomialModule.single A _ _) _ + (_ • PolynomialModule.single A _ _) i
        simp only [PolynomialModule.monomial_smul_single, AddMonoidAlgebra.single_apply,
          apply_ite d, leibniz, map_zero, PolynomialModule.single_apply, ite_add_zero,
          add_comm m n]
```

-- snippet 40
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.implicitDeriv (L155-L158)
def implicitDeriv (v : A[X]) :
    Derivation ℤ A[X] A[X] :=
mapCoeffs + v • derivative'.restrictScalars ℤ
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.RingTheory.Derivation.Basic).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
theorem leibniz_inv (a : K) : D a⁻¹ = -a⁻¹ ^ 2 • D a
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.RingTheory.Derivation.Basic.toFun_eq_coe (L75-L78)
theorem toFun_eq_coe : D.toFun = ⇑D :=
rfl

/-- See Note [custom simps projection] -/
```

-- snippet 2
```lean
-- Mathlib.RingTheory.Derivation.Basic.Simps (L79-L82)
def Simps.apply (D : Derivation R A M) : A → M := D
initialize_simps_projections Derivation (toFun → apply)
```

-- snippet 3
```lean
-- Mathlib.RingTheory.Derivation.Basic.hasCoeToLinearMap (L85-L87)
instance hasCoeToLinearMap : Coe (Derivation R A M) (A →ₗ[R] M) :=
⟨fun D => D.toLinearMap⟩
```

-- snippet 4
```lean
-- Mathlib.RingTheory.Derivation.Basic.mk_coe (L89-L91)
theorem mk_coe (f : A →ₗ[R] M) (h₁ h₂) : ((⟨f, h₁, h₂⟩ : Derivation R A M) : A → M) = f :=
rfl
```

-- snippet 5
```lean
-- Mathlib.RingTheory.Derivation.Basic.coeFn_coe (L93-L95)
theorem coeFn_coe (f : Derivation R A M) : ⇑(f : A →ₗ[R] M) = f :=
rfl
```

-- snippet 6
```lean
-- Mathlib.RingTheory.Derivation.Basic.coe_injective (L96-L98)
theorem coe_injective : @Function.Injective (Derivation R A M) (A → M) DFunLike.coe :=
DFunLike.coe_injective
```

-- snippet 7
```lean
-- Mathlib.RingTheory.Derivation.Basic.ext (L100-L102)
theorem ext (H : ∀ a, D1 a = D2 a) : D1 = D2 :=
DFunLike.ext _ _ H
```

-- snippet 8
```lean
-- Mathlib.RingTheory.Derivation.Basic.congr_fun (L103-L111)
theorem congr_fun (h : D1 = D2) (a : A) : D1 a = D2 a :=
DFunLike.congr_fun h a

protected theorem map_add : D (a + b) = D a + D b :=
  map_add D a b

protected theorem map_zero : D 0 = 0 :=
  map_zero D
```

-- snippet 9
```lean
-- Mathlib.RingTheory.Derivation.Basic.map_smul (L113-L115)
theorem map_smul : D (r • a) = r • D a :=
D.toLinearMap.map_smul r a
```

-- snippet 10
```lean
-- Mathlib.RingTheory.Derivation.Basic.leibniz (L117-L119)
theorem leibniz : D (a * b) = a • D b + b • D a :=
D.leibniz' _ _
```

-- snippet 11
```lean
-- Mathlib.RingTheory.Derivation.Basic.map_smul_of_tower (L121-L124)
theorem map_smul_of_tower {S : Type*} [SMul S A] [SMul S M] [LinearMap.CompatibleSMul A M S R]
    (D : Derivation R A M) (r : S) (a : A) : D (r • a) = r • D a :=
D.toLinearMap.map_smul_of_tower r a
```

-- snippet 12
```lean
-- Mathlib.RingTheory.Derivation.Basic.map_one_eq_zero (L126-L128)
theorem map_one_eq_zero : D 1 = 0 :=
D.map_one_eq_zero'
```

-- snippet 13
```lean
-- Mathlib.RingTheory.Derivation.Basic.map_algebraMap (L130-L132)
theorem map_algebraMap : D (algebraMap R A r) = 0 := by
rw [← mul_one r, map_mul, map_one, ← smul_def, map_smul, map_one_eq_zero, smul_zero]
```

-- snippet 14
```lean
-- Mathlib.RingTheory.Derivation.Basic.map_natCast (L134-L136)
theorem map_natCast (n : ℕ) : D (n : A) = 0 := by
rw [← nsmul_one, D.map_smul_of_tower n, map_one_eq_zero, smul_zero]
```

-- snippet 15
```lean
-- Mathlib.RingTheory.Derivation.Basic.leibniz_pow (L138-L148)
theorem leibniz_pow (n : ℕ) : D (a ^ n) = n • a ^ (n - 1) • D a := by
induction n with
  | zero => rw [pow_zero, map_one_eq_zero, zero_smul]
  | succ n ihn =>
    rcases (zero_le n).eq_or_lt with (rfl | hpos)
    · simp
    · have : a * a ^ (n - 1) = a ^ n := by rw [← pow_succ', Nat.sub_add_cancel hpos]
      simp only [pow_succ', leibniz, ihn, smul_comm a n (_ : M), smul_smul a, add_smul, this,
        Nat.add_succ_sub_one, add_zero, one_nsmul]

open Polynomial in
```

-- snippet 16
```lean
-- Mathlib.RingTheory.Derivation.Lie.mk (L102-L105)
def mk (x : Derivation R A' A') (y : Derivation R A A)
  (h : x ∘ (Algebra.ofId A A') = (Algebra.ofId A A') ∘ y) : couple R A A' :=
⟨(x, y), (Compatible.mem _).mpr h⟩
```

-- snippet 17
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.mapCoeffs_monomial (L70-L73)
lemma mapCoeffs_monomial (n : ℕ) (x : A) :
    d.mapCoeffs (monomial n x) = .single A n (d x) := Finsupp.ext fun _ ↦ by
simp [coeff_monomial, apply_ite d, PolynomialModule.single_apply]
```

-- snippet 18
```lean
-- Mathlib.RingTheory.Derivation.DifferentialRing.Differential (L80-L87)
def Differential.equiv {R R₂ : Type*} [CommRing R] [CommRing R₂] [Differential R₂]
    (h : R ≃+* R₂) : Differential R :=
⟨Derivation.mk' (h.symm.toAddMonoidHom.toIntLinearMap ∘ₗ
    Differential.deriv.toLinearMap ∘ₗ h.toAddMonoidHom.toIntLinearMap) (by simp)⟩

/--
Transfer a `DifferentialAlgebra` instance across a `AlgEquiv`.
-/
```

-- snippet 19
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.coeff_mapCoeffs (L127-L129)
lemma coeff_mapCoeffs (p : A[X]) (i) :
    coeff (mapCoeffs p) i = (coeff p i)′ := rfl
```

-- snippet 20
```lean
-- Mathlib.RingTheory.Derivation.Lie.mk_right (L109-L111)
lemma mk_right (x : Derivation R A' A') (y : Derivation R A A)
    (h : x ∘ (Algebra.ofId A A') = (Algebra.ofId A A') ∘ y) : (mk x y h).1.2 = y := rfl
```

-- snippet 21
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.mapCoeffs_C (L79-L84)
lemma mapCoeffs_C (x : A) :
    d.mapCoeffs (C x) = .single A 0 (d x) := by simp [← monomial_zero_left]
variable {B M' : Type*} [CommRing B] [Algebra R B] [Algebra A B]
    [AddCommGroup M'] [Module B M'] [Module R M'] [Module A M']
```

-- snippet 22
```lean
-- Mathlib.RingTheory.Derivation.Lie.bracket_eq_fun (L73-L81)
lemma bracket_eq_fun (X : Derivation R A A) (a : A) : ⁅X, a⁆ = X a := rfl
section CompatibleDerivations
variable {A' : Type*} [CommRing A'] [Algebra R A'] [Algebra A A'] [IsScalarTower R A A']

variable (R A A') in
/-- Let `σ : A → A'` be a an homomorphism. A derivation `d : A → A` and a derivation
`d' : A' → A'` are called compatible if `d' ∘ σ = σ ∘ d`. Couples of derivations
with this property form a Lie subalgebra of all couples of derivations. -/
```

-- snippet 23
```lean
-- Mathlib.RingTheory.Derivation.Lie.mem (L95-L101)
lemma mem (x : (Derivation R A' A') × (Derivation R A A)) :
    x ∈ couple R A A' ↔ x.1 ∘ Algebra.ofId A A' = Algebra.ofId A A' ∘ x.2 := by
constructor
  · intro hx; ext a; exact congrArg (· a) hx
  · intro hx; ext a; exact congrArg (· a) hx

/-- Generate an element of `couple` from `x y` satisfying the compatibility equation. -/
```

-- snippet 24
```lean
-- Mathlib.RingTheory.Derivation.Lie.commutator_apply (L48-L50)
theorem commutator_apply : ⁅D1, D2⁆ a = D1 (D2 a) - D2 (D1 a) :=
rfl
```

-- snippet 25
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.mapCoeffs_X (L75-L77)
lemma mapCoeffs_X :
    d.mapCoeffs (X : A[X]) = 0 := by simp [← monomial_one_one_eq_X]
```

-- snippet 26
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.mapCoeffs_apply (L66-L68)
lemma mapCoeffs_apply (p : A[X]) (i) :
    d.mapCoeffs p i = d (coeff p i) := rfl
```

-- snippet 27
```lean
-- Mathlib.RingTheory.Derivation.DifferentialRing.mem_range_of_deriv_eq_zero (L67-L71)
lemma mem_range_of_deriv_eq_zero (A : Type*) {B : Type*} [CommRing A] [CommRing B] [Algebra A B]
    [Differential B] [Differential.ContainConstants A B] {x : B} (h : x′ = 0) :
    x ∈ (algebraMap A B).range :=
Differential.ContainConstants.mem_range_of_deriv_eq_zero h
```

-- snippet 28
```lean
-- Mathlib.RingTheory.Derivation.DifferentialRing.algebraMap (L53-L66)
lemma algebraMap.coe_deriv {A : Type*} {B : Type*} [CommRing A] [CommRing B] [Algebra A B]
    [Differential A] [Differential B] [DifferentialAlgebra A B] (a : A) :
    (a′ : A) = (a : B)′ :=
(DifferentialAlgebra.deriv_algebraMap _).symm

/--
A differential ring `A` and an algebra over it `B` share constants if all
constants in B are in the range of `algebraMap A B`.
-/
class Differential.ContainConstants (A B : Type*) [CommRing A] [CommRing B]
    [Algebra A B] [Differential B] : Prop where
  /-- If the derivative of x is 0, then it's in the range of `algebraMap A B`. -/
  protected mem_range_of_deriv_eq_zero {x : B} (h : x′ = 0) : x ∈ (algebraMap A B).range
```

-- snippet 29
```lean
-- Mathlib.RingTheory.Derivation.DifferentialRing.DifferentialAlgebra (L88-L100)
lemma DifferentialAlgebra.equiv {A : Type*} [CommRing A] [Differential A]
    {R R₂ : Type*} [CommRing R] [CommRing R₂] [Differential R₂] [Algebra A R]
    [Algebra A R₂] [DifferentialAlgebra A R₂] (h : R ≃ₐ[A] R₂) :
    letI := Differential.equiv h.toRingEquiv
DifferentialAlgebra A R :=
  letI := Differential.equiv h.toRingEquiv
  ⟨fun a ↦ by
    change (LinearMap.comp ..) _ = _
    simp only [AlgEquiv.toRingEquiv_eq_coe, RingHom.toAddMonoidHom_eq_coe,
      RingEquiv.toRingHom_eq_coe, AlgEquiv.toRingEquiv_toRingHom, LinearMap.coe_comp,
      AddMonoidHom.coe_toIntLinearMap, AddMonoidHom.coe_coe, RingHom.coe_coe, Derivation.coeFn_coe,
      Function.comp_apply, AlgEquiv.commutes, deriv_algebraMap]
    apply h.symm.commutes⟩
```

-- snippet 30
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.deriv_aeval_eq (L145-L154)
theorem deriv_aeval_eq (x : R) (p : A[X]) :
    (aeval x p)′ = aeval x (mapCoeffs p) + aeval x (derivative p) * x′ := by
convert Derivation.apply_aeval_eq' Differential.deriv _ (Algebra.linearMap A R) ..
  · simp [mapCoeffs]
  · simp [deriv_algebraMap]

/--
The unique derivation which can be made to a `DifferentialAlgebra` on `A[X]` with
`X′ = v`.
-/
```

-- snippet 31
```lean
-- Mathlib.RingTheory.Derivation.Lie.mk_left (L106-L108)
lemma mk_left (x : Derivation R A' A') (y : Derivation R A A)
    (h : x ∘ (Algebra.ofId A A') = (Algebra.ofId A A') ∘ y) : (mk x y h).1.1 = x := rfl
```

-- snippet 32
```lean
-- Mathlib.RingTheory.Derivation.Lie.apply (L112-L122)
lemma apply (x : couple R A A') (a : A) :
    x.1.1 (Algebra.ofId A A' a) = (Algebra.ofId A A')  (x.1.2 a) := by
exact congrArg (· a) x.2

end Compatible

end CompatibleDerivations

end LieStructures

end Derivation
```

-- snippet 33
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.apply_eval_eq (L109-L122)
theorem apply_eval_eq (x : A) (p : A[X]) :
    d (eval x p) = PolynomialModule.eval x (d.mapCoeffs p) + eval x (derivative p) • d x :=
apply_aeval_eq d x p

end Derivation

namespace Differential

variable {A : Type*} [CommRing A] [Differential A]

set_option backward.isDefEq.respectTransparency false in
/--
A specialization of `Derivation.mapCoeffs` for the case of a differential ring.
-/
```

-- snippet 34
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.apply_aeval_eq' (L85-L97)
theorem apply_aeval_eq' (d' : Derivation R B M') (f : M →ₗ[A] M')
    (h : ∀ a, f (d a) = d' (algebraMap A B a)) (x : B) (p : A[X]) :
    d' (aeval x p) = PolynomialModule.eval x (PolynomialModule.map B f (d.mapCoeffs p)) +
      aeval x (derivative p) • d' x := by
induction p using Polynomial.induction_on' with
  | add => simp_all only [map_add, add_smul]; abel
  | monomial =>
    simp only [aeval_monomial, leibniz, leibniz_pow, mapCoeffs_monomial,
      PolynomialModule.map_single, PolynomialModule.eval_single, derivative_monomial, map_mul,
      _root_.map_natCast, h]
    rw [add_comm, ← smul_smul, ← smul_smul, Nat.cast_smul_eq_nsmul]
```

-- snippet 35
```lean
-- Mathlib.RingTheory.Derivation.Lie.commutator_coe_linear_map (L45-L47)
theorem commutator_coe_linear_map : ↑⁅D1, D2⁆ = ⁅(D1 : Module.End R A), (D2 : Module.End R A)⁆ :=
rfl
```

-- snippet 36
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.apply_aeval_eq (L98-L108)
theorem apply_aeval_eq [IsScalarTower R A B] [IsScalarTower A B M'] (d : Derivation R B M')
    (x : B) (p : A[X]) :
    d (aeval x p) = PolynomialModule.eval x ((d.compAlgebraMap A).mapCoeffs p) +
      aeval x (derivative p) • d x := by
convert apply_aeval_eq' (d.compAlgebraMap A) d LinearMap.id _ x p
  · apply Finsupp.ext
    intro x
    rfl
  · intro a
    rfl
```

-- snippet 37
```lean
-- Mathlib.RingTheory.Derivation.Lie.instLieAlgebra (L57-L61)
instance instLieAlgebra : LieAlgebra R (Derivation R A A) :=
{ Derivation.instModule with
    lie_smul := fun r d e => by
      ext a; simp only [commutator_apply, map_smul, smul_sub, smul_apply] }
```

-- snippet 38
```lean
-- Mathlib.RingTheory.Derivation.Lie.couple (L82-L94)
def couple : LieSubalgebra R  (Derivation R A' A' × Derivation R A A) where
  carrier := { x | x.fst.compAlgebraMapL R A A' A' = (Algebra.ofId A A').toLinearMap.compDer x.snd }
add_mem' := by simp_all
  zero_mem' := by simp
  smul_mem' := by simp_all
  lie_mem' {x y} hx hy := by
    have hxx (a : A) := congrArg (fun f => f a) hx
    have hyy (a : A) := congrArg (fun f => f a) hy
    ext z
    simp at hxx hyy
    simp [Derivation.commutator_apply, hxx, hyy]

namespace Compatible
```

-- snippet 39
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.mapCoeffs (L38-L64)
def mapCoeffs : Derivation R A[X] (PolynomialModule A M) where
  __ := (PolynomialModule.map A d.toLinearMap).comp
PolynomialModule.equivPolynomial.symm.toLinearMap
  map_one_eq_zero' := show (Finsupp.single 0 1).mapRange (d : A → M) d.map_zero = 0 by simp
  leibniz' p q := by
    dsimp
    induction p using Polynomial.induction_on' with
    | add => simp only [add_mul, map_add, add_smul, smul_add, add_add_add_comm, *]
    | monomial n a =>
      induction q using Polynomial.induction_on' with
      | add => simp only [mul_add, map_add, add_smul, smul_add, add_add_add_comm, *]
      | monomial m b =>
        refine Finsupp.ext fun i ↦ ?_
        dsimp [PolynomialModule.equivPolynomial, PolynomialModule.map]
        simp only [toFinsupp_mul, toFinsupp_monomial, AddMonoidAlgebra.single_mul_single]
        change d _ = _ + _
        -- TODO: copy more `Finsupp` API to `PolynomialModule`.
        -- We have to do a bit of work to go through the identification
        -- `PolynomialModule A M = ℕ →₀ M`...
        dsimp only [PolynomialModule, Finsupp.mapRange.linearMap_apply, coeFn_coe]
        rw [Finsupp.mapRange_single, Finsupp.mapRange_single]
        -- ... and here we go back through the identification.
        change _ = (_ • PolynomialModule.single A _ _) _ + (_ • PolynomialModule.single A _ _) i
        simp only [PolynomialModule.monomial_smul_single, AddMonoidAlgebra.single_apply,
          apply_ite d, leibniz, map_zero, PolynomialModule.single_apply, ite_add_zero,
          add_comm m n]
```

-- snippet 40
```lean
-- Mathlib.RingTheory.Derivation.MapCoeffs.implicitDeriv (L155-L158)
def implicitDeriv (v : A[X]) :
    Derivation ℤ A[X] A[X] :=
mapCoeffs + v • derivative'.restrictScalars ℤ
```
[/INST]