///|
// =====================================================================
// tensor.mbt — 張量積空間 R^m ⊗ R^n(以 m×n 係數陣列表示)
// 與線性映射空間、矩陣空間之自然同構由測試自證
// =====================================================================
/// 張量(R^m ⊗ R^n 之元素)
pub struct Tensor {
m : Int
n : Int
data : Array[Double]
} derive(Debug, Eq)
/// T-1 零張量
pub fn tensor_zero(m : Int, n : Int) -> Tensor {
{ m, n, data: Array::make(m * n, 0.0) }
}
/// T-2 純張量 u ⊗ v
pub fn pure_tensor(u : Array[Double], v : Array[Double]) -> Tensor {
let out = tensor_zero(u.length(), v.length())
for i = 0; i < u.length(); i = i + 1 {
for j = 0; j < v.length(); j = j + 1 {
out.data[i * v.length() + j] = u[i] * v[j]
}
}
out
}
/// T-3 加法
pub fn tensor_add(a : Tensor, b : Tensor) -> Tensor {
let out = tensor_zero(a.m, a.n)
for i = 0; i < a.m * a.n; i = i + 1 {
out.data[i] = a.data[i] + b.data[i]
}
out
}
/// T-4 純量乘法
pub fn tensor_scale(c : Double, a : Tensor) -> Tensor {
let out = tensor_zero(a.m, a.n)
for i = 0; i < a.m * a.n; i = i + 1 {
out.data[i] = c * a.data[i]
}
out
}
/// T-5 誘導內積 ⟨Σ aᵢⱼ eᵢ⊗fⱼ, Σ bᵢⱼ eᵢ⊗fⱼ⟩ = Σ aᵢⱼbᵢⱼ
pub fn tensor_inner(a : Tensor, b : Tensor) -> Double {
let mut s = 0.0
for i = 0; i < a.m * a.n; i = i + 1 {
s = s + a.data[i] * b.data[i]
}
s
}
/// T-6 內積空間字典(R^m ⊗ R^n)
pub fn tensor_ip(m : Int, n : Int) -> IPSp[Tensor] {
ips_make(
{
zero: tensor_zero(m, n),
add: tensor_add,
neg: fn(t) { tensor_scale(-1.0, t) },
scale: tensor_scale,
},
tensor_inner,
)
}
/// T-7 與矩陣空間之同構(平坦化)
pub fn tensor_to_mat(t : Tensor) -> Mat {
{ rows: t.m, cols: t.n, data: t.data.copy() }
}
/// T-8 矩陣 → 張量(同構之逆)
pub fn mat_to_tensor(m : Mat) -> Tensor {
{ m: m.rows, n: m.cols, data: m.data.copy() }
}
/// T-9 全收縮(m = n 時):Σᵢ tᵢᵢ ∈ R
pub fn tensor_contract(t : Tensor) -> Double {
let k = if t.m < t.n { t.m } else { t.n }
let mut s = 0.0
for i = 0; i < k; i = i + 1 {
s = s + t.data[i * t.n + i]
}
s
}
/// T-10 單腿收縮:以 φ ∈ (R^m)* 收縮第一腿,得 R^n 之向量
pub fn tensor_contract_first(t : Tensor, phi : Array[Double]) -> Array[Double] {
let out = Array::make(t.n, 0.0)
for j = 0; j < t.n; j = j + 1 {
let mut s = 0.0
for i = 0; i < t.m; i = i + 1 {
s = s + phi[i] * t.data[i * t.n + j]
}
out[j] = s
}
out
}
/// T-11 單腿收縮:以 ψ ∈ (R^n)* 收縮第二腿,得 R^m 之向量
pub fn tensor_contract_second(t : Tensor, psi : Array[Double]) -> Array[Double] {
let out = Array::make(t.m, 0.0)
for i = 0; i < t.m; i = i + 1 {
let mut s = 0.0
for j = 0; j < t.n; j = j + 1 {
s = s + t.data[i * t.n + j] * psi[j]
}
out[i] = s
}
out
}
/// T-12 雙線性求值:(φ ⊗ ψ)(T) = Σ tᵢⱼ φᵢ ψⱼ
pub fn tensor_bilinear_eval(
t : Tensor,
phi : Array[Double],
psi : Array[Double],
) -> Double {
let mut s = 0.0
for i = 0; i < t.m; i = i + 1 {
for j = 0; j < t.n; j = j + 1 {
s = s + t.data[i * t.n + j] * phi[i] * psi[j]
}
}
s
}
/// T-13 線性映射之張量積 A ⊗ B(Kronecker)
pub fn tensor_of_maps(a : Mat, b : Mat) -> Tensor {
let k = mat_kronecker(a, b)
mat_to_tensor(k)
}
/// T-14 張量秩上界估计(平坦化矩陣之秩)
pub fn tensor_flatten_rank(t : Tensor, eps : Double) -> Int {
mat_rank(tensor_to_mat(t), eps)
}