qarp.engines¶
Execution engines. Public depth: flat. Submodules are private.
- class qarp.engines.CudaqEngine(*, backend: str = 'statevector', precision: str = 'fp64', max_bond_dim: int = 0, target: str | None = None, n_shots: int | Shots = 10000, seed: int | None = None)[source]¶
Bases:
EnginePure-Python engine wrapping the C++ Transpiler +
qx.CudaqSimulator.provides_amplitudes = True(base default) — noiseless simulator; the device→host statevector transfer is separately capped by_check_statevector_host.Gradients:
"default"resolves to the batched parameter shift, which stays on-device for StateVector expectation values over a QubitOperator (batch_expectation); other targets pull the host statevector per point."adjoint"is refused — the adjoint is a CPU kernel and this engine never constructs a CPU simulator behind the caller’s back (a GPU adjoint is post-release work); use QarpEngine for it.- Parameters:
backend – One of
statevector(single GPU, default),statevector-mgpu(multi-GPU + MPI),tensornet,tensornet-mps.precision –
fp64(default) orfp32.max_bond_dim – Bond-dimension cap for
tensornet-mps(ignored otherwise).target – Optional NVQIR backend name passed verbatim to the simulator (
CUDAQ_DEFAULT_SIMULATOR), overridingbackend/precision. Use"qpp"to run on CPU (e.g. for tests/CI without a GPU) or to reach a backend not covered by thebackendenum.n_shots – Default shot count used when a primitive has
n_shots=None;qarp.EXACTmakes exact readout the engine-wide default.seed – Optional RNG seed (passed to the simulator). EXACT readouts involve no RNG and are seed-independent.
- class qarp.engines.Engine[source]¶
Bases:
ABCCommon surface implemented by all concrete engines.
Concrete engines own a transpiler + simulator, plan or compile each primitive’s circuits once on
build(), then dispatch one or many parameter sets throughrun()/batch_run()keeping the per-shot loop in C++ (no Python round-trip per shot).- batch_run(primitives: list[Runnable], param_sets: Sequence[Mapping], n_shots: int | Shots | None = None, rebuild: bool = True) list[list[float | complex | SamplingDistribution]][source]¶
Sweep one set of primitives over multiple parameter dicts.
Template:
_batch_setupthen the engine’s_sweep.- Parameters:
primitives – Primitive instances to evaluate.
param_sets – One dict per evaluation point.
n_shots – Override engine-default shot count for this sweep.
rebuild – If False, reuse a primitive’s circuits when a prior
build()compiled them under this engine’s settings.
- Returns:
results_by_set[set_idx][prim_idx] = scalar.
- build(primitives: Sequence[Runnable], params: Mapping = {}, rebuild: bool = True) None[source]¶
Compile all primitives (template method).
Per primitive:
prim.build()(derives its circuits, builds nothing) →_validate_primitive→ per circuit:_plan_unbuilt, else build → flatten → substitute →_validate_flat_commands→_warn_uninitialised_conditions→_compile_one→_post_compile_check→_plan_built, into oneCompiledCircuiteach onprim.compiled.rebuild=Falsereuses a primitive’s circuits when all were compiled under this engine’s_compile_stamp(), re-validating it — capability-relevant state may have changed — and compiles it afresh otherwise.
- kernels(primitive: Runnable) list[list[str]][source]¶
The kernels
run()andbatch_run()execute for each circuit ofprimitive, asBlock.kernels()lists them for one block: one list per circuit, in order,["gates"]where its gate stream runs (§14 Structured execution).primitivemust be compiled under this engine’s settings; one with no circuits has no kernels.
- resolve_gradient_method(prim: Runnable, method: str) str[source]¶
The concrete method
run_gradient(method=...)would use forprim.
- resource_modeler() ResourceModeler | None[source]¶
Modeler for
qarp.resources.ResourceEstimator, or None.Engines pricing gates beyond raw counting (e.g. a digital-Rz T-cost) override this. No in-tree engine does: the base
Noneis the only return, and the hook is the seam a modeling engine re-attaches to.
- run(params: Mapping = {}) list[float | complex | SamplingDistribution][source]¶
Simulate all built primitives and return their scalar results.
Template method: re-validates every primitive per call (noise toggles and
initial_statemutations must not slip through), substitutes parameters, and defers the engine-specific simulation to_dispatch_one.
- run_gradient(params: Mapping, method: str = 'default', options: Mapping | None = None) list[ndarray][source]¶
Per-primitive gradients — one array per built primitive.
Contract (
docs/contracts/qarp_conventions.md§17):result[i]has shape(len(params),)with columns in the insertion order ofparams— for every method.dtype is
float64, orcomplex128when the primitive’s value is complex by target (TRANSITION_AMPLITUDE, an expectation value over aqx.Blockoperator, a complex HadamardTest).The differentiated objective per target: EXPECTATION_VALUE and TRANSITION_AMPLITUDE — the value
run()returns (Re and Im separately); aStateVectorOVERLAP —|⟨bra|ket⟩|²althoughrun()returns the amplitude (gradient_kind == "squared_overlap"); every other primitive — the valuerun()returns.
method:"default"(this engine’s policy — adjoint where eligible on QarpEngine, parameter shift otherwise; may change between releases),"adjoint","parameter-shift","finite-diff"(options:fd_eps,fd_order1|2),"spsa"(options:spsa_c0,num_spsa,spsa_seed). An unknown name is aValueError; a method this engine does not declare ingradient_methodsis aCapabilityError.
- class qarp.engines.QarpEngine(device: Device | None = None, *, n_qubits: int | None = None, architecture: Architecture | None = None, noise_model=None, gate_set: GateSet | None = None, directedness: bool = False, n_shots: int | Shots = 10000, seed: int | None = None, structured: bool | None = None, optimization_level: int | None = None)[source]¶
Bases:
EnginePure Python engine wrapping C++ Transpiler + QarpSimulator.
- Pipeline:
- build(primitives) — reads each primitive’s circuits; a declared
composition is planned unbuilt, otherwise the circuit is built, flattened, run through the device-aware compilation pipeline (qx.compile_for_device: check_fits → rebase → route → re-rebase, whichever stages the device configures) and then planned from its flat stream.
- run(params) — dispatches per primitive on
consumes: AMPLITUDES →
primitive.run_from_amplitudes; COUNTS → csim sampling (anExactResultundern_shots=qarp.EXACT), reindexed back to logical-qubit order when the device routed, thenprimitive.run(results).- batch_run(…) — sweeps one set of primitives over multiple
parameter dicts, each evaluated as
runevaluates it.
- Parameters:
device – A pre-built
qx.Device. Mutually exclusive with field-style kwargs.n_qubits/architecture/noise_model/gate_set/directedness – Field shorthand — assembles an effective Device internally (provided in lieu of device=…).
n_shots – Default shot count used when a primitive has n_shots=None.
qarp.EXACTmakes exact readout the engine-wide default.seed – Optional RNG seed (passed to QarpSimulator). EXACT readouts involve no RNG and are seed-independent / bit-reproducible.
structured – Run sampling primitives’ block structure as typed kernels where cheaper than their gates (§14 Structured execution);
NonefollowsQARP_STRUCTURED(default on). Engines with adevicealways run the gate path.
- gradient_methods: frozenset[str] = frozenset({'adjoint', 'default', 'finite-diff', 'parameter-shift', 'spsa'})¶
- property noise_model¶
The device’s noise model (C++
qx.NoiseModel), or None.qx.Devicecopies the model at construction, so toggling the object originally passed in has no effect afterwards — toggle this one instead:engine.noise_model.enabled = False(the disable-noise-for-gradients workflow).
- class qarp.engines.Runnable(*args, **kwargs)[source]¶
Bases:
ProtocolMembers engines actually touch on an executable item, grouped by what they describe: the quantity, the circuits, the estimator. A new member joins one group.
TargetandConsumesare importable: they live inqarp._types, below both layers, and engines compare them by identity.operatorstaysAny:QubitOperatorlives above this layer, so engines duck-type it — importing it here would recreate the engines⇄algorithms cycle this protocol removes.