Skip to main content

How to execute your circuits with error mitigation

In Haiqu SDK, applying error mitigation to your workloads is extremely easy: you just have to toggle the corresponding flag use_mitigation=True in the haiqu.run function. Haiqu applies different mitigation strategies depending on your workload type. Specify your circuits with measurements to get a mitigated distribution (bitstring counts), or supply an observable to get a mitigated expectation value. Both modes share the same flag — the SDK detects the right strategy automatically.

Distribution Mitigation

When your circuit includes measurements and you are sampling bitstrings, Haiqu performs noise learning alongside your circuit execution and uses it to correct the returned shot distribution.
1

Prepare your circuit

Define your circuit and add measurements so the backend returns a shot distribution.
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
2

Specify execution details

Set your target device, credentials, and number of shots.
device = haiqu.get_device("ibm_torino")
options = {
    "ibm_quantum_token": "<YOUR_TOKEN>",
    "ibm_quantum_instance": "<INSTANCE_CRN>",
}
shots = 1000
Instead of adding credentials to options every time, consider saving them using save_aws_credentials() or save_ibm_credentials().
3

Run with error mitigation

Pass use_mitigation=True to haiqu.run. The SDK applies the distribution-mode mitigation pipeline automatically.
job = haiqu.run(
    circuits=circuit,
    device=device,
    options=options,
    shots=shots,
    use_mitigation=True,
)

job.progress()
print(job.result())

Observable Mitigation

When your circuit targets an expectation value — for example in VQE, QAOA, or Hamiltonian ground-state estimation — supply a Pauli observable instead of terminal measurements. Haiqu applies a dedicated mitigation pipeline suited to expectation values. This mode incurs 2× circuit and shot overhead per unique circuit to perform the necessary noise characterization at the observable level.
1

Prepare your circuit and observable

Define your circuit without terminal measurements, and specify the Pauli observable to evaluate.
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)

observables = [SparsePauliOp.from_list([("XY", 0.75), ("XX", -0.25)])]
2

Specify execution details

Set your target device, credentials, and number of shots.
device = haiqu.get_device("ibm_torino")
options = {
    "ibm_quantum_token": "<YOUR_TOKEN>",
    "ibm_quantum_instance": "<INSTANCE_CRN>",
}
shots = 1000
Instead of adding credentials to options every time, consider saving them using save_aws_credentials() or save_ibm_credentials().
3

Run with error mitigation

Pass both observables and use_mitigation=True. The SDK detects the observable and selects the appropriate mitigation pipeline automatically.
job = haiqu.run(
    circuits=circuit,
    observables=observables,
    device=device,
    options=options,
    shots=shots,
    use_mitigation=True,
)

job.progress()
print(job.result())

Fine-Tuning with Error Mitigation Options

Both distribution and observable modes support per-component control through the optional "error_mitigation_options" key inside options. Each flag is a boolean and has a sensible default — you only need to include the flags you want to override.
OptionDefaultDescription
"dynamical_decoupling"TrueInsert DD pulse sequences to suppress idle-qubit decoherence during execution
"readout_mitigation"TrueCorrect bitflip errors introduced during qubit measurement
"noise_tailoring"FalseApply Pauli twirling to convert coherent noise into stochastic noise, improving the effectiveness of downstream mitigation
"advanced_mitigation"TrueEnable the full advanced mitigation pipeline
Example — enabling noise tailoring while keeping all other defaults:
options = {
    "ibm_quantum_token": "<YOUR_TOKEN>",
    "ibm_quantum_instance": "<INSTANCE_CRN>",
    "error_mitigation_options": {
        "noise_tailoring": True,
    },
}
"error_mitigation_options" only takes effect when use_mitigation=True. Flags not included in the dictionary retain their defaults.

Error Mitigation Details

ObservableDistribution
Supported backendsIBM QPUs, AWS Braket (TBD)IBM QPUs, AWS Braket (TBD)
Circuit formatQiskit QuantumCircuitQiskit QuantumCircuit
Max. qubit numberup to 156 qubits (largest QPU)up to 156 (diminished efficiency with sampling)
Max. circuit depth / gate countup to 1000 2q gates for up to weight-5 observables, up to 300 2q gates for non-local observables
Circuit overhead2x circuit overhead per unique circuit2x the number of unique circuits (noise learning)
Shot overhead2x shot overhead per unique circuit2x the number of unique circuits (noise learning)
Execution speedO(1) seconds for QEM + execution time on QPUO(1) seconds for QEM + execution time on QPU