|
| 1 | +from qsurface.codes.elements import AncillaQubit |
| 2 | +from ..toric.sim import PerfectMeasurements as ToricPM, FaultyMeasurements as ToricFM |
| 3 | + |
| 4 | + |
| 5 | +class PerfectMeasurements(ToricPM): |
| 6 | + # Inherited docstring |
| 7 | + |
| 8 | + name = "rotated" |
| 9 | + |
| 10 | + _syndrome_dict = { 0: "x", 1: "z" } |
| 11 | + |
| 12 | + def init_surface(self, z: float = 0, **kwargs): |
| 13 | + """Initializes the rotated surface code on layer ``z``. |
| 14 | +
|
| 15 | + Parameters |
| 16 | + ---------- |
| 17 | + z : int or float, optional |
| 18 | + Layer of qubits, ``z=0`` for perfect measurements. |
| 19 | + """ |
| 20 | + self.ancilla_qubits[z], self.data_qubits[z], self.pseudo_qubits[z] = {}, {}, {} |
| 21 | + parity = self.init_parity_check |
| 22 | + |
| 23 | + # Add data qubits to surface |
| 24 | + for y in range(self.size[1]): |
| 25 | + for x in range(self.size[0]): |
| 26 | + self.add_data_qubit((x, y), z=z, **kwargs) |
| 27 | + |
| 28 | + # Add ancilla qubits to surface |
| 29 | + if self.size[1] % 2 == 1: |
| 30 | + for y in range(self.size[1] - 1): |
| 31 | + for x in range(self.size[0]): |
| 32 | + parity(self.add_ancilla_qubit((0.5 - 1 * (y%2) + x, y + 0.5), z=z, state_type=self._syndrome_dict[x%2], **kwargs)) |
| 33 | + else: |
| 34 | + commute = -1 |
| 35 | + for y in range(self.size[1] - 1): |
| 36 | + for x in range(self.size[0] + commute): |
| 37 | + commute *= -1 |
| 38 | + parity(self.add_ancilla_qubit((0.5 - 1 * (y%2) + x, y + 0.5), z=z, state_type=self._syndrome_dict[x%2], **kwargs)) |
| 39 | + |
| 40 | + outer_qubits = self.size[0] // 2 |
| 41 | + |
| 42 | + for x in range(outer_qubits): # for first and last row |
| 43 | + parity(self.add_ancilla_qubit((0.5 + 2*x, -0.5), z=z, state_type=self._syndrome_dict[1], **kwargs)) |
| 44 | + parity(self.add_ancilla_qubit((self.size[0] - 1.5 - 2*x, self.size[1] - 0.5), z=z, state_type=self._syndrome_dict[1], **kwargs)) |
| 45 | + |
| 46 | + # Add pseudo qubits to surface (boundaries) |
| 47 | + if self.size[1] % 2 == 1: |
| 48 | + for y in range(self.size[1] - 1): |
| 49 | + if y % 2 == 0: |
| 50 | + parity(self.add_pseudo_qubit((-0.5, y + 0.5), z=z, state_type=self._syndrome_dict[1], **kwargs)) |
| 51 | + else: |
| 52 | + parity(self.add_pseudo_qubit((self.size[0] - 0.5, y + 0.5), z=z, state_type=self._syndrome_dict[1], **kwargs)) |
| 53 | + else: |
| 54 | + for y in range(self.size[1] - 1): |
| 55 | + if y % 2 == 0: |
| 56 | + parity(self.add_pseudo_qubit((-0.5, y + 0.5), z=z, state_type=self._syndrome_dict[1], **kwargs)) |
| 57 | + parity(self.add_pseudo_qubit((self.size[0] - 0.5, y + 0.5), z=z, state_type=self._syndrome_dict[1], **kwargs)) |
| 58 | + |
| 59 | + for x in range(self.size[0]+1): |
| 60 | + if x % 2 == 0 or x >= (outer_qubits)*2: |
| 61 | + parity(self.add_pseudo_qubit((x - 0.5, - 0.5), z=z, state_type=self._syndrome_dict[x % 2], **kwargs)) |
| 62 | + parity(self.add_pseudo_qubit((self.size[0] - 0.5 - x, self.size[1] - 0.5), z=z, state_type=self._syndrome_dict[x % 2], **kwargs)) |
| 63 | + |
| 64 | + def init_parity_check(self, ancilla_qubit: AncillaQubit, **kwargs): |
| 65 | + """Initiates a parity check measurement. |
| 66 | +
|
| 67 | + For every ancilla qubit on ``(x,y)``, four neighboring data qubits are entangled for parity check measurements. |
| 68 | +
|
| 69 | + Parameters |
| 70 | + ---------- |
| 71 | + ancilla_qubit : `~.codes.elements.AncillaQubit` |
| 72 | + Ancilla qubit to initialize. |
| 73 | + """ |
| 74 | + (x, y), z = ancilla_qubit.loc, ancilla_qubit.z |
| 75 | + checks = { |
| 76 | + (0.5, 0.5): ((x + 0.5), (y+0.5)), |
| 77 | + (-0.5, 0.5): ((x - 0.5), (y+0.5)), |
| 78 | + (0.5, -0.5): ((x + 0.5), (y - 0.5)), |
| 79 | + (-0.5, -0.5): ((x - 0.5), (y - 0.5)), |
| 80 | + } |
| 81 | + for key, loc in checks.items(): |
| 82 | + if loc in self.data_qubits[z]: |
| 83 | + self.entangle_pair(self.data_qubits[z][loc], ancilla_qubit, key) |
| 84 | + |
| 85 | + def init_logical_operator(self, **kwargs): |
| 86 | + """Initiates the logical operators [x,z] of the rotated code.""" |
| 87 | + operators = { |
| 88 | + "x": [self.data_qubits[self.decode_layer][(i, 0)].edges["x"] for i in range(self.size[0])], |
| 89 | + "z": [self.data_qubits[self.decode_layer][(0, i)].edges["z"] for i in range(self.size[1])], |
| 90 | + } |
| 91 | + self.logical_operators = operators |
| 92 | + |
| 93 | + |
| 94 | +class FaultyMeasurements(ToricFM, PerfectMeasurements): |
| 95 | + # Inherited docstring |
| 96 | + |
| 97 | + pass |
0 commit comments