Qiskit / qiskit

Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
https://www.ibm.com/quantum/qiskit
Apache License 2.0
5.28k stars 2.37k forks source link

VQE callback with gradient in some cases only records a single iteration #8726

Closed jiayu-shen closed 1 year ago

jiayu-shen commented 2 years ago

Environment

What is happening?

When gradient is passed into VQE, with some combinations of grad_method and the optimizer, only a single iteration is passed into the callback function of VQE.

How can we reproduce the issue?

The code is modified from https://qiskit.org/documentation/tutorials/algorithms/02_vqe_convergence.html.

import numpy as np
import pylab

from qiskit import Aer
from qiskit.opflow import X, Z, I
from qiskit.utils import QuantumInstance, algorithm_globals
from qiskit.algorithms import VQE, NumPyMinimumEigensolver
from qiskit.algorithms.optimizers import COBYLA, L_BFGS_B, SLSQP, ADAM, CG, SPSA
from qiskit.circuit.library import TwoLocal

from qiskit.opflow.gradients import Gradient

H2_op = (-1.052373245772859 * I ^ I) + \
        (0.39793742484318045 * I ^ Z) + \
        (-0.39793742484318045 * Z ^ I) + \
        (-0.01128010425623538 * Z ^ Z) + \
        (0.18093119978423156 * X ^ X)

algorithm_globals.random_seed = 50
ansatz = TwoLocal(rotation_blocks='ry', entanglement_blocks='cz')

optimizer = SLSQP(maxiter=60)

counts = []
values = []
def store_intermediate_result(eval_count, parameters, mean, std):
    counts.append(eval_count)
    values.append(mean)

vqe = VQE(ansatz, optimizer, callback=store_intermediate_result,
          gradient=Gradient(grad_method='fin_diff'),
          quantum_instance=QuantumInstance(backend=Aer.get_backend('statevector_simulator')))
result = vqe.compute_minimum_eigenvalue(operator=H2_op)
print(f'Value using Gradient: {result.eigenvalue.real:.5f}')

The last plot on the original page does not display a point, but if we plot the callback result with the marker set explicitly, the single point shows up.

pylab.rcParams['figure.figsize'] = (12, 8)
pylab.plot(counts, values, label=type(optimizer).__name__, marker='.')
pylab.xlabel('Eval count')
pylab.ylabel('Energy')
pylab.title('Energy convergence using Gradient')
pylab.legend(loc='upper right');

image This plot is supposed to show a history in optimization, but only a single iteration is passed into the callback. This single value is probably the very first iteration. The ipynb file https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/02_vqe_convergence.ipynb, however, did display a plot of history.

The same issue occurs when only the optimizer is changed to ADAM optimizer = ADAM(maxiter=60, lr=0.01) still with gradient=Gradient(grad_method='fin_diff'), the output is a single point with Value using Gradient: -1.07393. With ADAM optimizer = ADAM(maxiter=60, lr=0.01) and gradient=Gradient(grad_method='param_shift') in VQE, the code takes longer to run, and produces still a single point but at a lower value Value using Gradient: -1.81570.

When using NaturalGradient(grad_method='param_shift', qfi_method='lin_comb_full', regularization='ridge') as the gradient in VQE and optimizer = GradientDescent(maxiter=10), there is still a single point at -1.181444027905341, as is shown in the plot below image Changing from grad_method='param_shift' to grad_method='lin_comb' has a similar issue.

What should happen?

For the cases of the original tutorial page, "ADAM + Gradient(grad_method='param_shift')", and "GradientDescent + NaturalGradient", the callback is expected to store the history of optimization.

Any suggestions?

No response

woodsp-ibm commented 1 year ago

This is for the older QuantumInstance based VQE. The new VQE uses the new gradients. The older VQE is now deprecated and soon to be removed. As such I am going to close this as at this stage, even if the problem still exists, its not going to get addressed.