QNLP  v1.0
test_oracle.cpp
Go to the documentation of this file.
1 #include "oracle.hpp"
2 
3 #include "Simulator.hpp"
4 #include "IntelSimulator.cpp"
5 #include "catch2/catch.hpp"
6 
7 #include <bitset>
8 
9 using namespace QNLP;
10 
11 //For simplicity, enabling complex double only
12 typedef ComplexDP Type;
13 template class QNLP::Oracle<IntelSimulator>;
14 
19 TEST_CASE("3 qubit Oracle standalone class","[oracle]"){
20  std::size_t num_qubits = 3;
22  auto& reg = sim.getQubitRegister();
23  Oracle<decltype(sim)> oracle;
24 
25  SECTION("2^3 bit patterns (8)"){
26  // Testing patterns 000 001 010 011, etc.
27  const std::vector<std::size_t> bit_patterns {0, 1, 2, 3, 4, 5, 6, 7};
28 
29  //Declare which indices are control lines
30  std::vector<std::size_t> ctrl_indices;
31  for(std::size_t i = 0; i < num_qubits-1; ++i){
32  ctrl_indices.push_back(i);
33  }
34 
35  // Loop over given bit-patterns and show effect on resulting state
36  for(auto &i : bit_patterns){
37  DYNAMIC_SECTION("bitStringNCU with pattern " << i){
38  sim.initRegister();
39  //Create initial superposition
40  for(std::size_t j = 0; j < num_qubits; ++j){
41  sim.applyGateH(j);
42  }
43 
44  // Mark state: convert matching state pattern to |11...1>
45  // apply nCZ, and undo conversion; negates the matched pattern phase
46  oracle.bitStringNCU(sim, i, ctrl_indices, num_qubits-1, sim.getGateZ(), "Z");
47 
48  CAPTURE( reg[i], i );
49  REQUIRE( reg[i].real() < 0.);
50  }
51 
52  DYNAMIC_SECTION("bitStringPhaseOracle with pattern " << i){
53  sim.initRegister();
54  //Create initial superposition
55  for(std::size_t j = 0; j < num_qubits; ++j){
56  sim.applyGateH(j);
57  }
58 
59  // Mark state: convert matching state pattern to |11...1>
60  // apply nCZ, and undo conversion; negates the matched pattern phase
61  oracle.bitStringPhaseOracle(sim, i, ctrl_indices, num_qubits-1);
62 
63  CAPTURE( reg[i], i );
64  REQUIRE( reg[i].real() < 0.);
65  }
66  }
67  }
68 
69  SECTION("4 bit patterns"){
70  // Testing patterns 000 001 010 011, etc.
71  const std::vector<std::size_t> bit_patterns {0, 5, 6, 7};
72 
73  //Declare which indices are control lines
74  std::vector<std::size_t> ctrl_indices;
75  for(std::size_t i = 0; i < num_qubits-1; ++i){
76  ctrl_indices.push_back(i);
77  }
78 
79  // Loop over given bit-patterns and show effect on resulting state
80  for(auto &i : bit_patterns){
81  DYNAMIC_SECTION("bitStringNCU with pattern " << i){
82  sim.initRegister();
83  //Create initial superposition
84  for(std::size_t j = 0; j < num_qubits; ++j){
85  sim.applyGateH(j);
86  }
87 
88  // Mark state: convert matching state pattern to |11...1>
89  // apply nCZ, and undo conversion; negates the matched pattern phase
90  oracle.bitStringNCU(sim, i, ctrl_indices, num_qubits-1, sim.getGateZ(), "Z");
91 
92  CAPTURE( reg[i], i );
93  REQUIRE( reg[i].real() < 0.);
94  }
95 
96  DYNAMIC_SECTION("bitStringPhaseOracle with pattern " << i){
97  sim.initRegister();
98  //Create initial superposition
99  for(std::size_t j = 0; j < num_qubits; ++j){
100  sim.applyGateH(j);
101  }
102 
103  // Mark state: convert matching state pattern to |11...1>
104  // apply nCZ, and undo conversion; negates the matched pattern phase
105  oracle.bitStringPhaseOracle(sim, i, ctrl_indices, num_qubits-1);
106 
107  CAPTURE( reg[i], i );
108  REQUIRE( reg[i].real() < 0.);
109  }
110  }
111  }
112 }
113 
118 TEST_CASE("8 qubit Oracle standalone class","[oracle]"){
119  std::size_t num_qubits = 8;
121  auto& reg = sim.getQubitRegister();
122  Oracle<decltype(sim)> oracle;
123 
124  SECTION("2^8 bit patterns (256)"){
125  // Testing patterns 000 001 010 011, etc.
126  std::vector<std::size_t> bit_patterns;
127  for (std::size_t s = 0; s < (std::size_t) (0b1 << num_qubits); s++){
128  bit_patterns.push_back(s);
129  }
130 
131  //Declare which indices are control lines
132  std::vector<std::size_t> ctrl_indices;
133  for(std::size_t i = 0; i < num_qubits-1; ++i){
134  ctrl_indices.push_back(i);
135  }
136 
137  // Loop over given bit-patterns and show effect on resulting state
138  for(auto &i : bit_patterns){
139  DYNAMIC_SECTION("bitStringNCU with pattern " << i){
140  sim.initRegister();
141  //Create initial superposition
142  for(std::size_t j = 0; j < num_qubits; ++j){
143  sim.applyGateH(j);
144  }
145 
146  // Mark state: convert matching state pattern to |11...1>
147  // apply nCZ, and undo conversion; negates the matched pattern phase
148  oracle.bitStringNCU(sim, i, ctrl_indices, num_qubits-1, sim.getGateZ(), "Z");
149 
150  CAPTURE( reg[i], i );
151  REQUIRE( reg[i].real() < 0.);
152  }
153 
154  DYNAMIC_SECTION("bitStringPhaseOracle with pattern " << i){
155  sim.initRegister();
156  //Create initial superposition
157  for(std::size_t j = 0; j < num_qubits; ++j){
158  sim.applyGateH(j);
159  }
160 
161  // Mark state: convert matching state pattern to |11...1>
162  // apply nCZ, and undo conversion; negates the matched pattern phase
163  oracle.bitStringPhaseOracle(sim, i, ctrl_indices, num_qubits-1);
164 
165  CAPTURE( reg[i], i );
166  REQUIRE( reg[i].real() < 0.);
167  }
168  }
169  }
170 
171  SECTION("4 bit patterns"){
172  // Testing patterns 000 001 010 011, etc.
173  const std::vector<std::size_t> bit_patterns {0, 5, 6, 7};
174 
175  //Declare which indices are control lines
176  std::vector<std::size_t> ctrl_indices;
177  for(std::size_t i = 0; i < num_qubits-1; ++i){
178  ctrl_indices.push_back(i);
179  }
180 
181  // Loop over given bit-patterns and show effect on resulting state
182  for(auto &i : bit_patterns){
183  DYNAMIC_SECTION("bitStringNCU with pattern " << i){
184  sim.initRegister();
185  //Create initial superposition
186  for(std::size_t j = 0; j < num_qubits; ++j){
187  sim.applyGateH(j);
188  }
189 
190  // Mark state: convert matching state pattern to |11...1>
191  // apply nCZ, and undo conversion; negates the matched pattern phase
192  oracle.bitStringNCU(sim, i, ctrl_indices, num_qubits-1, sim.getGateZ(), "Z");
193 
194  CAPTURE( reg[i], i );
195  REQUIRE( reg[i].real() < 0.);
196  }
197 
198  DYNAMIC_SECTION("bitStringPhaseOracle with pattern " << i){
199  sim.initRegister();
200  //Create initial superposition
201  for(std::size_t j = 0; j < num_qubits; ++j){
202  sim.applyGateH(j);
203  }
204 
205  // Mark state: convert matching state pattern to |11...1>
206  // apply nCZ, and undo conversion; negates the matched pattern phase
207  oracle.bitStringPhaseOracle(sim, i, ctrl_indices, num_qubits-1);
208 
209  CAPTURE( reg[i], i );
210  REQUIRE( reg[i].real() < 0.);
211  }
212  }
213  }
214 }
215 
220 TEST_CASE("3 qubit Oracle simulator method","[oracle]"){
221  std::size_t num_qubits = 3;
223  auto& reg = sim.getQubitRegister();
224 
225  SECTION("2^3 bit patterns (8)"){
226  // Testing patterns 000 001 010 011, etc.
227  const std::vector<std::size_t> bit_patterns {0, 1, 2, 3, 4, 5, 6, 7};
228 
229  //Declare which indices are control lines
230  std::vector<std::size_t> ctrl_indices;
231  for(std::size_t i = 0; i < num_qubits-1; ++i){
232  ctrl_indices.push_back(i);
233  }
234 
235  // Loop over given bit-patterns and show effect on resulting state
236  for(auto &i : bit_patterns){
237  DYNAMIC_SECTION("applyOracleU with pattern " << i){
238  sim.initRegister();
239  //Create initial superposition
240  for(std::size_t j = 0; j < num_qubits; ++j){
241  sim.applyGateH(j);
242  }
243 
244  // Mark state: convert matching state pattern to |11...1>
245  // apply nCZ, and undo conversion; negates the matched pattern phase
246  //oracle.bitStringNCU(sim, i, ctrl_indices, num_qubits-1, sim.getGateZ());
247  sim.applyOracleU(i, ctrl_indices, num_qubits-1, sim.getGateZ(), "Z");
248 
249  CAPTURE( reg[i], i );
250  REQUIRE( reg[i].real() < 0.);
251  }
252 
253  DYNAMIC_SECTION("applyOraclePhase with pattern " << i){
254  sim.initRegister();
255  //Create initial superposition
256  for(std::size_t j = 0; j < num_qubits; ++j){
257  sim.applyGateH(j);
258  }
259 
260  // Mark state: convert matching state pattern to |11...1>
261  // apply nCZ, and undo conversion; negates the matched pattern phase
262  sim.applyOraclePhase(i, ctrl_indices, num_qubits-1);
263 
264  CAPTURE( reg[i], i );
265  REQUIRE( reg[i].real() < 0.);
266  }
267  }
268  }
269 
270  SECTION("4 bit patterns"){
271  // Testing patterns 000 001 010 011, etc.
272  const std::vector<std::size_t> bit_patterns {0, 5, 6, 7};
273 
274  //Declare which indices are control lines
275  std::vector<std::size_t> ctrl_indices;
276  for(std::size_t i = 0; i < num_qubits-1; ++i){
277  ctrl_indices.push_back(i);
278  }
279 
280  // Loop over given bit-patterns and show effect on resulting state
281  for(auto &i : bit_patterns){
282  DYNAMIC_SECTION("applyOracleU with pattern " << i){
283  sim.initRegister();
284  //Create initial superposition
285  for(std::size_t j = 0; j < num_qubits; ++j){
286  sim.applyGateH(j);
287  }
288 
289  // Mark state: convert matching state pattern to |11...1>
290  // apply nCZ, and undo conversion; negates the matched pattern phase
291  sim.applyOracleU(i, ctrl_indices, num_qubits-1, sim.getGateZ(), "Z");
292 
293  CAPTURE( reg[i], i );
294  REQUIRE( reg[i].real() < 0.);
295  }
296 
297  DYNAMIC_SECTION("applyOraclePhase with pattern " << i){
298  sim.initRegister();
299  //Create initial superposition
300  for(std::size_t j = 0; j < num_qubits; ++j){
301  sim.applyGateH(j);
302  }
303 
304  // Mark state: convert matching state pattern to |11...1>
305  // apply nCZ, and undo conversion; negates the matched pattern phase
306  sim.applyOraclePhase(i, ctrl_indices, num_qubits-1);
307 
308  CAPTURE( reg[i], i );
309  REQUIRE( reg[i].real() < 0.);
310  }
311  }
312  }
313 }
314 
319 TEST_CASE("8 qubit Oracle simulator method","[oracle]"){
320  std::size_t num_qubits = 8;
322  auto& reg = sim.getQubitRegister();
323 
324  SECTION("2^8 bit patterns (256)"){
325  // Testing patterns 000 001 010 011, etc.
326  std::vector<std::size_t> bit_patterns;
327  for (std::size_t s = 0; s < (std::size_t) (0b1 << num_qubits); s++){
328  bit_patterns.push_back(s);
329  }
330 
331  //Declare which indices are control lines
332  std::vector<std::size_t> ctrl_indices;
333  for(std::size_t i = 0; i < num_qubits-1; ++i){
334  ctrl_indices.push_back(i);
335  }
336 
337  // Loop over given bit-patterns and show effect on resulting state
338  for(auto &i : bit_patterns){
339  DYNAMIC_SECTION("applyOracleU with pattern " << i){
340  sim.initRegister();
341  //Create initial superposition
342  for(std::size_t j = 0; j < num_qubits; ++j){
343  sim.applyGateH(j);
344  }
345 
346  // Mark state: convert matching state pattern to |11...1>
347  // apply nCZ, and undo conversion; negates the matched pattern phase
348  sim.applyOracleU(i, ctrl_indices, num_qubits-1, sim.getGateZ(), "Z");
349 
350  CAPTURE( reg[i], i );
351  REQUIRE( reg[i].real() < 0.);
352  }
353 
354  DYNAMIC_SECTION("applyOraclePhase with pattern " << i){
355  sim.initRegister();
356  //Create initial superposition
357  for(std::size_t j = 0; j < num_qubits; ++j){
358  sim.applyGateH(j);
359  }
360 
361  // Mark state: convert matching state pattern to |11...1>
362  // apply nCZ, and undo conversion; negates the matched pattern phase
363  sim.applyOraclePhase(i, ctrl_indices, num_qubits-1);
364 
365  CAPTURE( reg[i], i );
366  REQUIRE( reg[i].real() < 0.);
367  }
368  }
369  }
370 
371  SECTION("4 bit patterns"){
372  // Testing patterns 000 001 010 011, etc.
373  const std::vector<std::size_t> bit_patterns {0, 5, 6, 7};
374 
375  //Declare which indices are control lines
376  std::vector<std::size_t> ctrl_indices;
377  for(std::size_t i = 0; i < num_qubits-1; ++i){
378  ctrl_indices.push_back(i);
379  }
380 
381  // Loop over given bit-patterns and show effect on resulting state
382  for(auto &i : bit_patterns){
383  DYNAMIC_SECTION("applyOracleU with pattern " << i){
384  sim.initRegister();
385  //Create initial superposition
386  for(std::size_t j = 0; j < num_qubits; ++j){
387  sim.applyGateH(j);
388  }
389 
390  // Mark state: convert matching state pattern to |11...1>
391  // apply nCZ, and undo conversion; negates the matched pattern phase
392  sim.applyOracleU(i, ctrl_indices, num_qubits-1, sim.getGateZ(), "Z");
393 
394  CAPTURE( reg[i], i );
395  REQUIRE( reg[i].real() < 0.);
396  }
397 
398  DYNAMIC_SECTION("applyOraclePhase with pattern " << i){
399  sim.initRegister();
400  //Create initial superposition
401  for(std::size_t j = 0; j < num_qubits; ++j){
402  sim.applyGateH(j);
403  }
404 
405  // Mark state: convert matching state pattern to |11...1>
406  // apply nCZ, and undo conversion; negates the matched pattern phase
407  sim.applyOraclePhase(i, ctrl_indices, num_qubits-1);
408 
409  CAPTURE( reg[i], i );
410  REQUIRE( reg[i].real() < 0.);
411  }
412  }
413  }
414 }
Class definition for IntelSimulator. The purpose of this class is to map the functionality of the und...
TEST_CASE("3 qubit Oracle standalone class","[oracle]")
Test 3 qubit Oracle standalone class.
Definition: test_oracle.cpp:19
Class definition for defining and applying an Oracle.
Definition: oracle.hpp:26
static void bitStringPhaseOracle(SimulatorType &s, std::size_t bitstring, const std::vector< std::size_t > &ctrlIndices, std::size_t target)
Takes bitstring as the binary pattern and indices as the qubits to operate upon. Applies the appropri...
Definition: oracle.hpp:126
Functions for applying black-box like functions to select appropriate qubits matching given patterns.
static void bitStringNCU(SimulatorType &s, std::size_t bitstring, const std::vector< std::size_t > &ctrl_indices, const std::size_t target, const Mat2x2Type &U, std::string gateLabel)
Takes bitstring as the binary pattern and indices as the qubits to operate upon. Applies the appropri...
Definition: oracle.hpp:54
ComplexDP Type
Definition: test_oracle.cpp:12