-
Notifications
You must be signed in to change notification settings - Fork 2
/
grover.py
126 lines (100 loc) · 3.36 KB
/
grover.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import numpy as np
from gates import X, Z, H
from tensorprod import tensor
def oracle(circuit, M, targets):
"""
Constructs the oracle for Grover's search algorithm for a given set of
target states.
Parameters
----------
circuit : Circuit
Quantum circuit to add the oracle to
M : integer
Number of target states
targets : list of strings
List of target states (in binary) for the Grover's search algorithm
Returns
-------
state : np.ndarray
State of the system after the application of the oracle.
"""
state = None
n = circuit.num_rails
for target in targets:
qubits = [n,] # The last qubit of the oracle is flipped when the
# function is 1, and is not flipped when the
# function is 0 (y XOR f)
gate = X.copy()
t = np.array(list(target), dtype=int)
one_controls = np.where(t == 1)[0] + 1 # +1 since rails are numbered
# from 1 to n, not 0 to n-1
zero_controls = -1 * (np.where(t == 0)[0] + 1)
controls = np.hstack((one_controls, zero_controls))
state = circuit.add_gate(gate, qubits, controls)
return state
def cond_phase_shift(circuit):
"""
Performs the conditional phase shift operation 2|0><0| - I on the given
circuit.
Parameters
----------
circuit : Circuit
Quantum circuit to apply the conditional phase shift operation on
Returns
-------
state : np.ndarray
State of the system after the application of the conditional phase
shift operation.
"""
n = circuit.num_rails
state = None
# First, invert all qubits
for i in range(1, n):
qubits = [i,]
gate = X.copy()
circuit.add_gate(gate, qubits)
# Then, apply a Z operation on any one qubit, with a control from all other
# input qubits. This will ensure that the state gets negated only when it
# is |111...1>
gate = Z.copy()
qubits = [n-1,]
controls = range(1, n-1)
circuit.add_gate(gate, qubits, controls)
# Finally, invert everything back, so that only |000...0> would have
# suffered negation
for i in range(1, n):
qubits = [i,]
gate = X.copy()
state = circuit.add_gate(gate, qubits)
return state
def iterator(circuit, M, targets):
"""
Builds and adds a Grover iterator for the given targets to the given
cicuit.
Parameters
----------
circuit : Circuit
Quantum circuit to add the oracle to
M : integer
Number of target states
targets : list of strings
List of target states (in binary) for the Grover's search algorithm
Returns
-------
state : np.ndarray
State of the system after the application of the oracle.
"""
n = circuit.num_rails
# First, apply the oracle
oracle(circuit, M, targets)
# Now, we need to perform the inversion-about-the-mean operation
# So, first apply the n-qubit Hadamard gate on the first n-1 rails
for i in range(1, n):
circuit.add_gate(H, [i,])
# Then apply the conditional phase shift operation
cond_phase_shift(circuit)
# Finally, reapply the n-qubit Hadamard gate
state = None
for i in range(1, n):
state = circuit.add_gate(H, [i,])
return state