# Quantum Capacity

import matplotlib.pyplot as plt
import numpy as np
import random
import trueq as tq


First, we demonstrate using QCAP in the simplest setting: we create a small circuit and compute its QCAP bound.

# make a circuit to assess
circuit = tq.Circuit(
[
{1: tq.Gate.x, (0, 2): tq.Gate.cz},
{0: tq.Gate.h, 1: tq.Gate.h},
{(1, 2): tq.Gate.cnot, (0, 4): tq.Gate.cz},
]
)

# generate a circuit collection to measure the QCAP
circuits = tq.make_qcap(circuit, [0, 4, 16, 32])

# run the circuits on your hardware or simulator
sim.run(circuits)

# generate the QCAP bound
tq.qcap_bound(circuit, circuits)

True-Q formatting will not be loaded without trusting this notebook or rerunning the affected cells. Notebooks can be marked as trusted by clicking "File -> Trust Notebook".
 QCAP Quantum Capacity Paulis (0, 1, 2, 4) Key: labels: (0, 1, 2, 4) protocol: QCAP twirl: Paulis on [0, 1, 2, 4] ${e}_{IU}$ The inferred upper bound on the process infidelity of a circuit if it were run under RC. 2.3e-02 (1.4e-03) 0.02270754498662919, 0.001444899020676287

Next, we perform a small study demonstrating the effectiveness of the QCAP bound on the family of random circuits which use the following hard cycles:

hard_cycles = [
tq.Cycle({(0, 1): tq.Gate.cz, (2, 3): tq.Gate.cz}),
tq.Cycle({(0, 2): tq.Gate.cz, (1, 3): tq.Gate.cz}),
tq.Cycle({(0, 3): tq.Gate.cz, (1, 2): tq.Gate.cz}),
]


First, we use the QCAP assessment to measure the process infidelity of each of these hard cycles.

qcap_circuits = tq.make_qcap(hard_cycles, [4, 16])
sim.run(qcap_circuits)
qcap_fit = qcap_circuits.fit()


Then, we generate a random circuit using these hard cycles interleaved with single qubit cycles for a number of circuit depths. In each instance, we randomly compile the random circuit 20 times; QCAP bounds the performance of circuits whose noise profile has been tailored by RC.

def make_random_circuit(depth):
circuit = tq.Circuit()
for _ in range(depth):
circuit += {q: tq.Gate.random(2) for q in range(4)}
circuit += random.choice(hard_cycles)
circuit += {q: tq.Gate.random(2) for q in range(4)}
circuit.measure_all()
circuit.key = tq.Key(depth=depth)
return circuit

random_circuits = tq.CircuitCollection()
depths = list(range(5, 30, 5))
for depth in depths:
bare_circuit = make_random_circuit(depth)
random_circuits += bare_circuit
random_circuits += tq.randomly_compile(bare_circuit, 20)

sim.run(random_circuits, 1000)


Finally, we collect and plot the data.

qcaps = np.empty((len(depths), 2))
rc_tvds = np.empty((len(depths), 2))
for idx, depth in enumerate(depths):
bare_circuit = random_circuits.subset(protocol=["RC"], depth=depth)
rc_circuits = random_circuits.subset(protocol="RC", depth=depth)

# compute the QCAP bound for this circuit
qcaps[idx, :] = tq.qcap_bound(bare_circuit, qcap_fit).e_IU[1:]

# compute the TVD from the RC results to the ideal bitstring distribution
ideal_probs = tq.Simulator().sample(bare_circuit, float("inf"))
rc_tvds[idx, :] = rc_circuits.sum_results().tvd(ideal_probs)

plt.errorbar(depths, qcaps[:, 0], yerr=2.96 * qcaps[:, 1], label="QCAP Bound")
plt.errorbar(depths, rc_tvds[:, 0], yerr=2.96 * rc_tvds[:, 1], label="RC TVD")
plt.ylim([0, 0.3])
plt.legend()
plt.xlabel("Circuit Depth") Text(0.5, 23.52222222222222, 'Circuit Depth')


Total running time of the script: ( 0 minutes 18.116 seconds)

Gallery generated by Sphinx-Gallery