Tutorials
qcr:2607.23270.1

Noise Models from Rigetti Calibration Data on Amazon Braket

This intermediate tutorial shows how to build a realistic noise model for the Rigetti Cepheus-1-108Q superconducting device directly from its reported calibration data and validate it against real QPU results on Amazon Braket. It retrieves the device's one- and two-qubit calibration metrics through the Braket SDK, explaining each quantity: the T1 relaxation and T2 dephasing times, single-qubit randomized-benchmarking and simultaneous randomized-benchmarking fidelities, readout fidelity, and two-qubit gate fidelities per connected edge. From these it constructs a per-qubit noise model that adds amplitude-damping and phase-damping channels derived from T1 and T2, depolarizing noise from the simultaneous-RB fidelity, and readout bit-flip error from the readout fidelity, plus two-qubit depolarizing noise on each connected pair, inserting identity gates so that relaxation acts during idle moments. The notebook runs the same circuits on the noisy local density-matrix simulator and on the Cepheus-1-108Q QPU, computes bit-string fidelities, and confirms the noisy simulation tracks the hardware far better than a noise-free one. It then coarse-grains the model by averaging rates across qubits, trading accuracy for a much smaller parameter set. It matters because calibration-derived noise models let researchers anticipate hardware behavior before spending on QPU time.
Qubit
Circuit-based
Uploaded 4 weeks ago
9
Views
GitHub587
Citing this entry? Use this QCR ID
Uploaded by
QL
QCR Librarian

Overview

amazon-braket/amazon-braket-examples
587261
In [ ]:
# --- Setup cell added by QCR (not part of the original tutorial) ---
# Source: amazon-braket/amazon-braket-examples @ 0c0818f315479aab9deebed7e7ed7533ac581923, Apache License 2.0.
# Installs the example's dependencies. If a later cell still reports a missing
# package, restart the runtime/kernel and run again from the top.
%pip install -q amazon-braket-sdk==1.117.3 matplotlib pandas

Noise models on Rigetti

This notebook shows how to construct a noise model from device calibration data for Rigetti Cepheus-1-108Q. We compare the measurement outcomes of circuits run on a noisy simulator with the same circuits run on quantum processing units (QPUs), to show that simulating circuits with noise models more closely mimics QPUs.

Before you begin: We recommend being familiar with Noise models on Amazon Braket. Additionally, users should be familiar with Running quantum circuits on QPU devices.

Table of Contents

  • Noise model for Rigetti
    • Loading device calibration data
    • Comparing noisy simulator results to QPU results
    • Smaller noise models compared to QPU results
In [1]:
# Use Braket SDK Cost Tracking to estimate the cost to run this example
from braket.tracking import Tracker

t = Tracker().start()
In [2]:
import numpy as np
import pandas as pd

from braket.aws import AwsDevice
from braket.circuits import Circuit, Gate
from braket.circuits.noise_model import GateCriteria, NoiseModel, ObservableCriteria
from braket.circuits.noises import (
    BitFlip,
    Depolarizing,
    TwoQubitDepolarizing,
)
from braket.devices import Devices, LocalSimulator

Braket provides access to hardware providers' reported calibration data. This can be used to construct noise models to approximate the behavior of the QPU when running circuits on a noisy simulator. In this tutorial, we focus on local noise models with no crosstalk interactions. Real devices can have crosstalk and unexpected effects that can further degrade the results.

The Cepheus-1-108Q calibration data is available on the Braket devices page. Under qubit specs, the calibration data include the qubit index, with corresponding values for the , , fidelity from randomized benchmarking (fRB), fidelity from simultaneous randomized benchmarking (fsRB), and readout fidelity (fRO). Under "edge specs", the data includes the RB fidelity for two qubit gates for each connected edge in the device topology.

One-qubit calibration data (Qubit specs)

Two-qubit calibration data (Edge specs)

We can programmatically access all the calibration data with the Braket SDK. First we load the AwsDevice using the ARN for Rigetti Cepheus-1-108Q.

In [3]:
rigetti = AwsDevice(Devices.Rigetti.Cepheus1108Q)

The properties dictionary contains one- and two-qubit calibration data.

In [4]:
one_qubit_data = rigetti.properties.standardized.oneQubitProperties
two_qubit_data = rigetti.properties.standardized.twoQubitProperties

For Cepheus-1-108Q, we can get all qubit indices with one_qubit_data.keys() or with rigetti.topology_graph.nodes.

The keys of the two qubit dictionary are the connected qubit pairs separated by a hyphen. For example, if qubit 0 and 1 are connected the key is "0-1".

One-qubit noise

Let's look at the one qubit calibration data for qubit 0.

In [5]:
one_qubit_data["0"]
OneQubitProperties(T1=CoherenceTime(value=1.334841857469904e-05, standardError=None, unit='S'), T2=CoherenceTime(value=1.1487766417239698e-05, standardError=None, unit='S'), oneQubitFidelity=[Fidelity1Q(fidelityType=FidelityType(name='RANDOMIZED_BENCHMARKING', description=None), fidelity=0.9964546331080112, standardError=0.00020783764046460049), Fidelity1Q(fidelityType=FidelityType(name='SIMULTANEOUS_RANDOMIZED_BENCHMARKING', description=None), fidelity=0.9964546331080112, standardError=0.00020783764046460049), Fidelity1Q(fidelityType=FidelityType(name='READOUT', description=None), fidelity=0.971, standardError=None)])

For each qubit, there are various metrics of the quality:

  • T1: Thermal relaxation time is related to the time it takes for the excited state, |1⟩, to decay into the ground state, |0⟩. The probability of remaining in the excited state is

  • T2: The dephasing time, is the decay constant for the scale for a |+⟩ state to decohere into the completely mixed state.

  • Fidelity (RB): Single-qubit randomized benchmarking fidelities. RB fidelity quantifies the average gate fidelity where the average is over all Clifford gates. RB describes an effective noise model with gate-independent depolarizing noise on each Clifford gate.

  • Fidelity (sRB): Single-qubit simultaneous randomized benchmarking fidelities. These are extracted by running single-qubit RB on all qubits simultaneously. Note that we expect the sRB fidelity to be lower than standard RB fidelity due to non-local crosstalk type noise on the device.

  • Readout fidelity: Single-qubit readout fidelities describes the probability of a bit flip error before readout in the computational basis. The readout fidelity is related to the probability of correctly measuring the ground state and excited states respectively, e.g.

Now that we know how to extract and use the calibration data, we can build a simple noise model. For every qubit we will add:

  • amplitude dampening noise with probability for every gate
  • phase dampening noise with probability for every gate
  • depolarizing noise with probability (from simultaneous RB fidelity) for every gate
  • readout bit flip noise with probability to measurements

Technically, the sRB fidelity already includes effects from /, however to be explicit we add these as separate terms. In a sense, this model might overestimate the noise on the QPU.

To create the noise model, we iterate over all qubits keys in one_qubit_data

In [6]:
noise_model = NoiseModel()

# Readout Noise Model
for q, data in rigetti.properties.standardized.oneQubitProperties.items():
    try:
        readout_error = 1 - data.oneQubitFidelity[2].fidelity  # readout
        noise_model.add_noise(BitFlip(readout_error), ObservableCriteria(qubits=int(q)))

        depolarizing_rate = (
            1 - data.oneQubitFidelity[1].fidelity
        )  # SIMULTANEOUS_RANDOMIZED_BENCHMARKING
        noise_model.add_noise(Depolarizing(probability=depolarizing_rate), GateCriteria(qubits=q))
    except:  # noqa: PERF203
        pass
In [7]:
num_params = sum(len(item.noise.parameters) for item in noise_model.instructions)
print(f"Number of terms in noise model is: {len(noise_model.instructions)}")
print(f"Number of parameters in noise model is: {num_params}")
Number of terms in noise model is: 120
Number of parameters in noise model is: 120

Two-qubit noise

Next we consider adding two-qubit noise to the model.

Let's first look at the data provided in the Cepheus-1-108Q device calibration data. On the first connect, "0-1", the properties are:

In [8]:
two_qubit_data["0-1"]
TwoQubitProperties(twoQubitGateFidelity=[GateFidelity2Q(direction=None, gateName='CZ', fidelity=0.9943965178886834, standardError=0.001071379877124974, fidelityType=FidelityType(name='INTERLEAVED_RANDOMIZED_BENCHMARKING', description=None))])

Here, we see the fidelity per gate (CZ) and the associated standard error.

Next we loop over the entries in the two_qubit_data dictionary and add two-qubit depolarizing noise to the model. Notice that Cepheus-1-108Q has symmetric connections ("0-1" and "1-0") so we need to add noise in both directions.

In [9]:
# Two-qubit noise
for pair, data in two_qubit_data.items():  # iterate over qubit connections
    # parse strings "0-1" to integers [0, 1]
    q0, q1 = (int(s) for s in pair.split("-"))
    try:
        if data.twoQubitGateFidelity[0].gateName == "CZ":
            phase_rate = 1 - data.twoQubitGateFidelity[0].fidelity
            noise_model.add_noise(
                TwoQubitDepolarizing(phase_rate),
                GateCriteria(Gate.CZ, [(q0, q1), (q1, q0)]),  # symmetric connections
            )
    except:
        pass
In [10]:
num_params = sum(len(item.noise.parameters) for item in noise_model.instructions)
print(f"Number of terms in noise model is: {len(noise_model.instructions)}")
print(f"Number of parameters in noise model is: {num_params}")
Number of terms in noise model is: 313
Number of parameters in noise model is: 313

Compare circuits run on device vs simulator with a noise model

Let's just look at the first 5 qubits. Note that to ensure the noise model applied T1 and T2 noise during the time between gate, we manually add identity gates to each moment.

In [11]:
np.random.seed(42)

circ = Circuit().rx(0, 0.5).rz(1, 0.5).rz(2, 0.5).rx(0, np.pi).rx(1, np.pi).rx(2, np.pi).cz(0, 1)
print(circ)
T  : │     0      │     1      │  2  │
      ┌──────────┐ ┌──────────┐       
q0 : ─┤ Rx(0.50) ├─┤ Rx(3.14) ├───●───
      └──────────┘ └──────────┘   │   
      ┌──────────┐ ┌──────────┐ ┌─┴─┐ 
q1 : ─┤ Rz(0.50) ├─┤ Rx(3.14) ├─┤ Z ├─
      └──────────┘ └──────────┘ └───┘ 
      ┌──────────┐ ┌──────────┐       
q2 : ─┤ Rz(0.50) ├─┤ Rx(3.14) ├───────
      └──────────┘ └──────────┘       
T  : │     0      │     1      │  2  │
In [12]:
noisy_circ = noise_model.apply(circ)

print(noisy_circ)
T  : │     0      │     1      │          2           │
      ┌──────────┐ ┌──────────┐       ┌──────────────┐ 
q0 : ─┤ Rx(0.50) ├─┤ Rx(3.14) ├───●───┤ DEPO(0.0056) ├─
      └──────────┘ └──────────┘   │   └──────┬───────┘ 
      ┌──────────┐ ┌──────────┐ ┌─┴─┐ ┌──────┴───────┐ 
q1 : ─┤ Rz(0.50) ├─┤ Rx(3.14) ├─┤ Z ├─┤ DEPO(0.0056) ├─
      └──────────┘ └──────────┘ └───┘ └──────────────┘ 
      ┌──────────┐ ┌──────────┐                        
q2 : ─┤ Rz(0.50) ├─┤ Rx(3.14) ├────────────────────────
      └──────────┘ └──────────┘                        
T  : │     0      │     1      │          2           │
In [13]:
simulator = LocalSimulator()  # noise free simulator
task = simulator.run(circ, shots=10_000)
free_probs = task.result().measurement_probabilities
In [14]:
noisy_simulator = LocalSimulator("braket_dm")
noisy_task = noisy_simulator.run(noisy_circ, shots=10_000)
noisy_probs = noisy_task.result().measurement_probabilities
Note: The below section runs tasks on the Rigetti Cepheus-1-108Q device. When you run this notebook, make sure the device is currently available. You can find QPU availability windows on the Devices page in the Amazon Braket Console.
Note: Running the circuit below will result in charges on your AWS account.
In [15]:
rigetti_task = rigetti.run(circ, shots=10_000, disable_qubit_rewiring=True)
rigetti_result = rigetti_task.result()
rigetti_probs = rigetti_result.measurement_probabilities
In [16]:
free_sim = pd.DataFrame.from_dict(free_probs, orient="index").rename(columns={0: "free_sim"})
noisy_sim = pd.DataFrame.from_dict(noisy_probs, orient="index").rename(columns={0: "noisy_sim"})
Cepheus = pd.DataFrame.from_dict(rigetti_probs, orient="index").rename(columns={0: "Cepheus-1-108Q"})
df = Cepheus.join(noisy_sim).join(free_sim)
df
Cepheus-1-108Q noisy_sim free_sim
110 0.1250 NaN NaN
111 0.7125 0.9326 0.9391
011 0.0792 0.0649 0.0609
010 0.0122 NaN NaN
100 0.0127 NaN NaN
101 0.0508 0.0009 NaN
001 0.0064 0.0016 NaN
000 0.0012 NaN NaN

We can compute the fidelity between the free simulation and Rigetti, as well as the noisy simulation and Rigetti.

In [17]:
def fidelity(p, q):
    return np.sum(np.sqrt(p * q))


f_free_Cepheus = fidelity(df["free_sim"], df["Cepheus-1-108Q"])
f_noisy_Cepheus = fidelity(df["noisy_sim"], df["Cepheus-1-108Q"])

print(f"\nTotal fidelity between Cepheus-1-108Q and noise-free simulator is {f_free_Cepheus}")
print(f"\nTotal fidelity between Cepheus-1-108Q and noisy simulator is {f_noisy_Cepheus}")
Total fidelity between Cepheus-1-108Q and noise-free simulator is 0.8874405164437654

Total fidelity between Cepheus-1-108Q and noisy simulator is 0.8968109011001625

To better visualize, we can also plot the output probability distributions from each circuit:

In [18]:
import matplotlib.pyplot as plt

%matplotlib inline

df.plot.bar(
    title="Comparing noise-free simulator, noisy simulator, and Cepheus-1-108Q",
    figsize=(12, 6),
)

text = f"f_free_Cepheus = {f_free_Cepheus:.3f} \nf_noise_model_Cepheus = {f_noisy_Cepheus:.3f}"
plt.text(1, 0.5, text, fontsize=14)
plt.show()

We confirm that the simulator with a noise model is closer to the distribution produced by Cepheus-1-108Q.

Smaller, reduced noise models

The full Rigetti Cepheus-1-108Q noise model contains due to non-uniform qubit noise. We can obtain simpler, smaller noise models by coarse graining the model above.

Here, we consider taking the average over all qubits for the , , depolarizing, and readout depolarizing rates. This is a substantially smaller noise model, but may be less accurate.

We use the from_filter function to extract all instructions with amplitude dampening noise in the model. We then compute the mean of the error probabilities.

In [19]:
avg_depo = np.mean(
    [n.noise.parameters for n in noise_model.from_filter(noise=Depolarizing).instructions],
)
avg_readout = np.mean(
    [n.noise.parameters for n in noise_model.from_filter(noise=BitFlip).instructions],
)

Now we construct a new noise model with the mean values above:

In [20]:
simple_noise_model = NoiseModel()
simple_noise_model.add_noise(Depolarizing(avg_depo), GateCriteria())
simple_noise_model.add_noise(BitFlip(avg_readout), ObservableCriteria())

print(simple_noise_model)
Gate Noise:
  Depolarizing(0.047140541447784685), GateCriteria(None, None)
Readout Noise:
  BitFlip(0.053861111111111123), ObservableCriteria(None, None)

We can see the resultant circuits contain qubit-independent noise:

In [21]:
simple_noisy_circ = simple_noise_model.apply(circ)
print(simple_noisy_circ)
T  : │             0              │             1              │  ╏
      ┌──────────┐ ┌─────────────┐ ┌──────────┐ ┌─────────────┐   ╏
q0 : ─┤ Rx(0.50) ├─┤ DEPO(0.047) ├─┤ Rx(3.14) ├─┤ DEPO(0.047) ├─  ╏
      └──────────┘ └─────────────┘ └──────────┘ └─────────────┘   ╏
      ┌──────────┐ ┌─────────────┐ ┌──────────┐ ┌─────────────┐   ╏
q1 : ─┤ Rz(0.50) ├─┤ DEPO(0.047) ├─┤ Rx(3.14) ├─┤ DEPO(0.047) ├─  ╏
      └──────────┘ └─────────────┘ └──────────┘ └─────────────┘   ╏
      ┌──────────┐ ┌─────────────┐ ┌──────────┐ ┌─────────────┐   ╏
q2 : ─┤ Rz(0.50) ├─┤ DEPO(0.047) ├─┤ Rx(3.14) ├─┤ DEPO(0.047) ├─  ╏
      └──────────┘ └─────────────┘ └──────────┘ └─────────────┘   ╏
T  : │             0              │             1              │  ╏
                                                                  ╏
╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸┳╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸╸┛
                              ┃                                    
T  : │          2          │  ┃
            ┌─────────────┐   ┃
q0 : ───●───┤ DEPO(0.047) ├─  ┃
        │   └─────────────┘   ┃
      ┌─┴─┐ ┌─────────────┐   ┃
q1 : ─┤ Z ├─┤ DEPO(0.047) ├─  ┃
      └───┘ └─────────────┘   ┃
                              ┃
q2 : ───────────────────────  ┃
                              ┃
T  : │          2          │  ┃
                              ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

We run the circuit on a noisy simulator below

In [22]:
simple_noisy_task = noisy_simulator.run(simple_noisy_circ, shots=100_000)
simple_noisy_probs = simple_noisy_task.result().measurement_probabilities

and add it to the previous dataframe

In [23]:
simple_noisy_sim = pd.DataFrame.from_dict(simple_noisy_probs, orient="index").rename(
    columns={0: "simple_noisy_sim"},
)
df = df.join(simple_noisy_sim)
df
Cepheus-1-108Q noisy_sim free_sim simple_noisy_sim
110 0.1250 NaN NaN 0.04814
111 0.7125 0.9326 0.9391 0.73935
011 0.0792 0.0649 0.0609 0.11805
010 0.0122 NaN NaN 0.00720
100 0.0127 NaN NaN 0.00452
101 0.0508 0.0009 NaN 0.07078
001 0.0064 0.0016 NaN 0.01130
000 0.0012 NaN NaN 0.00066

We compute the fidelity between the simple noise model and the QPU:

In [24]:
f_simple = fidelity(df["simple_noisy_sim"], df["Cepheus-1-108Q"])

print(f"\nTotal fidelity between Cepheus-1-108Q and full noise model is: {f_noisy_Cepheus}")
print(f"\nTotal fidelity between Cepheus-1-108Q and simple noise model is: {f_simple}")
print(f"\nTotal fidelity between Cepheus-1-108Q and noise-free is: {f_free_Cepheus}")
Total fidelity between Cepheus-1-108Q and full noise model is: 0.8968109011001625

Total fidelity between Cepheus-1-108Q and simple noise model is: 0.9863729453631813

Total fidelity between Cepheus-1-108Q and noise-free is: 0.8874405164437654
In [25]:
df.plot.bar(title="Comparing simulators and Cepheus-1-108Q", figsize=(12, 6))
text = f"f_free = {f_free_Cepheus:.3f} \nf_simple_noise_model = {f_simple:.3f} \nf_noise_model = {f_noisy_Cepheus:.3f}"
plt.text(1, 0.5, text, fontsize=14)
plt.show()

We see that compared to the full noise model, the simple model is less accurate, however, it is still a significant improvement over the noise-free case and has far fewer parameters in the model.

Summary

In this notebook, we showed how to construct a noise model for Rigetti Cepheus-1-108Q based only on the available calibration data. We used a coarse assumption of gate-independent single-qubit depolarizing noise and gate-dependant two-qubit noise. Our qubit-dependent model could be improved in many ways. We could add gate-dependence noise, or change the depolarizing channel to Pauli channels.

In [26]:
print("Quantum Task Summary")
print(t.quantum_tasks_statistics())
print(
    "Note: Charges shown are estimates based on your Amazon Braket simulator and quantum processing unit (QPU) task usage. Estimated charges shown may differ from your actual charges. Estimated charges do not factor in any discounts or credits, and you may experience additional charges based on your use of other services such as Amazon Elastic Compute Cloud (Amazon EC2).",
)
print(
    f"Estimated cost to run this example: {t.qpu_tasks_cost() + t.simulator_tasks_cost():.3f} USD",
)
Quantum Task Summary
{<_Rigetti.Cepheus1108Q: 'arn:aws:braket:us-west-1::device/qpu/rigetti/Cepheus-1-108Q'>: {'shots': 10000, 'tasks': {'COMPLETED': 1}}}
Note: Charges shown are estimates based on your Amazon Braket simulator and quantum processing unit (QPU) task usage. Estimated charges shown may differ from your actual charges. Estimated charges do not factor in any discounts or credits, and you may experience additional charges based on your use of other services such as Amazon Elastic Compute Cloud (Amazon EC2).
Estimated cost to run this example: 4.550 USD
In [ ]:
In [ ]:

Join the Discussion

Comments (0)

No comments yet. Be the first to share your thoughts!

Indexed by QCR Librarian

This entry was created automatically from publicly available records. QCR links to public sources and only stores repository content where the license permits redistribution.

Versions

v1 Latest
Jul 14, 2026
qcr:2607.23270.1

Cite all versions? Use the base QCR ID to always reference the latest version of this entry.

Tools used

Amazon Braket SDK

Keywords

braket
noise-model
calibration-data
rigetti
superconducting-qubits
readout-error
density-matrix-simulator

You may also like5