API reference¶
Backend¶
- class mimiq_qiskit.MimiqBackend(runner, *, name='mimiq', num_qubits=64, description=None, provider=None)[source]¶
Qiskit BackendV2 powered by MIMIQ.
- Parameters:
runner (
Any) – A MIMIQ connection, a MIMIQBackendinstance, or a(circuit, *, nsamples, seed) -> QCSResultscallable.name (
str) – Backend name reported to Qiskit. Defaults to"mimiq".num_qubits (
int) – Qubit count advertised on theTarget. The MIMIQ cloud handles many more; raise this when transpiling wide circuits against the backend.description (
str|None) – Human-readable backend description.
Beyond
shotsandseed,runaccepts MIMIQ-specific options which are forwarded to MIMIQ when set: the circuit-preparation knobsfuse,fuse_threshold,canonicaldecompose,reorderqubits,remove_swaps, and the simulator/job settingsbonddim,entdim,mpscutoff,mpsmethod,mpotraversal,timelimit,noisemodel,label.- property max_circuits: int | None¶
The maximum number of circuits that can be run in a single job.
If there is no limit this will return None
- run(run_input, **options)[source]¶
Convert and submit one circuit or a list of circuits to MIMIQ.
- Parameters:
run_input – A
QuantumCircuitor an iterable of them.**options –
shotsandseed, plus any of the MIMIQ-specific run options listed on the class. Options set here override the backend defaults for this call.
- Return type:
- Returns:
A
MimiqJobrunning the whole batch as one MIMIQ job; calljob.result()to block for theqiskit.result.Result.
- property target: Target¶
A
qiskit.transpiler.Targetobject for the backend.- Return type:
Target
- class mimiq_qiskit.MimiqJob(backend, *, qiskit_circuits, work, shots, job_id=None)[source]¶
Background-thread job. One thread per
run()call.workis a zero-argument callable returning the list ofQCSResults(one per submitted circuit); the whole batch is one MIMIQ job.
- class mimiq_qiskit.MimiqProvider(runner, *, num_qubits=64)[source]¶
Expose the MIMIQ backend for a single connection or runner.
Example:
from mimiqlink import MimiqConnection from mimiq_qiskit import MimiqProvider conn = MimiqConnection(); conn.connect() provider = MimiqProvider(conn) backend = provider.get_backend("mimiq")
Primitives¶
Native Qiskit V2 primitives backed by MIMIQ. Prefer these over Qiskit’s
generic BackendSamplerV2 / BackendEstimatorV2: the estimator reads
observables off the state instead of sampling them, and both batch a pub’s
circuits into a single MIMIQ submission. See Circuits that end in an ensemble
for how the estimator handles a circuit that ends in an ensemble.
- class mimiq_qiskit.MimiqSamplerV2(backend, *, default_shots=1024, seed=None, run_options=None)[source]¶
BaseSamplerV2that samples bitstrings on MIMIQ.- Parameters:
backend – A
MimiqBackend, or a connection / MIMIQ backend / runner thatMimiqBackendcan wrap.default_shots (
int) – Shots used for pubs that don’t specify their own.seed – Seed forwarded to MIMIQ. Defaults to the backend’s.
run_options – Extra MIMIQ run options (
noisemodel,bonddim, …) merged over the backend’s.
- run(pubs, *, shots=None)[source]¶
Run and collect samples from each pub.
- Parameters:
pubs (
Iterable) – An iterable of pub-like objects. For example, a list of circuits or tuples(circuit, parameter_values).shots (
int|None) – The total number of shots to sample for each sampler pub that does not specify its own shots. IfNone, the primitive’s default shots value will be used, which can vary by implementation.
- Return type:
- Returns:
The job object of Sampler’s result.
- class mimiq_qiskit.MimiqEstimatorV2(backend, *, method='auto', trajectories=None, shots=None, emulate_shot_noise=False, default_precision=0.0, seed=None, run_options=None)[source]¶
BaseEstimatorV2that evaluates observables on MIMIQ.Each Pauli term is evaluated on the simulator state rather than sampled, so a circuit that ends in a definite state gives an exact value at any term weight and reports a standard error of zero.
A circuit that ends in an ensemble has no single exact value: a mid-circuit measurement, a reset, a noise channel, or a server-side
noisemodelmakes MIMIQ re-evolve the circuit once per shot, and each trajectory has its own expectation value. The average over trajectories is the density-matrix value, so that is what this reports, with the sample standard error instds. Reading one trajectory would be unbiased but as noisy as the observable’s range, so a stochastic circuit with no budget raises rather than returning it. Ashotsbudget switches to hardware-style estimation from measurements in rotated bases.mimiq_qiskit.estimationdocuments the three methods and howmethod="auto"chooses between them.- Parameters:
backend – A
MimiqBackend, or anything it can wrap.method (
str) –"auto"(default),"exact","trajectories", or"shots".trajectories (
int|None) – Trajectories to average for a stochastic circuit.Nonesizes it fromprecision. Ignored for a deterministic circuit, which has one answer.shots (
int|None) – Shots per measurement basis. Giving this selects sampled estimation;Nonesizes it fromprecisionwhenmethod="shots".emulate_shot_noise (
bool) – Add Gaussian noise of widthprecisionto an otherwise exact value, as Qiskit’sStatevectorEstimatordoes. One evolution instead of a shot budget, for code that wants to see plausible shot noise without paying for it.default_precision (
float) – Precision forruncalls and pubs that do not carry their own.0.0, meaning “as exact as the simulator gets”.seed – Seed forwarded to MIMIQ, and to the
emulate_shot_noisegenerator. Defaults to the backend’s.run_options – Extra MIMIQ run options merged over the backend’s.
Result metadata reports
method, whether the value isexact, whether the run wasstochastic, thetrajectoriesorshotsspent, thetarget_precision, andmin_fidelity: the lowest simulator fidelity behind the pub, which on an MPS backend is the truncation error that averaging cannot remove.- run(pubs, *, precision=None)[source]¶
Estimate every pub and return the job carrying the results.
precisionoverridesdefault_precisionfor this call. A positive value sizes the trajectory or shot budget asceil(1/precision**2)where one is needed.- Parameters:
- Return type:
Converters¶
See What converts, and how for what each direction accepts.
- mimiq_qiskit.qiskit_to_mimiq(qc)[source]¶
Convert a Qiskit
QuantumCircuitto a MIMIQmimiqcircuits.Circuit.- Parameters:
qc – A Qiskit
QuantumCircuit.- Return type:
Circuit- Returns:
A MIMIQ
Circuitwith operations pushed in the same order.- Raises:
UnsupportedGateError – An operation in
qchas neither a MIMIQ mapping nor a Qiskit definition to decompose.
- mimiq_qiskit.mimiq_to_qiskit(circuit)[source]¶
Convert a MIMIQ
Circuitback to a QiskitQuantumCircuit.Gates map onto concrete Qiskit gate classes, so the result is a fully defined circuit that Qiskit can transpile and simulate. Any unitary operation with no named counterpart –
Control,Inverse,Power,Parallel,GateCustom, and gates Qiskit has no equivalent for such asGateSYorGateRNZ– becomes aUnitaryGatecarrying its matrix. That is operator-faithful but not structure-faithful, so a round trip through both converters preserves the unitary, not the gate names.The result uses single anonymous quantum and classical registers sized to the circuit; register identity from any original Qiskit circuit is not preserved.
- Raises:
UnsupportedGateError – The circuit holds a non-unitary operation with no Qiskit equivalent (a noise channel, for instance), or a gate with unbound symbolic parameters.
- Parameters:
circuit (
Circuit)
- exception mimiq_qiskit.converter.UnsupportedGateError[source]¶
Raised when a Qiskit or MIMIQ operation has no mapping.
Estimation internals¶
The engine behind MimiqEstimatorV2, and the Pauli-observable
helpers it rests on. These are the shared surface a provider-specific
estimator builds on, so that every MIMIQ estimator resolves methods,
averages trajectories, and reports metadata identically.
The estimation engine behind the MIMIQ Qiskit estimators.
MimiqEstimatorV2 runs this against a MimiqBackend,
and provider-specific estimators (such as TensorWeaver’s) run it against their
own simulator, so that every one of them resolves methods, averages
trajectories, and reports metadata the same way. Feed
estimate_pub() an EstimatorPub,
an EstimatorConfig, and a run callable that submits MIMIQ
circuits.
Three ways to get an expectation value¶
exactOne evolution, and each Pauli term read straight off the state. No statistical error at all: the only error is the simulator’s own (for an MPS engine, the truncation). Only meaningful for a circuit that ends in a single definite state.
trajectoriesA circuit carrying a mid-circuit measurement, a reset, a noise channel, or qubit loss does not end in one state; it ends in an ensemble. The engine re-evolves it once per shot, and each trajectory reports its own expectation value. Averaging them estimates the density-matrix value \(\mathrm{Tr}(\rho O)\) without bias, so that is what this does. Reading one trajectory instead, as a single-shot run must, returns a random draw whose spread can cover the observable’s whole range.
shotsWhat hardware and Qiskit’s own
BackendEstimatorV2do: rotate into each measurement basis, measure, and average the ±1 eigenvalues. Correct for every circuit, and the way to compare against a shot-based reference, but for the same budget it is strictly noisier than averaging trajectories, since it samples the observable on top of sampling the ensemble.
The default, "auto", evaluates exactly when the circuit is deterministic
and averages trajectories when it is not. It refuses to guess a budget: a
stochastic circuit with no trajectories, shots, or precision set
raises rather than returning one trajectory dressed up as an exact number.
- class mimiq_qiskit.estimation.EstimatorConfig(method='auto', trajectories=None, shots=None, emulate_shot_noise=False, default_precision=0.0, seed=None, assume_stochastic=False)[source]¶
How an estimator should turn circuits into expectation values.
- Parameters:
method (
str) –"auto"(the default) evaluates exactly when the circuit is deterministic and averages trajectories when it is not."exact","trajectories", and"shots"force one of the three methods described in this module.trajectories (
int|None) – Trajectories to average.Nonesizes it from the pub’sprecision.shots (
int|None) – Shots per measurement basis for the sampled method.Nonesizes it from the pub’sprecision. Giving this selects"shots"undermethod="auto".emulate_shot_noise (
bool) – Add Gaussian noise of widthprecisionto a value that came out exact, the way Qiskit’sStatevectorEstimatordoes. A cheap stand-in for shot noise that costs one evolution instead of a shot budget. Ignored when the value carries real statistical error already.default_precision (
float) – Precision for pubs that do not carry their own.seed (
int|None) – Seeds theemulate_shot_noisegenerator. The simulator’s own seed belongs to theruncallable.assume_stochastic (
bool) – Treat every circuit as stochastic even when its instructions look deterministic. Set this when the simulator adds noise the circuit does not show, such as a server-sidenoisemodelrun option.
- Raises:
ValueError – If
methodis unknown, a count is not positive, or bothtrajectoriesandshotsare set, which would ask for two methods at once.
- mimiq_qiskit.estimation.estimate_pub(pub, config, run)[source]¶
Estimate every observable in
puband package the result.- Parameters:
pub (
EstimatorPub) – The pub to estimate. Its observables and parameter bindings broadcast against each other under Qiskit’s rules, and the result arrays take the broadcast shape.config (
EstimatorConfig) – Which method to use and what to spend on it.run (
Callable[[list,int],Sequence]) –run(circuits, nsamples) -> list[QCSResults], submitting a list of MIMIQ circuits and returning one result per circuit in the same order. Everything backend-specific (the connection, the simulator options, the seed) lives behind this callable.
- Return type:
- Returns:
A
PubResultwhoseevsandstdstake the pub’s shape. Its metadata reportsmethod,exact,stochastic, the budget actually spent, thetarget_precision, andmin_fidelitywhere the backend reports one.- Raises:
ValueError – If the circuit is stochastic and no budget was given (see this module’s docstring), or if the backend returns a result the requested method cannot be read out of.
Pauli-observable helpers shared by the MIMIQ Qiskit estimators.
Qiskit hands an EstimatorV2 its observables as {pauli_label: coefficient}
mappings, with qubit 0 on the right of each label. Everything here takes
labels in that convention and reports qubit indices, so no caller has to
reverse a label by hand.
Two estimation strategies need these helpers:
The direct path evaluates each Pauli term on the simulator state. It needs the term’s support (
pauli_support()) to build oneExpectationValueoperation per term (push_pauli_terms()), and reads the z-register back withread_pauli_terms().The sampling path measures the state in rotated bases. It needs the terms collected into simultaneously measurable sets (
measurement_groups()), one measurement circuit per set (append_measurement()), per-term averages back out of the shots (pauli_expectations()), and a final weighted sum (combine_sampled_terms()).
average_trajectories() serves the direct path when the circuit is
stochastic and every trajectory returns its own value.
- class mimiq_qiskit.observables.MeasurementGroup(labels, basis)[source]¶
A set of Pauli terms that one measurement can serve.
The members commute qubit-wise: on every qubit that two of them both act on, they act with the same Pauli. So rotating each qubit in
basisinto the Z basis and measuring it yields, in one pass, the eigenvalue of every member.- labels¶
The Qiskit Pauli labels in the group, in a deterministic order.
- basis¶
{qubit: pauli}over every qubit any member acts on.
- mimiq_qiskit.observables.append_measurement(circuit, group)[source]¶
Copy
circuitand measuregroup’s basis on the end of it.Each qubit in the group’s basis is rotated into the Z basis (
Hfor anXfactor,SdgthenHfor aYone, nothing for aZ) and measured into a register added for the purpose. The rotations are the same ones Qiskit’sBackendEstimatorV2uses.- Parameters:
circuit (
QuantumCircuit) – The state-preparation circuit. Not modified.group (
MeasurementGroup) – The terms to measure together.
- Return type:
- Returns:
(measurement_circuit, clbits), whereclbitsholds the global classical-bit index of each measured qubit ingroup.qubitsorder. That is the orderpauli_expectations()expects its samples in.- Raises:
ValueError – If
circuitalready has a register named_est, so adding ours would be ambiguous. Rename yours.
- mimiq_qiskit.observables.average_trajectories(values)[source]¶
Mean and standard error of one expectation value per trajectory.
The trajectory average is an unbiased estimator of the density-matrix expectation value: a branch sampled with probability \(\|K_k\psi\|^2\) and renormalised gives \(\mathbb{E}[\langle\psi_k|O|\psi_k\rangle] = \sum_k \langle\psi|K_k^\dagger O K_k|\psi\rangle = \mathrm{Tr}(\rho' O)\), and the same holds for measurement branches. So averaging is correct, and reading a single trajectory is one draw from a distribution whose spread can be as wide as the observable’s own range.
- Parameters:
- Return type:
- Returns:
(mean, standard_error). A single trajectory reports an error of zero, there being nothing to estimate a spread from; that zero means “unknown”, not “exact”, so check the run’s metadata before trusting it.- Raises:
ValueError – If
valuesis empty.
- mimiq_qiskit.observables.combine_sampled_terms(identity, terms, expectations, shots)[source]¶
Weight sampled term averages into one expectation value and its error.
- Parameters:
identity (
float) – The identity term’s coefficient, fromsplit_identity().terms (
Mapping[str,float]) –{label: coefficient}for the measured terms.expectations (
Mapping[str,tuple[float,float]]) –{label: (expectation, variance)}, frompauli_expectations().shots (
int) – Shots behind each term average.
- Return type:
- Returns:
(expectation_value, standard_error). The error follows Qiskit’sBackendEstimatorV2convention,Σ |cᵢ| √Var(Pᵢ) / √N, which adds the per-term errors as if the terms were perfectly correlated and so is an upper bound on the true standard error.
- mimiq_qiskit.observables.measurement_groups(labels)[source]¶
Collect Pauli labels into qubit-wise commuting measurement groups.
Grouping is what keeps the circuit count down: an observable with 50 terms over a shared basis costs one measurement circuit, not 50. The partition comes from Qiskit’s own
group_commuting(), so it matches whatBackendEstimatorV2would do with the same observable.- Parameters:
labels (
Iterable[str]) – Non-identity Qiskit Pauli labels, all of the same width.- Return type:
- Returns:
One
MeasurementGroupper basis, ordered deterministically. Empty whenlabelsis empty.- Raises:
ValueError – If a label is all-identity. Those carry no measurement; take them out with
split_identity()first.
- mimiq_qiskit.observables.pauli_expectations(group, samples)[source]¶
Average every term in
groupover one measurement’s shots.A term’s eigenvalue on a shot is
(-1) ** parityof the measured bits on its support, the rotations having already turned each factor into a Z.- Parameters:
group (
MeasurementGroup) – The group that was measured.samples (
Iterable[Sequence[int]]) – One sequence of bits per shot, each ordered likegroup.qubits.
- Return type:
- Returns:
{label: (expectation, variance)}. The variance is the single-shot1 - ⟨P⟩²; divide it by the shot count to get the squared standard error of the mean.- Raises:
ValueError – If
samplesis empty, since nothing can be averaged.
- mimiq_qiskit.observables.pauli_support(label)[source]¶
Return
(qubit, pauli)for each non-identity factor, qubit-ascending.Qiskit Pauli labels are little-endian: the leftmost character acts on the highest-index qubit, so character
kof ann-character label acts on qubitn - 1 - k.- Parameters:
label (
str) – A Qiskit Pauli label such as"IXZ". Characters must be one ofI,X,Y,Z.- Return type:
- Returns:
The non-identity factors as
(qubit index, pauli character)pairs, sorted by qubit index. Empty for an all-identity label.
Example:
>>> pauli_support("IXZ") [(0, 'Z'), (1, 'X')]
- mimiq_qiskit.observables.push_pauli_terms(circuit, labels, *, firstzvar=0)[source]¶
Push one
ExpectationValueoperation per Pauli label onto a circuit.Each term is evaluated on the state itself rather than sampled, so it is exact at any weight, and only the term’s own qubits are named: a weight-2 term on a 500-qubit register stays a two-qubit operation.
Labels are pushed once each, so several observables sharing a term at the same parameter binding can share its z-variable and its evaluation.
- Parameters:
- Return type:
- Returns:
{label: zvar}, the z-variable each term’s value will land in. Pass it toread_pauli_terms()along with the z-register that comes back.
- mimiq_qiskit.observables.read_pauli_terms(zstate, zvar_of, identity, terms)[source]¶
Combine one z-register into an observable’s expectation value.
- Parameters:
zstate (
Sequence[complex]) – One trajectory’s z-register, as returned inQCSResults.zstates.zvar_of (
Mapping[str,int]) –{label: zvar}, frompush_pauli_terms().identity (
float) – The identity term’s coefficient, fromsplit_identity().terms (
Mapping[str,float]) –{label: coefficient}for this observable’s measured terms. Every label must appear inzvar_of.
- Return type:
- Returns:
identity + Σ cᵢ Re⟨Pᵢ⟩. Each⟨Pᵢ⟩is real for a Pauli string on a normalised state, so taking the real part discards only round-off.
- mimiq_qiskit.observables.shots_for_precision(precision)[source]¶
Shots needed for a target precision,
ceil(1 / precision²).Qiskit’s convention, so a pub’s
precisionsizes a MIMIQ run the same way it would size a hardware one.- Parameters:
precision (
float) – Target standard error. Must be positive.- Return type:
- Returns:
The shot count, at least 1.
- Raises:
ValueError – If
precisionis not positive.
- mimiq_qiskit.observables.split_identity(observable)[source]¶
Separate an observable’s identity term from its measurable ones.
The identity term contributes its coefficient to the expectation value outright, with no evolution and no error, so it is kept apart from the terms that have to be evaluated.
- Parameters:
observable (
Mapping[str,complex]) –{pauli_label: coefficient}, as produced bycoerce().- Return type:
- Returns:
(identity_coefficient, terms)wheretermsmaps each non-identity label to its real coefficient. Repeated labels are summed.- Raises:
ValueError – If a coefficient has an imaginary part too large to be round-off.
EstimatorV2observables must be Hermitian, which in the Pauli basis means real coefficients, and silently discarding an imaginary part would hide the mistake.