Skip to content

API Reference

For a guided tour see Getting Started and Circuit Execution.

Gate / operator matrix inputs

Methods that take a 1- or 2-qubit gate or operator (apply_gate_1q, apply_gate_2q, expectation_1q, expectation_2q, apply_kraus_*, apply_mixed_unitary_*) expect a numpy complex128 array: a (2, 2) array for a 1-qubit gate, a (4, 4) array for a 2-qubit gate, and a (n_ops, dim, dim) stack for a set of Kraus / mixed-unitary operators.

Qubit / bitstring ordering

Exaqt is little-endian by qubit index: qubit 0 is the least-significant bit of the amplitude index, so bs[0] is qubit 0. This matches Qiskit's little-endian ordering and MimiqCircuitsBase.

State vector — ExaqtSV

The dense quantum register. Amplitudes are complex128, indexed little-endian (qubit 0 = LSB).

Constructors:

Method Description
ExaqtSV.zero(num_qubits) \|0...0> state on num_qubits qubits
ExaqtSV.from_bitstring(bits) Product state from a 0/1 sequence (qubit 0 = LSB)
ExaqtSV.from_amplitudes(num_qubits, arr) State from a complex128 amplitude array

Properties & inspection:

Member Returns
sv.num_qubits int — number of qubits
sv.len / len(sv) int — number of amplitudes, 2**num_qubits
sv.get(idx) complex — amplitude of basis state idx
sv.probability(idx) float — probability of basis state idx
sv.amplitudes() complex128 numpy array of all amplitudes
sv.norm_squared() float — squared norm
sv.normalize() float — norm before normalising; renormalises in place
sv.reset_to_zero() Reset to \|0...0> in place
sv.clone() Deep copy

Single-qubit gates (target qubit last, angles first):

Method Description
sv.apply_x/y/z(target) Pauli gates
sv.apply_h(target) Hadamard
sv.apply_s/sdg/t/tdg/sx(target) Phase / T / SX gates
sv.apply_p(lmbda, target) Phase gate P(lambda)
sv.apply_rx/ry/rz(angle, target) Rotation gates
sv.apply_u(theta, phi, lmbda, target) General U gate
sv.apply_gate_1q(gate, target) Arbitrary 1-qubit unitary, (2, 2) complex128

Two-qubit gates:

Method Description
sv.apply_cx/cy/cz(a, b) Controlled Pauli gates
sv.apply_swap/iswap(q1, q2) (i)SWAP
sv.apply_cp(lmbda, q1, q2) Controlled phase
sv.apply_crx/cry/crz(angle, control, target) Controlled rotations
sv.apply_rxx/ryy/rzz(theta, q1, q2) Two-qubit rotations
sv.apply_gate_2q(gate, q1, q2) Arbitrary 2-qubit unitary, (4, 4) complex128

Multi-controlled gates:

Method Description
sv.apply_mcx(controls, target) Multi-controlled X
sv.apply_controlled_gate_1q(gate, controls, target) Controlled 1-qubit unitary
sv.apply_controlled_gate_2q(gate, controls, q1, q2) Controlled 2-qubit unitary

Measurement & sampling (all take a seeded Rng):

Method Returns
sv.prob_zero(target) float — probability of measuring 0 on target
sv.measure_qubit(target, rng) int — outcome, collapses the state
sv.reset_qubit(target, rng) int — pre-reset outcome, resets qubit to \|0>
sv.sample_bitstring(rng) uint8 array — one sampled bitstring
sv.sample(rng, nsamples) (nsamples, num_qubits) uint8 array

Noise channels (each takes a seeded Rng):

Method Description
sv.apply_kraus_1q(kraus_ops, target, rng) 1-qubit Kraus channel, (n_ops, 2, 2)
sv.apply_kraus_2q(kraus_ops, q1, q2, rng) 2-qubit Kraus channel, (n_ops, 4, 4)
sv.apply_mixed_unitary_1q(unitaries, probs, target, rng) 1-qubit mixed-unitary channel
sv.apply_mixed_unitary_2q(unitaries, probs, q1, q2, rng) 2-qubit mixed-unitary channel

Expectation values:

Method Returns
sv.expectation_1q(op, target) complex<psi\|O\|psi> for a (2, 2) operator
sv.expectation_2q(op, q1, q2) complex<psi\|O\|psi> for a (4, 4) operator
sv.expectation_pauli(paulis, qubits) complex — expectation of a Pauli string (e.g. "ZZZ")

Simulator — ExaqtQCS

exaqt.ExaqtQCS

Bases: LocalBackend

State-vector quantum circuit simulator.

Subclasses :class:mimiqcircuits.backends.LocalBackend and declares the Julia ExaqtQCS capability set plus parametric (Python-only — supported through the inherited slow-path :meth:bind; the Julia wrapper omits the token).

Parametric circuits are supported via the inherited slow-path :meth:bind (substitute then re-compile); there is no native compile-once / bind-many fast path yet.

Pauli-string expectations on any number of qubits are supported: ExpectationValue(PauliString("XYZ...")) dispatches to the native mask-based expectation_pauli (cost O(2^n) in the state size, independent of the string length). Only expectations of non-Pauli operators (e.g. a GateCustom matrix, or a Control/Power/Inverse-wrapped Pauli) keep the dense two-qubit cap.

Caveat — noise + :class:ExactFidelity: _apply_kraus renormalises the state after sampling a Kraus branch, so the per-shot fidelity is always 1.0 and the typed wrap is :class:ExactFidelity. That is honest for trace-preserving channels (the sampled trajectory is exact under renormalisation). For non-trace-preserving channels (e.g. amplitude damping with explicit loss) the surviving-trajectory probability is not tracked, and :class:ExactFidelity over-states reliability.

Attributes:

Name Type Description
seed

instance-level RNG seed. None means "fresh entropy on every :meth:execute". An integer makes the instance reproducible. Per-call seed= / rng= (mutually exclusive) overrides the instance value.

reorderqubits

qubit-reordering policy for the default pipeline (:meth:default_passes). None (the default) reorders automatically once a circuit is wide enough to benefit (>= 13 qubits); False never reorders; True / "greedy" / "sa" always reorders with that method. Exaqt relabels qubits to land gates on the fastest SIMD kernels — the state-vector analogue of the distance-based reorderqubits used by tensor-network backends. Instance-only (the local backend has no execute(..., reorderqubits=) knob); for finer control pass a :class:~exaqt.ExaqtReorderQubitsPass via execute(..., passes=).

Examples:

>>> import mimiqcircuits as mc
>>> from exaqt import ExaqtQCS
>>> sim = ExaqtQCS()
>>> c = mc.Circuit()
>>> c.push(mc.GateH(), 0)
...
>>> c.push(mc.GateCX(), 0, 1)
...
>>> c.push(mc.Measure(), 0, 0)
...
>>> c.push(mc.Measure(), 1, 1)
...
>>> results = sim.execute(c, nsamples=1000)

__init__(seed=None, reorderqubits=None)

execute(circuit, nsamples=1000, *, seed=None, rng=None, num_qubits=None, passes=None, callback=None, param_grid=None, strict_pass_order=True, stopped=None, progress=False)

Execute a circuit and return :class:mimiqcircuits.QCSResults.

seed and rng are mutually exclusive entropy sources; pass at most one. With neither, the simulator's instance seed (set at construction) is used, falling back to fresh OS entropy. Amplitudes are requested via in-circuit :class:Amplitude ops that write into results.zstates.

With no passes, :meth:default_passes runs — gate fusion above a cache-derived qubit threshold, then qubit reordering per the reorderqubits constructor option. Pass passes=PassPipeline() to disable both or a custom pipeline to retune them.

evolvezerostate(circuit, *, seed=None)

Evolve the zero state through circuit; return (state, fidelity) with a plain float fidelity (always 1.0 for Exaqt's renormalising path).

Convenience: matches the engines-side SimulatorState.zero(...) + evolve(state, c, rng=...) two-step. The dual-shape :meth:evolve covers the more general case where the caller owns the state.

Seed resolution mirrors :meth:execute: call-site seed= → instance self.seed → fresh cryptographic entropy from :mod:secrets.

For circuits with Kraus channels or mid-circuit measurements this is a single stochastic trajectory; use :meth:execute for ensemble statistics.

evolve(state, compiled, *, rng=None, callback=None, stopped=None)

Evolve state under compiled. Returns (state, ExactFidelity) — state-vector evolution is exact per trajectory, so no truncation bound is reported.

compile(circuit)

Identity-wrap the circuit.

NOTE: Exaqt dispatches every supported gate natively, so no Julia-side convertcircuit impurity applies here (cf. the engines wrappers). The wrap is a pure identity over the circuit.

expectation(state, op, *qubits)

Compute ⟨ψ|op|ψ⟩ on state without mutating it.

Supports 1- and 2-qubit operators. qubits is the list of qubit indices op acts on (0-based, matching the rest of the Python API).

Raises :class:ValueError for any other operator size.

capabilities()


Composite state — ExaqtState

exaqt.ExaqtState

Bases: State

Composite simulation state.

Use one of the staticmethod factories — :meth:zero, :meth:one, :meth:product — to construct a state, then pass it to :func:exaqt.evolve or :func:exaqt.apply_instruction.

Attributes:

Name Type Description
q ExaqtSV

the dense quantum register.

c list[int]

classical-bit register, length num_bits.

z list[complex]

complex z-variable register, length num_zvars.

zero(num_qubits, num_bits=0, num_zvars=0) staticmethod

|0…0⟩ quantum state, classical/z registers initialised to 0.

one(num_qubits, num_bits=0, num_zvars=0) staticmethod

|1…1⟩ quantum state, classical/z registers initialised to 1.

product(bits, num_bits=0, num_zvars=0) staticmethod

Product state from a 0/1 bitstring (qubit 0 = LSB).

amplitude(bitstring)

Get the amplitude for a given computational basis state.

sample(nsamples, rng=None, *, seed=None)

Sample measurement outcomes from the quantum state.

Either rng (a :class:random.Random) or seed (an int) may be passed, but not both. The Rust Rng is constructed from a 63-bit derived seed when rng is given.

reset()

Reset all four registers to their zero state in place.


Per-instruction primitives

exaqt.evolve(state, circuit, *, rng=None, callback=None)

Evolve state through every instruction in circuit in place.

Returns (state, fidelity). Fidelity is always 1.0 for the state-vector simulator.

callback, when given, is called as callback(i, total) after each applied instruction — the execute driver turns this into the per-step execution bar.

exaqt.apply_instruction(state, inst, rng=None)

Apply a single circuit instruction to state in place.

Returns fidelity (1.0 — Exaqt is a noiseless simulator). Raises :class:NotImplementedError for operations the rust core does not support yet (Kraus channels, BondDim, SchmidtRank).


Compilation passes

exaqt.ExaqtReorderQubitsPass

Bases: AbstractPass

Reorder qubits to land gates on the fastest kernels.

Uses the native optimize_ordering to minimise the estimated runtime Σ weight · kernel_cost(slot) over qubit permutations, where kernel_cost captures the two-qubit SIMD threshold (lower index >= 2) and the slower 1-qubit slots 0/1/2.

Parameters

method: "greedy" (default, deterministic) or "sa" / "simulated_annealing". True is a back-compat shorthand for "greedy". seed: Seed for "sa". None draws one from the pass-context RNG. qubit_threshold: Minimum qubit count for the pass to act; smaller circuits pass through unchanged. 0 (the default) always reorders — the gate is meant for the default pipeline, which sets it so reordering only kicks in once the state vector outgrows the cache.

spec()

Identify this pass and its method / optional seed.

preserves(feature)

Always True: relabelling preserves every circuit feature; the pipeline maps the output cstate back to the user's frame.

apply(ctx, circuit)

Run the optimiser and return the rewritten circuit plus the permutation it chose (None if it left the circuit unchanged).


Random number generator — Rng

Rng(seed) is a seeded PRNG handle used by every measurement, sampling, and noise-channel method. The same seed reproduces the same Xoshiro256++ stream across the Rust core and the Python and Julia wrappers.

from exaqt import Rng
rng = Rng(seed=42)

Package metadata

Member Returns
exaqt.__version__ str — installed version of the mimiq-exaqt distribution

exaqt.docs_dir()

Path to the HTML documentation bundled with the package.

Returns the directory holding the built documentation site (index.html and assets) that ships inside the wheel. Open it with the exaqt docs console command. The directory is absent in editable maturin develop installs, which do not build the docs.


Exceptions

All exceptions subclass ExaqtError (itself a RuntimeError):

Exception Raised when
GateShapeError a gate matrix has the wrong shape or layout
QubitIndexError a qubit index is out of bounds, or duplicated
DegenerateStateError sampling a state with zero / non-finite norm
NonUnitaryError a non-unitary user matrix (only with the unitary-checks build feature)