Skip to content

noise/index.py

class Error

A Kraus/error operator represented as a NumPy ndarray subclass.

Conceptually, an error operator E acts on a state as ρEρE, and a noise channel is typically a collection {Ek}.

nametypedefault
correctableboolFalse
dintNone
namestrNone
paramsdict[str, Any]None

class Channel

A quantum channel represented in Kraus form using localized Gates.

For Kraus operators {Ek}, the channel acts as Φ(ρ)=kEkρEk.

nametypedefault
correctableslist[Union[int, list[int]]]None
opslist[list[Gate]]None

init

No Definition provided

py
def __init__(self: Any, ops: list[list[Gate]]) -> Any
Implementation
python
def __init__(self, ops: list[list[Gate]]):
    assert isinstance(ops, list) and len(ops) > 0, 'ops must be a list of Gate lists'
    self.ops = ops
    self.correctables = []
    first = ops[0][0]
    self.d: int = first.total_dim

run

Apply the channel in Kraus form: ρkEkρEk. Executes localized gate operations via forwardd.

py
def run(self: Any, rho: Union['State', pt.Tensor, np.ndarray]) -> pt.Tensor
Implementation
python
def run(self, rho: Union['State', pt.Tensor, np.ndarray]) -> pt.Tensor:
    if hasattr(rho, 'isDensity'):
        if not rho.isDensity:
            rho = rho.density()
    elif isinstance(rho, pt.Tensor) and rho.ndim == 1:
        rho = rho.view(-1, 1) @ pt.conj(rho.view(1, -1))
        rho = rho.to(pt.complex64)
    tensor_rho = getattr(rho, 'tensor', rho)
    if isinstance(tensor_rho, np.ndarray):
        if tensor_rho.ndim == 1:
            tensor_rho = np.outer(tensor_rho, tensor_rho.conj())
        tensor_rho = pt.from_numpy(tensor_rho)
    device = self.ops[0][0].device if len(self.ops[0]) > 0 else 'cpu'
    tensor_rho = tensor_rho.to(device=device, dtype=C64)
    rho_out = pt.zeros_like(tensor_rho)
    for kraus_word in self.ops:
        rho_branch = tensor_rho.clone()
        for g in kraus_word:
            rho_branch = g.forwardd(rho_branch)
        rho_out += rho_branch
    return rho_out

correctable

Return the subset(s) of Kraus operators marked as correctable (if any).

py
def correctable(self: Any) -> Any
Implementation
python
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[list[Gate]]] = []
        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 kEkEk=I (approx.).

py
def isTP(self: Any) -> bool
Implementation
python
def isTP(self) -> bool:
    first = self.ops[0][0]
    total = pt.zeros((self.d, self.d), dtype=C64, device=first.device)
    for word in self.ops:
        Ek = self._materialize(word)
        total += Ek.conj().T @ Ek
    identity = pt.eye(self.d, dtype=C64, device=first.device)
    return bool(pt.allclose(total, identity, atol=1e-08))

isCP

Check complete-positivity (CP) by verifying Choi matrix is PSD.

py
def isCP(self: Any) -> bool
Implementation
python
def isCP(self) -> bool:
    J = self.toChoi()
    eig = pt.linalg.eigvalsh(J.to(pt.complex128))
    return bool((eig.real >= -1e-05).all().item())

isCPTP

Check if the channel is CPTP (completely positive and trace preserving).

py
def isCPTP(self: Any) -> bool
Implementation
python
def isCPTP(self) -> bool:
    return self.isCP and self.isTP

toChoi

Compute the Choi matrix J(Φ)=i,j|ij|Φ(|ij|).

py
def toChoi(self: Any) -> pt.Tensor
Implementation
python
def toChoi(self) -> pt.Tensor:
    d = self.d
    J = pt.zeros((d * d, d * d), dtype=pt.complex128)
    basis = pt.eye(d, dtype=pt.complex128)
    for i in range(d):
        for j in range(d):
            Eij = pt.outer(basis[i], basis[j])
            J += pt.kron(Eij, self.run(Eij).to(pt.complex128))
    return J

toSuperop

Compute the superoperator S such that vec(Φ(ρ))=Svec(ρ), i.e. S=kEkEk.

py
def toSuperop(self: Any) -> pt.Tensor
Implementation
python
def toSuperop(self) -> pt.Tensor:
    mats = [self._materialize(word).to(pt.complex128) for word in self.ops]
    d = self.d
    S = pt.zeros((d * d, d * d), dtype=pt.complex128)
    for Ek in mats:
        S += pt.kron(Ek, Ek.conj())
    return S

toStinespring

Compute a Stinespring isometry V by stacking Kraus operators.

Constructs V:CdCdCr with V=k|kEk, represented as a (dr)×d matrix.

py
def toStinespring(self: Any) -> pt.Tensor
Implementation
python
def toStinespring(self) -> pt.Tensor:
    K = len(self.ops)
    d = self.d
    r = K
    V = pt.zeros((d * r, d), dtype=pt.complex128)
    for n, O in enumerate(self.ops):
        Ek = self._materialize(O).to(pt.complex128)
        V[n * d:(n + 1) * d, :] = Ek
    return V

Ak

Alias for the Kraus list {Ek}

py
def Ak(self: Any) -> list[Error]
Implementation
python
def Ak(self) -> list[Error]:
    return self.ops

class Multiplex

Container class for multiple channels, e.g. for different noise models or parameter regimes. Allows us to run multiple channels on a state successively.

nametypedefault
channelslist['Channel']None

init

No Definition provided

py
def __init__(self: Any, channels: list[Union['Channel', 'Multiplex']]) -> Any
Implementation
python
def __init__(self, channels: list[Union['Channel', 'Multiplex']]):
    assert isinstance(channels, list) and len(channels) > 0, 'channels must be List[Channel] or List[Multiplex]'
    clist: list['Channel'] = []
    for ch in channels:
        if isinstance(ch, Multiplex):
            clist.extend(ch.channels)
        else:
            clist.append(ch)
    self.channels = clist

run

Apply channels in sequence: ρΦnΦ1(ρ).

py
def run(self: Any, rho: Union['State', pt.Tensor, np.ndarray]) -> pt.Tensor
Implementation
python
def run(self, rho: Union['State', pt.Tensor, np.ndarray]) -> pt.Tensor:
    result = rho
    for channel in self.channels:
        result = channel.run(result)
    return result