---
title: "张量网络"
description: "理解 ArcTN 如何用张量的腿、输出腿和维度表表示普通边、超边与开放指标。"
eyebrow: "核心概念"
---

## 结构模型 {#structural-model}

ArcTN 的规划器先读取网络结构，不读取张量数值。一个网络由 `inputs`、`output` 和 `size_dict` 三部分组成：张量是节点，同名腿表示共享指标，维度表给出每个指标的取值范围。

```diagram
tensor-network
示例 A[a,b]、B[b,c]、C[c,d]：b、c 是内部腿，a、d 列入 output 并保留为结果轴。
```

| 字段 | 内容 | 需要保持的语义 |
| --- | --- | --- |
| inputs | 每个输入张量的腿标签列表 | 外层顺序对应张量顺序，内层顺序对应张量轴顺序 |
| output | 最终结果保留的腿 | 顺序定义结果数组的轴顺序 |
| size\_dict | 腿标签到维度的映射 | 必须覆盖全部已使用腿，且不能包含未使用腿 |

## 普通边、超边与输出腿 {#edges-and-open-legs}

一条腿出现在两个张量上且未列入 `output` 时，对应普通内部边；出现在三个或更多不同张量上时，对应超边（hyperedge）。因此 ArcTN 的数据模型不局限于普通图。列入 `output` 的腿不会在收缩中消去，最终会按 `output` 的顺序排列。

| 腿的出现方式 | 结构含义 | 执行结果 |
| --- | --- | --- |
| 出现在多个不同张量，且不在 output | 内部边或超边 | 沿该指标求和 |
| 列入 output | 开放腿 | 保留为结果轴 |
| 在同一输入张量中出现两次，既不在 output 中，也不被其他张量引用 | 迹（trace） | 两个轴取相同坐标后求和 |
| 在同一输入张量中出现两次，且被其他张量引用或列入 output | 取对角（diagonal extraction） | 两个轴合并为一个保留指标 |

> [!WARNING]
> **重复腿的边界**
>
> 同一条腿在一个输入张量中最多出现两次。三次或更多的重复腿当前不受支持，会在网络校验时返回错误。

## 一个三张量网络 {#example}

Python 高层接口的结构输入

```python
# A[a,b] B[b,c] C[c,d] -> Y[a,d]
inputs = [
    ("a", "b"),
    ("b", "c"),
    ("c", "d"),
]
output = ("a", "d")
size_dict = {"a": 2, "b": 3, "c": 4, "d": 5}
```

腿 `b` 和 `c` 是内部腿，收缩完成后被消去；`a` 和 `d` 是输出腿，最终结果 shape 为 `(2, 5)`。Python 接口允许使用可哈希标签，并在进入 Rust 前把标签映射为紧凑整数。

> **标签与维度**
>
> 标签只表示指标身份，不携带物理含义。两个物理上不同的指标不能因为维度相同就使用同一个标签；维度相同不等于指标相同。

## 规划前校验 {#validation}

| 检查项 | 要求 |
| --- | --- |
| 输入数量 | 至少有一个输入张量 |
| 维度 | 每条已使用腿都有维度，维度为正整数，元素数计算不能溢出 |
| 维度表 | 不能缺少已使用腿，也不能保留完全未使用的条目 |
| 输出腿 | 不能重复，并且必须来自输入网络 |
| 重复腿 | 同一腿在单个输入张量中最多出现两次 |
| 数值执行 | 每个数组的 shape 必须与对应 `inputs` 和 `size_dict` 一致 |

```rust
use arctn::TensorNetwork;

let net = TensorNetwork {
    name: "example".into(),
    inputs: vec![vec![0, 1], vec![1, 2], vec![2, 3]],
    output: vec![0, 3],
    size_dict: [(0, 2), (1, 3), (2, 4), (3, 5)]
        .into_iter().collect(),
};
net.validate()?;
```

> **校验不是路径搜索**
>
> 直接用 Rust 结构体字段构造 `TensorNetwork` 时应显式调用 `validate()`。JSON、Python、规划、路径重放和执行入口也会在各自边界执行所需校验。
