qarp

OpenQARP — quantum algorithm research platform.

Cross-cutting names only: config, EXACT / Shots, the result types and post-selection. Public depth: every subpackage is a namespace (absorb, algorithms, blocks, cutting, devices, emit, engines, factories, graphs, operators, optimizers, plotting, resources, utils), plus two modules — errors (the exception surface, imported qualified: qarp.errors.CapabilityError) and endianness (the MSB-boundary conversions, §1 of the conventions). None of them is imported here, so import qarp stays thin; from qarp import * pulls them all.

class qarp.Consumes(*values)[source]

Bases: Enum

What raw engine output a primitive’s estimator consumes.

Declared class-level on each primitive; engines dispatch on it. Lives here, below both layers, so engines can read it without importing from qarp.algorithms.

Variables:
  • COUNTS – Measurement statistics from sampled circuits (protocol primitives: Sampler, HadamardTest, PauliAveraging, …).

  • AMPLITUDES – Simulator statevectors, contracted directly (StateVector). Requires an engine with amplitude access — noiseless simulation.

AMPLITUDES = 1
COUNTS = 0
class qarp.ExactResult(n_qubits: int, keys: ndarray, probs: ndarray, n_shots: int = 1)[source]

Bases: object

Exact Born distribution duck-typing qx.SamplingResult.

keys (sorted int64 outcome bitmasks) and probs carry the distribution, pruned below ~1e-12 so it sums to 1 − O(pruned) — compare distributions at ~1e-10, never exactly. counts is the same data as a dict, built on first access: estimators that can consume the arrays (outcome_arrays()) never pay for a 2^n-entry dict. n_shots = 1 is a normalization trick so every estimator’s count / n_shots yields the probability unchanged — it is NOT a statistical claim: never infer shot-noise error bars or adaptive shot budgets from it (the variance of these numbers is exactly 0). Check is_exact to discriminate from a sampled result.

property counts: dict[int, float]
is_exact: bool = True
keys: ndarray
n_qubits: int
n_shots: int = 1
probs: ndarray
class qarp.MPIConfig[source]

Bases: object

MPI launcher detection — nothing more.

OpenQARP does not implement MPI parallelism: a composite algorithm constructed under a multi-rank launcher raises CapabilityError rather than running the same serial work on every rank. Detection is environment-only so no mpi4py import (and no MPI_Init_thread) ever happens inside OpenQARP.

Set QARP_DISABLE_MPI=1 to silence the detection (e.g. one rank of a job that drives OpenQARP serially on purpose).

static is_disabled() bool[source]

Check if MPI is explicitly disabled via QARP_DISABLE_MPI.

classmethod is_mpi_env() bool[source]

Check if running under an MPI launcher (env-only, no mpi4py import).

classmethod world_size() int[source]

Get MPI world size from environment (no mpi4py import).

class qarp.PostSelected(distribution: dict[tuple[int, ...], float], success_rate: float)[source]

Bases: object

Conditioned distribution plus the probability mass that survived.

distribution: dict[tuple[int, ...], float]
success_rate: float
class qarp.PostSelection(conditions: Mapping[int, int])[source]

Bases: object

Immutable post-selection condition on a subset of qubits.

Construct with a {qubit index: required bit} mapping for fixed-bit conditions, or via the sector constructors hamming_weight() / parity(). Hashable: fixed-bit specs compare by their conditions, sector specs by predicate identity — either way a spec can key a cache across a parameter sweep.

apply(distribution: dict[tuple[int, ...], float]) PostSelected[source]

Condition a {bits-tuple: probability} distribution.

Keys must be LSB-first tuples covering every selected qubit. Fixed-bit specs drop the (now-constant) selected positions from the output keys; sector specs keep full-width keys. Zero surviving mass yields PostSelected({}, 0.0) — no raise, so parameter sweeps survive nodes with vanishing support.

apply_statevector(statevector, n_qubits: int) Tuple[ndarray, float][source]

Project a statevector onto the condition; renormalise.

Returns (conditional_state, success_probability) with success = ‖P|ψ⟩‖². Fixed-bit specs return the state of the surviving qubits (ascending order, 2^(n-k) amplitudes — the selected qubits collapsed to a product basis state and factor out). Sector specs return the projected state on the FULL register (2^n): a subspace projection leaves the selected qubits entangled with the rest, so no reduction exists. Zero success returns the zero vector of the appropriate size with p = 0.0.

classmethod hamming_weight(qubits: Sequence[int], k: int) PostSelection[source]

Keep outcomes with exactly k ones across qubits (particle-number sector under Jordan-Wigner).

property is_fixed: bool

True for fixed-bit conditions (selected qubits are removed from the output); False for sector conditions (full width preserved).

classmethod parity(qubits: Sequence[int], even: bool = True) PostSelection[source]

Keep outcomes whose bit-sum over qubits is even (or odd).

qubits: Tuple[int, ...]
success_rate(distribution: dict[tuple[int, ...], float]) float[source]

Kept probability mass only (shortcut for apply(...).success_rate).

class qarp.Shots(*values)[source]

Bases: Enum

Non-integer shot-count sentinels for the n_shots knob.

Shots.EXACT (re-exported as qarp.EXACT) requests the ∞-shot limit of a sampling primitive: the engine computes the exact Born distribution |ψ|² instead of drawing samples. Deliberately a plain Enum, never IntEnum: arithmetic or ordering on a leaked sentinel must fail loudly with TypeError, not compute garbage. Enum members survive deepcopy with identity intact (copy.n_shots is EXACT keeps working through the QSE/MonteCarlo/QMEGS deepcopy paths — a plain object() sentinel would not).

EXACT = 'exact'
qarp.EXACT = Shots.EXACT

Non-integer shot-count sentinels for the n_shots knob.

Shots.EXACT (re-exported as qarp.EXACT) requests the ∞-shot limit of a sampling primitive: the engine computes the exact Born distribution |ψ|² instead of drawing samples. Deliberately a plain Enum, never IntEnum: arithmetic or ordering on a leaked sentinel must fail loudly with TypeError, not compute garbage. Enum members survive deepcopy with identity intact (copy.n_shots is EXACT keeps working through the QSE/MonteCarlo/QMEGS deepcopy paths — a plain object() sentinel would not).

qarp.SamplingDictionary

dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object’s

(key, value) pairs

dict(iterable) -> new dictionary initialized as if via:

d = {} for k, v in iterable:

d[k] = v

dict(**kwargs) -> new dictionary initialized with the name=value pairs

in the keyword argument list. For example: dict(one=1, two=2)

alias of dict[tuple[int, …], float]

qarp.config = <qarp._config.__ConfigObject__ object>