Three CNOTs#
This notebook shows the construction and simulation results of three logical CNOT gates between three logical qubits with lattice surgery [1].
Construction#
The three CNOT gates are applied in the following order:
tqec
provides builtin functions tqec.gallery.three_cnots
to construct three logical CNOT gates compressed in spacetime.
[1]:
from tqec.gallery import three_cnots
graph = three_cnots()
graph.view_as_html()
[1]:
The three logical CNOTs has six independent stabilizer flow generators: XXI -> XIX
, IXI -> IXX
, IIX -> IIX
, ZII -> ZII
, ZZI -> IZI
, IZZ -> IIZ
. Here we show the correlation surfaces for the generators.
[2]:
correlation_surfaces = graph.find_correlation_surfaces()
XXI -> XIX
#
[3]:
graph.view_as_html(
pop_faces_at_direction="-Y",
show_correlation_surface=correlation_surfaces[0],
)
[3]:
IXI -> IXX
#
[4]:
graph.view_as_html(
pop_faces_at_direction="-Y",
show_correlation_surface=correlation_surfaces[4],
)
[4]:
IIX -> IIX
#
[5]:
graph.view_as_html(
pop_faces_at_direction="-Y",
show_correlation_surface=correlation_surfaces[5],
)
[5]:
ZII -> ZII
#
[6]:
graph.view_as_html(
pop_faces_at_direction="+Z",
show_correlation_surface=correlation_surfaces[1],
)
[6]:
ZZI -> IZI
#
[7]:
graph.view_as_html(
pop_faces_at_direction="+X",
show_correlation_surface=correlation_surfaces[2],
)
[7]:
IZZ -> IIZ
#
[8]:
graph.view_as_html(
pop_faces_at_direction="+X",
show_correlation_surface=correlation_surfaces[3],
)
[8]:
Example Circuit#
Here we show an example circuit of three logical CNOTs with \(d=3\) surface code that is initialized and measured in X basis. You can download the circuit here or view it in Crumble.
[9]:
from tqec import Basis, NoiseModel, compile_block_graph
graph = three_cnots(Basis.X)
compiled_graph = compile_block_graph(graph)
circuit = compiled_graph.generate_stim_circuit(
k=1, noise_model=NoiseModel.uniform_depolarizing(p=0.001)
)
Simulation#
Here we show the simulation results for all the six observables under uniform depolarizing noise model.
Click to show the full code used for simulation
from pathlib import Path
import matplotlib.pyplot as plt
import numpy
import sinter
from tqec.gallery import three_cnots
from tqec import NoiseModel
from tqec.simulation.plotting.inset import plot_observable_as_inset
from tqec.simulation.simulation import start_simulation_using_sinter
from tqec.utils.enums import Basis
SAVE_DIR = Path("results")
def generate_graphs(support_observable_basis: Basis) -> None:
block_graph = three_cnots(support_observable_basis)
zx_graph = block_graph.to_zx_graph()
correlation_surfaces = block_graph.find_correlation_surfaces()
stats = start_simulation_using_sinter(
block_graph,
range(1, 4),
list(numpy.logspace(-4, -1, 10)),
NoiseModel.uniform_depolarizing,
manhattan_radius=2,
observables=correlation_surfaces,
num_workers=20,
max_shots=10_000_000,
max_errors=5_000,
decoders=["pymatching"],
print_progress=True,
)
for i, stat in enumerate(stats):
fig, ax = plt.subplots()
sinter.plot_error_rate(
ax=ax,
stats=stat,
x_func=lambda stat: stat.json_metadata["p"],
failure_units_per_shot_func=lambda stat: stat.json_metadata["d"],
group_func=lambda stat: stat.json_metadata["d"],
)
plot_observable_as_inset(ax, zx_graph, correlation_surfaces[i])
ax.grid(axis="both")
ax.legend()
ax.loglog()
ax.set_title("Three CNOTs Error Rate")
ax.set_xlabel("Physical Error Rate")
ax.set_ylabel("Logical Error Rate(per round)")
fig.savefig(
SAVE_DIR
/ f"three_cnots_result_{support_observable_basis}_observable_{i}.png"
)
def main():
SAVE_DIR.mkdir(exist_ok=True)
generate_graphs(Basis.Z)
generate_graphs(Basis.X)
if __name__ == "__main__"
main()
XXI -> XIX
#

IXI -> IXX
#

IIX -> IIX
#

ZII -> ZII
#

ZZI -> IZI
#

IZZ -> IIZ
#

References#
[1] Horsman, D., Fowler, A. G., Devitt, S., & Van Meter, R. (2012). Surface code quantum computing by lattice surgery. New Journal of Physics, 14(12), 123011.