-
Notifications
You must be signed in to change notification settings - Fork 1
/
qOracles.py
260 lines (204 loc) · 7.24 KB
/
qOracles.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# -*- coding: utf-8 -*-
# This code is part of Qiskit.
#
# (C) Copyright IBM 2019.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""
Adapted by André Sequeira from
The Custom Circuit-based Quantum Oracle.
to
qmfOracle which marks elements of a superposition state who are greater than
a predefined value k
&
searchOracle which marks the elements of a superposition state that are equal to a certain index
"""
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.aqua import AquaError
from qiskit.aqua.components.oracles import Oracle
from mag_compare_gates import mag_gt_k
import numpy as np
class qmfOracle(Oracle):
"""
From the helper class for creating oracles from user-supplied quantum circuits
"""
def __init__(self,oracle_circuit=None,variable_register=None, output_register=None, index=None , ancillary_register=None,ancillary_mag=None,extra_regs=None):
"""
Constructor.
Args:
variable_register (QuantumRegister): The register holding variable qubit(s) for the oracle function -> Reward Register
output_register (QuantumRegister): The register holding output qubit(s) for the oracle function -> marked elements
circuit (QuantumCircuit): The quantum circuit corresponding to the intended oracle function
typically the circuit already been built
"""
super().__init__()
if variable_register is None:
raise AquaError('Missing QuantumRegister for variables.')
if index is None:
raise AquaError('Missing default maximum index.')
self._variable_register = variable_register
self._output_register = output_register if output_register is not None else QuantumRegister(1,name="out")
self._ancillary_register = ancillary_register
self._index = index
self._ancillary_mag=ancillary_mag if ancillary_mag is not None else QuantumRegister(len(self._variable_register),name="ancillary_mag")
self._extra_regs=extra_regs
if oracle_circuit is None:
self._circuit = self.construct_circuit()
else:
self._circuit = circuit
self._circuit.add_register(self._output_register,self._ancillary_mag)
if ancillary_register is not None:
self._circuit.add_register(self._ancillary_register)
@property
def variable_register(self):
return self._variable_register
@property
def output_register(self):
return self._output_register
@property
def ancillary_register(self):
return self._ancillary_register
@property
def index(self):
return self._index
@property
def circuit(self):
return self._circuit
@property
def extra_registers(self):
return self._extra_regs
@property
def get_registers(self):
regs = [self._variable_register]
if self._extra_regs is not None:
for r in self._extra_regs:
regs.append(r)
return regs
def construct_circuit(self):
"""Construct the oracle circuit.
Returns:
A quantum circuit for the oracle.
"""
qcircuit = QuantumCircuit(self._variable_register,self._output_register,self._ancillary_mag)
if self._ancillary_register is not None:
qcircuit.add_register(self._ancillary_register)
###circuit,k,output,ancilla###
mag_gt_k(qcircuit,self._variable_register,self._index,self._output_register,self._ancillary_mag)
return qcircuit
def evaluate_classically(self, measurement):
meas = measurement.split(" ")
registers={}
j=len(meas[:-1])-1
if self._extra_regs is not None:
for i in range(len(self._extra_regs)):
registers[self._extra_regs[i].name] = meas[j]
j-=1
val = int(meas[-1],2)
registers[self._variable_register.name] = val
return val>self._index , registers
class searchOracle(Oracle):
def __init__(self,oracle_circuit=None,variable_register=None, index=None , ancillary_register=None,extra_regs=None,output_register=None,method="output"):
"""
Constructor.
Args:
variable_register (QuantumRegister): The register holding variable qubit(s) for the oracle function -> Reward Register
output_register (QuantumRegister): The register holding output qubit(s) for the oracle function -> marked elements
circuit (QuantumCircuit): The quantum circuit corresponding to the intended oracle function
typically the circuit already been built
"""
super().__init__()
if variable_register is None:
raise AquaError('Missing QuantumRegister for variables.')
if index is None:
raise AquaError('Missing default index.')
self._variable_register = QuantumRegister(len(variable_register),"var_reg")
self._ancillary_register = ancillary_register
self._index = index
self._method = method
if self._method == "output":
self._output_register = QuantumRegister(1,name="out")
self._circuit = self.construct_circuit()
elif output_register is None:
raise AquaError(' Missing output ')
else:
self._output_register = output_register
self._circuit = self.construct_circuit()
self._extra_regs = extra_regs
@property
def variable_register(self):
return self._variable_register
@property
def extra_registers(self):
return self._extra_regs
@property
def state_prep_circuit(self):
return self._state_prep_circuit
@property
def output_register(self):
return self._output_register
@property
def ancillary_register(self):
return self._ancillary_register
@property
def index(self):
return self._index
@property
def circuit(self):
return self._circuit
@property
def get_registers(self):
if self._method == "no_output":
regs = [self._output_register]+[self._variable_register]
else:
regs = [self._variable_register]
if self._extra_regs is not None:
for r in self._extra_regs:
regs.append(r)
return regs
def new_index(self,index):
self._index = index
def construct_circuit(self):
"""Construct the oracle circuit.
Returns:
A quantum circuit for the oracle.
"""
if self._method == "output":
n = len(self._variable_register)
indexB = np.binary_repr(self._index,width=n)
self._circuit = QuantumCircuit(self._variable_register,self._output_register)
if self._ancillary_register is not None:
self._circuit.add_register(self._ancillary_register)
j=n-1
for q in indexB:
if not int(q):
self._circuit.x(self._variable_register[j])
j-=1
self._circuit.mct (self._variable_register, self._output_register[0],None,mode='advanced')
j=n-1
for q in indexB:
if not int(q):
self._circuit.x(self._variable_register[j])
j-=1
else:
self._circuit = QuantumCircuit(self._variable_register,self._output_register)
self._circuit.z(self._output_register)
return self._circuit
def evaluate_classically(self, measurement):
meas = measurement.split(" ")
registers={}
if self._extra_regs is not None:
for i in range(len(self._extra_regs)):
registers[self._extra_regs[i].name] = meas[i]
val = int(meas[-1],2)
if self._method == "no_output":
registers[self._output_register.name] = val
registers[self._variable_register.name] = meas[-2]
else:
registers[self._variable_register.name] = val
return val==self._index , registers