---
title: "Saving paths and slicing information"
description: "What ArcTNExecutionPlan stores, its JSON format, and how to validate, convert, and execute a loaded plan."
eyebrow: "Numerical execution"
---

## Paths and related objects {#representations}

| Representation | Stored information | Main use |
| --- | --- | --- |
| SSA path | IDs of the two tensors contracted at each step | Specifies contraction order; does not include a network or slicing set |
| arctn\_schedule report | Path, metrics, and search diagnostics | Inspect search results; add network information with ArcTNExecutionPlan for persistence |
| ArcTNExecutionPlan | Network connectivity and dimensions, SSA path, slicing set, and size limit | Save to a file, then load for validation or execution |
| ArcTNCompiledContraction | Native axis transformations and matrix-multiplication parameters, or an external-backend expression | Repeat unsliced execution in the current process |
| Cotengra ContractionTree | Tree structure and slicing indices | Execute through Quimb/Cotengra |

`ArcTNExecutionPlan` is more than a path list: it also stores network and slicing information. Numerical arrays and compiled kernels are not persisted.

## Saving and loading {#lifecycle}

Use `arctn_plan` to search for a path and obtain an `ArcTNExecutionPlan`, then save or execute it. Loading reuses the existing path and slicing set without replanning; choose the execution backend when calling `execute` or `compile`.

See [saving and reusing plans](/docs/tutorial-reuse#save-load) for a complete example.

## Contents of version 2 JSON {#schema}

| Field | Meaning |
| --- | --- |
| schema / schema\_version | arctn-execution-plan / 2 |
| path\_format | ssa-v1; explicitly identifies integers as SSA tensor IDs, not positions in a linear-path list |
| network | inputs, output, and size\_dict; index labels are stored as zero-based integers |
| network\_canon | String derived from connectivity, tensor order, axis order, and dimensions, used to compare network identity |
| ssa\_path | Path whose references have been validated and which produces the final result from all inputs |
| sliced.legs | Slicing-index set used during execution; an empty array for unsliced execution |
| target\_size | Optional per-slice element-count bound for pairwise contraction results; single-tensor networks check the final output |
| metrics / planning / provenance | Compact metrics, public call settings, and version provenance |

Python calls accept hashable index labels such as strings. Saving maps labels to integers in first-occurrence order, for example `"a"`, `"b"`, `"c"` to `0`, `1`, `2`. This changes only label representation, not array order, axis order, or connectivity, so the JSON file does not depend on the original Python label objects. A newly created in-memory plan may retain the original labels for inspection; a loaded plan uses the integers in the file.

When loading a version 2 file, Rust checks consistency among the network, SSA path, slicing set, and `target_size`, and recomputes any stored core metrics from the network and path. This detects invalid path references, nonexistent slicing indices, or metrics inconsistent with the path. Loading does not search again. See [checking a saved plan file](/docs/validation#plan-example) for error handling. `planning` and `provenance` record settings and version information; they do not determine numerical-execution correctness.

`target_size` is not a bound on RSS, VRAM, allocator caches, or backend workspace. A version 2 file that specifies this constraint must store a positive integer `target_size`, its logarithmic counterpart `memory_target_log2_elements`, and `memory_constraint_metric="max_intermediate_elements_per_slice"`. Rust revalidates the constraint using the saved path and slicing set when loading.

## Conversion and execution {#operations}

| Method | Replans? | Restrictions |
| --- | --- | --- |
| to\_linear\_path() | No | Returns the linear path used by opt\_einsum |
| to\_tree() | No | Requires Cotengra; converts the path and slicing indices to a contraction tree |
| execute(arrays, backend=...) | No | Executes the saved path and slicing set |
| compile(backend=...) | No | Requires an empty slicing set; returns a compiled object reusable in the current process |

`plan.execute()`, `plan.to_tree()`, and `plan.compile()` never replan. `native` uses the ArcTN Rust CPU implementation; other explicitly selected backends use opt\_einsum and the corresponding array library. External-backend slices are currently enumerated sequentially in Python; native slices execute through Rust/Rayon.

You cannot call `plan.compile()` with a nonempty slicing set because `ArcTNCompiledContraction` does not currently support sliced execution. Use `plan.execute()`, or convert to a Cotengra tree with `plan.to_tree()`.

## Compatibility {#compatibility}

- Python ArcTNExecutionPlan.load() accepts only self-contained version 2 files.
- Rust and CLI readers support versions 1 and 2; version 1 requires the caller to supply and verify an external network.
- tnpath --save-path writes version 2; tnexec still requires --net and checks that the saved and supplied networks match.
- Legacy files without a schema identifier are read only when explicitly allowed; they are not accepted by default.
