Metadata-Version: 2.5
Name: src_method
Version: 0.4.0
Summary: Successive Randomized Compression.
Project-URL: Homepage, https://algorithmiq.fi
Project-URL: Documentation, https://docs.algorithmiq.fi
Project-URL: Repository, https://github.com/Algorithmiq/src-method
Project-URL: Changelog, https://github.com/Algorithmiq/src-method/releases
Project-URL: Bug Tracker, https://github.com/Algorithmiq/src-method/issues
Project-URL: Discussions, https://github.com/Algorithmiq/src-method/discussions
Author-email: Algorithmiq Development Team <aurora@algorithmiq.fi>
License-Expression: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Chemistry
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: <3.15,>=3.11
Requires-Dist: numpy<3,>=2.0
Requires-Dist: opt-einsum>=3.4.0
Provides-Extra: gpu-nvidia
Requires-Dist: cupy-cuda13x[ctk]>=14; extra == 'gpu-nvidia'
Provides-Extra: gpu-rocm
Requires-Dist: cupy>=14.1.1; extra == 'gpu-rocm'
Description-Content-Type: text/markdown

# Successive Randomized Compression

[![Documentation](https://github.com/Algorithmiq/src-method/actions/workflows/docpages.yml/badge.svg)](https://algorithmiq.github.io/src-method/)
[![Test src_method](https://github.com/Algorithmiq/src-method/actions/workflows/test.yml/badge.svg)](https://github.com/Algorithmiq/src-method/actions/workflows/test.yml)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)

An implementation of the SRC algorithm introduced in [Camaño, Epperly and Tropp, *Quantum* **10**, 2022 (2026)](https://doi.org/10.22331/q-2026-03-10-2022), extending the idea to other kinds of tensor networks.

### Features

The following primitives are supported:

1. MPO-MPS randomized contraction-compression.
2. MPO-MPO randomized contraction-compression.
3. MPO randomized compression.
4. MPS randomized compression.
5. Randomized contraction-compression of a whole stack of trains in one sweep:
   `MPO^k`, `MPO^k . MPS` and `MPS . MPO^k`.

`src_method` has no tensor-network framework dependency: it takes and returns plain lists of per-site NumPy arrays, one array per site.

```python
from src_method import apply, compress, src
```

The `apply` function covers cases 1 and 2 above, the `compress` function cases 3 and 4, and `src` all five: `apply` and `compress` are its two- and one-train special cases. All three functions are pure, meaning no in-place modification ever happens. The user should
manage the assignment of the returned objects, possibly overwriting the input variables.
See the [reference documentation](https://algorithmiq.github.io/src-method/) for details, and the [tests](tests/) or [benchmarks](benches/) folders for usage examples.

Whether a train is an MPS or an MPO is inferred from the rank of its first site tensor, so no wrapper type is needed.

**NOTE**: the current implementation targets tensor networks with 3 or more sites. For smaller networks, an exact SVD-based fallback is dispatched, with a warning.

### Tensor Indexing Conventions

The array layout follows the default `quimb` tensor indexing conventions, so results round-trip through [Quimb](https://quimb.readthedocs.io/en/latest/autoapi/quimb/tensor/index.html) without any permutation:

```python
import quimb.tensor as qtn

result = qtn.MatrixProductOperator(apply(H1.arrays, H2.arrays, chi_out=64))
```

- **MPO Tensors:** Bulk tensors have index order `('l', 'r', 'u', 'd')`.
  Boundary tensors (at the edges) are rank-3, dropping the outer `'l'` or `'r'` index.

- **MPS Tensors:** Bulk tensors have index order `('l', 'r', 'u')`.
  Boundary tensors are rank-2, dropping the outer bond index.

Where `'l'`/`'r'` are left/right virtual bonds and `'u'`/`'d'` are the upper/lower physical legs.
Please keep this in mind when constructing or manipulating tensors directly.

### Contraction Conventions

`src` contracts a *stack* of trains and compresses the result in a single sweep:

```python
from src_method import src

state = src(U3, U2, U1, psi, chi_out=64)  # U3 U2 U1 |psi>, U1 acts first
```

The stack is written in mathematical order. Each contraction joins the `'d'` leg of a train with the `'u'` leg (or the physical leg of an MPS) of the train to its right:

| Stack | Contraction | Result |
|---|---|---|
| `src(A)`, `src(psi)` | none | compressed MPO or MPS |
| `src(A, B, ...)` | `A.d` with `B.u` | MPO |
| `src(A, ..., psi)` | `A.d` with `psi` | MPS on the `'u'` leg of `A` (a ket) |
| `src(phi, A, ...)` | `phi` with `A.u` | MPS on the `'d'` leg of the last MPO (a bra) |

An MPS may appear only first or last, and not both. `apply(A, B)` and `compress(A)` are the two- and one-train cases; `apply` accepts only an MPO on the left.

A leading MPS is a row vector used **without conjugation**: `src(phi, A, B)` computes `phiᵀ A B`, which equals `src(Bᵀ, Aᵀ, phi)` with `ᵀ` swapping the `'u'` and `'d'` legs. For the physical bra `<psi| A B`, conjugate first:

```python
bra = src([t.conj() for t in psi], A, B, chi_out=64)
```

The result then pairs with a ket by plain contraction, with no further conjugation.

**Cost.** The per-site cost of the sweep grows with `chi_out**2` times the product of the bond dimensions of the layers. Compressing a whole stack at once pays off for shallow stacks of thin layers, such as two or three Trotter layers; apply anything else pairwise. See [the stack depth benchmarks](benches/stack/README.md) for measurements.

### GPU Support

`src_method` runs on CPU (NumPy) by default and can be accelerated on GPUs via [CuPy](https://cupy.dev/). Both **NVIDIA** (CUDA) and **AMD** (ROCm) GPUs are supported through optional install extras.

At runtime, pass `device="gpu"` to use GPU acceleration. The library handles backend dispatch automatically.

### Large Problems

Stacks that do not fit on the GPU, or in host memory, still run: the sweep reads the input cores one site at a time (from NumPy arrays, `np.memmap`, zarr or HDF5 datasets), batches every contraction to a memory budget, and keeps the sketched environments on the GPU, in host memory or on local disk. The budgets are detected, or set explicitly with `Resources`:

```python
from src_method import Resources, src

out = src(
    N,
    V,
    M,
    U,
    chi_out=2000,
    device="gpu",
    resources=Resources(gpu_memory="36GB", scratch_dir="/local/scratch"),
)
```

On a node with several GPUs, `Resources(devices=4)` splits the sweep among four of them, in the same process.

See [Large problems](https://algorithmiq.github.io/src-method/features/large-problems) for the budgets, the scratch directory, several GPUs and how to read the logged plan.

### Logging

`src_method` logs through the standard library `logging` module, under the
`src_method` logger, and stays silent by default: it adds only a `NullHandler`
and never touches the root logger or its handlers. Progress and timing messages
are emitted at `DEBUG`, the small-network fallback at `WARNING`. To see them,
configure logging in your application:

```python
import logging

logging.basicConfig(level=logging.INFO)
logging.getLogger("src_method").setLevel(logging.DEBUG)
```

## Installation

```bash
# CPU only (default)
uv pip install src_method

# With NVIDIA GPU support (CUDA 13.x, driver >= 580)
uv pip install "src_method[gpu-nvidia]"

# With AMD GPU support (ROCm)
uv pip install "src_method[gpu-rocm]"
```

When including `src_method` in another project's `pyproject.toml`:

```toml
# CPU only
dependencies = ["src_method"]

# With NVIDIA GPU support
dependencies = ["src_method[gpu-nvidia]"]

# With AMD GPU support
dependencies = ["src_method[gpu-rocm]"]
```

## Setting up the development environment

The code has a [DevContainer] configuration that will get you up and running
with all dependencies installed and configured, including sane defaults for the
editor.

You will need:

1. A working [Docker] installation:
   - For macOS and Windows, install [Docker Desktop](https://docs.docker.com/get-docker/)
   - For Linux, install [Docker Engine](https://docs.docker.com/engine/install/#server) following the instructions for your specific distro.
2. The [Visual Studio Code] editor. A recent version is recommended, _e.g._ >=1.78
3. The VSCode [DevContainers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers).
4. The [GitHub CLI] tool.

You can clone the repository with:

```
gh repo clone Algorithmiq/src-method
```

We recommend using a Git credential manager, such as [GitHub CLI], configured to
use HTTPS as protocol for Git operations.

Once the code is locally available, you can open its containing folder in
[Visual Studio Code]. The editor will then set up the [DevContainer] for you.
The first time you open the folder the startup will take a few minutes. Once the
process is done, you will have _all_ project dependencies installed, including
the git hooks.
[Visual Studio Code] will be already configured with all the extensions helpful for Python development.

> [!TIP]
> The order in which Visual Studio Code loads the extensions in the
> DevContainer is non-deterministic.  You might have to execute the *Reload Window*
> command to get everything to work as expected after a fresh build of the container.

### Alternative: Nix flake

If you prefer [Nix] over Docker, the repository ships a `flake.nix` that provides
a development shell with [uv], [Git] and the [GitHub CLI], plus the native
libraries the binary wheels need at runtime. Python itself and all project
dependencies remain managed by `uv`.

With [flakes enabled](https://nixos.wiki/wiki/Flakes#Enable_flakes_temporarily), run:

```bash
nix develop
```

Entering the shell runs `uv sync --all-groups` and activates the uv project
environment (`$UV_PROJECT_ENVIRONMENT` if set, otherwise `.venv`), so you land
in a ready-to-use environment. GPU extras are not installed by the flake: add them
explicitly with `uv sync --all-groups --extra gpu-nvidia` (or `--all-groups --extra gpu-rocm`) on a machine with the matching drivers.

If you use [direnv], the provided `.envrc` enters the shell automatically:

```bash
direnv allow
```

Unlike the DevContainer, the Nix shell does not install the git hooks for
you. Run `prek install --prepare-hooks` once after the first `nix develop`.

## Documentation

The documentation is a [Fumadocs] site under `docs/`, published [at this link].
It covers concepts, features, tutorials, the API reference generated from the
docstrings, and the developer guide.

To preview it locally you need [Node.js] 22 or later:

```bash
uv sync --group docs
cd docs
npm ci
uv run python scripts/gen_api_dump.py src_method -d .
node scripts/generate-api.mjs
uv run python scripts/notebooks_to_mdx.py
npm run dev
```

and open http://localhost:3000. See [`docs/README.md`](docs/README.md) for details.

[DevContainer]: https://containers.dev/
[Docker]: https://docs.docker.com/get-docker/
[Visual Studio Code]: https://code.visualstudio.com/
[GitHub CLI]: https://cli.github.com/
[Git]: https://git-scm.com/
[Nix]: https://nixos.org/download/
[direnv]: https://direnv.net/
[uv]: https://docs.astral.sh/uv/
[Fumadocs]: https://fumadocs.dev
[Node.js]: https://nodejs.org
[at this link]: https://algorithmiq.github.io/src-method/
