Numerical contraction
Evaluate arrays along a contraction path using native Rust CPU execution or another array library, returning axes in output order.
On this page
From path to numerical result
A contraction path determines the order of computation; numerical execution reads input arrays and computes intermediate tensors and the final result step by step.
| Use | Entry point |
|---|---|
| Plan and execute, optionally with slicing | arctn_contract |
| Execute a saved path and slicing set | ArcTNExecutionPlan.execute |
| Execute a supplied SSA path in Rust | contract_network |
| Execute a supplied SSA path and slicing set in Rust | contract_network_sliced |
Python defaults to backend="native", the ArcTN Rust CPU executor. You may also select execution backends such as NumPy or CuPy. In Quimb, pass an ArcTNOptimizer to optimize= and let Quimb/Cotengra execute the contraction; see the Quimb example.
Native pairwise contraction steps
Native execution first checks that array count, axis dimensions, and stored element counts match the network, then validates that the path produces the final result from those inputs. For example, an input of shape (2, 3) must contain six elements and cannot simply be substituted with axes ordered as (3, 2). See input and path checks for examples.
After validation, each step arranges input axes according to which indices must be retained or summed, groups like axes into matrix dimensions, and performs matrix multiplication (GEMM). A shared index must be retained if it still occurs in a later tensor or the final output; it is summed only when no longer needed.
C[b,i,j] = Σk A[b,i,k] B[b,k,j]
- b
- Shared by both tensors; retained as batch axes
- k
- Shared by both tensors; summed out in this step
- i, j
- Free axes from A and B, respectively
Reordering and merging axes converts the operation to batched GEMM. The result is then restored to the output tensor's axis order.
Indices shared by both inputs and retained after contraction become batch axes; shared indices to be summed become matrix-multiplication contraction axes. Retained indices found on only one side form the row and column axes respectively. The final result is permuted into the order specified by output.
Inputs, dtype, and results
| Rust type | Python data type |
|---|---|
f32 |
float32 |
f64 |
float64 |
Complex32 |
complex64 |
Complex64 |
complex128 |
For every execution, array count and shapes must match the network, and all inputs must use the same supported data type. The Python native backend prepares C-contiguous NumPy arrays; output specifies result-axis order.
Execution uses dense pairwise contraction, without bond-dimension truncation or low-rank approximation. The metric called FLOPs in PathStats counts scalar multiplications from the network structure and path. It is not directly equivalent to CPU instruction count, memory traffic, or actual runtime.
Even paths with identical PathStats can have different runtimes because of axis ordering, transpositions, and GEMM shapes. Measure backend performance separately with the same path, inputs, dtype, threads, and timing boundaries.
Direct execution
Rust: execute an existing path without searching again
use arctn::contract_network;
let result = contract_network(&net, tensors, &ssa_path)?;
Python: plan and execute
from arctn import arctn_contract
result, info = arctn_contract(
inputs, output, size_dict, arrays,
preset="heavy", backend="native",
return_info=True,
)
info records the actual backend and execution time. If only array values change while the structure and path remain fixed, compile once and execute repeatedly. To persist a path and slicing set across processes, use arctn_plan; see saving and reusing plans.