# ibmq_16_melbourne system of Qiskit giving wrong result for Bernstein-Vazirani Algorithm

I have just started learning Qiskit and to begin I tried running the Bernstein Vazirani Algorithm(secret number detector) on qasm_simulator and the ibmq_16_melbourne system and compared their results. My results on the Qasm simulator exactly matches the secret number, but I am getting wrong result on the real system. Please review my codes, circuits and results below:

import qiskit
from qiskit import IBMQ
import time
from qiskit import *
from qiskit.tools.visualization import plot_histogram
from qiskit.tools.visualization import plot_bloch_multivector
import matplotlib.pyplot as plt
from qiskit.tools.monitor import job_monitor
#IBMQ.save_account('Account key',overwrite=True)  #  Run it for once

# 6 bit secret number
secretNumber= '101001'

circuit= QuantumCircuit(6+1,6) # 6 qubit for secret no. +1 qubit
circuit. h([0,1,2,3,4,5])
circuit.x(6)
circuit.h(6)
circuit.barrier()

# splitting the string into char
splitSecretNumber= list(secretNumber)
lengthofSecretNumber= len(splitSecretNumber)

x=0
while(x< lengthofSecretNumber):
if(str(splitSecretNumber[x])=='1'):
circuit.cx(int(x),6)
x=x+1

circuit.barrier()
circuit.h([0,1,2,3,4,5])
circuit.barrier()
circuit.measure([0,1,2,3,4,5],[0,1,2,3,4,5])
circuit.draw(output="mpl")

simulator= Aer.get_backend('qasm_simulator')
simulationResult = execute(circuit,simulator, shots=1).result()
counts= simulationResult.get_counts()
print(counts)
plot_histogram(simulationResult.get_counts(circuit))
plt.show()


The histogram and circuit obtained are for Qasm simulator are as below:

Python Code executed on ibmq_16_melbourne system using Pycharm IDE-

import qiskit
from qiskit import IBMQ
import time
from qiskit import *
from qiskit.tools.visualization import plot_histogram
from qiskit.tools.visualization import plot_bloch_multivector
import matplotlib.pyplot as plt
from qiskit.tools.monitor import job_monitor
#IBMQ.save_account('Account key',overwrite=True)  #  Run it for once

# 6 bit secret number
secretNumber= '101001'

circuit= QuantumCircuit(6+1,6) # 6 qubit for secret no. +1 qubit
circuit. h([0,1,2,3,4,5])
circuit.x(6)
circuit.h(6)
circuit.barrier()

# splitting the string into char
splitSecretNumber= list(secretNumber)
lengthofSecretNumber= len(splitSecretNumber)

x=0
while(x< lengthofSecretNumber):
if(str(splitSecretNumber[x])=='1'):
circuit.cx(int(x),6)
x=x+1

circuit.barrier()
circuit.h([0,1,2,3,4,5])
circuit.barrier()
circuit.measure([0,1,2,3,4,5],[0,1,2,3,4,5])
circuit.draw(output="mpl")

provider=IBMQ.get_provider('ibm-q')
realMachine= provider.get_backend('ibmq_16_melbourne')
result = execute(circuit,realMachine, shots=1000).result()
counts= result.get_counts()
print(counts)
plot_histogram(counts)
plt.show()


The histogram and circuit obtained are for ibmq_16_melbourne system are as below:

The @epelaaez explanation is on the spot on how noise works.

In this answer I would like to focus more on how to reduce that noise. For that, let's introduce the notion of the Qiskit transpiler. The transpiler adapts the circuit to run it in the backend.

The circuit that you are running in ibmq_16_melbourne is the following:

from qiskit import transpile

realMachine_circuit = transpile(circuit, realMachine)
realMachine_circuit.draw('mpl', idle_wires=False)


The depth of this circuit (check realMachine_circuit.depth()) is 22 layers, which has the T1 and T2 noise effect described by @epelaaez. Also has the following amount of gates(check realMachine_circuit.count_ops()):

OrderedDict([('rz', 26),
('cx', 18),
('sx', 13),
('measure', 6),
('barrier', 3)])


More gates means more single (for rz and sx) and 2-qubit (for cx) gates error.

Therefore, for reducing noise, the option is to reduce the depth of the circuit and the amount of gates used in the circuit. The easier way to do this is to tell the transpiler to spend more computational resources in optimization. You can do that with the parameter optimization_level, which maxim number is 3. Here, the result:

realMachine_circuit = transpile(circuit, realMachine, optimization_level=3)
realMachine_circuit.draw('mpl', idle_wires=False)


This results in a better circuit:

print('depth: ', realMachine_circuit.depth())
print('count_ops: ', list(realMachine_circuit.count_ops().items()))

depth:  10
count_ops:  [('rz', 26), ('sx', 13), ('measure', 6), ('barrier', 3), ('cx', 3)]


Other aspect to consider is the effect of barrier. While I understand you put them there for pedagogic reasons, they do have meaning for the transpiler. The transpiler does not optimize gates across barriers. So you can remove them before transpiling like this:

from qiskit.transpiler.passes import RemoveBarriers
realMachine_circuit = transpile(RemoveBarriers()(circuit), realMachine, optimization_level=3)
print('depth: ', realMachine_circuit.depth())
print('count_ops: ', list(realMachine_circuit.count_ops().items()))
realMachine_circuit.draw('mpl', idle_wires=False)

depth:  9
count_ops:  [('rz', 11), ('sx', 7), ('measure', 6), ('cx', 3)]


Now, with all this together, let's execute in real hardware to see the result:

job = execute(RemoveBarriers()(circuit), realMachine, optimization_level=3)
counts= job.result().get_counts()
plot_histogram(counts)


Now, the correct result is "more evident". Here is the most frequent result (in this case, matching the simulation):

counts.most_frequent()

'100101'

• Thank you @luciana. It is a great answer. Thank you for this great help. Jun 14 at 15:35
• Hi @luciana, there is a concept of Fidelity in quantum computers. Can you give me some idea regarding how to calculate the Fidelity for the above question? Jun 14 at 18:19

That’s just how real quantum computers work. The QASM simulator is able to simulate ideal conditions where there is no noise in your qubits/circuit. However, you cannot avoid noise when running on real hardware. Here you can find information about the specific device you’re talking about.

You want to look into T1, T2 and the readout and CNOT error rate. Very briefly, the following is what each error rate means.

T1: relaxation time. This is the time it takes for the excited state $$|1\rangle$$ to decay into the ground state $$|0\rangle$$. Therefore, all operations should be made in a fraction of T1 to ensure that excited states don’t decay and ruin the computation.

T2: dephasing time. This is the time after which a state can gain an unintended phase factor from the environment.

Readout: this is measured by doing a bunch of experiments in which the $$|0\rangle$$ or $$|1\rangle$$ state is prepared and immediately measured. A readout error happens when you measure the opposite of what you prepared. Then, the readout error is the average of the two possible errors. For example: if you get 2% error when measuring $$|1\rangle$$ and 1% error when measuring $$|0\rangle$$, the readout error will be 1.5%.
CNOT: this is calculated using randomized benchmarking for two-qubit Clifford gates. The idea is to take a register on a random walk starting from state $$|0\rangle$$ and ending also on $$|0\rangle$$. The CNOT error is derived from the probability of actually getting back to the ground state. Read more about this here.