{
"cells": [
{
"cell_type": "markdown",
"id": "74154c03-d48f-4f41-867b-5e30254ce31a",
"metadata": {},
"source": [
"# Noise models on Amazon Braket\n",
"\n",
"\n",
"This notebook introduces noise models on Amazon Braket. We show how to create noise models containing different types of noise and instructions for how to apply the noise to a circuit.\n",
"In the next notebooks, we will show how to construct a noise model from device calibration data for real quantum processing units (QPUs). \n",
"\n",
"**Before you begin**: We recommend being familiar with noise channels in Braket. For an introduction see [Simulating Noise On Amazon Braket](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Simulating_Noise_On_Amazon_Braket.ipynb).\n",
"Additionally, users should be familiar with [Running quantum circuits on QPU devices](https://github.com/aws/amazon-braket-examples/blob/main/examples/getting_started/2_Running_quantum_circuits_on_QPU_devices/2_Running_quantum_circuits_on_QPU_devices.ipynb)\n",
"\n",
"### Table of Contents\n",
"- What is a noise model?\n",
"- Introduction to Noise Models\n",
" - Adding noise to a noise model\n",
" - Applying noise models to circuits\n",
" - Qubit noise\n",
" - Readout noise\n",
" - Filtering noise models\n",
" - Saving and loading noise models"
]
},
{
"cell_type": "markdown",
"id": "0c874b33-fa75-4d0f-80d4-46de40a14aa5",
"metadata": {},
"source": [
"## What is a noise model? \n",
"\n",
"Quantum devices and QPUs are subject noise on qubits and gate operations due to imperfect control.\n",
"The presence of noise deteriorates the quality of a quantum computation, especially when creating highly-entangled states. \n",
"Understanding the source and magnitude of this noise is essential to debugging and improving quantum computers. \n",
"\n",
"\n",
"The general noise on a quantum device is modelled as a noise channel (see [Simulating Noise On Amazon Braket](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Simulating_Noise_On_Amazon_Braket.ipynb)). The size of the full noise channel for a QPU scales exponentially with the number of qubits. Accordingly, it is essential to place assumptions on the noise channel to make it practical to simulate and debug circuits of interest.\n",
"\n",
"\n",
"A noise model encapsulates the assumptions on quantum noise channels and how they act on a given circuit. \n",
"Simulating this noisy circuit gives information about much the noise impacts the results of the quantum computation. \n",
"By incrementally adjusting the noise model, the impact of noise can be understood on a variety of quantum algorithms. \n",
"\n",
"Finding realistic and accurate noise models for quantum devices is a active field of research. \n",
"While simple models that treat each qubit or gate independently are useful, the effects of non-local crosstalk are often the most important when using multi-qubit devices. "
]
},
{
"cell_type": "markdown",
"id": "4d832c58-4505-4dc4-9ebc-239dd3c203da",
"metadata": {},
"source": [
"## Introduction to noise models\n",
"\n",
"Noise models are contained in the Amazon Braket SDK, within the circuits module. The following lines of code import the required features:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "e5e15fcd-55a2-4168-acc6-a38100f94511",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"from braket.aws import AwsDevice\n",
"from braket.circuits import Circuit, Gate, Noise, Observable\n",
"from braket.circuits.noise_model import (GateCriteria, NoiseModel,\n",
" ObservableCriteria)\n",
"from braket.circuits.noises import (AmplitudeDamping, BitFlip, Depolarizing,\n",
" PauliChannel, PhaseDamping, PhaseFlip,\n",
" TwoQubitDepolarizing)\n",
"from braket.devices import LocalSimulator"
]
},
{
"cell_type": "markdown",
"id": "f3489d3f-672a-42a2-a852-1a2f7a2631d2",
"metadata": {},
"source": [
"### Adding noise to a noise model\n",
"\n",
"A noise model consists of a list of noise model instructions. Similar to circuits, we can add `NoiseModelInstructions` to model. First, we start we an empty noise model:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "901c7adc-8924-451d-8120-4ec7cb2c8ba8",
"metadata": {},
"outputs": [],
"source": [
"noise_model = NoiseModel()"
]
},
{
"cell_type": "markdown",
"id": "3b0a0113-c368-4073-9d5e-65280c5c2379",
"metadata": {},
"source": [
"A `NoiseModelInstruction` consists of two pieces of information: (1) what noise channel to apply, and (2) when to apply it. Common noise channels are available in the Braket noise module (see [**Simulating Noise On Amazon Braket**](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Simulating_Noise_On_Amazon_Braket.ipynb)). The information about when to apply the noise is contained a `Criteria` object. Criteria can depend on qubits, gates, or measured observables.\n",
"\n",
"For example, consider applying depolarizing noise with probability $p=0.1$ noise after every Hadamard gate (`Gate.H`). \n",
"The depolarizing channel maps a state $\\rho$ to the maximal mixed state $I/d$ with probability $p$, i.e. $\\rho \\rightarrow (1-p)\\rho + \\frac{p}{3}\\left(X\\rho X + Y\\rho Y + Z\\rho Z\\right)$. In Braket, we denote this as `Depolarizing(0.1)`. \n",
"The condition to apply the noise only depends on the gate, so it is created with `GateCriteria(Gate.H)`.\n",
"The default behavior for gate criteria is to apply to all qubits, which is specified by setting `qubits=None`. \n",
"We can specify only a subset of qubits with `GateCriteria(gates=Gate.H, qubits=[0,1])` which will only apply noise to qubits 0 and 1. \n",
"Similarly, we can apply the same noise channel to a set of gates with `GateCriteria(gates=[Gate.H, Gate.S], qubits=[0])` which applies noise to both the Hadamard and phase gate on qubit 0. "
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "92a8f43c-94c9-4987-bef1-3f28d8c533c3",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Gate Noise:\n",
" Depolarizing(0.1), GateCriteria({'H'}, None)\n"
]
}
],
"source": [
"noise_model = NoiseModel()\n",
"noise_model.add_noise(Depolarizing(0.1), GateCriteria(Gate.H))\n",
"print(noise_model)"
]
},
{
"cell_type": "markdown",
"id": "4afee7ff-30fa-4101-870e-f4fac4beea1e",
"metadata": {},
"source": [
"Great! We added depolarizing noise on gate $H$ to the noise model.\n",
"\n",
"**Note**: Be careful adding noise to the model. If we repeat the `noise_model.add_noise()` twice with the same noise and criteria, we will get two entries in the noise model!\n",
"\n",
"Similar to a circuit with instructions, we can see the list of noise model instructions with:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "d04178e2-5074-4519-be0e-21819517ef76",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[NoiseModelInstruction(noise=Depolarizing(0.1), criteria=GateCriteria({'H'}, None))]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"noise_model.instructions"
]
},
{
"cell_type": "markdown",
"id": "00d55a98-320c-4eab-9011-c4186c611596",
"metadata": {},
"source": [
"Here, we only have one instruction which applies depolarizing noise after every $H$ gate."
]
},
{
"cell_type": "markdown",
"id": "134c59eb-617f-4230-8a6d-c1f8e715d6bb",
"metadata": {},
"source": [
"### Applying noise models to circuits\n",
"\n",
"Noise models encapsulate all the information about the noise we wish to apply to circuits. \n",
"This lets us apply noise channels across different circuits with minimal repetition.\n",
"\n",
"For example, consider the circuit:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "07513636-a747-4c67-935c-4640f38a7dc9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"T : |0|1|\n",
" \n",
"q0 : -H-Y-\n",
" \n",
"q1 : -S-X-\n",
" \n",
"q2 : -H-Z-\n",
"\n",
"T : |0|1|\n"
]
}
],
"source": [
"circ = Circuit().h(0).s(1).h(2).y(0).x(1).z(2)\n",
"print(circ)"
]
},
{
"cell_type": "markdown",
"id": "46f9c503-a8f3-4daa-be2c-907900af61aa",
"metadata": {},
"source": [
"We can apply the noise model to the circuit with `noise_model.apply(circ)` to produce the noisy circuit."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "d94f3908-6e96-4878-9566-6d04ba5feaab",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"T : | 0 |1|\n",
" \n",
"q0 : -H-DEPO(0.1)-Y-\n",
" \n",
"q1 : -S-----------X-\n",
" \n",
"q2 : -H-DEPO(0.1)-Z-\n",
"\n",
"T : | 0 |1|\n"
]
}
],
"source": [
"noisy_circ = noise_model.apply(circ)\n",
"print(noisy_circ)"
]
},
{
"cell_type": "markdown",
"id": "85424a62-4ec0-420b-ac2a-ba5e3ccfd81d",
"metadata": {},
"source": [
"Notice how depolarizing noise is applied after every Hadamard gate, just like it was specified in the noise model.\n",
"\n",
"We can also apply multiple noise models to a circuit. For example,"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "9def4229",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"T : | 0 |1|\n",
" \n",
"q0 : -H-BF(0.2)---DEPO(0.1)-Y-\n",
" \n",
"q1 : -S---------------------X-\n",
" \n",
"q2 : -H-DEPO(0.1)-----------Z-\n",
"\n",
"T : | 0 |1|\n"
]
}
],
"source": [
"noise_model_2 = NoiseModel().add_noise(BitFlip(0.2), criteria=GateCriteria(Gate.H, 0))\n",
"\n",
"noisy_circ_2 = noise_model_2.apply(noisy_circ)\n",
"\n",
"print(noisy_circ_2)"
]
},
{
"cell_type": "markdown",
"id": "beab4c73",
"metadata": {},
"source": [
"Notice that the most recently applied noise model inserts noise directly after the target gate(s)."
]
},
{
"cell_type": "markdown",
"id": "f1058f37-b3f5-48b6-b28f-fad69f1c988a",
"metadata": {},
"source": [
"### Modeling qubit decoherence by gate noise\n",
"\n",
"Let's add a few more types of noise to the model.\n",
"This time we will add amplitude dampening noise after every single-qubit gate, but only on qubit $0$.\n",
"This is intended to mimic the effect of the |1⟩ state decaying into the ground state |0⟩."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "f2325d73-b9dc-4014-b34f-5886dae4968f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Gate Noise:\n",
" Depolarizing(0.1), GateCriteria({'H'}, None)\n",
" AmplitudeDamping(0.1), GateCriteria(None, {0})\n"
]
}
],
"source": [
"noise_model.add_noise(AmplitudeDamping(0.1), GateCriteria(qubits=0))\n",
"print(noise_model)"
]
},
{
"cell_type": "markdown",
"id": "79acfb26-8e71-485b-8c9e-9ff2c1411696",
"metadata": {},
"source": [
"Let's also add a highly-specific type of noise.\n",
"Consider adding a Pauli channel noise after the `X` gate only on qubit `1`."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "65b88f6d-66e6-4000-8578-441fc213a70e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Gate Noise:\n",
" Depolarizing(0.1), GateCriteria({'H'}, None)\n",
" AmplitudeDamping(0.1), GateCriteria(None, {0})\n",
" PauliChannel(0.1, 0.2, 0.3), GateCriteria({'X'}, {1})\n"
]
}
],
"source": [
"noise_model.add_noise(PauliChannel(0.1, 0.2, 0.3), GateCriteria(gates=Gate.X, qubits=1))\n",
"print(noise_model)"
]
},
{
"cell_type": "markdown",
"id": "7e220eca-f370-45b3-8cd1-6fa0aa2a32d8",
"metadata": {},
"source": [
"Now we have a noise model containing three terms.\n",
"\n",
"- depolarizing(0.1) after every Hadamard gate\n",
"- amplitude dampening(0.1) after every gate on qubit 0.\n",
"- Pauli channel(0.1, 0.2, 0.3) after an $X$-gate on qubit 1.\n",
"\n",
"Let' apply it to previous circuit:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "40ff7893-f45d-45d7-a77e-c247c5932559",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"T : | 0 | 1 |\n",
" \n",
"q0 : -H-DEPO(0.1)-AD(0.1)-Y-AD(0.1)---------\n",
" \n",
"q1 : -S-------------------X-PC(0.1,0.2,0.3)-\n",
" \n",
"q2 : -H-DEPO(0.1)---------Z-----------------\n",
"\n",
"T : | 0 | 1 |\n"
]
}
],
"source": [
"print(noise_model.apply(circ))"
]
},
{
"cell_type": "markdown",
"id": "685f8ed8-fcac-4cc2-8e57-411dde73dbb9",
"metadata": {},
"source": [
"Take a minute to double check that this is correct.\n",
"\n",
"**Note**: If two or more criteria apply to the same gate and target qubits, then the order of the noise instructions in the noise model matters. In the above example, the Hadamard gate on qubit 0 has two types of noise applied after the gate. Since depolarizing noise appeared first in the noise model, it was applied first. The next criteria had amplitude dampening, so it was applied *after* the depolarizing noise. "
]
},
{
"cell_type": "markdown",
"id": "38445cb5-dec1-4980-a213-603697ae9bf3",
"metadata": {},
"source": [
"### Readout noise\n",
"\n",
"Similarly, we can also add readout noise to circuits. By default, circuits at the end of a Braket circuit are measured in the $Z$-basis.\n",
"\n",
"Let's add a bit flip readout noise with probability $0.01$ on qubits 0 and 1."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "aa01c6db-1fb3-4d4f-bae0-155a6b28e518",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Readout Noise:\n",
" BitFlip(0.01), ObservableCriteria(None, {1, 2})\n"
]
}
],
"source": [
"noise_model = NoiseModel()\n",
"noise_model.add_noise(BitFlip(0.01), ObservableCriteria(qubits=[1, 2]))\n",
"print(noise_model)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "833d5002-88ac-476b-9a60-614ae26c07b7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"T : |0|1|\n",
" \n",
"q0 : -H-Y-\n",
" \n",
"q1 : -S-X-\n",
" \n",
"q2 : -H-Z-\n",
"\n",
"T : |0|1|\n"
]
}
],
"source": [
"print(noise_model.apply(circ))"
]
},
{
"cell_type": "markdown",
"id": "d2b98157-ad3a-4b34-9831-85abc09f19e7",
"metadata": {},
"source": [
"### Observable Criteria\n",
"\n",
"Readout noise can also depend on the measurement basis. For single-qubit measurements, those would be measuring the in $X$, $Y$, or $Z$ basis. In Braket, measurements in other basis are defined with observables at the end of a circuit (see [Braket result types](https://docs.aws.amazon.com/braket/latest/developerguide/braket-result-types.html)).\n",
"\n",
"For example, lets' measure $X$ on qubit 0, and $Z$ on qubit 1."
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "a4fba08d-947c-4703-872c-f2600f0100af",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"T : |0|1|Result Types|\n",
" \n",
"q0 : -H-Y-Sample(X)----\n",
" \n",
"q1 : -S-X-Sample(Z)----\n",
" \n",
"q2 : -H-Z--------------\n",
"\n",
"T : |0|1|Result Types|\n"
]
}
],
"source": [
"circ.sample(Observable.X(), target=0)\n",
"circ.sample(Observable.Z(), target=1)\n",
"print(circ)"
]
},
{
"cell_type": "markdown",
"id": "b3f66148-38db-4a65-9545-ba30e366c30b",
"metadata": {},
"source": [
"Noise models can also contain instructions based on which observable is present.\n",
"\n",
"For example, let's add a phase flip error on qubit 0 when we measure in the $X$-basis. Let's also add a bit flip channel when measuring in the $Z$-basis."
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "d04ce147-f881-41f2-94b9-fa6ccfdfcdea",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Readout Noise:\n",
" PhaseFlip(0.02), ObservableCriteria({'X'}, {0})\n",
" BitFlip(0.01), ObservableCriteria({'Z'}, {1})\n"
]
}
],
"source": [
"noise_model = NoiseModel()\n",
"noise_model.add_noise(PhaseFlip(0.02), ObservableCriteria(Observable.X, 0))\n",
"noise_model.add_noise(BitFlip(0.01), ObservableCriteria(Observable.Z, 1))\n",
"print(noise_model)"
]
},
{
"cell_type": "markdown",
"id": "82153657-56b2-4c24-bdb7-dd2dd79a6b61",
"metadata": {},
"source": [
"Let's apply this noise model to a circuit.\n",
"The circuit is the same as above, but this time we measure `Observable.X` on qubit 0."
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "d0e9a783-558e-4e86-abe0-4dc095c4b25d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"T : |0| 1 |Result Types|\n",
" \n",
"q0 : -H-Y-PF(0.02)-Sample(X)----\n",
" \n",
"q1 : -S-X-BF(0.01)-Sample(Z)----\n",
" \n",
"q2 : -H-Z-----------------------\n",
"\n",
"T : |0| 1 |Result Types|\n"
]
}
],
"source": [
"noisy_circ = noise_model.apply(circ)\n",
"print(noisy_circ)"
]
},
{
"cell_type": "markdown",
"id": "dd08b5d3-f87d-4155-9721-cc9145b05035",
"metadata": {},
"source": [
"Take a minute to double check that all the terms in the noise model are applied in the correct place in the circuit."
]
},
{
"cell_type": "markdown",
"id": "ce8555fe-f8f1-49e6-ac9d-5f9a8a7a410e",
"metadata": {},
"source": [
"### Filtering noise models\n",
"\n",
"We can reduce the size of the noise model by selecting only noise and criteria relevant to our interest.\n",
"For instance, we might only care about noise affecting qubit 0.\n",
"\n",
"Let's start with a large noise model:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "bf87cb71-0a83-46c0-9d7e-13402dff3cf0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Gate Noise:\n",
" Depolarizing(0.1), GateCriteria({'H'}, None)\n",
" Depolarizing(0.1), GateCriteria(None, None)\n",
" AmplitudeDamping(0.1), GateCriteria(None, {0})\n",
" PauliChannel(0.1, 0.2, 0.3), GateCriteria({'X'}, {0})\n",
"Readout Noise:\n",
" PhaseFlip(0.02), ObservableCriteria({'X'}, {0})\n",
" BitFlip(0.01), ObservableCriteria({'Z'}, {1})\n"
]
}
],
"source": [
"noise_model = NoiseModel()\n",
"noise_model.add_noise(Depolarizing(0.1), GateCriteria(Gate.H))\n",
"noise_model.add_noise(Depolarizing(0.1), GateCriteria())\n",
"\n",
"noise_model.add_noise(AmplitudeDamping(0.1), GateCriteria(qubits=0))\n",
"noise_model.add_noise(PauliChannel(0.1, 0.2, 0.3), GateCriteria(Gate.X, qubits=0))\n",
"noise_model.add_noise(PhaseFlip(0.02), ObservableCriteria(Observable.X, 0))\n",
"noise_model.add_noise(BitFlip(0.01), ObservableCriteria(Observable.Z, 1))\n",
"print(noise_model)"
]
},
{
"cell_type": "markdown",
"id": "47619c82-60dc-4000-9886-865dc043213c",
"metadata": {},
"source": [
"Now we filter the noise model by `qubit=0` which returns a *new* noise model with only the noise affecting qubit 0. "
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "9b15f5fb-f1d7-4fb5-aadf-c6e85e2cb291",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Gate Noise:\n",
" Depolarizing(0.1), GateCriteria({'H'}, None)\n",
" Depolarizing(0.1), GateCriteria(None, None)\n",
" AmplitudeDamping(0.1), GateCriteria(None, {0})\n",
" PauliChannel(0.1, 0.2, 0.3), GateCriteria({'X'}, {0})\n",
"Readout Noise:\n",
" PhaseFlip(0.02), ObservableCriteria({'X'}, {0})\n"
]
}
],
"source": [
"reduced_noise_model = noise_model.from_filter(qubit=0)\n",
"print(reduced_noise_model)"
]
},
{
"cell_type": "markdown",
"id": "925c0e6d-598b-4428-a254-b1d26ed2f3e6",
"metadata": {},
"source": [
"Likewise, we can scope the noise model to only include noise that references a specific gate.\n",
"Below, we filter by gate = `Gate.H`. Notice that qubit criteria, which doesn't depend on gate, is also included."
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "11e6967a-37b7-499a-98c4-81c13535d484",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Gate Noise:\n",
" Depolarizing(0.1), GateCriteria({'H'}, None)\n",
" Depolarizing(0.1), GateCriteria(None, None)\n",
" AmplitudeDamping(0.1), GateCriteria(None, {0})\n"
]
}
],
"source": [
"reduced_noise_model = noise_model.from_filter(gate=Gate.H)\n",
"print(reduced_noise_model)"
]
},
{
"cell_type": "markdown",
"id": "f79279ba-634c-4f26-a698-1796a75912d6",
"metadata": {},
"source": [
"Similarly we can also filter by the type of noise, for instance to get only bit flip channels, we do:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "12a0ffb0-3217-45a3-84e7-562d8378b350",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Readout Noise:\n",
" BitFlip(0.01), ObservableCriteria({'Z'}, {1})\n"
]
}
],
"source": [
"reduced_noise_model = noise_model.from_filter(noise=BitFlip)\n",
"print(reduced_noise_model)"
]
},
{
"cell_type": "markdown",
"id": "c414a99d-1a7a-4761-839a-0a60d239d664",
"metadata": {},
"source": [
"We can also combine filters to get more specific reductions."
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "bfe264f4-12fb-4b16-bd6a-093c7b80a22a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Gate Noise:\n",
" Depolarizing(0.1), GateCriteria({'H'}, None)\n",
" Depolarizing(0.1), GateCriteria(None, None)\n"
]
}
],
"source": [
"reduced_noise_model = noise_model.from_filter(gate=Gate.H, qubit=1)\n",
"print(reduced_noise_model)"
]
},
{
"cell_type": "markdown",
"id": "1b9ed8de-e9aa-4ca1-b2c0-fda6892c4dbd",
"metadata": {},
"source": [
"If we don't filter by anything, the returned model will be the same as the original."
]
},
{
"cell_type": "markdown",
"id": "16e40060-d791-4b0d-88e1-c8912c3192f1",
"metadata": {},
"source": [
"### Saving and loading noise models\n",
"\n",
"Noise models can be converted to Python dictionaries. This makes it easy to save and load models."
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "25865b8e-68f2-4d55-a225-275ec0d16978",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'instructions': [{'noise': {'__class__': 'Depolarizing',\n",
" 'probability': 0.1,\n",
" 'qubit_count': 1,\n",
" 'ascii_symbols': ('DEPO(0.1)',)},\n",
" 'criteria': {'__class__': 'GateCriteria', 'gates': ['H'], 'qubits': None}},\n",
" {'noise': {'__class__': 'Depolarizing',\n",
" 'probability': 0.1,\n",
" 'qubit_count': 1,\n",
" 'ascii_symbols': ('DEPO(0.1)',)},\n",
" 'criteria': {'__class__': 'GateCriteria', 'gates': None, 'qubits': None}},\n",
" {'noise': {'__class__': 'AmplitudeDamping',\n",
" 'gamma': 0.1,\n",
" 'qubit_count': 1,\n",
" 'ascii_symbols': ('AD(0.1)',)},\n",
" 'criteria': {'__class__': 'GateCriteria', 'gates': None, 'qubits': [0]}},\n",
" {'noise': {'__class__': 'PauliChannel',\n",
" 'probX': 0.1,\n",
" 'probY': 0.2,\n",
" 'probZ': 0.3,\n",
" 'qubit_count': 1,\n",
" 'ascii_symbols': ('PC(0.1,0.2,0.3)',)},\n",
" 'criteria': {'__class__': 'GateCriteria', 'gates': ['X'], 'qubits': [0]}},\n",
" {'noise': {'__class__': 'PhaseFlip',\n",
" 'probability': 0.02,\n",
" 'qubit_count': 1,\n",
" 'ascii_symbols': ('PF(0.02)',)},\n",
" 'criteria': {'__class__': 'ObservableCriteria',\n",
" 'observables': ['X'],\n",
" 'qubits': [0]}},\n",
" {'noise': {'__class__': 'BitFlip',\n",
" 'probability': 0.01,\n",
" 'qubit_count': 1,\n",
" 'ascii_symbols': ('BF(0.01)',)},\n",
" 'criteria': {'__class__': 'ObservableCriteria',\n",
" 'observables': ['Z'],\n",
" 'qubits': [1]}}]}"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"noise_model.to_dict()"
]
},
{
"cell_type": "markdown",
"id": "57170712",
"metadata": {},
"source": [
"To save the Python dictionary as a json file in a local directory, we use the json package."
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "b9564451-7ab5-415b-8fa3-beb79b2aeb33",
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"\n",
"# save to local file\n",
"json.dump(noise_model.to_dict(), open(\"model_dict.json\", \"w\"))\n",
"\n",
"# Load from local file:\n",
"model_dict = json.load(open(\"model_dict.json\"))"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "340c6010-0e8e-45c0-8a08-5956860c7a48",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Gate Noise:\n",
" Depolarizing(0.1), GateCriteria({'H'}, None)\n",
" Depolarizing(0.1), GateCriteria(None, None)\n",
" AmplitudeDamping(0.1), GateCriteria(None, {0})\n",
" PauliChannel(0.1, 0.2, 0.3), GateCriteria({'X'}, {0})\n",
"Readout Noise:\n",
" PhaseFlip(0.02), ObservableCriteria({'X'}, {0})\n",
" BitFlip(0.01), ObservableCriteria({'Z'}, {1})\n"
]
}
],
"source": [
"print(NoiseModel().from_dict(model_dict))"
]
},
{
"cell_type": "markdown",
"id": "87aec0e3",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"In this section, we showed how to construct custom noise models in Braket containing qubit, gate, and readout noise. We showed how to apply noise models to circuits, construct smaller noise models by filtering, and how to save/load models."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.5"
},
"toc-autonumbering": false,
"toc-showcode": false,
"toc-showmarkdowntxt": false,
"toc-showtags": true
},
"nbformat": 4,
"nbformat_minor": 5
}