Created
May 2, 2025 09:05
-
-
Save TheBlackPlague/3d205ce2bb014acb4381976aee5edcd3 to your computer and use it in GitHub Desktop.
A naive implementation of Grover's Algorithm, configured to run on IBM's Quantum Computer (you may change the backend to Aer for simulation purposes).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ---- IBM [START] | |
from os import environ | |
from qiskit_ibm_runtime import QiskitRuntimeService, IBMBackend, SamplerV2 as Sampler, SamplerOptions | |
from qiskit_ibm_runtime.options import DynamicalDecouplingOptions | |
SERVICE: QiskitRuntimeService = QiskitRuntimeService(channel="ibm_quantum", token=environ["IBM_QUANTUM_TOKEN"]) | |
def get_backend(n: int) -> IBMBackend: | |
global SERVICE | |
return SERVICE.least_busy(min_num_qubits=n, operational=True, simulator=False) | |
def get_sampler(backend: IBMBackend) -> Sampler: | |
dd_options = DynamicalDecouplingOptions() | |
dd_options.enable = True | |
options = SamplerOptions() | |
options.dynamical_decoupling = dd_options | |
return Sampler(backend, options) | |
# ---- IBM [END] | |
# ---- GROVER [START] | |
from qiskit import QuantumRegister, QuantumCircuit | |
from math import pi, floor, sqrt | |
def grover_oracle(n: int, target: int) -> QuantumCircuit: | |
q = QuantumRegister(n, "input") | |
a = QuantumRegister(n - 1 - 2, "ancilla") | |
c = QuantumCircuit(q, a) | |
for i in range(n): | |
if ((target >> i) & 1) == 0: c.x(q[i]) | |
c.h(q[n - 1]) | |
c.mcx(q[:n - 1], q[n - 1], mode="v-chain", ancilla_qubits=a) | |
c.h(q[n - 1]) | |
for i in range(n): | |
if ((target >> i) & 1) == 0: c.x(q[i]) | |
return c | |
def grover_diffusion(n: int) -> QuantumCircuit: | |
q = QuantumRegister(n, "input") | |
a = QuantumRegister(n - 1 - 2, "ancilla") | |
c = QuantumCircuit(q, a) | |
c.h(q) | |
c.x(q) | |
c.h(q[-1]) | |
c.mcx(q[:-1], q[-1], mode="v-chain", ancilla_qubits=a) | |
c.h(q[-1]) | |
c.x(q) | |
c.h(q) | |
return c | |
def grover_algorithm(n: int, oracle: QuantumCircuit, diffusion: QuantumCircuit) -> QuantumCircuit: | |
q = QuantumRegister(n, "input") | |
a = QuantumRegister(n - 1 - 2, "ancilla") | |
c = QuantumCircuit(q, a) | |
c.h(q) | |
N = 2 ** n | |
K = floor(pi / 4 * sqrt(N)) | |
for _ in range(K): | |
c.append(oracle .to_gate(label="Oracle" ), q[:] + a[:]) | |
c.append(diffusion.to_gate(label="Diffusion"), q[:] + a[:]) | |
return c | |
# ---- GROVER [END] | |
# ---- BOOT | |
import matplotlib.pyplot as plt | |
from qiskit import transpile | |
from qiskit.visualization import plot_histogram | |
n = 4 | |
target = 14 # 1110 in binary | |
shots = 1024 | |
backend = get_backend(n) | |
sampler = get_sampler(backend) | |
oracle = grover_oracle(n, target) | |
diffusion = grover_diffusion(n) | |
circuit = grover_algorithm(n, oracle, diffusion) | |
circuit.measure_all() | |
optimized_circuit = transpile(circuit, backend, optimization_level=3, layout_method="sabre") | |
print(optimized_circuit.depth()) | |
job = sampler.run([optimized_circuit], shots=shots) | |
result = job.result()[0].data.meas.get_counts() | |
most_likely = max(result, key=result.get) | |
print(f"Most probable state: {most_likely}") | |
plot_histogram(result) | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment