Theory Hermitean_Matrices
subsection ‹Hermitean matrices›
text ‹Hermitean matrices over $\mathbb{C}$ generalize symmetric matrices over $\mathbb{R}$. Quadratic
forms with Hermitean matrices represent circles and lines in the extended complex plane (when
applied to homogenous coordinates).›
theory Hermitean_Matrices
imports Unitary_Matrices
begin
definition hermitean :: "complex_mat ⇒ bool" where
"hermitean A ⟷ mat_adj A = A"
lemma hermitean_transpose:
shows "hermitean A ⟷ mat_transpose A = mat_cnj A"
unfolding hermitean_def
by (cases A) (auto simp add: mat_adj_def mat_cnj_def)
text ‹Characterization of 2x2 Hermitean matrices elements.
All 2x2 Hermitean matrices are of the form
$$
\left(
\begin{array}{cc}
A & B\\
\overline{B} & D
\end{array}
\right),
$$
for real $A$ and $D$ and complex $B$.
›
lemma hermitean_mk_circline [simp]:
shows "hermitean (cor A, B, cnj B, cor D)"
unfolding hermitean_def mat_adj_def mat_cnj_def
by simp
lemma hermitean_mk_circline' [simp]:
assumes "is_real A" and "is_real D"
shows "hermitean (A, B, cnj B, D)"
using assms eq_cnj_iff_real
unfolding hermitean_def mat_adj_def mat_cnj_def
by force
lemma hermitean_elems:
assumes "hermitean (A, B, C, D)"
shows "is_real A" and "is_real D" and "B = cnj C" and "cnj B = C"
using assms eq_cnj_iff_real[of A] eq_cnj_iff_real[of D]
by (auto simp add: hermitean_def mat_adj_def mat_cnj_def)
text ‹Operations that preserve the Hermitean property›
lemma hermitean_mat_cnj:
shows "hermitean H ⟷ hermitean (mat_cnj H)"
by (cases H) (auto simp add: hermitean_def mat_adj_def mat_cnj_def)
lemma hermitean_mult_real:
assumes "hermitean H"
shows "hermitean ((cor k) *⇩s⇩m H)"
using assms
unfolding hermitean_def
by simp
lemma hermitean_congruence:
assumes "hermitean H"
shows "hermitean (congruence M H)"
using assms
unfolding hermitean_def
by (auto simp add: mult_mm_assoc)
text ‹Identity matrix is Hermitean›
lemma hermitean_eye [simp]:
shows "hermitean eye"
by (auto simp add: hermitean_def mat_adj_def mat_cnj_def)
lemma hermitean_eye' [simp]:
shows "hermitean (1, 0, 0, 1)"
by (auto simp add: hermitean_def mat_adj_def mat_cnj_def)
text ‹Unit circle matrix is Hermitean›
lemma hermitean_unit_circle [simp]:
shows "hermitean (1, 0, 0, -1)"
by (auto simp add: hermitean_def mat_adj_def mat_cnj_def)
text ‹Hermitean matrices have real determinant›
lemma mat_det_hermitean_real:
assumes "hermitean A"
shows "is_real (mat_det A)"
using assms
unfolding hermitean_def
by (metis eq_cnj_iff_real mat_det_adj)
text ‹Zero matrix is the only Hermitean matrix with both determinant and trace equal
to zero›
lemma hermitean_det_zero_trace_zero:
assumes "mat_det A = 0" and "mat_trace A = (0::complex)" and "hermitean A"
shows "A = mat_zero"
using assms
proof-
{
fix a d c
assume "a * d = cnj c * c" "a + d = 0" "cnj a = a"
from ‹a + d = 0› have "d = -a"
by (metis add_eq_0_iff)
hence "- (cor (Re a))⇧2 = (cor (cmod c))⇧2"
using ‹cnj a = a› eq_cnj_iff_real[of a]
using ‹a*d = cnj c * c›
using complex_mult_cnj_cmod[of "cnj c"]
by (simp add: power2_eq_square)
hence "- (Re a)⇧2 ≥ 0"
using zero_le_power2[of "cmod c"]
by (metis Re_complex_of_real of_real_minus of_real_power)
hence "a = 0"
using zero_le_power2[of "Re a"]
using ‹cnj a = a› eq_cnj_iff_real[of a]
by (simp add: complex_eq_if_Re_eq)
} note * = this
obtain a b c d where "A = (a, b, c, d)"
by (cases A) auto
thus ?thesis
using *[of a d c] *[of d a c]
using assms ‹A = (a, b, c, d)›
by (auto simp add: hermitean_def mat_adj_def mat_cnj_def)
qed
subsubsection ‹Bilinear and quadratic forms with Hermitean matrices›
text ‹A Hermitean matrix $(A, B, \overline{B}, D)$, for real $A$ and $D$, gives rise to bilinear form
$A\cdot \overline{v_{11}} \cdot v_{21}+\overline{B} \cdot \overline{v_{12}} \cdot v_{21} +
B \cdot \overline{v_{11}} \cdot v_{22}+D\cdot \overline{v_{12}}\cdot v_{22}$ (acting on vectors $(v_{11}, v_{12})$ and
$(v_{21}, v_{22})$) and to the quadratic form $A \cdot \overline{v_1} \cdot v_1+\overline{B}\cdot \overline{v_2}\cdot v_1 +
B\cdot \overline{v_1}\cdot v_2 + D\cdot \overline{v_2} \cdot v_2$ (acting on the vector $(v_1, v_2)$).›
lemma bilinear_form_hermitean_commute:
assumes "hermitean H"
shows "bilinear_form v1 v2 H = cnj (bilinear_form v2 v1 H)"
proof-
have "v2 *⇩v⇩m mat_cnj H *⇩v⇩v vec_cnj v1 = vec_cnj v1 *⇩v⇩v (mat_adj H *⇩m⇩v v2)"
by (subst mult_vv_commute, subst mult_mv_mult_vm, simp add: mat_adj_def mat_transpose_mat_cnj)
also
have "… = bilinear_form v1 v2 H"
using assms
by (simp add: mult_vv_mv hermitean_def)
finally
show ?thesis
by (simp add: cnj_mult_vv vec_cnj_mult_vm)
qed
lemma quad_form_hermitean_real:
assumes "hermitean H"
shows "is_real (quad_form z H)"
using assms
by (subst eq_cnj_iff_real[symmetric]) (simp del: quad_form_def add: hermitean_def)
lemma quad_form_vec_cnj_mat_cnj:
assumes "hermitean H"
shows "quad_form (vec_cnj z) (mat_cnj H) = quad_form z H"
using assms
using cnj_mult_vv cnj_quad_form hermitean_def vec_cnj_mult_vm by auto
subsubsection ‹Eigenvalues, eigenvectors and diagonalization of Hermitean matrices›
text ‹Hermitean matrices have real eigenvalues›
lemma hermitean_eigenval_real:
assumes "hermitean H" and "eigenval k H"
shows "is_real k"
proof-
from assms obtain v where "v ≠ vec_zero" "H *⇩m⇩v v = k *⇩s⇩v v"
unfolding eigenval_def
by blast
have "k * (v *⇩v⇩v vec_cnj v) = (k *⇩s⇩v v) *⇩v⇩v (vec_cnj v)"
by (simp add: mult_vv_scale_sv1)
also have "... = (H *⇩m⇩v v) *⇩v⇩v (vec_cnj v)"
using ‹H *⇩m⇩v v = k *⇩s⇩v v›
by simp
also have "... = v *⇩v⇩v (mat_transpose H *⇩m⇩v (vec_cnj v))"
by (simp add: mult_mv_vv)
also have "... = v *⇩v⇩v (vec_cnj (mat_cnj (mat_transpose H) *⇩m⇩v v))"
by (simp add: vec_cnj_mult_mv)
also have "... = v *⇩v⇩v (vec_cnj (H *⇩m⇩v v))"
using ‹hermitean H›
by (simp add: hermitean_def mat_adj_def)
also have "... = v *⇩v⇩v (vec_cnj (k *⇩s⇩v v))"
using ‹H *⇩m⇩v v = k *⇩s⇩v v›
by simp
finally have "k * (v *⇩v⇩v vec_cnj v) = cnj k * (v *⇩v⇩v vec_cnj v)"
by (simp add: mult_vv_scale_sv2)
hence "k = cnj k"
using ‹v ≠ vec_zero›
using scalsquare_vv_zero[of v]
by (simp add: mult_vv_commute)
thus ?thesis
by (metis eq_cnj_iff_real)
qed
text ‹Non-diagonal Hermitean matrices have distinct eigenvalues›
lemma hermitean_distinct_eigenvals:
assumes "hermitean H"
shows "(∃ k⇩1 k⇩2. k⇩1 ≠ k⇩2 ∧ eigenval k⇩1 H ∧ eigenval k⇩2 H) ∨ mat_diagonal H"
proof-
obtain A B C D where HH: "H = (A, B, C, D)"
by (cases H) auto
show ?thesis
proof (cases "B = 0")
case True
thus ?thesis
using ‹hermitean H› hermitean_elems[of A B C D] HH
by auto
next
case False
have "(mat_trace H)⇧2 ≠ 4 * mat_det H"
proof (rule ccontr)
have "C = cnj B" "is_real A" "is_real D"
using hermitean_elems HH ‹hermitean H›
by auto
assume "¬ ?thesis"
hence "(A + D)⇧2 = 4*(A*D - B*C)"
using HH
by auto
hence "(A - D)⇧2 = - 4*B*cnj B"
using ‹C = cnj B›
by (auto simp add: power2_eq_square field_simps)
hence "(A - D)⇧2 / cor ((cmod B)⇧2) = -4"
using ‹B ≠ 0› complex_mult_cnj_cmod[of B]
by (auto simp add: field_simps)
hence "(Re A - Re D)⇧2 / (cmod B)⇧2 = -4"
using ‹is_real A› ‹is_real D› ‹B ≠ 0›
using Re_divide_real[of "cor ((cmod B)⇧2)" "(A - D)⇧2"]
by (auto simp add: power2_eq_square)
thus False
by (metis abs_neg_numeral abs_power2 neg_numeral_neq_numeral power_divide)
qed
show ?thesis
apply (rule disjI1)
apply (subst eigen_equation)+
using complex_quadratic_equation_monic_distinct_roots[of "-mat_trace H" "mat_det H"] ‹(mat_trace H)⇧2 ≠ 4 * mat_det H›
by auto
qed
qed
text ‹Eigenvectors corresponding to different eigenvalues of Hermitean matrices are
orthogonal›
lemma hermitean_ortho_eigenvecs:
assumes "hermitean H"
assumes "eigenpair k1 v1 H" and "eigenpair k2 v2 H" and "k1 ≠ k2"
shows "vec_cnj v2 *⇩v⇩v v1 = 0" and "vec_cnj v1 *⇩v⇩v v2 = 0"
proof-
from assms
have "v1 ≠ vec_zero" "H *⇩m⇩v v1 = k1 *⇩s⇩v v1"
"v2 ≠ vec_zero" "H *⇩m⇩v v2 = k2 *⇩s⇩v v2"
unfolding eigenpair_def
by auto
have real_k: "is_real k1" "is_real k2"
using assms
using hermitean_eigenval_real[of H k1]
using hermitean_eigenval_real[of H k2]
unfolding eigenpair_def eigenval_def
by blast+
have "vec_cnj (H *⇩m⇩v v2) = vec_cnj (k2 *⇩s⇩v v2)"
using ‹H *⇩m⇩v v2 = k2 *⇩s⇩v v2›
by auto
hence "vec_cnj v2 *⇩v⇩m H = k2 *⇩s⇩v vec_cnj v2"
using ‹hermitean H› real_k eq_cnj_iff_real[of k1] eq_cnj_iff_real[of k2]
unfolding hermitean_def
by (cases H, cases v2) (auto simp add: mat_adj_def mat_cnj_def vec_cnj_def)
have "k2 * (vec_cnj v2 *⇩v⇩v v1) = k1 * (vec_cnj v2 *⇩v⇩v v1)"
using ‹H *⇩m⇩v v1 = k1 *⇩s⇩v v1›
using ‹vec_cnj v2 *⇩v⇩m H = k2 *⇩s⇩v vec_cnj v2›
by (cases v1, cases v2, cases H)
(metis mult_vv_mv mult_vv_scale_sv1 mult_vv_scale_sv2)
thus "vec_cnj v2 *⇩v⇩v v1 = 0"
using ‹k1 ≠ k2›
by simp
hence "cnj (vec_cnj v2 *⇩v⇩v v1) = 0"
by simp
thus "vec_cnj v1 *⇩v⇩v v2 = 0"
by (simp add: cnj_mult_vv mult_vv_commute)
qed
text ‹Hermitean matrices are diagonizable by unitary matrices. Diagonal entries are
real and the sign of the determinant is preserved.›
lemma hermitean_diagonizable:
assumes "hermitean H"
shows "∃ k1 k2 M. mat_det M ≠ 0 ∧ unitary M ∧ congruence M H = (k1, 0, 0, k2) ∧
is_real k1 ∧ is_real k2 ∧ sgn (Re k1 * Re k2) = sgn (Re (mat_det H))"
proof-
from assms
have "(∃k⇩1 k⇩2. k⇩1 ≠ k⇩2 ∧ eigenval k⇩1 H ∧ eigenval k⇩2 H) ∨ mat_diagonal H"
using hermitean_distinct_eigenvals[of H]
by simp
thus ?thesis
proof
assume "∃k⇩1 k⇩2. k⇩1 ≠ k⇩2 ∧ eigenval k⇩1 H ∧ eigenval k⇩2 H"
then obtain k1 k2 where "k1 ≠ k2" "eigenval k1 H" "eigenval k2 H"
using hermitean_distinct_eigenvals
by blast
then obtain v1 v2 where "eigenpair k1 v1 H" "eigenpair k2 v2 H"
"v1 ≠ vec_zero" "v2 ≠ vec_zero"
unfolding eigenval_def eigenpair_def
by blast
hence *: "vec_cnj v2 *⇩v⇩v v1 = 0" "vec_cnj v1 *⇩v⇩v v2 = 0"
using ‹k1 ≠ k2› hermitean_ortho_eigenvecs ‹hermitean H›
by auto
obtain v11 v12 v21 v22 where vv: "v1 = (v11, v12)" "v2 = (v21, v22)"
by (cases v1, cases v2) auto
let ?nv1' = "vec_cnj v1 *⇩v⇩v v1" and ?nv2' = "vec_cnj v2 *⇩v⇩v v2"
let ?nv1 = "cor (sqrt (Re ?nv1'))"
let ?nv2 = "cor (sqrt (Re ?nv2'))"
have "?nv1' ≠ 0" "?nv2' ≠ 0"
using ‹v1 ≠ vec_zero› ‹v2 ≠ vec_zero› vv
by (simp add: scalsquare_vv_zero)+
moreover
have "is_real ?nv1'" "is_real ?nv2'"
using vv
by (auto simp add: vec_cnj_def)
ultimately
have "?nv1 ≠ 0" "?nv2 ≠ 0"
using complex_eq_if_Re_eq
by auto
have "Re (?nv1') ≥ 0" "Re (?nv2') ≥ 0"
using vv
by (auto simp add: vec_cnj_def)
obtain nv1 nv2 where "nv1 = ?nv1" "nv1 ≠ 0" "nv2 = ?nv2" "nv2 ≠ 0"
using ‹?nv1 ≠ 0› ‹?nv2 ≠ 0›
by auto
let ?M = "(1/nv1 * v11, 1/nv2 * v21, 1/nv1 * v12, 1/nv2 * v22)"
have "is_real k1" "is_real k2"
using ‹eigenval k1 H› ‹eigenval k2 H› ‹hermitean H›
by (auto simp add: hermitean_eigenval_real)
moreover
have "mat_det ?M ≠ 0"
proof (rule ccontr)
assume "¬ ?thesis"
hence "v11 * v22 = v12 * v21"
using ‹nv1 ≠ 0› ‹nv2 ≠ 0›
by (auto simp add: field_simps)
hence "∃ k. k ≠ 0 ∧ v2 = k *⇩s⇩v v1"
using vv ‹v1 ≠ vec_zero› ‹v2 ≠ vec_zero›
apply auto
apply (rule_tac x="v21/v11" in exI, force simp add: field_simps)
apply (rule_tac x="v21/v11" in exI, force simp add: field_simps)
apply (rule_tac x="v22/v12" in exI, force simp add: field_simps)
apply (rule_tac x="v22/v12" in exI, force simp add: field_simps)
done
thus False
using * ‹vec_cnj v1 *⇩v⇩v v2 = 0› ‹vec_cnj v2 *⇩v⇩v v2 ≠ 0› vv ‹?nv1' ≠ 0›
by (metis mult_vv_scale_sv2 mult_zero_right)
qed
moreover
have "unitary ?M"
proof-
have **: "cnj nv1 * nv1 = ?nv1'" "cnj nv2 * nv2 = ?nv2'"
using ‹nv1 = ?nv1› ‹nv1 ≠ 0› ‹nv2 = ?nv2› ‹nv2 ≠ 0› ‹is_real ?nv1'› ‹is_real ?nv2'›
using ‹Re (?nv1') ≥ 0› ‹Re (?nv2') ≥ 0›
by auto
have ***: "cnj nv1 * nv2 ≠ 0" "cnj nv2 * nv1 ≠ 0"
using vv ‹nv1 = ?nv1› ‹nv1 ≠ 0› ‹nv2 = ?nv2› ‹nv2 ≠ 0› ‹is_real ?nv1'› ‹is_real ?nv2'›
by auto
show ?thesis
unfolding unitary_def
using vv ** ‹?nv1' ≠ 0› ‹?nv2' ≠ 0› * ***
unfolding mat_adj_def mat_cnj_def vec_cnj_def
by simp (metis (no_types, lifting) add_divide_distrib divide_eq_0_iff divide_eq_1_iff)
qed
moreover
have "congruence ?M H = (k1, 0, 0, k2)"
proof-
have "mat_inv ?M *⇩m⇩m H *⇩m⇩m ?M = (k1, 0, 0, k2)"
proof-
have *: "H *⇩m⇩m ?M = ?M *⇩m⇩m (k1, 0, 0, k2)"
using ‹eigenpair k1 v1 H› ‹eigenpair k2 v2 H› vv ‹?nv1 ≠ 0› ‹?nv2 ≠ 0›
unfolding eigenpair_def vec_cnj_def
by (cases H) (smt mult_mm.simps vec_map.simps add.right_neutral add_cancel_left_left distrib_left fst_mult_sv mult.commute mult.left_commute mult_mv.simps mult_zero_right prod.sel(1) prod.sel(2) snd_mult_sv)
show ?thesis
using mult_mm_inv_l[of ?M "(k1, 0, 0, k2)" "H *⇩m⇩m ?M", OF ‹mat_det ?M ≠ 0› *[symmetric], symmetric]
by (simp add: mult_mm_assoc)
qed
moreover
have "mat_inv ?M = mat_adj ?M"
using ‹mat_det ?M ≠ 0› ‹unitary ?M› mult_mm_inv_r[of ?M "mat_adj ?M" eye]
by (simp add: unitary_def)
ultimately
show ?thesis
by simp
qed
moreover
have "sgn (Re k1 * Re k2) = sgn (Re (mat_det H))"
using ‹congruence ?M H = (k1, 0, 0, k2)› ‹is_real k1› ‹is_real k2›
using Re_det_sgn_congruence[of ?M H] ‹mat_det ?M ≠ 0› ‹hermitean H›
by simp
ultimately
show ?thesis
by (rule_tac x="k1" in exI, rule_tac x="k2" in exI, rule_tac x="?M" in exI) simp
next
assume "mat_diagonal H"
then obtain A D where "H = (A, 0, 0, D)"
by (cases H) auto
moreover
hence "is_real A" "is_real D"
using ‹hermitean H› hermitean_elems[of A 0 0 D]
by auto
ultimately
show ?thesis
by (rule_tac x="A" in exI, rule_tac x="D" in exI, rule_tac x="eye" in exI) (simp add: unitary_def mat_adj_def mat_cnj_def)
qed
qed
end