Skip to content

Commit

Permalink
Refactor Plaquette hierarchy (#137)
Browse files Browse the repository at this point in the history
This PR addresses #136.

---------

Co-authored-by: Yiming Zhang <61700160+inmzhang@users.noreply.github.com>
  • Loading branch information
nelimee and inmzhang authored Feb 28, 2024
1 parent 708e4e2 commit 1a54dfb
Show file tree
Hide file tree
Showing 23 changed files with 879 additions and 979 deletions.
117 changes: 78 additions & 39 deletions notebooks/logical_qubit_extended_memory_experiment.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,17 @@
" AfterResetFlipNoise,\n",
" BeforeMeasurementFlipNoise,\n",
")\n",
"from tqec.plaquette.plaquette import PlaquetteList\n",
"from tqec.plaquette.plaquette import Plaquette\n",
"from tqec.plaquette.library import (\n",
" XXPlaquetteList,\n",
" XXXXPlaquetteList,\n",
" ZZPlaquetteList,\n",
" ZZZZPlaquetteList,\n",
" ZSquareInitialisationPlaquette,\n",
" ZRoundedInitialisationPlaquette,\n",
" XXMemoryPlaquette,\n",
" XXXXMemoryPlaquette,\n",
" ZZMemoryPlaquette,\n",
" ZZZZMemoryPlaquette,\n",
" MeasurementRoundedPlaquette,\n",
" MeasurementSquarePlaquette,\n",
")\n",
"from tqec.position import Shape2D\n",
"from tqec.display import display_template"
]
},
Expand Down Expand Up @@ -129,7 +132,6 @@
" Dimension(k_width, LinearFunction(2)),\n",
" Dimension(k_height, LinearFunction(2)),\n",
" )\n",
"\n",
" # 2. Define the different plaquettes that will be used on the template defined above.\n",
" # As noted in the text description above this function, the plaquette instances in the list below\n",
" # implement by default the memory experiment we want to perform. That is the reason why there is no\n",
Expand All @@ -140,17 +142,63 @@
" # - CNOTs indices are 3, 4, 5, 6\n",
" # - (H gate for X-stabilizers is 7)\n",
" # - Measurement index is 8\n",
" plaquettes: list[PlaquetteList] = [\n",
" XXPlaquetteList(\n",
" PlaquetteOrientation.UP, [1, 2, 5, 6, 7, 8], include_detector=False\n",
" ),\n",
" ZZPlaquetteList(PlaquetteOrientation.LEFT, [1, 5, 6, 8]),\n",
" XXXXPlaquetteList([1, 2, 3, 4, 5, 6, 7, 8], include_detector=False),\n",
" ZZZZPlaquetteList([1, 3, 4, 5, 6, 8]),\n",
" ZZPlaquetteList(PlaquetteOrientation.RIGHT, [1, 3, 4, 8]),\n",
" XXPlaquetteList(\n",
" PlaquetteOrientation.DOWN, [1, 2, 3, 4, 7, 8], include_detector=False\n",
" ),\n",
" plaquettes: list[list[Plaquette]] = [\n",
" [\n",
" ZRoundedInitialisationPlaquette(PlaquetteOrientation.UP),\n",
" XXMemoryPlaquette(\n",
" PlaquetteOrientation.UP,\n",
" [1, 2, 5, 6, 7, 8],\n",
" include_detector=False,\n",
" is_first_round=True,\n",
" ),\n",
" XXMemoryPlaquette(PlaquetteOrientation.UP, [1, 2, 5, 6, 7, 8]),\n",
" MeasurementRoundedPlaquette(\n",
" PlaquetteOrientation.UP, include_detector=False\n",
" ),\n",
" ],\n",
" [\n",
" ZRoundedInitialisationPlaquette(PlaquetteOrientation.LEFT),\n",
" ZZMemoryPlaquette(\n",
" PlaquetteOrientation.LEFT, [1, 5, 6, 8], is_first_round=True\n",
" ),\n",
" ZZMemoryPlaquette(PlaquetteOrientation.LEFT, [1, 5, 6, 8]),\n",
" MeasurementRoundedPlaquette(PlaquetteOrientation.LEFT),\n",
" ],\n",
" [\n",
" ZSquareInitialisationPlaquette(),\n",
" XXXXMemoryPlaquette(\n",
" [1, 2, 3, 4, 5, 6, 7, 8], include_detector=False, is_first_round=True\n",
" ),\n",
" XXXXMemoryPlaquette([1, 2, 3, 4, 5, 6, 7, 8]),\n",
" MeasurementSquarePlaquette(include_detector=False),\n",
" ],\n",
" [\n",
" ZSquareInitialisationPlaquette(),\n",
" ZZZZMemoryPlaquette([1, 3, 4, 5, 6, 8], is_first_round=True),\n",
" ZZZZMemoryPlaquette([1, 3, 4, 5, 6, 8]),\n",
" MeasurementSquarePlaquette(),\n",
" ],\n",
" [\n",
" ZRoundedInitialisationPlaquette(PlaquetteOrientation.RIGHT),\n",
" ZZMemoryPlaquette(\n",
" PlaquetteOrientation.RIGHT, [1, 3, 4, 8], is_first_round=True\n",
" ),\n",
" ZZMemoryPlaquette(PlaquetteOrientation.RIGHT, [1, 3, 4, 8]),\n",
" MeasurementRoundedPlaquette(PlaquetteOrientation.RIGHT),\n",
" ],\n",
" [\n",
" ZRoundedInitialisationPlaquette(PlaquetteOrientation.DOWN),\n",
" XXMemoryPlaquette(\n",
" PlaquetteOrientation.DOWN,\n",
" [1, 2, 3, 4, 7, 8],\n",
" include_detector=False,\n",
" is_first_round=True,\n",
" ),\n",
" XXMemoryPlaquette(PlaquetteOrientation.DOWN, [1, 2, 3, 4, 7, 8]),\n",
" MeasurementRoundedPlaquette(\n",
" PlaquetteOrientation.DOWN, include_detector=False\n",
" ),\n",
" ],\n",
" ]\n",
"\n",
" # 3. Define the layer modifiers.\n",
Expand All @@ -160,48 +208,39 @@
" # cirq.CircuitOperation that natively supports repeting an operation efficiently, and that is\n",
" # natively recognized by the `tqec` library.\n",
" def make_repeated_layer(circuit: cirq.Circuit) -> cirq.Circuit:\n",
" # Note: we do not care on which qubit it is applied, but we want a SHIFT_COORDS instruction\n",
" # to be inserted somewhere in the repetition loop. It is inserted at the beginning.\n",
" circuit_to_repeat = cirq.Circuit([make_shift_coords(0, 0, 1)]) + circuit\n",
" circuit_to_repeat = circuit + cirq.Circuit(\n",
" cirq.Moment(make_shift_coords(0, 0, 1))\n",
" )\n",
" repeated_circuit_operation = cirq.CircuitOperation(\n",
" circuit_to_repeat.freeze()\n",
" ).repeat(repetitions)\n",
" return cirq.Circuit([repeated_circuit_operation])\n",
"\n",
" layer_modificators = {1: make_repeated_layer}\n",
" layer_modificators = {2: make_repeated_layer}\n",
"\n",
" # 4. Actually create the cirq.Circuit instance by concatenating the circuits generated\n",
" # for each layer and potentially modified by the modifiers defined above.\n",
" circuit = cirq.Circuit()\n",
" for layer_index in range(3):\n",
" for layer_index in range(4):\n",
" layer_circuit = generate_circuit(\n",
" template,\n",
" [plaquette_list.plaquettes[layer_index] for plaquette_list in plaquettes],\n",
" [plaquette_list[layer_index] for plaquette_list in plaquettes],\n",
" )\n",
" layer_circuit = normalise_circuit(layer_circuit)\n",
" circuit += layer_modificators.get(layer_index, lambda circ: circ)(layer_circuit)\n",
" circuit += cirq.Moment(make_shift_coords(0, 0, 1))\n",
"\n",
" # 5. Define the observable.\n",
" # The observable is defined and added to the cirq.Circuit instance just here.\n",
" # We assume that each plaquette has the same shape (i.e., needs the same number of qubits on the X and\n",
" # Y dimensions). XX and ZZ stabilizers have been artificially made 3x3 plaquettes for this purpose. This\n",
" # assumption will eventually need to be lifted.\n",
" plaquette_shape: Shape2D = plaquettes[0].plaquettes[0].shape\n",
" assert all(\n",
" p.shape == plaquette_shape\n",
" for plaquette_list in plaquettes\n",
" for p in plaquette_list.plaquettes\n",
" ), \"All plaquettes should have exactly the same shape for the moment.\"\n",
" origin = cirq.GridQubit(\n",
" (plaquette_shape.y - 1) * (1 + 2 * k_height // 2), plaquette_shape.x - 1\n",
" )\n",
" increments = template.get_increments()\n",
" origin = cirq.GridQubit(increments.y * k_width + 1, 1)\n",
" circuit.append(\n",
" cirq.Moment(\n",
" make_observable(\n",
" origin,\n",
" [\n",
" (cirq.GridQubit(0, i * (plaquette_shape.x - 1)), -1)\n",
" for i in range(2 * k_width + 1)\n",
" (cirq.GridQubit(0, i * increments.x), -1)\n",
" for i in range(0, template.shape.x - 1)\n",
" ],\n",
" )\n",
" )\n",
Expand Down Expand Up @@ -341,7 +380,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
"version": "3.12.0"
}
},
"nbformat": 4,
Expand Down
118 changes: 78 additions & 40 deletions notebooks/logical_qubit_memory_experiment.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,17 @@
" AfterResetFlipNoise,\n",
" BeforeMeasurementFlipNoise,\n",
")\n",
"from tqec.plaquette.plaquette import PlaquetteList\n",
"from tqec.plaquette.plaquette import Plaquette\n",
"from tqec.plaquette.library import (\n",
" XXPlaquetteList,\n",
" XXXXPlaquetteList,\n",
" ZZPlaquetteList,\n",
" ZZZZPlaquetteList,\n",
")\n",
"from tqec.position import Shape2D"
" ZSquareInitialisationPlaquette,\n",
" ZRoundedInitialisationPlaquette,\n",
" XXMemoryPlaquette,\n",
" XXXXMemoryPlaquette,\n",
" ZZMemoryPlaquette,\n",
" ZZZZMemoryPlaquette,\n",
" MeasurementSquarePlaquette,\n",
" MeasurementRoundedPlaquette,\n",
")"
]
},
{
Expand Down Expand Up @@ -121,17 +124,63 @@
" # - CNOTs indices are 3, 4, 5, 6\n",
" # - (H gate for X-stabilizers is 7)\n",
" # - Measurement index is 8\n",
" plaquettes: list[PlaquetteList] = [\n",
" XXPlaquetteList(\n",
" PlaquetteOrientation.UP, [1, 2, 5, 6, 7, 8], include_detector=False\n",
" ),\n",
" ZZPlaquetteList(PlaquetteOrientation.LEFT, [1, 5, 6, 8]),\n",
" XXXXPlaquetteList([1, 2, 3, 4, 5, 6, 7, 8], include_detector=False),\n",
" ZZZZPlaquetteList([1, 3, 4, 5, 6, 8]),\n",
" ZZPlaquetteList(PlaquetteOrientation.RIGHT, [1, 3, 4, 8]),\n",
" XXPlaquetteList(\n",
" PlaquetteOrientation.DOWN, [1, 2, 3, 4, 7, 8], include_detector=False\n",
" ),\n",
" plaquettes: list[list[Plaquette]] = [\n",
" [\n",
" ZRoundedInitialisationPlaquette(PlaquetteOrientation.UP),\n",
" XXMemoryPlaquette(\n",
" PlaquetteOrientation.UP,\n",
" [1, 2, 5, 6, 7, 8],\n",
" include_detector=False,\n",
" is_first_round=True,\n",
" ),\n",
" XXMemoryPlaquette(PlaquetteOrientation.UP, [1, 2, 5, 6, 7, 8]),\n",
" MeasurementRoundedPlaquette(\n",
" PlaquetteOrientation.UP, include_detector=False\n",
" ),\n",
" ],\n",
" [\n",
" ZRoundedInitialisationPlaquette(PlaquetteOrientation.LEFT),\n",
" ZZMemoryPlaquette(\n",
" PlaquetteOrientation.LEFT, [1, 5, 6, 8], is_first_round=True\n",
" ),\n",
" ZZMemoryPlaquette(PlaquetteOrientation.LEFT, [1, 5, 6, 8]),\n",
" MeasurementRoundedPlaquette(PlaquetteOrientation.LEFT),\n",
" ],\n",
" [\n",
" ZSquareInitialisationPlaquette(),\n",
" XXXXMemoryPlaquette(\n",
" [1, 2, 3, 4, 5, 6, 7, 8], include_detector=False, is_first_round=True\n",
" ),\n",
" XXXXMemoryPlaquette([1, 2, 3, 4, 5, 6, 7, 8]),\n",
" MeasurementSquarePlaquette(include_detector=False),\n",
" ],\n",
" [\n",
" ZSquareInitialisationPlaquette(),\n",
" ZZZZMemoryPlaquette([1, 3, 4, 5, 6, 8], is_first_round=True),\n",
" ZZZZMemoryPlaquette([1, 3, 4, 5, 6, 8]),\n",
" MeasurementSquarePlaquette(),\n",
" ],\n",
" [\n",
" ZRoundedInitialisationPlaquette(PlaquetteOrientation.RIGHT),\n",
" ZZMemoryPlaquette(\n",
" PlaquetteOrientation.RIGHT, [1, 3, 4, 8], is_first_round=True\n",
" ),\n",
" ZZMemoryPlaquette(PlaquetteOrientation.RIGHT, [1, 3, 4, 8]),\n",
" MeasurementRoundedPlaquette(PlaquetteOrientation.RIGHT),\n",
" ],\n",
" [\n",
" ZRoundedInitialisationPlaquette(PlaquetteOrientation.DOWN),\n",
" XXMemoryPlaquette(\n",
" PlaquetteOrientation.DOWN,\n",
" [1, 2, 3, 4, 7, 8],\n",
" include_detector=False,\n",
" is_first_round=True,\n",
" ),\n",
" XXMemoryPlaquette(PlaquetteOrientation.DOWN, [1, 2, 3, 4, 7, 8]),\n",
" MeasurementRoundedPlaquette(\n",
" PlaquetteOrientation.DOWN, include_detector=False\n",
" ),\n",
" ],\n",
" ]\n",
"\n",
" # 3. Define the layer modifiers.\n",
Expand All @@ -141,50 +190,39 @@
" # cirq.CircuitOperation that natively supports repeting an operation efficiently, and that is\n",
" # natively recognized by the `tqec` library.\n",
" def make_repeated_layer(circuit: cirq.Circuit) -> cirq.Circuit:\n",
" # Note: we do not care on which qubit it is applied, but we want a SHIFT_COORDS instruction\n",
" # to be inserted somewhere in the repetition loop. It is inserted at the beginning.\n",
" any_qubit = next(iter(circuit.all_qubits()), None)\n",
" assert (\n",
" any_qubit is not None\n",
" ), \"Could not find any qubit in the given Circuit instance.\"\n",
" circuit_to_repeat = cirq.Circuit([make_shift_coords(0, 0, 1)]) + circuit\n",
" circuit_to_repeat = circuit + cirq.Circuit(\n",
" cirq.Moment(make_shift_coords(0, 0, 1))\n",
" )\n",
" repeated_circuit_operation = cirq.CircuitOperation(\n",
" circuit_to_repeat.freeze()\n",
" ).repeat(repetitions)\n",
" return cirq.Circuit([repeated_circuit_operation])\n",
"\n",
" layer_modificators = {1: make_repeated_layer}\n",
" layer_modificators = {2: make_repeated_layer}\n",
"\n",
" # 4. Actually create the cirq.Circuit instance by concatenating the circuits generated\n",
" # for each layer and potentially modified by the modifiers defined above.\n",
" circuit = cirq.Circuit()\n",
" for layer_index in range(3):\n",
" for layer_index in range(4):\n",
" layer_circuit = generate_circuit(\n",
" template,\n",
" [plaquette_list.plaquettes[layer_index] for plaquette_list in plaquettes],\n",
" [plaquette_list[layer_index] for plaquette_list in plaquettes],\n",
" )\n",
" layer_circuit = normalise_circuit(layer_circuit)\n",
" circuit += layer_modificators.get(layer_index, lambda circ: circ)(layer_circuit)\n",
" circuit += cirq.Moment(make_shift_coords(0, 0, 1))\n",
"\n",
" # 5. Define the observable.\n",
" # The observable is defined and added to the cirq.Circuit instance just here.\n",
" # We assume that each plaquette has the same shape (i.e., needs the same number of qubits on the X and\n",
" # Y dimensions). XX and ZZ stabilizers have been artificially made 3x3 plaquettes for this purpose. This\n",
" # assumption will eventually need to be lifted.\n",
" plaquette_shape: Shape2D = plaquettes[0].plaquettes[0].shape\n",
" assert all(\n",
" p.shape == plaquette_shape\n",
" for plaquette_list in plaquettes\n",
" for p in plaquette_list.plaquettes\n",
" ), \"All plaquettes should have exactly the same shape for the moment.\"\n",
" origin = cirq.GridQubit(plaquette_shape.y - 1, plaquette_shape.x - 1)\n",
" increments = template.get_increments()\n",
" origin = cirq.GridQubit(increments.y * k + 1, 1)\n",
" circuit.append(\n",
" cirq.Moment(\n",
" make_observable(\n",
" origin,\n",
" [\n",
" (cirq.GridQubit(0, i * (plaquette_shape.x - 1)), -1)\n",
" for i in range(2 * k + 1)\n",
" (cirq.GridQubit(0, i * increments.x), -1)\n",
" for i in range(0, template.shape.x - 1)\n",
" ],\n",
" )\n",
" )\n",
Expand Down
Loading

0 comments on commit 1a54dfb

Please sign in to comment.