https://quantum.cloud.ibm.com/learning/en/courses/fundamentals-of-quantum-algorithms/quantum-query-algorithms/deutsch-algorithm
https://en.wikipedia.org/wiki/Deutsch%E2%80%93Jozsa_algorithm
Implementaion link: https://github.com/computingnotes/QuantumAlgorithmsUsingQiskit/blob/main/deutsch_algorithm_using_qiskit.ipynb
GitHub: https://github.com/computingnotes
Deutsch’s Algorithm Implementation in Qiskit¶
In [45]:
# --- 1. Installation and Setup ---
# Install necessary libraries silently
!pip install qiskit qiskit_aer pylatexenc -q
In [46]:
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
In [47]:
# Imports
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
from typing import Literal
from IPython.display import display
# Display Qiskit version for confirmation
from qiskit import __version__
print(f"Qiskit Version: {__version__}")
Qiskit Version: 2.2.3
In [49]:
# --- 2. DeutschSolver Class ---
class DeutschSolver:
"""
A class to implement and run Deutsch's algorithm for a single-bit function.
The goal is to determine if f: {0, 1} -> {0, 1} is constant or balanced
with a single quantum query.
"""
def __init__(self):
# Initialize the simulator for execution
self.simulator = AerSimulator()
def create_oracle(self, case: int) -> QuantumCircuit:
"""
Generates the quantum oracle (Uf) circuit for one of the 4 possible functions.
"""
if case not in [1, 2, 3, 4]:
raise ValueError("`case` must be 1, 2, 3, or 4.")
# 2 qubits: Qubit 0 (input), Qubit 1 (auxiliary/output)
f = QuantumCircuit(2, name=f"Uf{case}")
# Functions f2 and f3 use CNOT
if case in [2, 3]:
f.cx(0, 1)
# Functions f3 and f4 use an X-gate offset
if case in [3, 4]:
f.x(1)
return f
def build_circuit(self, oracle: QuantumCircuit) -> QuantumCircuit:
"""
Compiles the full Deutsch algorithm circuit around the given oracle.
"""
n = oracle.num_qubits - 1 # n=1 for the input register
qc = QuantumCircuit(n + 1, n)
# --- Stage 1: Initial Preparation ---
# Prepare auxiliary qubit (Qubit n=1) in |1>
qc.x(n)
# Apply H to both qubits to create |+>|- >
qc.h(range(n + 1))
# --- Stage 2: Quantum Query ---
qc.barrier()
# Insert the oracle (Uf)
qc.compose(oracle, inplace=True)
qc.barrier()
# --- Stage 3: Interference and Measurement ---
# Apply final H gate to the input qubit (Qubit 0)
qc.h(range(n))
# Measure input qubit (Qubit 0)
qc.measure(range(n), range(n))
return qc
def run(self, oracle: QuantumCircuit) -> Literal["constant", "balanced"]:
"""
Executes the algorithm and determines if the function is constant or balanced.
"""
# 1. Build the full circuit
full_circuit = self.build_circuit(oracle)
# 2. Run the simulation
result = self.simulator.run(full_circuit, shots=1, memory=True).result()
measurements = result.get_memory()
# 3. Interpret the result
# '0' -> Constant, '1' -> Balanced
if measurements[0] == "0":
return "constant"
else:
return "balanced"
In [50]:
# --- 3. Execution and Demonstration ---
print("--- Running Deutsch's Algorithm for all 4 Cases ---")
# Initialize the solver
solver = DeutschSolver()
# Functions to test and their classical properties
functions = {
1: "f1(a)=0 (Constant)",
2: "f2(a)=a (Balanced)",
3: "f3(a)=¬a (Balanced)",
4: "f4(a)=1 (Constant)"
}
# Run the algorithm for all four cases
for case, description in functions.items():
oracle = solver.create_oracle(case)
result = solver.run(oracle)
print(f"\nCase {case} ({description}):")
print(f" -> Quantum Result: '{result}'")
print("-" * 40)
print("--- Full Circuit Diagram for Case 3 (Balanced Function) ---")
# Visualize the full circuit for one example
f3_oracle = solver.create_oracle(3)
full_f3_circuit = solver.build_circuit(f3_oracle)
display(full_f3_circuit.draw(output="mpl"))
--- Running Deutsch's Algorithm for all 4 Cases --- Case 1 (f1(a)=0 (Constant)): -> Quantum Result: 'constant' Case 2 (f2(a)=a (Balanced)): -> Quantum Result: 'balanced' Case 3 (f3(a)=¬a (Balanced)): -> Quantum Result: 'balanced' Case 4 (f4(a)=1 (Constant)): -> Quantum Result: 'constant' ---------------------------------------- --- Full Circuit Diagram for Case 3 (Balanced Function) ---
Code Explanation:


Qiskit Code Explanation: Deutsch’s Algorithm
| Section | Code Line(s) | Description |
|---|---|---|
| Setup | !pip install qiskit qiskit_aer pylatexenc -q | Installs necessary libraries: Qiskit, the Aer simulator, and LaTeX rendering tools. |
from qiskit import ... | Imports core Qiskit classes (QuantumCircuit), the simulator (AerSimulator), and visualization tools (display). | |
self.simulator = AerSimulator() | Initializes the local high-performance simulator for execution. | |
create_oracle | def create_oracle(self, case: int) -> ... | Defines the method to generate the quantum oracle ($U_f$) circuit for the function $f$. |
f = QuantumCircuit(2, name=f"Uf{case}") | Creates the 2-qubit circuit (Qubit 0 = input, Qubit 1 = auxiliary). | |
if case in [2, 3]: f.cx(0, 1) | Implements the balanced functions (f2, f3) by applying a CNOT gate. | |
if case in [3, 4]: f.x(1) | Implements an output offset for functions where $f(1)=1$ (f3, f4) using an X-gate. | |
build_circuit | def build_circuit(self, oracle: QuantumCircuit) -> ... | Defines the method that constructs the full Deutsch circuit. |
qc = QuantumCircuit(n + 1, n) | Creates 2 quantum qubits and 1 classical bit for the result. | |
qc.x(n); qc.h(range(n + 1)) | Preparation: Sets the auxiliary qubit to $ | |
qc.compose(oracle, inplace=True) | Query: Inserts the oracle ($U_f$). This is the single query that performs the Phase Kickback. | |
qc.h(range(n)) | Interference: Applies the final Hadamard gate to the input qubit (Qubit 0). | |
qc.measure(range(n), range(n)) | Measures the input qubit (Qubit 0). The result is ‘0’ if constant, ‘1’ if balanced. | |
run | def run(self, oracle: QuantumCircuit) -> Literal[...] | Defines the execution method. |
result = self.simulator.run(full_circuit, shots=1, ...).result() | Runs the compiled circuit on the simulator exactly once. | |
if measurements[0] == "0": return "constant" | Interpretation: If the measurement is ‘0’, the result of $f(0) \oplus f(1)$ is 0, meaning the function is constant. | |
else: return "balanced" | If the measurement is ‘1’, the result of $f(0) \oplus f(1)$ is 1, meaning the function is balanced. | |
| Execution | solver = DeutschSolver() | Initializes the solver object. |
for case, description in functions.items(): ... | Loops through and tests all four required function cases (f1, f2, f3, f4). | |
display(full_f3_circuit.draw(output="mpl")) | Generates and displays the visual diagram of the full quantum circuit for a specific case (f3 in the source). |