Metadata-Version: 2.4
Name: zxparam
Version: 0.1.0
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Typing :: Typed
Requires-Dist: numpy>=1.26
Requires-Dist: quimb>=1.7 ; extra == 'quimb'
Provides-Extra: quimb
License-File: LICENSE
Summary: A parameterized ZX calculus library
Keywords: quantum,quantum-computing,circuit-simulation,zx-calculus
Author-email: Rafael Haenel <rhaenel@quera.com>
License-Expression: Apache-2.0
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Documentation, https://queracomputing.github.io/zxparam/latest
Project-URL: Homepage, https://github.com/QuEraComputing/zxparam
Project-URL: Issues, https://github.com/QuEraComputing/zxparam/issues
Project-URL: Repository, https://github.com/QuEraComputing/zxparam

# zxparam

A Python library for exact, parametric rewriting of ZX-diagrams. Phases can
depend on Boolean parameters, so one simplification serves every parameter
assignment, and diagrams can mix quantum and classical parts, such as
measurements, noise and classical outputs.

## Key features

- **Parametric rewriting.** A phase is a concrete angle plus π times a parity of
  Boolean parameters. Every rewrite rule holds for all parameter values, so a
  diagram is reduced once and then evaluated per assignment. This follows
  ParamZX ([paper](https://arxiv.org/abs/2403.06777),
  [code](https://github.com/mjsutcliffe99/ParamZX)).
- **Quantum and classical domains.** Spiders and wires are quantum or
  classical. Quantum ones stand for both copies of the doubled diagram, so the
  same graph describes pure circuits, measurements, decoherence and classical
  logic. The rules (`full_reduce`, pivots, local complementation, gadget fusion,
  ground elimination, …) are domain-aware.
- **Exact scalars.** Scalars are kept exactly, in the dyadic ring with
  parametric phase terms, never as floats.
- **Stabilizer-rank decomposition.** `decompose` writes a closed diagram as a
  sum of exactly represented stabilizer terms. The strategies `cat5`, `bss`
  and `cutting` are ported from
  [PyZX-Param](https://github.com/rafaelha/pyzx).
- **Circuit extraction.** `extract_circuit` turns a simplified diagram back into
  gates whose tensor equals the diagram's, scalar included. Classical data
  becomes measurements, discards and classically controlled gates through the
  ZX⏚ ground form of Borgna, Perdrix and Valiron
  ([paper](https://arxiv.org/abs/2109.06071),
  [code](https://github.com/aborgna/pyzx/tree/zxgnd)). It extends the frontier
  extraction of
  [Duncan et al.](https://doi.org/10.22331/q-2020-06-04-279)
  ([PyZX](https://github.com/zxcalc/pyzx)).
- **Tensor contraction and drawing.** `Graph.to_tensor` contracts diagrams with
  quimb, and `draw` renders them with D3 in Jupyter.

## Installation

```bash
pip install "zxparam[quimb] @ git+https://github.com/QuEraComputing/zxparam"
```

The `quimb` extra is needed for `Graph.to_tensor`. Installing from source builds
the compiled core, which needs a Rust toolchain ([rustup](https://rustup.rs)).

## Usage

```python
import itertools

import numpy as np
import zxparam as zx

# A Clifford+T circuit whose spiders carry Pauli phases p0, p1 ∈ {0, 1}.
g = zx.random_clifford_t(3, 60, seed=1, pauli_params={0, 1})
h = g.copy()
zx.full_reduce(h)  # one reduction, valid for every parameter value
for p0, p1 in itertools.product((0, 1), repeat=2):
    b = {0: p0, 1: p1}
    assert np.allclose(h.to_tensor(b), g.to_tensor(b))

# Close the circuit and decompose it into exact parametric stabilizer terms.
for v in [*g.inputs(), *g.outputs()]:
    g.plug(v, zx.VertexType.X)
terms = zx.decompose(g)
assert np.isclose(terms.evaluate({0: 1, 1: 0}), g.to_tensor({0: 1, 1: 0}))
```

## Development

```bash
uv sync --group dev
uv run pytest
uv run ruff check
uv run ruff format --check
uv run ty check
```

`uv sync` builds the compiled core in `rust/`, and `uv run` and `uv sync`
rebuild it after a change to its Rust sources. `cargo test` in `rust/` runs
the core's own tests.

### Known performance gaps

Two speed targets of the Rust port are not met yet:

- `full_reduce` on dense random circuits, such as
  `random_clifford_t(20, 16000)`, is about 17× faster than the Python
  implementation it replaced, against a target of 20×.
- `extract_circuit` on 40-qubit random circuits of 30,000 gates, after
  `full_reduce`, is about 12× faster, against a target of 20×.

Both spend their time in the core's adjacency updates: the edge toggles of
local complementation, of the pivots and of the extractor's row additions.
A denser adjacency layout in `rust/zxparam/src/graph/` is the likely fix.

## License

[Apache License 2.0](LICENSE)

