def _compute_gradients(self, excitation_pool, theta, delta, var_form, operator, optimizer): """ Computes the gradients for all available excitation operators. Args: excitation_pool (list): pool of excitation operators theta (list): list of (up to now) optimal parameters delta (float): finite difference step size (for gradient computation) var_form (VariationalForm): current variational form operator (LegacyBaseOperator): system Hamiltonian optimizer (Optimizer): classical optimizer algorithm Returns: list: List of pairs consisting of gradient and excitation operator. """ res = [] # compute gradients for all excitation in operator pool for exc in excitation_pool: # push next excitation to variational form var_form.push_hopping_operator(exc) # construct auxiliary VQE instance vqe = VQE(operator, var_form, optimizer) vqe.quantum_instance = self.quantum_instance # evaluate energies parameter_sets = theta + [-delta] + theta + [delta] energy_results = vqe._energy_evaluation(np.asarray(parameter_sets)) # compute gradient gradient = (energy_results[0] - energy_results[1]) / (2 * delta) res.append((np.abs(gradient), exc)) # pop excitation from variational form var_form.pop_hopping_operator() return res
def _compute_gradients( self, excitation_pool: List[WeightedPauliOperator], theta: List[float], vqe: VQE, ) -> List[Tuple[float, WeightedPauliOperator]]: """ Computes the gradients for all available excitation operators. Args: excitation_pool: pool of excitation operators theta: list of (up to now) optimal parameters vqe: the variational quantum eigensolver instance used for solving Returns: List of pairs consisting of gradient and excitation operator. """ res = [] # compute gradients for all excitation in operator pool for exc in excitation_pool: # push next excitation to variational form vqe.var_form.push_hopping_operator(exc) # NOTE: because we overwrite the var_form inside of the VQE, we need to update the VQE's # internal _var_form_params, too. We can do this by triggering the var_form setter. Once # the VQE does not store this pure var_form property any longer this can be removed. vqe.var_form = vqe.var_form # We also need to invalidate the internally stored expectation operator because it needs # to be updated for the new var_form. vqe._expect_op = None # evaluate energies parameter_sets = theta + [-self._delta] + theta + [self._delta] energy_results = vqe._energy_evaluation(np.asarray(parameter_sets)) # compute gradient gradient = (energy_results[0] - energy_results[1]) / (2 * self._delta) res.append((np.abs(gradient), exc)) # pop excitation from variational form vqe.var_form.pop_hopping_operator() return res