From bee5e7f62db400a4c2f6924064413371be0048eb Mon Sep 17 00:00:00 2001 From: Julien Gacon Date: Tue, 1 Mar 2022 16:35:19 +0100 Subject: [PATCH] Remove deprecated methods in ``qiskit.algorithms`` (#7257) * rm deprecated algo methods * add reno * fix tests, remove from varalgo * intial point was said to be abstract in varalgo! * attempt to fix sphinx #1 of ? Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .../algorithms/minimum_eigen_solvers/vqe.py | 60 --- .../hamiltonian_phase_estimation_result.py | 15 - qiskit/algorithms/variational_algorithm.py | 359 +----------------- ...recated-algo-methods-eb101adf17a2b920.yaml | 14 + test/python/algorithms/test_vqe.py | 28 +- 5 files changed, 28 insertions(+), 448 deletions(-) create mode 100644 releasenotes/notes/remove-deprecated-algo-methods-eb101adf17a2b920.yaml diff --git a/qiskit/algorithms/minimum_eigen_solvers/vqe.py b/qiskit/algorithms/minimum_eigen_solvers/vqe.py index 83a09e9b9521..b87d481f80a2 100755 --- a/qiskit/algorithms/minimum_eigen_solvers/vqe.py +++ b/qiskit/algorithms/minimum_eigen_solvers/vqe.py @@ -38,7 +38,6 @@ from qiskit.opflow.gradients import GradientBase from qiskit.utils.validation import validate_min from qiskit.utils.backend_utils import is_aer_provider -from qiskit.utils.deprecation import deprecate_function from qiskit.utils import QuantumInstance, algorithm_globals from ..optimizers import Optimizer, SLSQP from ..variational_algorithm import VariationalAlgorithm, VariationalResult @@ -648,51 +647,6 @@ def energy_evaluation(parameters): return energy_evaluation - @deprecate_function( - """ -The VQE.get_optimal_cost method is deprecated as of Qiskit Terra 0.18.0 -and will be removed no sooner than 3 months after the releasedate. -This information is part of the returned result object and can be -queried as VQEResult.eigenvalue.""" - ) - def get_optimal_cost(self) -> float: - """Get the minimal cost or energy found by the VQE.""" - if self._ret.optimal_point is None: - raise AlgorithmError( - "Cannot return optimal cost before running the algorithm to find optimal params." - ) - return self._ret.optimal_value - - @deprecate_function( - """ -The VQE.get_optimal_circuit method is deprecated as of Qiskit Terra -0.18.0 and will be removed no sooner than 3 months after the releasedate. -This information is part of the returned result object and can be -queried as VQEResult.ansatz.bind_parameters(VQEResult.optimal_point).""" - ) - def get_optimal_circuit(self) -> QuantumCircuit: - """Get the circuit with the optimal parameters.""" - if self._ret.optimal_point is None: - raise AlgorithmError( - "Cannot find optimal circuit before running the algorithm to find optimal params." - ) - return self.ansatz.assign_parameters(self._ret.optimal_parameters) - - @deprecate_function( - """ -The VQE.get_optimal_vector method is deprecated as of Qiskit Terra 0.18.0 -and will be removed no sooner than 3 months after the releasedate. -This information is part of the returned result object and can be -queried as VQEResult.eigenvector.""" - ) - def get_optimal_vector(self) -> Union[List[float], Dict[str, int]]: - """Get the simulation outcome of the optimal circuit.""" - if self._ret.optimal_parameters is None: - raise AlgorithmError( - "Cannot find optimal circuit before running the algorithm to find optimal vector." - ) - return self._get_eigenstate(self._ret.optimal_parameters) - def _get_eigenstate(self, optimal_parameters) -> Union[List[float], Dict[str, int]]: """Get the simulation outcome of the ansatz, provided with parameters.""" optimal_circuit = self.ansatz.bind_parameters(optimal_parameters) @@ -704,20 +658,6 @@ def _get_eigenstate(self, optimal_parameters) -> Union[List[float], Dict[str, in return state - @property - @deprecate_function( - """ -The VQE.optimal_params property is deprecated as of Qiskit Terra 0.18.0 -and will be removed no sooner than 3 months after the releasedate. -This information is part of the returned result object and can be -queried as VQEResult.optimal_point.""" - ) - def optimal_params(self) -> np.ndarray: - """The optimal parameters for the ansatz.""" - if self._ret.optimal_point is None: - raise AlgorithmError("Cannot find optimal params before running the algorithm.") - return self._ret.optimal_point - class VQEResult(VariationalResult, MinimumEigensolverResult): """VQE Result.""" diff --git a/qiskit/algorithms/phase_estimators/hamiltonian_phase_estimation_result.py b/qiskit/algorithms/phase_estimators/hamiltonian_phase_estimation_result.py index a6a651c971e4..2ece1b12a8fc 100644 --- a/qiskit/algorithms/phase_estimators/hamiltonian_phase_estimation_result.py +++ b/qiskit/algorithms/phase_estimators/hamiltonian_phase_estimation_result.py @@ -14,7 +14,6 @@ from typing import Dict, Union, cast -from qiskit.utils.deprecation import deprecate_function from qiskit.algorithms.algorithm_result import AlgorithmResult from .phase_estimation_result import PhaseEstimationResult from .phase_estimation_scale import PhaseEstimationScale @@ -84,20 +83,6 @@ def filter_phases( else: return cast(Dict, phases) - @property - @deprecate_function( - """The 'HamiltonianPhaseEstimationResult.most_likely_phase' attribute - is deprecated as of 0.18.0 and will be removed no earlier than 3 months - after the release date. It has been renamed as the 'phase' attribute.""" - ) - def most_likely_phase(self) -> float: - """DEPRECATED - The most likely phase of the unitary corresponding to the Hamiltonian. - - Returns: - The most likely phase. - """ - return self.phase - @property def phase(self) -> float: """The most likely phase of the unitary corresponding to the Hamiltonian. diff --git a/qiskit/algorithms/variational_algorithm.py b/qiskit/algorithms/variational_algorithm.py index a603432193f9..92d8976ffc9f 100644 --- a/qiskit/algorithms/variational_algorithm.py +++ b/qiskit/algorithms/variational_algorithm.py @@ -26,368 +26,27 @@ (``qiskit.utils.algorithm_globals.random_seed = seed``). """ -import warnings -from typing import Optional, Callable, Union, Dict -import time -import logging -from abc import abstractmethod +from typing import Optional, Dict +from abc import ABC, abstractmethod import numpy as np -from qiskit.circuit import QuantumCircuit -from qiskit.providers import BaseBackend -from qiskit.providers import Backend -from qiskit.opflow.gradients import GradientBase -from qiskit.utils import QuantumInstance, algorithm_globals, deprecate_function from .algorithm_result import AlgorithmResult -from .optimizers import Optimizer, SLSQP -logger = logging.getLogger(__name__) - -class VariationalAlgorithm: +class VariationalAlgorithm(ABC): """The Variational Algorithm Base Class.""" - def __init__( - self, - ansatz: Optional[QuantumCircuit] = None, - optimizer: Optional[Optimizer] = None, - cost_fn: Optional[Callable] = None, - gradient: Optional[Union[GradientBase, Callable]] = None, - initial_point: Optional[np.ndarray] = None, - quantum_instance: Optional[Union[QuantumInstance, BaseBackend, Backend]] = None, - ) -> None: - """ - Args: - ansatz: An optional parameterized ansatz (a.k.a. variational form). - optimizer: A classical optimizer. - cost_fn: An optional cost function for optimizer. If not supplied here must be - supplied on :meth:`find_minimum`. - gradient: An optional gradient operator or function for optimizer. - initial_point: An optional initial point (i.e. initial parameter values) - for the optimizer. - quantum_instance: Quantum Instance or Backend - - Raises: - ValueError: for invalid input - """ - if any( - arg is not None - for arg in [ansatz, optimizer, cost_fn, gradient, initial_point, quantum_instance] - ): - warnings.warn( - "The VariationalAlgorithm class has been reduced to an abstract " - "interface. Passing any arguments to the initializer is deprecated as of " - "Qiskit Terra 0.18.0 and will be unsupported no sooner than 3 months " - "after the release date.", - DeprecationWarning, - stacklevel=2, - ) - - self._quantum_instance = None - if quantum_instance: - self.quantum_instance = quantum_instance - - if optimizer is None: - logger.info("No optimizer provided, setting it to SLSPQ.") - optimizer = SLSQP() - - self._optimizer = optimizer - self._gradient = gradient - self._cost_fn = cost_fn - self._initial_point = initial_point - self._ansatz = ansatz - self._ansatz_params = None - if ansatz is not None: - self.ansatz = ansatz - - self._parameterized_circuits = None - - @property - @deprecate_function( - """ -The VariationalAlgorithm is reduced to an interface. Thus, the -quantum_instance property is deprecated as of Qiskit Terra 0.18.0 -and will be removed no sooner than 3 months after the releasedate.""" - ) - def quantum_instance(self) -> Optional[QuantumInstance]: - """Returns quantum instance.""" - return self._quantum_instance - - @quantum_instance.setter - @deprecate_function( - """ -The VariationalAlgorithm is reduced to an interface. Thus, the -quantum_instance property is deprecated as of Qiskit Terra 0.18.0 -and will be removed no sooner than 3 months after the releasedate.""" - ) - def quantum_instance( - self, quantum_instance: Union[QuantumInstance, BaseBackend, Backend] - ) -> None: - """Sets quantum instance.""" - if isinstance(quantum_instance, (BaseBackend, Backend)): - quantum_instance = QuantumInstance(quantum_instance) - self._quantum_instance = quantum_instance - - @property - @deprecate_function( - """ -The VariationalAlgorithm is reduced to an interface. Thus, the -ansatz property is deprecated as of Qiskit Terra 0.18.0 -and will be removed no sooner than 3 months after the releasedate.""" - ) - def ansatz(self) -> Optional[QuantumCircuit]: - """Returns the ansatz""" - return self._ansatz - - @ansatz.setter - @deprecate_function( - """ -The VariationalAlgorithm is reduced to an interface. Thus, the -ansatz property is deprecated as of Qiskit Terra 0.18.0 -and will be removed no sooner than 3 months after the releasedate.""" - ) - def ansatz(self, ansatz: Optional[QuantumCircuit]): - """Sets the ansatz""" - if isinstance(ansatz, QuantumCircuit): - # store the parameters - self._ansatz_params = sorted(ansatz.parameters, key=lambda p: p.name) - self._ansatz = ansatz - elif ansatz is None: - self._ansatz_params = None - self._ansatz = ansatz - else: - raise ValueError(f'Unsupported type "{type(ansatz)}" of ansatz') - - @property - @deprecate_function( - """ -The VariationalAlgorithm is reduced to an interface. Thus, the -optimizer property is deprecated as of Qiskit Terra 0.18.0 -and will be removed no sooner than 3 months after the releasedate.""" - ) - def optimizer(self) -> Optional[Optimizer]: - """Returns optimizer""" - return self._optimizer - - @optimizer.setter - @deprecate_function( - """ -The VariationalAlgorithm is reduced to an interface. Thus, the -optimizer property is deprecated as of Qiskit Terra 0.18.0 -and will be removed no sooner than 3 months after the releasedate.""" - ) - def optimizer(self, optimizer: Optimizer): - """Sets optimizer""" - self._optimizer = optimizer - @property - @deprecate_function( - """ -The VariationalAlgorithm is reduced to an interface. The -initial_point property will be made abstract no sooner than -3 months after the release date of Qiskit Terra 0.18.0. You should -make a concrete implementation in any derived class and not rely on -the implementation here which will be removed.""" - ) + @abstractmethod def initial_point(self) -> Optional[np.ndarray]: - """Returns initial point""" - return self._initial_point + """Returns initial point.""" + pass @initial_point.setter - @deprecate_function( - """ -The VariationalAlgorithm is reduced to an interface. The -initial_point property will be made abstract no sooner than -3 months after the release date of Qiskit Terra 0.18.0. You should -make a concrete implementation in any derived class and not rely on -the implementation here which will be removed.""" - ) - def initial_point(self, initial_point: np.ndarray): - """Sets initial point""" - self._initial_point = initial_point - - @deprecate_function( - """ -The VariationalAlgorithm is reduced to an interface. Thus, the -find_minimum method is deprecated as of Qiskit Terra 0.18.0 -and will be removed no sooner than 3 months after the releasedate.""" - ) - def find_minimum( - self, - initial_point: Optional[np.ndarray] = None, - ansatz: Optional[QuantumCircuit] = None, - cost_fn: Optional[Callable] = None, - optimizer: Optional[Optimizer] = None, - gradient_fn: Optional[Callable] = None, - ) -> "VariationalResult": - """Optimize to find the minimum cost value. - - Args: - initial_point: If not `None` will be used instead of any initial point supplied via - constructor. If `None` and `None` was supplied to constructor then a random - point will be used if the optimizer requires an initial point. - ansatz: If not `None` will be used instead of any ansatz supplied via constructor. - cost_fn: If not `None` will be used instead of any cost_fn supplied via - constructor. - optimizer: If not `None` will be used instead of any optimizer supplied via - constructor. - gradient_fn: Optional gradient function for optimizer - - Returns: - dict: Optimized variational parameters, and corresponding minimum cost value. - - Raises: - ValueError: invalid input - - """ - initial_point = initial_point if initial_point is not None else self.initial_point - ansatz = ansatz if ansatz is not None else self.ansatz - cost_fn = cost_fn if cost_fn is not None else self._cost_fn - optimizer = optimizer if optimizer is not None else self.optimizer - - if ansatz is None: - raise ValueError("Ansatz neither supplied to constructor nor find minimum.") - if cost_fn is None: - raise ValueError("Cost function neither supplied to constructor nor find minimum.") - if optimizer is None: - raise ValueError("Optimizer neither supplied to constructor nor find minimum.") - - nparms = ansatz.num_parameters - - if hasattr(ansatz, "parameter_bounds") and ansatz.parameter_bounds is not None: - bounds = ansatz.parameter_bounds - else: - bounds = [(None, None)] * nparms - - if initial_point is not None and len(initial_point) != nparms: - raise ValueError( - "Initial point size {} and parameter size {} mismatch".format( - len(initial_point), nparms - ) - ) - if len(bounds) != nparms: - raise ValueError("Ansatz bounds size does not match parameter size") - # If *any* value is *equal* in bounds array to None then the problem does *not* have bounds - problem_has_bounds = not np.any(np.equal(bounds, None)) - # Check capabilities of the optimizer - if problem_has_bounds: - if not optimizer.is_bounds_supported: - raise ValueError("Problem has bounds but optimizer does not support bounds") - else: - if optimizer.is_bounds_required: - raise ValueError("Problem does not have bounds but optimizer requires bounds") - if initial_point is not None: - if not optimizer.is_initial_point_supported: - raise ValueError("Optimizer does not support initial point") - else: - if optimizer.is_initial_point_required: - if hasattr(ansatz, "preferred_init_points"): - # Note: default implementation returns None, hence check again after below - initial_point = ansatz.preferred_init_points - - if initial_point is None: # If still None use a random generated point - low = [(l if l is not None else -2 * np.pi) for (l, u) in bounds] - high = [(u if u is not None else 2 * np.pi) for (l, u) in bounds] - initial_point = algorithm_globals.random.uniform(low, high) - - start = time.time() - if not optimizer.is_gradient_supported: # ignore the passed gradient function - gradient_fn = None - else: - if not gradient_fn: - gradient_fn = self._gradient - - logger.info("Starting optimizer.\nbounds=%s\ninitial point=%s", bounds, initial_point) - opt_params, opt_val, num_optimizer_evals = optimizer.optimize( - nparms, - cost_fn, - variable_bounds=bounds, - initial_point=initial_point, - gradient_function=gradient_fn, - ) - eval_time = time.time() - start - - result = VariationalResult() - result.optimizer_evals = num_optimizer_evals - result.optimizer_time = eval_time - result.optimal_value = opt_val - result.optimal_point = opt_params - result.optimal_parameters = dict(zip(self._ansatz_params, opt_params)) - - return result - - @deprecate_function( - """ -The VariationalAlgorithm is reduced to an interface. Thus, the -get_prob_vector_for_params method is deprecated as of Qiskit Terra 0.18.0 -and will be removed no sooner than 3 months after the releasedate.""" - ) - def get_prob_vector_for_params( - self, construct_circuit_fn, params_s, quantum_instance, construct_circuit_args=None - ): - """Helper function to get probability vectors for a set of params""" - circuits = [] - for params in params_s: - circuit = construct_circuit_fn(params, **construct_circuit_args) - circuits.append(circuit) - results = quantum_instance.execute(circuits) - - probs_s = [] - for circuit in circuits: - if quantum_instance.is_statevector: - sv = results.get_statevector(circuit) - probs = np.real(sv * np.conj(sv)) - probs_s.append(probs) - else: - counts = results.get_counts(circuit) - probs_s.append(self.get_probabilities_for_counts(counts)) - return np.array(probs_s) - - @deprecate_function( - """ -The VariationalAlgorithm is reduced to an interface. Thus, the -get_probabilities_for_counts method is deprecated as of Qiskit Terra 0.18.0 -and will be removed no sooner than 3 months after the releasedate.""" - ) - def get_probabilities_for_counts(self, counts): - """get probabilities for counts""" - shots = sum(counts.values()) - states = int(2 ** len(list(counts.keys())[0])) - probs = np.zeros(states) - for k, v in counts.items(): - probs[int(k, 2)] = v / shots - return probs - - @abstractmethod - def get_optimal_cost(self): - """get optimal cost""" - raise NotImplementedError() - - @abstractmethod - def get_optimal_circuit(self): - """get optimal circuit""" - raise NotImplementedError() - @abstractmethod - def get_optimal_vector(self): - """get optimal vector""" - raise NotImplementedError() - - @property - @abstractmethod - def optimal_params(self): - """returns optimal parameters""" - raise NotImplementedError() - - @deprecate_function( - """ -The VariationalAlgorithm is reduced to an interface. Thus, the -cleanup_paramterized_circuits method is deprecated as of Qiskit Terra 0.18.0 -and will be removed no sooner than 3 months after the releasedate.""" - ) - def cleanup_parameterized_circuits(self): - """set parameterized circuits to None""" - self._parameterized_circuits = None + def initial_point(self, initial_point: Optional[np.ndarray]) -> None: + """Sets initial point.""" + pass class VariationalResult(AlgorithmResult): diff --git a/releasenotes/notes/remove-deprecated-algo-methods-eb101adf17a2b920.yaml b/releasenotes/notes/remove-deprecated-algo-methods-eb101adf17a2b920.yaml new file mode 100644 index 000000000000..0736bafa2dd3 --- /dev/null +++ b/releasenotes/notes/remove-deprecated-algo-methods-eb101adf17a2b920.yaml @@ -0,0 +1,14 @@ +--- +other: + - | + Remove the following methods that have been deprecated in Qiskit Terra 0.18.0. + + * `qiskit.algorithms.VQE.get_optimal_cost` + * `qiskit.algorithms.VQE.get_optimal_circuit` + * `qiskit.algorithms.VQE.get_optimal_vector` + * `qiskit.algorithms.VQE.optimal_params` + * `qiskit.algorithms.HamiltonianPhaseEstimationResult.most_likely_phase` + * `qiskit.algorithms.PhaseEstimationResult.most_likely_phase` + + and the class :class:`~qiskit.algorithms.VariationalAlgorithm` is reduced to + an abstract interface. diff --git a/test/python/algorithms/test_vqe.py b/test/python/algorithms/test_vqe.py index 8ec56edc198c..6400f6a07a66 100644 --- a/test/python/algorithms/test_vqe.py +++ b/test/python/algorithms/test_vqe.py @@ -201,32 +201,14 @@ def test_basic_aer_qasm(self): result = vqe.compute_minimum_eigenvalue(operator=self.h2_op) self.assertAlmostEqual(result.eigenvalue.real, -1.86823, places=2) - def test_qasm_aux_operators_normalized(self): - """Test VQE with qasm_simulator returns normalized aux_operator eigenvalues.""" + def test_qasm_eigenvector_normalized(self): + """Test VQE with qasm_simulator returns normalized eigenvector.""" wavefunction = self.ry_wavefunction vqe = VQE(ansatz=wavefunction, quantum_instance=self.qasm_simulator) - _ = vqe.compute_minimum_eigenvalue(operator=self.h2_op) - - opt_params = [ - 3.50437328, - 3.87415376, - 0.93684363, - 5.92219622, - -1.53527887, - 1.87941418, - -4.5708326, - 0.70187027, - ] - - vqe._ret.optimal_point = opt_params - vqe._ret.optimal_parameters = dict( - zip(sorted(wavefunction.parameters, key=lambda p: p.name), opt_params) - ) - - with self.assertWarns(DeprecationWarning): - optimal_vector = vqe.get_optimal_vector() + result = vqe.compute_minimum_eigenvalue(operator=self.h2_op) - self.assertAlmostEqual(sum(v**2 for v in optimal_vector.values()), 1.0, places=4) + amplitudes = list(result.eigenstate.values()) + self.assertAlmostEqual(np.linalg.norm(amplitudes), 1.0, places=4) @unittest.skipUnless(has_aer(), "qiskit-aer doesn't appear to be installed.") def test_with_aer_statevector(self):