Repository: Qiskit/qiskit

Issue:
Bug using SNOBFIT in combination with UCCSD (VQE) / misleading function signature of optimizer SNOBFIT
When running a VQE algorithm with ansatz UCCSD the following error message shows up:
```
[...]
 File "C:\Users\poc\Anaconda3\envs\qiskit\lib\site-packages\qiskit_nature\algorithms\pes_samplers\bopes_sampler.py", line 175, in sample
    self._raw_results = self._run_points(points)
  File "C:\Users\poc\Anaconda3\envs\qiskit\lib\site-packages\qiskit_nature\algorithms\pes_samplers\bopes_sampler.py", line 201, in _run_points
    raw_result = self._run_single_point(point)  # dict of results
  File "C:\Users\poc\Anaconda3\envs\qiskit\lib\site-packages\qiskit_nature\algorithms\pes_samplers\bopes_sampler.py", line 259, in _run_single_point
    result = self._state_solver.solve(self._problem, aux_ops_current_step)
  File "C:\Users\poc\Anaconda3\envs\qiskit\lib\site-packages\qiskit_nature\algorithms\ground_state_solvers\ground_state_eigensolver.py", line 91, in solve
    raw_mes_result = self._solver.compute_minimum_eigenvalue(main_operator, aux_ops)  # type: ignore
  File "C:\Users\poc\Anaconda3\envs\qiskit\lib\site-packages\qiskit\algorithms\minimum_eigen_solvers\vqe.py", line 530, in compute_minimum_eigenvalue
    opt_result = self.optimizer.minimize(
  File "C:\Users\poc\Anaconda3\envs\qiskit\lib\site-packages\qiskit\algorithms\optimizers\snobfit.py", line 96, in minimize
    if abs(theta) > bounds[idx][0]:
TypeError: '>' not supported between instances of 'float' and 'NoneType'
```

In case of ansatz `EfficientSU2` the code runs fine, only with `UCCSD` I get the error.

I tracked down the error to be caused by missing parameter bounds. The function [signature](https://github.com/Qiskit/qiskit-terra/blob/cbb64ed266b55525738de20a4e43419d5fef6e32/qiskit/algorithms/optimizers/snobfit.py#L82) of the optimizer's `minimize` function (``) suggests that `None` is a valid value. But the code never handles None-type input (neither `None` nor the nested list/tuple with `None` values).

So, I propose one of the following changes:
- Change the signature of the `minimize` method (still not easy to read for a user)
- Catch the `None`s in the input bounds and add a more verbose error message that optimizer SNOBFIT requires parameter bounds
- Artificially add bounds for the optimizer. Basically the parameter can only be varied from 0 to 2pi so one could catch the `None` input and change it to these bounds. Though I'm not aware of the side effects this approach might have... Here it might be useful to ask also someone from qiskit nature whether it could be resolved within the UCCSD ansatz (though it would not solve the initial problem with the misleading signature/missing error message).

Any fixes (or suggestions therefore) are highly appreciated.



Discussion:
Thanks for reporting this!

If SNOBFIT requires bounds then I think the optimizer should raise an error if they are not passed. The interface is dictated by the `Optimizer` class so we can't really change that, and adding default bounds is very restrictive (e.g. [0,2pi] is not valid as soon as the circuit contains e.g. a gate like `Ry(0.0001 * theta)`).

Resolving patch:
diff --git a/qiskit/algorithms/optimizers/snobfit.py b/qiskit/algorithms/optimizers/snobfit.py
--- a/qiskit/algorithms/optimizers/snobfit.py
+++ b/qiskit/algorithms/optimizers/snobfit.py
@@ -84,6 +84,9 @@ def minimize(
         import skquant.opt as skq
         from SQSnobFit import optset
 
+        if bounds is None or any(None in bound_tuple for bound_tuple in bounds):
+            raise ValueError("Optimizer SNOBFIT requires bounds for all parameters.")
+
         snobfit_settings = {
             "maxmp": self._maxmp,
             "maxfail": self._maxfail,


Test patch:
diff --git a/test/python/algorithms/optimizers/test_optimizers_scikitquant.py b/test/python/algorithms/optimizers/test_optimizers_scikitquant.py
--- a/test/python/algorithms/optimizers/test_optimizers_scikitquant.py
+++ b/test/python/algorithms/optimizers/test_optimizers_scikitquant.py
@@ -13,8 +13,10 @@
 """ Test of scikit-quant optimizers. """
 
 import unittest
-
 from test.python.algorithms import QiskitAlgorithmsTestCase
+
+from ddt import ddt, data, unpack
+
 from qiskit import BasicAer
 from qiskit.circuit.library import RealAmplitudes
 from qiskit.utils import QuantumInstance, algorithm_globals
@@ -24,6 +26,7 @@
 from qiskit.algorithms.optimizers import BOBYQA, SNOBFIT, IMFIL
 
 
+@ddt
 class TestOptimizers(QiskitAlgorithmsTestCase):
     """Test scikit-quant optimizers."""
 
@@ -68,6 +71,21 @@ def test_snobfit(self):
         except MissingOptionalLibraryError as ex:
             self.skipTest(str(ex))
 
+    @data((None,), ([(-1, 1), (None, None)],))
+    @unpack
+    def test_snobfit_missing_bounds(self, bounds):
+        """SNOBFIT optimizer test with missing bounds."""
+        try:
+            optimizer = SNOBFIT()
+            with self.assertRaises(ValueError):
+                optimizer.minimize(
+                    fun=lambda _: 1,  # using dummy function (never called)
+                    x0=[0.1, 0.1],  # dummy initial point
+                    bounds=bounds,
+                )
+        except MissingOptionalLibraryError as ex:
+            self.skipTest(str(ex))
+
     def test_imfil(self):
         """IMFIL test."""
         try: