From e175b738d6db3b5f8fec5081dff91e1a91d18202 Mon Sep 17 00:00:00 2001 From: luciacuervovalor <67261900+luciacuervovalor@users.noreply.github.com> Date: Thu, 2 Feb 2023 13:00:08 +0100 Subject: [PATCH] Bug fix on QNSPSA (#9483) * Bug fix Old syntax was giving type error when dividing int by float * Bug fix * Convert to float to avoid type error * Add unit test * Add release note * Update releasenotes/notes/qnspsa-float-bug-fix-4035f7e1eb61dec2.yaml Co-authored-by: Julien Gacon * Ran black * Make unused argument explicitly ignored * Change to np array syntax * Pylint disable invalid name The name of variable "_y" must have this form because the argument is unused * Make black --------- Co-authored-by: Julien Gacon Co-authored-by: ElePT Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> (cherry picked from commit 2f49b5a5ba154245f4b78be8e635fea5aedf8de2) --- qiskit/algorithms/optimizers/qnspsa.py | 5 ++-- ...qnspsa-float-bug-fix-4035f7e1eb61dec2.yaml | 5 ++++ .../python/algorithms/optimizers/test_spsa.py | 25 +++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 releasenotes/notes/qnspsa-float-bug-fix-4035f7e1eb61dec2.yaml diff --git a/qiskit/algorithms/optimizers/qnspsa.py b/qiskit/algorithms/optimizers/qnspsa.py index b7ba29796205..207c9f59bbfb 100644 --- a/qiskit/algorithms/optimizers/qnspsa.py +++ b/qiskit/algorithms/optimizers/qnspsa.py @@ -228,9 +228,10 @@ def _point_sample(self, loss, x, eps, delta1, delta2): gradient_estimate = (loss_values[0] - loss_values[1]) / (2 * eps) * delta1 # compute the preconditioner point estimate + fidelity_values = np.asarray(fidelity_values, dtype=float) diff = fidelity_values[2] - fidelity_values[0] - diff -= fidelity_values[3] - fidelity_values[1] - diff /= 2 * eps**2 + diff = diff - (fidelity_values[3] - fidelity_values[1]) + diff = diff / (2 * eps**2) rank_one = np.outer(delta1, delta2) # -0.5 factor comes from the fact that we need -0.5 * fidelity diff --git a/releasenotes/notes/qnspsa-float-bug-fix-4035f7e1eb61dec2.yaml b/releasenotes/notes/qnspsa-float-bug-fix-4035f7e1eb61dec2.yaml new file mode 100644 index 000000000000..b5e6f63833b4 --- /dev/null +++ b/releasenotes/notes/qnspsa-float-bug-fix-4035f7e1eb61dec2.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixed bug in :class:`.QNSPSA` which raised a type error when the computed fidelities + happened to be integers but the perturbation was of type float. diff --git a/test/python/algorithms/optimizers/test_spsa.py b/test/python/algorithms/optimizers/test_spsa.py index c18d498291b8..8e48e2801bbf 100644 --- a/test/python/algorithms/optimizers/test_spsa.py +++ b/test/python/algorithms/optimizers/test_spsa.py @@ -255,3 +255,28 @@ def objective(x): with self.subTest("check number of function calls"): expected_nfev = 8 # 7 * maxiter + 1 self.assertEqual(result.nfev, expected_nfev) + + def test_point_sample(self): + """Test point sample function in QNSPSA""" + # pylint: disable=invalid-name + + def fidelity(x, _y): + x = np.asarray(x) + return np.ones_like(x, dtype=float) # some float + + def objective(x): + return x + + def get_perturbation(): + def perturbation(): + while True: + yield 1 + + return perturbation + + qnspsa = QNSPSA(fidelity, maxiter=1, learning_rate=0.1, perturbation=get_perturbation()) + initial_point = 1.0 + result = qnspsa.minimize(objective, initial_point) + + expected_nfev = 8 # 7 * maxiter + 1 + self.assertEqual(result.nfev, expected_nfev)