Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions docs/addons/qiskit-noise-learning/_toc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"parentUrl": "/docs/guides/addons",
"parentLabel": "Documentation",
"title": "Qiskit noise learning 0.1",
"collapsed": true,
"children": [
{
"title": "",
"children": [
{
"title": "Documentation home",
"url": "/docs/addons/qiskit-noise-learning"
},
{
"title": "Installation instructions",
"url": "/docs/addons/qiskit-noise-learning/install"
},
{
"title": "Guides",
"children": [
{
"title": "Mathematical formalism",
"url": "/docs/addons/qiskit-noise-learning/guides/formalism"
},
{
"title": "Build a learning experiment",
"url": "/docs/addons/qiskit-noise-learning/guides/workflow"
},
{
"title": "Learn the noise model of a gate with NoiseLearner",
"url": "/docs/addons/qiskit-noise-learning/guides/noise-learner"
}
]
},
{
"title": "GitHub",
"url": "https://github.com/Qiskit/qiskit-noise-learning"
}
],
"collapsible": false
},
{
"title": "API reference",
"collapsible": false,
"children": [
{
"title": "Python API reference",
"url": "/docs/api/qiskit-noise-learning"
}
]
}
]
}
180 changes: 180 additions & 0 deletions docs/addons/qiskit-noise-learning/guides/formalism.mdx

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions docs/addons/qiskit-noise-learning/guides/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: "Guides"
description: "Guides for the latest version of Qiskit noise learning"
---

# Guides

169 changes: 169 additions & 0 deletions docs/addons/qiskit-noise-learning/guides/noise-learner.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
---
title: "Learn the noise model of a gate with NoiseLearner"
description: "Learn the noise model of a gate with NoiseLearner for the latest version of Qiskit noise learning"
---

# Learn the noise model of a gate with NoiseLearner

This guide demonstrates using [`NoiseLearner`](/docs/api/qiskit-noise-learning/generated/noise-learner-noise-learner#qiskit_noise_learning.noise_learner.NoiseLearner "qiskit_noise_learning.noise_learner.NoiseLearner") to learn a noise model for a unitary gate.

1. Define the gate
2. Set up local simulation
3. Run the learner
4. Read the results

<Admonition title="Running on real hardware" type="note">
The circuits below are simulated locally, so this walkthrough needs no IBM Quantum® credentials. Two changes take it to a real device, each flagged again where it applies:

* **Step 1**: replace [`FakeMarrakesh`](/docs/api/qiskit-ibm-runtime/fake-provider-fake-marrakesh "(in Qiskit Runtime IBM Client)") with a real backend.
* **Step 2**: skip it, and drop the `executor` argument in step 3.
</Admonition>

<span id="define-the-gate" />

## 1. Define the gate

The gate whose noise we will learn is a [`BoxOp`](/docs/api/qiskit/qiskit.circuit.BoxOp) holding a layer of six disjoint `CZ` gates, with two Samplomatic annotations: `Twirl()` marks the box for Pauli twirling, and `InjectNoise("cz_gate")` names it. That name is the key under which the learned noise map is reported — and, because this guide simulates the gate, also the key under which noise is injected.

```python
from qiskit.circuit import QuantumCircuit
from qiskit_ibm_runtime.fake_provider import FakeMarrakesh
from samplomatic import InjectNoise, Twirl

backend = FakeMarrakesh()

cz_pairs = [(91, 92), (93, 94), (95, 99), (98, 111), (112, 113), (114, 115)]

circuit = QuantumCircuit(backend.num_qubits)
with circuit.box([Twirl(), InjectNoise("cz_gate")]):
for pair in cz_pairs:
circuit.cz(*pair)
```

<Admonition title="Running on real hardware" type="note">
```python
from qiskit_ibm_runtime import QiskitRuntimeService

backend = QiskitRuntimeService().backend("ibm_marrakesh")
```
</Admonition>

<span id="set-up-local-simulation" />

## 2. Set up local simulation

An [`AerExecutor`](/docs/api/qiskit-noise-learning/generated/aer-executor-aer-executor#qiskit_noise_learning.aer_executor.AerExecutor "qiskit_noise_learning.aer_executor.AerExecutor") runs a program on a local Aer simulator, injecting Pauli-Lindblad noise at the barriers Samplomatic places around each twirled gate.

The Pauli indices inside each map are local to the gate, in ascending physical-qubit order:

```python
cz_qubits = sorted({qubit for pair in cz_pairs for qubit in pair})
local = {qubit: index for index, qubit in enumerate(cz_qubits)}
local
```

```myst
{91: 0,
92: 1,
93: 2,
94: 3,
95: 4,
98: 5,
99: 6,
111: 7,
112: 8,
113: 9,
114: 10,
115: 11}
```

The gate gets a correlated `ZZ` term and a weaker `XX` term on each `CZ` pair, plus a single-qubit `Z` term everywhere; preparation and measurement each get a bit-flip term per qubit.

```python
from qiskit.quantum_info import PauliLindbladMap

num_qubits = len(cz_qubits)

cz_noise = PauliLindbladMap.from_sparse_list(
[("ZZ", [local[a], local[b]], 8e-4) for a, b in cz_pairs]
+ [("XX", [local[a], local[b]], 4e-4) for a, b in cz_pairs]
+ [("Z", [index], 3e-4) for index in range(num_qubits)],
num_qubits=num_qubits,
)

spam_noise = PauliLindbladMap.from_sparse_list(
[("X", [index], 5e-3) for index in range(num_qubits)], num_qubits=num_qubits
)

noise_dict = {"cz_gate": cz_noise, "P": spam_noise, "M": spam_noise}
```

Instantiate [`AerExecutor`](/docs/api/qiskit-noise-learning/generated/aer-executor-aer-executor#qiskit_noise_learning.aer_executor.AerExecutor "qiskit_noise_learning.aer_executor.AerExecutor") with the stabilizer method. Set `root_seed` to make the simulated data reproducible.

```python
from qiskit_aer import AerSimulator

from qiskit_noise_learning.aer_executor import AerExecutor

executor = AerExecutor(
AerSimulator(method="stabilizer"), noise_dict=noise_dict, root_seed=1234
)
```

<Admonition title="Running on real hardware" type="note">
Skip this step entirely.
</Admonition>

<span id="run-the-learner" />

## 3. Run the learner

[`LearningOptions`](/docs/api/qiskit-noise-learning/generated/noise-learner-learning-options#qiskit_noise_learning.noise_learner.LearningOptions "qiskit_noise_learning.noise_learner.LearningOptions") controls the shape of the experiment: how deep the twirled gate is repeated, and how many randomizations and shots are spent at each depth. Passing `executor` diverts the generated program to the simulator; leave it out and [`NoiseLearner`](/docs/api/qiskit-noise-learning/generated/noise-learner-noise-learner#qiskit_noise_learning.noise_learner.NoiseLearner "qiskit_noise_learning.noise_learner.NoiseLearner") submits to `backend` through IBM Quantum instead.

```python
from qiskit_noise_learning.noise_learner import LearningOptions, NoiseLearner

options = LearningOptions(
fragment_depths=[2, 16, 64, 128],
num_randomizations=50,
shots_per_randomizations=20,
)

learner = NoiseLearner(backend, options=options, executor=executor)

job = learner.run([circuit[0]])
result = job.result()
```

<Admonition title="Running on real hardware" type="note">
```python
learner = NoiseLearner(backend, options=options)
```
</Admonition>

<span id="read-the-results" />

## 4. Read the results

Everything the analysis pipeline produced is reachable through [`fit`](/docs/api/qiskit-noise-learning/generated/noise-learner-noise-learner-result#qiskit_noise_learning.noise_learner.NoiseLearnerResult.fit "qiskit_noise_learning.noise_learner.NoiseLearnerResult.fit"). Use the fit to plot per-qubit-pair fidelity decays: both the data and the exponential fit.

```python
result.fit.plot_qubit_pair_decays(
pairs=cz_pairs,
observable_type="means",
exponential_fit=True,
)
```

Extract the learned noise from [`to_dict()`](/docs/api/qiskit-noise-learning/generated/noise-learner-noise-learner-result#qiskit_noise_learning.noise_learner.NoiseLearnerResult.to_dict "qiskit_noise_learning.noise_learner.NoiseLearnerResult.to_dict"): one [`PauliLindbladMap`](/docs/api/qiskit/qiskit.quantum_info.PauliLindbladMap) per learned gate, keyed by the name from the `InjectNoise` annotation, and expressed in the backend’s own qubit indexing rather than that of the gate.

```python
learned = result.to_dict()["cz_gate"]
learned.num_terms
```

```myst
144
```

By default [`NoiseLearner`](/docs/api/qiskit-noise-learning/generated/noise-learner-noise-learner#qiskit_noise_learning.noise_learner.NoiseLearner "qiskit_noise_learning.noise_learner.NoiseLearner") fits a 2-local model, so the map carries a term for every Pauli supported on a connected pair of the gate’s qubits — 144 of them, of which only 24 were given a nonzero rate in step 2.
Loading
Loading