张量

oCAS 提供带显式指标管理的基础张量代数。Tensor 携带命名指标槽 (上标/下标)、可选的对称性元数据,并可转换为 Atom 表达式进行符号处理。


指标槽

每个张量指标具有:

属性类型含义
labelAtom指标名(通常为希腊字母或 i、j 等)
positionIndexPositionUpper(逆变)或 Lower(协变)
#![allow(unused)]
fn main() {
use ocas_core::arena::Arena;
use ocas_atom::AtomArena;
use ocas_atom::tensor::{IndexSlot, IndexPosition};

let arena = Arena::new();
let ctx = AtomArena::new(&arena);

let mu = IndexSlot::new(ctx.var("mu"), IndexPosition::Upper);
let nu = IndexSlot::new(ctx.var("nu"), IndexPosition::Lower);
}

创建张量

Tensor 由名称(Symbol)和指标槽向量定义:

#![allow(unused)]
fn main() {
use ocas_core::arena::Arena;
use ocas_atom::{AtomArena, Symbol};
use ocas_atom::tensor::{Tensor, IndexSlot, IndexPosition, Symmetry};

let arena = Arena::new();
let ctx = AtomArena::new(&arena);

let slots = vec![
    IndexSlot::new(ctx.var("mu"), IndexPosition::Upper),
    IndexSlot::new(ctx.var("nu"), IndexPosition::Lower),
];
let t = Tensor::new(Symbol::new("g"), slots);

println!("rank = {}", t.rank());       // 2
println!("name = {}", t.name());       // g
}

可选地附加对称性元数据:

#![allow(unused)]
fn main() {
let symmetric = t.clone().with_symmetry(Symmetry::Symmetric);
let antisymmetric = t.clone().with_symmetry(Symmetry::Antisymmetric);
}

对称性元数据对下游消费者是建议性的;张量代数运算不会自动对称化。


缩并

contract 接受两个张量,返回标量(当所有指标都缩并时)或含剩余自由 指标的 TensorProduct:

#![allow(unused)]
fn main() {
use ocas_core::arena::Arena;
use ocas_atom::{AtomArena, Symbol};
use ocas_atom::tensor::{contract, Contracted, IndexSlot, IndexPosition, Tensor};

let arena = Arena::new();
let ctx = AtomArena::new(&arena);

// 缩并两个 1 阶张量:A^μ B_μ → 标量
let a = Tensor::new(Symbol::new("A"), vec![
    IndexSlot::new(ctx.var("mu"), IndexPosition::Upper),
]);
let b = Tensor::new(Symbol::new("B"), vec![
    IndexSlot::new(ctx.var("mu"), IndexPosition::Lower),
]);

match contract(&ctx, &a, &b) {
    Contracted::Scalar(expr) => println!("scalar: {}", expr),
    Contracted::Product(tp) => {
        for f in &tp.factors {
            println!("free factor: {}", f.name());
        }
    }
}
}

缩并按标签和相反位置匹配指标。单次调用可缩并多对匹配指标。


对称化

symmetrise_sign 返回张量反对称化的符号:对哑指标(已缩并标签)的 偶排列返回 +1,奇排列返回 -1。这在计算类行列式表达式时很有用。

#![allow(unused)]
fn main() {
use ocas_atom::tensor::symmetrise_sign;

let sign = symmetrise_sign(&tensor);
}

转换为 Atom

张量可通过 to_atom 降级为标准 Atom 表达式:

#![allow(unused)]
fn main() {
let atom = tensor.to_atom(&ctx);
println!("{}", atom);  // 例如 g(mu, nu)
}

这允许张量参与通用符号处理流水线(重写、化简、微分)。


Python 与 C 用法

Python

from ocas import Tensor, contract_tensors, tensor_symmetrise_sign

# 创建 2 阶张量
g = Tensor("g", [("mu", "upper"), ("nu", "lower")])
print(g.rank())    # 2
print(g.name())    # g

# 缩并两个张量
A = Tensor("A", [("mu", "upper")])
B = Tensor("B", [("mu", "lower")])
result = contract_tensors(A, B)
print(result)      # 标量表达式

# 反对称化符号
sign = tensor_symmetrise_sign(g)

C

#include <ocas.h>

int err = 0;
/* 创建张量 A^μ(slots 为 "label,position;..." 字符串,symmetry 可传 NULL) */
struct ocas_OcasTensor *A = ocas_tensor_create("A", "mu,upper", NULL, &err);

/* 查询阶数 */
size_t rank = ocas_tensor_rank(A);  /* 1 */

ocas_tensor_free(A);

完整的绑定文档见 Python API 和 C/C++ API 章节。


张量规范化(0.22.0)

基于图同构的规范化为张量表达式提供与指标命名无关的唯一规范形。 仅由指标重命名不同的两个张量乘积会得到相同的规范形。

工作原理

  1. 将张量表达式编码为图:张量头成为头顶点,每个指标槽成为槽顶点, 缩并成为无向边,对称性编码为隐藏的位置数据。
  2. 对图运行 McKay 细化-个体化搜索(1-WL 颜色细化 + 带自同构轨道 剪枝的个体化 DFS)。
  3. 根据规范标号重建表达式,哑指标从按维度组的池中重命名(d0、 d1、…)。
#![allow(unused)]
fn main() {
use ocas_core::arena::Arena;
use ocas_atom::{AtomArena, Symbol};
use ocas_atom::tensor::canon::canonicalize_tensors;
use ocas_atom::tensor::spec::{SymmetrySpec, TensorRegistry};

let arena = Arena::new();
let ctx = AtomArena::new(&arena);

let mut reg = TensorRegistry::new();
reg.register(Symbol::new("T"), SymmetrySpec::none());
reg.register(Symbol::new("U"), SymmetrySpec::none());

let i = ctx.var("i");
let j = ctx.var("j");
let k = ctx.var("k");
let t = ctx.fun("T", &[i, j]);
let u = ctx.fun("U", &[j, k]);
let prod = ctx.mul(&[t, u]);

let ct = canonicalize_tensors(&ctx, prod, &reg).unwrap();
println!("规范形: {}", ct.canonical_form); // T(i,d0) * U(d0,k)
}

对称性规格

规格含义
SymmetrySpec::none()所有槽位独立
SymmetrySpec::fully_symmetric(n)槽位可互换(隐藏位置)
SymmetrySpec::fully_antisymmetric(n)反对称(Ricci 恒等式验证)
自定义子集symmetric_subsets / antisymmetric_subsets / cyclic 字段

哑指标管理

dummy::refresh_dummies 将恰好出现两次的标签重命名为规范名称 (d0、d1、…),按维度组分配:

#![allow(unused)]
fn main() {
use ocas_atom::tensor::dummy::refresh_dummies;
let result = refresh_dummies(&ctx, expr, &reg)?;
// "T(i,j)*U(j,i)" → "T(d0,d1)*U(d1,d0)"
}

Young 投影子(显式展开)

young::young_project 按 Young 盘将张量展开为置换和,列反对称:

#![allow(unused)]
fn main() {
use ocas_atom::tensor::young::{YoungTableau, young_project};

// 全反对称 [1,1]: f(a,b) → f(a,b) - f(b,a)
let result = young_project(&ctx, f_ab, &YoungTableau::new(vec![1, 1]));
// 全对称 [2]: g(a,b) → g(a,b) + g(b,a)
let result = young_project(&ctx, g_ab, &YoungTableau::new(vec![2]));
}

Python API

import ocas

# 规范化
result = ocas.canonicalize_tensors("T(i,j)*U(j,k)", {"T": "none", "U": "none"})

# 对称规范化(g(b,a) == g(a,b))
result = ocas.canonicalize_tensors("g(b,a)", {"g": "symmetric"})

# Young 投影
result = ocas.young_project("f(a,b)", [1, 1])

# 刷新哑指标
result = ocas.refresh_dummies("T(i,j)*U(j,i)", {"T": "none", "U": "none"})

限制

  • 张量代数是显式的:指标按标签匹配,不使用爱因斯坦求和约定。必须手 动调用 contract。
  • Tensor 的 Symmetry 元数据仅支持 Symmetric 与 Antisymmetric; 更细粒度的对称性(子集对称 symmetric_subsets、循环对称 cyclic) 通过 0.22.0 的 SymmetrySpec/TensorRegistry 在图规范化中表达。
  • 图规范化需要先用 TensorRegistry 注册各张量的对称性规格;未注册的 张量按无对称处理。
  • 基于图的规范化不执行自动对称性强制的 Wick 缩并等物理语义操作。