noise/lib.py
class Process
Factories for common multi-qudit noise processes.
Each constructor returns a Channel in Kraus form
GAD
Build an
Constructs tensor-product Kraus operators from single-site
def GAD(d: int, n: int, Y: float, p: float, order: int, group: bool) -> Channel [static]Implementation
def GAD(d: int, n: int, Y: float, p: float, order: int=1, group: bool=False) -> Channel:
assert isinstance(p, float), 'p must be a float'
assert isinstance(Y, float), 'Y must be a float'
assert p <= 1 and Y <= 1, 'p,Y must be in [0, 1]'
def _op_gen(error_word: Sequence[str]) -> Any:
temp: list[Any] = []
for tag in error_word:
order = int(tag[-1])
if 'a' in tag:
temp.append(GAD.A(order, d, Y, p))
elif 'r' in tag:
temp.append(GAD.R(order, d, Y, p))
else:
raise ValueError(f'Unknown tag {tag} in error word {error_word}')
return mkron(temp)
keys = list(permut(['a0', 'a1', 'r0', 'r1'] * n, n))
Ak = [_op_gen(key) for key in keys]
Ek: list[list[int]] = [[] for _ in range((order + 1) * 2 - 1)]
for key in keys:
s = np.sum([int(Em[-1]) for Em in key])
if s <= order and (not np.all(np.isclose(Ak[keys.index(key)], 0, atol=1e-08))):
if any(('r' in i and int(i[-1]) > 0 for i in key)):
Ek[2 * s - 1].append(keys.index(key))
else:
Ek[2 * s - 0].append(keys.index(key))
op_ch = Channel(Ak)
op_ch.correctables = Ek if group else ungroup(Ek)
return op_chAD
Build an
This is the
def AD(d: int, n: int, Y: float, order: int, group: bool) -> Channel [static]Implementation
def AD(d: int, n: int, Y: float, order: int=1, group: bool=False) -> Channel:
assert isinstance(Y, float), 'Y must be a float'
assert Y <= 1, 'Y must be in [0, 1]'
def _op_gen(error_word: Sequence[str]) -> Any:
individual = [GAD.A(int(tag[-1]), d, Y) for tag in error_word]
return mkron(individual)
keys = list(permut(['a0', 'a1'] * n, n))
Ak = [_op_gen(key) for key in keys]
Ek: list[list[int]] = [[] for _ in range(order + 1)]
for key in keys:
s = np.sum([int(Em[-1]) for Em in key])
if s <= order and (not np.all(np.isclose(Ak[keys.index(key)], 0, atol=1e-08))):
Ek[s].append(keys.index(key))
op_ch = Channel(Ak)
op_ch.correctables = Ek if group else ungroup(Ek)
return op_chPauli
Build an
Constructs tensor-product Kraus operators from
def Pauli(n: int, paulis: Optional[list[str]], p: Optional[list[float]], order: int, group: bool) -> Channel [static]Implementation
def Pauli(n: int, paulis: Optional[list[str]]=None, p: Optional[list[float]]=None, order: int=1, group: bool=False) -> Channel:
if paulis is None:
paulis = ['X', 'Y', 'Z']
if p is None:
p = [0.0, 0.0, 0.0]
funcs = {'I': Pauli.I, 'X': lambda p: Pauli.X(p[0]), 'Y': lambda p: Pauli.Y(p[1]), 'Z': lambda p: Pauli.Z(p[2])}
weight = {'I': 0, 'X': 1, 'Y': 1, 'Z': 1}
def _op_gen(word: Sequence[str]) -> Any:
return mkron([funcs[gate](p) for gate in word])
keys = permut((['I'] + paulis) * n, n)
Ak = [_op_gen(key) for key in keys]
Ek: list[list[int]] = [[] for _ in range(order + 1)]
for key in keys:
s = np.sum([weight[i] for i in key])
if s <= order and (not np.all(np.isclose(Ak[keys.index(key)], 0, atol=1e-08))):
Ek[s].append(keys.index(key))
op_ch = Channel(Ak)
op_ch.correctables = Ek if group else ungroup(Ek)
return op_chpermut
Return unique length-
Used to enumerate Kraus-operator “words” (tensor-product factor choices).
def permut(lst: List[str], n: int) -> List[List[str]]Implementation
def permut(lst: List[str], n: int) -> List[List[str]]:
if n > len(lst):
raise ValueError('n must be less than or equal to the length of lst')
return [list(p) for p in set(permutations(lst, n))]mkron
Compute a left-to-right Kronecker product
This is used to build many-body Kraus operators from single-site ones.
def mkron(args: Sequence[Any]) -> AnyImplementation
def mkron(args: Sequence[Any]) -> Any:
result = args[0]
for i in range(1, len(args)):
result = np.kron(result, args[i])
return resultungroup
No Definition provided
def ungroup(lst: List[List[Any]]) -> List[Any]Implementation
def ungroup(lst: List[List[Any]]) -> List[Any]:
return [item for sublist in lst for item in sublist]