def aux_operators( self, aux_operators: Optional[ Union[OperatorBase, LegacyBaseOperator, List[Optional[Union[OperatorBase, LegacyBaseOperator]]]]] ) -> None: """ Set aux operators """ if aux_operators is None: aux_operators = [] elif not isinstance(aux_operators, list): aux_operators = [aux_operators] # We need to handle the array entries being Optional i.e. having value None self._aux_op_nones = [op is None for op in aux_operators] if aux_operators: zero_op = I.tensorpower(self.operator.num_qubits) * 0.0 converted = [] for op in aux_operators: if op is None: converted.append(zero_op) elif isinstance(op, LegacyBaseOperator): converted.append(op.to_opflow()) else: converted.append(op) # For some reason Chemistry passes aux_ops with 0 qubits and paulis sometimes. aux_operators = [zero_op if op == 0 else op for op in converted] self._aux_operators = aux_operators # type: List
def aux_operators( self, aux_operators: Optional[ Union[OperatorBase, LegacyBaseOperator, List[Optional[Union[OperatorBase, LegacyBaseOperator]]]]] ) -> None: if aux_operators is None: aux_operators = [] elif not isinstance(aux_operators, list): aux_operators = [aux_operators] if aux_operators: zero_op = I.tensorpower(self.operator.num_qubits) * 0.0 converted = [ op.to_opflow() if isinstance(op, LegacyBaseOperator) else op for op in aux_operators ] # For some reason Chemistry passes aux_ops with 0 qubits and paulis sometimes. aux_operators = [zero_op if op == 0 else op for op in converted] self._aux_operators = aux_operators
def compute_minimum_eigenvalue( self, operator: OperatorBase, aux_operators: Optional[List[Optional[OperatorBase]]] = None ) -> MinimumEigensolverResult: super().compute_minimum_eigenvalue(operator, aux_operators) if self.quantum_instance is None: raise AlgorithmError( "A QuantumInstance or Backend " "must be supplied to run the quantum algorithm.") if operator is None: raise AlgorithmError("The operator was never provided.") operator = self._check_operator(operator) # We need to handle the array entries being Optional i.e. having value None if aux_operators: zero_op = I.tensorpower(operator.num_qubits) * 0.0 converted = [] for op in aux_operators: if op is None: converted.append(zero_op) else: converted.append(op) # For some reason Chemistry passes aux_ops with 0 qubits and paulis sometimes. aux_operators = [zero_op if op == 0 else op for op in converted] else: aux_operators = None self._quantum_instance.circuit_summary = True self._eval_count = 0 # Convert the gradient operator into a callable function that is compatible with the # optimization routine. if self._gradient: if isinstance(self._gradient, GradientBase): self._gradient = self._gradient.gradient_wrapper( ~StateFn(operator) @ StateFn(self._var_form), bind_params=self._var_form_params, backend=self._quantum_instance) if not self._expect_op: self._expect_op = self.construct_expectation( self._var_form_params, operator) vqresult = self.find_minimum(initial_point=self.initial_point, var_form=self.var_form, cost_fn=self._energy_evaluation, gradient_fn=self._gradient, optimizer=self.optimizer) self._ret = VQEResult() self._ret.combine(vqresult) if vqresult.optimizer_evals is not None and \ self._eval_count >= vqresult.optimizer_evals: self._eval_count = vqresult.optimizer_evals self._eval_time = vqresult.optimizer_time logger.info( 'Optimization complete in %s seconds.\nFound opt_params %s in %s evals', self._eval_time, vqresult.optimal_point, self._eval_count) self._ret.eigenvalue = vqresult.optimal_value + 0j self._ret.eigenstate = self.get_optimal_vector() self._ret.eigenvalue = self.get_optimal_cost() if aux_operators: self._eval_aux_ops(aux_operators) self._ret.aux_operator_eigenvalues = self._ret.aux_operator_eigenvalues[ 0] self._ret.cost_function_evals = self._eval_count return self._ret
def compute_minimum_eigenvalue( self, operator: OperatorBase, aux_operators: Optional[ListOrDict[OperatorBase]] = None ) -> MinimumEigensolverResult: super().compute_minimum_eigenvalue(operator, aux_operators) if self.quantum_instance is None: raise AlgorithmError( "A QuantumInstance or Backend must be supplied to run the quantum algorithm." ) self.quantum_instance.circuit_summary = True # this sets the size of the ansatz, so it must be called before the initial point # validation self._check_operator_ansatz(operator) # set an expectation for this algorithm run (will be reset to None at the end) initial_point = _validate_initial_point(self.initial_point, self.ansatz) bounds = _validate_bounds(self.ansatz) # We need to handle the array entries being zero or Optional i.e. having value None if aux_operators: zero_op = I.tensorpower(operator.num_qubits) * 0.0 # Convert the None and zero values when aux_operators is a list. # Drop None and convert zero values when aux_operators is a dict. if isinstance(aux_operators, list): key_op_iterator = enumerate(aux_operators) converted = [zero_op] * len(aux_operators) else: key_op_iterator = aux_operators.items() converted = {} for key, op in key_op_iterator: if op is not None: converted[key] = zero_op if op == 0 else op aux_operators = converted else: aux_operators = None # Convert the gradient operator into a callable function that is compatible with the # optimization routine. if isinstance(self._gradient, GradientBase): gradient = self._gradient.gradient_wrapper( ~StateFn(operator) @ StateFn(self._ansatz), bind_params=self._ansatz_params, backend=self._quantum_instance, ) else: gradient = self._gradient self._eval_count = 0 energy_evaluation, expectation = self.get_energy_evaluation( operator, return_expectation=True) start_time = time() # keep this until Optimizer.optimize is removed try: opt_result = self.optimizer.minimize(fun=energy_evaluation, x0=initial_point, jac=gradient, bounds=bounds) except AttributeError: # self.optimizer is an optimizer with the deprecated interface that uses # ``optimize`` instead of ``minimize``` warnings.warn( "Using an optimizer that is run with the ``optimize`` method is " "deprecated as of Qiskit Terra 0.19.0 and will be unsupported no " "sooner than 3 months after the release date. Instead use an optimizer " "providing ``minimize`` (see qiskit.algorithms.optimizers.Optimizer).", DeprecationWarning, stacklevel=2, ) opt_result = self.optimizer.optimize(len(initial_point), energy_evaluation, gradient, bounds, initial_point) eval_time = time() - start_time result = VQEResult() result.optimal_point = opt_result.x result.optimal_parameters = dict(zip(self._ansatz_params, opt_result.x)) result.optimal_value = opt_result.fun result.cost_function_evals = opt_result.nfev result.optimizer_time = eval_time result.eigenvalue = opt_result.fun + 0j result.eigenstate = self._get_eigenstate(result.optimal_parameters) logger.info( "Optimization complete in %s seconds.\nFound opt_params %s in %s evals", eval_time, result.optimal_point, self._eval_count, ) # TODO delete as soon as get_optimal_vector etc are removed self._ret = result if aux_operators is not None: aux_values = self._eval_aux_ops(opt_result.x, aux_operators, expectation=expectation) result.aux_operator_eigenvalues = aux_values return result
def compute_eigenvalues( self, operator: OperatorBase, aux_operators: Optional[List[Optional[OperatorBase]]] = None ) -> EigensolverResult: super().compute_eigenvalues(operator, aux_operators) if operator is None: raise AlgorithmError("Operator was never provided") self._check_set_k(operator) if aux_operators: zero_op = I.tensorpower(operator.num_qubits) * 0.0 # For some reason Chemistry passes aux_ops with 0 qubits and paulis sometimes. aux_operators = [ zero_op if op == 0 else op for op in aux_operators ] else: aux_operators = None k_orig = self._k if self._filter_criterion: # need to consider all elements if a filter is set self._k = 2**operator.num_qubits self._ret = EigensolverResult() self._solve(operator) # compute energies before filtering, as this also evaluates the aux operators self._get_energies(operator, aux_operators) # if a filter is set, loop over the given values and only keep if self._filter_criterion: eigvecs = [] eigvals = [] aux_ops = [] cnt = 0 for i in range(len(self._ret.eigenvalues)): eigvec = self._ret.eigenstates[i] eigval = self._ret.eigenvalues[i] if self._ret.aux_operator_eigenvalues is not None: aux_op = self._ret.aux_operator_eigenvalues[i] else: aux_op = None if self._filter_criterion(eigvec, eigval, aux_op): cnt += 1 eigvecs += [eigvec] eigvals += [eigval] if self._ret.aux_operator_eigenvalues is not None: aux_ops += [aux_op] if cnt == k_orig: break self._ret.eigenstates = np.array(eigvecs) self._ret.eigenvalues = np.array(eigvals) # conversion to np.array breaks in case of aux_ops self._ret.aux_operator_eigenvalues = aux_ops self._k = k_orig # evaluate ground state after filtering (in case a filter is set) self._get_ground_state_energy(operator) if self._ret.eigenstates is not None: self._ret.eigenstates = ListOp( [StateFn(vec) for vec in self._ret.eigenstates]) logger.debug('EigensolverResult:\n%s', self._ret) return self._ret
def compute_minimum_eigenvalue( self, operator: OperatorBase, aux_operators: Optional[List[Optional[OperatorBase]]] = None ) -> MinimumEigensolverResult: super().compute_minimum_eigenvalue(operator, aux_operators) if self.quantum_instance is None: raise AlgorithmError( "A QuantumInstance or Backend must be supplied to run the quantum algorithm." ) self.quantum_instance.circuit_summary = True # this sets the size of the ansatz, so it must be called before the initial point # validation self._check_operator_ansatz(operator) # set an expectation for this algorithm run (will be reset to None at the end) initial_point = _validate_initial_point(self.initial_point, self.ansatz) bounds = _validate_bounds(self.ansatz) # We need to handle the array entries being Optional i.e. having value None if aux_operators: zero_op = I.tensorpower(operator.num_qubits) * 0.0 converted = [] for op in aux_operators: if op is None: converted.append(zero_op) else: converted.append(op) # For some reason Chemistry passes aux_ops with 0 qubits and paulis sometimes. aux_operators = [zero_op if op == 0 else op for op in converted] else: aux_operators = None # Convert the gradient operator into a callable function that is compatible with the # optimization routine. if isinstance(self._gradient, GradientBase): gradient = self._gradient.gradient_wrapper( ~StateFn(operator) @ StateFn(self._ansatz), bind_params=self._ansatz_params, backend=self._quantum_instance, ) else: gradient = self._gradient self._eval_count = 0 energy_evaluation, expectation = self.get_energy_evaluation( operator, return_expectation=True) start_time = time() opt_params, opt_value, nfev = self.optimizer.optimize( num_vars=len(initial_point), objective_function=energy_evaluation, gradient_function=gradient, variable_bounds=bounds, initial_point=initial_point, ) eval_time = time() - start_time result = VQEResult() result.optimal_point = opt_params result.optimal_parameters = dict(zip(self._ansatz_params, opt_params)) result.optimal_value = opt_value result.cost_function_evals = nfev result.optimizer_time = eval_time result.eigenvalue = opt_value + 0j result.eigenstate = self._get_eigenstate(result.optimal_parameters) logger.info( "Optimization complete in %s seconds.\nFound opt_params %s in %s evals", eval_time, result.optimal_point, self._eval_count, ) # TODO delete as soon as get_optimal_vector etc are removed self._ret = result if aux_operators is not None: aux_values = self._eval_aux_ops(opt_params, aux_operators, expectation=expectation) result.aux_operator_eigenvalues = aux_values[0] return result