From d7dd5787e6320b9d633f2c5bf21493b77c1afc00 Mon Sep 17 00:00:00 2001 From: Manoel Marques Date: Wed, 31 Aug 2022 18:38:30 -0400 Subject: [PATCH] Rewrite Amplitude Estimators with Primitives --- qiskit/algorithms/amplitude_estimators/ae.py | 34 +++++++++++++++--- qiskit/algorithms/amplitude_estimators/fae.py | 35 +++++++++++++++--- qiskit/algorithms/amplitude_estimators/iae.py | 33 ++++++++++++++--- .../algorithms/amplitude_estimators/mlae.py | 36 ++++++++++++++++--- 4 files changed, 121 insertions(+), 17 deletions(-) diff --git a/qiskit/algorithms/amplitude_estimators/ae.py b/qiskit/algorithms/amplitude_estimators/ae.py index 4d4c89873235..6d067a911369 100644 --- a/qiskit/algorithms/amplitude_estimators/ae.py +++ b/qiskit/algorithms/amplitude_estimators/ae.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2018, 2020. +# (C) Copyright IBM 2018, 2022. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -14,13 +14,16 @@ from typing import Optional, Union, List, Tuple, Dict from collections import OrderedDict +import warnings import numpy as np from scipy.stats import chi2, norm from scipy.optimize import bisect from qiskit import QuantumCircuit, ClassicalRegister from qiskit.providers import Backend +from qiskit.primitives import BaseSampler from qiskit.utils import QuantumInstance +from qiskit.utils.deprecation import deprecate_function from .amplitude_estimator import AmplitudeEstimator, AmplitudeEstimatorResult from .ae_utils import pdf_a, derivative_log_pdf_a, bisect_max from .estimation_problem import EstimationProblem @@ -59,6 +62,7 @@ def __init__( phase_estimation_circuit: Optional[QuantumCircuit] = None, iqft: Optional[QuantumCircuit] = None, quantum_instance: Optional[Union[QuantumInstance, Backend]] = None, + sampler: Optional[BaseSampler] = None, ) -> None: r""" Args: @@ -68,7 +72,9 @@ def __init__( `qiskit.circuit.library.PhaseEstimation` when None. iqft: The inverse quantum Fourier transform component, defaults to using a standard implementation from `qiskit.circuit.library.QFT` when None. - quantum_instance: The backend (or `QuantumInstance`) to execute the circuits on. + quantum_instance: Pending deprecation\: The backend (or `QuantumInstance`) to execute + the circuits on. + sampler: base sampler Raises: ValueError: If the number of evaluation qubits is smaller than 1. @@ -79,6 +85,13 @@ def __init__( super().__init__() # set quantum instance + if quantum_instance is not None: + warnings.warn( + "The quantum_instance argument has been superseded by the sampler argument. " + "This argument will be deprecated in a future release and subsequently " + "removed after that.", + category=PendingDeprecationWarning, + ) self.quantum_instance = quantum_instance # get parameters @@ -87,10 +100,17 @@ def __init__( self._iqft = iqft self._pec = phase_estimation_circuit + self._sampler = sampler @property + @deprecate_function( + "The AmplitudeEstimation.quantum_instance getter is pending deprecation. " + "This property will be deprecated in a future release and subsequently " + "removed after that.", + category=PendingDeprecationWarning, + ) def quantum_instance(self) -> Optional[QuantumInstance]: - """Get the quantum instance. + """Pending deprecation: Get the quantum instance. Returns: The quantum instance used to run this algorithm. @@ -98,8 +118,14 @@ def quantum_instance(self) -> Optional[QuantumInstance]: return self._quantum_instance @quantum_instance.setter + @deprecate_function( + "The AmplitudeEstimation.quantum_instance setter is pending deprecation. " + "This property will be deprecated in a future release and subsequently " + "removed after that.", + category=PendingDeprecationWarning, + ) def quantum_instance(self, quantum_instance: Union[QuantumInstance, Backend]) -> None: - """Set quantum instance. + """Pending deprecation: Set quantum instance. Args: quantum_instance: The quantum instance used to run this algorithm. diff --git a/qiskit/algorithms/amplitude_estimators/fae.py b/qiskit/algorithms/amplitude_estimators/fae.py index db8ee9151d50..ffa7a2510374 100644 --- a/qiskit/algorithms/amplitude_estimators/fae.py +++ b/qiskit/algorithms/amplitude_estimators/fae.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2020. +# (C) Copyright IBM 2017, 2022. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -13,11 +13,14 @@ """Faster Amplitude Estimation.""" from typing import Optional, Union, List, Tuple +import warnings import numpy as np from qiskit.circuit import QuantumCircuit, ClassicalRegister from qiskit.providers import Backend +from qiskit.primitives import BaseSampler from qiskit.utils import QuantumInstance +from qiskit.utils.deprecation import deprecate_function from qiskit.algorithms.exceptions import AlgorithmError from .amplitude_estimator import AmplitudeEstimator, AmplitudeEstimatorResult @@ -51,13 +54,16 @@ def __init__( maxiter: int, rescale: bool = True, quantum_instance: Optional[Union[QuantumInstance, Backend]] = None, + sampler: Optional[BaseSampler] = None, ) -> None: r""" Args: delta: The probability that the true value is outside of the final confidence interval. maxiter: The number of iterations, the maximal power of Q is `2 ** (maxiter - 1)`. rescale: Whether to rescale the problem passed to `estimate`. - quantum_instance: The quantum instance or backend to run the circuits. + quantum_instance: Pending deprecation\: The quantum instance or backend + to run the circuits. + sampler: base sampler .. note:: @@ -66,16 +72,31 @@ def __init__( """ super().__init__() + # set quantum instance + if quantum_instance is not None: + warnings.warn( + "The quantum_instance argument has been superseded by the sampler argument. " + "This argument will be deprecated in a future release and subsequently " + "removed after that.", + category=PendingDeprecationWarning, + ) self.quantum_instance = quantum_instance self._shots = (int(1944 * np.log(2 / delta)), int(972 * np.log(2 / delta))) self._rescale = rescale self._delta = delta self._maxiter = maxiter self._num_oracle_calls = 0 + self._sampler = sampler @property + @deprecate_function( + "The FasterAmplitudeEstimation.quantum_instance getter is pending deprecation. " + "This property will be deprecated in a future release and subsequently " + "removed after that.", + category=PendingDeprecationWarning, + ) def quantum_instance(self) -> Optional[QuantumInstance]: - """Get the quantum instance. + """Pending deprecation: Get the quantum instance. Returns: The quantum instance used to run this algorithm. @@ -83,8 +104,14 @@ def quantum_instance(self) -> Optional[QuantumInstance]: return self._quantum_instance @quantum_instance.setter + @deprecate_function( + "The FasterAmplitudeEstimation.quantum_instance setter is pending deprecation. " + "This property will be deprecated in a future release and subsequently " + "removed after that.", + category=PendingDeprecationWarning, + ) def quantum_instance(self, quantum_instance: Union[QuantumInstance, Backend]) -> None: - """Set quantum instance. + """Pending deprecation: Set quantum instance. Args: quantum_instance: The quantum instance used to run this algorithm. diff --git a/qiskit/algorithms/amplitude_estimators/iae.py b/qiskit/algorithms/amplitude_estimators/iae.py index 42727cc5aea0..ddfb1af653c4 100644 --- a/qiskit/algorithms/amplitude_estimators/iae.py +++ b/qiskit/algorithms/amplitude_estimators/iae.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2018, 2020. +# (C) Copyright IBM 2018, 2022. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -13,12 +13,15 @@ """The Iterative Quantum Amplitude Estimation Algorithm.""" from typing import Optional, Union, List, Tuple, Dict, cast +import warnings import numpy as np from scipy.stats import beta from qiskit import ClassicalRegister, QuantumCircuit from qiskit.providers import Backend +from qiskit.primitives import BaseSampler from qiskit.utils import QuantumInstance +from qiskit.utils.deprecation import deprecate_function from .amplitude_estimator import AmplitudeEstimator, AmplitudeEstimatorResult from .estimation_problem import EstimationProblem @@ -53,6 +56,7 @@ def __init__( confint_method: str = "beta", min_ratio: float = 2, quantum_instance: Optional[Union[QuantumInstance, Backend]] = None, + sampler: Optional[BaseSampler] = None, ) -> None: r""" The output of the algorithm is an estimate for the amplitude `a`, that with at least @@ -66,7 +70,8 @@ def __init__( each iteration, can be 'chernoff' for the Chernoff intervals or 'beta' for the Clopper-Pearson intervals (default) min_ratio: Minimal q-ratio (:math:`K_{i+1} / K_i`) for FindNextK - quantum_instance: Quantum Instance or Backend + quantum_instance: Pending deprecation\: Quantum Instance or Backend + sampler: base sampler Raises: AlgorithmError: if the method to compute the confidence intervals is not supported @@ -89,6 +94,13 @@ def __init__( super().__init__() # set quantum instance + if quantum_instance is not None: + warnings.warn( + "The quantum_instance argument has been superseded by the sampler argument. " + "This argument will be deprecated in a future release and subsequently " + "removed after that.", + category=PendingDeprecationWarning, + ) self.quantum_instance = quantum_instance # store parameters @@ -96,10 +108,17 @@ def __init__( self._alpha = alpha self._min_ratio = min_ratio self._confint_method = confint_method + self._sampler = sampler @property + @deprecate_function( + "The IterativeAmplitudeEstimation.quantum_instance getter is pending deprecation. " + "This property will be deprecated in a future release and subsequently " + "removed after that.", + category=PendingDeprecationWarning, + ) def quantum_instance(self) -> Optional[QuantumInstance]: - """Get the quantum instance. + """Pending deprecation: Get the quantum instance. Returns: The quantum instance used to run this algorithm. @@ -107,8 +126,14 @@ def quantum_instance(self) -> Optional[QuantumInstance]: return self._quantum_instance @quantum_instance.setter + @deprecate_function( + "The IterativeAmplitudeEstimation.quantum_instance setter is pending deprecation. " + "This property will be deprecated in a future release and subsequently " + "removed after that.", + category=PendingDeprecationWarning, + ) def quantum_instance(self, quantum_instance: Union[QuantumInstance, Backend]) -> None: - """Set quantum instance. + """Pending deprecation: Set quantum instance. Args: quantum_instance: The quantum instance used to run this algorithm. diff --git a/qiskit/algorithms/amplitude_estimators/mlae.py b/qiskit/algorithms/amplitude_estimators/mlae.py index 21ca0cb35d1a..0ccc6d0c65e5 100644 --- a/qiskit/algorithms/amplitude_estimators/mlae.py +++ b/qiskit/algorithms/amplitude_estimators/mlae.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2018, 2020. +# (C) Copyright IBM 2018, 2022. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -13,6 +13,7 @@ """The Maximum Likelihood Amplitude Estimation algorithm.""" from typing import Optional, List, Union, Tuple, Dict, Callable +import warnings import numpy as np from scipy.optimize import brute from scipy.stats import norm, chi2 @@ -20,6 +21,8 @@ from qiskit.providers import Backend from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit from qiskit.utils import QuantumInstance +from qiskit.primitives import BaseSampler +from qiskit.utils.deprecation import deprecate_function from .amplitude_estimator import AmplitudeEstimator, AmplitudeEstimatorResult from .estimation_problem import EstimationProblem @@ -52,6 +55,7 @@ def __init__( evaluation_schedule: Union[List[int], int], minimizer: Optional[MINIMIZER] = None, quantum_instance: Optional[Union[QuantumInstance, Backend]] = None, + sampler: Optional[BaseSampler] = None, ) -> None: r""" Args: @@ -64,7 +68,8 @@ def __init__( according to ``evaluation_schedule``. The minimizer takes a function as first argument and a list of (float, float) tuples (as bounds) as second argument and returns a single float which is the found minimum. - quantum_instance: Quantum Instance or Backend + quantum_instance: Pending deprecation\: Quantum Instance or Backend + sampler: base sampler Raises: ValueError: If the number of oracle circuits is smaller than 1. @@ -73,6 +78,13 @@ def __init__( super().__init__() # set quantum instance + if quantum_instance is not None: + warnings.warn( + "The quantum_instance argument has been superseded by the sampler argument. " + "This argument will be deprecated in a future release and subsequently " + "removed after that.", + category=PendingDeprecationWarning, + ) self.quantum_instance = quantum_instance # get parameters @@ -98,9 +110,17 @@ def default_minimizer(objective_fn, bounds): else: self._minimizer = minimizer + self._sampler = sampler + @property + @deprecate_function( + "The MaximumLikelihoodAmplitudeEstimation.quantum_instance getter is pending deprecation. " + "This property will be deprecated in a future release and subsequently " + "removed after that.", + category=PendingDeprecationWarning, + ) def quantum_instance(self) -> Optional[QuantumInstance]: - """Get the quantum instance. + """Pending deprecation: Get the quantum instance. Returns: The quantum instance used to run this algorithm. @@ -108,8 +128,14 @@ def quantum_instance(self) -> Optional[QuantumInstance]: return self._quantum_instance @quantum_instance.setter + @deprecate_function( + "The MaximumLikelihoodAmplitudeEstimation.quantum_instance setter is pending deprecation. " + "This property will be deprecated in a future release and subsequently " + "removed after that.", + category=PendingDeprecationWarning, + ) def quantum_instance(self, quantum_instance: Union[QuantumInstance, Backend]) -> None: - """Set quantum instance. + """Pending deprecation: Set quantum instance. Args: quantum_instance: The quantum instance used to run this algorithm. @@ -148,7 +174,7 @@ def construct_circuits( qc_0.compose(estimation_problem.state_preparation, inplace=True) for k in self._evaluation_schedule: - qc_k = qc_0.copy(name="qc_a_q_%s" % k) + qc_k = qc_0.copy(name=f"qc_a_q_{k}") if k != 0: qc_k.compose(estimation_problem.grover_operator.power(k), inplace=True)