///|
// =====================================================================
// hermitian.mbt — 複內積空間 C^n 與 Hermitian 矩陣空間
// 內積約定:⟨u,v⟩ = Σ conj(uᵢ)vᵢ(第一變量共軛線性)
// =====================================================================
/// H-1 C^n 零向量
pub fn cvec_zero(n : Int) -> Array[C] {
Array::make(n, czero())
}
/// H-2 C^n 加法
pub fn cvec_add(a : Array[C], b : Array[C]) -> Array[C] {
let out : Array[C] = []
for i = 0; i < a.length(); i = i + 1 {
out.push(cadd(a[i], b[i]))
}
out
}
/// H-3 C^n 負元
pub fn cvec_neg(a : Array[C]) -> Array[C] {
let out : Array[C] = []
for x in a {
out.push(cneg(x))
}
out
}
/// H-4 C^n 複純量乘法
pub fn cvec_cscale(c : C, a : Array[C]) -> Array[C] {
let out : Array[C] = []
for x in a {
out.push(cmul(c, x))
}
out
}
/// H-5 C^n 實純量乘法(視為實向量空間)
pub fn cvec_scale(s : Double, a : Array[C]) -> Array[C] {
let out : Array[C] = []
for x in a {
out.push(cscale(s, x))
}
out
}
/// H-6 Hermitian 內積 ⟨u,v⟩ = Σ conj(uᵢ)vᵢ
pub fn cvec_inner(a : Array[C], b : Array[C]) -> C {
let mut s = czero()
for i = 0; i < a.length(); i = i + 1 {
s = cadd(s, cmul(cconj(a[i]), b[i]))
}
s
}
/// H-7 實值二次範數 ⟨v,v⟩ ∈ R
pub fn cvec_norm2(v : Array[C]) -> Double {
let g = cvec_inner(v, v)
g.re
}
/// H-8 範數
pub fn cvec_norm(v : Array[C]) -> Double {
cvec_norm2(v).sqrt()
}
/// H-9 C^n 之內積空間字典(視為實內積空間:取內積實部)
pub fn cvec_real_ip(n : Int) -> IPSp[Array[C]] {
ips_make(
{
zero: cvec_zero(n),
add: cvec_add,
neg: cvec_neg,
scale: cvec_scale,
},
fn(a, b) { cvec_inner(a, b).re },
)
}
/// H-10 正交性(複)
pub fn cvec_is_orthogonal(a : Array[C], b : Array[C], eps : Double) -> Bool {
cabs(cvec_inner(a, b)) < eps
}
/// H-11 複 Gram–Schmidt 標準正交化
pub fn cvec_orthonormal(vs : Array[Array[C]], eps : Double) -> Array[Array[C]] {
let out : Array[Array[C]] = []
for v in vs {
let mut w = v
for u in out {
// c = ⟨u,w⟩/⟨u,u⟩; w -= c·u
let c = cdiv(cvec_inner(u, w), cfrom_real(cvec_norm2(u)))
w = cvec_add(w, cvec_cscale(cneg(c), u))
}
let nrm = cvec_norm(w)
if nrm > eps {
out.push(cvec_scale(1.0 / nrm, w))
}
}
out
}
/// 複矩陣
pub struct CMat {
rows : Int
cols : Int
data : Array[C]
}
/// H-12 複零矩陣
pub fn cmat_new(rows : Int, cols : Int) -> CMat {
{ rows, cols, data: Array::make(rows * cols, czero()) }
}
/// H-13 取元素
pub fn cmat_get(m : CMat, i : Int, j : Int) -> C {
m.data[i * m.cols + j]
}
/// H-14 設元素
pub fn cmat_set(m : CMat, i : Int, j : Int, v : C) -> Unit {
m.data[i * m.cols + j] = v
}
/// H-15 共軛轉置(dagger)
pub fn cmat_dagger(m : CMat) -> CMat {
let out = cmat_new(m.cols, m.rows)
for i = 0; i < m.rows; i = i + 1 {
for j = 0; j < m.cols; j = j + 1 {
cmat_set(out, j, i, cconj(cmat_get(m, i, j)))
}
}
out
}
/// H-16 Hermitian 判定 A = A†
pub fn cmat_is_hermitian(m : CMat, eps : Double) -> Bool {
let d = cmat_dagger(m)
let mut ok = true
for i = 0; i < m.rows * m.cols; i = i + 1 {
if !ceq_eps(m.data[i], d.data[i], eps) {
ok = false
}
}
ok
}
/// H-17 複矩陣-向量乘
pub fn cmat_vec(m : CMat, x : Array[C]) -> Array[C] {
let out : Array[C] = []
for i = 0; i < m.rows; i = i + 1 {
let mut s = czero()
for j = 0; j < m.cols; j = j + 1 {
s = cadd(s, cmul(cmat_get(m, i, j), x[j]))
}
out.push(s)
}
out
}
/// H-18 複矩陣乘法
pub fn cmat_mul(a : CMat, b : CMat) -> CMat {
let out = cmat_new(a.rows, b.cols)
for i = 0; i < a.rows; i = i + 1 {
for k = 0; k < b.cols; k = k + 1 {
let mut s = czero()
for j = 0; j < a.cols; j = j + 1 {
s = cadd(s, cmul(cmat_get(a, i, j), cmat_get(b, j, k)))
}
cmat_set(out, i, k, s)
}
}
out
}
/// H-19 複 Rayleigh 商(Hermitian 時為實數)
pub fn cmat_rayleigh(m : CMat, x : Array[C]) -> Double {
let ax = cmat_vec(m, x)
cvec_inner(x, ax).re / cvec_norm2(x)
}
/// H-20 Hermitian 矩陣特徵值(複 Jacobi 旋轉,非對角元消去)
/// 回傳實特徵值陣列與酉矩陣 Q(行為特徵向量)
pub fn cmat_jacobi_hermitian(
m : CMat,
max_sweeps : Int,
) -> (Array[Double], CMat) {
let n = m.rows
let s = m.data.copy()
let q = cmat_new(n, n)
for i = 0; i < n; i = i + 1 {
cmat_set(q, i, i, cone())
}
for _sw = 0; _sw < max_sweeps; _sw = _sw + 1 {
let mut off = 0.0
for i = 0; i < n; i = i + 1 {
for j = i + 1; j < n; j = j + 1 {
off = off + cnorm2(s[i * n + j])
}
}
if off.sqrt() < 1.0e-13 {
break
}
for p = 0; p < n - 1; p = p + 1 {
for r = p + 1; r < n; r = r + 1 {
let apq = s[p * n + r]
if cabs(apq) < 1.0e-16 {
continue
}
// G = P·R:先相位對角化 P[r,r]=e^{−iθ},再實旋轉 R
let rho = cabs(apq)
let phase = cdiv(apq, cfrom_real(rho)) // e^{iθ}
let phc = cconj(phase) // e^{−iθ}
let app = s[p * n + p].re
let aqq = s[r * n + r].re
let tau = (aqq - app) / (2.0 * rho)
// 歸零條件之最小根:t² − 2τt − 1 = 0
let t =
if tau >= 0.0 {
-1.0 / (tau + (tau * tau + 1.0).sqrt())
} else {
1.0 / (-tau + (tau * tau + 1.0).sqrt())
}
let c = 1.0 / (t * t + 1.0).sqrt()
let ss = t * c
// S ← G† S G:先更新行(右乘 G)
for i = 0; i < n; i = i + 1 {
let sip = s[i * n + p]
let siq = s[i * n + r]
s[i * n + p] = cadd(cscale(c, sip), cmul(cscale(ss, phc), siq))
s[i * n + r] = cadd(cscale(-ss, sip), cmul(cscale(c, phc), siq))
}
// 再更新列(左乘 G†)
for j = 0; j < n; j = j + 1 {
let spj = s[p * n + j]
let sqj = s[r * n + j]
s[p * n + j] = cadd(cscale(c, spj), cmul(cscale(ss, phase), sqj))
s[r * n + j] = cadd(cscale(-ss, spj), cmul(cscale(c, phase), sqj))
}
// 累積 Q ← Q G(行變換)
for i = 0; i < n; i = i + 1 {
let qip = q.data[i * n + p]
let qiq = q.data[i * n + r]
q.data[i * n + p] = cadd(cscale(c, qip), cmul(cscale(ss, phc), qiq))
q.data[i * n + r] = cadd(cscale(-ss, qip), cmul(cscale(c, phc), qiq))
}
}
}
}
let vals : Array[Double] = []
for i = 0; i < n; i = i + 1 {
vals.push(s[i * n + i].re)
}
(vals, { rows: n, cols: n, data: q.data })
}
/// H-21 酉性誤差 ‖Q†Q − I‖_F
pub fn cmat_unitary_error(q : CMat) -> Double {
let prod = cmat_mul(cmat_dagger(q), q)
let mut err = 0.0
for i = 0; i < prod.rows; i = i + 1 {
for j = 0; j < prod.cols; j = j + 1 {
let want = if i == j { 1.0 } else { 0.0 }
let d = csub(cmat_get(prod, i, j), cfrom_real(want))
err = err + cnorm2(d)
}
}
err.sqrt()
}