Search code examples
optimizationchemistryqiskit

issues encountered in using scikit-quant optimizers in Qiskit VQE workflows (Aer backend)


as I am testing all optimizers advised in qiskit.algorithms.optimizers reference page to evaluate their performance in a VQE qiskit nature workflow on the Aer backend with and without noise model, I decided to call scikit-quant optimizers BOBYQA, IMFIL and SNOBFIT using the same syntax I used for Local and Global Optimizers described in the same reference page.

vqe_solver = VQEUCCFactory(noisy_est, UCCSD(), BOBYQA())
from qiskit_nature.second_q.algorithms import GroundStateEigensolver

calc = GroundStateEigensolver(converter, vqe_solver)
res = calc.solve(problem)

With the other optimizers I encountered no issues at all and runs went fine. I expected to use the same syntax for scikit-quant optimizers, but that does not work.
I got issues with the three of the scikit-quant set, with different error messages.

You can read the backtraces below, purged by irrelevant file paths.

BOBIQA:

Traceback (most recent call last):
  File "...lib/python3.10/site-packages/qiskit/algorithms/minimum_eigensolvers/vqe.py", line 253, in evaluate_energy
    job = self.estimator.run(batch_size * [ansatz], batch_size * [operator], parameters)
  File "...lib/python3.10/site-packages/qiskit/primitives/base/base_estimator.py", line 222, in run
    parameter_values = self._validate_parameter_values(
  File "...lib/python3.10/site-packages/qiskit/primitives/base/base_primitive.py", line 108, in _validate_parameter_values
    raise TypeError("Invalid parameter values, expected Sequence[Sequence[float]].")
TypeError: Invalid parameter values, expected Sequence[Sequence[float]].

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File ".../test.py", line 159, in <module>
    res = calc.solve(problem)
  File ...lib/python3.10/site-packages/qiskit_nature/second_q/algorithms/ground_state_solvers/ground_state_eigensolver.py", line 96, in solve
    raw_mes_result = self.solver.compute_minimum_eigenvalue(  # type: ignore
  File "...lib/python3.10/site-packages/qiskit/algorithms/minimum_eigensolvers/vqe.py", line 191, in compute_minimum_eigenvalue
    optimizer_result = self.optimizer.minimize(
  File "...lib/python3.10/site-packages/qiskit/algorithms/optimizers/bobyqa.py", line 69, in minimize
    res, history = skq.minimize(
  File "...lib/python3.10/site-packages/skquant/opt/__init__.py", line 56, in minimize
    return optimizer.minimize(func, x0, bounds, budget, options, **optkwds)
  File "...lib/python3.10/site-packages/skquant/opt/_pybobyqa.py", line 33, in minimize
    result = pybobyqa.solve(
  File "...lib/python3.10/site-packages/pybobyqa/solver.py", line 809, in solve
    solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns, nf, nx, nsamples, params,
  File "...lib/python3.10/site-packages/pybobyqa/solver.py", line 157, in solve_main
    exit_info = control.initialise_coordinate_directions(number_of_samples, num_directions, params)
  File "...lib/python3.10/site-packages/pybobyqa/controller.py", line 181, in initialise_coordinate_directions
    f_list, num_samples_run, exit_info = self.evaluate_objective(x, number_of_samples, params)
  File "...lib/python3.10/site-packages/pybobyqa/controller.py", line 349, in evaluate_objective
    f_list[i] = eval_objective(self.objfun, remove_scaling(x, self.scaling_changes), self.args, eval_num=self.nf, pt_num=self.nx,
  File "...lib/python3.10/site-packages/pybobyqa/util.py", line 51, in eval_objective
    f = objfun(x, *args)
  File "...lib/python3.10/site-packages/SQCommon/_objective.py", line 24, in __call__
    result = self.objective(par)
  File "...lib/python3.10/site-packages/qiskit/algorithms/minimum_eigensolvers/vqe.py", line 256, in evaluate_energy
    raise AlgorithmError("The primitive job to evaluate the energy failed!") from exc
qiskit.algorithms.exceptions.AlgorithmError: 'The primitive job to evaluate the energy failed!

IMFIL:

Traceback (most recent call last):
  File ".../test.py", line 159, in <module>
    res = calc.solve(problem)
  File "...lib/python3.10/site-packages/qiskit_nature/second_q/algorithms/ground_state_solvers/ground_state_eigensolver.py", line 96, in solve
    raw_mes_result = self.solver.compute_minimum_eigenvalue(  # type: ignore
  File "...lib/python3.10/site-packages/qiskit/algorithms/minimum_eigensolvers/vqe.py", line 191, in compute_minimum_eigenvalue
    optimizer_result = self.optimizer.minimize(
  File "...lib/python3.10/site-packages/qiskit/algorithms/optimizers/imfil.py", line 72, in minimize
    res, history = skq.minimize(
  File "...ibm_sdk/lib/python3.10/site-packages/skquant/opt/__init__.py", line 56, in minimize
    return optimizer.minimize(func, x0, bounds, budget, options, **optkwds)
  File "...lib/python3.10/site-packages/SQImFil/_imfil.py", line 160, in minimize
    dbounds = bounds[:,(1,)] - bounds[:,(0,)]
TypeError: unsupported operand type(s) for -: 'NoneType' and 'NoneType'

SNOBFIT:

Traceback (most recent call last):
  File ".../test.py", line 159, in <module>
    res = calc.solve(problem)
  File "...lib/python3.10/site-packages/qiskit_nature/second_q/algorithms/ground_state_solvers/ground_state_eigensolver.py", line 96, in solve
    raw_mes_result = self.solver.compute_minimum_eigenvalue(  # type: ignore
  File "...lib/python3.10/site-packages/qiskit/algorithms/minimum_eigensolvers/vqe.py", line 191, in compute_minimum_eigenvalue
    optimizer_result = self.optimizer.minimize(
  File "...lib/python3.10/site-packages/qiskit/algorithms/optimizers/snobfit.py", line 99, in minimize
    raise ValueError("Optimizer SNOBFIT requires bounds for all parameters.")
ValueError: Optimizer SNOBFIT requires bounds for all parameters.

Can you suggest me specific workarounds for each of them, keeping into account that, for instance, SNOBFIT bounds may take into account that an UCCSD ansatz has been used? Thank you in advance.


Solution

  • Let me start out by mentioning there is an issue on Qiskit to address bounds that would also address the problem with those optimizers with UCC https://github.com/Qiskit/qiskit-terra/issues/9718. You can read more in that about what is happening etc. In the meanwhile I can give a workaround as described below.

    First I will point out your code above shows the use of Factories in Nature, and the workaround needs more direct access to the ansatz. Factories, I will note, were deprecated in the latest release Of Qiskit Nature with a migration guide to using UCC directly https://qiskit.org/ecosystem/nature/migration/0.6_b_mes_factory.html

    So the workaround comes down to this. You can set a different bounds on the anstaz, i.e. override its default, by doing this choosing some non-None bounds in my example +/-9999

    ansatz.parameter_bounds = [(-9999, 9999)]  * ansatz.num_parameters
    

    which will allow these optimizers to be then used with UCCSD - where anstaz is the above is whatever the UCCSD instance variable is you use.

    BUT.... in using UCCSD directly you do need to set the VQE initial point to ensure it starts in the HF state. You can follow the above migration guide and use the HFInitialPoint object or set all zeros NOT a random number. Otherwise the UCC will not start properly in the HartreeFock State and the answer is likely not to be correct. Setting all zeros for the VQE initial point, given the same ansatz, can be done as follows and ensures its size matches the ansatz

    initial_point = np.asarray([0] * ansatz.num_parameters)
    

    This following howto may also be of help as it covers using UCC with VQE https://qiskit.org/ecosystem/nature/howtos/vqe_ucc.html and also notes the above.