Visualizing Quality Metrics¶
A quantum computers performance can change on a regular basis. This can be mitigated to some extent by calibration of the device which generates a calibration set, which is a set of parameters to current operate the quantum computer at. Because of drifts in the environment that the quantum computer operates at, regular calibration is required to account for these drifts and maintain optimal performance.
To test the current performance of the calibration, we also benchmark the device, producing a quality metrics set. These benchmarks reflect the current status of the quantum computer and are essential pieces of information for using the system. For example, performance can often be increased by choosing a particular qubit or tunable coupler when running your quantum circuit.
This notebook demonstrates how one can read the quality metrics set from the API and visualize it.
Importing Libraries¶
import json
import os
import matplotlib.pyplot as plt
import requests
from iqm.iqm_client import IQMClient
from iqm.qiskit_iqm import IQMProvider
Getting the data from the API¶
The calibration set ID and quality metrics set data are bundled together in JSON format available from the Cortex API. In this example, we make a HTTP request to the particular API endpoint, in this case, calibration/metrics/latest
. We use the IQMClient
to add the authentication token to the request, which is needed for accessing VTT quantum computers.
First we define a helper function to get the data. The function get_calibration_data
takes input IQMClient
, calibration_set_id
and optionally a filename
. The filename
option can be pass to save the data to a json file.
def get_calibration_data(
client: IQMClient, calibration_set_id=None, filename: str = None
):
"""
Return the calibration data and figures of merit using IQMClient.
Optionally you can input a calibration set id (UUID) to query historical results
Optionally save the response to a json file, if filename is provided
"""
headers = {"User-Agent": client._signature}
bearer_token = client._get_bearer_token()
headers["Authorization"] = bearer_token
if calibration_set_id:
url = os.path.join(client._base_url, "calibration/metrics/", calibration_set_id)
else:
url = os.path.join(client._base_url, "calibration/metrics/latest")
response = requests.get(url, headers=headers)
response.raise_for_status() # will raise an HTTPError if the response was not ok
data = response.json()
data_str = json.dumps(data, indent=4)
if filename:
with open(filename, "w") as f:
f.write(data_str)
print(f"Data saved to {filename}")
return data
Defining the IQM Client¶
Setup the qiskit IQMProvider
using the link to backend.
provider = IQMProvider("https://qc.vtt.fi/helmi/cocos")
backend = provider.get_backend()
# If you receive an error you may need to set the IQM_TOKENS_FILE environment variable
# os.environ["IQM_TOKENS_FILE"] = "/path/to/file"
We can then get the raw calibration data and see what it looks like
calibration_data = get_calibration_data(backend.client)
print(calibration_data)
Here are the alternative options
# cal_set_id = "1b7b8415-1ec6-41d5-8c11-9800c111612c"
# calibration_data = get_calibration_data(backend.client, cal_set_id)
# calibration_data = get_calibration_data(
# backend.client, cal_set_id, filename=f"{cal_set_id}.json"
# )
We can parse this data to see individual metrics and values. For example:
calibration_data["metrics"]
The data is in the format
{
'component.metric':
{
'value': '1',
'unit': '',
'uncertainity': '',
'timestamp': '2024-04-08T05:05:47.58068'
}
}
Plotting the data¶
To plot the data, we utilise a simple plotting function which can plot a specific metric which we are interested in. The function iterates over the gathered data and extracts the particular keys and values for the input metric. This requires knowing and using the same string as the metric you are interested in.
def plot_metrics(
metric: str, title: str, ylabel: str, xlabel: str, data: dict, limits: list = []
):
# Initialize lists to store the values and labels
values = []
labels = []
# Iterate over the calibration data and collect values and labels based on the metric
for key, metric_data in data["metrics"].items():
if key.endswith(metric):
values.append(float(metric_data["value"]))
# Extract the qubit label from the key
labels.append(key.split(".")[0])
# Check if values were found for the given metric
if not values:
return f"{metric} not in quality metrics set!"
# Set the width and gap between the bars
bar_width = 0.4
# Calculate the positions of the bars
positions = range(len(values))
# Plot the values with labels
plt.bar(positions, values, width=bar_width, tick_label=labels)
if len(limits) == 2:
plt.ylim(limits)
plt.grid(axis="y")
plt.xlabel(xlabel)
plt.ylabel(ylabel)
plt.title(title)
plt.xticks(rotation=90)
plt.tight_layout()
plt.show()
Readout Fidelities¶
The readout fidelity describes how well the quantum computer can measure your quantum state. From the readout fidelity one can see how much error from their quantum circuit they can attribute to incorrectly reading out or measuring the quantum state.
Readout fidelity includes both state preparation and measurement errors here.
Typical values for readout fidelities are between $94\%$ and $99\%$ for VTT quantum computers.
plot_metrics(
metric="single_shot_readout_fidelity",
title="Single Shot Readout Fidelities",
xlabel="Qubits",
ylabel="Success rate",
data=calibration_data,
limits=[0.85, 1],
)
$T_1$ & $T_2$ Times¶
The $T_1$ and $T_2$ times are the coherence times for the system.
The $T_1$ time is called the longitudinal relaxation rate and describes how quickly the excited state of the qubit returns to its ground state.
The $T_2$ time is called the transverse relaxation rate and describes loss of coherence of a superposition state.
The $T_2$-echo time describes the loss of coherence of the superposition state of the qubit. It is more precise than the $T_2$ Time as it is less susceptible to low-frequency noise.
Based on these values you can approximate how many gates you can run on the quantum computer before decoherence occurs, which is an important quantity when writing quantum circuits.
Typical values for the coherence times are between $10 \mu s$ and $60 \mu s$ for VTT's quantum computers.
plot_metrics(
metric="t1_time",
title="T1 times",
xlabel="Qubits",
ylabel="Time",
data=calibration_data,
)
plot_metrics(
metric="t2_time",
title="T2 times",
xlabel="Qubits",
ylabel="Time",
data=calibration_data,
)
plot_metrics(
metric="t2_echo_time",
title="T2 Echo times",
xlabel="Qubits",
ylabel="Time",
data=calibration_data,
)
Single qubit gate fidelities¶
Single qubit gate fidelities are measured through executing the single qubit randomized benchmarking (RB) experiment.
In this experiment a random sequence of single-qubit clifford gates are sampled and the survival probabilities are measured. An exponential curve is then fit and an estimate for the average gate fidelity across the set of clifford gates is calculated.
It is important to note that single qubit gate fidelities are independent of state preparation and measurement (SPAM) errors.
Typical values range between $99.99\%$ and $99.999\%$.
plot_metrics(
metric="fidelity_1qb_gates_averaged",
title="Single-qubit Gate Fidelities",
xlabel="Qubits",
ylabel="Fidelities",
data=calibration_data,
limits=[0.95, 1],
)
Two qubit gate fidelities¶
The calibration data reports two metrics for the two-qubit gate fidelity. The CZ gate fidelity and the two-qubit average gate fidelity.
The CZ fidelity is estimated using interleaved randomized benchmarking. In this randomized benchmarking sequence is interleaved with the CZ gate, obtaining the average gate fidelity for that specific gate. This is important to know because VTT's quantum computers have their two-qubit native gate as the CZ gate. The fidelity is usually higher than the average 2QB gate fidelity as a random 2QB Clifford transpiles on average to 8.25 1QB gates and 1.5 2QB CZ gates.
The 2QB average gate fidelity is estimated with randomized benchmarking protocol in a similar fashion to the single-qubit RB protocol.
Typical values are between $97\%$ and $99\%$ for CZ gate fidelities and $93\%$ and $96\%$ for two-qubit RB.
plot_metrics(
metric="cz_gate_fidelity",
title="CZ Gate Fidelities",
xlabel="Qubit pairs",
ylabel="Fidelities",
data=calibration_data,
limits=[0.8, 1],
)
plot_metrics(
metric="fidelity_2qb_cliffords_averaged",
title="Two-qubit Gates Cliffords Averaged",
xlabel="Qubits",
ylabel="Fidelities",
data=calibration_data,
limits=[0.7, 1],
)
Software versions¶
cirq-iqm==12.2
iqm-client==15.3
iqm-cortex-cli==5.8
qiskit-iqm==11.10