Skip to content

Commit 8d9ce52

Browse files
committed
Implement Deutsch-Jozsa Algorithm In Qiskit
Signed-off-by: Abhishek Jaisingh <abhi2254015@gmail.com>
1 parent 05f4089 commit 8d9ce52

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

quantum/deutsch_jozsa.py

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Deutsch-Josza Algorithm is one of the first examples of a quantum
4+
algorithm that is exponentially faster than any possible deterministic
5+
classical algorithm
6+
7+
Premise:
8+
We are given a hidden Boolean function f ,
9+
which takes as input a string of bits, and returns either 0 or 1:
10+
11+
f({x0,x1,x2,...}) -> 0 or 1 , where xn is 0 or 1
12+
13+
The property of the given Boolean function is that it is guaranteed to
14+
either be balanced or constant. A constant function returns all 0 's
15+
or all 1 's for any input, while a balanced function returns 0 's for
16+
exactly half of all inputs and 1 's for the other half. Our task is to
17+
determine whether the given function is balanced or constant.
18+
19+
References:
20+
- https://en.wikipedia.org/wiki/Deutsch-Jozsa_algorithm
21+
- https://qiskit.org/textbook/ch-algorithms/deutsch-jozsa.html
22+
"""
23+
24+
import numpy as np
25+
import qiskit as q
26+
27+
28+
def dj_oracle(case: str, n: int) -> q.QuantumCircuit:
29+
"""
30+
Returns a Quantum Circuit for the Oracle function.
31+
The circuit returned can represent balanced or constant function,
32+
according to the arguments passed
33+
"""
34+
# This circuit has n+1 qubits: the size of the input,
35+
# plus one output qubit
36+
oracle_qc = q.QuantumCircuit(n+1)
37+
38+
# First, let's deal with the case in which oracle is balanced
39+
if case == "balanced":
40+
# First generate a random number that tells us which CNOTs to
41+
# wrap in X-gates:
42+
b = np.random.randint(1,2**n)
43+
# Next, format 'b' as a binary string of length 'n', padded with zeros:
44+
b_str = format(b, '0'+str(n)+'b')
45+
# Next, we place the first X-gates. Each digit in our binary string
46+
# correspopnds to a qubit, if the digit is 0, we do nothing, if it's 1
47+
# we apply an X-gate to that qubit:
48+
for qubit in range(len(b_str)):
49+
if b_str[qubit] == '1':
50+
oracle_qc.x(qubit)
51+
# Do the controlled-NOT gates for each qubit, using the output qubit
52+
# as the target:
53+
for qubit in range(n):
54+
oracle_qc.cx(qubit, n)
55+
# Next, place the final X-gates
56+
for qubit in range(len(b_str)):
57+
if b_str[qubit] == '1':
58+
oracle_qc.x(qubit)
59+
60+
# Case in which oracle is constant
61+
if case == "constant":
62+
# First decide what the fixed output of the oracle will be
63+
# (either always 0 or always 1)
64+
output = np.random.randint(2)
65+
if output == 1:
66+
oracle_qc.x(n)
67+
68+
oracle_gate = oracle_qc.to_gate()
69+
oracle_gate.name = "Oracle" # To show when we display the circuit
70+
return oracle_gate
71+
72+
73+
def dj_algorithm(oracle: q.QuantumCircuit, n: int) -> q.QuantumCircuit:
74+
"""
75+
Returns the complete Deustch-Jozsa Quantum Circuit,
76+
adding Input & Output registers and Hadamard & Measurement Gates,
77+
to the Oracle Circuit passed in arguments
78+
"""
79+
dj_circuit = q.QuantumCircuit(n+1, n)
80+
# Set up the output qubit:
81+
dj_circuit.x(n)
82+
dj_circuit.h(n)
83+
# And set up the input register:
84+
for qubit in range(n):
85+
dj_circuit.h(qubit)
86+
# Let's append the oracle gate to our circuit:
87+
dj_circuit.append(oracle, range(n+1))
88+
# Finally, perform the H-gates again and measure:
89+
for qubit in range(n):
90+
dj_circuit.h(qubit)
91+
92+
for i in range(n):
93+
dj_circuit.measure(i, i)
94+
95+
return dj_circuit
96+
97+
98+
def deutsch_jozsa(case: str, n: int) -> q.result.counts.Counts:
99+
"""
100+
Main function that builds the circuit using other helper functions,
101+
runs the experiment 1000 times & returns the resultant qubit counts
102+
>>> deutsch_jozsa("constant", 3)
103+
{'000': 1000}
104+
>>> deutsch_jozsa("balanced", 3)
105+
{'111': 1000}
106+
"""
107+
# Use Aer's qasm_simulator
108+
simulator = q.Aer.get_backend("qasm_simulator")
109+
110+
oracle_gate = dj_oracle(case, n)
111+
dj_circuit = dj_algorithm(oracle_gate, n)
112+
113+
# Execute the circuit on the qasm simulator
114+
job = q.execute(dj_circuit, simulator, shots=1000)
115+
116+
# Return the histogram data of the results of the experiment.
117+
return job.result().get_counts(dj_circuit)
118+
119+
120+
if __name__ == "__main__":
121+
counts = deutsch_jozsa("constant", 3)
122+
print(f"Deutsch Jozsa - Constant Oracle: {counts}")
123+
124+
counts = deutsch_jozsa("balanced", 3)
125+
print(f"Deutsch Jozsa - Balanced Oracle: {counts}")

0 commit comments

Comments
 (0)