Source code for qiskit_qec.geometry.tiles.hexagontile

# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2022
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""HexagonTile class."""
from math import sqrt
import numpy as np
from qiskit.exceptions import QiskitError
from qiskit_qec.geometry.model.shell import Shell
from qiskit_qec.geometry.tiles.tile import Tile
from qiskit_qec.geometry.tiles.tilefactory import TileFactory
from qiskit_qec.operators.pauli_list import PauliList


# pylint: disable=anomalous-backslash-in-string)
[docs] class HexagonTile(Tile): r"""Hexagon Tile Weight 6 operators (0,1,2):: q0 q1 v0 v1 o-----o q3 / \ q4 v5 o 0 o v2 q2 q3 \ / v0 v1 q6 o-----o q7 o-----o v4 v3 q5 / \ q6 .(0,0) v5 o 1 o v2 q6 q7 \ / v0 v1 o-----o o-----o v4 v3 q9 / \ q10 q8 q9 v5 o 2 o v2 \ / o-----o v4 v3 q11 q12 o-----o / \ o-----o 0 o / \ / o 1 o-----o \ / \ o-----o 2 o \ / o-----o Weight 2 operators (3,4,5,6,7,8,9,10,11):: q0 o v1 3 / o v0 q3 q2 4 q3 q3 q4 v1 o-----o v0 o v1 o v1 \ 5 / 6 o v0 o v0 q6 q7 v0 o-----o v1 q6 7 q7 q6 q7 o v0 o v0 q8 10 q9 / 8 \ 9 v1 o-----o v0 o o v1 q9 q10 o v0 \ 11 o v1 q11 o 3/ o--4--o o \5 /6 o--7--o /8 \9 o--10-o o \11 o """ wf_operator_dict = { "cX": [ PauliList(["XXXXXX"], input_qubit_order="left-to-right"), # 0 PauliList(["XXXXXX"], input_qubit_order="left-to-right"), # 1 PauliList(["XXXXXX"], input_qubit_order="left-to-right"), # 2 None, # 3 None, # 4 None, # 5 None, # 6 None, # 7 None, # 8 None, # 9 None, # 10 None, # 11 ], "cZ": [ PauliList(["ZZZZZZ"], input_qubit_order="left-to-right"), PauliList(["ZZZZZZ"], input_qubit_order="left-to-right"), PauliList(["ZZZZZZ"], input_qubit_order="left-to-right"), None, # 3 None, # 4 None, # 5 None, # 6 None, # 7 None, # 8 None, # 9 None, # 10 None, # 11 ], "dXZ": [ PauliList(["XXXXXX", "ZZZZZZ"], input_qubit_order="left-to-right"), PauliList(["XXXXXX", "ZZZZZZ"], input_qubit_order="left-to-right"), PauliList(["XXXXXX", "ZZZZZZ"], input_qubit_order="left-to-right"), None, # 3 None, # 4 None, # 5 None, # 6 None, # 7 None, # 8 None, # 9 None, # 10 None, # 11 ], "dZX": [ PauliList(["ZZZZZZ", "XXXXXX"], input_qubit_order="left-to-right"), PauliList(["ZZZZZZ", "XXXXXX"], input_qubit_order="left-to-right"), PauliList(["ZZZZZZ", "XXXXXX"], input_qubit_order="left-to-right"), None, # 3 None, # 4 None, # 5 None, # 6 None, # 7 None, # 8 None, # 9 None, # 10 None, # 11 ], "cYZX2-hXX": [ PauliList(["YZXYZX"], input_qubit_order="left-to-right"), # 0 PauliList(["YZXYZX"], input_qubit_order="left-to-right"), # 1 PauliList(["YZXYZX"], input_qubit_order="left-to-right"), # 2 None, # 3 PauliList(["XX"]), # 4 None, # 5 None, # 6 PauliList(["XX"]), # 7 None, # 8 None, # 9 PauliList(["XX"]), # 10 None, # 11 ], "cZ-aXX": [ PauliList(["XXXXXX"], input_qubit_order="left-to-right"), # 0 PauliList(["XXXXXX"], input_qubit_order="left-to-right"), # 1 PauliList(["XXXXXX"], input_qubit_order="left-to-right"), # 2 PauliList(["XX"]), # 3 PauliList(["XX"]), # 4 PauliList(["XX"]), # 5 PauliList(["XX"]), # 6 PauliList(["XX"]), # 7 PauliList(["XX"]), # 8 PauliList(["XX"]), # 9 PauliList(["XX"]), # 10 PauliList(["XX"]), # 11 ], } # Descriptions of wireframes # qubit indices for each wireframe wf_q_indices = [ [0, 1, 4, 7, 6, 3], # 0 [2, 3, 6, 9, 8, 5], # 1 [6, 7, 10, 12, 11, 9], # 2 [3, 0], # 3 [3, 2], # 4 [6, 3], # 5 [7, 4], # 6 [6, 7], # 7 [6, 9], # 8 [7, 10], # 9 [9, 8], # 10 [9, 11], # 11 ] # pylint: disable=invalid-name r = sqrt(3) / 2 h = 1 / 2 # coordinates for each wireframe vertex in path list form to enable the # creation of the associate edges wf_coordinates = [ [[0, 2 * r], [2 * h, 2 * r], [1 + h, r], [1, 0], [0, 0], [-h, r]], # 0 [[-1 - h, r], [-h, r], [0, 0], [-h, -r], [-1 - h, -r], [-2, 0]], # 1 [[0, 0], [1, 0], [1 + h, -r], [2 * h, -2 * r], [0, -2 * r], [-h, -r]], # 2 [[-h, r], [0, 2 * r]], # 3 [[-h, r], [-1 - h, r]], # 4 [[0, 0], [-h, r]], # 5 [[1, 0], [1 + h, r]], # 6 [[0, 0], [1, 0]], # 7 [[0, 0], [-h, -r]], # 8 [[1, 0], [1 + h, -r]], # 9 [[-h, -r], [-1 - h, -r]], # 10 [[-h, -r], [0, -2 * r]], # 11 ] # If the wf's are closed loops or not wf_loop_indicator = [ True, True, True, False, False, False, False, False, False, False, False, False, ] # How wireframes components combine into faces/operators faces_wf_components = [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11]] # Face colors (wf's inherit colors from faces) face_colors = [ "yellowgreen", "tomato", "steelblue", "red", "red", "red", "red", "red", "red", "red", "red", "red", ] num_faces = 12 size = np.array([2 * h + 2, 4 * r]) num_qubits = 13 u_vec = np.array([3, 0]) v_vec = np.array([3 / 2, 3 * r]) def __new__( cls, origin: np.array, qubit_count=None, qubit_data=None, operators=None, optype="cZ-aXX", ) -> Shell: r"""Hexagon Tile Tile:: q0 q1 v0 v1 o-----o q3 / \ q4 v5 o 0 o v2 q2 q3 \ / v0 v1 q6 o-----o q7 o-----o v4 v3 q5 / \ q6 .(0,0) v5 o 1 o v2 q6 q7 \ / v0 v1 o-----o o-----o v4 v3 q9 / \ q10 q8 q9 v5 o 2 o v2 \ / o-----o v4 v3 q11 q12 o-----o / \ o-----o 0 o / \ / o 1 o-----o \ / \ o-----o 2 o \ / o-----o Weight 2 operators (3,4,5,6,7,8,9,10,11):: q0 o v1 3 / o v0 q3 q2 4 q3 q3 q4 v1 o-----o v0 o v1 o v1 \ 5 / 6 o v0 o v0 q6 q7 v0 o-----o v1 q6 7 q7 q6 q7 o v0 o v0 q8 10 q9 / 8 \ 9 v1 o-----o v0 o o v1 q9 q10 o v0 \ 11 o v1 q11 o 3/ o--4--o o \5 /6 o--7--o /8 \9 o--10-o o \11 o Face colors for faces [0,1,2] are ["yellowgreen","tomato","steelblue"] and red for the weight 2 faces. Preformatted operators are stored in HexagonTile.wf_operator_dict The operator variable may be used to define the operators specifically. The operator must be a list of PauliList objects where each PauliList describes the opertors to be built for the faces as indexed above 0,1,2,3, ... If the PauliList contains k Paulis then k operators will be created for the given face. If a face is not wanted then that face should be listed as None. See HexagonTile.wf_operator_dict for examples. Args: origin (np.array): Coordinates of origin of tile (shell) qubit_count: Qubit counter. Defaults to None. qubit_data: Qubit data. Defaults to None. operators: Operators for tile faces. Defaults to None. optype (optional): Which of the listed opertor mapppings to used. Defaults to "pXZXZ". A appropriately scalled lattice basis for tiling with the HexagonTile can be accessed from [HexagonTile.u_vec, HexagonTile.v_vec] Raises: QiskitError: Unsupported operator type Returns: Shell: Returns a Checker Board tile (shell) with provided origin """ if operators is None: try: operators = HexagonTile.wf_operator_dict[optype] except KeyError as key_error: raise QiskitError(f"Unsupported operator type: {optype}") from key_error return TileFactory( origin=origin, wf_coordinates=HexagonTile.wf_coordinates, wf_q_indices=HexagonTile.wf_q_indices, wf_loop_indicator=HexagonTile.wf_loop_indicator, faces_wf_components=HexagonTile.faces_wf_components, num_qubits=HexagonTile.num_qubits, face_colors=HexagonTile.face_colors, qubit_count=qubit_count, qubit_data=qubit_data, operators=operators, )