# Estimating $\pi$ using Quantum Computing - why does it work only in simulator?

I followed the steps from the Qiskit tutorial on YouTube titled "How can I estimate Pi using a quantum computer? - 1 Minute Qiskit"

The code uses Qiskit and apparently works successfully when executed in Aer Simulator:

# estimate Pi in the simulator
nq = 15
estimate = get_pi_estimate(nq)
print(f"{nq} qubits, pi ≈ {estimate}")


15 qubits, pi ≈ 3.1417066155321187

However, when running on an actual quantum computer, the resulting number is quite strange:

# estimate Pi using in the actual equipment
%%time
nq = 15
estimate = get_pi_estimate(nq, backend=qcomp)
print(f"{nq} qubits, pi ≈ {estimate}")


15 qubits, pi ≈ 0.52487586096428

Here are the code snippets in order to reproduce the steps:

import numpy as np
from qiskit import *
from qiskit.providers.aer import AerSimulator
from qiskit import IBMQ

def qpe_pre(circ_, n_qubits):
circ_.h(range(n_qubits))
circ_.x(n_qubits)
for x in reversed(range(n_qubits)):
for _ in range(2 ** (n_qubits - 1 - x)):
circ_.cp(1, n_qubits - 1 - x, n_qubits)

def qft_dagger(circ_, n_qubits):
"""n-qubit QFTdagger the first n qubits in circ"""
for qubit in range(int(n_qubits / 2)):
circ_.swap(qubit, n_qubits - qubit - 1)
for j in range(0, n_qubits):
for m in range(j):
circ_.cp(-np.pi / float(2 ** (j - m)), m, j)
circ_.h(j)

def create_circuit(n_qubits):

# create the circuit
circ = QuantumCircuit(n_qubits + 1, n_qubits)

# create the input state
qpe_pre(circ, n_qubits)

# apply a barrier
circ.barrier()

# apply the inverse fourier transform
qft_dagger(circ, n_qubits)

# apply a barrier
circ.barrier()

# measure all but the last qubits
circ.measure(range(n_qubits), range(n_qubits))

return circ

def run_job(circ, backend, shots=10000):
job = execute(circ, backend, shots=shots,
#blocking_enable=True,
#blocking_qubits=15,
seed_simulator=1)
return job.result().get_counts()

simulator = AerSimulator(method="statevector")
simulator

def get_pi_estimate(n_qubits, circ=None, backend=simulator):

# create the circuit if not existent
if not circ:
circ = create_circuit(n_qubits)

# run the job and get the results
counts = run_job(circ, backend=backend, shots=10000)

# get the count that occurred most frequently
max_counts_result = max(counts, key=counts.get)
max_counts_result = int(max_counts_result, 2)

# solve for pi from the measured counts
theta = max_counts_result / 2 ** n_qubits
return (1. / (2 * theta))

provider = IBMQ.get_provider('ibm-q')

resource = 'ibm_perth' # 7 qubits
qcomp = provider.get_backend(resource)

• Real quantum computers are very noisy. Applying QFT and many more subroutines is too much for them so you basically get just noise. Nov 22, 2023 at 17:37

Actual Quantum Hardware is very noisy, hence you can't get the desired result, running your code directly onto it. What you can do instead is make use of some error mitigation techniques.

1. Transpile your quantum circuit to the desired backend , each qubit has a different error rate, so you need to map your quantum circuit to the best layout possible.

2. When we leave the qubits idle, they accumulate errors, so you can make use of Dynamic Decoupling to get rid of that.

There are more such techniques that you can apply and it's fairly easy to apply them as well. You just have to set the optimization_level and the reselience_level while executing your quantum circuit.

Now this will not get you the exact $$3.14$$ you are looking for, but will drastically improve your result from the one you are getting currently.

You can see how to implement this here.

Or you can see in detail in this previous Stack question