You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This example demonstrates how to use TranslationalMaps to create rotated surface codes.
This example uses the low level functions to create rotated surface codes. These ideas can then be wrapped in
higher level functions to do the work in a lot less steps. I notebook for this example will be added shortly along with how to access this classes.
The classes used below are modified or new classes in quantum_info. They are currently not in the standard quantum_info module. Once all the appropriate architectural decisions have been made for the framework then they can be added. These prototype classes will be made available though. (to add)
import numpy as np
from qiskit.quantum_info.operators.symplectic import Pauli
from qiskit.quantum_info.operators.symplectic import TranslationMap
from qiskit.quantum_info.operators.symplectic import PauliRep
from qiskit.quantum_info.operators.symplectic import PauliList
We start with a function that maps matrix coordinates of the rotated surface code
to integer coordinates. The function below is a general function that generates the function
needed for any given dxd rotated surface code
def matrix_to_indices_gen(d):
"""Translate matrix data qubit labels/coordinates to indices for the square
rotated surface code
A generalized function to create a function that translates matrix data qubit
labels/coordinates of the dxd surface code to single index representation
Square Rotated Surface Code of dimension d (d^2 data quibts) at positions x
(0,0)=0 x (0,1)=1 x (0,2)=2 x ... (0,d-1)=d-1 x
(1,0)=d x (1,1)=d+1 x (1,2)=d+2 x ... (1,d-1)=d+d-1 x
...
(d-1,0)=d x (d-1,1)=d+1 x (d-1,2)=d+2 x ... (d-1,d-1)=(d-1)d+d-1 x
return map: (x,y) -> (d*x)+y
Args:
d (integer): dimension of dxd surface code
"""
def code_function(x,y):
return (d*x)+y
return code_function
Create function to translate matrix data qubit labels/coordinates to indices for the square
for 3x3 rotated surface code
matrix_to_indice_funct = matrix_to_indices_gen(3)
An is_index method for the matrix coordinates is used to detect when an index is passed or and array on indices
def is_index_2tuple(index):
index = np.asarray(index)
if index.shape == (2,):
return True
else:
return False
Create an iterator for the domain of the matrix_to_indice_funct function/map. This allows the Map to either
use the provided function to translate matrix coordinates into internal integers coordinates or use a lookup table.
Create the QubitMap for the matrix index to integer index function. A QubitMap is a specific type of TranslationMap that
always maps labels to integer indices. In this case we also create the lookup table for the Map (not necessary though)
As a side example we can also create a TranslationMap that maps cartesian coordinates/indices for the rotated
surface code qubits to matrix indices as follows:
def cc_to_matrix_funct(coord, base=(0,0)):
"""Translate cartesian coordinates of data qubit labels/coordinates to matrix labels/coordinates
for the square rotated surface code
Square Rotated Surface Code of dimension d (d^2 data quibts) at positions x, base = (a,b)
(cc coordinate) = (matrix coordinate)
(0,0)=(0,0) x (1,0)=(0,1) x (2,0)=(0,2) x ... (d-1,0)=(0,d-1) x
(0,-1)=(1,0) x (1,-1)=(1,1) x (2,-1)=(1,2) x ... (d-1,-1)=(1,d-1) x
...
(0, -(d-1))=(d-1,0) x =(1,-(d-1))=(d-1,1) x (2,-(d-1))=(d-1,2) x ... (d-1,-(d-1))=(d-1,d-1) x
Setting base = (a,b) translate the cartesian coordinates by (a,b) first
return map: (x,y)-(a,b) -> (-y,x)
Args:
coord (tuple): coordinate (x,y) in R2
base (tuple): [Optional] Translate coordinate by tupl. Default = (0,0)
Returns:
[tuple]: Matrix cordinate of provided cartesian coordinate
"""
return (-coord[1]+base[1],coord[0]-base[0])
Now create the TranslationMap for the cartesian coordinate to matrix function
We can now start creating the stabilizers for the rotated surface code. We start by creating some helper functions.
First to calculate the matrix coordinates of a single square (weight four) stabilizers:
def square(c):
"""Calculate matrix coordinates for square stabilizers in plane rotated surface codes
Args:
c (tuple): matrix coordinate of upper left corner of square stabilizer
Returns:
[list]: list of coordinates (tuples) of square stabilizer
"""
return [(c[0],c[1]),(c[0]+1,c[1]),(c[0],c[1]+1),(c[0]+1,c[1]+1)]
and now to find the coordinates of all the square stabilizers
def square_stabilizers_coord(d, offset=False):
"""Generate the matrix coordinates of the stabilizers for the dxd rotated surface code
The offset parameter determines which of the two types of stabilizers you get.
Offset = False -> the stabilizers returned start at the top left and cherkerboard out
_
/ \
--------
|x | | ...
--------
.
.
.
Offset = True -> the stabilizer returned start offset by one from the top left
and checkerboard out
_
/ \
--------
| | x | ...
--------
.
.
.
Args:
d (integer): size of dxd rotated surface code
offset (bool): True for offset from top left, False if not. Default is False
Returns:
[list]: list of one of two types of square stabilizer coordinates starting from offset
"""
stab_coord = []
for i in range(d-1):
for j in range(d-1):
if (i+j)%2:
if offset:
stab_coord.append(square((i,j)))
else:
if not offset:
stab_coord.append(square((i,j)))
return stab_coord
Generate the coordinates for the square stabilizers
Here we choose to say that the top left square stabilizer is a X stabilizer
Translate the coordinates to indices for the square stabilizers
square_x_stab_indices = [map(matrix_to_indice_map, stab) for stab in square_x_stab_coord]
square_z_stab_indices = [map(matrix_to_indice_map, stab) for stab in square_z_stab_coord]
Translate the indices to symplectic vectors for the square stabilizers
square_x_stab_symp = np.asarray([indices_to_boolean(stab, 3**2) for stab in square_x_stab_indices])
square_z_stab_symp = np.asarray([indices_to_boolean(stab, 3**2) for stab in square_z_stab_indices])
We now need to generate the weight two stabilizers. Again we use some helper functions:
def half_square(d, side="top", offset=False):
"""Calculate matrix coordinate for edge stabilizers (2 quibt stabilizers) of
dxd rotated surface code.
The side parameter determines which side is produced: top, left, right, bottom
The offset parameter determines if the surface code is left or right handled
Offset = True (right handed)
_
/ \
--------
| | | ...
--------
.
.
.
Offset = False (left handed)
_
/ \
--------
| | | ...
--------
.
.
.
Args:
d ([type]): [description]
side (str, optional): [description]. Defaults to "top".
offset (bool, optional): [description]. Defaults to False.
Raises:
QiskitError: Unknown side
Returns:
(list): list of lists of pairs of tuples representing the edge stabilizer matrix coordinates
"""
if side == "top":
return [[(0, i+offset), (0, i+1+offset)] for i in range(d-2) if i%2 == 0]
elif side == "bottom":
return [[(d-1,i+1-offset),(d-1,i+2-offset)] for i in range(d-2) if i%2 == 0]
elif side == "left":
return [[(i+1-offset,0),(i+2-offset,0)] for i in range(d-2) if i%2 == 0]
elif side == "right":
return [[(i+offset,d-1),(i+1+offset,d-1)] for i in range(d-2) if i%2 == 0]
else:
raise QiskitError("Unknown side, Use one of <top, left, right, bottom>")
def half_stab_coords(d, offset=False, pair="TB"):
if pair == "TB":
sides = ["top", "bottom"]
else:
sides = ["left", "right"]
stab_coord = [half_square(d, side=side, offset=offset) for side in sides]
return [item for sublist in stab_coord for item in sublist]
Generate the coordinates for the weight 2 stabilizers. We previsouly chose that the top left square stabilizer is a X stabilizer. We will choose the surface code to be a left handed and therefore the top and bottom weight two stabilizers will be Z stabilizers and the left and right weight two stabilizers will be X stabilizers
Translate the coordinates to indices for the weight two stabilizers
edge_x_stab_indices = [map(matrix_to_indice_map, stab) for stab in edge_x_stab_coord]
edge_z_stab_indices = [map(matrix_to_indice_map, stab) for stab in edge_z_stab_coord]
Translate the indices to symplectic vectors for the square stabilizers
edge_x_stab_symp = np.asarray([indices_to_boolean(stab, 3**2) for stab in edge_x_stab_indices])
edge_z_stab_symp = np.asarray([indices_to_boolean(stab, 3**2) for stab in edge_z_stab_indices])
Generate the Pauli's for the weight two stabilizers
Collect the non iI generators for the 3x3 plan rotated surface code where the top left square stabilizer is a X stabilizer and the surface is left handed
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Creating a rotated surface code
This example demonstrates how to use TranslationalMaps to create rotated surface codes.
This example uses the low level functions to create rotated surface codes. These ideas can then be wrapped in
higher level functions to do the work in a lot less steps. I notebook for this example will be added shortly along with how to access this classes.
The classes used below are modified or new classes in quantum_info. They are currently not in the standard quantum_info module. Once all the appropriate architectural decisions have been made for the framework then they can be added. These prototype classes will be made available though. (to add)
We start with a function that maps matrix coordinates of the rotated surface code
to integer coordinates. The function below is a general function that generates the function
needed for any given dxd rotated surface code
Create function to translate matrix data qubit labels/coordinates to indices for the square
for 3x3 rotated surface code
An is_index method for the matrix coordinates is used to detect when an index is passed or and array on indices
Create an iterator for the domain of the matrix_to_indice_funct function/map. This allows the Map to either
use the provided function to translate matrix coordinates into internal integers coordinates or use a lookup table.
Create the QubitMap for the matrix index to integer index function. A QubitMap is a specific type of TranslationMap that
always maps labels to integer indices. In this case we also create the lookup table for the Map (not necessary though)
As a side example we can also create a TranslationMap that maps cartesian coordinates/indices for the rotated
surface code qubits to matrix indices as follows:
Now create the TranslationMap for the cartesian coordinate to matrix function
We can now start creating the stabilizers for the rotated surface code. We start by creating some helper functions.
First to calculate the matrix coordinates of a single square (weight four) stabilizers:
and now to find the coordinates of all the square stabilizers
Generate the coordinates for the square stabilizers
Here we choose to say that the top left square stabilizer is a X stabilizer
Translate the coordinates to indices for the square stabilizers
Translate the indices to symplectic vectors for the square stabilizers
Generate the Pauli's for the square stabilizers
We now need to generate the weight two stabilizers. Again we use some helper functions:
Generate the coordinates for the weight 2 stabilizers. We previsouly chose that the top left square stabilizer is a X stabilizer. We will choose the surface code to be a left handed and therefore the top and bottom weight two stabilizers will be Z stabilizers and the left and right weight two stabilizers will be X stabilizers
Translate the coordinates to indices for the weight two stabilizers
Translate the indices to symplectic vectors for the square stabilizers
Generate the Pauli's for the weight two stabilizers
Collect the non iI generators for the 3x3 plan rotated surface code where the top left square stabilizer is a X stabilizer and the surface is left handed
Create the Stabilizer group given these non iI generators
Create the Stabilizer Code from the Stabilizer Group
Beta Was this translation helpful? Give feedback.
All reactions