---
title: "ArcTN: Rust-native tensor-network contraction planning"
description: "ArcTN is a Rust tensor-network library for contraction-path optimization, slicing, and numerical execution, with Python integration for Quimb, opt_einsum, and other tools. ArcTN accepts tensor networks; it does not directly convert quantum-circuit tasks into networks. Build those networks with a frontend such as Quimb or supply them yourself."
eyebrow: ""
---

## Licensing and permitted use {#license}

Source code that the company is entitled to license is governed by the [Arclight Non-Commercial Source-Available License 1.0](https://github.com/Quill-ArcLight/ArcTN/blob/HEAD/LICENSE), which prohibits commercial use and closed-source integration. This is not an OSI-approved open-source license. Commercial use requires separate authorization.

- Third-party dependencies retain their own licenses. Versions previously licensed under MIT / Apache retain the rights already granted; see [third-party and historical licensing notices](https://github.com/Quill-ArcLight/ArcTN/blob/HEAD/THIRD_PARTY_NOTICES.md).
- Light / Heavy dynamic libraries are licensed separately. The source license for company code does not authorize their use or distribution. Their external distribution terms have not yet been determined, and neither the initial source release nor wheels built from that source include them.

See the [ArcTN repository license section](https://github.com/Quill-ArcLight/ArcTN#license) for full details. Commercial licensing and license inquiries: [quill@arclightquantum.com](mailto:quill@arclightquantum.com).

## Tensor networks and binary contraction trees {#contraction-trees}

A tensor network describes how tensors connect through indices. With pairwise contraction, the computation can be represented by a **binary contraction tree**: leaves are input tensors, internal nodes are contractions, and the root is the final result.

One network can have different contraction trees. Consider the four-matrix product $ABCD$ below: both orders produce the same $2\times2$ result, but require different amounts of computation.

```diagram
contraction-trees
The figure counts scalar multiplications in ordinary matrix multiplication.
```

A contraction tree describes how tensors combine; a contraction path lists the actual computation steps. For example, the first tree permits either $AB$ or $CD$ to be computed first, followed by their combination. **Contraction-path optimization** searches different trees and selects a lower-cost order according to objectives such as computation and memory traffic. Light / Heavy use heuristic search and do not guarantee global optimality. See [tensor networks and contraction trees](/docs/tensor-network).

## Planning and execution {#position}

Describe a tensor network with `inputs`, `output`, and `size_dict`, and specify an objective to optimize its contraction path.

When intermediate tensors are too large, set `target_size` to split a large contraction into smaller sliced contractions. `target_size` bounds the element count of any single contraction result within each slice: for example, one million `float64` elements occupy about 8 MB. It does not bound total program memory; input arrays and temporary computation space must be counted separately.

ArcTN supports both planning alone and numerical computation. Save a path and slicing scheme as an `ArcTNExecutionPlan`, an intermediate representation (IR) between planning and execution. With arrays supplied, `arctn_contract` can plan and execute directly. Existing Quimb networks can also use ArcTN plans through `ArcTNOptimizer`.

For quantum circuits, use the [Quimb frontend](/docs/tutorial-quimb): build the circuit in Quimb and pass `optimize=ArcTNOptimizer(...)` when computing amplitudes or expectation values. ArcTN then optimizes the path without requiring you to assemble `inputs`, `output`, and `size_dict` manually. Quimb converts the task into a network and may simplify it before search; Quimb / Cotengra perform numerical contraction.

### VQE, QAOA, and quantum machine learning {#variational}

In these algorithms, a circuit frontend builds the tensor network for an amplitude, probability, or expectation value from a parameterized circuit. ArcTN optimizes its contraction path, and an outer classical optimizer updates circuit parameters from the results. With Quimb, integrate through `optimize=ArcTNOptimizer(...)` and execute through Quimb / Cotengra; alternatively, pass the network and arrays directly to `arctn_contract`.

After parameter updates, reuse an existing path if tensor order, index correspondence, dimensions, and output order remain unchanged. ArcTN is not a complete quantum machine-learning training framework: the application or framework handles losses, parameter gradients, and training loops. See the [VQE and QAOA examples](/docs/tutorial-quimb#variational) and [path reuse when parameters change](/docs/tutorial-reuse#variational-reuse).

```diagram
ecosystem
```

## From quantum circuit to contraction result {#first-example}

Two qubits start in $|00\rangle$ and undergo H, $R_y(\pi/3)$, CNOT, and $R_y(\pi/4)$ in sequence. To compute the final probability of measuring `11`, first find the amplitude $A_{11}=\langle11|U|00\rangle$, then evaluate $P(11)=|A_{11}|^2$. The basis order here is $|q_0q_1\rangle$.

### Inspecting contractions step by step {#contraction-example}

Express the initial state, quantum gates, and terminal $\langle1|$ as tensors, then ask ArcTN to search for a path. The diagram matches circuit gates to tensors; click the next-step button to inspect the generated path and intermediate results.

The NumPy run control computes the amplitude and probability along this path and compares them with ArcTN, a direct contraction, and an independent state-vector calculation.

```diagram
contraction-demo
```

- [Quick start](/docs/quick-start) — Begin with a smaller Python example.

## Numerical execution and integrations {#usage}

### Direct contraction execution {#direct-execution}

With numerical arrays supplied, `arctn_contract` performs planning, optional slicing, and execution in one call. It defaults to the native ArcTN CPU executor, with explicit external-array backends also available. `return_info=True` returns planning and execution reports alongside the result.

- [Numerical execution](/docs/execution) — Array types, contraction steps, and returned information.
- [Slicing example](/docs/tutorial-slicing) — Set `target_size` and choose Fixed or Dynamic slicing.

### Using Quimb {#quimb-integration}

Pass an `ArcTNOptimizer` to Quimb through `optimize=` to use ArcTN path search. `ArcTNOptimizer.search()` returns a `ContractionTree` with the path and slicing indices; Quimb / Cotengra perform subsequent numerical contraction.

- [Quimb example](/docs/tutorial-quimb)

### Saving and reusing paths {#reuse-plan}

With the same structure and dimensions, changing array values does not require a new path search. Use `arctn_plan` to obtain the path and slicing information, and save it for later contractions.

- [Saving and reusing paths](/docs/tutorial-reuse)

## Core capabilities {#capabilities}

| Capability | Implementation | Further reading |
| --- | --- | --- |
| Path generation | Greedy, randomized greedy, dynamic programming, and recursive hypergraph bisection | [Path-search algorithms](/docs/greedy-search) |
| Path improvement | Subtree reconfiguration, simulated annealing, replica exchange, and fixed-leaf-order dynamic programming | [Annealing and replica exchange](/docs/tree-search), [subtree reconfiguration](/docs/reconfiguration) |
| Automatic path optimization | Light / Heavy presets schedule generation and improvement | [Planning pipeline](/docs/auto) |
| Slicing | Fixed preserves the path; Dynamic permits local path changes | [Slicing](/docs/slicing) |
| Numerical execution | Native CPU executor or an explicit opt_einsum array backend | [Execution backends](/docs/execution-backends) |
| Parallel and distributed execution | Rayon on one host and `tnmpi` for distributed slices | [Parallel settings](/docs/parallelism) |

## Scope and boundaries {#boundaries}

- The native executor uses CPUs; CuPy, PyTorch, and JAX arrays run through their explicitly selected external backends.
- Slicing does not perform low-rank truncation. Currently only internal indices are sliced: all values are enumerated and their results summed. Output indices remain intact and are not sliced.
- Light, Heavy, and most local-search methods are heuristic and do not guarantee global optimality. Dynamic programming is suitable for small subproblems; see its [search scope](/docs/structured-search).
- `max_time` is checked at algorithm checkpoints, not enforced as a process timeout. Use an external process or job scheduler for a strict limit.

- [Compatibility and limitations](/docs/versioning)
- [Benchmark suite](/docs/benchmarks)
