---
title: "Light / Heavy interfaces"
description: "Choose Light or Heavy and plan a contraction path through Python, Rust, or the command line."
eyebrow: "Automatic contraction planning"
---

## Choosing a preset {#comparison}

Light emphasizes low search overhead and quickly finding a path; Heavy invests more search effort in tasks where path quality matters more. Both use the same network input and optimization objective.

| Item | Light | Heavy |
| --- | --- | --- |
| Emphasis | Search overhead | Path quality |
| Typical use | Quickly obtain an executable path | Invest more search time in expensive contractions or repeated execution |
| Public invocation | `preset="light"` | `preset="heavy"` |

Both return a complete path and an optional report. Light / Heavy are implemented in a separate compiled library, which the complete Python wheel includes and loads automatically; source builds require [separate configuration](/docs/installation#engine). Internal candidate allocation and stage records are not part of the public interface.

Light and Heavy do not denote different numerical precisions. Specify array types and execution backends separately; different contraction orders may produce different floating-point rounding errors.

## Python, Rust, and command-line interfaces {#interfaces}

```python
from arctn import arctn_path

light_path = arctn_path(
    inputs, output, size_dict, preset="light", seed=3
)
heavy_path = arctn_path(
    inputs, output, size_dict, preset="heavy", seed=3
)
```

```rust
use arctn::{auto_path_preset, AutoPreset};

let result = auto_path_preset(
    &network, AutoPreset::Light, 3, None,
)?;
```

```bash
tnpath network.json --method auto --preset light --seed 3
```

## Comparing presets on your networks {#comparison-protocol}

Compare the actual planning time and final path metrics on representative networks when choosing a preset. The relative benefit of Light and Heavy depends on network structure, objective, thread configuration, random seeds, and time limits.

| Conditions to keep fixed | Results to record |
| --- | --- |
| Same network, output indices, and dimensions | Whether planning succeeds and the returned path format |
| Same PlannerObjective weights | log10\_flops, log2\_read\_write, and log2\_max\_size |
| Same physical cores, thread settings, and external load | Planning-call time and end-to-end time |
| Explicit seed set, successful-run count, and total-run count | Each run, rather than only the best result |

Heavy uses a larger search budget, but is not guaranteed to outperform Light on every run. Measure speed and path-quality differences under the same conditions.

## Thread settings {#threads}

Start with eight worker threads and set the Rayon thread-pool width before launching the program:

```bash
RAYON_NUM_THREADS=8 python plan.py
```

| Setting | What it controls |
| --- | --- |
| `RAYON_NUM_THREADS` | Rayon worker count; it does not reserve exclusive physical cores |
| CPU affinity | CPUs on which the process may run |
| NUMA binding | CPU and memory placement |

With more CPU resources, increase the worker count in increments of eight; see [recommended thread settings](/docs/parallelism#recommended-threads) for the number of search starts. Starts share the thread pool. More threads may increase the amount of search work, so doubling the count does not necessarily halve planning time. See [timing and CPU usage](/docs/performance-boundaries) for measurement guidance.

## Interface contract {#preset-boundary}

Switching between Light and Heavy does not change the network-input format, path format, or return type. The public interface selects a preset and sets the objective, seed, and time limit; callers do not need to schedule internal stages.
