QNLP  v1.0
test_diffusion.cpp File Reference
#include "diffusion.hpp"
#include "oracle.hpp"
#include "Simulator.hpp"
#include "IntelSimulator.cpp"
#include "catch2/catch.hpp"
#include <bitset>
Include dependency graph for test_diffusion.cpp:

Go to the source code of this file.

Typedefs

typedef ComplexDP Type
 

Functions

 TEST_CASE ("4 qubit diffusion using module","[diffusion]")
 Test diffusion for 4 qubits. More...
 
 TEST_CASE ("8 qubit diffusion using module","[diffusion]")
 Test diffusion for 8 qubits. More...
 
 TEST_CASE ("4 qubit diffusion using Simulator method","[diffusion]")
 Test diffusion for 4 qubits using Simulator method. More...
 
 TEST_CASE ("8 qubit diffusion using Simulator method","[diffusion]")
 Test diffusion for 8 qubits using Simulator method. More...
 

Typedef Documentation

◆ Type

typedef ComplexDP Type

Definition at line 11 of file test_diffusion.cpp.

Function Documentation

◆ TEST_CASE() [1/4]

TEST_CASE ( "4 qubit diffusion using module"  ,
""  [diffusion] 
)

Test diffusion for 4 qubits.

Definition at line 17 of file test_diffusion.cpp.

17  {
18  std::size_t num_qubits = 4;
20  auto& reg = sim.getQubitRegister();
21  double previous_prob = 0.;
22 
23  SECTION("2^4 bit patterns (16)"){
24  // Testing patterns 000 001 010 011, etc.
25  std::vector<std::size_t> bit_patterns;
26  for(std::size_t s = 0; s < (std::size_t)(0b1 << num_qubits); s++){
27  bit_patterns.push_back(s);
28  }
29 
30  //Declare which indices are control lines
31  std::vector<std::size_t> ctrl_indices;
32  for(std::size_t i = 0; i < num_qubits-1; ++i){
33  ctrl_indices.push_back(i);
34  }
35 
36  //Create oracle object with num_ctrl_gates and indices
37  Oracle<decltype(sim)> oracle;
38 
39  Diffusion<decltype(sim)> diffusion;
40 
41  // Loop over given bit-patterns and show effect on resulting state
42  for(auto &i : bit_patterns){
43  DYNAMIC_SECTION("bitStringNCU with pattern " << i){
44  sim.initRegister();
45  //Create initial superposition
46  for(std::size_t j = 0; j < num_qubits; ++j){
47  sim.applyGateH(j);
48  }
49 
50  // sqrt(N) iterations optimal
51  for(int iteration = 1 ; iteration < (M_PI/4)*sqrt( (0b1<<num_qubits) / 1); iteration++){
52  // Mark state: convert matching state pattern to |11...1>
53  // apply nCZ, and undo conversion; negates the matched pattern phase
54  oracle.bitStringNCU(sim, i, ctrl_indices, num_qubits-1, sim.getGateZ(), "Z");
55 
56  CAPTURE( reg[i], i );
57  //REQUIRE( reg[i].real() < 0.);
58  //reg.Print("PRE-DIFF iteration=" + std::to_string(iteration));
59 
60  diffusion.applyOpDiffusion( sim, ctrl_indices, num_qubits-1);
61  CAPTURE( reg[i], i );
62  if(i>0){
63  REQUIRE( abs(reg[i])*abs(reg[i]) > abs(reg[0])*abs(reg[0]) );
64  }
65  else {
66  REQUIRE( abs(reg[i])*abs(reg[i]) > abs(reg[1])*abs(reg[1]) );
67  }
68  REQUIRE( abs(reg[i])*abs(reg[i]) > previous_prob );
69  previous_prob = abs(reg[i])*abs(reg[i]);
70  }
71  }
72  }
73  }
74 }
Class definition for IntelSimulator. The purpose of this class is to map the functionality of the und...
Class definition for defining and applying an Oracle.
Definition: oracle.hpp:26
Class definition for applying Grover diffusion to a marked register.
Definition: diffusion.hpp:27
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
void applyOpDiffusion(SimulatorType &sim, const std::vector< std::size_t > &ctrlIndices, const std::size_t target)
Application of the Grover diffusion operator to already marked register. Follows the Q = -A S_0 A str...
Definition: diffusion.hpp:49

References QNLP::Diffusion< SimulatorType >::applyOpDiffusion(), QNLP::Oracle< SimulatorType >::bitStringNCU(), ncu_opt_tester::num_qubits, and ncu_opt_tester::sim.

Here is the call graph for this function:

◆ TEST_CASE() [2/4]

TEST_CASE ( "8 qubit diffusion using module"  ,
""  [diffusion] 
)

Test diffusion for 8 qubits.

Definition at line 80 of file test_diffusion.cpp.

80  {
81  std::size_t num_qubits = 8;
83  auto& reg = sim.getQubitRegister();
84  double previous_prob = 0.;
85 
86  SECTION("2^8 bit patterns (256)"){
87  // Testing patterns 000 001 010 011, etc.
88  std::vector<std::size_t> bit_patterns;
89  for(std::size_t s = 0; s < (std::size_t)(0b1 << num_qubits); s++){
90  bit_patterns.push_back(s);
91  }
92 
93  //Declare which indices are control lines
94  std::vector<std::size_t> ctrl_indices;
95  for(std::size_t i = 0; i < num_qubits-1; ++i){
96  ctrl_indices.push_back(i);
97  }
98 
99  //Create oracle object with num_ctrl_gates and indices
100  Oracle<decltype(sim)> oracle;
101 
102  Diffusion<decltype(sim)> diffusion;
103 
104  // Loop over given bit-patterns and show effect on resulting state
105  for(auto &i : bit_patterns){
106  DYNAMIC_SECTION("bitStringNCU with pattern " << i){
107  sim.initRegister();
108  //Create initial superposition
109  for(std::size_t j = 0; j < num_qubits; ++j){
110  sim.applyGateH(j);
111  }
112 
113  // O sqrt(N) iterations optimal
114  // R = (M_PI/4)*sqrt( (0b1<<num_qubits) / 1);
115  for(int iteration = 1 ; iteration < (M_PI/4)*sqrt( (0b1<<num_qubits) / 1); iteration++){
116  // Mark state: convert matching state pattern to |11...1>
117  // apply nCZ, and undo conversion; negates the matched pattern phase
118  oracle.bitStringNCU(sim, i, ctrl_indices, num_qubits-1, sim.getGateZ(), "Z");
119 
120  CAPTURE( reg[i], i );
121  //REQUIRE( reg[i].real() < 0.);
122  //reg.Print("PRE-DIFF iteration=" + std::to_string(iteration));
123 
124  diffusion.applyOpDiffusion( sim, ctrl_indices, num_qubits-1);
125  CAPTURE( reg[i], i );
126  if(i>0){
127  REQUIRE( abs(reg[i])*abs(reg[i]) > abs(reg[0])*abs(reg[0]) );
128  }
129  else {
130  REQUIRE( abs(reg[i])*abs(reg[i]) > abs(reg[1])*abs(reg[1]) );
131  }
132  REQUIRE( abs(reg[i])*abs(reg[i]) > previous_prob );
133  previous_prob = abs(reg[i])*abs(reg[i]);
134  }
135  }
136  }
137  }
138 }
Class definition for IntelSimulator. The purpose of this class is to map the functionality of the und...
Class definition for defining and applying an Oracle.
Definition: oracle.hpp:26
Class definition for applying Grover diffusion to a marked register.
Definition: diffusion.hpp:27
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
void applyOpDiffusion(SimulatorType &sim, const std::vector< std::size_t > &ctrlIndices, const std::size_t target)
Application of the Grover diffusion operator to already marked register. Follows the Q = -A S_0 A str...
Definition: diffusion.hpp:49

References QNLP::Diffusion< SimulatorType >::applyOpDiffusion(), QNLP::Oracle< SimulatorType >::bitStringNCU(), ncu_opt_tester::num_qubits, and ncu_opt_tester::sim.

Here is the call graph for this function:

◆ TEST_CASE() [3/4]

TEST_CASE ( "4 qubit diffusion using Simulator method"  ,
""  [diffusion] 
)

Test diffusion for 4 qubits using Simulator method.

Definition at line 144 of file test_diffusion.cpp.

144  {
145  std::size_t num_qubits = 4;
147  auto& reg = sim.getQubitRegister();
148  double previous_prob = 0.;
149 
150  SECTION("2^4 bit patterns (16)"){
151  // Testing patterns 000 001 010 011, etc.
152  std::vector<std::size_t> bit_patterns;
153  for(std::size_t s = 0; s < (std::size_t)(0b1 << num_qubits); s++){
154  bit_patterns.push_back(s);
155  }
156 
157  //Declare which indices are control lines
158  std::vector<std::size_t> ctrl_indices;
159  for(std::size_t i = 0; i < num_qubits-1; ++i){
160  ctrl_indices.push_back(i);
161  }
162 
163  // Loop over given bit-patterns and show effect on resulting state
164  for(auto &i : bit_patterns){
165  DYNAMIC_SECTION("bitStringNCU with pattern " << i){
166  sim.initRegister();
167  //Create initial superposition
168  for(std::size_t j = 0; j < num_qubits; ++j){
169  sim.applyGateH(j);
170  }
171 
172  // sqrt(N) iterations optimal
173  for(int iteration = 1 ; iteration < (M_PI/4)*sqrt( (0b1<<num_qubits) / 1); iteration++){
174  // Mark state: convert matching state pattern to |11...1>
175  // apply nCZ, and undo conversion; negates the matched pattern phase
176  sim.applyOracleU(i, ctrl_indices, num_qubits-1, sim.getGateZ(), "Z");
177 
178  CAPTURE( reg[i], i );
179  sim.applyDiffusion(ctrl_indices, num_qubits-1);
180 
181  CAPTURE( reg[i], i );
182  if(i>0){
183  REQUIRE( abs(reg[i])*abs(reg[i]) > abs(reg[0])*abs(reg[0]) );
184  }
185  else {
186  REQUIRE( abs(reg[i])*abs(reg[i]) > abs(reg[1])*abs(reg[1]) );
187  }
188  REQUIRE( abs(reg[i])*abs(reg[i]) > previous_prob );
189  previous_prob = abs(reg[i])*abs(reg[i]);
190  }
191  }
192  }
193  }
194 }
Class definition for IntelSimulator. The purpose of this class is to map the functionality of the und...

References ncu_opt_tester::num_qubits, and ncu_opt_tester::sim.

◆ TEST_CASE() [4/4]

TEST_CASE ( "8 qubit diffusion using Simulator method"  ,
""  [diffusion] 
)

Test diffusion for 8 qubits using Simulator method.

Definition at line 200 of file test_diffusion.cpp.

200  {
201  std::size_t num_qubits = 8;
203  auto& reg = sim.getQubitRegister();
204  double previous_prob = 0.;
205 
206  SECTION("2^8 bit patterns (256)"){
207  // Testing patterns 000 001 010 011, etc.
208  std::vector<std::size_t> bit_patterns;
209  for(std::size_t s = 0; s < (std::size_t)(0b1 << num_qubits); s++){
210  bit_patterns.push_back(s);
211  }
212 
213  //Declare which indices are control lines
214  std::vector<std::size_t> ctrl_indices;
215  for(std::size_t i = 0; i < num_qubits-1; ++i){
216  ctrl_indices.push_back(i);
217  }
218 
219  // Loop over given bit-patterns and show effect on resulting state
220  for(auto &i : bit_patterns){
221  DYNAMIC_SECTION("bitStringNCU with pattern " << i){
222  sim.initRegister();
223  //Create initial superposition
224  for(std::size_t j = 0; j < num_qubits; ++j){
225  sim.applyGateH(j);
226  }
227 
228  // O sqrt(N) iterations optimal
229  // R = (M_PI/4)*sqrt( (0b1<<num_qubits) / 1);
230  for(int iteration = 1 ; iteration < (M_PI/4)*sqrt( (0b1<<num_qubits) / 1); iteration++){
231  // Mark state: convert matching state pattern to |11...1>
232  // apply nCZ, and undo conversion; negates the matched pattern phase
233  sim.applyOracleU(i, ctrl_indices, num_qubits-1, sim.getGateZ(), "Z");
234 
235  CAPTURE( reg[i], i );
236 
237  sim.applyDiffusion(ctrl_indices, num_qubits-1);
238  CAPTURE( reg[i], i );
239  if(i>0){
240 
241  REQUIRE( abs(reg[i])*abs(reg[i]) > abs(reg[0])*abs(reg[0]) );
242  }
243  else {
244  REQUIRE( abs(reg[i])*abs(reg[i]) > abs(reg[1])*abs(reg[1]) );
245  }
246  REQUIRE( abs(reg[i])*abs(reg[i]) > previous_prob );
247  previous_prob = abs(reg[i])*abs(reg[i]);
248  }
249  }
250  }
251  }
252 }
Class definition for IntelSimulator. The purpose of this class is to map the functionality of the und...

References ncu_opt_tester::num_qubits, and ncu_opt_tester::sim.