[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.Matrix.ConjTranspose).

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

```lean
theorem vecMul_conjTranspose [Fintype n] [StarRing α] (A : Matrix m n α) (x : n → α) :
    x ᵥ* Aᴴ = star (A *ᵥ star x)
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose (L41-L43)
def conjTranspose [Star α] (M : Matrix m n α) : Matrix n m α :=
M.transpose.map star
```

-- snippet 2
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose_single (L48-L57)
lemma conjTranspose_single [DecidableEq n] [DecidableEq m] [AddMonoid α]
    [StarAddMonoid α] (i : m) (j : n) (a : α) :
    (single i j a)ᴴ = single j i (star a) := by
change (single i j a).transpose.map starAddEquiv = single j i (star a)
  simp

section Diagonal

variable [DecidableEq n]
```

-- snippet 3
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.diagonal_conjTranspose (L59-L67)
theorem diagonal_conjTranspose [AddMonoid α] [StarAddMonoid α] (v : n → α) :
    (diagonal v)ᴴ = diagonal (star v) := by
rw [conjTranspose, diagonal_transpose, diagonal_map (star_zero _)]
  rfl

end Diagonal

section Diag
```

-- snippet 4
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.diag_conjTranspose (L69-L82)
theorem diag_conjTranspose [Star α] (A : Matrix n n α) :
    diag Aᴴ = star (diag A) :=
rfl

end Diag

section DotProduct

variable [Fintype m] [Fintype n]

section StarRing

variable [NonUnitalSemiring α] [StarRing α] (v w : m → α)
```

-- snippet 5
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.star_dotProduct_star (L83-L84)
theorem star_dotProduct_star : star v ⬝ᵥ star w = star (w ⬝ᵥ v) := by simp [dotProduct]
```

-- snippet 6
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.star_dotProduct (L85-L86)
theorem star_dotProduct : star v ⬝ᵥ w = star (star w ⬝ᵥ v) := by simp [dotProduct]
```

-- snippet 7
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.dotProduct_star (L87-L96)
theorem dotProduct_star : v ⬝ᵥ star w = star (w ⬝ᵥ star v) := by simp [dotProduct]
end StarRing

end DotProduct

section NonUnitalSemiring

variable [NonUnitalSemiring α]
```

-- snippet 8
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.star_mulVec (L97-L100)
theorem star_mulVec [Fintype n] [StarRing α] (M : Matrix m n α) (v : n → α) :
    star (M *ᵥ v) = star v ᵥ* Mᴴ :=
funext fun _ => (star_dotProduct_star _ _).symm
```

-- snippet 9
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.star_vecMul (L101-L104)
theorem star_vecMul [Fintype m] [StarRing α] (M : Matrix m n α) (v : m → α) :
    star (v ᵥ* M) = Mᴴ *ᵥ star v :=
funext fun _ => (star_dotProduct_star _ _).symm
```

-- snippet 10
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.mulVec_conjTranspose (L105-L108)
theorem mulVec_conjTranspose [Fintype m] [StarRing α] (A : Matrix m n α) (x : m → α) :
    Aᴴ *ᵥ x = star (star x ᵥ* A) :=
funext fun _ => star_dotProduct _ _
```

-- snippet 11
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose_vecMulVec (L116-L127)
theorem conjTranspose_vecMulVec [Mul α] [StarMul α] (w : m → α) (v : n → α) :
    (vecMulVec w v)ᴴ = vecMulVec (star v) (star w) :=
ext fun _ _ => star_mul _ _

section ConjTranspose

open Matrix

/-- Tell `simp` what the entries are in a conjugate transposed matrix.

  Compare with `mul_apply`, `diagonal_apply_eq`, etc.
-/
```

-- snippet 12
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose_apply (L129-L132)
theorem conjTranspose_apply [Star α] (M : Matrix m n α) (i j) :
    M.conjTranspose j i = star (M i j) :=
rfl
```

-- snippet 13
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose_conjTranspose (L134-L137)
theorem conjTranspose_conjTranspose [InvolutiveStar α] (M : Matrix m n α) : Mᴴᴴ = M :=
Matrix.ext <| by simp

variable (n α) in
```

-- snippet 14
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose_involutive (L138-L141)
theorem conjTranspose_involutive [InvolutiveStar α] :
    (conjTranspose : Matrix n n α → Matrix n n α).Involutive :=
conjTranspose_conjTranspose
```

-- snippet 15
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose_transpose (L142-L145)
theorem conjTranspose_transpose [Star α] (M : Matrix m n α) :
    Mᴴᵀ = M.map star :=
rfl
```

-- snippet 16
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.adjugate_def (L191-L193)
theorem adjugate_def (A : Matrix n n α) : adjugate A = of fun i => cramer Aᵀ (Pi.single i 1) :=
rfl
```

-- snippet 17
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_zero (L136-L142)
theorem cramer_zero [Nontrivial n] : cramer (0 : Matrix n n α) = 0 := by
ext i j
  obtain ⟨j', hj'⟩ : ∃ j', j' ≠ j := exists_ne j
  apply det_eq_zero_of_column_eq_zero j'
  simp [updateCol_ne hj']

/-- Use linearity of `cramer` to take it out of a summation. -/
```

-- snippet 18
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.sum_cramer (L143-L147)
theorem sum_cramer {β} (s : Finset β) (f : β → n → α) :
    (∑ x ∈ s, cramer A (f x)) = cramer A (∑ x ∈ s, f x) :=
(map_sum (cramer A) ..).symm

/-- Use linearity of `cramer` and vector evaluation to take `cramer A _ i` out of a summation. -/
```

-- snippet 19
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_subsingleton_apply (L133-L135)
theorem cramer_subsingleton_apply [Subsingleton n] (A : Matrix n n α) (b : n → α) (i : n) :
    cramer A b i = b i := by rw [cramer_apply, det_eq_elem_of_subsingleton _ i, updateCol_self]
```

-- snippet 20
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.IsSymm (L227-L229)
theorem IsSymm.adjugate {A : Matrix n n α} (hA : A.IsSymm) : A.adjugate.IsSymm := by
rw [IsSymm, Matrix.adjugate_transpose, hA.eq]
```

-- snippet 21
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_transpose_row_self (L103-L114)
theorem cramer_transpose_row_self (i : n) : Aᵀ.cramer (A i) = Pi.single i A.det := by
ext j
  rw [cramer_apply, Pi.single_apply]
  split_ifs with h
  · -- i = j: this entry should be `A.det`
    subst h
    simp only [updateCol_transpose, det_transpose, updateRow_eq_self]
  · -- i ≠ j: this entry should be 0
    rw [updateCol_transpose, det_transpose]
    apply det_zero_of_row_eq h
    rw [updateRow_self, updateRow_ne (Ne.symm h)]
```

-- snippet 22
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramerMap (L76-L78)
def cramerMap (i : n) : α :=
(A.updateCol i b).det
```

-- snippet 23
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_transpose_apply (L100-L102)
theorem cramer_transpose_apply (i : n) : cramer Aᵀ b i = (A.updateRow i b).det := by
rw [cramer_apply, updateCol_transpose, det_transpose]
```

-- snippet 24
```lean
-- Mathlib.LinearAlgebra.Matrix.AbsoluteValue.det_sum_le (L52-L61)
theorem det_sum_le {ι : Type*} (s : Finset ι) {A : ι → Matrix n n R} {abv : AbsoluteValue R S}
    {x : S} (hx : ∀ k i j, abv (A k i j) ≤ x) :
    abv (det (∑ k ∈ s, A k)) ≤ (Fintype.card n)! • (#s • x) ^ Fintype.card n :=
det_le fun i j =>
    calc
      abv ((∑ k ∈ s, A k) i j) = abv (∑ k ∈ s, A k i j) := by simp only [sum_apply]
      _ ≤ ∑ k ∈ s, abv (A k i j) := abv.sum_le _ _
      _ ≤ ∑ _k ∈ s, x := by gcongr; apply hx
      _ = #s • x := sum_const _
```

-- snippet 25
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.adjugate_submatrix_equiv_self (L231-L238)
theorem adjugate_submatrix_equiv_self (e : n ≃ m) (A : Matrix m m α) :
    adjugate (A.submatrix e e) = (adjugate A).submatrix e e := by
ext i j
  have : (fun j ↦ Pi.single i 1 <| e.symm j) = Pi.single (e i) 1 :=
    Function.update_comp_equiv (0 : n → α) e.symm i 1
  rw [adjugate_apply, submatrix_apply, adjugate_apply, ← det_submatrix_equiv_self e,
    updateRow_submatrix_equiv, this]
```

-- snippet 26
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramerMap_is_linear (L79-L82)
theorem cramerMap_is_linear (i : n) : IsLinearMap α fun b => cramerMap A b i :=
{ map_add := det_updateCol_add _ _
    map_smul := det_updateCol_smul _ _ }
```

-- snippet 27
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_row_self (L115-L119)
theorem cramer_row_self (i : n) (h : ∀ j, b j = A j i) : A.cramer b = Pi.single i A.det := by
rw [← transpose_transpose A, det_transpose]
  convert cramer_transpose_row_self Aᵀ i
  exact funext h
```

-- snippet 28
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.adjugate (L188-L190)
def adjugate (A : Matrix n n α) : Matrix n n α :=
of fun i => cramer Aᵀ (Pi.single i 1)
```

-- snippet 29
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer (L94-L96)
def cramer (A : Matrix n n α) : (n → α) →ₗ[α] (n → α) :=
IsLinearMap.mk' (cramerMap A) (cramer_is_linear A)
```

-- snippet 30
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_reindex (L164-L187)
theorem cramer_reindex (e : m ≃ n) (A : Matrix m m α) (b : n → α) :
    cramer (reindex e e A) b = cramer A (b ∘ e) ∘ e.symm :=
cramer_submatrix_equiv _ _ _

end Cramer

section Adjugate

/-!
### `adjugate` section

Define the `adjugate` matrix and a few equations.
These will hold for any matrix over a commutative ring.
-/

/-- The adjugate matrix is the transpose of the cofactor matrix.

  Typically, the cofactor matrix is defined by taking minors,
  i.e. the determinant of the matrix with a row and column removed.
  However, the proof of `mul_adjugate` becomes a lot easier if we use the
  matrix replacing a column with a basis vector, since it allows us to use
  facts about the `cramer` map.
-/
```

-- snippet 31
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_is_linear (L83-L93)
theorem cramer_is_linear : IsLinearMap α (cramerMap A) := by
constructor <;> intros <;> ext i
  · apply (cramerMap_is_linear A i).1
  · apply (cramerMap_is_linear A i).2

/-- `cramer A b i` is the determinant of the matrix `A` with column `i` replaced with `b`,
  and thus `cramer A b` is the vector output by Cramer's rule on `A` and `b`.

  If `A * x = b` has a unique solution in `x`, `cramer A` sends the vector `b` to `A.det • x`.
  Otherwise, the outcome of `cramer` is well-defined but not necessarily useful.
-/
```

-- snippet 32
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_one (L121-L127)
theorem cramer_one : cramer (1 : Matrix n n α) = 1 := by
ext i j
  convert congr_fun (cramer_row_self (1 : Matrix n n α) (Pi.single i 1) i _) j
  · simp
  · intro j
    rw [Matrix.one_eq_pi_single, Pi.single_comm]
```

-- snippet 33
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_submatrix_equiv (L158-L163)
theorem cramer_submatrix_equiv (A : Matrix m m α) (e : n ≃ m) (b : n → α) :
    cramer (A.submatrix e e) b = cramer A (b ∘ e.symm) ∘ e := by
ext i
  simp_rw [Function.comp_apply, cramer_apply, updateCol_submatrix_equiv,
    det_submatrix_equiv_self e, Function.comp_def]
```

-- snippet 34
```lean
-- Mathlib.LinearAlgebra.Matrix.AbsoluteValue.det_le (L42-L51)
theorem det_le {A : Matrix n n R} {abv : AbsoluteValue R S} {x : S} (hx : ∀ i j, abv (A i j) ≤ x) :
    abv A.det ≤ (Fintype.card n)! • x ^ Fintype.card n :=
calc
    abv A.det = abv (∑ σ : Perm n, Perm.sign σ • ∏ i, A (σ i) i) := congr_arg abv (det_apply _)
    _ ≤ ∑ σ : Perm n, abv (Perm.sign σ • ∏ i, A (σ i) i) := abv.sum_le _ _
    _ = ∑ σ : Perm n, ∏ i, abv (A (σ i) i) :=
      sum_congr rfl fun σ _ => by rw [abv.map_units_int_smul, abv.map_prod]
    _ ≤ ∑ _σ : Perm n, ∏ _i : n, x := by gcongr; simp [hx]
    _ = (Fintype.card n)! • x ^ Fintype.card n := by simp [Fintype.card_perm]
```

-- snippet 35
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.adjugate_transpose (L198-L226)
theorem adjugate_transpose (A : Matrix n n α) : (adjugate A)ᵀ = adjugate Aᵀ := by
ext i j
  rw [transpose_apply, adjugate_apply, adjugate_apply, updateRow_transpose, det_transpose]
  rw [det_apply', det_apply']
  apply Finset.sum_congr rfl
  intro σ _
  congr 1
  by_cases h : i = σ j
  · -- Everything except `(i, j)` (= `(σ j, j)`) is given by A, and the rest is a single `1`.
    congr
    ext j'
    subst h
    have : σ j' = σ j ↔ j' = j := σ.injective.eq_iff
    rw [updateRow_apply, updateCol_apply]
    simp_rw [this]
    rw [← dite_eq_ite, ← dite_eq_ite]
    congr 1 with rfl
    rw [Pi.single_eq_same, Pi.single_eq_same]
  · -- Otherwise, we need to show that there is a `0` somewhere in the product.
    have : (∏ j' : n, updateCol A j (Pi.single i 1) (σ j') j') = 0 := by
      apply prod_eq_zero (mem_univ j)
      rw [updateCol_self, Pi.single_eq_of_ne' h]
    rw [this]
    apply prod_eq_zero (mem_univ (σ⁻¹ i))
    simp only [Perm.coe_inv, apply_symm_apply, updateRow_self]
    apply Pi.single_eq_of_ne
    intro h'
    exact h ((symm_apply_eq σ).mp h')
```

-- snippet 36
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_apply (L97-L99)
theorem cramer_apply (i : n) : cramer A b i = (A.updateCol i b).det :=
rfl
```

-- snippet 37
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.sum_cramer_apply (L148-L157)
theorem sum_cramer_apply {β} (s : Finset β) (f : n → β → α) (i : n) :
    (∑ x ∈ s, cramer A (fun j => f j x) i) = cramer A (fun j : n => ∑ x ∈ s, f j x) i :=
calc
    (∑ x ∈ s, cramer A (fun j => f j x) i) = (∑ x ∈ s, cramer A fun j => f j x) i :=
      (Finset.sum_apply i s _).symm
    _ = cramer A (fun j : n => ∑ x ∈ s, f j x) i := by
      rw [sum_cramer, cramer_apply]
      congr with j
      apply Finset.sum_apply
```

-- snippet 38
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.adjugate_apply (L194-L197)
theorem adjugate_apply (A : Matrix n n α) (i j : n) :
    adjugate A i j = (A.updateRow j (Pi.single i 1)).det := by
rw [adjugate_def, of_apply, cramer_apply, updateCol_transpose, det_transpose]
```

-- snippet 39
```lean
-- Mathlib.LinearAlgebra.Matrix.AbsoluteValue.det_sum_smul_le (L62-L73)
theorem det_sum_smul_le {ι : Type*} (s : Finset ι) {c : ι → R} {A : ι → Matrix n n R}
    {abv : AbsoluteValue R S} {x : S} (hx : ∀ k i j, abv (A k i j) ≤ x) {y : S}
    (hy : ∀ k, abv (c k) ≤ y) :
    abv (det (∑ k ∈ s, c k • A k)) ≤
      Nat.factorial (Fintype.card n) • (#s • y * x) ^ Fintype.card n := by
simpa only [smul_mul_assoc] using
    det_sum_le s fun k i j =>
      calc
        abv (c k * A k i j) = abv (c k) * abv (A k i j) := abv.map_mul _ _
        _ ≤ y * x := mul_le_mul (hy k) (hx k i j) (abv.nonneg _) ((abv.nonneg _).trans (hy k))

end Matrix
```

-- snippet 40
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_smul (L128-L131)
theorem cramer_smul (r : α) (A : Matrix n n α) :
    cramer (r • A) = r ^ (Fintype.card n - 1) • cramer A :=
LinearMap.ext fun _ => funext fun _ => det_updateCol_smul_left _ _ _ _
```

<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.Matrix.ConjTranspose).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
theorem vecMul_conjTranspose [Fintype n] [StarRing α] (A : Matrix m n α) (x : n → α) :
    x ᵥ* Aᴴ = star (A *ᵥ star x)
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose (L41-L43)
def conjTranspose [Star α] (M : Matrix m n α) : Matrix n m α :=
M.transpose.map star
```

-- snippet 2
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose_single (L48-L57)
lemma conjTranspose_single [DecidableEq n] [DecidableEq m] [AddMonoid α]
    [StarAddMonoid α] (i : m) (j : n) (a : α) :
    (single i j a)ᴴ = single j i (star a) := by
change (single i j a).transpose.map starAddEquiv = single j i (star a)
  simp

section Diagonal

variable [DecidableEq n]
```

-- snippet 3
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.diagonal_conjTranspose (L59-L67)
theorem diagonal_conjTranspose [AddMonoid α] [StarAddMonoid α] (v : n → α) :
    (diagonal v)ᴴ = diagonal (star v) := by
rw [conjTranspose, diagonal_transpose, diagonal_map (star_zero _)]
  rfl

end Diagonal

section Diag
```

-- snippet 4
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.diag_conjTranspose (L69-L82)
theorem diag_conjTranspose [Star α] (A : Matrix n n α) :
    diag Aᴴ = star (diag A) :=
rfl

end Diag

section DotProduct

variable [Fintype m] [Fintype n]

section StarRing

variable [NonUnitalSemiring α] [StarRing α] (v w : m → α)
```

-- snippet 5
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.star_dotProduct_star (L83-L84)
theorem star_dotProduct_star : star v ⬝ᵥ star w = star (w ⬝ᵥ v) := by simp [dotProduct]
```

-- snippet 6
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.star_dotProduct (L85-L86)
theorem star_dotProduct : star v ⬝ᵥ w = star (star w ⬝ᵥ v) := by simp [dotProduct]
```

-- snippet 7
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.dotProduct_star (L87-L96)
theorem dotProduct_star : v ⬝ᵥ star w = star (w ⬝ᵥ star v) := by simp [dotProduct]
end StarRing

end DotProduct

section NonUnitalSemiring

variable [NonUnitalSemiring α]
```

-- snippet 8
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.star_mulVec (L97-L100)
theorem star_mulVec [Fintype n] [StarRing α] (M : Matrix m n α) (v : n → α) :
    star (M *ᵥ v) = star v ᵥ* Mᴴ :=
funext fun _ => (star_dotProduct_star _ _).symm
```

-- snippet 9
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.star_vecMul (L101-L104)
theorem star_vecMul [Fintype m] [StarRing α] (M : Matrix m n α) (v : m → α) :
    star (v ᵥ* M) = Mᴴ *ᵥ star v :=
funext fun _ => (star_dotProduct_star _ _).symm
```

-- snippet 10
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.mulVec_conjTranspose (L105-L108)
theorem mulVec_conjTranspose [Fintype m] [StarRing α] (A : Matrix m n α) (x : m → α) :
    Aᴴ *ᵥ x = star (star x ᵥ* A) :=
funext fun _ => star_dotProduct _ _
```

-- snippet 11
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose_vecMulVec (L116-L127)
theorem conjTranspose_vecMulVec [Mul α] [StarMul α] (w : m → α) (v : n → α) :
    (vecMulVec w v)ᴴ = vecMulVec (star v) (star w) :=
ext fun _ _ => star_mul _ _

section ConjTranspose

open Matrix

/-- Tell `simp` what the entries are in a conjugate transposed matrix.

  Compare with `mul_apply`, `diagonal_apply_eq`, etc.
-/
```

-- snippet 12
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose_apply (L129-L132)
theorem conjTranspose_apply [Star α] (M : Matrix m n α) (i j) :
    M.conjTranspose j i = star (M i j) :=
rfl
```

-- snippet 13
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose_conjTranspose (L134-L137)
theorem conjTranspose_conjTranspose [InvolutiveStar α] (M : Matrix m n α) : Mᴴᴴ = M :=
Matrix.ext <| by simp

variable (n α) in
```

-- snippet 14
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose_involutive (L138-L141)
theorem conjTranspose_involutive [InvolutiveStar α] :
    (conjTranspose : Matrix n n α → Matrix n n α).Involutive :=
conjTranspose_conjTranspose
```

-- snippet 15
```lean
-- Mathlib.LinearAlgebra.Matrix.ConjTranspose.conjTranspose_transpose (L142-L145)
theorem conjTranspose_transpose [Star α] (M : Matrix m n α) :
    Mᴴᵀ = M.map star :=
rfl
```

-- snippet 16
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.adjugate_def (L191-L193)
theorem adjugate_def (A : Matrix n n α) : adjugate A = of fun i => cramer Aᵀ (Pi.single i 1) :=
rfl
```

-- snippet 17
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_zero (L136-L142)
theorem cramer_zero [Nontrivial n] : cramer (0 : Matrix n n α) = 0 := by
ext i j
  obtain ⟨j', hj'⟩ : ∃ j', j' ≠ j := exists_ne j
  apply det_eq_zero_of_column_eq_zero j'
  simp [updateCol_ne hj']

/-- Use linearity of `cramer` to take it out of a summation. -/
```

-- snippet 18
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.sum_cramer (L143-L147)
theorem sum_cramer {β} (s : Finset β) (f : β → n → α) :
    (∑ x ∈ s, cramer A (f x)) = cramer A (∑ x ∈ s, f x) :=
(map_sum (cramer A) ..).symm

/-- Use linearity of `cramer` and vector evaluation to take `cramer A _ i` out of a summation. -/
```

-- snippet 19
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_subsingleton_apply (L133-L135)
theorem cramer_subsingleton_apply [Subsingleton n] (A : Matrix n n α) (b : n → α) (i : n) :
    cramer A b i = b i := by rw [cramer_apply, det_eq_elem_of_subsingleton _ i, updateCol_self]
```

-- snippet 20
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.IsSymm (L227-L229)
theorem IsSymm.adjugate {A : Matrix n n α} (hA : A.IsSymm) : A.adjugate.IsSymm := by
rw [IsSymm, Matrix.adjugate_transpose, hA.eq]
```

-- snippet 21
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_transpose_row_self (L103-L114)
theorem cramer_transpose_row_self (i : n) : Aᵀ.cramer (A i) = Pi.single i A.det := by
ext j
  rw [cramer_apply, Pi.single_apply]
  split_ifs with h
  · -- i = j: this entry should be `A.det`
    subst h
    simp only [updateCol_transpose, det_transpose, updateRow_eq_self]
  · -- i ≠ j: this entry should be 0
    rw [updateCol_transpose, det_transpose]
    apply det_zero_of_row_eq h
    rw [updateRow_self, updateRow_ne (Ne.symm h)]
```

-- snippet 22
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramerMap (L76-L78)
def cramerMap (i : n) : α :=
(A.updateCol i b).det
```

-- snippet 23
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_transpose_apply (L100-L102)
theorem cramer_transpose_apply (i : n) : cramer Aᵀ b i = (A.updateRow i b).det := by
rw [cramer_apply, updateCol_transpose, det_transpose]
```

-- snippet 24
```lean
-- Mathlib.LinearAlgebra.Matrix.AbsoluteValue.det_sum_le (L52-L61)
theorem det_sum_le {ι : Type*} (s : Finset ι) {A : ι → Matrix n n R} {abv : AbsoluteValue R S}
    {x : S} (hx : ∀ k i j, abv (A k i j) ≤ x) :
    abv (det (∑ k ∈ s, A k)) ≤ (Fintype.card n)! • (#s • x) ^ Fintype.card n :=
det_le fun i j =>
    calc
      abv ((∑ k ∈ s, A k) i j) = abv (∑ k ∈ s, A k i j) := by simp only [sum_apply]
      _ ≤ ∑ k ∈ s, abv (A k i j) := abv.sum_le _ _
      _ ≤ ∑ _k ∈ s, x := by gcongr; apply hx
      _ = #s • x := sum_const _
```

-- snippet 25
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.adjugate_submatrix_equiv_self (L231-L238)
theorem adjugate_submatrix_equiv_self (e : n ≃ m) (A : Matrix m m α) :
    adjugate (A.submatrix e e) = (adjugate A).submatrix e e := by
ext i j
  have : (fun j ↦ Pi.single i 1 <| e.symm j) = Pi.single (e i) 1 :=
    Function.update_comp_equiv (0 : n → α) e.symm i 1
  rw [adjugate_apply, submatrix_apply, adjugate_apply, ← det_submatrix_equiv_self e,
    updateRow_submatrix_equiv, this]
```

-- snippet 26
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramerMap_is_linear (L79-L82)
theorem cramerMap_is_linear (i : n) : IsLinearMap α fun b => cramerMap A b i :=
{ map_add := det_updateCol_add _ _
    map_smul := det_updateCol_smul _ _ }
```

-- snippet 27
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_row_self (L115-L119)
theorem cramer_row_self (i : n) (h : ∀ j, b j = A j i) : A.cramer b = Pi.single i A.det := by
rw [← transpose_transpose A, det_transpose]
  convert cramer_transpose_row_self Aᵀ i
  exact funext h
```

-- snippet 28
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.adjugate (L188-L190)
def adjugate (A : Matrix n n α) : Matrix n n α :=
of fun i => cramer Aᵀ (Pi.single i 1)
```

-- snippet 29
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer (L94-L96)
def cramer (A : Matrix n n α) : (n → α) →ₗ[α] (n → α) :=
IsLinearMap.mk' (cramerMap A) (cramer_is_linear A)
```

-- snippet 30
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_reindex (L164-L187)
theorem cramer_reindex (e : m ≃ n) (A : Matrix m m α) (b : n → α) :
    cramer (reindex e e A) b = cramer A (b ∘ e) ∘ e.symm :=
cramer_submatrix_equiv _ _ _

end Cramer

section Adjugate

/-!
### `adjugate` section

Define the `adjugate` matrix and a few equations.
These will hold for any matrix over a commutative ring.
-/

/-- The adjugate matrix is the transpose of the cofactor matrix.

  Typically, the cofactor matrix is defined by taking minors,
  i.e. the determinant of the matrix with a row and column removed.
  However, the proof of `mul_adjugate` becomes a lot easier if we use the
  matrix replacing a column with a basis vector, since it allows us to use
  facts about the `cramer` map.
-/
```

-- snippet 31
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_is_linear (L83-L93)
theorem cramer_is_linear : IsLinearMap α (cramerMap A) := by
constructor <;> intros <;> ext i
  · apply (cramerMap_is_linear A i).1
  · apply (cramerMap_is_linear A i).2

/-- `cramer A b i` is the determinant of the matrix `A` with column `i` replaced with `b`,
  and thus `cramer A b` is the vector output by Cramer's rule on `A` and `b`.

  If `A * x = b` has a unique solution in `x`, `cramer A` sends the vector `b` to `A.det • x`.
  Otherwise, the outcome of `cramer` is well-defined but not necessarily useful.
-/
```

-- snippet 32
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_one (L121-L127)
theorem cramer_one : cramer (1 : Matrix n n α) = 1 := by
ext i j
  convert congr_fun (cramer_row_self (1 : Matrix n n α) (Pi.single i 1) i _) j
  · simp
  · intro j
    rw [Matrix.one_eq_pi_single, Pi.single_comm]
```

-- snippet 33
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_submatrix_equiv (L158-L163)
theorem cramer_submatrix_equiv (A : Matrix m m α) (e : n ≃ m) (b : n → α) :
    cramer (A.submatrix e e) b = cramer A (b ∘ e.symm) ∘ e := by
ext i
  simp_rw [Function.comp_apply, cramer_apply, updateCol_submatrix_equiv,
    det_submatrix_equiv_self e, Function.comp_def]
```

-- snippet 34
```lean
-- Mathlib.LinearAlgebra.Matrix.AbsoluteValue.det_le (L42-L51)
theorem det_le {A : Matrix n n R} {abv : AbsoluteValue R S} {x : S} (hx : ∀ i j, abv (A i j) ≤ x) :
    abv A.det ≤ (Fintype.card n)! • x ^ Fintype.card n :=
calc
    abv A.det = abv (∑ σ : Perm n, Perm.sign σ • ∏ i, A (σ i) i) := congr_arg abv (det_apply _)
    _ ≤ ∑ σ : Perm n, abv (Perm.sign σ • ∏ i, A (σ i) i) := abv.sum_le _ _
    _ = ∑ σ : Perm n, ∏ i, abv (A (σ i) i) :=
      sum_congr rfl fun σ _ => by rw [abv.map_units_int_smul, abv.map_prod]
    _ ≤ ∑ _σ : Perm n, ∏ _i : n, x := by gcongr; simp [hx]
    _ = (Fintype.card n)! • x ^ Fintype.card n := by simp [Fintype.card_perm]
```

-- snippet 35
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.adjugate_transpose (L198-L226)
theorem adjugate_transpose (A : Matrix n n α) : (adjugate A)ᵀ = adjugate Aᵀ := by
ext i j
  rw [transpose_apply, adjugate_apply, adjugate_apply, updateRow_transpose, det_transpose]
  rw [det_apply', det_apply']
  apply Finset.sum_congr rfl
  intro σ _
  congr 1
  by_cases h : i = σ j
  · -- Everything except `(i, j)` (= `(σ j, j)`) is given by A, and the rest is a single `1`.
    congr
    ext j'
    subst h
    have : σ j' = σ j ↔ j' = j := σ.injective.eq_iff
    rw [updateRow_apply, updateCol_apply]
    simp_rw [this]
    rw [← dite_eq_ite, ← dite_eq_ite]
    congr 1 with rfl
    rw [Pi.single_eq_same, Pi.single_eq_same]
  · -- Otherwise, we need to show that there is a `0` somewhere in the product.
    have : (∏ j' : n, updateCol A j (Pi.single i 1) (σ j') j') = 0 := by
      apply prod_eq_zero (mem_univ j)
      rw [updateCol_self, Pi.single_eq_of_ne' h]
    rw [this]
    apply prod_eq_zero (mem_univ (σ⁻¹ i))
    simp only [Perm.coe_inv, apply_symm_apply, updateRow_self]
    apply Pi.single_eq_of_ne
    intro h'
    exact h ((symm_apply_eq σ).mp h')
```

-- snippet 36
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_apply (L97-L99)
theorem cramer_apply (i : n) : cramer A b i = (A.updateCol i b).det :=
rfl
```

-- snippet 37
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.sum_cramer_apply (L148-L157)
theorem sum_cramer_apply {β} (s : Finset β) (f : n → β → α) (i : n) :
    (∑ x ∈ s, cramer A (fun j => f j x) i) = cramer A (fun j : n => ∑ x ∈ s, f j x) i :=
calc
    (∑ x ∈ s, cramer A (fun j => f j x) i) = (∑ x ∈ s, cramer A fun j => f j x) i :=
      (Finset.sum_apply i s _).symm
    _ = cramer A (fun j : n => ∑ x ∈ s, f j x) i := by
      rw [sum_cramer, cramer_apply]
      congr with j
      apply Finset.sum_apply
```

-- snippet 38
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.adjugate_apply (L194-L197)
theorem adjugate_apply (A : Matrix n n α) (i j : n) :
    adjugate A i j = (A.updateRow j (Pi.single i 1)).det := by
rw [adjugate_def, of_apply, cramer_apply, updateCol_transpose, det_transpose]
```

-- snippet 39
```lean
-- Mathlib.LinearAlgebra.Matrix.AbsoluteValue.det_sum_smul_le (L62-L73)
theorem det_sum_smul_le {ι : Type*} (s : Finset ι) {c : ι → R} {A : ι → Matrix n n R}
    {abv : AbsoluteValue R S} {x : S} (hx : ∀ k i j, abv (A k i j) ≤ x) {y : S}
    (hy : ∀ k, abv (c k) ≤ y) :
    abv (det (∑ k ∈ s, c k • A k)) ≤
      Nat.factorial (Fintype.card n) • (#s • y * x) ^ Fintype.card n := by
simpa only [smul_mul_assoc] using
    det_sum_le s fun k i j =>
      calc
        abv (c k * A k i j) = abv (c k) * abv (A k i j) := abv.map_mul _ _
        _ ≤ y * x := mul_le_mul (hy k) (hx k i j) (abv.nonneg _) ((abv.nonneg _).trans (hy k))

end Matrix
```

-- snippet 40
```lean
-- Mathlib.LinearAlgebra.Matrix.Adjugate.cramer_smul (L128-L131)
theorem cramer_smul (r : α) (A : Matrix n n α) :
    cramer (r • A) = r ^ (Fintype.card n - 1) • cramer A :=
LinearMap.ext fun _ => funext fun _ => det_updateCol_smul_left _ _ _ _
```
[/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.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital).

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

```lean
lemma cfcHom_id :
    cfcHom ha ((ContinuousMap.id R).restrict <| spectrum R a) = a
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.is (L50-L142)
theorem is nearly impossible to state nicely in terms of `cfcHom` (see `cfcHom_comp`). An
additional advantage of the unbundled approach is that expressions like `fun x : R ↦ x⁻¹` are valid
arguments to `cfc`, and a bundled continuous counterpart can only make sense when the spectrum of
`a` does not contain zero and when we have an `⁻¹` operation on the domain.

A reader familiar with C⋆-algebra theory may be somewhat surprised at the level of abstraction here.
For instance, why not require `A` to be an actual C⋆-algebra? Why define separate continuous
functional calculi for `R := ℂ`, `ℝ` or `ℝ≥0` instead of simply using the continuous functional
calculus for normal elements? The reason for both can be explained with a simple example,
`A := Matrix n n ℝ`. In Mathlib, matrices are not equipped with a norm (nor even a metric), and so
requiring `A` to be a C⋆-algebra is far too stringent. Likewise, `A` is not a `ℂ`-algebra, and so
it is impossible to consider the `ℂ`-spectrum of `a : Matrix n n ℝ`.

There is another, more practical reason to define separate continuous functional calculi for
different scalar rings. It gives us the ability to use functions defined on these types, and the
algebra of functions on them. For example, for `R := ℝ` it is quite natural to consider the
functions `(·⁺ : ℝ → ℝ)` and `(·⁻ : ℝ → ℝ)` because the functions `ℝ → ℝ` form a lattice ordered
group. If `a : A` is selfadjoint, and we define `a⁺ := cfc (·⁺ : ℝ → ℝ) a`, and likewise for `a⁻`,
then the properties `a⁺ * a⁻ = 0 = a⁻ * a⁺` and `a = a⁺ - a⁻` are trivial consequences of the
corresponding facts for functions. In contrast, if we had to do this using functions on `ℂ`, the
proofs of these facts would be much more cumbersome.

## Example

The canonical example of the continuous functional calculus is when `A := Matrix n n ℂ`, `R := ℂ`
and `p := IsStarNormal`. In this case, `spectrum ℂ a` consists of the eigenvalues of the normal
matrix `a : Matrix n n ℂ`, and, because this set is discrete, any function is continuous on the
spectrum. The continuous functional calculus allows us to make sense of expressions like `log a`
(`:= cfc log a`), and when `0 ∉ spectrum ℂ a`, we get the nice property `exp (log a) = a`, which
arises from the composition property `cfc exp (cfc log a) = cfc (exp ∘ log) a = cfc id a = a`, since
`exp ∘ log = id` *on the spectrum of `a`*. Of course, there are other ways to make sense of `exp`
and `log` for matrices (power series), and these agree with the continuous functional calculus.
In fact, given `f : C(spectrum ℂ a, ℂ)`, `cfc f a` amounts to diagonalizing `a` (possible since `a`
is normal), and applying `f` to the resulting diagonal entries. That is, if `a = u * d * star u`
with `u` a unitary matrix and `d` diagonal, then `cfc f a = u * d.map f * star u`.

In addition, if `a : Matrix n n ℂ` is positive semidefinite, then the `ℂ`-spectrum of `a` is
contained in (the range of the coercion of) `ℝ≥0`. In this case, we get a continuous functional
calculus with `R := ℝ≥0`. From this we can define `√a := cfc a NNReal.sqrt`, which is also
positive semidefinite (because `cfc` preserves the predicate), and this is truly a square root since
```
√a * √a = cfc NNReal.sqrt a * cfc NNReal.sqrt a =
  cfc (NNReal.sqrt ^ 2) a = cfc id a = a
```
The composition property allows us to show that, in fact, this is the *unique* positive semidefinite
square root of `a` because, if `b` is any positive semidefinite square root, then
```
b = cfc id b = cfc (NNReal.sqrt ∘ (· ^ 2)) b =
  cfc NNReal.sqrt (cfc b (· ^ 2)) = cfc NNReal.sqrt a = √a
```

## Main declarations

+ `ContinuousFunctionalCalculus R A (p : A → Prop)`: a class stating that every `a : A` satisfying
  `p a` has a star algebra homomorphism from the continuous `R`-valued functions on the
  `R`-spectrum of `a` into the algebra `A`. This map is a closed embedding, and satisfies the
  **spectral mapping theorem**.
+ `cfcHom : p a → C(spectrum R a, R) →⋆ₐ[R] A`: the underlying star algebra homomorphism for an
  element satisfying property `p`.
+ `cfc : (R → R) → A → A`: an unbundled version of `cfcHom` which takes the junk value `0` when
  `cfcHom` is not defined.
+ `cfcUnits`: builds a unit from `cfc f a` when `f` is nonzero and continuous on the
  spectrum of `a`.

## Main theorems

+ `cfc_comp : cfc (x ↦ g (f x)) a = cfc g (cfc f a)`
+ `cfc_polynomial`: the continuous functional calculus extends the polynomial functional calculus.

## Implementation details

Instead of defining a class depending on a term `a : A`, we register it for an `outParam` predicate
`p : A → Prop`, and then any element of `A` satisfying this predicate has the associated star
algebra homomorphism with the specified properties. In so doing we avoid a common pitfall:
dependence of the class on a term. This avoids annoying situations where `a b : A` are
propositionally equal, but not definitionally so, and hence Lean would not be able to automatically
identify the continuous functional calculi associated to these elements. In order to guarantee
the necessary properties, we require that the continuous functional calculus preserves this
predicate. That is, `p a → p (cfc f a)` for any function `f` continuous on the spectrum of `a`.

As stated above, the unbundled approach to `cfc` has its advantages. For instance, given an
expression `cfc f a`, the user is free to rewrite either `a` or `f` as desired with no possibility
of the expression ceasing to be defined. However, this unbundling also has some potential downsides.
In particular, by unbundling, proof requirements are deferred until the user calls the lemmas, most
of which have hypotheses both of `p a` and of `ContinuousOn f (spectrum R a)`.

In order to minimize burden to the user, we provide `autoParams` in terms of two tactics. Goals
related to continuity are dispatched by (a small wrapper around) `fun_prop`. As for goals involving
the predicate `p`, it should be noted that these will only ever be of the form `IsStarNormal a`,
`IsSelfAdjoint a` or `0 ≤ a`. For the moment we provide a rudimentary tactic to deal with these
goals, but it can be modified to become more sophisticated as the need arises.
-/
```

-- snippet 2
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.ContinuousFunctionalCalculus (L210-L213)
lemma ContinuousFunctionalCalculus.isCompact_spectrum (a : A) :
    IsCompact (spectrum R a) :=
isCompact_iff_compactSpace.mpr inferInstance
```

-- snippet 3
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.StarAlgHom (L214-L241)
lemma StarAlgHom.ext_continuousMap [UniqueHom R A]
    (a : A) [CompactSpace (spectrum R a)] (φ ψ : C(spectrum R a, R) →⋆ₐ[R] A)
    (hφ : Continuous φ) (hψ : Continuous ψ)
    (h : φ (.restrict (spectrum R a) <| .id R) = ψ (.restrict (spectrum R a) <| .id R)) :
    φ = ψ :=
UniqueHom.eq_of_continuous_of_map_id (spectrum R a) φ ψ hφ hψ h

section cfcHom

variable {a : A} (ha : p a)

-- Note: since `spectrum R a` is closed, we may always extend `f : C(spectrum R a, R)` to a function
-- of type `C(R, R)` by the Tietze extension theorem (assuming `R` is either `ℝ`, `ℂ` or `ℝ≥0`).

/-- The star algebra homomorphism underlying an instance of the continuous functional calculus;
a version for continuous functions on the spectrum.

In this case, the user must supply the fact that `a` satisfies the predicate `p`, for otherwise it
may be the case that no star algebra homomorphism exists. For instance if `R := ℝ` and `a` is an
element whose spectrum (in `ℂ`) is disjoint from `ℝ`, then `spectrum ℝ a = ∅` and so there can be
no star algebra homomorphism between these spaces.

While `ContinuousFunctionalCalculus` is stated in terms of these homomorphisms, in practice the
user should instead prefer `cfc` over `cfcHom`.
-/
noncomputable def cfcHom : C(spectrum R a, R) →⋆ₐ[R] A :=
  (ContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose
```

-- snippet 4
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_continuous (L243-L245)
lemma cfcHom_continuous : Continuous (cfcHom ha : C(spectrum R a, R) →⋆ₐ[R] A) :=
(ContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose_spec.1
```

-- snippet 5
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_injective (L246-L248)
lemma cfcHom_injective : Function.Injective (cfcHom ha : C(spectrum R a, R) →⋆ₐ[R] A) :=
(ContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose_spec.2.1
```

-- snippet 6
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_map_spectrum (L254-L257)
lemma cfcHom_map_spectrum (f : C(spectrum R a, R)) :
    spectrum R (cfcHom ha f) = Set.range f :=
(ContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose_spec.2.2.2.1 f
```

-- snippet 7
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_predicate (L258-L262)
lemma cfcHom_predicate (f : C(spectrum R a, R)) :
    p (cfcHom ha f) :=
(ContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose_spec.2.2.2.2 f

open scoped ContinuousFunctionalCalculus in
```

-- snippet 8
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_eq_of_continuous_of_map_id (L263-L268)
lemma cfcHom_eq_of_continuous_of_map_id [UniqueHom R A]
    (φ : C(spectrum R a, R) →⋆ₐ[R] A) (hφ₁ : Continuous φ)
    (hφ₂ : φ (.restrict (spectrum R a) <| .id R) = a) : cfcHom ha = φ :=
(cfcHom ha).ext_continuousMap a φ (cfcHom_continuous ha) hφ₁ <| by
    rw [cfcHom_id ha, hφ₂]
```

-- snippet 9
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_comp (L269-L287)
theorem cfcHom_comp [UniqueHom R A] (f : C(spectrum R a, R))
    (f' : C(spectrum R a, spectrum R (cfcHom ha f)))
    (hff' : ∀ x, f x = f' x) (g : C(spectrum R (cfcHom ha f), R)) :
    cfcHom ha (g.comp f') = cfcHom (cfcHom_predicate ha f) g := by
let φ : C(spectrum R (cfcHom ha f), R) →⋆ₐ[R] A :=
    (cfcHom ha).comp <| ContinuousMap.compStarAlgHom' R R f'
  suffices cfcHom (cfcHom_predicate ha f) = φ from DFunLike.congr_fun this.symm g
  refine cfcHom_eq_of_continuous_of_map_id (cfcHom_predicate ha f) φ ?_ ?_
  · exact cfcHom_continuous ha |>.comp f'.continuous_precomp
  · simp only [φ, StarAlgHom.comp_apply, ContinuousMap.compStarAlgHom'_apply]
    congr
    ext x
    simp [hff']

end cfcHom

section cfcL

/-- `cfcHom` bundled as a continuous linear map. -/
```

-- snippet 10
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfc_apply (L318-L320)
lemma cfc_apply : cfc f a = cfcHom (a := a) ha ⟨_, hf.restrict⟩ := by
rw [cfc_def, dif_pos ⟨ha, hf⟩]
```

-- snippet 11
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfc_apply_pi (L321-L326)
lemma cfc_apply_pi {ι : Type*} (f : ι → R → R) (a : A) (ha : p a := by cfc_tac)
(hf : ∀ i, ContinuousOn (f i) (spectrum R a) := by cfc_cont_tac) :
    (fun i => cfc (f i) a) = (fun i => cfcHom (a := a) ha ⟨_, (hf i).restrict⟩) := by
  ext i
  simp only [cfc_apply (f i) a ha (hf i)]
```

-- snippet 12
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfc_apply_of_not_and (L327-L330)
lemma cfc_apply_of_not_and {f : R → R} (a : A) (ha : ¬ (p a ∧ ContinuousOn f (spectrum R a))) :
    cfc f a = 0 := by
rw [cfc_def, dif_neg ha]
```

-- snippet 13
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfc_apply_of_not_predicate (L331-L334)
lemma cfc_apply_of_not_predicate {f : R → R} (a : A) (ha : ¬ p a) :
    cfc f a = 0 := by
rw [cfc_def, dif_neg (not_and_of_not_left _ ha)]
```

-- snippet 14
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfc_apply_of_not_continuousOn (L335-L338)
lemma cfc_apply_of_not_continuousOn {f : R → R} (a : A) (hf : ¬ ContinuousOn f (spectrum R a)) :
    cfc f a = 0 := by
rw [cfc_def, dif_neg (not_and_of_not_right _ hf)]
```

-- snippet 15
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_eq_cfc_extend (L339-L347)
lemma cfcHom_eq_cfc_extend {a : A} (g : R → R) (ha : p a) (f : C(spectrum R a, R)) :
    cfcHom ha f = cfc (Function.extend Subtype.val f g) a := by
have h : f = (spectrum R a).restrict (Function.extend Subtype.val f g) := by
    ext; simp
  have hg : ContinuousOn (Function.extend Subtype.val f g) (spectrum R a) :=
    continuousOn_iff_continuous_restrict.mpr <| h ▸ map_continuous f
  rw [cfc_apply ..]
  congr!
```

-- snippet 16
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.nnnorm_star (L60-L63)
theorem nnnorm_star (x : E) : ‖star x‖₊ = ‖x‖₊ :=
Subtype.ext <| norm_star _

/-- The `star` map in a normed star group is a normed group homomorphism. -/
```

-- snippet 17
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.norm_star (L56-L58)
lemma norm_star (x : E) : ‖x⋆‖ = ‖x‖ :=
le_antisymm (NormedStarGroup.norm_star_le x) (by simpa using NormedStarGroup.norm_star_le x⋆)
```

-- snippet 18
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.eventually_star_eq (L161-L171)
lemma eventually_star_eq {l : Filter A} (hl : l.IsIncreasingApproximateUnit) :
    ∀ᶠ x in l, star x = x :=
hl.eventually_isSelfAdjoint.mp <| .of_forall fun _ ↦ IsSelfAdjoint.star_eq

end Filter.IsIncreasingApproximateUnit

namespace CStarAlgebra

open Submodule in
/-- To show that `l` is a one-sided approximate unit for `A`, it suffices to verify it only for
`m : A` with `0 ≤ m` and `‖m‖ < 1`. -/
```

-- snippet 19
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.hasBasis_approximateUnit (L211-L218)
lemma hasBasis_approximateUnit :
    (approximateUnit A).HasBasis (fun x : A ↦ 0 ≤ x ∧ ‖x‖ < 1) ({x | · ≤ x} ∩ closedBall 0 1) :=
isBasis_nonneg_sections A |>.hasBasis.inf_principal (closedBall 0 1)

/-- This is a common reasoning sequence in C⋆-algebra theory. If `0 ≤ x ≤ y ≤ 1`, then the norm of
`z - y * z` is controlled by the norm of `star z * (1 - x) * z`, which is advantageous because the
latter is nonnegative. This is a key step in establishing the existence of an increasing approximate
unit in general C⋆-algebras. -/
```

-- snippet 20
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.star_isometry (L68-L71)
theorem star_isometry : Isometry (star : E → E) :=
show Isometry starAddEquiv from
    AddMonoidHomClass.isometry_of_norm starAddEquiv (show ∀ x, ‖x⋆‖ = ‖x‖ from norm_star)
```

-- snippet 21
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.eventually_isSelfAdjoint (L157-L160)
lemma eventually_isSelfAdjoint {l : Filter A} (hl : l.IsIncreasingApproximateUnit) :
    ∀ᶠ x in l, IsSelfAdjoint x :=
hl.eventually_nonneg.mp <| .of_forall fun _ ↦ IsSelfAdjoint.of_nonneg
```

-- snippet 22
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.increasingApproximateUnit (L314-L331)
lemma increasingApproximateUnit :
    IsIncreasingApproximateUnit (approximateUnit A) where
  tendsto_mul_left := by
rw [tendsto_mul_left_iff_tendsto_mul_right]
    · exact tendsto_mul_right_approximateUnit
    · rw [(hasBasis_approximateUnit A).eventually_iff]
      peel (hasBasis_approximateUnit A).ex_mem with x hx
      exact ⟨hx, fun y hy ↦ (hx.1.trans hy.1).isSelfAdjoint⟩
  tendsto_mul_right := tendsto_mul_right_approximateUnit
  eventually_nonneg := .filter_mono inf_le_left <|
    (isBasis_nonneg_sections A).hasBasis.eventually_iff.mpr ⟨0, by simp⟩
  eventually_norm := .filter_mono inf_le_right <| by simp
  neBot := hasBasis_approximateUnit A |>.neBot_iff.mpr
    fun hx ↦ ⟨_, ⟨le_rfl, by simpa using hx.2.le⟩⟩

end CStarAlgebra

end ApproximateUnit
```

-- snippet 23
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.norm_self_mul_star (L125-L128)
theorem norm_self_mul_star {x : E} : ‖x * x⋆‖ = ‖x‖ * ‖x‖ := by
nth_rw 1 [← star_star x]
  simp only [norm_star_mul_self, norm_star]
```

-- snippet 24
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.RingHomIsometric (L82-L91)
instance RingHomIsometric.starRingEnd [NormedCommRing E] [StarRing E] [NormedStarGroup E] :
    RingHomIsometric (starRingEnd E) :=
⟨@norm_star _ _ _ _⟩

/-- A C*-ring is a normed star ring that satisfies the stronger condition `‖x‖ ^ 2 ≤ ‖x⋆ * x‖`
for every `x`. Note that this condition actually implies equality, as is shown in
`norm_star_mul_self` below. -/
class CStarRing (E : Type*) [NonUnitalNormedRing E] [StarRing E] : Prop where
  norm_mul_self_le : ∀ x : E, ‖x‖ * ‖x‖ ≤ ‖x⋆ * x‖
```

-- snippet 25
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.isBasis_nonneg_sections (L197-L205)
lemma isBasis_nonneg_sections :
    IsBasis (fun x : A ↦ 0 ≤ x ∧ ‖x‖ < 1) ({x | · ≤ x}) where
  nonempty := ⟨0, by simp⟩
inter {x y} hx hy := by
    peel directedOn_nonneg_ball x (by simpa) y (by simpa) with z hz
    exact ⟨by simpa using hz.1, fun a ha ↦ ⟨hz.2.1.trans ha, hz.2.2.trans ha⟩⟩

/-- The canonical approximate unit in a C⋆-algebra generated by the basis of sets
`{x | a ≤ x} ∩ closedBall 0 1` for `0 ≤ a`. See also `CStarAlgebra.hasBasis_approximateUnit`. -/
```

-- snippet 26
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.norm_sub_mul_self_le_of_inr (L246-L313)
lemma norm_sub_mul_self_le_of_inr {x y : A} (z : A) (hx₀ : 0 ≤ x) (hxy : x ≤ y) (hy₁ : ‖y‖ ≤ 1)
    {c : ℝ} (hc : 0 ≤ c) (h : ‖star (z : A⁺¹) * (1 - x) * z‖ ≤ c ^ 2) :
    ‖z - y * z‖ ≤ c := by
rw [← norm_inr (𝕜 := ℂ), inr_sub, inr_mul]
  refine norm_sub_mul_self_le _ ?_ ?_ hc h
  · rwa [inr_nonneg_iff]
  · have hy := hx₀.trans hxy
    rw [Set.mem_Icc, inr_le_iff _ _ hx₀.isSelfAdjoint hy.isSelfAdjoint,
      ← norm_le_one_iff_of_nonneg _, norm_inr]
    exact ⟨hxy, hy₁⟩

set_option backward.isDefEq.respectTransparency false in
variable {A} in
/-- This shows `CStarAlgebra.approximateUnit` is a one-sided approximate unit, but this is marked
`private` because it is only used to prove `CStarAlgebra.increasingApproximateUnit`. -/
private lemma tendsto_mul_right_approximateUnit (m : A) :
    Tendsto (· * m) (approximateUnit A) (𝓝 m) := by
  refine tendsto_mul_right_of_forall_nonneg_tendsto (fun m hm₁ hm₂ ↦ ?_) m
  rw [(hasBasis_approximateUnit A).tendsto_iff nhds_basis_closedBall]
  intro ε hε
  lift ε to ℝ≥0 using hε.le
  rw [coe_pos] at hε
  refine ⟨cfcₙ (fun y : ℝ≥0 ↦ 1 - (1 + y)⁻¹) (ε⁻¹ ^ 2 • m),
    ⟨cfcₙ_nonneg_of_predicate, norm_cfcₙ_one_sub_one_add_inv_lt_one (ε⁻¹ ^ 2 • m)⟩, ?_⟩
  rintro x ⟨(hx₁ : _ ≤ x), hx₂⟩
  simp only [mem_closedBall, dist_eq_norm', zero_sub, norm_neg] at hx₂ ⊢
  rw [← coe_nnnorm, coe_le_coe]
  have hx₀ : 0 ≤ x := cfcₙ_nonneg_of_predicate.trans hx₁
  rw [← inr_le_iff _ _ (.of_nonneg cfcₙ_nonneg_of_predicate) (.of_nonneg hx₀),
    nnreal_cfcₙ_eq_cfc_inr _ _ (by simp [tsub_self]), inr_smul] at hx₁
  rw [← norm_inr (𝕜 := ℂ)] at hm₂ hx₂
  rw [← inr_nonneg_iff] at hx₀ hm₁
  rw [← nnnorm_inr (𝕜 := ℂ), inr_sub, inr_mul]
  generalize (x : A⁺¹) = x, (m : A⁺¹) = m at *
  set g : ℝ≥0 → ℝ≥0 := fun y ↦ 1 - (1 + y)⁻¹
  have hg : Continuous g := by
    rw [← continuousOn_univ]
    fun_prop (disch := intro _ _; positivity)
  have hg' : ContinuousOn (fun y ↦ (1 + ε⁻¹ ^ 2 • y)⁻¹) (spectrum ℝ≥0 m) :=
    ContinuousOn.inv₀ (by fun_prop) fun _ _ ↦ by positivity
  have hx : x ∈ Set.Icc 0 1 := mem_Icc_iff_norm_le_one.mpr ⟨hx₀, hx₂⟩
  have hx' : x ∈ Set.Icc _ 1 := ⟨hx₁, hx.2⟩
  refine nnnorm_sub_mul_self_le m cfc_nonneg_of_predicate hx' ?_
  suffices star m * (1 - cfc g (ε⁻¹ ^ 2 • m)) * m =
      cfc (fun y : ℝ≥0 ↦ y * (1 + ε⁻¹ ^ 2 • y)⁻¹ * y) m by
    rw [this]
    refine nnnorm_cfc_nnreal_le fun y hy ↦ ?_
    calc
      y * (1 + ε⁻¹ ^ 2 • y)⁻¹ * y = y * ε ^ 2 * (y / (ε ^ 2 + y)) := by simp [field]
      _ ≤ ε ^ 2 * 1 := by
        gcongr
        · refine mul_le_of_le_one_left (zero_le _) ?_
          have hm' := hm₂.le
          rw [norm_le_one_iff_of_nonneg m hm₁, ← cfc_id' ℝ≥0 m, ← cfc_one (R := ℝ≥0) m,
            cfc_nnreal_le_iff _ _ _ (QuasispectrumRestricts.nnreal_of_nonneg hm₁)] at hm'
          exact hm' y hy
        · exact div_le_one (by positivity) |>.mpr le_add_self
      _ = ε ^ 2 := mul_one _
  rw [cfc_mul _ _ m (continuousOn_id' _ |>.fun_mul hg') (continuousOn_id' _),
    cfc_mul _ _ m (continuousOn_id' _) hg', cfc_id' .., hm₁.star_eq]
  congr
  rw [← cfc_one (R := ℝ≥0) m, ← cfc_comp_smul _ _ _ hg.continuousOn hm₁,
    ← cfc_tsub _ _ m (by simp [g]) hm₁ (by fun_prop) (Continuous.continuousOn <| by fun_prop)]
  refine cfc_congr (fun y _ ↦ ?_)
  simp [g, tsub_tsub_cancel_of_le]

/-- The filter `CStarAlgebra.approximateUnit` generated by the sections
`{x | a ≤ x} ∩ closedBall 0 1` for `0 ≤ a` forms an increasing approximate unit. -/
```

-- snippet 27
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.starNormedAddGroupHom (L64-L67)
def starNormedAddGroupHom : NormedAddGroupHom E E :=
{ starAddEquiv with bound' := ⟨1, fun _ => le_trans (norm_star _).le (one_mul _).symm.le⟩ }

/-- The `star` map in a normed star group is an isometry -/
```

-- snippet 28
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.of_le_norm_mul_star_self (L100-L114)
lemma of_le_norm_mul_star_self
    [NonUnitalNormedRing E] [StarRing E]
    (h : ∀ x : E, ‖x‖ * ‖x‖ ≤ ‖x * x⋆‖) : CStarRing E :=
have : NormedStarGroup E :=
    { norm_star_le x := by
        obtain (hx | hx) := eq_zero_or_norm_pos x⋆
        · simp [hx]
        · refine le_of_mul_le_mul_right ?_ hx
          simpa [sq, mul_comm ‖x⋆‖] using h x⋆ |>.trans <| norm_mul_le _ _ }
  ⟨star_involutive.surjective.forall.mpr <| by simpa⟩

variable [NonUnitalNormedRing E] [StarRing E] [CStarRing E]

-- see Note [lower instance priority]
/-- In a C*-ring, star preserves the norm. -/
```

-- snippet 29
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.nnnorm_sub_mul_self_le (L219-L237)
lemma nnnorm_sub_mul_self_le {A : Type*} [CStarAlgebra A] [PartialOrder A] [StarOrderedRing A]
    {x y : A} (z : A) (hx₀ : 0 ≤ x) (hy : y ∈ Set.Icc x 1) {c : ℝ≥0}
    (h : ‖star z * (1 - x) * z‖₊ ≤ c ^ 2) :
    ‖z - y * z‖₊ ≤ c := by
nth_rw 1 [← one_mul z]
  rw [← sqrt_sq c, le_sqrt_iff_sq_le, ← sub_mul, sq, ← CStarRing.nnnorm_star_mul_self]
  simp only [star_mul, star_sub, star_one]
  have hy₀ : y ∈ Set.Icc 0 1 := ⟨hx₀.trans hy.1, hy.2⟩
  have hy' : 1 - y ∈ Set.Icc 0 1 := Set.sub_mem_Icc_zero_iff_right.mpr hy₀
  rw [hy₀.1.star_eq, ← mul_assoc, mul_assoc (star _), ← sq]
  refine nnnorm_le_nnnorm_of_nonneg_of_le (star_left_conjugate_nonneg (pow_nonneg hy'.1 2) _) ?_
    |>.trans h
  refine star_left_conjugate_le_conjugate ?_ _
  trans (1 - y)
  · simpa using pow_antitone hy'.1 hy'.2 one_le_two
  · gcongr
    exact hy.1

/-- A variant of `nnnorm_sub_mul_self_le` which uses `‖·‖` instead of `‖·‖₊`. -/
```

-- snippet 30
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.Set (L91-L104)
lemma Set.InvOn.one_sub_one_add_inv : Set.InvOn (fun x ↦ 1 - (1 + x)⁻¹) (fun x ↦ x * (1 - x)⁻¹)
    {x : ℝ≥0 | x < 1} {x : ℝ≥0 | x < 1} := by
have : (fun x : ℝ≥0 ↦ x * (1 + x)⁻¹) = fun x ↦ 1 - (1 + x)⁻¹ := by
    ext x : 1
    simp [field, mul_tsub]
  rw [← this]
  constructor <;> intro x (hx : x < 1)
  · have : 0 < 1 - x := tsub_pos_of_lt hx
    simp [field, tsub_add_cancel_of_le hx.le]
  · simp [mul_assoc, ← mul_inv, mul_tsub]
    field_simp
    simp

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 31
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.CStarAlgebra (L110-L152)
lemma CStarAlgebra.directedOn_nonneg_ball :
    DirectedOn (· ≤ ·) ({x : A | 0 ≤ x} ∩ Metric.ball 0 1) := by
let f : ℝ≥0 → ℝ≥0 := fun x => 1 - (1 + x)⁻¹
  let g : ℝ≥0 → ℝ≥0 := fun x => x * (1 - x)⁻¹
  suffices ∀ a b : A, 0 ≤ a → 0 ≤ b → ‖a‖ < 1 → ‖b‖ < 1 →
      a ≤ cfcₙ f (cfcₙ g a + cfcₙ g b) by
    rintro a ⟨(ha₁ : 0 ≤ a), ha₂⟩ b ⟨(hb₁ : 0 ≤ b), hb₂⟩
    simp only [Metric.mem_ball, dist_zero_right] at ha₂ hb₂
    refine ⟨cfcₙ f (cfcₙ g a + cfcₙ g b), ⟨by simp, ?_⟩, ?_, ?_⟩
    · simpa only [Metric.mem_ball, dist_zero_right] using norm_cfcₙ_one_sub_one_add_inv_lt_one _
    · exact this a b ha₁ hb₁ ha₂ hb₂
    · exact add_comm (cfcₙ g a) (cfcₙ g b) ▸ this b a hb₁ ha₁ hb₂ ha₂
  rintro a b ha₁ - ha₂ -
  calc
    a = cfcₙ (f ∘ g) a := by
      conv_lhs => rw [← cfcₙ_id ℝ≥0 a]
      refine cfcₙ_congr (Set.InvOn.one_sub_one_add_inv.1.eqOn.symm.mono fun x hx ↦ ?_)
      exact lt_of_le_of_lt (le_nnnorm_of_mem_quasispectrum hx) ha₂
    _ = cfcₙ f (cfcₙ g a) := by
      rw [cfcₙ_comp f g a ?_ (by simp [f, tsub_self]) ?_ (by simp [g]) ha₁]
      · fun_prop (disch := intro _ _; positivity)
      · have (x) (hx : x ∈ σₙ ℝ≥0 a) : 1 - x ≠ 0 := by
          refine tsub_pos_of_lt ?_ |>.ne'
          exact lt_of_le_of_lt (le_nnnorm_of_mem_quasispectrum hx) ha₂
        fun_prop (disch := assumption)
    _ ≤ cfcₙ f (cfcₙ g a + cfcₙ g b) := by
      have hab' : cfcₙ g a ≤ cfcₙ g a + cfcₙ g b := le_add_of_nonneg_right cfcₙ_nonneg_of_predicate
      exact CFC.monotoneOn_one_sub_one_add_inv cfcₙ_nonneg_of_predicate
        (cfcₙ_nonneg_of_predicate.trans hab') hab'

section ApproximateUnit

open Metric Filter Topology

/-- An *increasing approximate unit* in a C⋆-algebra is an approximate unit contained in the
closed unit ball of nonnegative elements. -/
structure Filter.IsIncreasingApproximateUnit (l : Filter A) : Prop extends l.IsApproximateUnit where
  eventually_nonneg : ∀ᶠ x in l, 0 ≤ x
  eventually_norm : ∀ᶠ x in l, ‖x‖ ≤ 1

namespace Filter.IsIncreasingApproximateUnit

omit [StarOrderedRing A] in
```

-- snippet 32
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.norm_cfcₙ_one_sub_one_add_inv_lt_one (L105-L109)
lemma norm_cfcₙ_one_sub_one_add_inv_lt_one (a : A) :
    ‖cfcₙ (fun x : ℝ≥0 ↦ 1 - (1 + x)⁻¹) a‖ < 1 :=
nnnorm_cfcₙ_nnreal_lt fun x _ ↦ tsub_lt_self zero_lt_one (by positivity)

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 33
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.tendsto_mul_right_of_forall_nonneg_tendsto (L172-L185)
lemma tendsto_mul_right_of_forall_nonneg_tendsto {l : Filter A}
    (h : ∀ m, 0 ≤ m → ‖m‖ < 1 → Tendsto (· * m) l (𝓝 m)) (m : A) :
    Tendsto (· * m) l (𝓝 m) := by
obtain ⟨n, c, x, rfl⟩ := mem_span_set'.mp <| by
    change m ∈ span ℂ ({x | 0 ≤ x} ∩ ball 0 1)
    simp [span_nonneg_inter_unitBall]
  simp_rw [Finset.mul_sum]
  refine tendsto_finset_sum _ fun i _ ↦ ?_
  simp_rw [mul_smul_comm]
  exact tendsto_const_nhds.smul <| h (x i) (x i).2.1 <| by simpa using (x i).2.2

omit [PartialOrder A] in
/-- Multiplication on the left by `m` tends to `𝓝 m` if and only if multiplication on the right
does, provided the elements are eventually selfadjoint along the filter `l`. -/
```

-- snippet 34
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.norm_star_mul_self' (L129-L130)
theorem norm_star_mul_self' {x : E} : ‖x⋆ * x‖ = ‖x⋆‖ * ‖x‖ := by rw [norm_star_mul_self, norm_star]
```

-- snippet 35
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.eventually_nnnorm (L153-L156)
lemma eventually_nnnorm {l : Filter A} (hl : l.IsIncreasingApproximateUnit) :
    ∀ᶠ x in l, ‖x‖₊ ≤ 1 :=
hl.eventually_norm
```

-- snippet 36
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.norm_sub_mul_self_le (L238-L245)
lemma norm_sub_mul_self_le {A : Type*} [CStarAlgebra A] [PartialOrder A] [StarOrderedRing A]
    {x y : A} (z : A) (hx₀ : 0 ≤ x) (hy : y ∈ Set.Icc x 1)
    {c : ℝ} (hc : 0 ≤ c) (h : ‖star z * (1 - x) * z‖ ≤ c ^ 2) :
    ‖z - y * z‖ ≤ c :=
nnnorm_sub_mul_self_le z hx₀ hy h (c := ⟨c, hc⟩)

variable {A} in
/-- A variant of `norm_sub_mul_self_le` for non-unital algebras that passes to the unitization. -/
```

-- snippet 37
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.norm_star_mul_self (L122-L124)
theorem norm_star_mul_self {x : E} : ‖x⋆ * x‖ = ‖x‖ * ‖x‖ :=
le_antisymm ((norm_mul_le _ _).trans (by rw [norm_star])) (CStarRing.norm_mul_self_le x)
```

-- snippet 38
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.tendsto_mul_left_iff_tendsto_mul_right (L186-L196)
lemma tendsto_mul_left_iff_tendsto_mul_right {l : Filter A} (hl : ∀ᶠ x in l, IsSelfAdjoint x) :
    (∀ m, Tendsto (m * ·) l (𝓝 m)) ↔ (∀ m, Tendsto (· * m) l (𝓝 m)) := by
refine ⟨fun h m ↦ ?_, fun h m ↦ ?_⟩
  all_goals
    apply (star_star m ▸ (continuous_star.tendsto _ |>.comp <| h (star m))).congr'
    filter_upwards [hl] with x hx
    simp [hx.star_eq]

variable (A)

/-- The sections of positive strict contractions form a filter basis. -/
```

-- snippet 39
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.approximateUnit (L206-L210)
def approximateUnit : Filter A :=
(isBasis_nonneg_sections A).filter ⊓ 𝓟 (closedBall 0 1)

/-- The canonical approximate unit in a C⋆-algebra has a basis of sets
`{x | a ≤ x} ∩ closedBall 0 1` for `0 ≤ a`. -/
```

-- snippet 40
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.CFC (L54-L72)
lemma CFC.monotoneOn_one_sub_one_add_inv :
    MonotoneOn (cfcₙ (fun x : ℝ≥0 ↦ 1 - (1 + x)⁻¹)) (Set.Ici (0 : A)) := by
intro a ha b hb hab
  simp only [Set.mem_Ici] at ha hb
  rw [← inr_le_iff .., nnreal_cfcₙ_eq_cfc_inr a _, nnreal_cfcₙ_eq_cfc_inr b _]
  rw [← inr_le_iff a b (.of_nonneg ha) (.of_nonneg hb)] at hab
  rw [← inr_nonneg_iff] at ha hb
  have h_cfc_one_sub (c : A⁺¹) (hc : 0 ≤ c := by cfc_tac) :
      cfc (fun x : ℝ≥0 ↦ 1 - (1 + x)⁻¹) c = 1 - cfc (·⁻¹ : ℝ≥0 → ℝ≥0) (1 + c) := by
    rw [cfc_tsub _ _ _ (fun x _ ↦ by simp) (hg := by fun_prop (disch := intro _ _; positivity)),
      cfc_const_one ℝ≥0 c, cfc_comp' (·⁻¹) (1 + ·) c ?_, cfc_add .., cfc_const_one ℝ≥0 c,
      cfc_id' ℝ≥0 c]
    exact continuousOn_id.inv₀ (Set.forall_mem_image.mpr fun x _ ↦ by dsimp only [id]; positivity)
  rw [h_cfc_one_sub (a : A⁺¹), h_cfc_one_sub (b : A⁺¹)]
  gcongr
  rw [← CFC.rpow_neg_one_eq_cfc_inv, ← CFC.rpow_neg_one_eq_cfc_inv]
  exact rpow_neg_one_le_rpow_neg_one (by gcongr)

set_option backward.isDefEq.respectTransparency false in
```

<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.CStarAlgebra.ContinuousFunctionalCalculus.Unital).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
lemma cfcHom_id :
    cfcHom ha ((ContinuousMap.id R).restrict <| spectrum R a) = a
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.is (L50-L142)
theorem is nearly impossible to state nicely in terms of `cfcHom` (see `cfcHom_comp`). An
additional advantage of the unbundled approach is that expressions like `fun x : R ↦ x⁻¹` are valid
arguments to `cfc`, and a bundled continuous counterpart can only make sense when the spectrum of
`a` does not contain zero and when we have an `⁻¹` operation on the domain.

A reader familiar with C⋆-algebra theory may be somewhat surprised at the level of abstraction here.
For instance, why not require `A` to be an actual C⋆-algebra? Why define separate continuous
functional calculi for `R := ℂ`, `ℝ` or `ℝ≥0` instead of simply using the continuous functional
calculus for normal elements? The reason for both can be explained with a simple example,
`A := Matrix n n ℝ`. In Mathlib, matrices are not equipped with a norm (nor even a metric), and so
requiring `A` to be a C⋆-algebra is far too stringent. Likewise, `A` is not a `ℂ`-algebra, and so
it is impossible to consider the `ℂ`-spectrum of `a : Matrix n n ℝ`.

There is another, more practical reason to define separate continuous functional calculi for
different scalar rings. It gives us the ability to use functions defined on these types, and the
algebra of functions on them. For example, for `R := ℝ` it is quite natural to consider the
functions `(·⁺ : ℝ → ℝ)` and `(·⁻ : ℝ → ℝ)` because the functions `ℝ → ℝ` form a lattice ordered
group. If `a : A` is selfadjoint, and we define `a⁺ := cfc (·⁺ : ℝ → ℝ) a`, and likewise for `a⁻`,
then the properties `a⁺ * a⁻ = 0 = a⁻ * a⁺` and `a = a⁺ - a⁻` are trivial consequences of the
corresponding facts for functions. In contrast, if we had to do this using functions on `ℂ`, the
proofs of these facts would be much more cumbersome.

## Example

The canonical example of the continuous functional calculus is when `A := Matrix n n ℂ`, `R := ℂ`
and `p := IsStarNormal`. In this case, `spectrum ℂ a` consists of the eigenvalues of the normal
matrix `a : Matrix n n ℂ`, and, because this set is discrete, any function is continuous on the
spectrum. The continuous functional calculus allows us to make sense of expressions like `log a`
(`:= cfc log a`), and when `0 ∉ spectrum ℂ a`, we get the nice property `exp (log a) = a`, which
arises from the composition property `cfc exp (cfc log a) = cfc (exp ∘ log) a = cfc id a = a`, since
`exp ∘ log = id` *on the spectrum of `a`*. Of course, there are other ways to make sense of `exp`
and `log` for matrices (power series), and these agree with the continuous functional calculus.
In fact, given `f : C(spectrum ℂ a, ℂ)`, `cfc f a` amounts to diagonalizing `a` (possible since `a`
is normal), and applying `f` to the resulting diagonal entries. That is, if `a = u * d * star u`
with `u` a unitary matrix and `d` diagonal, then `cfc f a = u * d.map f * star u`.

In addition, if `a : Matrix n n ℂ` is positive semidefinite, then the `ℂ`-spectrum of `a` is
contained in (the range of the coercion of) `ℝ≥0`. In this case, we get a continuous functional
calculus with `R := ℝ≥0`. From this we can define `√a := cfc a NNReal.sqrt`, which is also
positive semidefinite (because `cfc` preserves the predicate), and this is truly a square root since
```
√a * √a = cfc NNReal.sqrt a * cfc NNReal.sqrt a =
  cfc (NNReal.sqrt ^ 2) a = cfc id a = a
```
The composition property allows us to show that, in fact, this is the *unique* positive semidefinite
square root of `a` because, if `b` is any positive semidefinite square root, then
```
b = cfc id b = cfc (NNReal.sqrt ∘ (· ^ 2)) b =
  cfc NNReal.sqrt (cfc b (· ^ 2)) = cfc NNReal.sqrt a = √a
```

## Main declarations

+ `ContinuousFunctionalCalculus R A (p : A → Prop)`: a class stating that every `a : A` satisfying
  `p a` has a star algebra homomorphism from the continuous `R`-valued functions on the
  `R`-spectrum of `a` into the algebra `A`. This map is a closed embedding, and satisfies the
  **spectral mapping theorem**.
+ `cfcHom : p a → C(spectrum R a, R) →⋆ₐ[R] A`: the underlying star algebra homomorphism for an
  element satisfying property `p`.
+ `cfc : (R → R) → A → A`: an unbundled version of `cfcHom` which takes the junk value `0` when
  `cfcHom` is not defined.
+ `cfcUnits`: builds a unit from `cfc f a` when `f` is nonzero and continuous on the
  spectrum of `a`.

## Main theorems

+ `cfc_comp : cfc (x ↦ g (f x)) a = cfc g (cfc f a)`
+ `cfc_polynomial`: the continuous functional calculus extends the polynomial functional calculus.

## Implementation details

Instead of defining a class depending on a term `a : A`, we register it for an `outParam` predicate
`p : A → Prop`, and then any element of `A` satisfying this predicate has the associated star
algebra homomorphism with the specified properties. In so doing we avoid a common pitfall:
dependence of the class on a term. This avoids annoying situations where `a b : A` are
propositionally equal, but not definitionally so, and hence Lean would not be able to automatically
identify the continuous functional calculi associated to these elements. In order to guarantee
the necessary properties, we require that the continuous functional calculus preserves this
predicate. That is, `p a → p (cfc f a)` for any function `f` continuous on the spectrum of `a`.

As stated above, the unbundled approach to `cfc` has its advantages. For instance, given an
expression `cfc f a`, the user is free to rewrite either `a` or `f` as desired with no possibility
of the expression ceasing to be defined. However, this unbundling also has some potential downsides.
In particular, by unbundling, proof requirements are deferred until the user calls the lemmas, most
of which have hypotheses both of `p a` and of `ContinuousOn f (spectrum R a)`.

In order to minimize burden to the user, we provide `autoParams` in terms of two tactics. Goals
related to continuity are dispatched by (a small wrapper around) `fun_prop`. As for goals involving
the predicate `p`, it should be noted that these will only ever be of the form `IsStarNormal a`,
`IsSelfAdjoint a` or `0 ≤ a`. For the moment we provide a rudimentary tactic to deal with these
goals, but it can be modified to become more sophisticated as the need arises.
-/
```

-- snippet 2
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.ContinuousFunctionalCalculus (L210-L213)
lemma ContinuousFunctionalCalculus.isCompact_spectrum (a : A) :
    IsCompact (spectrum R a) :=
isCompact_iff_compactSpace.mpr inferInstance
```

-- snippet 3
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.StarAlgHom (L214-L241)
lemma StarAlgHom.ext_continuousMap [UniqueHom R A]
    (a : A) [CompactSpace (spectrum R a)] (φ ψ : C(spectrum R a, R) →⋆ₐ[R] A)
    (hφ : Continuous φ) (hψ : Continuous ψ)
    (h : φ (.restrict (spectrum R a) <| .id R) = ψ (.restrict (spectrum R a) <| .id R)) :
    φ = ψ :=
UniqueHom.eq_of_continuous_of_map_id (spectrum R a) φ ψ hφ hψ h

section cfcHom

variable {a : A} (ha : p a)

-- Note: since `spectrum R a` is closed, we may always extend `f : C(spectrum R a, R)` to a function
-- of type `C(R, R)` by the Tietze extension theorem (assuming `R` is either `ℝ`, `ℂ` or `ℝ≥0`).

/-- The star algebra homomorphism underlying an instance of the continuous functional calculus;
a version for continuous functions on the spectrum.

In this case, the user must supply the fact that `a` satisfies the predicate `p`, for otherwise it
may be the case that no star algebra homomorphism exists. For instance if `R := ℝ` and `a` is an
element whose spectrum (in `ℂ`) is disjoint from `ℝ`, then `spectrum ℝ a = ∅` and so there can be
no star algebra homomorphism between these spaces.

While `ContinuousFunctionalCalculus` is stated in terms of these homomorphisms, in practice the
user should instead prefer `cfc` over `cfcHom`.
-/
noncomputable def cfcHom : C(spectrum R a, R) →⋆ₐ[R] A :=
  (ContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose
```

-- snippet 4
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_continuous (L243-L245)
lemma cfcHom_continuous : Continuous (cfcHom ha : C(spectrum R a, R) →⋆ₐ[R] A) :=
(ContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose_spec.1
```

-- snippet 5
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_injective (L246-L248)
lemma cfcHom_injective : Function.Injective (cfcHom ha : C(spectrum R a, R) →⋆ₐ[R] A) :=
(ContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose_spec.2.1
```

-- snippet 6
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_map_spectrum (L254-L257)
lemma cfcHom_map_spectrum (f : C(spectrum R a, R)) :
    spectrum R (cfcHom ha f) = Set.range f :=
(ContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose_spec.2.2.2.1 f
```

-- snippet 7
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_predicate (L258-L262)
lemma cfcHom_predicate (f : C(spectrum R a, R)) :
    p (cfcHom ha f) :=
(ContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose_spec.2.2.2.2 f

open scoped ContinuousFunctionalCalculus in
```

-- snippet 8
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_eq_of_continuous_of_map_id (L263-L268)
lemma cfcHom_eq_of_continuous_of_map_id [UniqueHom R A]
    (φ : C(spectrum R a, R) →⋆ₐ[R] A) (hφ₁ : Continuous φ)
    (hφ₂ : φ (.restrict (spectrum R a) <| .id R) = a) : cfcHom ha = φ :=
(cfcHom ha).ext_continuousMap a φ (cfcHom_continuous ha) hφ₁ <| by
    rw [cfcHom_id ha, hφ₂]
```

-- snippet 9
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_comp (L269-L287)
theorem cfcHom_comp [UniqueHom R A] (f : C(spectrum R a, R))
    (f' : C(spectrum R a, spectrum R (cfcHom ha f)))
    (hff' : ∀ x, f x = f' x) (g : C(spectrum R (cfcHom ha f), R)) :
    cfcHom ha (g.comp f') = cfcHom (cfcHom_predicate ha f) g := by
let φ : C(spectrum R (cfcHom ha f), R) →⋆ₐ[R] A :=
    (cfcHom ha).comp <| ContinuousMap.compStarAlgHom' R R f'
  suffices cfcHom (cfcHom_predicate ha f) = φ from DFunLike.congr_fun this.symm g
  refine cfcHom_eq_of_continuous_of_map_id (cfcHom_predicate ha f) φ ?_ ?_
  · exact cfcHom_continuous ha |>.comp f'.continuous_precomp
  · simp only [φ, StarAlgHom.comp_apply, ContinuousMap.compStarAlgHom'_apply]
    congr
    ext x
    simp [hff']

end cfcHom

section cfcL

/-- `cfcHom` bundled as a continuous linear map. -/
```

-- snippet 10
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfc_apply (L318-L320)
lemma cfc_apply : cfc f a = cfcHom (a := a) ha ⟨_, hf.restrict⟩ := by
rw [cfc_def, dif_pos ⟨ha, hf⟩]
```

-- snippet 11
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfc_apply_pi (L321-L326)
lemma cfc_apply_pi {ι : Type*} (f : ι → R → R) (a : A) (ha : p a := by cfc_tac)
(hf : ∀ i, ContinuousOn (f i) (spectrum R a) := by cfc_cont_tac) :
    (fun i => cfc (f i) a) = (fun i => cfcHom (a := a) ha ⟨_, (hf i).restrict⟩) := by
  ext i
  simp only [cfc_apply (f i) a ha (hf i)]
```

-- snippet 12
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfc_apply_of_not_and (L327-L330)
lemma cfc_apply_of_not_and {f : R → R} (a : A) (ha : ¬ (p a ∧ ContinuousOn f (spectrum R a))) :
    cfc f a = 0 := by
rw [cfc_def, dif_neg ha]
```

-- snippet 13
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfc_apply_of_not_predicate (L331-L334)
lemma cfc_apply_of_not_predicate {f : R → R} (a : A) (ha : ¬ p a) :
    cfc f a = 0 := by
rw [cfc_def, dif_neg (not_and_of_not_left _ ha)]
```

-- snippet 14
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfc_apply_of_not_continuousOn (L335-L338)
lemma cfc_apply_of_not_continuousOn {f : R → R} (a : A) (hf : ¬ ContinuousOn f (spectrum R a)) :
    cfc f a = 0 := by
rw [cfc_def, dif_neg (not_and_of_not_right _ hf)]
```

-- snippet 15
```lean
-- Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital.cfcHom_eq_cfc_extend (L339-L347)
lemma cfcHom_eq_cfc_extend {a : A} (g : R → R) (ha : p a) (f : C(spectrum R a, R)) :
    cfcHom ha f = cfc (Function.extend Subtype.val f g) a := by
have h : f = (spectrum R a).restrict (Function.extend Subtype.val f g) := by
    ext; simp
  have hg : ContinuousOn (Function.extend Subtype.val f g) (spectrum R a) :=
    continuousOn_iff_continuous_restrict.mpr <| h ▸ map_continuous f
  rw [cfc_apply ..]
  congr!
```

-- snippet 16
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.nnnorm_star (L60-L63)
theorem nnnorm_star (x : E) : ‖star x‖₊ = ‖x‖₊ :=
Subtype.ext <| norm_star _

/-- The `star` map in a normed star group is a normed group homomorphism. -/
```

-- snippet 17
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.norm_star (L56-L58)
lemma norm_star (x : E) : ‖x⋆‖ = ‖x‖ :=
le_antisymm (NormedStarGroup.norm_star_le x) (by simpa using NormedStarGroup.norm_star_le x⋆)
```

-- snippet 18
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.eventually_star_eq (L161-L171)
lemma eventually_star_eq {l : Filter A} (hl : l.IsIncreasingApproximateUnit) :
    ∀ᶠ x in l, star x = x :=
hl.eventually_isSelfAdjoint.mp <| .of_forall fun _ ↦ IsSelfAdjoint.star_eq

end Filter.IsIncreasingApproximateUnit

namespace CStarAlgebra

open Submodule in
/-- To show that `l` is a one-sided approximate unit for `A`, it suffices to verify it only for
`m : A` with `0 ≤ m` and `‖m‖ < 1`. -/
```

-- snippet 19
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.hasBasis_approximateUnit (L211-L218)
lemma hasBasis_approximateUnit :
    (approximateUnit A).HasBasis (fun x : A ↦ 0 ≤ x ∧ ‖x‖ < 1) ({x | · ≤ x} ∩ closedBall 0 1) :=
isBasis_nonneg_sections A |>.hasBasis.inf_principal (closedBall 0 1)

/-- This is a common reasoning sequence in C⋆-algebra theory. If `0 ≤ x ≤ y ≤ 1`, then the norm of
`z - y * z` is controlled by the norm of `star z * (1 - x) * z`, which is advantageous because the
latter is nonnegative. This is a key step in establishing the existence of an increasing approximate
unit in general C⋆-algebras. -/
```

-- snippet 20
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.star_isometry (L68-L71)
theorem star_isometry : Isometry (star : E → E) :=
show Isometry starAddEquiv from
    AddMonoidHomClass.isometry_of_norm starAddEquiv (show ∀ x, ‖x⋆‖ = ‖x‖ from norm_star)
```

-- snippet 21
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.eventually_isSelfAdjoint (L157-L160)
lemma eventually_isSelfAdjoint {l : Filter A} (hl : l.IsIncreasingApproximateUnit) :
    ∀ᶠ x in l, IsSelfAdjoint x :=
hl.eventually_nonneg.mp <| .of_forall fun _ ↦ IsSelfAdjoint.of_nonneg
```

-- snippet 22
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.increasingApproximateUnit (L314-L331)
lemma increasingApproximateUnit :
    IsIncreasingApproximateUnit (approximateUnit A) where
  tendsto_mul_left := by
rw [tendsto_mul_left_iff_tendsto_mul_right]
    · exact tendsto_mul_right_approximateUnit
    · rw [(hasBasis_approximateUnit A).eventually_iff]
      peel (hasBasis_approximateUnit A).ex_mem with x hx
      exact ⟨hx, fun y hy ↦ (hx.1.trans hy.1).isSelfAdjoint⟩
  tendsto_mul_right := tendsto_mul_right_approximateUnit
  eventually_nonneg := .filter_mono inf_le_left <|
    (isBasis_nonneg_sections A).hasBasis.eventually_iff.mpr ⟨0, by simp⟩
  eventually_norm := .filter_mono inf_le_right <| by simp
  neBot := hasBasis_approximateUnit A |>.neBot_iff.mpr
    fun hx ↦ ⟨_, ⟨le_rfl, by simpa using hx.2.le⟩⟩

end CStarAlgebra

end ApproximateUnit
```

-- snippet 23
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.norm_self_mul_star (L125-L128)
theorem norm_self_mul_star {x : E} : ‖x * x⋆‖ = ‖x‖ * ‖x‖ := by
nth_rw 1 [← star_star x]
  simp only [norm_star_mul_self, norm_star]
```

-- snippet 24
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.RingHomIsometric (L82-L91)
instance RingHomIsometric.starRingEnd [NormedCommRing E] [StarRing E] [NormedStarGroup E] :
    RingHomIsometric (starRingEnd E) :=
⟨@norm_star _ _ _ _⟩

/-- A C*-ring is a normed star ring that satisfies the stronger condition `‖x‖ ^ 2 ≤ ‖x⋆ * x‖`
for every `x`. Note that this condition actually implies equality, as is shown in
`norm_star_mul_self` below. -/
class CStarRing (E : Type*) [NonUnitalNormedRing E] [StarRing E] : Prop where
  norm_mul_self_le : ∀ x : E, ‖x‖ * ‖x‖ ≤ ‖x⋆ * x‖
```

-- snippet 25
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.isBasis_nonneg_sections (L197-L205)
lemma isBasis_nonneg_sections :
    IsBasis (fun x : A ↦ 0 ≤ x ∧ ‖x‖ < 1) ({x | · ≤ x}) where
  nonempty := ⟨0, by simp⟩
inter {x y} hx hy := by
    peel directedOn_nonneg_ball x (by simpa) y (by simpa) with z hz
    exact ⟨by simpa using hz.1, fun a ha ↦ ⟨hz.2.1.trans ha, hz.2.2.trans ha⟩⟩

/-- The canonical approximate unit in a C⋆-algebra generated by the basis of sets
`{x | a ≤ x} ∩ closedBall 0 1` for `0 ≤ a`. See also `CStarAlgebra.hasBasis_approximateUnit`. -/
```

-- snippet 26
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.norm_sub_mul_self_le_of_inr (L246-L313)
lemma norm_sub_mul_self_le_of_inr {x y : A} (z : A) (hx₀ : 0 ≤ x) (hxy : x ≤ y) (hy₁ : ‖y‖ ≤ 1)
    {c : ℝ} (hc : 0 ≤ c) (h : ‖star (z : A⁺¹) * (1 - x) * z‖ ≤ c ^ 2) :
    ‖z - y * z‖ ≤ c := by
rw [← norm_inr (𝕜 := ℂ), inr_sub, inr_mul]
  refine norm_sub_mul_self_le _ ?_ ?_ hc h
  · rwa [inr_nonneg_iff]
  · have hy := hx₀.trans hxy
    rw [Set.mem_Icc, inr_le_iff _ _ hx₀.isSelfAdjoint hy.isSelfAdjoint,
      ← norm_le_one_iff_of_nonneg _, norm_inr]
    exact ⟨hxy, hy₁⟩

set_option backward.isDefEq.respectTransparency false in
variable {A} in
/-- This shows `CStarAlgebra.approximateUnit` is a one-sided approximate unit, but this is marked
`private` because it is only used to prove `CStarAlgebra.increasingApproximateUnit`. -/
private lemma tendsto_mul_right_approximateUnit (m : A) :
    Tendsto (· * m) (approximateUnit A) (𝓝 m) := by
  refine tendsto_mul_right_of_forall_nonneg_tendsto (fun m hm₁ hm₂ ↦ ?_) m
  rw [(hasBasis_approximateUnit A).tendsto_iff nhds_basis_closedBall]
  intro ε hε
  lift ε to ℝ≥0 using hε.le
  rw [coe_pos] at hε
  refine ⟨cfcₙ (fun y : ℝ≥0 ↦ 1 - (1 + y)⁻¹) (ε⁻¹ ^ 2 • m),
    ⟨cfcₙ_nonneg_of_predicate, norm_cfcₙ_one_sub_one_add_inv_lt_one (ε⁻¹ ^ 2 • m)⟩, ?_⟩
  rintro x ⟨(hx₁ : _ ≤ x), hx₂⟩
  simp only [mem_closedBall, dist_eq_norm', zero_sub, norm_neg] at hx₂ ⊢
  rw [← coe_nnnorm, coe_le_coe]
  have hx₀ : 0 ≤ x := cfcₙ_nonneg_of_predicate.trans hx₁
  rw [← inr_le_iff _ _ (.of_nonneg cfcₙ_nonneg_of_predicate) (.of_nonneg hx₀),
    nnreal_cfcₙ_eq_cfc_inr _ _ (by simp [tsub_self]), inr_smul] at hx₁
  rw [← norm_inr (𝕜 := ℂ)] at hm₂ hx₂
  rw [← inr_nonneg_iff] at hx₀ hm₁
  rw [← nnnorm_inr (𝕜 := ℂ), inr_sub, inr_mul]
  generalize (x : A⁺¹) = x, (m : A⁺¹) = m at *
  set g : ℝ≥0 → ℝ≥0 := fun y ↦ 1 - (1 + y)⁻¹
  have hg : Continuous g := by
    rw [← continuousOn_univ]
    fun_prop (disch := intro _ _; positivity)
  have hg' : ContinuousOn (fun y ↦ (1 + ε⁻¹ ^ 2 • y)⁻¹) (spectrum ℝ≥0 m) :=
    ContinuousOn.inv₀ (by fun_prop) fun _ _ ↦ by positivity
  have hx : x ∈ Set.Icc 0 1 := mem_Icc_iff_norm_le_one.mpr ⟨hx₀, hx₂⟩
  have hx' : x ∈ Set.Icc _ 1 := ⟨hx₁, hx.2⟩
  refine nnnorm_sub_mul_self_le m cfc_nonneg_of_predicate hx' ?_
  suffices star m * (1 - cfc g (ε⁻¹ ^ 2 • m)) * m =
      cfc (fun y : ℝ≥0 ↦ y * (1 + ε⁻¹ ^ 2 • y)⁻¹ * y) m by
    rw [this]
    refine nnnorm_cfc_nnreal_le fun y hy ↦ ?_
    calc
      y * (1 + ε⁻¹ ^ 2 • y)⁻¹ * y = y * ε ^ 2 * (y / (ε ^ 2 + y)) := by simp [field]
      _ ≤ ε ^ 2 * 1 := by
        gcongr
        · refine mul_le_of_le_one_left (zero_le _) ?_
          have hm' := hm₂.le
          rw [norm_le_one_iff_of_nonneg m hm₁, ← cfc_id' ℝ≥0 m, ← cfc_one (R := ℝ≥0) m,
            cfc_nnreal_le_iff _ _ _ (QuasispectrumRestricts.nnreal_of_nonneg hm₁)] at hm'
          exact hm' y hy
        · exact div_le_one (by positivity) |>.mpr le_add_self
      _ = ε ^ 2 := mul_one _
  rw [cfc_mul _ _ m (continuousOn_id' _ |>.fun_mul hg') (continuousOn_id' _),
    cfc_mul _ _ m (continuousOn_id' _) hg', cfc_id' .., hm₁.star_eq]
  congr
  rw [← cfc_one (R := ℝ≥0) m, ← cfc_comp_smul _ _ _ hg.continuousOn hm₁,
    ← cfc_tsub _ _ m (by simp [g]) hm₁ (by fun_prop) (Continuous.continuousOn <| by fun_prop)]
  refine cfc_congr (fun y _ ↦ ?_)
  simp [g, tsub_tsub_cancel_of_le]

/-- The filter `CStarAlgebra.approximateUnit` generated by the sections
`{x | a ≤ x} ∩ closedBall 0 1` for `0 ≤ a` forms an increasing approximate unit. -/
```

-- snippet 27
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.starNormedAddGroupHom (L64-L67)
def starNormedAddGroupHom : NormedAddGroupHom E E :=
{ starAddEquiv with bound' := ⟨1, fun _ => le_trans (norm_star _).le (one_mul _).symm.le⟩ }

/-- The `star` map in a normed star group is an isometry -/
```

-- snippet 28
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.of_le_norm_mul_star_self (L100-L114)
lemma of_le_norm_mul_star_self
    [NonUnitalNormedRing E] [StarRing E]
    (h : ∀ x : E, ‖x‖ * ‖x‖ ≤ ‖x * x⋆‖) : CStarRing E :=
have : NormedStarGroup E :=
    { norm_star_le x := by
        obtain (hx | hx) := eq_zero_or_norm_pos x⋆
        · simp [hx]
        · refine le_of_mul_le_mul_right ?_ hx
          simpa [sq, mul_comm ‖x⋆‖] using h x⋆ |>.trans <| norm_mul_le _ _ }
  ⟨star_involutive.surjective.forall.mpr <| by simpa⟩

variable [NonUnitalNormedRing E] [StarRing E] [CStarRing E]

-- see Note [lower instance priority]
/-- In a C*-ring, star preserves the norm. -/
```

-- snippet 29
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.nnnorm_sub_mul_self_le (L219-L237)
lemma nnnorm_sub_mul_self_le {A : Type*} [CStarAlgebra A] [PartialOrder A] [StarOrderedRing A]
    {x y : A} (z : A) (hx₀ : 0 ≤ x) (hy : y ∈ Set.Icc x 1) {c : ℝ≥0}
    (h : ‖star z * (1 - x) * z‖₊ ≤ c ^ 2) :
    ‖z - y * z‖₊ ≤ c := by
nth_rw 1 [← one_mul z]
  rw [← sqrt_sq c, le_sqrt_iff_sq_le, ← sub_mul, sq, ← CStarRing.nnnorm_star_mul_self]
  simp only [star_mul, star_sub, star_one]
  have hy₀ : y ∈ Set.Icc 0 1 := ⟨hx₀.trans hy.1, hy.2⟩
  have hy' : 1 - y ∈ Set.Icc 0 1 := Set.sub_mem_Icc_zero_iff_right.mpr hy₀
  rw [hy₀.1.star_eq, ← mul_assoc, mul_assoc (star _), ← sq]
  refine nnnorm_le_nnnorm_of_nonneg_of_le (star_left_conjugate_nonneg (pow_nonneg hy'.1 2) _) ?_
    |>.trans h
  refine star_left_conjugate_le_conjugate ?_ _
  trans (1 - y)
  · simpa using pow_antitone hy'.1 hy'.2 one_le_two
  · gcongr
    exact hy.1

/-- A variant of `nnnorm_sub_mul_self_le` which uses `‖·‖` instead of `‖·‖₊`. -/
```

-- snippet 30
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.Set (L91-L104)
lemma Set.InvOn.one_sub_one_add_inv : Set.InvOn (fun x ↦ 1 - (1 + x)⁻¹) (fun x ↦ x * (1 - x)⁻¹)
    {x : ℝ≥0 | x < 1} {x : ℝ≥0 | x < 1} := by
have : (fun x : ℝ≥0 ↦ x * (1 + x)⁻¹) = fun x ↦ 1 - (1 + x)⁻¹ := by
    ext x : 1
    simp [field, mul_tsub]
  rw [← this]
  constructor <;> intro x (hx : x < 1)
  · have : 0 < 1 - x := tsub_pos_of_lt hx
    simp [field, tsub_add_cancel_of_le hx.le]
  · simp [mul_assoc, ← mul_inv, mul_tsub]
    field_simp
    simp

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 31
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.CStarAlgebra (L110-L152)
lemma CStarAlgebra.directedOn_nonneg_ball :
    DirectedOn (· ≤ ·) ({x : A | 0 ≤ x} ∩ Metric.ball 0 1) := by
let f : ℝ≥0 → ℝ≥0 := fun x => 1 - (1 + x)⁻¹
  let g : ℝ≥0 → ℝ≥0 := fun x => x * (1 - x)⁻¹
  suffices ∀ a b : A, 0 ≤ a → 0 ≤ b → ‖a‖ < 1 → ‖b‖ < 1 →
      a ≤ cfcₙ f (cfcₙ g a + cfcₙ g b) by
    rintro a ⟨(ha₁ : 0 ≤ a), ha₂⟩ b ⟨(hb₁ : 0 ≤ b), hb₂⟩
    simp only [Metric.mem_ball, dist_zero_right] at ha₂ hb₂
    refine ⟨cfcₙ f (cfcₙ g a + cfcₙ g b), ⟨by simp, ?_⟩, ?_, ?_⟩
    · simpa only [Metric.mem_ball, dist_zero_right] using norm_cfcₙ_one_sub_one_add_inv_lt_one _
    · exact this a b ha₁ hb₁ ha₂ hb₂
    · exact add_comm (cfcₙ g a) (cfcₙ g b) ▸ this b a hb₁ ha₁ hb₂ ha₂
  rintro a b ha₁ - ha₂ -
  calc
    a = cfcₙ (f ∘ g) a := by
      conv_lhs => rw [← cfcₙ_id ℝ≥0 a]
      refine cfcₙ_congr (Set.InvOn.one_sub_one_add_inv.1.eqOn.symm.mono fun x hx ↦ ?_)
      exact lt_of_le_of_lt (le_nnnorm_of_mem_quasispectrum hx) ha₂
    _ = cfcₙ f (cfcₙ g a) := by
      rw [cfcₙ_comp f g a ?_ (by simp [f, tsub_self]) ?_ (by simp [g]) ha₁]
      · fun_prop (disch := intro _ _; positivity)
      · have (x) (hx : x ∈ σₙ ℝ≥0 a) : 1 - x ≠ 0 := by
          refine tsub_pos_of_lt ?_ |>.ne'
          exact lt_of_le_of_lt (le_nnnorm_of_mem_quasispectrum hx) ha₂
        fun_prop (disch := assumption)
    _ ≤ cfcₙ f (cfcₙ g a + cfcₙ g b) := by
      have hab' : cfcₙ g a ≤ cfcₙ g a + cfcₙ g b := le_add_of_nonneg_right cfcₙ_nonneg_of_predicate
      exact CFC.monotoneOn_one_sub_one_add_inv cfcₙ_nonneg_of_predicate
        (cfcₙ_nonneg_of_predicate.trans hab') hab'

section ApproximateUnit

open Metric Filter Topology

/-- An *increasing approximate unit* in a C⋆-algebra is an approximate unit contained in the
closed unit ball of nonnegative elements. -/
structure Filter.IsIncreasingApproximateUnit (l : Filter A) : Prop extends l.IsApproximateUnit where
  eventually_nonneg : ∀ᶠ x in l, 0 ≤ x
  eventually_norm : ∀ᶠ x in l, ‖x‖ ≤ 1

namespace Filter.IsIncreasingApproximateUnit

omit [StarOrderedRing A] in
```

-- snippet 32
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.norm_cfcₙ_one_sub_one_add_inv_lt_one (L105-L109)
lemma norm_cfcₙ_one_sub_one_add_inv_lt_one (a : A) :
    ‖cfcₙ (fun x : ℝ≥0 ↦ 1 - (1 + x)⁻¹) a‖ < 1 :=
nnnorm_cfcₙ_nnreal_lt fun x _ ↦ tsub_lt_self zero_lt_one (by positivity)

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 33
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.tendsto_mul_right_of_forall_nonneg_tendsto (L172-L185)
lemma tendsto_mul_right_of_forall_nonneg_tendsto {l : Filter A}
    (h : ∀ m, 0 ≤ m → ‖m‖ < 1 → Tendsto (· * m) l (𝓝 m)) (m : A) :
    Tendsto (· * m) l (𝓝 m) := by
obtain ⟨n, c, x, rfl⟩ := mem_span_set'.mp <| by
    change m ∈ span ℂ ({x | 0 ≤ x} ∩ ball 0 1)
    simp [span_nonneg_inter_unitBall]
  simp_rw [Finset.mul_sum]
  refine tendsto_finset_sum _ fun i _ ↦ ?_
  simp_rw [mul_smul_comm]
  exact tendsto_const_nhds.smul <| h (x i) (x i).2.1 <| by simpa using (x i).2.2

omit [PartialOrder A] in
/-- Multiplication on the left by `m` tends to `𝓝 m` if and only if multiplication on the right
does, provided the elements are eventually selfadjoint along the filter `l`. -/
```

-- snippet 34
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.norm_star_mul_self' (L129-L130)
theorem norm_star_mul_self' {x : E} : ‖x⋆ * x‖ = ‖x⋆‖ * ‖x‖ := by rw [norm_star_mul_self, norm_star]
```

-- snippet 35
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.eventually_nnnorm (L153-L156)
lemma eventually_nnnorm {l : Filter A} (hl : l.IsIncreasingApproximateUnit) :
    ∀ᶠ x in l, ‖x‖₊ ≤ 1 :=
hl.eventually_norm
```

-- snippet 36
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.norm_sub_mul_self_le (L238-L245)
lemma norm_sub_mul_self_le {A : Type*} [CStarAlgebra A] [PartialOrder A] [StarOrderedRing A]
    {x y : A} (z : A) (hx₀ : 0 ≤ x) (hy : y ∈ Set.Icc x 1)
    {c : ℝ} (hc : 0 ≤ c) (h : ‖star z * (1 - x) * z‖ ≤ c ^ 2) :
    ‖z - y * z‖ ≤ c :=
nnnorm_sub_mul_self_le z hx₀ hy h (c := ⟨c, hc⟩)

variable {A} in
/-- A variant of `norm_sub_mul_self_le` for non-unital algebras that passes to the unitization. -/
```

-- snippet 37
```lean
-- Mathlib.Analysis.CStarAlgebra.Basic.norm_star_mul_self (L122-L124)
theorem norm_star_mul_self {x : E} : ‖x⋆ * x‖ = ‖x‖ * ‖x‖ :=
le_antisymm ((norm_mul_le _ _).trans (by rw [norm_star])) (CStarRing.norm_mul_self_le x)
```

-- snippet 38
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.tendsto_mul_left_iff_tendsto_mul_right (L186-L196)
lemma tendsto_mul_left_iff_tendsto_mul_right {l : Filter A} (hl : ∀ᶠ x in l, IsSelfAdjoint x) :
    (∀ m, Tendsto (m * ·) l (𝓝 m)) ↔ (∀ m, Tendsto (· * m) l (𝓝 m)) := by
refine ⟨fun h m ↦ ?_, fun h m ↦ ?_⟩
  all_goals
    apply (star_star m ▸ (continuous_star.tendsto _ |>.comp <| h (star m))).congr'
    filter_upwards [hl] with x hx
    simp [hx.star_eq]

variable (A)

/-- The sections of positive strict contractions form a filter basis. -/
```

-- snippet 39
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.approximateUnit (L206-L210)
def approximateUnit : Filter A :=
(isBasis_nonneg_sections A).filter ⊓ 𝓟 (closedBall 0 1)

/-- The canonical approximate unit in a C⋆-algebra has a basis of sets
`{x | a ≤ x} ∩ closedBall 0 1` for `0 ≤ a`. -/
```

-- snippet 40
```lean
-- Mathlib.Analysis.CStarAlgebra.ApproximateUnit.CFC (L54-L72)
lemma CFC.monotoneOn_one_sub_one_add_inv :
    MonotoneOn (cfcₙ (fun x : ℝ≥0 ↦ 1 - (1 + x)⁻¹)) (Set.Ici (0 : A)) := by
intro a ha b hb hab
  simp only [Set.mem_Ici] at ha hb
  rw [← inr_le_iff .., nnreal_cfcₙ_eq_cfc_inr a _, nnreal_cfcₙ_eq_cfc_inr b _]
  rw [← inr_le_iff a b (.of_nonneg ha) (.of_nonneg hb)] at hab
  rw [← inr_nonneg_iff] at ha hb
  have h_cfc_one_sub (c : A⁺¹) (hc : 0 ≤ c := by cfc_tac) :
      cfc (fun x : ℝ≥0 ↦ 1 - (1 + x)⁻¹) c = 1 - cfc (·⁻¹ : ℝ≥0 → ℝ≥0) (1 + c) := by
    rw [cfc_tsub _ _ _ (fun x _ ↦ by simp) (hg := by fun_prop (disch := intro _ _; positivity)),
      cfc_const_one ℝ≥0 c, cfc_comp' (·⁻¹) (1 + ·) c ?_, cfc_add .., cfc_const_one ℝ≥0 c,
      cfc_id' ℝ≥0 c]
    exact continuousOn_id.inv₀ (Set.forall_mem_image.mpr fun x _ ↦ by dsimp only [id]; positivity)
  rw [h_cfc_one_sub (a : A⁺¹), h_cfc_one_sub (b : A⁺¹)]
  gcongr
  rw [← CFC.rpow_neg_one_eq_cfc_inv, ← CFC.rpow_neg_one_eq_cfc_inv]
  exact rpow_neg_one_le_rpow_neg_one (by gcongr)

set_option backward.isDefEq.respectTransparency false in
```
[/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.Topology.IndicatorConstPointwise).

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

```lean
lemma tendsto_indicator_const_iff_tendsto_pi_pure [T1Space β] (b : β) [NeZero b] :
    Tendsto (fun i ↦ (As i).indicator (fun (_ : α) ↦ b)) L (𝓝 (A.indicator (fun (_ : α) ↦ b)))
      ↔ (Tendsto (fun i x ↦ x ∈ As i) L <| Filter.pi (pure <| · ∈ A))
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Topology.IndicatorConstPointwise.tendsto_ite (L43-L71)
lemma tendsto_ite {β : Type*} {p : ι → Prop} [DecidablePred p] {q : Prop} [Decidable q]
    {a b : β} {F G : Filter β}
    (haG : {a}ᶜ ∈ G) (hbF : {b}ᶜ ∈ F) (haF : principal {a} ≤ F) (hbG : principal {b} ≤ G) :
    Tendsto (fun i ↦ if p i then a else b) L (if q then F else G) ↔ ∀ᶠ i in L, p i ↔ q := by
constructor <;> intro h
  · by_cases hq : q
    · simp only [hq, ite_true] at h
      filter_upwards [mem_map.mp (h hbF)] with i hi
      simp only [Set.preimage_compl, Set.mem_compl_iff, Set.mem_preimage, Set.mem_singleton_iff,
        ite_eq_right_iff, not_forall, exists_prop] at hi
      tauto
    · simp only [hq, ite_false] at h
      filter_upwards [mem_map.mp (h haG)] with i hi
      simp only [Set.preimage_compl, Set.mem_compl_iff, Set.mem_preimage, Set.mem_singleton_iff,
        ite_eq_left_iff, not_forall, exists_prop] at hi
      tauto
  · have obs : (fun _ ↦ if q then a else b) =ᶠ[L] (fun i ↦ if p i then a else b) := by
      filter_upwards [h] with i hi
      simp only [hi]
    apply Tendsto.congr' obs
    by_cases hq : q
    · simp only [hq, ite_true]
      apply le_trans _ haF
      simp
    · simp only [hq, ite_false]
      apply le_trans _ hbG
      simp only [principal_singleton, le_pure_iff, mem_map, Set.mem_singleton_iff,
        Set.preimage_const_of_mem, univ_mem]
```

-- snippet 2
```lean
-- Mathlib.Topology.IndicatorConstPointwise.tendsto_indicator_const_apply_iff_eventually' (L72-L85)
lemma tendsto_indicator_const_apply_iff_eventually' (b : β)
    (nhds_b : {0}ᶜ ∈ 𝓝 b) (nhds_o : {b}ᶜ ∈ 𝓝 0) (x : α) :
    Tendsto (fun i ↦ (As i).indicator (fun (_ : α) ↦ b) x) L (𝓝 (A.indicator (fun (_ : α) ↦ b) x))
      ↔ ∀ᶠ i in L, (x ∈ As i ↔ x ∈ A) := by
classical
  have heart := @tendsto_ite ι L β (fun i ↦ x ∈ As i) _ (x ∈ A) _ b 0 (𝓝 b) (𝓝 (0 : β))
                nhds_o nhds_b ?_ ?_
  · convert heart
    by_cases hxA : x ∈ A <;> simp [hxA]
  · simp only [principal_singleton, le_def, mem_pure]
    exact fun s s_nhds ↦ mem_of_mem_nhds s_nhds
  · simp only [principal_singleton, le_def, mem_pure]
    exact fun s s_nhds ↦ mem_of_mem_nhds s_nhds
```

-- snippet 3
```lean
-- Mathlib.Topology.IndicatorConstPointwise.tendsto_indicator_const_iff_forall_eventually' (L86-L95)
lemma tendsto_indicator_const_iff_forall_eventually'
    (b : β) (nhds_b : {0}ᶜ ∈ 𝓝 b) (nhds_o : {b}ᶜ ∈ 𝓝 0) :
    Tendsto (fun i ↦ (As i).indicator (fun (_ : α) ↦ b)) L (𝓝 (A.indicator (fun (_ : α) ↦ b)))
      ↔ ∀ x, ∀ᶠ i in L, (x ∈ As i ↔ x ∈ A) := by
simp_rw [tendsto_pi_nhds]
  apply forall_congr'
  exact tendsto_indicator_const_apply_iff_eventually' L b nhds_b nhds_o

/-- The indicator functions of `Asᵢ` evaluated at `x` tend to the indicator function of `A`
evaluated at `x` if and only if we eventually have the equivalence `x ∈ Asᵢ ↔ x ∈ A`. -/
```

-- snippet 4
```lean
-- Mathlib.Topology.IndicatorConstPointwise.tendsto_indicator_const_iff_tendsto_pi_pure' (L113-L120)
lemma tendsto_indicator_const_iff_tendsto_pi_pure'
    (b : β) (nhds_b : {0}ᶜ ∈ 𝓝 b) (nhds_o : {b}ᶜ ∈ 𝓝 0) :
    Tendsto (fun i ↦ (As i).indicator (fun (_ : α) ↦ b)) L (𝓝 (A.indicator (fun (_ : α) ↦ b)))
      ↔ (Tendsto (fun i x ↦ x ∈ As i) L <| Filter.pi (pure <| · ∈ A)) := by
rw [tendsto_indicator_const_iff_forall_eventually' _ b nhds_b nhds_o, tendsto_pi]
  simp_rw [tendsto_pure]
  aesop
```

<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.Topology.IndicatorConstPointwise).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
lemma tendsto_indicator_const_iff_tendsto_pi_pure [T1Space β] (b : β) [NeZero b] :
    Tendsto (fun i ↦ (As i).indicator (fun (_ : α) ↦ b)) L (𝓝 (A.indicator (fun (_ : α) ↦ b)))
      ↔ (Tendsto (fun i x ↦ x ∈ As i) L <| Filter.pi (pure <| · ∈ A))
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Topology.IndicatorConstPointwise.tendsto_ite (L43-L71)
lemma tendsto_ite {β : Type*} {p : ι → Prop} [DecidablePred p] {q : Prop} [Decidable q]
    {a b : β} {F G : Filter β}
    (haG : {a}ᶜ ∈ G) (hbF : {b}ᶜ ∈ F) (haF : principal {a} ≤ F) (hbG : principal {b} ≤ G) :
    Tendsto (fun i ↦ if p i then a else b) L (if q then F else G) ↔ ∀ᶠ i in L, p i ↔ q := by
constructor <;> intro h
  · by_cases hq : q
    · simp only [hq, ite_true] at h
      filter_upwards [mem_map.mp (h hbF)] with i hi
      simp only [Set.preimage_compl, Set.mem_compl_iff, Set.mem_preimage, Set.mem_singleton_iff,
        ite_eq_right_iff, not_forall, exists_prop] at hi
      tauto
    · simp only [hq, ite_false] at h
      filter_upwards [mem_map.mp (h haG)] with i hi
      simp only [Set.preimage_compl, Set.mem_compl_iff, Set.mem_preimage, Set.mem_singleton_iff,
        ite_eq_left_iff, not_forall, exists_prop] at hi
      tauto
  · have obs : (fun _ ↦ if q then a else b) =ᶠ[L] (fun i ↦ if p i then a else b) := by
      filter_upwards [h] with i hi
      simp only [hi]
    apply Tendsto.congr' obs
    by_cases hq : q
    · simp only [hq, ite_true]
      apply le_trans _ haF
      simp
    · simp only [hq, ite_false]
      apply le_trans _ hbG
      simp only [principal_singleton, le_pure_iff, mem_map, Set.mem_singleton_iff,
        Set.preimage_const_of_mem, univ_mem]
```

-- snippet 2
```lean
-- Mathlib.Topology.IndicatorConstPointwise.tendsto_indicator_const_apply_iff_eventually' (L72-L85)
lemma tendsto_indicator_const_apply_iff_eventually' (b : β)
    (nhds_b : {0}ᶜ ∈ 𝓝 b) (nhds_o : {b}ᶜ ∈ 𝓝 0) (x : α) :
    Tendsto (fun i ↦ (As i).indicator (fun (_ : α) ↦ b) x) L (𝓝 (A.indicator (fun (_ : α) ↦ b) x))
      ↔ ∀ᶠ i in L, (x ∈ As i ↔ x ∈ A) := by
classical
  have heart := @tendsto_ite ι L β (fun i ↦ x ∈ As i) _ (x ∈ A) _ b 0 (𝓝 b) (𝓝 (0 : β))
                nhds_o nhds_b ?_ ?_
  · convert heart
    by_cases hxA : x ∈ A <;> simp [hxA]
  · simp only [principal_singleton, le_def, mem_pure]
    exact fun s s_nhds ↦ mem_of_mem_nhds s_nhds
  · simp only [principal_singleton, le_def, mem_pure]
    exact fun s s_nhds ↦ mem_of_mem_nhds s_nhds
```

-- snippet 3
```lean
-- Mathlib.Topology.IndicatorConstPointwise.tendsto_indicator_const_iff_forall_eventually' (L86-L95)
lemma tendsto_indicator_const_iff_forall_eventually'
    (b : β) (nhds_b : {0}ᶜ ∈ 𝓝 b) (nhds_o : {b}ᶜ ∈ 𝓝 0) :
    Tendsto (fun i ↦ (As i).indicator (fun (_ : α) ↦ b)) L (𝓝 (A.indicator (fun (_ : α) ↦ b)))
      ↔ ∀ x, ∀ᶠ i in L, (x ∈ As i ↔ x ∈ A) := by
simp_rw [tendsto_pi_nhds]
  apply forall_congr'
  exact tendsto_indicator_const_apply_iff_eventually' L b nhds_b nhds_o

/-- The indicator functions of `Asᵢ` evaluated at `x` tend to the indicator function of `A`
evaluated at `x` if and only if we eventually have the equivalence `x ∈ Asᵢ ↔ x ∈ A`. -/
```

-- snippet 4
```lean
-- Mathlib.Topology.IndicatorConstPointwise.tendsto_indicator_const_iff_tendsto_pi_pure' (L113-L120)
lemma tendsto_indicator_const_iff_tendsto_pi_pure'
    (b : β) (nhds_b : {0}ᶜ ∈ 𝓝 b) (nhds_o : {b}ᶜ ∈ 𝓝 0) :
    Tendsto (fun i ↦ (As i).indicator (fun (_ : α) ↦ b)) L (𝓝 (A.indicator (fun (_ : α) ↦ b)))
      ↔ (Tendsto (fun i x ↦ x ∈ As i) L <| Filter.pi (pure <| · ∈ A)) := by
rw [tendsto_indicator_const_iff_forall_eventually' _ b nhds_b nhds_o, tendsto_pi]
  simp_rw [tendsto_pure]
  aesop
```
[/INST]