Source code for ssip.merge_result
from dataclasses import dataclass
import numpy as np
from ssip.basic_functions import (
BinMatrix,
CSScode,
column_echelon_form,
find_paired_basis,
find_X_basis,
find_Z_basis,
image_basis_calc,
kernel_basis_calc,
multiply_F2,
vec_addition,
)
[docs]
@dataclass
class MergeResult:
"""A collection of data which informs the user about a merge, or
multiple merges, which were performed.
Attributes:
Code: The output merged code.
MergeMap: The map on qubits from the input to output code.
NewZStabs: The indices of any new Z stabiliser generators.
NewXStabs: The indices of any new X stabiliser generators.
NewQubits: The indices of any new data qubits.
NewZLogicals: A basis for the space of new Z logicals
introduced by the merge, if there are any.
NewXLogicals: A basis for the space of new X logicals
introduced by the merge, if there are any.
OldZLogicals: A basis for the space of old Z logicals
retained by the merge, if there are any.
OldXLogicals: A basis for the space of old X logicals
retained by the merge, if there are any.
"""
Code: CSScode
# if the merge was a Z-merge, this is the chain map at degree 1;
# if X-merge, cochain map at degree 1
MergeMap: BinMatrix
NewZStabs: list
NewXStabs: list
NewQubits: list
NewZLogicals: list
NewXLogicals: list
OldZLogicals: list
OldXLogicals: list
[docs]
def find_logical_splitting(
old_code: CSScode,
new_code: CSScode,
merge_map: BinMatrix,
num_before_logicals: int,
num_after_logicals: int,
num_merges: int = 1,
basis: str = "Z",
):
if basis != "Z" and basis != "X":
raise ValueError("Must enter Z or X basis.")
num_new_logicals = num_after_logicals - num_before_logicals + num_merges
hom_before = None
if basis == "Z":
hom_before = np.array(find_Z_basis(old_code)).T
else:
hom_before = np.array(find_X_basis(old_code)).T
if hom_before.shape[1] != num_before_logicals:
raise RuntimeError("Dimensions do not match up when returning merge data.")
hom_before_in_merged_code = multiply_F2(merge_map, hom_before)
im_basis_after = None
if basis == "Z":
im_basis_after = np.array(image_basis_calc(new_code.PZ.T))
else:
im_basis_after = np.array(image_basis_calc(new_code.PX.T))
Q = np.array(kernel_basis_calc(im_basis_after))
ker_before_in_after_hom = multiply_F2(Q, hom_before_in_merged_code)
mat1 = column_echelon_form(ker_before_in_after_hom)
num_old_logicals = num_before_logicals - num_merges
vecs_to_add = [0] * num_old_logicals
height = ker_before_in_after_hom.shape[0]
for i in np.arange(num_old_logicals):
v = [0] * (mat1.shape[0] - height)
for j in np.arange(height, mat1.shape[0]):
v[j - height] = mat1[j][i]
vecs_to_add[i] = v
logical_basis = [0] * num_old_logicals
for i in np.arange(num_old_logicals):
vecs = [
list(hom_before_in_merged_code[:, j])
for j in np.arange(len(vecs_to_add[i]))
if vecs_to_add[i][j]
]
logical_basis[i] = vec_addition(vecs)
S = np.array(kernel_basis_calc(ker_before_in_after_hom.T))
if basis == "Z":
ker_after = np.array(kernel_basis_calc(new_code.PX)).T
else:
ker_after = np.array(kernel_basis_calc(new_code.PZ)).T
ker_after_quotient_old_logicals = multiply_F2(S, multiply_F2(Q, ker_after))
mat = column_echelon_form(ker_after_quotient_old_logicals, True)
height = ker_after_quotient_old_logicals.shape[0]
vecs_to_add = [0] * num_new_logicals
for i in np.arange(num_new_logicals):
v = [0] * (mat.shape[0] - height)
for j in np.arange(height, mat.shape[0]):
v[j - height] = mat[j][i]
vecs_to_add[i] = v
gauge_basis = [0] * num_new_logicals
for i in np.arange(num_new_logicals):
vecs = [
list(ker_after[:, j])
for j in np.arange(len(vecs_to_add[i]))
if vecs_to_add[i][j]
]
gauge_basis[i] = vec_addition(vecs)
if basis == "Z":
new_Z_logicals = gauge_basis
old_Z_logicals = logical_basis
total_Z_basis = gauge_basis + logical_basis
trial_X_basis = find_X_basis(new_code)
total_X_basis = find_paired_basis(total_Z_basis, trial_X_basis)
new_X_logicals = total_X_basis[:num_new_logicals]
old_X_logicals = total_X_basis[num_new_logicals:]
return (new_Z_logicals, new_X_logicals, old_Z_logicals, old_X_logicals)
else:
new_X_logicals = gauge_basis
old_X_logicals = logical_basis
total_X_basis = gauge_basis + logical_basis
trial_Z_basis = find_Z_basis(new_code)
total_Z_basis = find_paired_basis(total_X_basis, trial_Z_basis)
new_Z_logicals = total_Z_basis[:num_new_logicals]
old_Z_logicals = total_Z_basis[num_new_logicals:]
return (new_Z_logicals, new_X_logicals, old_Z_logicals, old_X_logicals)