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.
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.