Note

This is the documentation for the current state of the development branch of Qiskit Experiments. The documentation or APIs here can change prior to being released.

T1 Characterization

Background

In a \(T_1\) experiment, we measure an excited qubit after a delay. Due to decoherence processes (e.g. the amplitude damping channel), it is possible that, at the time of measurement, after the delay, the qubit will not be excited anymore. The larger the delay time is, the more likely is the qubit to fall to the ground state. The goal of the experiment is to characterize the decay rate of the qubit towards the ground state.

We start by fixing a delay time \(t\) and a number of shots \(s\). Then, by repeating \(s\) times the procedure of exciting the qubit, waiting, and measuring, we estimate the probability to measure \(|1\rangle\) after the delay. We repeat this process for a set of delay times, resulting in a set of probability estimates.

In the absence of state preparation and measurement errors, the probability to measure \(|1\rangle\) after time \(t\) is \(e^{-t/T_1}\), for a constant \(T_1\) (the coherence time), which is our target number. Since state preparation and measurement errors do exist, the qubit’s decay towards the ground state assumes the form \(Ae^{-t/T_1} + B\), for parameters \(A, T_1\), and \(B\), which we deduce from the probability estimates.

The following code demonstrates a basic run of a \(T_1\) experiment for qubit 0.

Note

This tutorial requires the qiskit-aer and qiskit-ibm-runtime packages to run simulations. You can install them with python -m pip install qiskit-aer qiskit-ibm-runtime.

import numpy as np
from qiskit.qobj.utils import MeasLevel
from qiskit_experiments.framework import ParallelExperiment
from qiskit_experiments.library import T1
from qiskit_experiments.library.characterization.analysis.t1_analysis import T1KerneledAnalysis

# A T1 simulator
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel
from qiskit_ibm_runtime.fake_provider import FakePerth

# A kerneled data simulator
from qiskit_experiments.test.mock_iq_backend import MockIQBackend
from qiskit_experiments.test.mock_iq_helpers import MockIQT1Helper

# Create a pure relaxation noise model for AerSimulator
noise_model = NoiseModel.from_backend(
    FakePerth(), thermal_relaxation=True, gate_error=False, readout_error=False
)

# Create a fake backend simulator
backend = AerSimulator.from_backend(FakePerth(), noise_model=noise_model)

# Look up target T1 of qubit-0 from device properties
qubit0_t1 = FakePerth().qubit_properties(0).t1

# Time intervals to wait before measurement
delays = np.arange(1e-6, 3 * qubit0_t1, 3e-5)
# Create an experiment for qubit 0
# with the specified time intervals
exp = T1(physical_qubits=(0,), delays=delays)

# Set scheduling method so circuit is scheduled for delay noise simulation
exp.set_transpile_options(scheduling_method='asap')

# Run the experiment circuits and analyze the result
exp_data = exp.run(backend=backend, seed_simulator=101).block_for_results()

# Print the result
display(exp_data.figure(0))
for result in exp_data.analysis_results():
    print(result)
../../_images/t1_1_0.png
AnalysisResult
- name: @Parameters_T1Analysis
- value: CurveFitResult:
 - fitting method: least_squares
 - number of sub-models: 1
  * F_exp_decay(x) = amp * exp(-x/tau) + base
 - success: True
 - number of function evals: 20
 - degree of freedom: 3
 - chi-square: 2.0093912890351855
 - reduced chi-square: 0.6697970963450618
 - Akaike info crit.: -0.5635658057926642
 - Bayesian info crit.: -1.188287398108499
 - init params:
  * amp = 0.9170731707317072
  * tau = 5.607702037182498e-05
  * base = 0.06585365853658537
 - fit params:
  * amp = 1.0086868600245593 ± 0.015516360599905375
  * tau = 5.857050868543882e-05 ± 2.8452247868322258e-06
  * base = -0.008900903447908065 ± 0.015635835560472412
 - correlations:
  * (amp, base) = -0.9367372951891404
  * (tau, base) = -0.9216265221283944
  * (amp, tau) = 0.825232199013559
- quality: good
- extra: <3 items>
- device_components: ['Q0']
- verified: False
AnalysisResult
- name: T1
- value: (5.86+/-0.28)e-05
- χ²: 0.6697970963450618
- quality: good
- extra: <3 items>
- device_components: ['Q0']
- verified: False

\(T_1\) experiments with kerneled measurement

\(T_1\) experiments can also be done with kerneled measurements. If we set the run option meas_level=MeasLevel.KERNELED, the job will not discriminate the IQ data and will not label it. In the T1 experiment, since we know that \(P(1|t=0)=1\), we will add a circuit with delay=0, and another circuit with a very large delay. In this configuration we know that the data starts from a point [I,Q] that is close to a logical value ‘1’ and ends at a point [I,Q] that is close to a logical value ‘0’.

# Experiment
ns = 1e-9
mu = 1e-6

# qubit properties
t1 = 45 * mu

# we will guess that our guess is 10% off the exact value of t1 for qubit 0.
t1_estimated_shift = t1/10

# We use log space for the delays because of the noise properties
delays = np.logspace(1, 11, num=23, base=np.exp(1))
delays *= ns

# Adding circuits with delay=0 and long delays so the centers in the IQ plane won't be misplaced.
# Without this, the fitting can provide wrong results.
delays = np.insert(delays, 0, 0)
delays = np.append(delays, [t1*3])

num_qubits = 2
num_shots = 2048

backend = MockIQBackend(
    MockIQT1Helper(
        t1=t1,
        iq_cluster_centers=[((-5.0, -4.0), (-5.0, 4.0)), ((3.0, 1.0), (5.0, -3.0))],
        iq_cluster_width=[1.0, 2.0],
    )
)

# Creating a T1 experiment
expT1_kerneled = T1((0,), delays)
expT1_kerneled.analysis = T1KerneledAnalysis()
expT1_kerneled.analysis.set_options(p0={"amp": 1, "tau": t1 + t1_estimated_shift, "base": 0})

# Running the experiment
expdataT1_kerneled = expT1_kerneled.run(
    backend=backend, meas_return="avg", meas_level=MeasLevel.KERNELED, shots=num_shots
).block_for_results()

# Displaying results
display(expdataT1_kerneled.figure(0))
for result in expdataT1_kerneled.analysis_results():
    print(result)
../../_images/t1_2_0.png
AnalysisResult
- name: @Parameters_T1KerneledAnalysis
- value: CurveFitResult:
 - fitting method: least_squares
 - number of sub-models: 1
  * F_exp_decay(x) = amp * exp(-x/tau) + base
 - success: True
 - number of function evals: 24
 - degree of freedom: 22
 - chi-square: 0.0016265491601967787
 - reduced chi-square: 7.393405273621721e-05
 - Akaike info crit.: -235.00426032116496
 - Bayesian info crit.: -231.34763284656037
 - init params:
  * amp = 1.0
  * tau = 4.95e-05
  * base = 0.0
 - fit params:
  * amp = 1.0469535442726126 ± 0.011310466790860061
  * tau = 4.394415455708184e-05 ± 1.035755542082525e-06
  * base = -0.05146921117096622 ± 0.011431939576229254
 - correlations:
  * (amp, base) = -0.9835183492877463
  * (tau, base) = -0.849316060844548
  * (amp, tau) = 0.8027246629067045
- quality: good
- extra: <3 items>
- device_components: ['Q0']
- verified: False
AnalysisResult
- name: T1
- value: (4.39+/-0.10)e-05
- χ²: 7.393405273621721e-05
- quality: good
- extra: <3 items>
- device_components: ['Q0']
- verified: False

See also

  • API documentation: T1