Quick Start Guide for IQM Error Reduction Tools#
IQM Error Reduction Tools is a library providing techniques to avoid noise and mitigate errors in quantum computation. It operates by postprocessing measurement results after the execution to improve their accuracy. With this library, you can:
apply readout error mitigation (REM) to correct measurement errors
characterize readout noise and build calibration models
use Pauli twirling to tailor noise into more tractable forms
combine all steps into a unified workflow via the high-level
REMWorkflowAPI
This notebook walks through the minimal steps to get started. For a deeper dive into each technique, see tutorial_rem_workflow_highlevel.ipynb and the other tutorials in this docs folder.
Authentication#
IQM uses bearer token authentication to manage access to quantum computers. Get your personal token from the web dashboard and pass it when constructing the backend objects:
server_url = "https://<your-station-url>"
api_token = "<YOUR TOKEN HERE>"
Alternatively, set the IQM_TOKEN environment variable and omit the token argument.
import numpy as np
import matplotlib.pyplot as plt
from qiskit import QuantumCircuit, transpile
from qiskit.quantum_info import Statevector
from iqm.qiskit_iqm import IQMProvider
from iqm.pulla.pulla import Pulla
from iqm.error_reduction_tools.rem import REMWorkflow, WorkflowConfiguration
from iqm.error_reduction_tools.twirling.twirling_api import TwirlingConfiguration
from iqm.error_reduction_tools.utils.general_utils import total_variational_distance
provider = IQMProvider(url=server_url, token=api_token)
backend = provider.get_backend()
client = Pulla(server_url, token=api_token)
def generate_circuit(
num_qubits: int, scale: float = 2, seed: int = None
) -> tuple[QuantumCircuit, dict[str, float]]:
"""Generate a circuit with a single layer of random R gates."""
rgen = np.random.default_rng(seed)
rotations = (
np.pi
/ 2
* (1 + np.tanh(scale * (rgen.random(num_qubits) - 0.5) * 2) / np.tanh(scale))
)
qc = QuantumCircuit(num_qubits)
for q, theta in enumerate(rotations):
qc.r(theta, 0, q)
probs = Statevector.from_instruction(qc).probabilities()
ideal_counts = {
f"{i:0{num_qubits}b}": float(p)
for i, p in enumerate(probs)
if p > 1e-15
}
qc.measure_all()
return qc, ideal_counts
target_circuit, exact_counts = generate_circuit(num_qubits=4, seed=0)
transpiled_circ = transpile(
target_circuit, backend=backend, initial_layout=np.arange(1, 5)
)
transpiled_circ.draw("mpl", fold=0)
Run the REM Workflow#
The simplest usage is a single call to REMWorkflow.run(). It automatically:
Runs readout error characterization circuits on the QPU.
Twirls and executes your circuits.
Post-processes the counts to produce mitigated results.
For finer control (e.g. reusing a saved characterization, setting shot counts, or choosing a twirling strategy), see tutorial_rem_workflow_highlevel.ipynb.
# One-liner: characterization + twirled execution + mitigation in a single call
results = REMWorkflow(client).run([transpiled_circ])
print("Mitigated counts:")
print(dict(sorted(results.mitigated_counts[0].items(), key=lambda x: -x[1])[:10]))
# Compare mitigated results against raw (unmitigated) execution
raw_counts = backend.run(transpiled_circ, shots=10_000).result().get_counts()
tvd_raw = total_variational_distance(raw_counts, exact_counts)
tvd_mitigated = total_variational_distance(results.mitigated_counts[0], exact_counts)
labels = ["Raw (no REM)", "Twirled + REM"]
values = [tvd_raw, tvd_mitigated]
colors = ["tab:blue", "tab:green"]
plt.figure(figsize=(5, 4))
bars = plt.bar(labels, values, color=colors)
for bar, v in zip(bars, values):
plt.text(
bar.get_x() + bar.get_width() / 2,
bar.get_height(),
f"{v:.3f}",
ha="center",
va="bottom",
fontsize=10,
)
plt.ylabel("Total Variational Distance (TVD)")
plt.title("Lower TVD = closer to ideal")
plt.ylim(0, max(values) * 1.4)
plt.tight_layout()
plt.show()
Next Steps#
tutorial_rem_workflow_highlevel.ipynb— reusing characterization, observable estimation, workflow metadataAPI reference — full documentation of
REMWorkflow,WorkflowConfiguration, andTwirlingConfiguration