Haiqu.run(circuits, parameters=None, shots=1000, observables=None, readout_bases=None, device=None, device_id=None, options=None, use_mitigation=False, use_packing=False, pack_size=None, job_name=None, job_description=None, dry_run=False)
Run quantum circuits on the selected backend. This flexible method supports multiple execution scenarios, with different combinations of circuits, parameters, and observables. When multiple values are provided for any of them, the results are returned as nested lists with up to 3 layers, ordered by circuits, then observables, and finally parameters.NOTE
Everydevice_id — including "aer_simulator" — dispatches to the Haiqu cloud; there is no
local execution path, and login() must have succeeded first. Jobs submitted before
init() is called are logged under a shared default experiment; call
haiqu.init("my experiment") first so runs stay organized on the dashboard.
- Parameters:
- circuits (QuantumCircuit | list *[*QuantumCircuit ] | CircuitModel | list *[*CircuitModel ]) — The quantum circuit(s) to execute. Can be a single circuit or a list of circuits.
-
parameters (list | None) —
The parameters for the circuits. Can be a single set of parameters or nested lists of parameter sets. For
multiple circuits, must be a list where each element corresponds to parameters for that circuit. Defaults
to
None, in which case the circuits must not have any parameters. Each inner list must have lengthcircuit.num_parameters. Values are bound positionally in the order of Qiskit’sQuantumCircuit.parameters. When parameters are created one-by-one, that order is typically alphabetical by name (e.g.theta10beforetheta2), independent of gate addition order;ParameterVectorcircuits use vector index order instead (e.g.theta[0],theta[1]). Inspectlist(circuit.parameters)for the exact order. - shots (int) — The number of shots for each circuit execution. Defaults to 1000.
-
observables (SparsePauliOp | list *[*SparsePauliOp ] | list *[*list *[*SparsePauliOp ] ] | None) —
The observable(s) to measure. The order of Pauli terms in a single string follows the Qiskit
reversed-order convention (e.g.,
"IZ"measures qubit 0 in the Z basis). Defaults toNone, in which case the circuits must include their own measurements. Accepted shapes:- Single circuit: a single
SparsePauliOp, the nested form[[op1, op2, ...]], or a bare list[op1, op2, ...]. - Multiple circuits: a list of length
num_circuits, where each element is independently either a singleSparsePauliOp(one observable on that circuit) or a list ofSparsePauliOp(multiple observables on that circuit). Mixing is allowed —[[op1, op2], op3]for two circuits is valid.
- Single circuit: a single
-
readout_bases (list *[*str ] | None) —
Per-qubit Pauli bases to read the circuits out in, e.g.
["XXXX", "ZZZZ", "XZYZ"]. Each string follows the same Qiskit reversed-order convention asobservables(basis[-1]applies to qubit 0) and needs one character per qubit, drawn fromX,YandZ(useZfor a qubit that should not be rotated). The circuits keep their own measurements; this rotates the readout before them. One distribution is returned per basis per circuit, soresult()gains a basis axis in the same position observables occupy:[circuit][basis], or[circuit][basis][parameter]with a parameter sweep. UseRunJobModel.result_by_basis()to get them keyed by basis string. Mutually exclusive withobservables. Combines withuse_packing: each packed copy of the circuit is read out in the same basis, so a basis string still has one character per circuit qubit. Note that each basis is a separate execution, so the cost islen(readout_bases) * shots. Defaults toNone, which reads out in the computational basis as before. -
device (DeviceModel | None) — The device to run the circuits on. If specified,
device_idis ignored. Devices fromget_device()withuse_fractional_gates=Trueuse fractional gates. -
device_id (str | None) — The ID of the device to run the circuits on. Defaults to
None. -
options (dict | None) —
Options to pass to the device. Supports an optional
"error_mitigation_options"key with a dictionary of boolean flags to control individual error mitigation components whenuse_mitigation=True. Supported keys:"dynamical_decoupling"(bool): Toggle dynamical decoupling. Defaults toTrue."readout_mitigation"(bool): Toggle readout error mitigation. Defaults toTrue."noise_tailoring"(bool): Toggle noise tailoring via Pauli twirling. Defaults toFalse."advanced_mitigation"(bool): Toggle advanced mitigation. Defaults toTrue.
aer_simulator, pass{"method": "matrix_product_state"}. An optional"noise_model"key runs a noisy simulation. It is only supported whendevice_id="aer_simulator"ordevice_id="ionq_simulator", and the accepted value differs by backend:aer_simulator: adictor aqiskit_aer.noise.NoiseModelobject (serialized automatically before submission).ionq_simulator: astridentifier naming a characterized IonQ device (e.g."aria-1").
None(or omitting the key) runs a noiseless simulation. Simulator qubit limits (enforced server-side):- Statevector (
aer_simulatordefault): up to 24 qubits. - MPS (
aer_simulatorwithmethod="matrix_product_state", including with fake devices): no strict qubit limit. - Noisy simulation without MPS (fake devices such as
fake_kyiv, oraer_simulatorwith anoise_model): up to 12 qubits.
-
use_mitigation (bool) — Whether to use error mitigation techniques. Defaults to
False. -
use_packing (bool) — Whether to use circuit packing for efficient device utilization. Defaults to
False. Warning: Experimental — packing replicates circuits on unused device qubits to run multiple copies in parallel, which may increase errors for deeper input circuits. For example, a 4-qubit circuit with pack_size=2 and 1000 shots runs two copies in parallel with 500 shots each, yielding 1000 shots of results while only paying for 500 shot executions on the QPU — a 2x cost saving. -
pack_size (int | None) — Number of circuit copies to pack onto the device. Must be >= 2.
Only valid when
use_packing=True. IfNone(default), the backend will pack into at most 2/3 of the device qubits. -
job_name (str | None) — The name for the job. If
None(default), a name will be automatically generated. - job_description (str | None) — The description for the job.
-
dry_run (bool) — Whether to stop just prior to backend execution for QPU cost estimation. Defaults to
False. WhenTrue, the job result will be empty since execution on the device is skipped. The estimated QPU cost is then available viajob.estimated_qpu_cost.
- Returns:
The Run job that will execute the circuit.
: Call
job.result()to retrieve the execution results as a nested list ordered by circuits → observables → parameters:- Without observables: list of measurement distributions (
dict[str, float]), one per circuit, in Qiskit bit-order. - With observables, no parameter sweep: 2D list of expectation values, indexed
[circuit][observable]. - With observables and a parameter sweep: 3D list of expectation values, indexed
[circuit][observable][parameter].
Whendry_run=True,result()is empty; usejob.estimated_qpu_costinstead.job.infoexposes auxiliary metadata (uncertaintywhen observables are supplied,qpu_cost). Runhelp(job.result)for the full description of result andinfocontents. - Without observables: list of measurement distributions (
- Return type: RunJobModel