18
18
from .measurements import find_observable_groups
19
19
20
20
__all__ = [
21
- "expval_joint_sampling_grouping " ,
22
- "expval_joint_analytical " ,
23
- "expval_joint_sampling " ,
24
- "expval " ,
25
- "measure " ,
26
- "MeasureAll_Density "
21
+ "expval_joint_sampling_grouping_density " ,
22
+ "expval_joint_sampling_density " ,
23
+ "expval_joint_analytical_density " ,
24
+ "expval_density " ,
25
+ "measure_density " ,
26
+ "MeasureAll_density "
27
27
]
28
28
29
29
30
- def measure (noisedev : tq .NoiseDevice , n_shots = 1024 , draw_id = None ):
30
+ def measure_density (noisedev : tq .NoiseDevice , n_shots = 1024 , draw_id = None ):
31
31
"""Measure the target density matrix and obtain classical bitstream distribution
32
32
Args:
33
33
noisedev: input tq.NoiseDevice
@@ -62,7 +62,7 @@ def measure(noisedev: tq.NoiseDevice, n_shots=1024, draw_id=None):
62
62
return distri_all
63
63
64
64
65
- def expval_joint_sampling_grouping (
65
+ def expval_joint_sampling_grouping_density (
66
66
noisedev : tq .NoiseDevice ,
67
67
observables : List [str ],
68
68
n_shots_per_group = 1024 ,
@@ -85,7 +85,7 @@ def expval_joint_sampling_grouping(
85
85
86
86
expval_all_obs = {}
87
87
for obs_group , obs_elements in groups .items ():
88
- # for each group need to clone a new qdev and its states
88
+ # for each group need to clone a new qdev and its densities
89
89
noisedev_clone = tq .NoiseDevice (n_wires = noisedev .n_wires , bsz = noisedev .bsz , device = noisedev .device )
90
90
noisedev_clone .clone_densities (noisedev .densities )
91
91
@@ -94,7 +94,7 @@ def expval_joint_sampling_grouping(
94
94
rotation (noisedev_clone , wires = wire )
95
95
96
96
# measure
97
- distributions = measure (noisedev_clone , n_shots = n_shots_per_group )
97
+ distributions = measure_density (noisedev_clone , n_shots = n_shots_per_group )
98
98
# interpret the distribution for different observable elements
99
99
for obs_element in obs_elements :
100
100
expval_all = []
@@ -118,15 +118,70 @@ def expval_joint_sampling_grouping(
118
118
return expval_all_obs
119
119
120
120
121
- def expval_joint_sampling (
121
+ def expval_joint_sampling_density (
122
122
qdev : tq .NoiseDevice ,
123
123
observable : str ,
124
124
n_shots = 1024 ,
125
125
):
126
- return
126
+ """
127
+ Compute the expectation value of a joint observable from sampling
128
+ the measurement bistring
129
+ Args:
130
+ qdev: the noise device
131
+ observable: the joint observable, on the qubit 0, 1, 2, 3, etc in this order
132
+ Returns:
133
+ the expectation value
134
+ Examples:
135
+ >>> import torchquantum as tq
136
+ >>> import torchquantum.functional as tqf
137
+ >>> x = tq.QuantumDevice(n_wires=2)
138
+ >>> tqf.hadamard(x, wires=0)
139
+ >>> tqf.x(x, wires=1)
140
+ >>> tqf.cnot(x, wires=[0, 1])
141
+ >>> print(expval_joint_sampling(x, 'II', n_shots=8192))
142
+ tensor([[0.9997]])
143
+ >>> print(expval_joint_sampling(x, 'XX', n_shots=8192))
144
+ tensor([[0.9991]])
145
+ >>> print(expval_joint_sampling(x, 'ZZ', n_shots=8192))
146
+ tensor([[-0.9980]])
147
+ """
148
+ # rotation to the desired basis
149
+ n_wires = qdev .n_wires
150
+ paulix = op .op_name_dict ["paulix" ]
151
+ pauliy = op .op_name_dict ["pauliy" ]
152
+ pauliz = op .op_name_dict ["pauliz" ]
153
+ iden = op .op_name_dict ["i" ]
154
+ pauli_dict = {"X" : paulix , "Y" : pauliy , "Z" : pauliz , "I" : iden }
155
+
156
+ qdev_clone = tq .NoiseDevice (n_wires = qdev .n_wires , bsz = qdev .bsz , device = qdev .device )
157
+ qdev_clone .clone_densities (qdev .densities )
158
+
159
+ observable = observable .upper ()
160
+ for wire in range (n_wires ):
161
+ for rotation in pauli_dict [observable [wire ]]().diagonalizing_gates ():
162
+ rotation (qdev_clone , wires = wire )
127
163
164
+ mask = np .ones (len (observable ), dtype = bool )
165
+ mask [np .array ([* observable ]) == "I" ] = False
166
+
167
+ expval_all = []
168
+ # measure
169
+ distributions = measure_density (qdev_clone , n_shots = n_shots )
170
+ for distri in distributions :
171
+ n_eigen_one = 0
172
+ n_eigen_minus_one = 0
173
+ for bitstring , n_count in distri .items ():
174
+ if np .dot (list (map (lambda x : eval (x ), [* bitstring ])), mask ).sum () % 2 == 0 :
175
+ n_eigen_one += n_count
176
+ else :
177
+ n_eigen_minus_one += n_count
178
+
179
+ expval = n_eigen_one / n_shots + (- 1 ) * n_eigen_minus_one / n_shots
180
+ expval_all .append (expval )
181
+
182
+ return torch .tensor (expval_all , dtype = F_DTYPE )
128
183
129
- def expval_joint_analytical (
184
+ def expval_joint_analytical_density (
130
185
noisedev : tq .NoiseDevice ,
131
186
observable : str ,
132
187
n_shots = 1024
@@ -174,7 +229,7 @@ def expval_joint_analytical(
174
229
175
230
expval_all = []
176
231
# measure
177
- distributions = measure (noisedev_clone , n_shots = n_shots )
232
+ distributions = measure_density (noisedev_clone , n_shots = n_shots )
178
233
for distri in distributions :
179
234
n_eigen_one = 0
180
235
n_eigen_minus_one = 0
@@ -190,7 +245,7 @@ def expval_joint_analytical(
190
245
return torch .tensor (expval_all , dtype = F_DTYPE )
191
246
192
247
193
- def expval (
248
+ def expval_density (
194
249
noisedev : tq .NoiseDevice ,
195
250
wires : Union [int , List [int ]],
196
251
observables : Union [op .Observable , List [op .Observable ]],
@@ -223,7 +278,7 @@ def expval(
223
278
return torch .stack (expectations , dim = - 1 )
224
279
225
280
226
- class MeasureAll_Density (tq .QuantumModule ):
281
+ class MeasureAll_density (tq .QuantumModule ):
227
282
"""Obtain the expectation value of all the qubits."""
228
283
229
284
def __init__ (self , obs , v_c_reg_mapping = None ):
@@ -265,9 +320,9 @@ def set_v_c_reg_mapping(self, mapping):
265
320
op (qdev , wires = 0 )
266
321
267
322
# measure the state on z basis
268
- print (tq .measure (qdev , n_shots = 1024 ))
323
+ print (tq .measure_density (qdev , n_shots = 1024 ))
269
324
270
325
# obtain the expval on a observable
271
- expval = expval_joint_sampling (qdev , 'II' , 100000 )
326
+ expval = expval_joint_sampling_density (qdev , 'II' , 100000 )
272
327
# expval_ana = expval_joint_analytical(qdev, 'II')
273
328
print (expval )
0 commit comments