From 95d62b5c0f8c88392094a4bb3f8e10ea52bc8397 Mon Sep 17 00:00:00 2001 From: Ken Nakanishi Date: Wed, 20 Nov 2019 10:37:20 +0900 Subject: [PATCH 01/10] add NFT optimizer --- qiskit/aqua/components/optimizers/__init__.py | 4 +- qiskit/aqua/components/optimizers/nft.py | 192 ++++++++++++++++++ test/aqua/test_optimizers.py | 8 +- 3 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 qiskit/aqua/components/optimizers/nft.py diff --git a/qiskit/aqua/components/optimizers/__init__.py b/qiskit/aqua/components/optimizers/__init__.py index d58ab2c3ef..a35940ce6f 100644 --- a/qiskit/aqua/components/optimizers/__init__.py +++ b/qiskit/aqua/components/optimizers/__init__.py @@ -26,6 +26,7 @@ from .spsa import SPSA from .tnc import TNC from .aqgd import AQGD +from .nft import NFT __all__ = ['Optimizer', @@ -39,7 +40,8 @@ 'SLSQP', 'SPSA', 'TNC', - 'AQGD'] + 'AQGD', + 'NFT'] try: import nlopt diff --git a/qiskit/aqua/components/optimizers/nft.py b/qiskit/aqua/components/optimizers/nft.py new file mode 100644 index 0000000000..60d85425de --- /dev/null +++ b/qiskit/aqua/components/optimizers/nft.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- + +# This code is part of Qiskit. +# +# (C) Copyright IBM 2018, 2019. +# +# 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 +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +import logging + +import numpy as np +from scipy.optimize import minimize +from scipy.optimize import OptimizeResult + +from qiskit.aqua.components.optimizers import Optimizer + + +logger = logging.getLogger(__name__) + + +class NFT(Optimizer): + """Nakanishi-Fujii-Todo algorithm.""" + + CONFIGURATION = { + 'name': 'NFT', + 'description': 'NFT Optimizer', + 'input_schema': { + '$schema': 'http://json-schema.org/draft-07/schema#', + 'id': 'nft_schema', + 'type': 'object', + 'properties': { + 'maxiter': { + 'type': ['integer', 'null'], + 'default': None + }, + 'maxfev': { + 'type': ['integer', 'null'], + 'default': 1024 + }, + 'reset_interval': { + 'type': 'integer', + 'default': 32 + }, + 'disp': { + 'type': 'boolean', + 'default': False + }, + }, + 'additionalProperties': False + }, + 'support_level': { + 'gradient': Optimizer.SupportLevel.ignored, + 'bounds': Optimizer.SupportLevel.ignored, + 'initial_point': Optimizer.SupportLevel.required + }, + 'options': ['maxiter', 'maxfev', 'disp', 'reset_interval'], + 'optimizer': ['local'] + } + + # pylint: disable=unused-argument + def __init__(self, maxiter=None, maxfev=1024, disp=False, reset_interval=32): + """ + Constructor. + + For details, please refer to + https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html. + + Args: + maxiter (int): Maximum number of iterations to perform. + maxfev (int): Maximum number of function evaluations to perform. + reset_interval (int): The minimum estimates directly once + in``reset_interval`` times. + disp (bool): Set to True to print convergence messages. + """ + self.validate(locals()) + super().__init__() + for k, v in locals().items(): + if k in self._configuration['options']: + self._options[k] = v + + def optimize(self, num_vars, objective_function, gradient_function=None, + variable_bounds=None, initial_point=None): + super().optimize(num_vars, objective_function, gradient_function, + variable_bounds, initial_point) + + res = minimize(objective_function, initial_point, + method=nakanishi_fujii_todo, options=self._options) + return res.x, res.fun, res.nfev + + +def nakanishi_fujii_todo(fun, x0, args=(), maxiter=None, maxfev=1024, + reset_interval=32, eps=1e-32, callback=None, **_): + """ + Find the global minimum of a function using the nakanishi_fujii_todo + algorithm [1]. + Parameters + ---------- + fun : callable ``f(x, *args)`` + Function to be optimized. ``args`` can be passed as an optional item + in the dict ``minimizer_kwargs``. + This function must satisfy the three condition written in Ref. [1]. + x0 : ndarray, shape (n,) + Initial guess. Array of real elements of size (n,), + where 'n' is the number of independent variables. + args : tuple, optional + Extra arguments passed to the objective function. + maxiter : int + Maximum number of iterations to perform. + Default: None. + maxfev : int + Maximum number of function evaluations to perform. + Default: 1024. + reset_interval : int + The minimum estimates directly once in ``reset_interval`` times. + Default: 32. + callback : callable, optional + Called after each iteration. + Returns + ------- + res : OptimizeResult + The optimization result represented as a ``OptimizeResult`` object. + Important attributes are: ``x`` the solution array. See + `OptimizeResult` for a description of other attributes. + Notes + ----- + In this optimization method, the optimization function have to satisfy + three conditions written in [1]. + References + ---------- + .. [1] K. M. Nakanishi, K. Fujii, and S. Todo. 2019. + Sequential minimal optimization for quantum-classical hybrid algorithms. + arXiv preprint arXiv:1903.12166. + """ + + x0 = np.asarray(x0) + recycle_z0 = None + niter = 0 + funcalls = 0 + + while True: + + idx = niter % x0.size + + if reset_interval > 0: + if niter % reset_interval == 0: + recycle_z0 = None + + if recycle_z0 is None: + z0 = fun(np.copy(x0), *args) + funcalls += 1 + else: + z0 = recycle_z0 + + p = np.copy(x0) + p[idx] = x0[idx] + np.pi / 2 + z1 = fun(p, *args) + funcalls += 1 + + p = np.copy(x0) + p[idx] = x0[idx] - np.pi / 2 + z3 = fun(p, *args) + funcalls += 1 + + z2 = z1 + z3 - z0 + c = (z1 + z3) / 2 + a = np.sqrt((z0 - z2) ** 2 + (z1 - z3) ** 2) / 2 + b = np.arctan((z1 - z3) / ((z0 - z2) + eps * (z0 == z2))) + x0[idx] + b += 0.5 * np.pi + 0.5 * np.pi * np.sign((z0 - z2) + eps * (z0 == z2)) + + x0[idx] = b + recycle_z0 = c - a + + niter += 1 + + if callback is not None: + callback(np.copy(x0)) + + if maxfev is not None: + if funcalls >= maxfev: + break + + if maxiter is not None: + if niter >= maxiter: + break + + return OptimizeResult(fun=fun(np.copy(x0)), x=x0, nit=niter, nfev=funcalls, success=(niter > 1)) diff --git a/test/aqua/test_optimizers.py b/test/aqua/test_optimizers.py index ab3399cc65..b7f07af6f9 100644 --- a/test/aqua/test_optimizers.py +++ b/test/aqua/test_optimizers.py @@ -22,7 +22,7 @@ from qiskit.aqua import aqua_globals from qiskit.aqua.components.optimizers import (ADAM, CG, COBYLA, L_BFGS_B, NELDER_MEAD, - POWELL, SLSQP, SPSA, TNC) + POWELL, SLSQP, SPSA, TNC, NFT) class TestOptimizers(QiskitAquaTestCase): @@ -93,6 +93,12 @@ def test_tnc(self): res = self._optimize(optimizer) self.assertLessEqual(res[2], 10000) + def test_nft(self): + """ nft test """ + optimizer = NFT(maxfev=10000, reset_interval=32) + res = self._optimize(optimizer) + self.assertLessEqual(res[2], 10000) + if __name__ == '__main__': unittest.main() From 669c568ec3a3eb3857869e0aa6be01b542825aec Mon Sep 17 00:00:00 2001 From: Ken Nakanishi Date: Wed, 20 Nov 2019 10:54:32 +0900 Subject: [PATCH 02/10] update docstring --- qiskit/aqua/components/optimizers/nft.py | 74 ++++++++++++------------ 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/qiskit/aqua/components/optimizers/nft.py b/qiskit/aqua/components/optimizers/nft.py index 60d85425de..1f7b876dda 100644 --- a/qiskit/aqua/components/optimizers/nft.py +++ b/qiskit/aqua/components/optimizers/nft.py @@ -76,7 +76,13 @@ def __init__(self, maxiter=None, maxfev=1024, disp=False, reset_interval=32): maxfev (int): Maximum number of function evaluations to perform. reset_interval (int): The minimum estimates directly once in``reset_interval`` times. - disp (bool): Set to True to print convergence messages. + Notes: + In this optimization method, the optimization function have to satisfy + three conditions written in [1]. + References: + .. [1] K. M. Nakanishi, K. Fujii, and S. Todo. 2019. + Sequential minimal optimization for quantum-classical hybrid algorithms. + arXiv preprint arXiv:1903.12166. """ self.validate(locals()) super().__init__() @@ -99,41 +105,37 @@ def nakanishi_fujii_todo(fun, x0, args=(), maxiter=None, maxfev=1024, """ Find the global minimum of a function using the nakanishi_fujii_todo algorithm [1]. - Parameters - ---------- - fun : callable ``f(x, *args)`` - Function to be optimized. ``args`` can be passed as an optional item - in the dict ``minimizer_kwargs``. - This function must satisfy the three condition written in Ref. [1]. - x0 : ndarray, shape (n,) - Initial guess. Array of real elements of size (n,), - where 'n' is the number of independent variables. - args : tuple, optional - Extra arguments passed to the objective function. - maxiter : int - Maximum number of iterations to perform. - Default: None. - maxfev : int - Maximum number of function evaluations to perform. - Default: 1024. - reset_interval : int - The minimum estimates directly once in ``reset_interval`` times. - Default: 32. - callback : callable, optional - Called after each iteration. - Returns - ------- - res : OptimizeResult - The optimization result represented as a ``OptimizeResult`` object. - Important attributes are: ``x`` the solution array. See - `OptimizeResult` for a description of other attributes. - Notes - ----- - In this optimization method, the optimization function have to satisfy - three conditions written in [1]. - References - ---------- - .. [1] K. M. Nakanishi, K. Fujii, and S. Todo. 2019. + Args: + fun (callable ``f(x, *args)``): + Function to be optimized. ``args`` can be passed as an optional item + in the dict ``minimizer_kwargs``. + This function must satisfy the three condition written in Ref. [1]. + x0 (ndarray, shape (n,)): + Initial guess. Array of real elements of size (n,), + where 'n' is the number of independent variables. + args (tuple, optional): + Extra arguments passed to the objective function. + maxiter (int): + Maximum number of iterations to perform. + Default: None. + maxfev (int): + Maximum number of function evaluations to perform. + Default: 1024. + reset_interval (int): + The minimum estimates directly once in ``reset_interval`` times. + Default: 32. + callback (callable, optional): + Called after each iteration. + Returns: + res (OptimizeResult): + The optimization result represented as a ``OptimizeResult`` object. + Important attributes are: ``x`` the solution array. See + `OptimizeResult` for a description of other attributes. + Notes: + In this optimization method, the optimization function have to satisfy + three conditions written in [1]. + References: + .. [1] K. M. Nakanishi, K. Fujii, and S. Todo. 2019. Sequential minimal optimization for quantum-classical hybrid algorithms. arXiv preprint arXiv:1903.12166. """ From 3a7dbfa8b7c2cb7c597061405a18f70f37b439e9 Mon Sep 17 00:00:00 2001 From: Manoel Marques Date: Wed, 20 Nov 2019 10:03:44 -0500 Subject: [PATCH 03/10] fix lint --- .pylintdict | 4 ++++ .pylintrc | 4 ++-- qiskit/aqua/components/optimizers/nft.py | 14 ++++++++++---- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.pylintdict b/.pylintdict index 1fc8ab8c51..4fc47a1242 100644 --- a/.pylintdict +++ b/.pylintdict @@ -151,6 +151,7 @@ formatter fortran fourier ftol +Fujii fullname func gambetta @@ -268,6 +269,7 @@ msq multiclass multinomial multiprocess +Nakanishi nan narray nasdaq @@ -278,6 +280,7 @@ ndarray's nelder nevals nfev +nft nk nlopt nn @@ -431,6 +434,7 @@ tiajb tibja timestamp tnc +Todo toffoli tol tomo diff --git a/.pylintrc b/.pylintrc index 6040fbfed6..7855ee3139 100644 --- a/.pylintrc +++ b/.pylintrc @@ -72,7 +72,7 @@ disable=no-self-use, # disabled as it is too verbose too-many-public-methods, too-few-public-methods, too-many-ancestors, unnecessary-pass, # allow for methods with just "pass", for clarity no-else-return, # relax "elif" after a clause with a return - docstring-first-line-empty # relax docstring style + docstring-first-line-empty, # relax docstring style @@ -172,7 +172,7 @@ attr-rgx=[a-z_][a-z0-9_]{2,30}$ attr-name-hint=[a-z_][a-z0-9_]{2,30}$ # Regular expression matching correct argument names -argument-rgx=[a-z_][a-z0-9_]{2,30}$ +argument-rgx=[a-z_][a-z0-9_]{2,30}|ax$ # Naming hint for argument names argument-name-hint=[a-z_][a-z0-9_]{2,30}$ diff --git a/qiskit/aqua/components/optimizers/nft.py b/qiskit/aqua/components/optimizers/nft.py index 1f7b876dda..6e933751e8 100644 --- a/qiskit/aqua/components/optimizers/nft.py +++ b/qiskit/aqua/components/optimizers/nft.py @@ -2,7 +2,7 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2018, 2019. +# (C) Copyright IBM 2019. # # 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 @@ -12,6 +12,8 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. +"""Nakanishi-Fujii-Todo algorithm.""" + import logging import numpy as np @@ -74,6 +76,7 @@ def __init__(self, maxiter=None, maxfev=1024, disp=False, reset_interval=32): Args: maxiter (int): Maximum number of iterations to perform. maxfev (int): Maximum number of function evaluations to perform. + disp (bool): disp reset_interval (int): The minimum estimates directly once in``reset_interval`` times. Notes: @@ -100,17 +103,18 @@ def optimize(self, num_vars, objective_function, gradient_function=None, return res.x, res.fun, res.nfev +# pylint: disable=invalid-name def nakanishi_fujii_todo(fun, x0, args=(), maxiter=None, maxfev=1024, reset_interval=32, eps=1e-32, callback=None, **_): """ Find the global minimum of a function using the nakanishi_fujii_todo algorithm [1]. Args: - fun (callable ``f(x, *args)``): + fun (callable): ``f(x, *args)`` Function to be optimized. ``args`` can be passed as an optional item in the dict ``minimizer_kwargs``. This function must satisfy the three condition written in Ref. [1]. - x0 (ndarray, shape (n,)): + x0 (ndarray): shape (n,) Initial guess. Array of real elements of size (n,), where 'n' is the number of independent variables. args (tuple, optional): @@ -124,10 +128,12 @@ def nakanishi_fujii_todo(fun, x0, args=(), maxiter=None, maxfev=1024, reset_interval (int): The minimum estimates directly once in ``reset_interval`` times. Default: 32. + eps (float): eps + **_ : additional options callback (callable, optional): Called after each iteration. Returns: - res (OptimizeResult): + OptimizeResult: The optimization result represented as a ``OptimizeResult`` object. Important attributes are: ``x`` the solution array. See `OptimizeResult` for a description of other attributes. From a7943f8886edb781d3b0bb9142c58ba6da2c016a Mon Sep 17 00:00:00 2001 From: Manoel Marques Date: Fri, 27 Dec 2019 11:33:13 -0500 Subject: [PATCH 04/10] fix lint --- qiskit/aqua/components/optimizers/nft.py | 69 ++++++++++++------------ 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/qiskit/aqua/components/optimizers/nft.py b/qiskit/aqua/components/optimizers/nft.py index 6e933751e8..b22aa3378c 100644 --- a/qiskit/aqua/components/optimizers/nft.py +++ b/qiskit/aqua/components/optimizers/nft.py @@ -19,7 +19,7 @@ import numpy as np from scipy.optimize import minimize from scipy.optimize import OptimizeResult - +from qiskit.aqua.utils.validation import validate from qiskit.aqua.components.optimizers import Optimizer @@ -29,42 +29,33 @@ class NFT(Optimizer): """Nakanishi-Fujii-Todo algorithm.""" - CONFIGURATION = { - 'name': 'NFT', - 'description': 'NFT Optimizer', - 'input_schema': { - '$schema': 'http://json-schema.org/draft-07/schema#', - 'id': 'nft_schema', - 'type': 'object', - 'properties': { - 'maxiter': { - 'type': ['integer', 'null'], - 'default': None - }, - 'maxfev': { - 'type': ['integer', 'null'], - 'default': 1024 - }, - 'reset_interval': { - 'type': 'integer', - 'default': 32 - }, - 'disp': { - 'type': 'boolean', - 'default': False - }, + _INPUT_SCHEMA = { + '$schema': 'http://json-schema.org/draft-07/schema#', + 'id': 'nft_schema', + 'type': 'object', + 'properties': { + 'maxiter': { + 'type': ['integer', 'null'], + 'default': None + }, + 'maxfev': { + 'type': ['integer', 'null'], + 'default': 1024 + }, + 'reset_interval': { + 'type': 'integer', + 'default': 32 + }, + 'disp': { + 'type': 'boolean', + 'default': False }, - 'additionalProperties': False - }, - 'support_level': { - 'gradient': Optimizer.SupportLevel.ignored, - 'bounds': Optimizer.SupportLevel.ignored, - 'initial_point': Optimizer.SupportLevel.required }, - 'options': ['maxiter', 'maxfev', 'disp', 'reset_interval'], - 'optimizer': ['local'] + 'additionalProperties': False } + _OPTIONS = ['maxiter', 'maxfev', 'disp', 'reset_interval'] + # pylint: disable=unused-argument def __init__(self, maxiter=None, maxfev=1024, disp=False, reset_interval=32): """ @@ -87,12 +78,20 @@ def __init__(self, maxiter=None, maxfev=1024, disp=False, reset_interval=32): Sequential minimal optimization for quantum-classical hybrid algorithms. arXiv preprint arXiv:1903.12166. """ - self.validate(locals()) + validate(locals(), self._INPUT_SCHEMA) super().__init__() for k, v in locals().items(): - if k in self._configuration['options']: + if k in self._OPTIONS: self._options[k] = v + def get_support_level(self): + """ return support level dictionary """ + return { + 'gradient': Optimizer.SupportLevel.ignored, + 'bounds': Optimizer.SupportLevel.ignored, + 'initial_point': Optimizer.SupportLevel.required + } + def optimize(self, num_vars, objective_function, gradient_function=None, variable_bounds=None, initial_point=None): super().optimize(num_vars, objective_function, gradient_function, From b9fec3a9dece3b144a155d3069d2c1afa4b714e5 Mon Sep 17 00:00:00 2001 From: Manoel Marques Date: Tue, 7 Jan 2020 20:13:08 -0500 Subject: [PATCH 05/10] remove json schema --- qiskit/aqua/components/optimizers/nft.py | 44 ++++++------------------ 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/qiskit/aqua/components/optimizers/nft.py b/qiskit/aqua/components/optimizers/nft.py index b22aa3378c..d5ae953a38 100644 --- a/qiskit/aqua/components/optimizers/nft.py +++ b/qiskit/aqua/components/optimizers/nft.py @@ -14,13 +14,13 @@ """Nakanishi-Fujii-Todo algorithm.""" +from typing import Optional import logging import numpy as np from scipy.optimize import minimize from scipy.optimize import OptimizeResult -from qiskit.aqua.utils.validation import validate -from qiskit.aqua.components.optimizers import Optimizer +from .optimizer import Optimizer logger = logging.getLogger(__name__) @@ -29,35 +29,14 @@ class NFT(Optimizer): """Nakanishi-Fujii-Todo algorithm.""" - _INPUT_SCHEMA = { - '$schema': 'http://json-schema.org/draft-07/schema#', - 'id': 'nft_schema', - 'type': 'object', - 'properties': { - 'maxiter': { - 'type': ['integer', 'null'], - 'default': None - }, - 'maxfev': { - 'type': ['integer', 'null'], - 'default': 1024 - }, - 'reset_interval': { - 'type': 'integer', - 'default': 32 - }, - 'disp': { - 'type': 'boolean', - 'default': False - }, - }, - 'additionalProperties': False - } - _OPTIONS = ['maxiter', 'maxfev', 'disp', 'reset_interval'] # pylint: disable=unused-argument - def __init__(self, maxiter=None, maxfev=1024, disp=False, reset_interval=32): + def __init__(self, + maxiter: Optional[int] = None, + maxfev: int = 1024, + disp: bool = False, + reset_interval: int = 32) -> None: """ Constructor. @@ -65,10 +44,10 @@ def __init__(self, maxiter=None, maxfev=1024, disp=False, reset_interval=32): https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html. Args: - maxiter (int): Maximum number of iterations to perform. - maxfev (int): Maximum number of function evaluations to perform. - disp (bool): disp - reset_interval (int): The minimum estimates directly once + maxiter: Maximum number of iterations to perform. + maxfev: Maximum number of function evaluations to perform. + disp: disp + reset_interval: The minimum estimates directly once in``reset_interval`` times. Notes: In this optimization method, the optimization function have to satisfy @@ -78,7 +57,6 @@ def __init__(self, maxiter=None, maxfev=1024, disp=False, reset_interval=32): Sequential minimal optimization for quantum-classical hybrid algorithms. arXiv preprint arXiv:1903.12166. """ - validate(locals(), self._INPUT_SCHEMA) super().__init__() for k, v in locals().items(): if k in self._OPTIONS: From ab6eefe59f2058f68a8e6bbd5b4015af8ccbe3d9 Mon Sep 17 00:00:00 2001 From: Manoel Marques Date: Fri, 10 Jan 2020 10:38:44 -0500 Subject: [PATCH 06/10] Fix docstring --- qiskit/aqua/components/optimizers/nft.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/qiskit/aqua/components/optimizers/nft.py b/qiskit/aqua/components/optimizers/nft.py index d5ae953a38..d55ed9a53b 100644 --- a/qiskit/aqua/components/optimizers/nft.py +++ b/qiskit/aqua/components/optimizers/nft.py @@ -48,14 +48,16 @@ def __init__(self, maxfev: Maximum number of function evaluations to perform. disp: disp reset_interval: The minimum estimates directly once - in``reset_interval`` times. + in``reset_interval`` times. + Notes: In this optimization method, the optimization function have to satisfy - three conditions written in [1]. + three conditions written in [1]_. + References: .. [1] K. M. Nakanishi, K. Fujii, and S. Todo. 2019. - Sequential minimal optimization for quantum-classical hybrid algorithms. - arXiv preprint arXiv:1903.12166. + Sequential minimal optimization for quantum-classical hybrid algorithms. + arXiv preprint arXiv:1903.12166. """ super().__init__() for k, v in locals().items(): From 2133e9b8da190fe48dd47703d1b31c229dfb4d2f Mon Sep 17 00:00:00 2001 From: Manoel Marques Date: Sat, 1 Feb 2020 11:13:34 -0500 Subject: [PATCH 07/10] fix copyright year --- qiskit/aqua/components/optimizers/nft.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/aqua/components/optimizers/nft.py b/qiskit/aqua/components/optimizers/nft.py index d55ed9a53b..8f3454caa2 100644 --- a/qiskit/aqua/components/optimizers/nft.py +++ b/qiskit/aqua/components/optimizers/nft.py @@ -2,7 +2,7 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2019. +# (C) Copyright IBM 2019, 2020. # # 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 From 5419e5d982bb5aa2b2ad6c08278c1b1a2679103d Mon Sep 17 00:00:00 2001 From: woodsp Date: Wed, 25 Mar 2020 15:09:47 -0400 Subject: [PATCH 08/10] Add specific unit test for NFT --- .pylintdict | 1 - .pylintrc | 4 +- qiskit/aqua/components/optimizers/nft.py | 12 +++--- test/aqua/test_optimizer_nft.py | 53 ++++++++++++++++++++++++ test/aqua/test_optimizers.py | 8 +--- 5 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 test/aqua/test_optimizer_nft.py diff --git a/.pylintdict b/.pylintdict index a2f5955369..04192e5fc3 100644 --- a/.pylintdict +++ b/.pylintdict @@ -522,7 +522,6 @@ tibja timelimit timestamp tnc -Todo toctree toffoli tol diff --git a/.pylintrc b/.pylintrc index 7855ee3139..6040fbfed6 100644 --- a/.pylintrc +++ b/.pylintrc @@ -72,7 +72,7 @@ disable=no-self-use, # disabled as it is too verbose too-many-public-methods, too-few-public-methods, too-many-ancestors, unnecessary-pass, # allow for methods with just "pass", for clarity no-else-return, # relax "elif" after a clause with a return - docstring-first-line-empty, # relax docstring style + docstring-first-line-empty # relax docstring style @@ -172,7 +172,7 @@ attr-rgx=[a-z_][a-z0-9_]{2,30}$ attr-name-hint=[a-z_][a-z0-9_]{2,30}$ # Regular expression matching correct argument names -argument-rgx=[a-z_][a-z0-9_]{2,30}|ax$ +argument-rgx=[a-z_][a-z0-9_]{2,30}$ # Naming hint for argument names argument-name-hint=[a-z_][a-z0-9_]{2,30}$ diff --git a/qiskit/aqua/components/optimizers/nft.py b/qiskit/aqua/components/optimizers/nft.py index 8f3454caa2..6068e12702 100644 --- a/qiskit/aqua/components/optimizers/nft.py +++ b/qiskit/aqua/components/optimizers/nft.py @@ -27,7 +27,11 @@ class NFT(Optimizer): - """Nakanishi-Fujii-Todo algorithm.""" + """ + Nakanishi-Fujii-Todo algorithm. + + See https://arxiv.org/abs/1903.12166 + """ _OPTIONS = ['maxiter', 'maxfev', 'disp', 'reset_interval'] @@ -38,9 +42,7 @@ def __init__(self, disp: bool = False, reset_interval: int = 32) -> None: """ - Constructor. - - For details, please refer to + Built out using scipy framework, for details, please refer to https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html. Args: @@ -48,7 +50,7 @@ def __init__(self, maxfev: Maximum number of function evaluations to perform. disp: disp reset_interval: The minimum estimates directly once - in``reset_interval`` times. + in ``reset_interval`` times. Notes: In this optimization method, the optimization function have to satisfy diff --git a/test/aqua/test_optimizer_nft.py b/test/aqua/test_optimizer_nft.py new file mode 100644 index 0000000000..d9ec5f439b --- /dev/null +++ b/test/aqua/test_optimizer_nft.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- + +# This code is part of Qiskit. +# +# (C) Copyright IBM 2020 +# +# 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 +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +""" Test of NFT optimizer """ + +from test.aqua import QiskitAquaTestCase +from qiskit import BasicAer + +from qiskit.aqua import QuantumInstance, aqua_globals +from qiskit.aqua.operators import WeightedPauliOperator +from qiskit.aqua.components.variational_forms import RY +from qiskit.aqua.components.optimizers import NFT +from qiskit.aqua.algorithms import VQE + + +class TestOptimizerNFT(QiskitAquaTestCase): + """ Test NFT optimizer using RY with VQE """ + + def setUp(self): + super().setUp() + self.seed = 50 + aqua_globals.random_seed = self.seed + pauli_dict = { + 'paulis': [{"coeff": {"imag": 0.0, "real": -1.052373245772859}, "label": "II"}, + {"coeff": {"imag": 0.0, "real": 0.39793742484318045}, "label": "IZ"}, + {"coeff": {"imag": 0.0, "real": -0.39793742484318045}, "label": "ZI"}, + {"coeff": {"imag": 0.0, "real": -0.01128010425623538}, "label": "ZZ"}, + {"coeff": {"imag": 0.0, "real": 0.18093119978423156}, "label": "XX"} + ] + } + self.qubit_op = WeightedPauliOperator.from_dict(pauli_dict) + + def test_nft(self): + """ Test NFT optimizer by using it """ + + result = VQE(self.qubit_op, + RY(self.qubit_op.num_qubits), + NFT()).run( + QuantumInstance(BasicAer.get_backend('statevector_simulator'), + seed_simulator=aqua_globals.random_seed, + seed_transpiler=aqua_globals.random_seed)) + self.assertAlmostEqual(result.eigenvalue.real, -1.857275, places=6) diff --git a/test/aqua/test_optimizers.py b/test/aqua/test_optimizers.py index ccd0207535..6d854eefa9 100644 --- a/test/aqua/test_optimizers.py +++ b/test/aqua/test_optimizers.py @@ -22,7 +22,7 @@ from qiskit.aqua import aqua_globals from qiskit.aqua.components.optimizers import (ADAM, CG, COBYLA, L_BFGS_B, P_BFGS, NELDER_MEAD, - POWELL, SLSQP, SPSA, TNC, NFT) + POWELL, SLSQP, SPSA, TNC) class TestOptimizers(QiskitAquaTestCase): @@ -99,12 +99,6 @@ def test_tnc(self): res = self._optimize(optimizer) self.assertLessEqual(res[2], 10000) - def test_nft(self): - """ nft test """ - optimizer = NFT(maxfev=10000, reset_interval=32) - res = self._optimize(optimizer) - self.assertLessEqual(res[2], 10000) - if __name__ == '__main__': unittest.main() From 068c11614659d4fd8f63680787637e07b2463057 Mon Sep 17 00:00:00 2001 From: woodsp Date: Wed, 25 Mar 2020 15:44:27 -0400 Subject: [PATCH 09/10] Spelling and changelog --- .pylintdict | 1 + CHANGELOG.md | 1 + 2 files changed, 2 insertions(+) diff --git a/.pylintdict b/.pylintdict index 04192e5fc3..c8dbe9da03 100644 --- a/.pylintdict +++ b/.pylintdict @@ -523,6 +523,7 @@ timelimit timestamp tnc toctree +Todo toffoli tol tomo diff --git a/CHANGELOG.md b/CHANGELOG.md index 568f2e2fa2..508912c90c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Changelog](http://keepachangelog.com/en/1.0.0/). Added ----- +- NFT optimizer, part of a project of Qiskit Camp Asia 2019 (#759) - Algorithm interface and result classes (#849) - Chemistry FCIDump file driver (#859) - Chemistry stack automatic Z2 symmetry reduction (#870) From c23dba4f11dcd766f847cef0ffc0aa0bad75ae46 Mon Sep 17 00:00:00 2001 From: woodsp Date: Wed, 25 Mar 2020 15:45:40 -0400 Subject: [PATCH 10/10] Spelling and changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 508912c90c..fa6f556574 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ Changelog](http://keepachangelog.com/en/1.0.0/). Added ----- -- NFT optimizer, part of a project of Qiskit Camp Asia 2019 (#759) +- NFT optimizer, part of a project of Qiskit Camp Asia 2019 (#729) - Algorithm interface and result classes (#849) - Chemistry FCIDump file driver (#859) - Chemistry stack automatic Z2 symmetry reduction (#870)