ArcTN Rust-native tensor-network contraction planning

ArcTN repository

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.

On this page

Licensing and permitted use

Source code that the company is entitled to license is governed by the Arclight Non-Commercial Source-Available License 1.0, which prohibits commercial use and closed-source integration. This is not an OSI-approved open-source license. Commercial use requires separate authorization.

See the ArcTN repository license section for full details. Commercial licensing and license inquiries: quill@arclightquantum.com.

Tensor networks and binary 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 ABCDABCD below: both orders produce the same 2×22\times2 result, but require different amounts of computation.

Connections between tensors

A: 2×8 · B: 8×2
C: 2×8 · D: 8×2

Contraction tree 1

(AB)(CD)

32 + 32 + 8 = 72 multiplications

Contraction tree 2

((AB)C)D

32 + 32 + 32 = 96 multiplications

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 ABAB or CDCD 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.

Planning and execution

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: 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

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 and path reuse when parameters change.

Quantum computing tasks
Amplitudes · Expectation values · Probabilities and sampling

Circuit definition: Qiskit or Quimb

Simulation methods
General tensor-network contractionConstruct a network for the target physical quantity, then optimize its contraction order.

Other tensor-network methods: MPS state updates with optional truncation; PEPS update and contraction algorithms.

Other methods: dense state vectors or density matrices, stabilizer methods, and Pauli propagation.

Network input
Quimb TensorNetwork or a user-constructed tensor network

inputs · output · size_dict

arrays (for execution)

Qiskit circuits require conversion; compatible OpenQASM 2 circuits can be imported by Quimb.

Contraction planning
ArcTN
Light / Heavy path searchOptional fixed / dynamic slicing

Contraction path + sliced indices

Numerical execution
Execute with ArcTN

arctn_contract(…)

Or save the contraction order and slicing information: ArcTNExecutionPlan (IR)

Native CPU executor (Rust)

Or opt_einsum + NumPy / CuPy / Torch / JAX

Execute through Quimb

ArcTNOptimizer.search()

cotengra.ContractionTree

Quimb / Cotengra execution → autoray

CPU or GPU array backend

Contraction result: scalar or tensor

ArcTN handles tensor contractions, including contraction subproblems in MPS and PEPS algorithms. The caller manages state updates, truncation, sampling, and noise models.

From quantum circuit to contraction result

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

Inspecting contractions step by step

Express the initial state, quantum gates, and terminal 1\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.

Quantum circuit

Starting from |00>, apply H and Ry, then CNOT, followed by Ry on q0.q0 |0⟩⟨1|q1 |0⟩⟨1|HRy(π/3)CNOTRy(π/4)

Time runs from left to right. The CNOT control is q0 and the target is q1; the terminal ⟨1| bras specify the output to compute.

Corresponding tensor network

Eight tensors are connected by seven indices, a through g. T4 is a rank-4 CNOT tensor; each initial state and terminal bra is a rank-1 tensor.abcdefgT0T1T2T3T5T6T7T4

Each edge is a shared index taking values 0 or 1. All indices are summed over, producing an amplitude.

How do quantum gates become tensors?
Circuit objectTensorIndices and shape
Two initial states |0⟩T0 and T1, vectors [1, 0][a] and [b], 2 elements each
H, Ry(π/3)T2 and T3, single-qubit gate matrices[c,a] and [d,b], each 2 × 2
CNOTT4, with two output axes and two input axes[e,f,c,d], 2 × 2 × 2 × 2
Ry(π/4)T5, a single-qubit gate matrix[g,e], 2 × 2
Two terminal ⟨1| bras specifying output 11T6 and T7, dual vectors [0, 1][g] and [f], 2 elements each

Gate tensors place output axes before input axes. The 4 × 4 CNOT matrix is reshaped with reshape(2, 2, 2, 2) into four axes [e,f,c,d] without changing element order. With the terminal vectors connected, the network has no open indices, so the output argument passed to ArcTN is output=[].

This example constructs the tensors with NumPy. ArcTN plans from inputs, output and size_dict; it does not parse circuit diagrams or quantum gates.

ArcTN contraction path Light · seed 0
0 / 7

SSA path [(4, 7), (0, 2), (8, 9), (1, 3), (5, 6), (10, 11), (12, 13)]

  1. (4, 7) → 8Pending
  2. (0, 2) → 9Pending
  3. (8, 9) → 10Pending
  4. (1, 3) → 11Pending
  5. (5, 6) → 12Pending
  6. (10, 11) → 13Pending
  7. (12, 13) → 14Pending

T0…T7 are the circuit's input tensors; T8 onward are the results produced at each step. Left and right placement in the tree is for layout only; IDs match the actual path.

Binary contraction tree

Leaves are initial states, quantum gates, or terminal bras; each internal node represents a pairwise contraction.

Inputs readySelect Next to follow the input contractions. Summing over all indices produces a scalar amplitude.

Currently retained: T0 [a]T1 [b]T2 [c,a]T3 [d,b]T4 [e,f,c,d]T5 [g,e]T6 [g]T7 [f]

T0[a]

2 · float64
1
0

T1[b]

2 · float64
1
0

T2[c,a]

2 × 2 · float64
0.7071070.707107
0.707107-0.707107

T3[d,b]

2 × 2 · float64
0.866025-0.5
0.50.866025

T4[e,f,c,d]

2 × 2 × 2 × 2 · float64
1000
0100
0001
0010
Table rows: [e,f]; columns: [c,d]

T5[g,e]

2 × 2 · float64
0.92388-0.382683
0.3826830.92388

T6[g]

2 · float64
0
1

T7[f]

2 · float64
0
1

Elements are shown in input-axis order. The CNOT 4 × 4 table groups [e,f] as rows and [c,d] as columns. After selecting Next, matrices are reordered and grouped by that step's summed index.

ArcTN final amplitude A₁₁

0.701057
Saved native execution result

Probability of measuring 11: P(11) = |A₁₁|²

0.491481
Computed from the amplitude, not from measurement sample frequencies

Complete path: 42 FLOPs · Largest contraction result: 8 elements

Path and metrics
text
{
  "ssa_path": [[4, 7], [0, 2], [8, 9], [1, 3], [5, 6], [10, 11], [12, 13]],
  "linear_path": [[4, 7], [0, 2], [4, 5], [0, 1], [0, 1], [0, 1], [0, 1]],
  "metrics": {
    "log10_flops": 1.6232492903979006,
    "log2_max_size": 3,
    "log2_max_contraction_size": 4.700439718141093,
    "log2_total_size": 4.392317422778761,
    "log2_read_write": 6.266786540694901,
    "log2_peak_size": 5.459431618637297,
    "log2_n_slices": null,
    "sliced_log10_flops_total": null,
    "sliced_log2_max_size": null,
    "sliced_log2_max_contraction_size": null,
    "sliced_log2_peak_size": null,
    "max_intermediate_log2_elements_per_slice": null
  }
}

Tables show up to 6 decimal places. Each step displays matrices in the native executor's axis order: columns of the left matrix and rows of the right matrix correspond to the summed index. After multiplication, the remaining indices are restored as axes of the result tensor.

Execute the complete path with NumPy

Execute the path returned by ArcTN without searching again. The first run loads Pyodide and NumPy from jsDelivr; computation runs in the browser.

Not run yet. Select Run NumPy to compute in your browser.

Execution steps (pseudocode)
text
tensors = store input arrays by SSA ID(arrays)
for left, right, out, axis_orders, matrix_shapes, output_shape in contractions:
    A = reorder axes and reshape as matrix(tensors[left], axis_orders.left, matrix_shapes.left)
    B = reorder axes and reshape as matrix(tensors[right], axis_orders.right, matrix_shapes.right)
    tensors[out] = reshape(A @ B, output_shape)
    del tensors[left], tensors[right]
amplitude = take final tensor(tensors)
probability = abs(amplitude) ** 2
compare amplitude(amplitude, ArcTN result, direct contraction result, state-vector result)
return amplitude, probability

This example uses the default objective FLOPs + 64 × read/write. The step buttons display saved results without repeating the search; Run NumPy executes this contraction path. FLOPs count scalar multiplications in this example.

Numerical execution and integrations

Direct contraction 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.

Using Quimb

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.

Saving and reusing paths

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.

Core capabilities

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

Scope and boundaries