Skip to content

Commit a77ea34

Browse files
committed
revise composed channel and standard gate
1 parent b364719 commit a77ea34

File tree

3 files changed

+55
-39
lines changed

3 files changed

+55
-39
lines changed

tensorcircuit/channels.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,3 +962,26 @@ def check_rep_transformation(
962962
print("test evolution identity of kraus and superop")
963963
density_matrix3 = evol_superop(density_matrix, superop)
964964
np.testing.assert_allclose(density_matrix1, density_matrix3, atol=1e-5)
965+
966+
967+
def composedkraus(kraus1: KrausList, kraus2: KrausList) -> KrausList:
968+
"""
969+
Compose the noise channels
970+
971+
:param kraus1: One noise channel
972+
:type kraus1: KrausList
973+
:param kraus2: Another noise channel
974+
:type kraus2: KrausList
975+
:return: Composed nosie channel
976+
:rtype: KrausList
977+
"""
978+
new_kraus = []
979+
for i in kraus1:
980+
for j in kraus2:
981+
k = Gate(backend.reshapem(i.tensor) @ backend.reshapem(j.tensor))
982+
new_kraus.append(k)
983+
return KrausList(
984+
new_kraus,
985+
name="composed_channel",
986+
is_unitary=kraus1.is_unitary and kraus2.is_unitary,
987+
)

tensorcircuit/noisemodel.py

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from . import gates
99
from . import Circuit, DMCircuit
1010
from .cons import backend
11-
from .channels import KrausList
11+
from .channels import KrausList, composedkraus
1212

1313
Gate = gates.Gate
1414
Tensor = Any
@@ -39,33 +39,6 @@ def __init__(self) -> None:
3939
self.has_quantum = False
4040
self.has_readout = False
4141

42-
def composedkraus(self, kraus1: KrausList, kraus2: KrausList) -> KrausList:
43-
"""
44-
Compose the noise channels
45-
46-
:param kraus1: One noise channel
47-
:type kraus1: KrausList
48-
:param kraus2: Another noise channel
49-
:type kraus2: KrausList
50-
:return: Composed nosie channel
51-
:rtype: KrausList
52-
"""
53-
dim = backend.shape_tuple(kraus1[0].tensor)
54-
dim2 = int(2 ** (len(dim) / 2))
55-
new_kraus = []
56-
for i in kraus1:
57-
for j in kraus2:
58-
k = Gate(
59-
backend.reshape(i.tensor, [dim2, dim2])
60-
@ backend.reshape(j.tensor, [dim2, dim2])
61-
)
62-
new_kraus.append(k)
63-
return KrausList(
64-
new_kraus,
65-
name="composed_channel",
66-
is_unitary=kraus1.is_unitary and kraus2.is_unitary,
67-
)
68-
6942
def add_noise(
7043
self,
7144
gate_name: str,
@@ -82,6 +55,9 @@ def add_noise(
8255
:param qubit: the list of noisy qubit, defaults to None, indicating applying the noise channel on all qubits
8356
:type qubit: Optional[Sequence[Any]], optional
8457
"""
58+
if gate_name is not "readout":
59+
gate_name = AbstractCircuit.standardize_gate(gate_name)
60+
8561
if gate_name not in self.nc:
8662
qubit_kraus = {}
8763
else:
@@ -90,18 +66,18 @@ def add_noise(
9066
if qubit is None:
9167
if qubit_kraus:
9268
for qname in qubit_kraus:
93-
qubit_kraus[qname] = self.composedkraus(qubit_kraus[qname], kraus) # type: ignore
69+
qubit_kraus[qname] = composedkraus(qubit_kraus[qname], kraus) # type: ignore
9470
else:
9571
qubit_kraus["Default"] = kraus
9672
else:
9773
for i in range(len(qubit)):
9874
if tuple(qubit[i]) in qubit_kraus:
99-
qubit_kraus[tuple(qubit[i])] = self.composedkraus(
75+
qubit_kraus[tuple(qubit[i])] = composedkraus(
10076
qubit_kraus[tuple(qubit[i])], kraus[i]
10177
)
10278
else:
10379
if "Default" in qubit_kraus:
104-
qubit_kraus[tuple(qubit[i])] = self.composedkraus(
80+
qubit_kraus[tuple(qubit[i])] = composedkraus(
10581
qubit_kraus["Default"], kraus[i]
10682
)
10783
else:
@@ -136,6 +112,9 @@ def apply_qir_with_noise(
136112
"""
137113
quantum_index = 0
138114
for d in qir:
115+
116+
d["name"] = AbstractCircuit.standardize_gate(d["name"])
117+
139118
if "parameters" not in d: # paramized gate
140119
c.apply_general_gate_delayed(d["gatef"], d["name"])(c, *d["index"])
141120
else:

tests/test_noisemodel.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
expectation_ps_noisfy,
1010
sample_expectation_ps_noisfy,
1111
)
12+
from tensorcircuit.channels import composedkraus
1213

1314

1415
@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
@@ -59,25 +60,38 @@ def test_noisemodel(backend):
5960
value = cnoise.expectation_ps(x=[0, 1])
6061

6162
value = expectation_ps_noisfy(c, x=[0, 1], noise_conf=noise_conf, nmc=10000)
62-
np.testing.assert_allclose(value, 0.09, atol=1e-2)
63+
np.testing.assert_allclose(value, 0.09, atol=1e-1)
6364

6465
value = expectation_ps_noisfy(dmc, x=[0, 1], noise_conf=noise_conf)
65-
np.testing.assert_allclose(value, 0.09, atol=1e-2)
66+
np.testing.assert_allclose(value, 0.09, atol=1e-1)
6667

6768
# with readout_error
6869
value = sample_expectation_ps_noisfy(dmc, x=[0, 1], noise_conf=noise_conf)
69-
np.testing.assert_allclose(value, -0.11, atol=1e-2)
70+
np.testing.assert_allclose(value, -0.11, atol=1e-1)
7071

7172
value = sample_expectation_ps_noisfy(c, x=[0, 1], noise_conf=noise_conf, nmc=100000)
72-
np.testing.assert_allclose(value, -0.11, atol=1e-2)
73+
np.testing.assert_allclose(value, -0.11, atol=1e-1)
7374

75+
# test composed channel
76+
newerror = composedkraus(error1, error3)
7477
noise_conf1 = NoiseConf()
75-
newnoise = noise_conf1.composedkraus(error1, error3)
76-
noise_conf1.add_noise("rx", [newnoise, error1], [[0], [1]])
78+
noise_conf1.add_noise("rx", [newerror, error1], [[0], [1]])
7779
noise_conf1.add_noise("h", [error3, error1], [[0], [1]])
7880
noise_conf1.add_noise("x", [error3], [[0]])
7981
noise_conf1.add_noise("cnot", [error2], [[0, 1]])
8082
noise_conf1.add_noise("readout", readout_error)
8183

82-
value = expectation_ps_noisfy(c, x=[0, 1], noise_conf=noise_conf, nmc=10000)
83-
np.testing.assert_allclose(value, 0.09, atol=1e-2)
84+
value = expectation_ps_noisfy(c, x=[0, 1], noise_conf=noise_conf1, nmc=10000)
85+
np.testing.assert_allclose(value, 0.09, atol=1e-1)
86+
87+
# test standardized gate
88+
newerror = composedkraus(error1, error3)
89+
noise_conf2 = NoiseConf()
90+
noise_conf2.add_noise("Rx", [newerror, error1], [[0], [1]])
91+
noise_conf2.add_noise("H", [error3, error1], [[0], [1]])
92+
noise_conf2.add_noise("x", [error3], [[0]])
93+
noise_conf2.add_noise("cx", [error2], [[0, 1]])
94+
noise_conf2.add_noise("readout", readout_error)
95+
96+
value = expectation_ps_noisfy(c, x=[0, 1], noise_conf=noise_conf2, nmc=10000)
97+
np.testing.assert_allclose(value, 0.09, atol=1e-1)

0 commit comments

Comments
 (0)