mimiqcircuits.backends

mimiqcircuits.backends — abstract Backend interface for quantum simulators.

Mirrors the Julia AbstractQCSs.jl surface so simulators plug in uniformly across both languages.

Module map:

capabilities, limits, topology -> .capabilities Backend, LocalBackend, RemoteBackend -> .backend Fidelity ADT -> .fidelity CompiledCircuit subclasses + bind -> .compiled AbstractPass + PassPipeline -> .passes Concrete passes (RemoveSwapsPass, …) -> .concrete_passes

Recommended import:

from mimiqcircuits.backends import Backend, LocalBackend, …

mimiqcircuits.backends.Capability

alias of str

class mimiqcircuits.backends.Limits(max_qubits=None, max_bond_dim=None, max_classical_bits=None, max_zvars=None, max_samples=None, max_circuit_depth=None)[source]

Bases: object

Numeric limits a simulator advertises.

None for any field means “unbounded” (or “not applicable” for fields like max_bond_dim on a state-vector simulator).

max_qubits: int | None = None
max_bond_dim: int | None = None
max_classical_bits: int | None = None
max_zvars: int | None = None
max_samples: int | None = None
max_circuit_depth: int | None = None
__init__(max_qubits=None, max_bond_dim=None, max_classical_bits=None, max_zvars=None, max_samples=None, max_circuit_depth=None)
class mimiqcircuits.backends.Topology[source]

Bases: object

Base class for device / connectivity topologies.

class mimiqcircuits.backends.AllToAll[source]

Bases: Topology

All-to-all connectivity (no constraint). Default for simulators.

__init__()
class mimiqcircuits.backends.CouplingMap(edges)[source]

Bases: Topology

Coupling map: each edge (i, j) means qubits i and j can interact directly. 1-based qubit indices to match the rest of MIMIQ.

edges: tuple[tuple[int, int], ...]
__init__(edges)
class mimiqcircuits.backends.LinearChain(n)[source]

Bases: Topology

Linear chain of n qubits with nearest-neighbor coupling.

n: int
__init__(n)
class mimiqcircuits.backends.AdmissionResult[source]

Bases: object

Base class for can_handle(backend, circuit) results.

class mimiqcircuits.backends.Admissible[source]

Bases: AdmissionResult

The backend can execute the circuit.

__init__()
class mimiqcircuits.backends.Marginal(warning)[source]

Bases: AdmissionResult

The backend can execute the circuit but it is near a limit (memory, bond dimension, runtime). warning is a user-facing message; downstream code still treats this as admissible.

warning: str
__init__(warning)
class mimiqcircuits.backends.Inadmissible(reason)[source]

Bases: AdmissionResult

The backend cannot execute the circuit.

reason: str
__init__(reason)
mimiqcircuits.backends.is_admissible(result)[source]

True for Admissible and Marginal.

exception mimiqcircuits.backends.UnsupportedCapabilityError(backend_name, capability, detail='')[source]

Bases: Exception

Raised when a backend is asked to run a feature it does not advertise in Backend.capabilities().

Backends use this to fail loudly rather than silently degrade. Tests rely on it to verify a backend’s capability set is honest (no “positive lies”).

__init__(backend_name, capability, detail='')[source]
mimiqcircuits.backends.register_cap_probe(capability, factory)[source]

Register a probe-circuit constructor for capability.

factory() must return a Circuit whose execution requires the named capability. Conformance tests use this registry to assert that backends reject what they do not advertise — silently accepting an undeclared feature would let “positive lies” slip through.

class mimiqcircuits.backends.Fidelity[source]

Bases: object

Base class for typed fidelity values. See the module docstring for the list of variants and the reducer functions.

class mimiqcircuits.backends.ExactFidelity[source]

Bases: Fidelity

The simulator believes the state is exact.

BLAS and SIMD round-off are not tracked; this is a structural claim about the algorithm, not a bit-perfect guarantee.

__init__()
class mimiqcircuits.backends.UnknownFidelity[source]

Bases: Fidelity

The backend does not track fidelity.

Reducers return nan. Prefer this variant over inventing a placeholder value when you genuinely do not know.

__init__()
class mimiqcircuits.backends.TruncationLowerBound(value)[source]

Bases: Fidelity

A single scalar lower bound on the whole-circuit fidelity.

Typical for MPS / MPO simulators, where value is the product of singular-value tails discarded during compression.

value: float
__init__(value)
class mimiqcircuits.backends.LowerBoundPerStep(values)[source]

Bases: Fidelity

Per-step lower-bound contributions.

as_lower_bound returns prod(clip(values, 0, 1)), which is a lower bound on the circuit fidelity only when successive truncation errors are uncorrelated. If your backend cannot make that assumption, collapse to a single TruncationLowerBound at construction time.

values: tuple[float, ...]
__init__(values)
class mimiqcircuits.backends.EstimatedFidelity(mean, stderr)[source]

Bases: Fidelity

Sample-based fidelity estimate with a standard error.

Use for randomised benchmarking, direct fidelity estimation, or cross-entropy benchmarking. as_lower_bound returns max(0, mean 3·stderr); as_interval returns the ±1σ band.

mean: float
stderr: float
__init__(mean, stderr)
mimiqcircuits.backends.as_lower_bound(f)[source]

Reduce f to a conservative scalar lower bound.

Returns nan when f is UnknownFidelity so that statistics over mixed-type fidelities do not silently treat “unknown” as “good”.

mimiqcircuits.backends.as_expected(f)[source]

Reduce f to a central / expected scalar.

For TruncationLowerBound the lower bound is the estimate; for EstimatedFidelity it is the sample mean. Returns nan for UnknownFidelity.

mimiqcircuits.backends.as_interval(f)[source]

(lo, hi) band. ±1σ for EstimatedFidelity; otherwise (as_lower_bound, as_expected).

class mimiqcircuits.backends.CompiledCircuit[source]

Bases: object

Backend-specific deterministic representation of a circuit.

Returned by LocalBackend.compile(). Concrete backends subclass to carry whatever payload they need — an MPO for an MPS simulator, a plain Circuit for a state-vector backend, a streaming thunk for an out-of-core simulator, …

Every subclass exposes two attributes:

property metadata: CompileMetadata
property source

The backend-specific artifact wrapped by this compiled circuit (e.g. a Circuit, an MPO, a streaming thunk).

class mimiqcircuits.backends.DefaultCompiledCircuit(_source, _metadata=<factory>)[source]

Bases: CompiledCircuit

Generic passthrough wrapper.

Use this when your backend’s compile step is effectively the identity — for example a state-vector simulator that consumes the input Circuit directly.

property metadata: CompileMetadata
property source

The backend-specific artifact wrapped by this compiled circuit (e.g. a Circuit, an MPO, a streaming thunk).

__init__(_source, _metadata=<factory>)
class mimiqcircuits.backends.CompiledParametricCircuit(_source, _metadata=<factory>)[source]

Bases: CompiledCircuit

Compiled artifact that still carries free symbolic parameters.

Produced by LocalBackend.compile() when the input is symbolic and the backend advertises the "parametric" capability. Resolve the parameters by calling LocalBackend.bind().

property metadata: CompileMetadata
property source

The backend-specific artifact wrapped by this compiled circuit (e.g. a Circuit, an MPO, a streaming thunk).

__init__(_source, _metadata=<factory>)
class mimiqcircuits.backends.CompileMetadata(measures=<factory>, active_qubits=<factory>, qubit_flips=<factory>, qubit_permutation=None, measure_action_counts=<factory>, prefix_endpoint=0)[source]

Bases: object

Compile-time side effects carried alongside a CompiledCircuit.

measures

Measurement-analysis entries (classifies each classical bit as Unused / Direct / Flip / Const0 / Const1). Empty when analysis has not run.

Type:

list

active_qubits

Qubit indices that must be simulated; the others can be dropped because they are provably |0⟩ at measurement.

Type:

list[int]

qubit_flips

Per-qubit final NOT flag absorbed from trailing single-qubit X gates.

Type:

list[bool]

qubit_permutation

Composed permutation applied by the pass pipeline. None when the pipeline is identity on qubit indices.

Type:

list[int] or None

measure_action_counts

Frequency of each measurement-action branch (debug aid).

Type:

dict[str, int]

prefix_endpoint

Index of the last instruction folded into the deterministic prefix when the backend splits prefix from stochastic suffix; 0 when no split applies.

Type:

int

measures: list
active_qubits: list[int]
qubit_flips: list[bool]
qubit_permutation: list[int] | None = None
measure_action_counts: dict[str, int]
prefix_endpoint: int = 0
__init__(measures=<factory>, active_qubits=<factory>, qubit_flips=<factory>, qubit_permutation=None, measure_action_counts=<factory>, prefix_endpoint=0)
exception mimiqcircuits.backends.UnboundSymbolicError(backend_name)[source]

Bases: Exception

Raised when LocalBackend.compile() is handed a circuit that still has free symbolic parameters but the backend does not advertise the "parametric" capability.

__init__(backend_name)[source]
class mimiqcircuits.backends.PassParam[source]

Bases: object

Base class for the JSON-safe sum used to serialise pass parameters.

The tagged variants (PStr, PInt, PFloat, PBool, PSym, PList, PDict) keep type information a plain dict would lose on the wire — e.g. "greedy" (a PStr) must not silently degrade and come back as a PSym. Equality is tag-sensitive: PSym("x") != PStr("x").

class mimiqcircuits.backends.PStr(value: 'str')[source]

Bases: PassParam

value: str
__init__(value)
class mimiqcircuits.backends.PInt(value: 'int')[source]

Bases: PassParam

value: int
__init__(value)
class mimiqcircuits.backends.PFloat(value: 'float')[source]

Bases: PassParam

value: float
__init__(value)
class mimiqcircuits.backends.PBool(value: 'bool')[source]

Bases: PassParam

value: bool
__init__(value)
class mimiqcircuits.backends.PSym(value)[source]

Bases: PassParam

Pass parameter that is semantically a Symbol (Julia) or enum.Enum-like in Python. Distinct from PStr at the tag level.

value: str
__init__(value)
class mimiqcircuits.backends.PList(items: 'tuple[PassParam, ...]')[source]

Bases: PassParam

items: tuple[PassParam, ...]
__init__(items)
class mimiqcircuits.backends.PDict(items: 'tuple[tuple[str, PassParam], ...]')[source]

Bases: PassParam

items: tuple[tuple[str, PassParam], ...]
__init__(items)
mimiqcircuits.backends.to_pass_param(x)[source]

Coerce a common Python value into a PassParam.

The bool-before-int check is load-bearing: bool is a subclass of int in Python, so isinstance(True, int) is True and reversing the order would tag every boolean as PInt.

class mimiqcircuits.backends.PassSpec(name, parameters=(), requires=(), conflicts=())[source]

Bases: object

Declarative summary of a pass.

Used for equality / memoisation (two passes with the same spec have the same hash and compare equal), for remote dispatch (the spec is the only thing shipped over the wire), and for observability. Equality is structural.

requires names other passes that must run before this one; conflicts names passes that cannot coexist with this one in the same pipeline. Both are advisory.

name: str
parameters: tuple[tuple[str, PassParam], ...] = ()
requires: tuple[str, ...] = ()
conflicts: tuple[str, ...] = ()
static from_dict(name, parameters=None, requires=(), conflicts=())[source]
__init__(name, parameters=(), requires=(), conflicts=())
class mimiqcircuits.backends.PassResult(qubit_permutation=None, metadata=<factory>)[source]

Bases: object

Side effects returned from AbstractPass.apply().

qubit_permutation is None when the pass leaves qubit indices unchanged. Any pass that does relabel qubits must return the relabel here so the pipeline can compose permutations and un-shuffle downstream outputs.

metadata is free-form pass-specific information (timings, gate counts, …) surfaced for observability.

qubit_permutation: list[int] | None = None
metadata: dict[str, Any]
__init__(qubit_permutation=None, metadata=<factory>)
class mimiqcircuits.backends.PassContext(backend=None, rng=<factory>, bitstrings=<factory>, features=<factory>)[source]

Bases: object

Inputs a pass needs but should not fetch from global state.

backend is the Backend the pipeline is compiling for, or None for backend-agnostic runs. rng is the dedicated pass-internal RNG. bitstrings are user-supplied amplitude targets in the original qubit space; the pipeline rewrites them into post-pass space as permutations compose. features are detected on the input circuit and filter passes via AbstractPass.preserves().

backend: Any | None = None
rng: Random
bitstrings: list
features: set[str]
__init__(backend=None, rng=<factory>, bitstrings=<factory>, features=<factory>)
class mimiqcircuits.backends.AbstractPass[source]

Bases: ABC

Base class for circuit-transformation passes.

Subclasses implement:

  • spec() — return a PassSpec describing the pass (used for equality, serialisation, and remote dispatch).

  • apply() — return (new_circuit, PassResult).

  • preserves() — override when the pass breaks a circuit feature; the default returns True for every feature. The pipeline filters passes by feature when the input circuit has a feature that the pass must preserve.

Recognised feature tokens: "feed_forward", "midcircuit_measure", "parametric", "loss", "exact_equivalence", "strict_qubit_count".

abstract spec()[source]
abstract apply(ctx, circuit)[source]
preserves(feature)[source]
class mimiqcircuits.backends.PassPipeline(passes=<factory>)[source]

Bases: object

An ordered, iterable sequence of passes.

Run via apply_passes(), which composes each pass’s qubit_permutation into a single permutation. Callers use the inverse of that permutation to map samples and Amplitude / ExpectationValue results back to the user’s original qubit space.

passes: list[AbstractPass]
__init__(passes=<factory>)
mimiqcircuits.backends.apply_passes(pipeline, ctx, circuit)[source]

Run pipeline against circuit.

Returns (transformed_circuit, composed_permutation, per_pass_results). composed_permutation is None when every pass left qubit indices unchanged.

Raises UnacceptedPassError if the backend rejects any pass. When the backend reports delegates_pass(p) is True the pass is not run here: the pipeline records a marker result and the backend handles the pass natively inside its compile or evolve.

mimiqcircuits.backends.invert_perm(perm)[source]

Inverse of a 1-based permutation.

exception mimiqcircuits.backends.UnacceptedPassError(backend_name, pass_name)[source]

Bases: Exception

Raised when a pipeline contains a pass the backend rejects.

The backend’s Backend.accepts_pass() is the gate; the pipeline fails loudly rather than silently dropping a pass the user explicitly requested.

__init__(backend_name, pass_name)[source]
exception mimiqcircuits.backends.RemotePassOrderError(backend_name)[source]

Bases: Exception

Raised when an ordered pipeline is submitted to a remote backend that does not advertise the "pass_order_honored" capability while strict_pass_order=True.

Pass strict_pass_order=False to opt into an unordered submission (recognised passes are translated into the server’s flat option set; unrecognised passes are dropped with a warning).

__init__(backend_name)[source]
class mimiqcircuits.backends.Backend[source]

Bases: ABC

Abstract base class for any simulator backend.

A concrete backend must:

Pick the right base for your simulator:

  • LocalBackend — the simulator runs in-process and you can hand it a State it mutates with each instruction.

  • RemoteBackend — the simulator runs elsewhere (cloud service, queued executor) and your wrapper submits jobs and polls for results.

See Implementing a Custom Backend.

abstract property name: str
abstract property version: str
abstract capabilities()[source]
limits()[source]
topology()[source]
can_handle(circuit)[source]

Default admission check against limits() and the backend’s advertised capabilities().

Backends with richer admission criteria (bond-dimension estimates, hardware connectivity, gate-set whitelists) should override.

Rejects (returns Inadmissible) when:

  • the circuit exceeds one of max_qubits / max_classical_bits / max_zvars declared by limits();

  • the circuit contains a loss-bearing operation (LossErr, QubitLoss) but the backend does not advertise the "loss" capability.

Returns Admissible otherwise.

stochastic_kind(op_or_instruction)[source]

Classify how this backend resolves op_or_instructionStochasticKind.Deterministic, StochasticKind.TrajectorySampleable, or StochasticKind.RuntimeOnly.

The default delegates to default_stochastic_kind() (mix-unitary Kraus is TS; non-mix-unitary Kraus, mid-circuit Measure, and LossErr are RT; everything else Deterministic). Backends that handle a specific op type differently override this method.

Backend-dependent: a MixedUnitary is TrajectorySampleable for an MPS-style sampler but could be RuntimeOnly for a backend that resolves it state-dependently. The classification lives on the backend, not on the op.

default_passes()[source]
accepts_pass(p)[source]
delegates_pass(p)[source]
abstract execute(circuit, *, nsamples=1000, seed=None, rng=None, passes=None, callback=None, param_grid=None, strict_pass_order=True)[source]

Run circuit on this backend and return QCSResults.

Pass circuit as a single Circuit or a list of circuits — a list returns a list of results in the same shape.

seed and rng are mutually exclusive sources of randomness; pass at most one. With neither, the backend draws fresh entropy. To request specific amplitudes, push Amplitude instructions into circuit and read the resulting results.zstates.

expectation(state, op, *qubits)[source]

Compute ⟨ψ|op|ψ⟩ on state non-destructively.

qubits is the list of qubit indices op acts on (0-based). Backends override when they advertise the "expectation_state" capability; the default raises NotImplementedError so undeclared backends fail loudly rather than silently degrading.

class mimiqcircuits.backends.LocalBackend[source]

Bases: Backend

Base class for simulators that run in the local process.

Subclasses implement a handful of primitives and inherit a full execute() driver — the Python analog of the Julia AbstractQCSs.execute driver. Once the hooks are wired up, routing (sampling-vs-trajectory), the final-block projection circuit, loss-sampling pre-pass, and amplitude lookups all work without any per-backend duplication.

Required hooks:

Optional hooks (sensible defaults provided):

  • prepare_trajectory() — refresh the compiled artifact once per Monte Carlo trajectory (default: identity).

  • recompile_per_trajectory() — predicate; default returns True iff the circuit contains a mixed-unitary Kraus channel.

  • bind() — substitute parameters into a parametric compile artifact (default: re-compile after substitution).

abstract build_state(nq, nb=0, nz=0, **kwargs)[source]
abstract compile(circuit)[source]
prepare_trajectory(compiled, rng)[source]

Refresh compiled for one Monte Carlo trajectory.

Override when the compiled artifact contains stochastic elements (sampled mixed-unitary channels, sampled Kraus branches, …) that must be redrawn per trajectory. The default leaves compiled unchanged, which is correct for fully deterministic compilation.

abstract evolve(state, compiled, *, rng=None, callback=None, stopped=None)[source]
recompile_per_trajectory(circuit)[source]

Return True iff compile() should be re-run for every trajectory. The default fires on any mixed-unitary krauschannel: those backends sample a branch at compile time, so the compiled artifact has to be regenerated per trajectory to expose a fresh sample. Backends that own their per-trajectory sampling internally (inside prepare_trajectory() or evolve()) should override to return False.

Mirrors the Julia AbstractQCSs.recompile_per_trajectory.

bind(compiled, params)[source]

Substitute params into a parametric compiled circuit.

The default implementation substitutes the symbols in the source circuit and re-runs compile(). This is correct but pays the full compile cost at every parameter point. Override when your backend can re-bind a pre-compiled artifact in-place (slot maps, pre-baked gate templates, …).

execute(circuit, *, nsamples=1000, seed=None, rng=None, passes=None, callback=None, param_grid=None, strict_pass_order=True, stopped=None, num_qubits=None)[source]

Run circuit on this backend and return QCSResults.

Pass circuit as a single Circuit or a list of circuits — a list returns a list of results in the same shape.

seed and rng are mutually exclusive sources of randomness; pass at most one. With neither, the backend draws fresh entropy. To request specific amplitudes, push Amplitude instructions into circuit and read the resulting results.zstates.

class mimiqcircuits.backends.RemoteBackend[source]

Bases: Backend

Base class for simulators that run on a remote service.

Subclasses implement submit(), which dispatches the request and returns a job handle. The inherited execute() calls submit(), then blocks on the returned job.wait().

abstract submit(circuits, nsamples, **kwargs)[source]

Send the request and return a job handle.

The job handle must expose a wait() method that blocks until results are available and returns mimiqcircuits.QCSResults (or a list when circuits was a list).

execute(circuit, *, nsamples=1000, seed=None, rng=None, passes=None, callback=None, param_grid=None, strict_pass_order=True)[source]

Run circuit on this backend and return QCSResults.

Pass circuit as a single Circuit or a list of circuits — a list returns a list of results in the same shape.

seed and rng are mutually exclusive sources of randomness; pass at most one. With neither, the backend draws fresh entropy. To request specific amplitudes, push Amplitude instructions into circuit and read the resulting results.zstates.

class mimiqcircuits.backends.State[source]

Bases: ABC

Composite simulation state held by a backend.

A state bundles three registers:

  • the quantum register (whatever representation the backend uses; state vector, MPS, tensor network, …);

  • the classical-bit register written by measurements and IfStatement outcomes;

  • the complex-valued register written by non-destructive observations (Amplitude, ExpectationValue, BondDim, …).

Required surface for every subclass:

Optional surface:

  • expectation() — backend overrides when it can compute ⟨ψ|O|ψ⟩ non-destructively (gated by the "expectation_state" capability).

  • reset() — backend overrides when it can rebuild itself in place to the zero state.

abstract property num_qubits: int

Number of qubits in the quantum register.

abstract property num_bits: int

Number of classical bits in the classical register.

abstract property num_zvars: int

Number of complex slots in the z-register.

abstract amplitude(bs)[source]
abstract sample(nsamples, rng=None, *, seed=None)[source]

Sample nsamples measurement outcomes from the state.

Exactly one source of randomness is consumed:

  • rng (positional or keyword): a random.Random whose getrandbits(63) produces the seed forwarded to the simulator’s PRNG.

  • seed (keyword): an int that seeds the simulator’s default PRNG directly.

  • neither: the simulator draws fresh cryptographic entropy.

Passing both rng and seed must raise TypeError. The two arguments are mutually exclusive.

expectation(op, *qubits)[source]

Compute ⟨ψ|op|ψ⟩ on this state.

Most backends implement expectation on the Backend rather than the State (so they can route through the simulator’s compile / evolve machinery). State-level expectation is provided as a convenience hook for backends whose quantum register supports it directly.

abstract property classical_bits
abstract property complex_values
reset()[source]
class mimiqcircuits.backends.RNGs(shot, noise, trajectory, pass_)[source]

Bases: object

Four independent RNG streams, one per simulation stage.

Keeping the streams separate means seeding one stage (for example sampling) does not affect the determinism of another (for example noise selection), even when the same execution touches both.

shot

Sampling shots from the final state.

Type:

random.Random

noise

Kraus and mixed-unitary noise sampling.

Type:

random.Random

trajectory

Monte Carlo trajectory selection.

Type:

random.Random

pass_

Randomised compilation passes (e.g. simulated-annealing reorderers).

Type:

random.Random

Construct from a single int seed via :py:meth:`from_seed`.
shot: Random
noise: Random
trajectory: Random
pass_: Random
static from_seed(master)[source]

Derive four streams from a single master seed.

XOR-tags the seed bits per stream — cheap, deterministic, and stable across Python versions, which matters because the downstream backends must reproduce results bit-for-bit from the same input.

static from_generator(gen)[source]

Draw a master seed from gen and forward to from_seed().

__init__(shot, noise, trajectory, pass_)
class mimiqcircuits.backends.MimiqRemoteBackend(connection, *, algorithm='auto', label=None, poll_interval=1.0)[source]

Bases: RemoteBackend

Cloud backend wrapping a mimiqcircuits.remote.RemoteConnection.

Construct with an authenticated connection (or any object that exposes callable submit(...) and get_results(...) methods). The constructor pins the simulator algorithm (which in turn shapes capabilities()) and the label / poll cadence; all other server knobs (bonddim, entdim, mpscutoff, mpsmethod, mpotraversal, timelimit, noisemodel) are passed at submit() / execute() time.

Caveats:

  1. Capabilities are synthesised client-side. The server has no capability endpoint yet, so capabilities() returns a conservative best-guess (_BASE_REMOTE_CAPABILITIES plus algorithm-conditional MPS tokens).

  2. ``pass_order_honored`` is not declared. The server takes a flat bag of booleans (remove_swaps, fuse, …) with no notion of pipeline order. A non-empty passes= with the default strict_pass_order=True raises RemotePassOrderError. Opt out with strict_pass_order=False: recognised passes are translated into legacy knobs and unrecognised ones are dropped with a single UserWarning.

  3. ``param_grid=`` raises NotImplementedError. Loop on the client side instead:

    for params in grid:
        backend.execute(c.evaluate(params), nsamples=n, seed=...)
    
  4. ``noisemodel=`` and ``ApplyNoiseModelPass`` are mutually exclusive. Specifying both raises ValueError.

  5. ``_MimiqJob.wait()`` blocks indefinitely by default. Pass timeout=<seconds> for a bounded wait that raises TimeoutError.

  6. ``seed=`` / ``rng=`` are mutually exclusive. The wire seed is a deterministic xor-fold of the four-stream RNGs bundle derived from your input, not literally the integer passed in.

  7. The connection must be authenticated (conn.connect() called) before the first execute(). The constructor does not trigger interactive auth, so an unauthenticated connection produces a 401 at submit time.

  8. Output shape mirrors input: a single Circuit returns a single QCSResults; a list returns a list of matching length.

  9. ``algorithm=”statevector”`` + ``noisemodel=`` is a server-side runtime error — state-vector cannot apply Kraus — and there is currently no client-side guard.

  10. ``algorithm=”statevector”`` makes MPS knobs meaningless (bonddim=, entdim=, mpscutoff=, mpsmethod=, mpotraversal=, BondDim / SchmidtRank instructions). capabilities() correctly omits :bond_dim / :schmidt_rank in that mode and limits() returns max_bond_dim=None, but submit() still forwards the kwargs to the server, which is canonical.

Example:

import mimiqcircuits as mc
conn = mc.MimiqConnection()
conn.connect()
backend = mc.backends.MimiqRemoteBackend(conn, algorithm="mps")
results = backend.execute(circuit, nsamples=1000, seed=42, bonddim=64)
__init__(connection, *, algorithm='auto', label=None, poll_interval=1.0)[source]
property name: str
property version: str
capabilities()[source]

Synthesised client-side. Tensor-network annotations (:bond_dim, :schmidt_rank) are declared only when the configured algorithm admits MPS execution.

limits()[source]

Static client-side limits. max_bond_dim is dropped on state-vector deployments where bond dimension is meaningless.

topology()[source]
submit(circuits, nsamples=1000, *, rngs=None, passes=None, callback=None, param_grid=None, strict_pass_order=True, bonddim=None, entdim=None, mpscutoff=None, mpsmethod=None, mpotraversal=None, timelimit=None, noisemodel=None, **kwargs)[source]

Submit circuits to the remote server.

Returns a _MimiqJob. Calling job.wait() blocks until results are available and post-processes QCSResults.fidelities into typed Fidelity instances.

execute(circuit, *, nsamples=1000, seed=None, rng=None, passes=None, callback=None, param_grid=None, strict_pass_order=True, **kwargs)[source]

Submit circuit to the cloud and wait for results.

seed and rng are mutually exclusive sources of randomness. Submit-time tuning options (bonddim, entdim, mpscutoff, mpsmethod, mpotraversal, timelimit, noisemodel) pass through to submit().

Output shape mirrors input: a single Circuit returns a single QCSResults; list[Circuit] returns list[QCSResults].

To request specific amplitudes, push Amplitude instructions into circuit and read results.zstates.

mimiqcircuits.backends.normalize_seed(seed, rngs)[source]

Reconcile the legacy seed= and the new rngs= kwargs.

Either may be provided, never both. rngs may be an int (passed through), an RNGs bundle (xor-folded to one seed), or None (returns the seed argument).

mimiqcircuits.backends.derive_grid_seeds(base_seed, n)[source]

Deterministically derive n distinct seeds from base_seed.

The param_grid loop calls this so each parameter point gets a different RNG stream; reusing base_seed directly would tie measurement outcomes across grid points. A None base_seed propagates as [None] * n (caller wants nondeterminism).

mimiqcircuits.backends.extract_projection(circuit)[source]

Reverse-scan circuit, absorbing every trailing operation that does not affect the qubit observables of the post-evolution state into a projection_circuit of classical-bit instructions. The remaining operations are returned as quantum_circuit — the part the simulator must evolve.

Absorbed operations:

  • Trailing Measure(q, b) / MeasureReset(q, b)Measure(q, b).

  • Trailing GateID — dropped as a no-op. GateX / GateY / GateZ are NOT absorbed: Y and Z carry phases that would corrupt amplitude lookups, and X absorbed alone would require XOR-ing the qubit-flip pattern into every user-supplied bitstrings entry for amplitudes to stay consistent. Keeping all Paulis in quantum_circuit means the projection only contains phase-free transformations and amplitude lookups need no compensation.

  • Reset(q) whose qubit has captured pending bits → those bits become classical constants (SetBit0 / SetBit1 based on absorbed X parity). A Reset whose qubit has no captured bits is harmless and dropped.

Anything that cannot be absorbed (other gates, Kraus channels, IfStatement, Amplitude, ExpectationValue, …) blocks its qubits and survives into quantum_circuit.

If the source has no classical register, the projection is synthesised over an identity bit↔qubit mapping (bit i mirrors qubit i, length = circuit.num_qubits()).

mimiqcircuits.backends.evaluate_projection(projection, sample)[source]

Run the projection circuit on a single raw quantum-state sample, returning the resulting classical bitstring.

mimiqcircuits.backends.needs_trajectories(circuit)[source]

Return True if circuit still contains any non-unitary op that requires per-shot evolution. Operations that don’t touch qubits (Amplitude on a z-register, Tick, …) or that declare themselves unitary (Gates, AbstractAnnotation, ExpectationValue, …) are ignored.

Mirrors the Julia AbstractQCSs.needs_trajectories: num_qubits(op) != 0 && !isunitary(op).

mimiqcircuits.backends.needs_loss_sampling(circuit)[source]

Return True if circuit contains a LossErr or QubitLoss operation that must be sampled (Method-1 pre-evolve sampling) before the simulator runs.

mimiqcircuits.backends.any_mixed_unitary(circuit)[source]

Return True if circuit contains a mixed-unitary krauschannel whose ismixedunitary() is true. Used as the default predicate for the per-trajectory recompile decision in LocalBackend.recompile_per_trajectory().

Mirrors the Julia AbstractQCSs.any_mixed_unitary.

mimiqcircuits.backends.remap_projection_qubits(projection, qubit_order, do_remap)[source]

Rewrite every Measure(q, b) instruction in projection so that q qubit_order[q]. Used by the driver when the pass pipeline reordered the qubits and the projection was synthesised in the reordered frame.

Returns a new Circuit; the input is not mutated.

class mimiqcircuits.backends.StochasticKind(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: IntEnum

Resolution-time taxonomy for operations.

Ordered so worst-case combines (max) compose across composite ops: Deterministic < TrajectorySampleable < RuntimeOnly.

  • Deterministic — no randomness; compile() can lower the op into the backend’s compiled form using only the source-circuit information.

  • TrajectorySampleable — non-deterministic but resolvable in prepare_trajectory() using RNG draws alone. Classical sample space and probabilities are state-independent as far as this backend is concerned.

  • RuntimeOnly — must be resolved during evolve() because branch probabilities or control-flow truth values depend on the live quantum or classical state.

Backend-dependent. See Backend.stochastic_kind().

Deterministic = 0
TrajectorySampleable = 1
RuntimeOnly = 2
mimiqcircuits.backends.default_stochastic_kind(op)[source]

Backend-agnostic default classification used by Backend.stochastic_kind(). Concrete backends override the method on Backend (not this function) when they handle a specific op type differently.

Defaults:

  • IfStatement / similar wrappers: recurse on the inner op.

  • krauschannel: TrajectorySampleable if ismixedunitary, else RuntimeOnly.

  • LossErr: RuntimeOnly (until sample_losses moves into prepare_trajectory(); F-S2 follow-up).

  • AbstractMeasurement: RuntimeOnly.

  • everything else: Deterministic.

mimiqcircuits.backends.stochastic_kind(backend, x)[source]

Free-function form: stochastic_kind(backend, x). Delegates to backend.stochastic_kind(x) so subclasses’ overrides bite.

mimiqcircuits.backends.is_deterministic(backend, x)[source]
mimiqcircuits.backends.is_trajectory_sampleable(backend, x)[source]
mimiqcircuits.backends.is_runtime_only(backend, x)[source]
mimiqcircuits.backends.is_stochastic(backend, x)[source]
mimiqcircuits.backends.first_stochastic(backend, circuit)[source]

Index of the first non-deterministic instruction in circuit as classified by backend, or None if purely deterministic.

mimiqcircuits.backends.last_stochastic(backend, circuit)[source]

Index of the last non-deterministic instruction in circuit, or None if purely deterministic.

mimiqcircuits.backends.first_runtime_only(backend, circuit)[source]

Index of the first RuntimeOnly instruction in circuit, or None if none exists. Distinct from first_stochastic(): TrajectorySampleable ops do not require barrier protection in MPS-style backends.

mimiqcircuits.backends.last_runtime_only(backend, circuit)[source]

Modules

backend

Abstract base classes for simulator backends.

capabilities

Capability vocabulary, numeric limits, topology, and admission types.

compiled

Compiled-circuit types and the metadata they carry.

fidelity

Typed fidelity values returned by Backend.evolve().

measure_analysis

Final-block analysis.

passes

Optimization-pass framework.

remote

Concrete RemoteBackend for the MIMIQ cloud service.

stochastic_kind(backend, x)

Free-function form: stochastic_kind(backend, x).