Theory Unitary_Matrices
subsection ‹Generalized Unitary Matrices›
theory Unitary_Matrices
imports Matrices More_Complex
begin
text ‹In this section (generalized) $2\times 2$ unitary matrices are introduced.›
text ‹Unitary matrices›
definition unitary where
  "unitary M ⟷ mat_adj M *⇩m⇩m M = eye"
text ‹Generalized unitary matrices›
definition unitary_gen where
  "unitary_gen M ⟷
   (∃ k::complex. k ≠ 0 ∧ mat_adj M *⇩m⇩m M = k *⇩s⇩m eye)"
text ‹Scalar can be always be a positive real›
lemma unitary_gen_real:
  assumes "unitary_gen M"
  shows "(∃ k::real. k > 0 ∧ mat_adj M *⇩m⇩m M = cor k *⇩s⇩m eye)"
proof-
  obtain k where *: "mat_adj M *⇩m⇩m M = k *⇩s⇩m eye" "k ≠ 0"
    using assms
    by (auto simp add: unitary_gen_def)
  obtain a b c d where "M = (a, b, c, d)"
    by (cases M) auto
  hence "k = cor ((cmod a)⇧2) + cor ((cmod c)⇧2)"
    using *
    by (subst  complex_mult_cnj_cmod[symmetric])+ (auto simp add: mat_adj_def mat_cnj_def)
  hence "is_real k ∧ Re k > 0"
    using ‹k ≠ 0›
    by (smt (verit) add_cancel_left_left arg_0_iff arg_complex_of_real_positive not_sum_power2_lt_zero of_real_0 plus_complex.simps(1) plus_complex.simps(2))
  thus ?thesis
    using *
    by (rule_tac x="Re k" in exI) simp
qed
text ‹Generalized unitary matrices can be factored into a product of a unitary matrix and a real
positive scalar multiple of the identity matrix›
lemma unitary_gen_unitary:
  shows "unitary_gen M ⟷
         (∃ k M'. k > 0 ∧ unitary M' ∧ M = (cor k *⇩s⇩m eye) *⇩m⇩m M')" (is "?lhs = ?rhs")
proof
  assume ?lhs
  then obtain k where *: "k>0" "mat_adj M *⇩m⇩m M = cor k *⇩s⇩m eye"
    using unitary_gen_real[of M]
    by auto
  let ?k' = "cor (sqrt k)"
  have "?k' * cnj ?k' = cor k"
    using ‹k > 0›
    by simp
  moreover
  have "Re ?k' > 0" "is_real ?k'" "?k' ≠ 0"
    using ‹k > 0›
    by auto
  ultimately
  show ?rhs
    using * mat_eye_l
    unfolding unitary_gen_def unitary_def
    by (rule_tac x="Re ?k'" in exI) (rule_tac x="(1/?k')*⇩s⇩mM" in exI, simp add: mult_sm_mm[symmetric])
next
  assume ?rhs
  then obtain k M' where "k > 0" "unitary M'" "M = (cor k *⇩s⇩m eye) *⇩m⇩m M'"
    by blast
  hence "M = cor k *⇩s⇩m M'"
    using mult_sm_mm[of "cor k" eye M'] mat_eye_l
    by simp
  thus ?lhs
    using ‹unitary M'› ‹k > 0›
    by (simp add: unitary_gen_def unitary_def)
qed
text ‹When they represent Möbius transformations, eneralized unitary matrices fix the imaginary unit circle. Therefore, they
fix a Hermitean form with (2, 0) signature (two positive and no negative diagonal elements).›
lemma unitary_gen_iff':
  shows "unitary_gen M ⟷ 
         (∃ k::complex. k ≠ 0 ∧ congruence M (1, 0, 0, 1) = k *⇩s⇩m (1, 0, 0, 1))"
  unfolding unitary_gen_def
  using mat_eye_r
  by (auto simp add: mult.assoc)
text ‹Unitary matrices are special cases of general unitary matrices›
lemma unitary_unitary_gen [simp]:
  assumes "unitary M" 
  shows "unitary_gen M"
  using assms
  unfolding unitary_gen_def unitary_def
  by auto
text ‹Generalized unitary matrices are regular›
lemma unitary_gen_regular:
  assumes "unitary_gen M"
  shows "mat_det M ≠ 0"
proof-
  from assms obtain k where
    "k ≠ 0" "mat_adj M *⇩m⇩m M = k *⇩s⇩m eye"
    unfolding unitary_gen_def
    by auto
  hence "mat_det (mat_adj M *⇩m⇩m M) ≠ 0"
    by simp
  thus ?thesis
    by (simp add: mat_det_adj)
qed
lemmas unitary_regular = unitary_gen_regular[OF unitary_unitary_gen]
subsubsection ‹Group properties›
text ‹Generalized $2\times 2$ unitary matrices form a group under
multiplication (usually denoted by $GU(2, \mathbb{C})$). The group is closed
under non-zero complex scalar multiplication. Since these matrices are
always regular, they form a subgroup of general linear group (usually
denoted by $GL(2, \mathbb{C})$) of all regular matrices.›
lemma unitary_gen_scale [simp]:
  assumes "unitary_gen M" and "k ≠ 0"
  shows "unitary_gen (k *⇩s⇩m M)"
  using assms
  unfolding unitary_gen_def
  by auto
lemma unitary_comp:
  assumes "unitary M1" and "unitary M2"
  shows "unitary (M1 *⇩m⇩m M2)"
  using assms
  unfolding unitary_def
  by (metis mat_adj_mult_mm mat_eye_l mult_mm_assoc)
lemma unitary_gen_comp:
  assumes "unitary_gen M1" and "unitary_gen M2"
  shows "unitary_gen (M1 *⇩m⇩m M2)"
proof-
  obtain k1 k2 where *: "k1 * k2 ≠ 0" "mat_adj M1 *⇩m⇩m M1 = k1 *⇩s⇩m eye" "mat_adj M2 *⇩m⇩m M2 = k2 *⇩s⇩m eye"
    using assms
    unfolding unitary_gen_def
    by auto
  have "mat_adj M2 *⇩m⇩m mat_adj M1 *⇩m⇩m (M1 *⇩m⇩m M2) = mat_adj M2 *⇩m⇩m (mat_adj M1 *⇩m⇩m M1) *⇩m⇩m M2"
    by (auto simp add: mult_mm_assoc)
  also have "... = mat_adj M2 *⇩m⇩m ((k1 *⇩s⇩m eye) *⇩m⇩m M2)"
    using *
    by (auto simp add: mult_mm_assoc)
  also have "... = mat_adj M2 *⇩m⇩m (k1 *⇩s⇩m M2)"
    using mult_sm_eye_mm[of k1 M2]
    by (simp del: eye_def)
  also have "... = k1 *⇩s⇩m (k2 *⇩s⇩m eye)"
    using *
    by auto
  finally
  show ?thesis
    using *
    unfolding unitary_gen_def
    by (rule_tac x="k1*k2" in exI, simp del: eye_def)
qed
lemma unitary_adj_eq_inv:
  shows "unitary M ⟷ mat_det M ≠ 0 ∧ mat_adj M = mat_inv M"
  using  unitary_regular[of M] mult_mm_inv_r[of M "mat_adj M" eye]  mat_eye_l[of "mat_inv M"] mat_inv_l[of M]
  unfolding unitary_def
  by - (rule, simp_all)
lemma unitary_inv:
  assumes "unitary M"
  shows "unitary (mat_inv M)"
  using assms
  unfolding unitary_adj_eq_inv
  using mat_adj_inv[of M] mat_det_inv[of M]
  by simp
lemma unitary_gen_inv:
  assumes "unitary_gen M"
  shows "unitary_gen (mat_inv M)"
proof-
    obtain k M' where "0 < k" "unitary M'" "M = cor k *⇩s⇩m eye *⇩m⇩m M'"
      using unitary_gen_unitary[of M] assms
      by blast
    hence "mat_inv M = cor (1/k) *⇩s⇩m mat_inv M'"
      by (metis mat_inv_mult_sm mult_sm_eye_mm norm_not_less_zero of_real_1 of_real_divide of_real_eq_0_iff sgn_1_neg sgn_greater sgn_if sgn_pos sgn_sgn)
    thus ?thesis
      using ‹k > 0› ‹unitary M'›
      by (subst unitary_gen_unitary[of "mat_inv M"]) (rule_tac x="1/k" in exI, rule_tac x="mat_inv M'" in exI, metis divide_pos_pos mult_sm_eye_mm unitary_inv zero_less_one)
  qed
subsubsection ‹The characterization in terms of matrix elements›
text ‹Special matrices are those having the determinant equal to 1. We first give their characterization.›
lemma unitary_special:
  assumes "unitary M" and "mat_det M = 1"
  shows "∃ a b. M = (a, b, -cnj b, cnj a)"
proof-
  have "mat_adj M = mat_inv M"
    using assms mult_mm_inv_r[of M "mat_adj M" "eye"] mat_eye_r mat_eye_l
    by (simp add: unitary_def)
  thus ?thesis
    using ‹mat_det M = 1›
    by (cases M) (auto simp add: mat_adj_def mat_cnj_def)
qed
lemma unitary_gen_special:
  assumes "unitary_gen M" and "mat_det M = 1"
  shows "∃ a b. M = (a, b, -cnj b, cnj a)"
proof-
  from assms
  obtain k where *: "k ≠ 0" "mat_adj M *⇩m⇩m M = k *⇩s⇩m eye"
    unfolding unitary_gen_def
    by auto
  hence "mat_det (mat_adj M *⇩m⇩m M) = k*k"
    by simp
  hence "k*k = 1"
    using assms(2)
    by (simp add: mat_det_adj)
  hence "k = 1 ∨ k = -1"
    using square_eq_1_iff[of k]
    by simp
  moreover
  have "mat_adj M = k *⇩s⇩m mat_inv M"
    using *
    using assms mult_mm_inv_r[of M "mat_adj M" "k *⇩s⇩m eye"] mat_eye_r mat_eye_l
    by simp (metis mult_sm_eye_mm *(2))
  moreover
  obtain a b c d where "M = (a, b, c, d)"
    by (cases M) auto
  ultimately
  have "M = (a, b, -cnj b, cnj a) ∨ M = (a, b, cnj b, -cnj a)"
    using assms(2)
    by (auto simp add: mat_adj_def mat_cnj_def)
  moreover
  have "Re (- (cor (cmod a))⇧2 - (cor (cmod b))⇧2) < 1"
    by (smt (verit) cmod_square complex_norm_square minus_complex.simps(1) of_real_power realpow_square_minus_le uminus_complex.simps(1))
  hence "- (cor (cmod a))⇧2 - (cor (cmod b))⇧2 ≠ 1"
    by force
  hence "M ≠ (a, b, cnj b, -cnj a)"
    using ‹mat_det M = 1› complex_mult_cnj_cmod[of a] complex_mult_cnj_cmod[of b]
    by auto
  ultimately
  show ?thesis
    by auto
qed
text ‹A characterization of all generalized unitary matrices›
lemma unitary_gen_iff:
  shows "unitary_gen M ⟷ 
         (∃ a b k. k ≠ 0 ∧ mat_det (a, b, -cnj b, cnj a) ≠ 0 ∧
                           M = k *⇩s⇩m (a, b, -cnj b, cnj a))" (is "?lhs = ?rhs")
proof
  assume ?lhs
  obtain d where *: "d*d = mat_det M"
    using ex_complex_sqrt
    by auto
  hence "d ≠ 0"
    using unitary_gen_regular[OF ‹unitary_gen M›]
    by auto
  from ‹unitary_gen M›
  obtain k where "k ≠ 0" "mat_adj M *⇩m⇩m M = k *⇩s⇩m eye"
    unfolding unitary_gen_def
    by auto
  hence "mat_adj ((1/d)*⇩s⇩mM) *⇩m⇩m ((1/d)*⇩s⇩mM) = (k / (d*cnj d)) *⇩s⇩m eye"
    by simp
  obtain a b where "(a, b, - cnj b, cnj a) = (1 / d) *⇩s⇩m M"
    using unitary_gen_special[of "(1 / d) *⇩s⇩m M"]  ‹unitary_gen M› *  unitary_gen_regular[of M] ‹d ≠ 0›
    by force
  moreover
  hence "mat_det (a, b, - cnj b, cnj a) ≠ 0"
    using unitary_gen_regular[OF ‹unitary_gen M›] ‹d ≠ 0›
    by auto
  ultimately
  show ?rhs
    apply (rule_tac x="a" in exI, rule_tac x="b" in exI, rule_tac x="d" in exI)
    using mult_sm_inv_l[of "1/d" M]
    by (auto simp add: field_simps)
next
  assume ?rhs
  then obtain a b k where "k ≠ 0 ∧ mat_det (a, b, - cnj b, cnj a) ≠ 0 ∧ M = k *⇩s⇩m (a, b, - cnj b, cnj a)"
    by auto
  thus ?lhs
    unfolding unitary_gen_def
    apply (auto simp add: mat_adj_def mat_cnj_def)
    using mult_eq_0_iff[of "cnj k * k" "cnj a * a + cnj b * b"]
    by (auto simp add: field_simps)
qed
text ‹A characterization of unitary matrices›
lemma unitary_iff:
  shows "unitary M ⟷
         (∃ a b k. (cmod a)⇧2 + (cmod b)⇧2 ≠ 0 ∧ 
                           (cmod k)⇧2 = 1 / ((cmod a)⇧2 + (cmod b)⇧2) ∧
                           M = k *⇩s⇩m (a, b, -cnj b, cnj a))" (is "?lhs = ?rhs")
proof
  assume ?lhs
  obtain k a b where *: "M = k *⇩s⇩m (a, b, -cnj b, cnj a)" "k ≠ 0" "mat_det (a, b, -cnj b, cnj a) ≠ 0"
    using unitary_gen_iff  unitary_unitary_gen[OF ‹unitary M›]
    by auto
  have md: "mat_det (a, b, -cnj b, cnj a) = cor ((cmod a)⇧2 + (cmod b)⇧2)"
    by (auto simp add: complex_mult_cnj_cmod)
  have "k * cnj k * mat_det (a, b, -cnj b, cnj a) = 1"
    using ‹unitary M› *
    unfolding unitary_def
    by (auto simp add: mat_adj_def mat_cnj_def field_simps)
  hence "(cmod k)⇧2 * ((cmod a)⇧2 + (cmod b)⇧2) = 1"
    by (metis (mono_tags, lifting) complex_norm_square md of_real_1 of_real_eq_iff of_real_mult)
  thus ?rhs
    using * mat_eye_l
    apply (rule_tac x="a" in exI, rule_tac x="b" in exI, rule_tac x="k" in exI)
    apply (auto simp add: complex_mult_cnj_cmod)
    by (metis ‹(cmod k)⇧2 * ((cmod a)⇧2 + (cmod b)⇧2) = 1› mult_eq_0_iff nonzero_eq_divide_eq zero_neq_one)
next
  assume ?rhs
  then obtain a b k where  *: "(cmod a)⇧2 + (cmod b)⇧2 ≠ 0" "(cmod k)⇧2 = 1 / ((cmod a)⇧2 + (cmod b)⇧2)" "M = k *⇩s⇩m (a, b, -cnj b, cnj a)"
    by auto
  have "(k * cnj k) * (a * cnj a) + (k * cnj k) * (b * cnj b) = 1"
    apply (subst complex_mult_cnj_cmod)+
    using *(1-2)
    by (metis (no_types, lifting) distrib_left nonzero_eq_divide_eq of_real_1 of_real_add of_real_divide of_real_eq_0_iff)
  thus ?lhs
    using *
    unfolding unitary_def
    by (simp add: mat_adj_def mat_cnj_def field_simps)
qed
end