1
- from tensorcircuit .tensorcircuit .abstractcircuit import AbstractCircuit
1
+ """
2
+ General Noise Model Construction.
3
+ """
4
+ import logging
5
+ from tensorcircuit .abstractcircuit import AbstractCircuit
2
6
from . import Circuit , DMCircuit
3
7
from .cons import backend
4
8
9
+ logger = logging .getLogger (__name__ )
10
+
5
11
6
12
class NoiseConf :
7
13
def __init__ (self ) -> None : # type: ignore
8
14
self .nc = {} # type: ignore
9
- self .quantum = False
10
- self .readout = False
11
- self .num_quantum = 0
15
+ self .has_quantum = False
16
+ self .has_readout = False
12
17
13
18
def add_noise (self , gate_name , kraus ): # type: ignore
14
19
self .nc [gate_name ] = kraus
15
20
if gate_name == "readout" :
16
- self .readout = True
21
+ self .has_readout = True
17
22
else :
18
- self .quantum = True
19
- self .num_quantum += 1
23
+ self .has_quantum = True
20
24
21
25
22
- def apply_qir (c , qir , noise_conf , randx = None ): # type: ignore
26
+ def apply_qir_with_noise (c , qir , noise_conf , status = None ): # type: ignore
23
27
24
28
quantum_index = 0
25
29
for d in qir :
@@ -39,74 +43,92 @@ def apply_qir(c, qir, noise_conf, randx=None): # type: ignore
39
43
40
44
else :
41
45
if d ["name" ] in noise_conf .nc :
42
- quantum_index += 1
43
46
if noise_conf .nc [d ["name" ]].is_unitary is True :
44
47
c .unitary_kraus (
45
48
noise_conf .nc [d ["name" ]],
46
49
* d ["index" ],
47
- status = randx [quantum_index - 1 ]
50
+ status = status [quantum_index ]
48
51
)
49
52
else :
50
53
c .general_kraus (
51
54
noise_conf .nc [d ["name" ]],
52
55
* d ["index" ],
53
- status = randx [quantum_index - 1 ]
56
+ status = status [quantum_index ]
54
57
)
58
+ quantum_index += 1
55
59
56
60
return c
57
61
58
62
59
- def circuit_with_noise (c , noise_conf , randx = None ): # type: ignore
63
+ def circuit_with_noise (c , noise_conf , status = None ): # type: ignore
60
64
qir = c .to_qir ()
61
65
cnew : AbstractCircuit
62
66
if isinstance (c , DMCircuit ):
63
67
cnew = DMCircuit (c ._nqubits )
64
68
else :
65
69
cnew = Circuit (c ._nqubits )
66
- cnew = apply_qir (cnew , qir , noise_conf , randx )
70
+ cnew = apply_qir_with_noise (cnew , qir , noise_conf , status )
67
71
return cnew
68
72
69
73
70
- def expectation_ps_noisfy (c , x = None , y = None , z = None , noise_conf = NoiseConf () , nmc = 1000 ): # type: ignore
74
+ def expectation_ps_noisfy (c , x = None , y = None , z = None , noise_conf = None , nmc = 1000 , status = None ): # type: ignore
71
75
72
- if noise_conf .readout is True :
73
- raise ValueError ("expectation_ps_noisfy can't support readout error." )
76
+ if noise_conf is None :
77
+ noise_conf = NoiseConf ()
78
+ else :
79
+ pass
80
+
81
+ num_quantum = c .gate_count (list (noise_conf .nc .keys ()))
74
82
83
+ if noise_conf .has_readout is True :
84
+ logger .warning ("expectation_ps_noisfy can't support readout error." )
75
85
else :
76
- if noise_conf . quantum is True :
86
+ pass
77
87
78
- # density matrix
79
- if isinstance (c , DMCircuit ):
80
- cnoise = circuit_with_noise (c , noise_conf )
81
- return cnoise .expectation_ps (x = x , y = y , z = z )
88
+ if noise_conf .has_quantum is True :
82
89
83
- # monte carlo
84
- else :
90
+ # density matrix
91
+ if isinstance (c , DMCircuit ):
92
+ cnoise = circuit_with_noise (c , noise_conf )
93
+ return cnoise .expectation_ps (x = x , y = y , z = z )
85
94
86
- def mcsim (randx ): # type: ignore
87
- cnoise = circuit_with_noise (c , noise_conf , randx )
88
- return cnoise .expectation_ps (x = x , y = y , z = z )
95
+ # monte carlo
96
+ else :
89
97
90
- mcsim_vmap = backend . vmap ( mcsim , vectorized_argnums = 0 )
91
- randx = backend . implicit_randu ([ nmc , noise_conf . num_quantum ] )
92
- value = backend . mean ( mcsim_vmap ( randx ) )
98
+ def mcsim ( status ): # type: ignore
99
+ cnoise = circuit_with_noise ( c , noise_conf , status )
100
+ return cnoise . expectation_ps ( x = x , y = y , z = z )
93
101
94
- return value
102
+ mcsim_vmap = backend .vmap (mcsim , vectorized_argnums = 0 )
103
+ if status is None :
104
+ status = backend .implicit_randu ([nmc , num_quantum ])
105
+ else :
106
+ pass
107
+ value = backend .mean (mcsim_vmap (status ))
95
108
96
- else :
97
- return c .expectation_ps (x = x , y = y , z = z )
109
+ return value
110
+
111
+ else :
112
+ return c .expectation_ps (x = x , y = y , z = z )
98
113
99
114
100
115
def sample_expectation_ps_noisfy ( # type: ignore
101
- c , x = None , y = None , z = None , noise_conf = NoiseConf () , nmc = 1000 , shots = None
116
+ c , x = None , y = None , z = None , noise_conf = None , nmc = 1000 , shots = None , status = None
102
117
):
103
118
104
- if noise_conf .readout is True :
119
+ if noise_conf is None :
120
+ noise_conf = NoiseConf ()
121
+ else :
122
+ pass
123
+
124
+ num_quantum = c .gate_count (list (noise_conf .nc .keys ()))
125
+
126
+ if noise_conf .has_readout is True :
105
127
readout_error = noise_conf .nc ["readout" ]
106
128
else :
107
129
readout_error = None
108
130
109
- if noise_conf .quantum is True :
131
+ if noise_conf .has_quantum is True :
110
132
111
133
# density matrix
112
134
if isinstance (c , DMCircuit ):
@@ -118,15 +140,18 @@ def sample_expectation_ps_noisfy( # type: ignore
118
140
# monte carlo
119
141
else :
120
142
121
- def mcsim (randx ): # type: ignore
122
- cnoise = circuit_with_noise (c , noise_conf , randx )
143
+ def mcsim (status ): # type: ignore
144
+ cnoise = circuit_with_noise (c , noise_conf , status )
123
145
return cnoise .sample_expectation_ps (
124
146
x = x , y = y , z = z , shots = shots , readout_error = readout_error
125
147
)
126
148
127
149
mcsim_vmap = backend .vmap (mcsim , vectorized_argnums = 0 )
128
- randx = backend .implicit_randu ([nmc , noise_conf .num_quantum ])
129
- value = backend .mean (mcsim_vmap (randx ))
150
+ if status is None :
151
+ status = backend .implicit_randu ([nmc , num_quantum ])
152
+ else :
153
+ pass
154
+ value = backend .mean (mcsim_vmap (status ))
130
155
return value
131
156
132
157
else :
0 commit comments