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._token_manager.get_bearer_token()
    headers["Authorization"] = bearer_token

    if calibration_set_id:
        url = os.path.join(
            client._api.iqm_server_url, "calibration/metrics/", calibration_set_id
        )
    else:
        url = os.path.join(client._api.iqm_server_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(os.environ["Q5_CORTEX_URL"])
backend = provider.get_backend()

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

{
  'metric':
  {
    'component':
    {
      'value': '1',
      'unit': '',
      'uncertainity': '',
      'timestamp': '2024-04-08T05:05:47.58068',
      'implementation': ''
    }
  }
}

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):
            for qb, qb_data in metric_data.items():
                if qb.startswith("QB"):
                    values.append(float(qb_data["value"]))
                    # Extract the qubit label from the key
                    labels.append(qb)

    # 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="measure_ssro_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="prx_rb_fidelity",
    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_irb_fidelity",
    title="CZ Gate Fidelities",
    xlabel="Qubit pairs",
    ylabel="Fidelities",
    data=calibration_data,
    limits=[0.8, 1],
)
plot_metrics(
    metric="clifford_rb_fidelity",
    title="Two-qubit Gates Cliffords Averaged",
    xlabel="Qubits",
    ylabel="Fidelities",
    data=calibration_data,
    limits=[0.7, 1],
)

Software versions

cirq-iqm==15.1
iqm-client==20.3
iqm-cortex-cli==5.10
qiskit-iqm==15.4