Repository navigation
Expand file tree
/
Copy pathexample_projectq_grover.py
More file actions
112 lines (87 loc) · 3.74 KB
/
Copy pathexample_projectq_grover.py
File metadata and controls
112 lines (87 loc) · 3.74 KB
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
"""
This example is copied from https://github.com/ProjectQ-Framework/ProjectQ
and is covered under the Apache 2.0 license.
"""
import os
import math
from projectq import MainEngine
from projectq.backends import ResourceCounter, Simulator
from projectq.meta import Compute, Control, Loop, Uncompute
from projectq.ops import CNOT, CZ, All, H, Measure, X, Z
from projectq.setups import restrictedgateset
from quantuminspire.api import QuantumInspireAPI
from quantuminspire.credentials import get_authentication
from quantuminspire.projectq.backend_qx import QIBackend
QI_URL = os.getenv('API_URL', 'https://api.quantum-inspire.com/')
def run_grover(eng, n, oracle):
"""
Runs Grover's algorithm on n qubit using the provided quantum oracle.
Args:
eng (MainEngine): Main compiler engine to run Grover on.
n (int): Number of bits in the solution.
oracle (function): Function accepting the engine, an n-qubit register,
and an output qubit which is flipped by the oracle for the correct
bit string.
Returns:
solution (list<int>): Solution bit-string.
"""
x = eng.allocate_qureg(n)
# start in uniform superposition
All(H) | x
# number of iterations we have to run:
num_it = int(math.pi / 4. * math.sqrt(1 << n))
# prepare the oracle output qubit (the one that is flipped to indicate the
# solution. start in state 1/sqrt(2) * (|0> - |1>) s.t. a bit-flip turns
# into a (-1)-phase.
oracle_out = eng.allocate_qubit()
X | oracle_out
H | oracle_out
# run num_it iterations
with Loop(eng, num_it):
# oracle adds a (-1)-phase to the solution
oracle(eng, x, oracle_out)
# reflection across uniform superposition
with Compute(eng):
All(H) | x
All(X) | x
with Control(eng, x[0:-1]):
Z | x[-1]
Uncompute(eng)
All(Measure) | x
Measure | oracle_out
eng.flush()
# return result
return [int(qubit) for qubit in x]
def alternating_bits_oracle(eng, qubits, output):
"""
Marks the solution string 1,0,1,0,...,0,1 by flipping the output qubit,
conditioned on qubits being equal to the alternating bit-string.
Args:
eng (MainEngine): Main compiler engine the algorithm is being run on.
qubits (Qureg): n-qubit quantum register Grover search is run on.
output (Qubit): Output qubit to flip in order to mark the solution.
"""
with Compute(eng):
All(X) | qubits[1::2]
with Control(eng, qubits):
X | output
Uncompute(eng)
# Remote Quantum-Inspire backend
authentication = get_authentication()
qi = QuantumInspireAPI(QI_URL, authentication)
qi_backend = QIBackend(quantum_inspire_api=qi)
compiler_engines = restrictedgateset.get_engine_list(one_qubit_gates=qi_backend.one_qubit_gates,
two_qubit_gates=qi_backend.two_qubit_gates,
other_gates=qi_backend.three_qubit_gates)
compiler_engines.extend([ResourceCounter()])
qi_engine = MainEngine(backend=qi_backend, engine_list=compiler_engines)
# Run remote Grover search to find a n-bit solution
result_qi = run_grover(qi_engine, 3, alternating_bits_oracle)
print("\nResult from the remote Quantum-Inspire backend: {}".format(result_qi))
# Local ProjectQ simulator backend
compiler_engines = restrictedgateset.get_engine_list(one_qubit_gates="any", two_qubit_gates=(CNOT, CZ))
compiler_engines.append(ResourceCounter())
local_engine = MainEngine(Simulator(), compiler_engines)
# Run local Grover search to find a n-bit solution
result_local = run_grover(local_engine, 3, alternating_bits_oracle)
print("Result from the local ProjectQ simulator backend: {}\n".format(result_local))