l3lab/ntp-mathlib huggingface dataset:
/-- If `f₁` and `f₂` are ring homs out of the polynomial ring and `p₁` and `p₂` are polynomials,
  then `f₁ p₁ = f₂ p₂` if `p₁ = p₂` and `f₁` and `f₂` are equal on `R` and on the variables
  of `p₁`.  -/
theorem hom_congr_vars {f₁ f₂ : MvPolynomial σ R →+* S} {p₁ p₂ : MvPolynomial σ R}
    (hC : f₁.comp C = f₂.comp C) (hv : ∀ i, i ∈ p₁.vars → i ∈ p₂.vars → f₁ (X i) = f₂ (X i))
    (hp : p₁ = p₂) : f₁ p₁ = f₂ p₂ :=
  calc
    f₁ p₁ = eval₂Hom (f₁.comp C) (f₁ ∘ X) p₁ := RingHom.congr_fun (by ext <;> 

Proof state:
case hX
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p q : MvPolynomial σ R
inst✝ : CommSemiring S
f₁ f₂ : MvPolynomial σ R →+* S
p₁ p₂ : MvPolynomial σ R
hC : RingHom.comp f₁ C = RingHom.comp f₂ C
hv : ∀ i ∈ vars p₁, i ∈ vars p₂ → f₁ (X i) = f₂ (X i)
hp : p₁ = p₂
i✝ : σ
⊢ f₁ (X i✝) = (eval₂Hom (RingHom.comp f₁ C) (⇑f₁ ∘ X)) (X i✝)

Next tactic:
simp
/-- If `f₁` and `f₂` are ring homs out of the polynomial ring and `p₁` and `p₂` are polynomials,
  then `f₁ p₁ = f₂ p₂` if `p₁ = p₂` and `f₁` and `f₂` are equal on `R` and on the variables
  of `p₁`.  -/
theorem hom_congr_vars {f₁ f₂ : MvPolynomial σ R →+* S} {p₁ p₂ : MvPolynomial σ R}
    (hC : f₁.comp C = f₂.comp C) (hv : ∀ i, i ∈ p₁.vars → i ∈ p₂.vars → f₁ (X i) = f₂ (X i))
    (hp : p₁ = p₂) : f₁ p₁ = f₂ p₂ :=
  calc
    f₁ p₁ = eval₂Hom (f₁.comp C) (f₁ ∘ X) p₁ := RingHom.congr_fun (by ext <;> simp) _
    _ = eval₂Hom (f₂.comp C) (f₂ ∘ X) p₂ := (eval₂Hom_congr' hC hv hp)
    _ = f₂ p₂ := RingHom.congr_fun (by 

Proof state:
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p q : MvPolynomial σ R
inst✝ : CommSemiring S
f₁ f₂ : MvPolynomial σ R →+* S
p₁ p₂ : MvPolynomial σ R
hC : RingHom.comp f₁ C = RingHom.comp f₂ C
hv : ∀ i ∈ vars p₁, i ∈ vars p₂ → f₁ (X i) = f₂ (X i)
hp : p₁ = p₂
⊢ eval₂Hom (RingHom.comp f₂ C) (⇑f₂ ∘ X) = f₂

Next tactic:
ext
/-- If `f₁` and `f₂` are ring homs out of the polynomial ring and `p₁` and `p₂` are polynomials,
  then `f₁ p₁ = f₂ p₂` if `p₁ = p₂` and `f₁` and `f₂` are equal on `R` and on the variables
  of `p₁`.  -/
theorem hom_congr_vars {f₁ f₂ : MvPolynomial σ R →+* S} {p₁ p₂ : MvPolynomial σ R}
    (hC : f₁.comp C = f₂.comp C) (hv : ∀ i, i ∈ p₁.vars → i ∈ p₂.vars → f₁ (X i) = f₂ (X i))
    (hp : p₁ = p₂) : f₁ p₁ = f₂ p₂ :=
  calc
    f₁ p₁ = eval₂Hom (f₁.comp C) (f₁ ∘ X) p₁ := RingHom.congr_fun (by ext <;> simp) _
    _ = eval₂Hom (f₂.comp C) (f₂ ∘ X) p₂ := (eval₂Hom_congr' hC hv hp)
    _ = f₂ p₂ := RingHom.congr_fun (by ext <;> 

Proof state:
case hC.a
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p q : MvPolynomial σ R
inst✝ : CommSemiring S
f₁ f₂ : MvPolynomial σ R →+* S
p₁ p₂ : MvPolynomial σ R
hC : RingHom.comp f₁ C = RingHom.comp f₂ C
hv : ∀ i ∈ vars p₁, i ∈ vars p₂ → f₁ (X i) = f₂ (X i)
hp : p₁ = p₂
x✝ : R
⊢ (RingHom.comp (eval₂Hom (RingHom.comp f₂ C) (⇑f₂ ∘ X)) C) x✝ = (RingHom.comp f₂ C) x✝

Next tactic:
simp
/-- If `f₁` and `f₂` are ring homs out of the polynomial ring and `p₁` and `p₂` are polynomials,
  then `f₁ p₁ = f₂ p₂` if `p₁ = p₂` and `f₁` and `f₂` are equal on `R` and on the variables
  of `p₁`.  -/
theorem hom_congr_vars {f₁ f₂ : MvPolynomial σ R →+* S} {p₁ p₂ : MvPolynomial σ R}
    (hC : f₁.comp C = f₂.comp C) (hv : ∀ i, i ∈ p₁.vars → i ∈ p₂.vars → f₁ (X i) = f₂ (X i))
    (hp : p₁ = p₂) : f₁ p₁ = f₂ p₂ :=
  calc
    f₁ p₁ = eval₂Hom (f₁.comp C) (f₁ ∘ X) p₁ := RingHom.congr_fun (by ext <;> simp) _
    _ = eval₂Hom (f₂.comp C) (f₂ ∘ X) p₂ := (eval₂Hom_congr' hC hv hp)
    _ = f₂ p₂ := RingHom.congr_fun (by ext <;> 

Proof state:
case hX
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p q : MvPolynomial σ R
inst✝ : CommSemiring S
f₁ f₂ : MvPolynomial σ R →+* S
p₁ p₂ : MvPolynomial σ R
hC : RingHom.comp f₁ C = RingHom.comp f₂ C
hv : ∀ i ∈ vars p₁, i ∈ vars p₂ → f₁ (X i) = f₂ (X i)
hp : p₁ = p₂
i✝ : σ
⊢ (eval₂Hom (RingHom.comp f₂ C) (⇑f₂ ∘ X)) (X i✝) = f₂ (X i✝)

Next tactic:
simp
theorem exists_rename_eq_of_vars_subset_range (p : MvPolynomial σ R) (f : τ → σ) (hfi : Injective f)
    (hf : ↑p.vars ⊆ Set.range f) : ∃ q : MvPolynomial τ R, rename f q = p :=
  ⟨aeval (fun i : σ => Option.elim' 0 X <| partialInv f i) p,
    by
      

Proof state:
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p✝ q : MvPolynomial σ R
inst✝ : CommSemiring S
p : MvPolynomial σ R
f : τ → σ
hfi : Injective f
hf : ↑(vars p) ⊆ range f
⊢ (rename f) ((aeval fun i => Option.elim' 0 X (partialInv f i)) p) = p

Next tactic:
show (rename f).toRingHom.comp _ p = RingHom.id _ p
theorem exists_rename_eq_of_vars_subset_range (p : MvPolynomial σ R) (f : τ → σ) (hfi : Injective f)
    (hf : ↑p.vars ⊆ Set.range f) : ∃ q : MvPolynomial τ R, rename f q = p :=
  ⟨aeval (fun i : σ => Option.elim' 0 X <| partialInv f i) p,
    by
      show (rename f).toRingHom.comp _ p = RingHom.id _ p
      

Proof state:
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p✝ q : MvPolynomial σ R
inst✝ : CommSemiring S
p : MvPolynomial σ R
f : τ → σ
hfi : Injective f
hf : ↑(vars p) ⊆ range f
⊢ (RingHom.comp ↑(rename f) ↑(aeval fun i => Option.elim' 0 X (partialInv f i))) p = (RingHom.id (MvPolynomial σ R)) p

Next tactic:
refine' hom_congr_vars _ _ _
theorem exists_rename_eq_of_vars_subset_range (p : MvPolynomial σ R) (f : τ → σ) (hfi : Injective f)
    (hf : ↑p.vars ⊆ Set.range f) : ∃ q : MvPolynomial τ R, rename f q = p :=
  ⟨aeval (fun i : σ => Option.elim' 0 X <| partialInv f i) p,
    by
      show (rename f).toRingHom.comp _ p = RingHom.id _ p
      refine' hom_congr_vars _ _ _
      · 

Proof state:
case refine'_1
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p✝ q : MvPolynomial σ R
inst✝ : CommSemiring S
p : MvPolynomial σ R
f : τ → σ
hfi : Injective f
hf : ↑(vars p) ⊆ range f
⊢ RingHom.comp (RingHom.comp ↑(rename f) ↑(aeval fun i => Option.elim' 0 X (partialInv f i))) C =
    RingHom.comp (RingHom.id (MvPolynomial σ R)) C

Next tactic:
ext1
theorem exists_rename_eq_of_vars_subset_range (p : MvPolynomial σ R) (f : τ → σ) (hfi : Injective f)
    (hf : ↑p.vars ⊆ Set.range f) : ∃ q : MvPolynomial τ R, rename f q = p :=
  ⟨aeval (fun i : σ => Option.elim' 0 X <| partialInv f i) p,
    by
      show (rename f).toRingHom.comp _ p = RingHom.id _ p
      refine' hom_congr_vars _ _ _
      · ext1
        

Proof state:
case refine'_1.a
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p✝ q : MvPolynomial σ R
inst✝ : CommSemiring S
p : MvPolynomial σ R
f : τ → σ
hfi : Injective f
hf : ↑(vars p) ⊆ range f
x✝ : R
⊢ (RingHom.comp (RingHom.comp ↑(rename f) ↑(aeval fun i => Option.elim' 0 X (partialInv f i))) C) x✝ =
    (RingHom.comp (RingHom.id (MvPolynomial σ R)) C) x✝

Next tactic:
simp [algebraMap_eq]
theorem exists_rename_eq_of_vars_subset_range (p : MvPolynomial σ R) (f : τ → σ) (hfi : Injective f)
    (hf : ↑p.vars ⊆ Set.range f) : ∃ q : MvPolynomial τ R, rename f q = p :=
  ⟨aeval (fun i : σ => Option.elim' 0 X <| partialInv f i) p,
    by
      show (rename f).toRingHom.comp _ p = RingHom.id _ p
      refine' hom_congr_vars _ _ _
      · ext1
        simp [algebraMap_eq]
      · 

Proof state:
case refine'_2
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p✝ q : MvPolynomial σ R
inst✝ : CommSemiring S
p : MvPolynomial σ R
f : τ → σ
hfi : Injective f
hf : ↑(vars p) ⊆ range f
⊢ ∀ i ∈ vars p,
    i ∈ vars p →
      (RingHom.comp ↑(rename f) ↑(aeval fun i => Option.elim' 0 X (partialInv f i))) (X i) =
        (RingHom.id (MvPolynomial σ R)) (X i)

Next tactic:
intro i hip _
theorem exists_rename_eq_of_vars_subset_range (p : MvPolynomial σ R) (f : τ → σ) (hfi : Injective f)
    (hf : ↑p.vars ⊆ Set.range f) : ∃ q : MvPolynomial τ R, rename f q = p :=
  ⟨aeval (fun i : σ => Option.elim' 0 X <| partialInv f i) p,
    by
      show (rename f).toRingHom.comp _ p = RingHom.id _ p
      refine' hom_congr_vars _ _ _
      · ext1
        simp [algebraMap_eq]
      · intro i hip _
        

Proof state:
case refine'_2
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p✝ q : MvPolynomial σ R
inst✝ : CommSemiring S
p : MvPolynomial σ R
f : τ → σ
hfi : Injective f
hf : ↑(vars p) ⊆ range f
i : σ
hip a✝ : i ∈ vars p
⊢ (RingHom.comp ↑(rename f) ↑(aeval fun i => Option.elim' 0 X (partialInv f i))) (X i) =
    (RingHom.id (MvPolynomial σ R)) (X i)

Next tactic:
rcases hf hip with ⟨i, rfl⟩
theorem exists_rename_eq_of_vars_subset_range (p : MvPolynomial σ R) (f : τ → σ) (hfi : Injective f)
    (hf : ↑p.vars ⊆ Set.range f) : ∃ q : MvPolynomial τ R, rename f q = p :=
  ⟨aeval (fun i : σ => Option.elim' 0 X <| partialInv f i) p,
    by
      show (rename f).toRingHom.comp _ p = RingHom.id _ p
      refine' hom_congr_vars _ _ _
      · ext1
        simp [algebraMap_eq]
      · intro i hip _
        rcases hf hip with ⟨i, rfl⟩
        

Proof state:
case refine'_2.intro
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p✝ q : MvPolynomial σ R
inst✝ : CommSemiring S
p : MvPolynomial σ R
f : τ → σ
hfi : Injective f
hf : ↑(vars p) ⊆ range f
i : τ
hip a✝ : f i ∈ vars p
⊢ (RingHom.comp ↑(rename f) ↑(aeval fun i => Option.elim' 0 X (partialInv f i))) (X (f i)) =
    (RingHom.id (MvPolynomial σ R)) (X (f i))

Next tactic:
simp [partialInv_left hfi]
theorem exists_rename_eq_of_vars_subset_range (p : MvPolynomial σ R) (f : τ → σ) (hfi : Injective f)
    (hf : ↑p.vars ⊆ Set.range f) : ∃ q : MvPolynomial τ R, rename f q = p :=
  ⟨aeval (fun i : σ => Option.elim' 0 X <| partialInv f i) p,
    by
      show (rename f).toRingHom.comp _ p = RingHom.id _ p
      refine' hom_congr_vars _ _ _
      · ext1
        simp [algebraMap_eq]
      · intro i hip _
        rcases hf hip with ⟨i, rfl⟩
        simp [partialInv_left hfi]
      · 

Proof state:
case refine'_3
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p✝ q : MvPolynomial σ R
inst✝ : CommSemiring S
p : MvPolynomial σ R
f : τ → σ
hfi : Injective f
hf : ↑(vars p) ⊆ range f
⊢ p = p

Next tactic:
rfl
theorem vars_rename [DecidableEq τ] (f : σ → τ) (φ : MvPolynomial σ R) :
    (rename f φ).vars ⊆ φ.vars.image f := by
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝² : CommSemiring R
p q : MvPolynomial σ R
inst✝¹ : CommSemiring S
inst✝ : DecidableEq τ
f : σ → τ
φ : MvPolynomial σ R
⊢ vars ((rename f) φ) ⊆ Finset.image f (vars φ)

Next tactic:
classical
  intro i hi
  simp only [vars_def, exists_prop, Multiset.mem_toFinset, Finset.mem_image] at hi ⊢
  simpa only [Multiset.mem_map] using degrees_rename _ _ hi
theorem vars_rename [DecidableEq τ] (f : σ → τ) (φ : MvPolynomial σ R) :
    (rename f φ).vars ⊆ φ.vars.image f := by
  classical
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝² : CommSemiring R
p q : MvPolynomial σ R
inst✝¹ : CommSemiring S
inst✝ : DecidableEq τ
f : σ → τ
φ : MvPolynomial σ R
⊢ vars ((rename f) φ) ⊆ Finset.image f (vars φ)

Next tactic:
intro i hi
theorem vars_rename [DecidableEq τ] (f : σ → τ) (φ : MvPolynomial σ R) :
    (rename f φ).vars ⊆ φ.vars.image f := by
  classical
  intro i hi
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝² : CommSemiring R
p q : MvPolynomial σ R
inst✝¹ : CommSemiring S
inst✝ : DecidableEq τ
f : σ → τ
φ : MvPolynomial σ R
i : τ
hi : i ∈ vars ((rename f) φ)
⊢ i ∈ Finset.image f (vars φ)

Next tactic:
simp only [vars_def, exists_prop, Multiset.mem_toFinset, Finset.mem_image] at hi ⊢
theorem vars_rename [DecidableEq τ] (f : σ → τ) (φ : MvPolynomial σ R) :
    (rename f φ).vars ⊆ φ.vars.image f := by
  classical
  intro i hi
  simp only [vars_def, exists_prop, Multiset.mem_toFinset, Finset.mem_image] at hi ⊢
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝² : CommSemiring R
p q : MvPolynomial σ R
inst✝¹ : CommSemiring S
inst✝ : DecidableEq τ
f : σ → τ
φ : MvPolynomial σ R
i : τ
hi : i ∈ degrees ((rename f) φ)
⊢ ∃ a ∈ degrees φ, f a = i

Next tactic:
simpa only [Multiset.mem_map] using degrees_rename _ _ hi
theorem mem_vars_rename (f : σ → τ) (φ : MvPolynomial σ R) {j : τ} (h : j ∈ (rename f φ).vars) :
    ∃ i : σ, i ∈ φ.vars ∧ f i = j := by
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p q : MvPolynomial σ R
inst✝ : CommSemiring S
f : σ → τ
φ : MvPolynomial σ R
j : τ
h : j ∈ vars ((rename f) φ)
⊢ ∃ i ∈ vars φ, f i = j

Next tactic:
classical
  simpa only [exists_prop, Finset.mem_image] using vars_rename f φ h
theorem mem_vars_rename (f : σ → τ) (φ : MvPolynomial σ R) {j : τ} (h : j ∈ (rename f φ).vars) :
    ∃ i : σ, i ∈ φ.vars ∧ f i = j := by
  classical
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
τ : Type u_2
r : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommSemiring R
p q : MvPolynomial σ R
inst✝ : CommSemiring S
f : σ → τ
φ : MvPolynomial σ R
j : τ
h : j ∈ vars ((rename f) φ)
⊢ ∃ i ∈ vars φ, f i = j

Next tactic:
simpa only [exists_prop, Finset.mem_image] using vars_rename f φ h
theorem IsHermitian.ext {A : Matrix n n α} : (∀ i j, star (A j i) = A i j) → A.IsHermitian := by
  

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝¹ : Star α
inst✝ : Star β
A : Matrix n n α
⊢ (∀ (i j : n), star (A j i) = A i j) → IsHermitian A

Next tactic:
intro h
theorem IsHermitian.ext {A : Matrix n n α} : (∀ i j, star (A j i) = A i j) → A.IsHermitian := by
  intro h; 

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝¹ : Star α
inst✝ : Star β
A : Matrix n n α
h : ∀ (i j : n), star (A j i) = A i j
⊢ IsHermitian A

Next tactic:
ext i j
theorem IsHermitian.ext {A : Matrix n n α} : (∀ i j, star (A j i) = A i j) → A.IsHermitian := by
  intro h; ext i j; 

Proof state:
case a.h
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝¹ : Star α
inst✝ : Star β
A : Matrix n n α
h : ∀ (i j : n), star (A j i) = A i j
i j : n
⊢ Aᴴ i j = A i j

Next tactic:
exact h i j
theorem IsHermitian.transpose {A : Matrix n n α} (h : A.IsHermitian) : Aᵀ.IsHermitian := by
  

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝¹ : Star α
inst✝ : Star β
A : Matrix n n α
h : IsHermitian A
⊢ IsHermitian Aᵀ

Next tactic:
rw [IsHermitian, conjTranspose, transpose_map]
theorem IsHermitian.transpose {A : Matrix n n α} (h : A.IsHermitian) : Aᵀ.IsHermitian := by
  rw [IsHermitian, conjTranspose, transpose_map]
  

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝¹ : Star α
inst✝ : Star β
A : Matrix n n α
h : IsHermitian A
⊢ (Matrix.map Aᵀ star)ᵀ = Aᵀ

Next tactic:
exact congr_arg Matrix.transpose h
@[simp]
theorem isHermitian_transpose_iff (A : Matrix n n α) : Aᵀ.IsHermitian ↔ A.IsHermitian :=
  ⟨by 

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝¹ : Star α
inst✝ : Star β
A : Matrix n n α
⊢ IsHermitian Aᵀ → IsHermitian A

Next tactic:
intro h
@[simp]
theorem isHermitian_transpose_iff (A : Matrix n n α) : Aᵀ.IsHermitian ↔ A.IsHermitian :=
  ⟨by intro h; 

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝¹ : Star α
inst✝ : Star β
A : Matrix n n α
h : IsHermitian Aᵀ
⊢ IsHermitian A

Next tactic:
rw [← transpose_transpose A]
@[simp]
theorem isHermitian_transpose_iff (A : Matrix n n α) : Aᵀ.IsHermitian ↔ A.IsHermitian :=
  ⟨by intro h; rw [← transpose_transpose A]; 

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝¹ : Star α
inst✝ : Star β
A : Matrix n n α
h : IsHermitian Aᵀ
⊢ IsHermitian Aᵀᵀ

Next tactic:
exact IsHermitian.transpose h
@[simp]
theorem isHermitian_submatrix_equiv {A : Matrix n n α} (e : m ≃ n) :
    (A.submatrix e e).IsHermitian ↔ A.IsHermitian :=
  ⟨fun h => by 

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝¹ : Star α
inst✝ : Star β
A : Matrix n n α
e : m ≃ n
h : IsHermitian (submatrix A ⇑e ⇑e)
⊢ IsHermitian A

Next tactic:
simpa using h.submatrix e.symm
/-- A block matrix `A.from_blocks B C D` is hermitian,
    if `A` and `D` are hermitian and `Bᴴ = C`. -/
theorem IsHermitian.fromBlocks {A : Matrix m m α} {B : Matrix m n α} {C : Matrix n m α}
    {D : Matrix n n α} (hA : A.IsHermitian) (hBC : Bᴴ = C) (hD : D.IsHermitian) :
    (A.fromBlocks B C D).IsHermitian := by
  

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝ : InvolutiveStar α
A : Matrix m m α
B : Matrix m n α
C : Matrix n m α
D : Matrix n n α
hA : IsHermitian A
hBC : Bᴴ = C
hD : IsHermitian D
⊢ IsHermitian (Matrix.fromBlocks A B C D)

Next tactic:
have hCB : Cᴴ = B := by rw [← hBC, conjTranspose_conjTranspose]
/-- A block matrix `A.from_blocks B C D` is hermitian,
    if `A` and `D` are hermitian and `Bᴴ = C`. -/
theorem IsHermitian.fromBlocks {A : Matrix m m α} {B : Matrix m n α} {C : Matrix n m α}
    {D : Matrix n n α} (hA : A.IsHermitian) (hBC : Bᴴ = C) (hD : D.IsHermitian) :
    (A.fromBlocks B C D).IsHermitian := by
  have hCB : Cᴴ = B := by 

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝ : InvolutiveStar α
A : Matrix m m α
B : Matrix m n α
C : Matrix n m α
D : Matrix n n α
hA : IsHermitian A
hBC : Bᴴ = C
hD : IsHermitian D
⊢ Cᴴ = B

Next tactic:
rw [← hBC, conjTranspose_conjTranspose]
/-- A block matrix `A.from_blocks B C D` is hermitian,
    if `A` and `D` are hermitian and `Bᴴ = C`. -/
theorem IsHermitian.fromBlocks {A : Matrix m m α} {B : Matrix m n α} {C : Matrix n m α}
    {D : Matrix n n α} (hA : A.IsHermitian) (hBC : Bᴴ = C) (hD : D.IsHermitian) :
    (A.fromBlocks B C D).IsHermitian := by
  have hCB : Cᴴ = B := by rw [← hBC, conjTranspose_conjTranspose]
  

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝ : InvolutiveStar α
A : Matrix m m α
B : Matrix m n α
C : Matrix n m α
D : Matrix n n α
hA : IsHermitian A
hBC : Bᴴ = C
hD : IsHermitian D
hCB : Cᴴ = B
⊢ IsHermitian (Matrix.fromBlocks A B C D)

Next tactic:
unfold Matrix.IsHermitian
/-- A block matrix `A.from_blocks B C D` is hermitian,
    if `A` and `D` are hermitian and `Bᴴ = C`. -/
theorem IsHermitian.fromBlocks {A : Matrix m m α} {B : Matrix m n α} {C : Matrix n m α}
    {D : Matrix n n α} (hA : A.IsHermitian) (hBC : Bᴴ = C) (hD : D.IsHermitian) :
    (A.fromBlocks B C D).IsHermitian := by
  have hCB : Cᴴ = B := by rw [← hBC, conjTranspose_conjTranspose]
  unfold Matrix.IsHermitian
  

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝ : InvolutiveStar α
A : Matrix m m α
B : Matrix m n α
C : Matrix n m α
D : Matrix n n α
hA : IsHermitian A
hBC : Bᴴ = C
hD : IsHermitian D
hCB : Cᴴ = B
⊢ (Matrix.fromBlocks A B C D)ᴴ = Matrix.fromBlocks A B C D

Next tactic:
rw [fromBlocks_conjTranspose, hBC, hCB, hA, hD]
/-- A diagonal matrix is hermitian if each diagonal entry is self-adjoint -/
lemma isHermitian_diagonal_iff [DecidableEq n]{d : n → α} :
    IsHermitian (diagonal d) ↔ (∀ i : n, IsSelfAdjoint (d i)) := by
  

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A : Matrix n n α
inst✝⁴ : AddMonoid α
inst✝³ : StarAddMonoid α
inst✝² : AddMonoid β
inst✝¹ : StarAddMonoid β
inst✝ : DecidableEq n
d : n → α
⊢ IsHermitian (diagonal d) ↔ ∀ (i : n), IsSelfAdjoint (d i)

Next tactic:
simp [isSelfAdjoint_iff, IsHermitian, conjTranspose, diagonal_transpose, diagonal_map]
/-- Note this is more general than `IsSelfAdjoint.mul_star_self` as `B` can be rectangular. -/
theorem isHermitian_mul_conjTranspose_self [Fintype n] (A : Matrix m n α) : (A * Aᴴ).IsHermitian :=
  by 

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝⁴ : NonUnitalSemiring α
inst✝³ : StarRing α
inst✝² : NonUnitalSemiring β
inst✝¹ : StarRing β
inst✝ : Fintype n
A : Matrix m n α
⊢ IsHermitian (A * Aᴴ)

Next tactic:
rw [IsHermitian, conjTranspose_mul, conjTranspose_conjTranspose]
/-- Note this is more general than `IsSelfAdjoint.star_mul_self` as `B` can be rectangular. -/
theorem isHermitian_transpose_mul_self [Fintype m] (A : Matrix m n α) : (Aᴴ * A).IsHermitian := by
  

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝⁴ : NonUnitalSemiring α
inst✝³ : StarRing α
inst✝² : NonUnitalSemiring β
inst✝¹ : StarRing β
inst✝ : Fintype m
A : Matrix m n α
⊢ IsHermitian (Aᴴ * A)

Next tactic:
rw [IsHermitian, conjTranspose_mul, conjTranspose_conjTranspose]
/-- Note this is more general than `IsSelfAdjoint.conjugate'` as `B` can be rectangular. -/
theorem isHermitian_conjTranspose_mul_mul [Fintype m] {A : Matrix m m α} (B : Matrix m n α)
    (hA : A.IsHermitian) : (Bᴴ * A * B).IsHermitian := by
  

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝⁴ : NonUnitalSemiring α
inst✝³ : StarRing α
inst✝² : NonUnitalSemiring β
inst✝¹ : StarRing β
inst✝ : Fintype m
A : Matrix m m α
B : Matrix m n α
hA : IsHermitian A
⊢ IsHermitian (Bᴴ * A * B)

Next tactic:
simp only [IsHermitian, conjTranspose_mul, conjTranspose_conjTranspose, hA.eq, Matrix.mul_assoc]
/-- Note this is more general than `IsSelfAdjoint.conjugate` as `B` can be rectangular. -/
theorem isHermitian_mul_mul_conjTranspose [Fintype m] {A : Matrix m m α} (B : Matrix n m α)
    (hA : A.IsHermitian) : (B * A * Bᴴ).IsHermitian := by
  

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝⁴ : NonUnitalSemiring α
inst✝³ : StarRing α
inst✝² : NonUnitalSemiring β
inst✝¹ : StarRing β
inst✝ : Fintype m
A : Matrix m m α
B : Matrix n m α
hA : IsHermitian A
⊢ IsHermitian (B * A * Bᴴ)

Next tactic:
simp only [IsHermitian, conjTranspose_mul, conjTranspose_conjTranspose, hA.eq, Matrix.mul_assoc]
theorem IsHermitian.inv [Fintype m] [DecidableEq m] {A : Matrix m m α} (hA : A.IsHermitian) :
    A⁻¹.IsHermitian := by 

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝³ : CommRing α
inst✝² : StarRing α
inst✝¹ : Fintype m
inst✝ : DecidableEq m
A : Matrix m m α
hA : IsHermitian A
⊢ IsHermitian A⁻¹

Next tactic:
simp [IsHermitian, conjTranspose_nonsing_inv, hA.eq]
@[simp]
theorem isHermitian_inv [Fintype m] [DecidableEq m] (A : Matrix m m α) [Invertible A] :
    A⁻¹.IsHermitian ↔ A.IsHermitian :=
  ⟨fun h => by 

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝⁴ : CommRing α
inst✝³ : StarRing α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
A : Matrix m m α
inst✝ : Invertible A
h : IsHermitian A⁻¹
⊢ IsHermitian A

Next tactic:
rw [← inv_inv_of_invertible A]
@[simp]
theorem isHermitian_inv [Fintype m] [DecidableEq m] (A : Matrix m m α) [Invertible A] :
    A⁻¹.IsHermitian ↔ A.IsHermitian :=
  ⟨fun h => by rw [← inv_inv_of_invertible A]; 

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝⁴ : CommRing α
inst✝³ : StarRing α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
A : Matrix m m α
inst✝ : Invertible A
h : IsHermitian A⁻¹
⊢ IsHermitian A⁻¹⁻¹

Next tactic:
exact IsHermitian.inv h
theorem IsHermitian.adjugate [Fintype m] [DecidableEq m] {A : Matrix m m α} (hA : A.IsHermitian) :
    A.adjugate.IsHermitian := by 

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝³ : CommRing α
inst✝² : StarRing α
inst✝¹ : Fintype m
inst✝ : DecidableEq m
A : Matrix m m α
hA : IsHermitian A
⊢ IsHermitian (Matrix.adjugate A)

Next tactic:
simp [IsHermitian, adjugate_conjTranspose, hA.eq]
/-- Note that `IsSelfAdjoint.zpow` does not apply to matrices as they are not a division ring. -/
theorem IsHermitian.zpow [Fintype m] [DecidableEq m] {A : Matrix m m α} (h : A.IsHermitian)
    (k : ℤ) :
    (A ^ k).IsHermitian := by
  

Proof state:
α : Type u_1
β : Type u_2
m : Type u_3
n : Type u_4
A✝ : Matrix n n α
inst✝³ : CommRing α
inst✝² : StarRing α
inst✝¹ : Fintype m
inst✝ : DecidableEq m
A : Matrix m m α
h : IsHermitian A
k : ℤ
⊢ IsHermitian (A ^ k)

Next tactic:
rw [IsHermitian, conjTranspose_zpow, h]