> ## Documentation Index
> Fetch the complete documentation index at: https://docs.haiqu.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Mitigation

> Mitigating the effects of the noise in your workloads

## 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.

<Steps>
  <Step title="Prepare your circuit">
    Define your circuit and add measurements so the backend returns a shot distribution.

    ```python theme={null}
    circuit = QuantumCircuit(2)
    circuit.h(0)
    circuit.cx(0, 1)
    circuit.measure_all()
    ```
  </Step>

  <Step title="Specify execution details">
    Set your target device, credentials, and number of shots.

    ```python theme={null}
    device = haiqu.get_device("ibm_torino")
    options = {
        "ibm_quantum_token": "<YOUR_TOKEN>",
        "ibm_quantum_instance": "<INSTANCE_CRN>",
    }
    shots = 1000
    ```

    <Tip>
      Instead of adding credentials to `options` every time, consider saving them using `save_aws_credentials()` or `save_ibm_credentials()`.
    </Tip>
  </Step>

  <Step title="Run with error mitigation">
    Pass `use_mitigation=True` to `haiqu.run`. The SDK applies the distribution-mode mitigation pipeline automatically.

    ```python theme={null}
    job = haiqu.run(
        circuits=circuit,
        device=device,
        options=options,
        shots=shots,
        use_mitigation=True,
    )

    job.progress()
    print(job.result())
    ```
  </Step>
</Steps>

***

## 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.

<Steps>
  <Step title="Prepare your circuit and observable">
    Define your circuit **without** terminal measurements, and specify the Pauli observable to evaluate.

    ```python theme={null}
    circuit = QuantumCircuit(2)
    circuit.h(0)
    circuit.cx(0, 1)

    observables = [SparsePauliOp.from_list([("XY", 0.75), ("XX", -0.25)])]
    ```
  </Step>

  <Step title="Specify execution details">
    Set your target device, credentials, and number of shots.

    ```python theme={null}
    device = haiqu.get_device("ibm_torino")
    options = {
        "ibm_quantum_token": "<YOUR_TOKEN>",
        "ibm_quantum_instance": "<INSTANCE_CRN>",
    }
    shots = 1000
    ```

    <Tip>
      Instead of adding credentials to `options` every time, consider saving them using `save_aws_credentials()` or `save_ibm_credentials()`.
    </Tip>
  </Step>

  <Step title="Run with error mitigation">
    Pass both `observables` and `use_mitigation=True`. The SDK detects the observable and selects the appropriate mitigation pipeline automatically.

    ```python theme={null}
    job = haiqu.run(
        circuits=circuit,
        observables=observables,
        device=device,
        options=options,
        shots=shots,
        use_mitigation=True,
    )

    job.progress()
    print(job.result())
    ```
  </Step>
</Steps>

***

## 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.

| Option                   | Default | Description                                                                                                                |
| :----------------------- | :------ | :------------------------------------------------------------------------------------------------------------------------- |
| `"dynamical_decoupling"` | `True`  | Insert DD pulse sequences to suppress idle-qubit decoherence during execution                                              |
| `"readout_mitigation"`   | `True`  | Correct bitflip errors introduced during qubit measurement                                                                 |
| `"noise_tailoring"`      | `False` | Apply Pauli twirling to convert coherent noise into stochastic noise, improving the effectiveness of downstream mitigation |
| `"advanced_mitigation"`  | `True`  | Enable the full advanced mitigation pipeline                                                                               |

Example — enabling noise tailoring while keeping all other defaults:

```python theme={null}
options = {
    "ibm_quantum_token": "<YOUR_TOKEN>",
    "ibm_quantum_instance": "<INSTANCE_CRN>",
    "error_mitigation_options": {
        "noise_tailoring": True,
    },
}
```

<Tip>
  `"error_mitigation_options"` only takes effect when `use_mitigation=True`. Flags not included in the dictionary retain their defaults.
</Tip>

***

## Error Mitigation Details

|                                     | **Observable**                                                                                   | **Distribution**                                  |
| :---------------------------------- | :----------------------------------------------------------------------------------------------- | :------------------------------------------------ |
| **Supported backends**              | IBM QPUs, AWS Braket (TBD)                                                                       | IBM QPUs, AWS Braket (TBD)                        |
| **Circuit format**                  | Qiskit QuantumCircuit                                                                            | Qiskit QuantumCircuit                             |
| **Max. qubit number**               | up to 156 qubits (largest QPU)                                                                   | up to 156 (diminished efficiency with sampling)   |
| **Max. circuit depth / gate count** | up to 1000 2q gates for up to weight-5 observables, up to 300 2q gates for non-local observables |                                                   |
| **Circuit overhead**                | 2x circuit overhead per unique circuit                                                           | 2x the number of unique circuits (noise learning) |
| **Shot overhead**                   | 2x shot overhead per unique circuit                                                              | 2x the number of unique circuits (noise learning) |
| **Execution speed**                 | O(1) seconds for QEM + execution time on QPU                                                     | O(1) seconds for QEM + execution time on QPU      |
