I am trying to solve the Vertex Cover problem using QAOA on an IBM Quantum backend. I've successfully converted my graph into a QUBO formulation and then into an Ising Hamiltonian format. However, when I attempt to run my quantum circuit on the backend, it doesn't work as expected.
Here’s my code:
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler, Session
from qiskit_optimization.algorithms import MinimumEigenOptimizer
from qiskit_algorithms import QAOA
from qiskit_algorithms.optimizers import COBYLA
from qiskit_algorithms.utils import algorithm_globals
service = QiskitRuntimeService(channel="ibm_quantum", token="mytoken")
backend = service.backend("ibm_sherbrooke")
# QAOA configuration
algorithm_globals.random_seed = 123
sampler = Sampler(mode=backend)
qaoa = QAOA(sampler=sampler, optimizer=COBYLA(), reps=3)
# Use QAOA as the optimizer
optimizer = MinimumEigenOptimizer(qaoa)
# Solve the problem
result = optimizer.solve(qubo)
# Display results
print(result)
This the error message which I get after running the code:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[25], line 19
16 optimizer = MinimumEigenOptimizer(qaoa)
18 # Problem lösen
---> 19 result = optimizer.solve(qubo)
21 # Ergebnisse anzeigen
22 print(result)
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\qiskit_optimization\algorithms\minimum_eigen_optimizer.py:205, in MinimumEigenOptimizer.solve(self, problem)
202 # construct operator and offset
203 operator, offset = problem_.to_ising()
--> 205 return self._solve_internal(operator, offset, problem_, problem)
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\qiskit_optimization\algorithms\minimum_eigen_optimizer.py:218, in MinimumEigenOptimizer._solve_internal(self, operator, offset, converted_problem, original_problem)
215 eigen_result: Optional[MinimumEigensolverResult] = None
216 if operator.num_qubits > 0:
217 # approximate ground state of operator using min eigen solver
--> 218 eigen_result = self._min_eigen_solver.compute_minimum_eigenvalue(operator)
219 # analyze results
220 raw_samples = None
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\qiskit_algorithms\minimum_eigensolvers\sampling_vqe.py:225, in SamplingVQE.compute_minimum_eigenvalue(self, operator, aux_operators)
220 else:
221 # we always want to submit as many estimations per job as possible for minimal
222 # overhead on the hardware
223 was_updated = _set_default_batchsize(self.optimizer)
--> 225 optimizer_result = self.optimizer.minimize(
226 fun=evaluate_energy, # type: ignore[arg-type]
227 x0=initial_point,
228 bounds=bounds,
229 )
231 # reset to original value
232 if was_updated:
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\qiskit_algorithms\optimizers\scipy_optimizer.py:148, in SciPyOptimizer.minimize(self, fun, x0, jac, bounds)
145 swapped_deprecated_args = True
146 self._options["maxfun"] = self._options.pop("maxiter")
--> 148 raw_result = minimize(
149 fun=fun,
150 x0=x0,
151 method=self._method,
152 jac=jac,
153 bounds=bounds,
154 options=self._options,
155 **self._kwargs,
156 )
157 if swapped_deprecated_args:
158 self._options["maxiter"] = self._options.pop("maxfun")
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\scipy\optimize\_minimize.py:737, in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)
734 res = _minimize_tnc(fun, x0, args, jac, bounds, callback=callback,
735 **options)
736 elif meth == 'cobyla':
--> 737 res = _minimize_cobyla(fun, x0, args, constraints, callback=callback,
738 bounds=bounds, **options)
739 elif meth == 'cobyqa':
740 res = _minimize_cobyqa(fun, x0, args, bounds, constraints, callback,
741 **options)
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\scipy\optimize\_cobyla_py.py:35, in synchronized.<locals>.wrapper(*args, **kwargs)
32 @functools.wraps(func)
33 def wrapper(*args, **kwargs):
34 with _module_lock:
---> 35 return func(*args, **kwargs)
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\scipy\optimize\_cobyla_py.py:278, in _minimize_cobyla(fun, x0, args, constraints, rhobeg, tol, maxiter, disp, catol, callback, bounds, **unknown_options)
275 def _jac(x, *args):
276 return None
--> 278 sf = _prepare_scalar_function(fun, x0, args=args, jac=_jac)
280 def calcfc(x, con):
281 f = sf.fun(x)
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\scipy\optimize\_optimize.py:288, in _prepare_scalar_function(fun, x0, jac, args, bounds, epsilon, finite_diff_rel_step, hess)
284 bounds = (-np.inf, np.inf)
286 # ScalarFunction caches. Reuse of fun(x) during grad
287 # calculation reduces overall function evaluations.
--> 288 sf = ScalarFunction(fun, x0, args, grad, hess,
289 finite_diff_rel_step, bounds, epsilon=epsilon)
291 return sf
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\scipy\optimize\_differentiable_functions.py:222, in ScalarFunction.__init__(self, fun, x0, args, grad, hess, finite_diff_rel_step, finite_diff_bounds, epsilon)
219 finite_diff_options["as_linear_operator"] = True
221 # Initial function evaluation
--> 222 self._update_fun()
224 # Initial gradient evaluation
225 self._wrapped_grad, self._ngev = _wrapper_grad(
226 grad,
227 fun=self._wrapped_fun,
228 args=args,
229 finite_diff_options=finite_diff_options
230 )
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\scipy\optimize\_differentiable_functions.py:294, in ScalarFunction._update_fun(self)
292 def _update_fun(self):
293 if not self.f_updated:
--> 294 fx = self._wrapped_fun(self.x)
295 if fx < self._lowest_f:
296 self._lowest_x = self.x
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\scipy\optimize\_differentiable_functions.py:20, in _wrapper_fun.<locals>.wrapped(x)
16 ncalls[0] += 1
17 # Send a copy because the user may overwrite it.
18 # Overwriting results in undefined behaviour because
19 # fun(self.x) will change self.x, with the two no longer linked.
---> 20 fx = fun(np.copy(x), *args)
21 # Make sure the function returns a true scalar
22 if not np.isscalar(fx):
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\qiskit_algorithms\minimum_eigensolvers\sampling_vqe.py:320, in SamplingVQE._get_evaluate_energy.<locals>.evaluate_energy(parameters)
315 parameters = np.reshape(parameters, (-1, num_parameters)).tolist()
316 batch_size = len(parameters)
318 estimator_result = estimator.run(
319 batch_size * [ansatz], batch_size * [operator], parameters
--> 320 ).result()
321 values = estimator_result.values
323 if self.callback is not None:
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\qiskit\primitives\primitive_job.py:51, in PrimitiveJob.result(self)
49 def result(self) -> ResultT:
50 self._check_submitted()
---> 51 return self._future.result()
File ~\AppData\Local\Programs\Python\Python312\Lib\concurrent\futures\_base.py:449, in Future.result(self, timeout)
447 raise CancelledError()
448 elif self._state == FINISHED:
--> 449 return self.__get_result()
451 self._condition.wait(timeout)
453 if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]:
File ~\AppData\Local\Programs\Python\Python312\Lib\concurrent\futures\_base.py:401, in Future.__get_result(self)
399 if self._exception:
400 try:
--> 401 raise self._exception
402 finally:
403 # Break a reference cycle with the exception in self._exception
404 self = None
File ~\AppData\Local\Programs\Python\Python312\Lib\concurrent\futures\thread.py:58, in _WorkItem.run(self)
55 return
57 try:
---> 58 result = self.fn(*self.args, **self.kwargs)
59 except BaseException as exc:
60 self.future.set_exception(exc)
File f:\QuantumComputingProjects\IBM_Qiskit\Lib\site-packages\qiskit_algorithms\minimum_eigensolvers\diagonal_estimator.py:117, in _DiagonalEstimator._call(self, circuits, observables, parameter_values, **run_options)
110 def _call(
111 self,
112 circuits: Sequence[int],
(...)
115 **run_options,
116 ) -> _DiagonalEstimatorResult:
--> 117 job = self.sampler.run(
118 [self._circuits[i] for i in circuits],
119 parameter_values,
120 **run_options,
121 )
122 sampler_result = job.result()
123 samples = sampler_result.quasi_dists
TypeError: SamplerV2.run() takes 2 positional arguments but 3 were given
I have a few questions:
Any help would be greatly appreciated!
Qiskit Optimization does not support the V2 versions of the primitives that are now needed to run on real devices (IBM backends). There is an open issue for that https://github.com/qiskit-community/qiskit-optimization/issues/587 though there some work is in progress, which you can see in the Pull Requests on the repository. Same for Qiskit Algorithms that the released version of Qiskit Optimization depends on.