Metadata-Version: 2.4
Name: mimiq-exaqt
Version: 0.2.1
Requires-Dist: mimiqcircuits>=0.26.2
Requires-Dist: numpy>=1.26
Requires-Dist: mimiq-qiskit>=0.2.0 ; extra == 'qiskit'
Provides-Extra: qiskit
Summary: SIMD-accelerated state-vector quantum simulator (rust core).
Author-email: Guido Masella <guido.masella@qperfect.io>
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

# mimiq-exaqt (python wrapper, rust core)

Python bindings for [`exaqt-rs`](../exaqt-rs) — a SIMD-accelerated
state-vector quantum simulator. The distribution is **`mimiq-exaqt`** and the
import package is **`exaqt`**; the native module is `exaqt._core`, whose
public types are re-exported on the top-level package.

## Install (release wheel)

Wheels are published to PyPI on each `v*` tag — one `abi3` wheel per
platform (Linux x86_64, macOS arm64, Windows x86_64), covering Python 3.10
and every later version:

```sh
pip install mimiq-exaqt
```

The wheel bundles the documentation. Read it offline, without a network round
trip, with:

```sh
exaqt docs                  # open the bundled site in a browser
exaqt docs --print-path     # or just print where it lives
```

## Install (development checkout)

From this repository, with `maturin` and `uv` available (the Nix devshell
provides both):

```sh
cd exaqt-python
uv venv && uv pip install "mimiqcircuits>=0.26.2" pytest numpy
.venv/bin/maturin develop --release
.venv/bin/python -m pytest -q tests/
```

A `maturin develop` build does not build the docs, so `exaqt docs` has nothing
to open. To produce the wheel exactly as CI publishes it — documentation
included — run `python scripts/build_wheel.py` instead.

## Quick example

```python
import numpy as np
from exaqt import ExaqtSV, Rng

sv = ExaqtSV.zero(3)
sv.apply_h(0)
sv.apply_cx(0, 1)
sv.apply_cx(0, 2)
print(sv.amplitudes())          # numpy complex128 array, length 2**3

# Multi-qubit Pauli expectation (no need to build a 2^k × 2^k matrix).
print(sv.expectation_pauli("XXX", [0, 1, 2]))   # +1 for the GHZ state

# Sampling.
r = Rng(seed=42)
shots = sv.sample(r, nsamples=1000)             # shape (1000, 3) uint8
```

## mimiqcircuits integration

```python
import mimiqcircuits as mc
from exaqt import ExaqtQCS

c = mc.Circuit()
c.push(mc.GateH(), 0)
c.push(mc.GateCX(), 0, 1)

sim = ExaqtQCS()
result = sim.execute(c, nsamples=1000)   # returns a mimiqcircuits.QCSResults
print(result)
```

## Conventions

- **Qubit ordering.** Qubit 0 is the **least-significant bit** of the
  basis-state index (matches Qiskit and MimiqCircuitsBase).
- **2-qubit gate basis.** For `apply_gate_2q(M, q1, q2)`, `q1` is the
  **most significant** bit of the gate's local 2×2-bit basis. See the
  Rust crate's docs for the precise layout.
- **Cross-language reproducibility.** The same `Rng(seed)` produces the
  same Xoshiro256++ stream in the Rust core, the Python wrapper, and
  the Julia wrapper.

## Errors

The wrapper raises Python exception subclasses of `ExaqtError`:

- `GateShapeError` — gate matrix has the wrong shape or layout.
- `QubitIndexError` — qubit index out of bounds, or duplicate qubits.
- `DegenerateStateError` — sampling a state with zero / non-finite norm.
- `NonUnitaryError` — only raised when the Rust crate is built with the
  `unitary-checks` feature; flags a non-unitary user matrix.

`MemoryError` is raised for state-vector allocations that won't fit
(e.g. `ExaqtSV.zero(40)`) — instead of aborting the process.

