# # Copyright 2020 Quantum Benchmark Inc. # """ Quantum Capacity ================ """ #%% import matplotlib.pyplot as plt import numpy as np import random import trueq as tq #%% # First, we demonstrate using :tqdoc:`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 = tq.Simulator().add_overrotation(0.03) sim.run(circuits) # generate the QCAP bound tq.qcap_bound(circuit, circuits) #%% # 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)[0] 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")