I'm trying to run the QAOA code from Qiskit (https://qiskit.org/textbook/ch-applications/qaoa.html) on a real quantum computer. However, it doesn't work.
Here starts my code:
import networkx as nx
import matplotlib.pyplot as plt
from qiskit import Aer, IBMQ
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit.providers.ibmq import least_busy
from qiskit.tools.monitor import job_monitor
from qiskit.visualization import plot_histogram
from qiskit.compiler import assemble
from qiskit.visualization import plot_circuit_layout
from qiskit import execute, transpile
from qiskit.circuit import Parameter
from qiskit.tools import parallel_map
provider = IBMQ.load_account()
backend = provider.get_backend('ibmq_manila')
shots = 2048
import networkx as nx
G = nx.Graph()
G.add_nodes_from([0, 1, 2, 3])
G.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 0)])
nx.draw(G, with_labels=True, alpha=0.8, node_size=500)
# Adjacency is essentially a matrix which tells you which nodes are connected. This matrix is given as a sparse matrix, so
# we need to convert it to a dense matrix
adjacency = nx.adjacency_matrix(G).todense()
nqubits = 4
beta = Parameter("$\\beta$")
gamma = Parameter("$\\gamma$")
qc_mix = QuantumCircuit(nqubits)
for i in range(0, nqubits):
qc_mix.rx(2 * beta, i)
qc_p = QuantumCircuit(nqubits)
for pair in list(G.edges()): # pairs of nodes
qc_p.rzz(2 * gamma, pair[0], pair[1])
qc_p.barrier()
qc_0 = QuantumCircuit(nqubits)
for i in range(0, nqubits):
qc_0.h(i)
qc_qaoa = QuantumCircuit(nqubits)
qc_qaoa.append(qc_0, [i for i in range(0, nqubits)])
qc_qaoa.append(qc_p, [i for i in range(0, nqubits)])
qc_qaoa.append(qc_mix, [i for i in range(0, nqubits)])
qc_qaoa.decompose().decompose().draw(output='mpl')
Until here, the code is the same as from Qiskit. However, I found out, that the basis gates used in the Qiskit circuit are not the ones that are used in a real quantum computer (her: ibm_manila).
This is seen in
backend.configuration().basis_gates
So, what I did, I transpiled the circuit and maximized the optimization level.
from qiskit import transpile
qc_basis = transpile(qc_qaoa, backend)
qc_basis.draw(output='mpl')
new_circ_lv3 = transpile(qc_basis, backend=backend, optimization_level=3)
plot_circuit_layout(new_circ_lv3, backend)
After that, the Qiskit code doesn't work anymore and I don't know how to solve it.
def maxcut_obj(x, G):
"""
Given a bitstring as a solution, this function returns
the number of edges shared between the two partitions
of the graph.
Args:
x: str
solution bitstring
G: networkx graph
Returns:
obj: float
Objective
"""
obj = 0
for i, j in G.edges():
if x[i] != x[j]:
obj -= 1
return obj
def compute_expectation(counts, G):
"""
Computes expectation value based on measurement results
Args:
counts: dict
key as bitstring, val as count
G: networkx graph
Returns:
avg: float
expectation value
"""
avg = 0
sum_count = 0
for bitstring, count in counts.items():
obj = maxcut_obj(bitstring, G)
avg += obj * count
sum_count += count
return avg/sum_count
# We will also bring the different circuit components that
# build the qaoa circuit under a single function
def create_qaoa_circ(G, theta):
"""
Creates a parametrized qaoa circuit
Args:
G: networkx graph
theta: list
unitary parameters
Returns:
qc: qiskit circuit
"""
nqubits = len(G.nodes())
p = len(theta)//2 # number of alternating unitaries
qc = QuantumCircuit(nqubits)
beta = theta[:p]
gamma = theta[p:]
# initial_state
for i in range(0, nqubits):
qc.h(i)
for irep in range(0, p):
# problem unitary
for pair in list(G.edges()):
qc.rzz(2 * gamma[irep], pair[0], pair[1])
# mixer unitary
for i in range(0, nqubits):
qc.rx(2 * beta[irep], i)
qc.measure_all()
return qc
# Finally we write a function that executes the circuit on the chosen backend
def get_expectation(G, p, shots=2048):
"""
Runs parametrized circuit
Args:
G: networkx graph
p: int,
Number of repetitions of unitaries
"""
backend.shots = shots
def execute_circ(theta):
qc = create_qaoa_circ(G, theta)
compiled_circuits = transpile(qc_basis, backend)
qobj = assemble(compiled_circuits, backend)
return compute_expectation(counts, G)
return execute_circ
from scipy.optimize import minimize
expectation = get_expectation(G, p=1)
res = minimize(expectation,
[1.0, 1.0],
method='COBYLA')
res
And I get this error:
---------------------------------------------------------------------------
QiskitError Traceback (most recent call last)
Input In [20], in <cell line: 8>()
3 #qc_basis.assign_parameters(create_qaoa_circ, inplace = True)
5 expectation = get_expectation(G, p=1)
----> 8 res = minimize(expectation,
9 [1.0, 1.0],
10 method='COBYLA')
12 res
File ~\anaconda3\lib\site-packages\scipy\optimize\_minimize.py:698, in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)
695 res = _minimize_tnc(fun, x0, args, jac, bounds, callback=callback,
696 **options)
697 elif meth == 'cobyla':
--> 698 res = _minimize_cobyla(fun, x0, args, constraints, callback=callback,
699 **options)
700 elif meth == 'slsqp':
701 res = _minimize_slsqp(fun, x0, args, jac, bounds,
702 constraints, callback=callback, **options)
File ~\anaconda3\lib\site-packages\scipy\optimize\_cobyla_py.py:34, in synchronized.<locals>.wrapper(*args, **kwargs)
31 @functools.wraps(func)
32 def wrapper(*args, **kwargs):
33 with _module_lock:
---> 34 return func(*args, **kwargs)
File ~\anaconda3\lib\site-packages\scipy\optimize\_cobyla_py.py:273, in _minimize_cobyla(fun, x0, args, constraints, rhobeg, tol, maxiter, disp, catol, callback, **unknown_options)
270 callback(np.copy(x))
272 info = np.zeros(4, np.float64)
--> 273 xopt, info = cobyla.minimize(calcfc, m=m, x=np.copy(x0), rhobeg=rhobeg,
274 rhoend=rhoend, iprint=iprint, maxfun=maxfun,
275 dinfo=info, callback=wrapped_callback)
277 if info[3] > catol:
278 # Check constraint violation
279 info[0] = 4
File ~\anaconda3\lib\site-packages\scipy\optimize\_cobyla_py.py:261, in _minimize_cobyla.<locals>.calcfc(x, con)
260 def calcfc(x, con):
--> 261 f = fun(np.copy(x), *args)
262 i = 0
263 for size, c in izip(cons_lengths, constraints):
Input In [18], in get_expectation.<locals>.execute_circ(theta)
111 qc = create_qaoa_circ(G, theta)
113 compiled_circuits = transpile(qc_basis, backend)
--> 114 qobj = assemble(compiled_circuits, backend)
116 #execute_circ.run_config.parameter_binds('gamma', 'beta')
117
118 # qobj = assemble(qc_basis).result().get_counts()
119 # counts = transpile.run(qc_basis).result().get_counts()
122 return compute_expectation(counts, G)
File ~\anaconda3\lib\site-packages\qiskit\compiler\assembler.py:205, in assemble(experiments, backend, qobj_id, qobj_header, shots, memory, max_credits, seed_simulator, qubit_lo_freq, meas_lo_freq, qubit_lo_range, meas_lo_range, schedule_los, meas_level, meas_return, meas_map, memory_slot_size, rep_time, rep_delay, parameter_binds, parametric_pulses, init_qubits, **run_config)
195 run_config = _parse_circuit_args(
196 parameter_binds,
197 backend,
(...)
201 **run_config_common_dict,
202 )
204 # If circuits are parameterized, bind parameters and remove from run_config
--> 205 bound_experiments, run_config = _expand_parameters(
206 circuits=experiments, run_config=run_config
207 )
208 end_time = time()
209 _log_assembly_time(start_time, end_time)
File ~\anaconda3\lib\site-packages\qiskit\compiler\assembler.py:596, in _expand_parameters(circuits, run_config)
589 # Check that all parameters are common to all circuits and binds
590 if (
591 not all_bind_parameters
592 or not all_circuit_parameters
593 or any(unique_parameters != bind_params for bind_params in all_bind_parameters)
594 or any(unique_parameters != parameters for parameters in all_circuit_parameters)
595 ):
--> 596 raise QiskitError(
597 (
598 "Mismatch between run_config.parameter_binds and all circuit parameters. "
599 + "Parameter binds: {} "
600 + "Circuit parameters: {}"
601 ).format(all_bind_parameters, all_circuit_parameters)
602 )
604 circuits = [
605 circuit.bind_parameters(binds) for circuit in circuits for binds in parameter_binds
606 ]
608 # All parameters have been expanded and bound, so remove from run_config
QiskitError: 'Mismatch between run_config.parameter_binds and all circuit parameters. Parameter binds: [] Circuit parameters: [ParameterView([Parameter($\\beta$), Parameter($\\gamma$)])]'
I'll be very grateful if someone could help me out to get rid of the 'Mismatch'-error! (I'm pretty new to coding with Qiskit and Python, so a detailed answer would be even more appreciated. Thanks!)