Decoherence

Real quantum computers must deal with decoherence, or the loss of information due to environmental disturbances (noise). The Bloch vector formalism we introduced in the previous section is sufficient to describe the state of the system under decoherence processes. The pure states we have studied so far have a Bloch vector of length 1, touching the surface of the Bloch sphere, and can be represented in density matrix form as \rho=| \psi\rangle \langle \psi | . Decoherence causes a change in our quantum states from pure to mixed states, which have a density matrix \rho that can be written as a sum over pure states

\rho = \sum_k p_k | \psi_k\rangle \langle \psi_k |

and a Bloch vector that sits inside the Bloch sphere

|\langle X\rangle|^2 +  |\langle Y\rangle|^2 + | \langle Z\rangle|^2 < 1 .

Energy relaxation and T_1

One important decoherence process is called energy relaxation, where the excited |1\rangle state decays toward the ground state |0\rangle . The time constant of this process, T_1 , is an extremely important figure-of-merit for any implementation of quantum computing, and one in which IBM has made great progress in recent years, ultimately leading to the prototype quantum computer you are now using. Experiment with the circuits below to see how adding many repetitions of additional do-nothing Idle Id gates (or Identity gates; these are gates that do nothing but wait) before measurement causes the state to gradually decay towards |0\rangle .

Below is a Qiskit script for measuring T_1 .

Qiskit example

# t1.py
import numpy as np
import matplotlib.pyplot as plt

from qiskit import QuantumCircuit, execute, IBMQ

provider = IBMQ.load_account()

# Build the circuits
pre = QuantumCircuit(1, 1)
pre.x(0)
pre.barrier()
meas = QuantumCircuit(1, 1)
meas.measure(0, 0)
circuits = []
exp_vector = range(1,51)
for exp_index in exp_vector:
    middle = QuantumCircuit(1, 1)
    for i in range(45*exp_index):
        middle.iden(0)
    circuits.append(pre + middle + meas)

# Execute the circuits
shots = 1024
backend = provider.get_backend('ibmqx2')
job = execute(circuits, 'ibmqx2', shots=shots)
result = job.result()

# Plot the result
exp_data = []
exp_error = []
for idx, _ in enumerate(exp_vector):
    data = result.get_counts(idx)
    try:
        p0 = data['0']/shots
    except KeyError:
        p0 = 0
    exp_data.append(p0)
    exp_error.append(np.sqrt(p0*(1-p0)/shots))

plt.errorbar(exp_vector, exp_data, exp_error)
plt.xlabel('time [45*gate time]')
plt.ylabel('Pr(0)')
plt.grid(True)

Dephasing and T_2

Dephasing is another decoherence process, and unlike energy relaxation, it affects only superposition states. It can be understood solely in a quantum setting as it has no classical analog. The time constant T_2 includes the effect of dephasing as well as energy relaxation, and is another crucial figure-of-merit. Again, IBM has some of the world’s best qubits by this metric. Practice with the scripts below to investigate the Ramsey and echo experiments. A Ramsey experiment measures T_2^* , which can be affected by slow noise, and the echo experiment removes some of this noise.

Below is a Qiskit script for measuring T_2^* (Ramsey) and T_2 (echo).

Qiskit example

# t2_ramsey.py
import numpy as np
import matplotlib.pyplot as plt

from qiskit import QuantumCircuit, execute

provider = IBMQ.load_account()

# Build the circuits
pre = QuantumCircuit(1, 1)
pre.h(0)
pre.barrier()
meas_x = QuantumCircuit(1, 1)
meas_x.barrier()
meas_x.h(0)
meas_x.measure(0, 0)
circuits = []
exp_vector = range(1,51)
phase = 0.0
for exp_index in exp_vector:
    middle = QuantumCircuit(1, 1)
    phase = phase + 6*np.pi/len(exp_vector)
    middle.u1(phase,0)
    for i in range(5*exp_index):
        middle.iden(0)
    circuits.append(pre + middle + meas_x)

# Execute the circuits
shots = 1024
backend = provider.get_backend('ibmqx2')
job = execute(circuits, backend, shots=shots)
result = job.result()

# Plot the result
exp_data = []
exp_error = []
for idx, _ in enumerate(exp_vector):
    data = result.get_counts(idx)
    try:
        p0 = data['0']/shots
    except KeyError:
        p0 = 0
    exp_data.append(p0)
    exp_error.append(np.sqrt(p0*(1-p0)/shots))

plt.errorbar(exp_vector, exp_data, exp_error)
plt.xlabel('time [5*gate time]')
plt.ylabel('Pr(+)')
plt.grid(True)

Qiskit example

 # t2_echo.py
import numpy as np
import matplotlib.pyplot as plt

from qiskit import IBMQ, QuantumCircuit, execute

provider = IBMQ.load_account()

# Build the circuits
pre = QuantumCircuit(1, 1)
pre.h(0)
pre.barrier()
meas_x = QuantumCircuit(1, 1)
meas_x.barrier()
meas_x.h(0)
meas_x.measure([0], [0])
circuits = []
exp_vector = range(1,51)
for exp_index in exp_vector:
    middle = QuantumCircuit(1, 1)
    for i in range(15*exp_index):
        middle.iden(0)
    middle.x(0)
    for i in range(15*exp_index):
        middle.iden(0)
    circuits.append(pre + middle + meas_x)


# Execute the circuits
backend = provider.get_backend('ibmqx2')
job = execute(circuits, backend)
result = job.result()

# Plot the result
exp_data = []
exp_error = []
for exp_index in exp_vector:
  data = result.get_counts(circuits[exp_index-1])
  try:
      p0 = data['0']/shots
  except KeyError:
      p0 = 0
  exp_data.append(p0)
  exp_error.append(np.sqrt(p0*(1-p0)/shots))

plt.errorbar(exp_vector, exp_data, exp_error)
plt.xlabel('time [31*gate time]')
plt.ylabel('Pr(+)')
plt.grid(True)

Progress in decoherence with superconducting qubits

Because T_2 is such an important quantity, it is interesting to chart how far the community of superconducting qubits has come over the years. Here is a graph depicting T_2 versus time.

image0