noise/index.py
class Error
A Kraus/error operator represented as a NumPy ndarray subclass.
Conceptually, an error operator
| name | type | default |
|---|---|---|
| correctable | bool | False |
| d | int | None |
| name | str | None |
| params | dict[str, Any] | None |
class Channel
A quantum channel represented in Kraus form.
For Kraus operators
| name | type | default |
|---|---|---|
| correctables | list[Union[int, list[int]]] | None |
| d | int | None |
| ops | list[Error] | None |
init
No Definition provided
def __init__(self: Any, ops: list[Error]) -> AnyImplementation
def __init__(self, ops: list[Error]):
assert isinstance(ops, list) and len(ops) > 0, 'ops must be List[ops]'
self.ops = unnull(ops)
self.d = ops[0].d if isinstance(ops[0], Error) else int(ops[0].shape[0])
self.correctables = []run
Apply the channel in Kraus form:
def run(self: Any, rho: Union[State, np.ndarray]) -> np.ndarrayImplementation
def run(self, rho: Union[State, np.ndarray]) -> np.ndarray:
rho_arr: Any = getattr(rho, 'tensor', rho)
result = [O @ rho_arr @ O.conj().T for O in self.ops]
return np.sum(result, axis=0)correctable
Return the subset(s) of Kraus operators marked as correctable (if any).
def correctable(self: Any) -> AnyImplementation
def correctable(self) -> Any:
if not self.correctables:
return []
c0 = self.correctables[0]
if isinstance(c0, int):
idxs = [i for i in self.correctables if isinstance(i, int)]
return [self.ops[i] for i in idxs]
if isinstance(c0, list):
Ek: list[list[Error]] = []
sets = [s for s in self.correctables if isinstance(s, list)]
for s in sets:
Ek.append([self.ops[i] for i in s])
return Ek
return Exception("Please don't change correctables")isTP
Check trace-preservation (TP) via
def isTP(self: Any) -> boolImplementation
def isTP(self) -> bool:
ti = [np.trace(O.conj().T @ O) for O in self.ops]
return bool(np.isclose(sum(ti), 1.0))isCP
Check complete-positivity (CP) by verifying Choi matrix is PSD.
def isCP(self: Any) -> boolImplementation
def isCP(self) -> bool:
J = self.toChoi()
eig = np.linalg.eigvalsh(J)
return bool(np.all(eig >= -1e-08))isCPTP
Check if the channel is CPTP (completely positive and trace preserving).
def isCPTP(self: Any) -> boolImplementation
def isCPTP(self) -> bool:
return self.isCP and self.isTPtoChoi
Compute the Choi matrix
def toChoi(self: Any) -> np.ndarrayImplementation
def toChoi(self) -> np.ndarray:
d = self.d
J = np.zeros((d * d, d * d), dtype=complex)
basis = np.eye(d, dtype=complex)
for i in range(d):
for j in range(d):
Eij = np.outer(basis[:, i], basis[:, j].conj())
PhiE = self.run(Eij)
J += np.kron(Eij, PhiE)
return JtoSuperop
Compute the superoperator
def toSuperop(self: Any) -> np.ndarrayImplementation
def toSuperop(self) -> np.ndarray:
d = self.d
S = np.zeros((d * d, d * d), dtype=complex)
I = np.eye(d, dtype=complex)
for k in range(d * d):
ek = I.flatten()[k]
E = ek.reshape(d, d)
vecPhi = self.run(E).flatten()
S[:, k] = vecPhi
return StoStinespring
Compute a Stinespring isometry
Constructs
def toStinespring(self: Any) -> np.ndarrayImplementation
def toStinespring(self) -> np.ndarray:
K = len(self.ops)
d = self.d
r = K
V = np.zeros((d * r, d), dtype=complex)
for n, O in enumerate(self.ops):
V[n * d:(n + 1) * d, :] = O
return VAk
Alias for the Kraus list
def Ak(self: Any) -> list[Error]Implementation
def Ak(self) -> list[Error]:
return self.opsunnull
Filter out (approximately) zero operators.
Drops any matrix
def unnull(lst: List[np.ndarray]) -> List[np.ndarray]Implementation
def unnull(lst: List[np.ndarray]) -> List[np.ndarray]:
return [matrix for matrix in lst if not np.all(np.isclose(matrix, 0, atol=1e-08))]