qec/codes.py
class Code
A codeword is an
For now Code only supports uniform dimension codes. So a dim of means only codewords of the form
| name | type | default |
|---|---|---|
| codewords | pt.Tensor | None |
| dim | int | None |
| dits | int | None |
| gates | Gategen | None |
| width | int | None |
init
No Definition provided
def __init__(self: Any, codewords: pt.Tensor, d: int) -> AnyImplementation
def __init__(self, codewords: pt.Tensor, d: int=None):
assert codewords.ndim >= 2, 'Codewords must be at least 2D tensors'
self.codewords = codewords
self.dim = codewords.shape[0]
width = codewords.shape[1]
_d = d if d is not None else self.dim
self.dits = int(round(ma.log(width) / ma.log(_d)))
self.gates = Gategen(_d)toTensor
No Definition provided
def toTensor(self: Any) -> AnyImplementation
def toTensor(self):
return self.codewordsisValid
No Definition provided
def isValid(code: Any) -> Any [static]Implementation
def isValid(code):
norms = pt.norm(code, dim=1)
if not pt.allclose(norms, pt.ones_like(norms)):
print('Norms:', pt.round(norms, decimals=2))
raise ValueError('Codewords are not normalized!')
ortho = code @ code.T - pt.eye(code.shape[0])
if not pt.allclose(ortho, pt.zeros_like(ortho), atol=0.001):
print('Orthogonality check:', pt.round(ortho, decimals=2))
raise ValueError('Codewords are not orthogonal!')fromStabilizers
We may get ["XXY", "ZZI"], or [["X", "X", "Y"], ["Z", "Z", "I"]]. In the first case we need to split the strings into lists of characters, in the second case we can directly use the lists.
We then use the constructed matrices to construct the projector onto the code space, and then extract the codewords using either method="svd" (Singular Value Decomposition, default) or method="rrf"(Randomized Range Finder).
SVD is more stable but may be slower for large codes, while RRF is faster but may be less stable. For small codes, SVD is usually preferred.
The d parameter sets the local dimension (default 2 for qubits). For d>2, X and Z are the generalized Weyl operators from Gategen.
def fromStabilizers(stabilizers: list[str] | list[list[str]], d: int, method: Any, numpy: Any) -> 'Code' [static]Implementation
def fromStabilizers(stabilizers: list[str] | list[list[str]], d: int=2, method='svd', numpy=False) -> 'Code':
assert method in ['svd', 'rrf'], f"method must be 'svd' or 'rrf', got '{method}'"
if isinstance(stabilizers[0], str):
stabilizers = [list(s) for s in stabilizers]
gg = Gategen(dim=d)
ops = {'I': pt.eye(d, dtype=C64), 'X': gg.X.tensor.to(C64), 'Z': gg.Z.tensor.to(C64)}
proj = Projector([composite(s, ops) for s in stabilizers])
if method == 'svd':
_, S, Vh = LA.svd(proj)
code = Vh[pt.isclose(S, pt.tensor(1.0))]
elif numpy:
code = SVD_RRF_np(proj)
else:
code = SVD_RRF(proj)
Code.isValid(code)
return Code(code, d=d)composite
No Definition provided
def composite(stabilizer: list[str], ops: dict) -> pt.TensorImplementation
def composite(stabilizer: list[str], ops: dict=None) -> pt.Tensor:
if ops is None:
ops = Pauli
mat = ops[stabilizer[0]]
for p in stabilizer[1:]:
mat = pt.kron(mat, ops[p])
return matProjector
No Definition provided
def Projector(stabilizers: list[pt.Tensor]) -> pt.TensorImplementation
def Projector(stabilizers: list[pt.Tensor]) -> pt.Tensor:
dim = stabilizers[0].shape[0]
I = pt.eye(dim, dtype=C64)
P = I
for S in stabilizers:
P = P @ ((I + S) * 0.5)
return PSVD_RRF
No Definition provided
def SVD_RRF(P: pt.Tensor, target_rank: Any) -> pt.TensorImplementation
def SVD_RRF(P: pt.Tensor, target_rank=2) -> pt.Tensor:
Omega = pt.randn((P.shape[0], target_rank), dtype=pt.float32).to(pt.complex64)
Y = P @ Omega
Q = LA.qr(Y, mode='reduced')[0]
return Q.TSVD_RRF_np
No Definition provided
def SVD_RRF_np(P: Any, target_rank: Any) -> AnyImplementation
def SVD_RRF_np(P, target_rank=2):
P = P.cpu().numpy()
Omega = np.random.normal(size=(P.shape[0], target_rank))
Y = P @ Omega
Q = SLA.qr(Y, mode='economic', overwrite_a=True, check_finite=False)[0]
return pt.from_numpy(Q.T)