QC DJ Algorithm
QC DJ Algorithm
Deutsch-Josza Algorithm
In this section, we first introduce the Deutsch-Josza problem, and classical and quantum algorithms to solve it. We then
implement the quantum algorithm using Qiskit, and run it on a simulator and device.
Contents
A. Introduction
1.1 Deutsch-Josza Problem
1.2 Deutsch-Josza Algorithm
F. Worked Example
I. Qiskit Implementation
3.1 Constant Oracle
3.2 Balanced Oracle
3.3 The Full Algorithm
3.4 Generalised Circuit
R. Running on Real Devices
T. Problems
U. References
1. Introduction
The Deutsch-Josza algorithm, first introduced in Reference [1], was the first example of a quantum algorithm that performs
better than the best classical algorithm. It showed that there can be advantages to using a quantum computer as a computational
tool for a specific problem.
𝑓({𝑥0 , 𝑥1 , 𝑥2 , . . . }) → 0 or 1 , where 𝑥𝑛 is 0 or 1
The property of the given Boolean function is that it is guaranteed to either be balanced or constant. A constant function returns
all 0 0's or all 1 1's for any input, while a balanced function returns 0 0's for exactly half of all inputs and 1 1's for the other half. Our
task is to determine whether the given function is balanced or constant.
Note that the Deutsch-Josza problem is an 𝑛 𝑛-bit extension of the single bit Deutsch problem.
Classical Solution
Classically, in the best case, two queries to the oracle can determine if the hidden Boolean function, 𝑓(𝑥) 𝑓(𝑥), is balanced: e.g. if
we get both 𝑓(0, 0, 0, . . . ) → 0 𝑓(0, 0, 0, . . . ) → 0 and 𝑓(1, 0, 0, . . . ) → 1 𝑓(1, 0, 0, . . . ) → 1, then we know the function is
balanced as we have obtained the two different outputs.
In the worst case, if we continue to see the same output for each input we try, we will have to check exactly half of all possible
about:srcdoc Page 1 of 13
Made with Jupyter Book 11/04/20, 10(12 AM
inputs plus one in order to be certain that 𝑓(𝑥) 𝑓(𝑥) is constant. Since the total number of possible inputs is 2 𝑛 2𝑛 , this implies that
we need 2 𝑛− 1 + 1 2𝑛 − 1 + 1 trial inputs to be certain that 𝑓(𝑥) 𝑓(𝑥) is constant in the worst case. For example, for a 4 4-bit string, if
th
we checked 8 8 out of the 1616 possible combinations, getting all 0 0's, it is still possible that the 9 9th input returns a 1 1 and
𝑓(𝑥) 𝑓(𝑥) is balanced. Probabilistically, this is a very unlikely event. In fact, if we get the same result continually in succession, we
can express the probability that the function is constant as a function of 𝑘 𝑘 inputs as:
1
𝑃constant (𝑘) = 1 − 𝑘− 1
for 𝑘 ≤ 2𝑛− 1
2
Realistically, we could opt to truncate our classical algorithm early, say if we were over x% confident. But if we want to be 100%
𝑛− 1
confident, we would need to check 2 + 1 2𝑛 − 1 + 1 inputs.
Quantum Solution
Using a quantum computer, we can solve this problem with 100% confidence after only one call to the function 𝑓(𝑥) 𝑓(𝑥),
provided we have the function 𝑓 𝑓 implemented as a quantum oracle, which maps the state |𝑥⟩|𝑦⟩ |𝑥⟩ | 𝑦⟩ to |𝑥⟩|𝑦 ⊕ 𝑓(𝑥)⟩
|𝑥⟩ | 𝑦 ⊕ 𝑓(𝑥)⟩, where ⊕ ⊕ is addition modulo 2 2. Below is the generic circuit for the Deutsh-Josza algorithm.
A. Prepare two quantum registers. The first is an 𝑛 𝑛-qubit register initialised to |0⟩ |0⟩, and the second is a one-qubit register
initialised to |1⟩ |1⟩:
2 𝑛− 1
1
1 ∑
|𝜓1 ⟩ = |𝑥⟩ (|0⟩ − |1⟩)
√‾
2‾‾
𝑛+ ‾
𝑥= 0
2 𝑛− 1
1
|𝜓2 ⟩ = |𝑥⟩(|𝑓(𝑥)⟩ − |1 ⊕ 𝑓(𝑥)⟩)
‾‾‾
√2 1 ∑
𝑛+ ‾
𝑥= 0
2 𝑛− 1
1
= (− 1)𝑓(𝑥) |𝑥⟩(|0⟩ − |1⟩)
√2 𝑛+ 1 ∑
‾‾‾‾ 𝑥= 0
about:srcdoc Page 2 of 13
Made with Jupyter Book 11/04/20, 10(12 AM
2 𝑛− 1 2 𝑛− 1
[ ]
1
(− 1)𝑓(𝑥) (− 1)𝑥⋅𝑦 |𝑦⟩
2 ∑ ∑
|𝜓3 ⟩ = 𝑛
𝑥= 0 𝑦= 0
2 𝑛− 1 2 𝑛− 1
[ ]
1
(− 1)𝑓(𝑥) (− 1)𝑥⋅𝑦 |𝑦⟩
2 ∑ ∑
= 𝑛
𝑦= 0 𝑥= 0
When the hidden Boolean function is constant, the quantum states before and after querying the oracle are the same.
The inverse of the Hadamard gate is the Hadamard gate itself. Thus, by Step 4, we essentially reverse Step 2 to obtain the initial
quantum state of all-zero at the first register.
When the hidden Boolean function is balanced, the quantum state after querying the oracle is orthogonal to the
quantum state before querying the oracle. Thus, by Step 4, when reverting the operation, we must end up with a quantum state
that is orthogonal to the initial quantum state of all-zero at the first register. This means we should never obtain the all-zero state.
Quantum Oracle
The key to the Deutsch-Josza Algorithm is the implementation of the quantum oracle.
For a balanced function, there are many different circuits we can create. One of the ways we can guarantee our circuit is
balanced is by performing a CNOT for each qubit in register 1, with the qubit in register 2 as the target. For example:
In the image above, the top three qubits form the input register, and the bottom qubit is the output register. We can see which
states give which output in the table below:
Outputs 0 Outputs 1
000 001
011 100
about:srcdoc Page 3 of 13
Made with Jupyter Book 11/04/20, 10(12 AM
101 010
110 111
We can change the results while keeping them balanced by wrapping selected controls in X-gates. For example, see the circuit
and its results table below:
Outputs 0 Outputs 1
001 000
010 011
100 101
111 110
2. Worked Example
Let's go through a specfic example for a two bit balanced function with hidden bitstring 𝑎 = 3 𝑎 = 3.
A. The first register of two qubits is initialized to |0⟩ |0⟩ and the second register qubit to |1⟩ |1⟩
1 1
|𝜓1 ⟩ = (|00⟩1 + |01⟩1 + |10⟩1 + |11⟩1 ) (|0⟩2 − |1⟩2 )
2 √2
‾
I. For 𝑎 = 3 𝑎 = 3, (11 in binary) the oracle function can be implemented as Q𝑓 = 𝐶 𝑋1𝑎 𝐶 𝑋2𝑎 Q𝑓 = 𝐶𝑋1𝑎 𝐶𝑋2𝑎 ,
1
|𝜓2 ⟩ = [|00⟩1 (|0 ⊕ 0 ⊕ 0⟩2 − |1 ⊕ 0 ⊕ 0⟩2 )
2√ 2
‾
+ |01⟩1 (|0 ⊕ 0 ⊕ 1⟩2 − |1 ⊕ 0 ⊕ 1⟩2 )
+ |10⟩1 (|0 ⊕ 1 ⊕ 0⟩2 − |1 ⊕ 1 ⊕ 0⟩2 )
+ |11⟩1 (|0 ⊕ 1 ⊕ 1⟩2 − |1 ⊕ 1 ⊕ 1⟩2 )]
R. Thus
about:srcdoc Page 4 of 13
Made with Jupyter Book 11/04/20, 10(12 AM
1
|𝜓2 ⟩ = [|00⟩1 (|0⟩2 − |1⟩2 ) − |01⟩1 (|0⟩2 − |1⟩2 )
2√2‾
− |10⟩1 (|0⟩2 − |1⟩2 ) + |11⟩1 (|0⟩2 − |1⟩2 )]
1 1
= (|00⟩1 − |01⟩1 − |10⟩1 + |11⟩1 ) (|0⟩2 − |1⟩2 )
2 √2 ‾
1 1 1
= (|0⟩10 − |1⟩10 ) (|0⟩11 − |1⟩11 ) (|0⟩2 − |1⟩2 )
√2‾ √2‾ √2‾
U. Measuring the first two qubits will give the non-zero 1111, indicating a balanced function.
3. Qiskit Implementation
We now implement the Deutsch-Josza algorithm for the example of a two bit balanced function with hidden bitstring 𝑎 = 3 𝑎 = 3.
First let's do our imports:
# initialization
import numpy as np
# importing Qiskit
from qiskit import IBMQ, BasicAer
from qiskit.providers.ibmq import least_busy
from qiskit import QuantumCircuit, execute
% matplotlib inline
% config InlineBackend.figure_format = 'svg'
Next, we set the size of the input register for our oracle:
const_oracle = QuantumCircuit(n+
+1)
output = np.
.random.
.randint(2)
if output == 1:
const_oracle.
.x(n)
const_oracle.
.draw('mpl')
about:srcdoc Page 5 of 13
Made with Jupyter Book 11/04/20, 10(12 AM
balanced_oracle = QuantumCircuit(n+
+1)
Next, we create a balanced oracle. As we saw in section 1b, we can create a balanced oracle by performing CNOTs with each
input qubit as a control and the output bit as the target. We can vary the input states that give 0 or 1 by wrapping some of the
controls in X-gates. Let's first choose a binary string of length n that dictates which controls to wrap:
b_str = "101"
Now we have this string, we can use it as a key to place our X-gates. For each qubit in our circuit, we place an X-gate if the
corresponding digit in b_str is 1 , or do nothing if the digit is 0 .
Next, we do our controlled-NOT gates, using each input qubit as a control, and the output qubit as a target:
balanced_oracle.
.barrier()
balanced_oracle.
.barrier()
about:srcdoc Page 6 of 13
Made with Jupyter Book 11/04/20, 10(12 AM
balanced_oracle.
.draw('mpl')
Finally, we repeat the code from two cells up to finish wrapping the controls:
We have just created a balanced oracle! All that's left to do is see if the Deutsch-Joza algorithm can solve it.
dj_circuit = QuantumCircuit(n+
+1, n)
dj_circuit.
.x(n)
dj_circuit.
.h(n)
dj_circuit.
.draw('mpl')
about:srcdoc Page 7 of 13
Made with Jupyter Book 11/04/20, 10(12 AM
Next, let's apply the oracle. Here we apply the balanced_oracle we created above:
dj_circuit += balanced_oracle
dj_circuit.
.draw('mpl')
Finally, we perform H-gates on the 𝑛 𝑛-input qubits, and measure our input register:
dj_circuit.
.draw('mpl')
about:srcdoc Page 8 of 13
Made with Jupyter Book 11/04/20, 10(12 AM
plot_histogram(answer)
We can see from the results above that we have a 0% chance of measuring 000 . This correctly predicts the function is balanced.
def dj_oracle
dj_oracle(case, n):
# We need to make a QuantumCircuit object to return
# This circuit has n+1 qubits: the size of the input,
about:srcdoc Page 9 of 13
Made with Jupyter Book 11/04/20, 10(12 AM
return oracle_qc.
.to_gate()
Let's also create a function that takes this oracle gate and performs the Deutsch-Joza algorithm on it:
def dj_algorithm
dj_algorithm(oracle, n):
dj_circuit = QuantumCircuit(n+
+1, n)
# Set up the output qubit:
dj_circuit.
.x(n)
dj_circuit.
.h(n)
# And set up the input register:
for qubit in range(n):
dj_circuit.
.h(qubit)
# Let's append the oracle gate to our circuit:
dj_circuit.
.append(oracle, range(n+
+1))
# Finally, perform the H-gates again and measure:
for qubit in range(n):
dj_circuit.
.h(qubit)
for i in range(n):
dj_circuit.
.measure(i, i)
return dj_circuit
Finally, let's use these functions to play around with the algorithm:
n = 4
about:srcdoc Page 10 of 13
Made with Jupyter Book 11/04/20, 10(12 AM
oracle_gate = dj_oracle('balanced', n)
dj_circuit = dj_algorithm(oracle_gate, n)
dj_circuit.
.draw('mpl')
# Load our saved IBMQ accounts and get the least busy backend device with less than or equal to (n+1) qubits
IBMQ.
.load_account()
about:srcdoc Page 11 of 13
Made with Jupyter Book 11/04/20, 10(12 AM
provider = IBMQ.
.get_provider(hub=
='ibm-q')
backend = least_busy(provider.
.backends(filters=
=lambda x: x..configuration().
.n_qubits >= (n+
+1) and
not x.
.configuration().
.simulator and x..status().
.operational==
==True
True))
print("least busy backend: ", backend)
# Run our circuit on the least busy backend. Monitor the execution of the job in the queue
from qiskit.tools.monitor import job_monitor
shots = 1024
job = execute(dj_circuit, backend=
=backend, shots=
=shots)
job_monitor(job, interval = 2)
plot_histogram(answer)
As we can see, most of the results are 1111 . The other results are due to errors in the quantum computation.
5. Problems
A. The above implementation of Deutsch-Josza is for a balanced function with a two bit input of 𝑎 = 3 𝑎 = 3. Modify the
implementation for a constant function. Are the results what you expect? Explain.
F. Modify the implementation above for a balanced function with a 4-bit input of 𝑎 = 13 𝑎 = 13. Are the results what you expect?
Explain.
about:srcdoc Page 12 of 13
Made with Jupyter Book 11/04/20, 10(12 AM
6. References
A. David Deutsch and Richard Jozsa (1992). "Rapid solutions of problems by quantum computation". Proceedings of the Royal
Society of London A. 439: 553–558. doi:10.1098/rspa.1992.0167.
F. R. Cleve; A. Ekert; C. Macchiavello; M. Mosca (1998). "Quantum algorithms revisited". Proceedings of the Royal Society of
London A. 454: 339–354. doi:10.1098/rspa.1998.0164.
import qiskit
qiskit.
.__qiskit_version__
{'qiskit-terra': '0.12.0',
'qiskit-aer': '0.4.1',
'qiskit-ignis': '0.2.0',
'qiskit-ibmq-provider': '0.6.0',
'qiskit-aqua': '0.6.5',
'qiskit': '0.17.0'}
about:srcdoc Page 13 of 13