@@ -26,7 +26,7 @@ class UCCVQE(UCC, VQE):
26
26
.. math::
27
27
E(\\ mathbf{t}) = \\ langle \\ Phi_0 | \\ hat{U}^\\ dagger(\\ mathbf{\\ mathbf{t}}) \\ hat{H} \\ hat{U}(\\ mathbf{\\ mathbf{t}}) | \\ Phi_0 \\ rangle
28
28
29
- using a disentagled UCC type ansatz
29
+ using a disentangled UCC type ansatz
30
30
31
31
.. math::
32
32
\\ hat{U}(\\ mathbf{t}) = \\ prod_\\ mu e^{t_\\ mu (\\ hat{\\ tau}_\\ mu - \\ hat{\\ tau}_\\ mu^\\ dagger)},
@@ -71,6 +71,7 @@ class UCCVQE(UCC, VQE):
71
71
"""
72
72
73
73
def __init__ (self , * args , ** kwargs ):
74
+ self .computer_initializable = True
74
75
super ().__init__ (* args , ** kwargs )
75
76
76
77
@abstractmethod
@@ -104,7 +105,7 @@ def measure_operators(self, operators, Ucirc, idxs=[]):
104
105
"""
105
106
106
107
if self ._fast :
107
- myQC = qforte . Computer ( self ._nqb )
108
+ myQC = self .get_initial_computer ( )
108
109
myQC .apply_circuit (Ucirc )
109
110
if not idxs :
110
111
grads = myQC .direct_oppl_exp_val (operators )
@@ -120,7 +121,8 @@ def measure_operators(self, operators, Ucirc, idxs=[]):
120
121
121
122
def measure_gradient (self , params = None ):
122
123
"""Returns the disentangled (factorized) UCC gradient, using a
123
- recursive approach.
124
+ recursive approach, as described in Section D of the Appendix of
125
+ 10.1038/s41467-019-10988-2
124
126
125
127
Parameters
126
128
----------
@@ -140,18 +142,11 @@ def measure_gradient(self, params=None):
140
142
else :
141
143
Utot = self .build_Uvqc (params )
142
144
143
- qc_psi = qforte .Computer (
144
- self ._nqb
145
- ) # build | sig_N > according ADAPT-VQE analytical grad section
145
+ qc_psi = self .get_initial_computer ()
146
146
qc_psi .apply_circuit (Utot )
147
- qc_sig = qforte .Computer (
148
- self ._nqb
149
- ) # build | psi_N > according ADAPT-VQE analytical grad section
150
- psi_i = copy .deepcopy (qc_psi .get_coeff_vec ())
151
- qc_sig .set_coeff_vec (
152
- copy .deepcopy (psi_i )
153
- ) # not sure if copy is faster or reapplication of state
147
+ qc_sig = qf .Computer (qc_psi )
154
148
qc_sig .apply_operator (self ._qb_ham )
149
+ qc_temp = qf .Computer (qc_psi )
155
150
156
151
mu = M - 1
157
152
@@ -161,15 +156,13 @@ def measure_gradient(self, params=None):
161
156
)
162
157
Kmu_prev .mult_coeffs (self ._pool_obj [self ._tops [mu ]][0 ])
163
158
164
- qc_psi .apply_operator (Kmu_prev )
159
+ qc_temp .apply_operator (Kmu_prev )
165
160
grads [mu ] = 2.0 * np .real (
166
- np .vdot (qc_sig .get_coeff_vec (), qc_psi .get_coeff_vec ())
161
+ np .vdot (qc_sig .get_coeff_vec (), qc_temp .get_coeff_vec ())
167
162
)
168
163
169
- # reset Kmu_prev |psi_i> -> |psi_i>
170
- qc_psi .set_coeff_vec (copy .deepcopy (psi_i ))
171
-
172
164
for mu in reversed (range (M - 1 )):
165
+ qc_temp = qf .Computer (qc_psi )
173
166
# mu => N-1 => M-2
174
167
# mu+1 => N => M-1
175
168
# Kmu => KN-1
@@ -243,15 +236,14 @@ def measure_gradient(self, params=None):
243
236
244
237
qc_sig .apply_circuit (Umu )
245
238
qc_psi .apply_circuit (Umu )
246
- psi_i = copy . deepcopy (qc_psi . get_coeff_vec () )
239
+ qc_temp = qf . Computer (qc_psi )
247
240
248
- qc_psi .apply_operator (Kmu )
241
+ qc_temp .apply_operator (Kmu )
249
242
grads [mu ] = 2.0 * np .real (
250
- np .vdot (qc_sig .get_coeff_vec (), qc_psi .get_coeff_vec ())
243
+ np .vdot (qc_sig .get_coeff_vec (), qc_temp .get_coeff_vec ())
251
244
)
252
245
253
246
# reset Kmu |psi_i> -> |psi_i>
254
- qc_psi .set_coeff_vec (copy .deepcopy (psi_i ))
255
247
Kmu_prev = Kmu
256
248
257
249
np .testing .assert_allclose (np .imag (grads ), np .zeros_like (grads ), atol = 1e-7 )
@@ -269,25 +261,22 @@ def measure_gradient3(self):
269
261
raise ValueError ("self._fast must be True for gradient measurement." )
270
262
271
263
Utot = self .build_Uvqc ()
272
- qc_psi = qforte . Computer ( self ._nqb )
264
+ qc_psi = self .get_initial_computer ( )
273
265
qc_psi .apply_circuit (Utot )
274
- psi_i = copy .deepcopy (qc_psi .get_coeff_vec ())
275
266
276
- qc_sig = qforte .Computer (self ._nqb )
277
- # TODO: Check if it's faster to recompute psi_i or copy it.
278
- qc_sig .set_coeff_vec (copy .deepcopy (psi_i ))
267
+ qc_sig = qforte .Computer (qc_psi )
279
268
qc_sig .apply_operator (self ._qb_ham )
280
269
281
270
grads = np .zeros (len (self ._pool_obj ))
282
271
283
272
for mu , (coeff , operator ) in enumerate (self ._pool_obj ):
273
+ qc_temp = qf .Computer (qc_psi )
284
274
Kmu = operator .jw_transform (self ._qubit_excitations )
285
275
Kmu .mult_coeffs (coeff )
286
- qc_psi .apply_operator (Kmu )
276
+ qc_temp .apply_operator (Kmu )
287
277
grads [mu ] = 2.0 * np .real (
288
- np .vdot (qc_sig .get_coeff_vec (), qc_psi .get_coeff_vec ())
278
+ np .vdot (qc_sig .get_coeff_vec (), qc_temp .get_coeff_vec ())
289
279
)
290
- qc_psi .set_coeff_vec (copy .deepcopy (psi_i ))
291
280
292
281
np .testing .assert_allclose (np .imag (grads ), np .zeros_like (grads ), atol = 1e-7 )
293
282
0 commit comments