Use this file to discover all available pages before exploring further.
View on GitHub
Open this notebook in GitHub to run it yourself
“Quantum Walk” is an approach for developing and designing quantum algorithms.Consider it as a quantum analogy to the classical random walk.This generic technique underlies many quantum algorithms. In particular, the Grover’s search algorithm can be viewed as a quantum walk.Similarly to classical random walks, quantum walks are divided into the discrete and continuous cases.This notebook focuses on discrete quantum walks, and is organized as follows:
One to one compares classical random walks with quantum walks via a specific example: a walk on a circle.
Specify and implement a simple example: a discrete walk on a circle, or more precisely, on a regular polygon with 2N nodes (see Figure 1).The idea behind the random/quantum walk:
Start at some initial point, e.g., the zeroth node.
Flip a coin.
Heads moves one step clockwise; tails moves counterclockwise.
Repeat steps 1-2 for a given total number of steps T.
import matplotlib.pyplot as pltimport numpy as npfrom classiq import *
Code a classical random walk and a discrete quantum walk side by side:Define a function to flip a coin:
Classical: the coin is either 0 or
To flip the coin, draw a random number from the set {0,1}.
Quantum: the coin is represented by a qubit and a “flip” is defined by some unitary operation on it.
Choose the Hadamard gate, which sends the ∣0⟩ state into an equal superposition of ∣0⟩ and ∣1⟩.
Finally, construct a function for the full walk, iterating between flipping a coin and a single walking step based on the coin’s state.Note the difference between the classical and quantum function declarations.For the quantum part you do not need to pass the circle size, as it is given by the size of the position state x.
# classicaldef random_walk_circle( time, # total time x, # position circle_size, # the size of the circle): coin = 0 for step in range(time): coin = classical_coin_flip(coin) if coin == 0: x = classical_step_clockwise(x, CIRCLE_SIZE) if coin == 1: x = classical_step_counterclockwise(x, CIRCLE_SIZE) return x# quantum@qfuncdef discrete_quantum_walk_circle( time: CInt, # total time coin: QBit, # coin x: QArray, # position): power( time, lambda: ( quantum_coin_flip(coin), control( coin == 0, lambda: quantum_step_clockwise(x), lambda: invert(lambda: quantum_step_clockwise(x)), ), ), )
Define and run a specific example, taking a circle of size 27, a total time of 50 steps, and 10,000 samples.
Quantum program link: https://platform.classiq.io/circuit/30HaT5Wr5mIPQAuGiEZCUj1r9VW
Plot the probabilities of ending at each position along the circle. In both the classical and quantum cases, consider the probability of the final position after time T=50.
There is a clear difference between the two distributions: the classical distribution is symmetric around the zero position, whereas the quantum example is asymmetric with a peak far from
This is a small example of the different behaviors of classical random walks and quantum walks.
As a first example, consider the circle geometry above, implemented with the generic definition but with a different initial condition for the coin.Take 21(∣0⟩+i∣1⟩) instead of ∣0⟩.This state is a balanced initial condition for the coin (see Ref. [1]) and can be prepared by applying an H gate followed by an S gate.
Now that the model is defined, you can synthesize, execute, and plot the outcome probability:
qprog_2 = synthesize(qmod_2)show(qprog_2)with ExecutionSession(qprog_2) as es: result_2 = es.sample({"t": 50})quantum_probs = { sample.state["x"]: sample.shots / NUM_SAMPLES for sample in result_2.parsed_counts}sorted_quantum_probs = dict(sorted(quantum_probs.items()))plt.plot(sorted_quantum_probs.keys(), sorted_quantum_probs.values(), ".-")plt.xlabel("position", fontsize=16)plt.ylabel("probability", fontsize=16)
Output:
Quantum program link: https://platform.classiq.io/circuit/30HaUVxpQxdS1rgV2do87MyYIPM
Output:
Text(0, 0.5, 'probability')
The distribution is symmetric. Clearly, the distribution of a quantum walk on a circle depends on the initial condition for the coin.This is another example of the peculiar behavior of quantum walks compared to classical random walks.
Next, consider a hypercube graph (see Figure 3).The quantum walk on a hypercube shows completely different behavior compared to its classical counterpart.One striking difference refers to the hitting time, which is the time it takes to reach node v starting from an initial node u. In particular, an interesting question is the hitting time between one corner of the hypercube “000..0” to the opposite one “111…1”. Ref. [2]) shows that the hitting time for the hypercube in quantum walks is exponentially faster than the analog quantity in classical random walks.The rigorous definition of the “hitting time” in the quantum case is nontrivial, and different definitions are relevant.This notebook does not use the exact definition, but simply demonstrates a specific result, highlighting the result of Ref. [2].Define Pcorner(T) as the probability of measuring the walker at the opposite corner ∣2N−1⟩ after T steps, starting at position ∣0⟩ at time
Examine this quantity for the quantum and the classical case.
Define a model for quantum walk on a hypercube.Two nodes in the hypercube are connected to each other if their Hamming distance is
Thus, a step along a hypercube is given by moving “1 Hamming distance away”.
For a d-dimensional hypercube, at each node there are d possible directions to move.Each of them is given by applying a bit flip on one of the bits. In the quantum case, this is obtained by applying an X gate on one of the N qubits.For the coin operator, take the “Grover diffuser” function.This choice refers to a symmetric quantum walk [1].The Grover diffuser operator is a reflection around a given state ∣ψ⟩:G=I−2∣ψ⟩⟨ψ∣,where I is the identity matrix. In the N-dimensional hypercube each node is connected to N nodes, thus, the coin state should include N different states. Therefore, the coin is represented by a quantum variable of size ⌈log2(N)⌉, and the Grover diffuser is defined with∣ψ⟩=N1i=0∑N−1∣i⟩.Build the model using the grover_diffuser function from the Classiq open library.
from classiq.execution import ExecutionPreferencesfrom classiq.qmod.symbolic import ceilingSPACE_SIZE = 4NUM_SHOTS = 1e4@qfuncdef main(t: CInt, x: Output[QArray[QBit, SPACE_SIZE]], coin: Output[QArray]): # start at the zero state location allocate(x) # start with equal superposition for the relevant states. allocate(SPACE_SIZE.bit_length() - 1, coin) prepare_uniform_trimmed_state(SPACE_SIZE, coin) discrete_quantum_walk( t, lambda coin: grover_diffuser( lambda coin: prepare_uniform_trimmed_state(SPACE_SIZE, coin), coin ), [ lambda: moving_one_hamming_dist(0, x), lambda: moving_one_hamming_dist(1, x), lambda: moving_one_hamming_dist(2, x), lambda: moving_one_hamming_dist(3, x), ], coin, )qmod_3 = create_model( main, execution_preferences=ExecutionPreferences(num_shots=NUM_SHOTS), constraints=Constraints(optimization_parameter="width"),)
qprog_3 = synthesize(qmod_3)show(qprog_3)
Output:
Quantum program link: https://platform.classiq.io/circuit/30HaVnHxgmGp7vcXVzm1HI85Iec
with ExecutionSession(qprog_3) as es: result_3 = es.sample({"t": 4})
print( "The probability to reach the opposite corner:", result_3.counts.get("1" * SPACE_SIZE, 0) / NUM_SHOTS,)
Output:
The probability to reach the opposite corner: 0.566
At T=4, the probability to measure the walker at the opposite corner is larger than 1/2.Check an analogous question in the classical random walk, where the distribution is taken over an ensemble of independent experiments:
initial_point = 0final_point = dict()for sample in range(NUM_SAMPLES): coin_state = np.random.randint(SPACE_SIZE) for k in range(SPACE_SIZE): if coin_state == k: temp_point = initial_point ^ 2**k initial_point = temp_point final_point[initial_point] = final_point.get(initial_point, 0) + 1print( "The probability to reach the opposite corner in the classical case:", final_point.get(2**SPACE_SIZE - 1, 0) / NUM_SAMPLES,)
Output:
The probability to reach the opposite corner in the classical case: 0.0583