Ejemplo n.º 1
0
    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 (BaseOperator): 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
            vqe._use_simulator_operator_mode = self._use_simulator_operator_mode
            # 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
Ejemplo n.º 2
0
    def _run(self):
        """
        Run the algorithm to compute the minimum eigenvalue.

        Returns:
            dict: Dictionary of results

        Raises:
            AquaError: wrong setting of operator and backend.
        """
        self._operator = VQE._config_the_best_mode(
            self, self._operator, self._quantum_instance.backend)
        self._use_simulator_operator_mode = \
            is_aer_statevector_backend(self._quantum_instance.backend) \
            and isinstance(self._operator, (WeightedPauliOperator, TPBGroupedWeightedPauliOperator))
        self._quantum_instance.circuit_summary = True

        cycle_regex = re.compile(r'(.+)( \1)+')
        # reg-ex explanation:
        # 1. (.+) will match at least one number and try to match as many as possible
        # 2. the match of this part is placed into capture group 1
        # 3. ( \1)+ will match a space followed by the contents of capture group 1
        # -> this results in any number of repeating numbers being detected

        threshold_satisfied = False
        alternating_sequence = False
        prev_op_indices = []
        theta = []
        max_grad = ()
        iteration = 0
        while not threshold_satisfied and not alternating_sequence:
            iteration += 1
            logger.info('--- Iteration #%s ---', str(iteration))
            # compute gradients
            cur_grads = self._compute_gradients(self._excitation_pool, theta,
                                                self._delta,
                                                self._var_form_base,
                                                self._operator,
                                                self._optimizer)
            # pick maximum gradient
            max_grad_index, max_grad = max(enumerate(cur_grads),
                                           key=lambda item: np.abs(item[1][0]))
            # store maximum gradient's index for cycle detection
            prev_op_indices.append(max_grad_index)
            # log gradients
            gradlog = "\nGradients in iteration #{}".format(str(iteration))
            gradlog += "\nID: Excitation Operator: Gradient  <(*) maximum>"
            for i, grad in enumerate(cur_grads):
                gradlog += '\n{}: {}: {}'.format(str(i), str(grad[1]),
                                                 str(grad[0]))
                if grad[1] == max_grad[1]:
                    gradlog += '\t(*)'
            logger.info(gradlog)
            if np.abs(max_grad[0]) < self._threshold:
                logger.info(
                    "Adaptive VQE terminated succesfully with a final maximum gradient: %s",
                    str(np.abs(max_grad[0])))
                threshold_satisfied = True
                break
            # check indices of picked gradients for cycles
            if cycle_regex.search(' '.join(map(str,
                                               prev_op_indices))) is not None:
                logger.info("Alternating sequence found. Finishing.")
                logger.info("Final maximum gradient: %s",
                            str(np.abs(max_grad[0])))
                alternating_sequence = True
                break
            # add new excitation to self._var_form_base
            self._var_form_base.push_hopping_operator(max_grad[1])
            theta.append(0.0)
            # run VQE on current Ansatz
            algorithm = VQE(self._operator,
                            self._var_form_base,
                            self._optimizer,
                            initial_point=theta)
            self._ret = algorithm.run(self._quantum_instance)
            theta = self._ret['opt_params'].tolist()
        # once finished evaluate auxiliary operators if any
        if self._aux_operators is not None and self._aux_operators:
            algorithm = VQE(self._operator,
                            self._var_form_base,
                            self._optimizer,
                            initial_point=theta,
                            aux_operators=self._aux_operators)
            self._ret = algorithm.run(self._quantum_instance)
        # extend VQE returned information with additional outputs
        logger.info('The final energy is: %s', str(self._ret['energy']))
        self._ret['num_iterations'] = iteration
        self._ret['final_max_grad'] = max_grad[0]
        if threshold_satisfied:
            self._ret['finishing_criterion'] = 'threshold_converged'
        elif alternating_sequence:
            self._ret['finishing_criterion'] = 'aborted_due_to_cyclicity'
        else:
            raise AquaError(
                'The algorithm finished due to an unforeseen reason!')
        return self._ret
Ejemplo n.º 3
0
                         num_particles,
                         qubit_mapping=qubit_mapping,
                         two_qubit_reduction=two_qubit_reduction)

depth = 1
var_form = UCCSD(hamiltonian.num_qubits,
                 depth,
                 num_orbitals,
                 num_particles,
                 initial_state=init_state,
                 qubit_mapping=qubit_mapping,
                 two_qubit_reduction=two_qubit_reduction)

optimizer = COBYLA(maxiter=5000)

algo = VQE(hamiltonian, var_form, optimizer)

results = algo.run(sv_simulator)
print(results)
energy = results['energy']
opt_params = results['opt_params']
ground_state = results['min_vector']

eom = QEquationOfMotion(hamiltonian,
                        num_orbitals,
                        num_particles,
                        qubit_mapping=qubit_mapping,
                        two_qubit_reduction=two_qubit_reduction)

excitation_energies, eom_matrices = eom.calculate_excited_states(ground_state)