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

Go to the source code of this file.

Typedefs

typedef ComplexDP Type
 

Functions

 TEST_CASE ("Test n-controlled unitary module with Pauli-X |11..10>","[ncu]")
 Test PauliX for NCU. More...
 
 TEST_CASE ("Test n-controlled unitary module with Pauli-Z on |111..1>","[ncu]")
 Test Pauli-Z for NCU. More...
 
 TEST_CASE ("Test n-controlled unitary module with Pauli-X and non-adjacent controls","[ncu]")
 Test Pauli-X and non-adjacent controls for NCU. More...
 

Typedef Documentation

◆ Type

typedef ComplexDP Type

Definition at line 12 of file test_ncu.cpp.

Function Documentation

◆ TEST_CASE() [1/3]

TEST_CASE ( "Test n-controlled unitary module with Pauli-X |11..  10,
,
""  [ncu] 
)

Test PauliX for NCU.

Definition at line 18 of file test_ncu.cpp.

18  {
19  std::size_t max_qubits = 8;
20  double mach_eps = 7./3. - 4./3. -1.;
21  std::vector<std::size_t> ctrl_lines;
22  //Generate simulator with n-qubits
23  for(std::size_t num_qubits = 4; num_qubits <= max_qubits; num_qubits++){
24  ctrl_lines.clear();
25  for(std::size_t i = 0; i <= num_qubits-2; i++){
26  ctrl_lines.push_back(i);
27  }
28  DYNAMIC_SECTION("Testing " << num_qubits << " qubits"){
29 
31 
32  // Loop over all possible control patterns
33  std::size_t max_pattern = (int) pow(2, num_qubits-1);
34  for(std::size_t pattern = 0; pattern < max_pattern; pattern++ ){
35  DYNAMIC_SECTION("Testing pattern " << pattern ){
36  sim.initRegister();
37 
38  // Loop over each individual qubit
39  for(std::size_t control_qubit_idx = 0; control_qubit_idx < num_qubits-1; control_qubit_idx++){
40  // Check if pattern has bit set
41  unsigned int window_select = (pattern >> control_qubit_idx) & 0b1;
42  if(window_select == 1){
43  sim.applyGateX(control_qubit_idx);
44  }
45  }
46 
47  auto &r = sim.getQubitRegister();
48  sim.applyGateNCU(sim.getGateX(), ctrl_lines, num_qubits-1, "X");
49 
50  if(pattern == max_pattern -1){
51  CHECK(sim.getQubitRegister().GetProbability(num_qubits-1) == Approx(1.).margin(1e-12));
52  }
53  else{
54  CHECK(sim.getQubitRegister().GetProbability(num_qubits-1) == Approx(0.).margin(1e-12));
55  }
56  }
57  }
58  }
59  }
60 }
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() [2/3]

TEST_CASE ( "Test n-controlled unitary module with Pauli-Z on |111..  1,
,
""  [ncu] 
)

Test Pauli-Z for NCU.

Definition at line 66 of file test_ncu.cpp.

66  {
67  std::size_t max_qubits = 8;
68  double mach_eps = 7./3. - 4./3. -1.;
69 
70  std::vector<std::size_t> ctrl_lines;
71  //Generate simulator with n-qubits
72  for(std::size_t num_qubits = 4; num_qubits <= max_qubits; num_qubits++){
73  ctrl_lines.clear();
74  for(std::size_t i = 0; i <= num_qubits-2; i++){
75  ctrl_lines.push_back(i);
76  }
77  DYNAMIC_SECTION("Testing " << num_qubits << " qubits"){
79  // Loop over all possible control patterns
80  std::size_t num_patterns = (int) pow(2, num_qubits);
81 
82  for(std::size_t pattern = 0; pattern < num_patterns; pattern++ ){
83  DYNAMIC_SECTION("Testing pattern " << pattern ){
84  sim.initRegister();
85  // Loop over each individual qubit
86  for(std::size_t control_qubit_idx = 0; control_qubit_idx < num_qubits; control_qubit_idx++){
87  // Check if pattern has bit set
88  unsigned int window_select = (pattern >> control_qubit_idx) & 0b1;
89  if(window_select == 1){
90  sim.applyGateX(control_qubit_idx);
91  }
92  }
93  auto &r = sim.getQubitRegister();
94  sim.applyGateNCU(sim.getGateZ(), ctrl_lines, num_qubits-1, "Z");
95 
96  // The pattern matching |11..1>|1> will flip the sign of the last qubit. Others will remain unaffected.
97  if(pattern == num_patterns-1){
98  CAPTURE(pattern, r[pattern]);
99  CHECK(r[pattern].real() == Approx(-1.).margin(1e-12) );
100  CHECK(r[pattern].imag() + 10*mach_eps == Approx(0.).margin(1e-12) ); //mach_eps to overcome floating point 0.
101  }
102  else{
103  CAPTURE(pattern, r[pattern]);
104  CHECK(r[pattern].real() == Approx(1.).margin(1e-12) );
105  CHECK(r[pattern].imag() + 10*mach_eps == Approx(0.).margin(1e-12) );
106  }
107  }
108  }
109  }
110  }
111 }
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() [3/3]

TEST_CASE ( "Test n-controlled unitary module with Pauli-X and non-adjacent controls"  ,
""  [ncu] 
)

Test Pauli-X and non-adjacent controls for NCU.

Definition at line 117 of file test_ncu.cpp.

117  {
118  const std::size_t max_qubits = 8;
119 
120  for(std::size_t num_qubits = 2; num_qubits <= max_qubits; num_qubits++ ){
122 
123  //Smallest use case
124  if(num_qubits == 3){
125  std::vector<std::size_t> vals0 {0,1}, vals1 {0,2}, vals2 {1,2};
126  SECTION("3 qubit test"){
127  for(std::size_t state = 0; state < (std::size_t) (0b1<<(num_qubits-1)); state++){
128  DYNAMIC_SECTION("CTRLs {0,1} STATE VALUE=" << state){
129  sim.initRegister();
130 
131  for(std::size_t ctrl_idx = 0; ctrl_idx < num_qubits; ctrl_idx++){
132  unsigned int window_select = (state >> ctrl_idx) & 0b1;
133  if(window_select == 1){
134  sim.applyGateX(vals0[ctrl_idx]);
135  }
136  }
137  CAPTURE(state);
138  CAPTURE(vals0);
139 
140  sim.applyGateNCU(sim.getGateX(), vals0, 2, "X");
141  vals0.push_back(2);
142  if(state == (std::size_t) (0b1<<(num_qubits-1)) - 1)
143  CHECK(sim.applyMeasurementToRegister(vals0, true) == 7);
144  else
145  CHECK(sim.applyMeasurementToRegister(vals0, true) != 7);
146  }
147  DYNAMIC_SECTION("CTRLs {0,2} STATE VALUE=" << state){
148  sim.initRegister();
149  for(std::size_t ctrl_idx = 0; ctrl_idx < num_qubits; ctrl_idx++){
150  unsigned int window_select = (state >> ctrl_idx) & 0b1;
151  if(window_select == 1){
152  sim.applyGateX(vals1[ctrl_idx]);
153  }
154  }
155  sim.applyGateNCU(sim.getGateX(), vals1, 1, "X");
156 
157  vals1.push_back(1);
158  CAPTURE(state, (0b1<<(num_qubits-1)) - 1, state == (std::size_t)(0b1<<(num_qubits-1)) - 1);
159 
160  if(state == (std::size_t) (0b1<<(num_qubits-1)) - 1)
161  CHECK(sim.applyMeasurementToRegister(vals1, true) == 7);
162  else
163  CHECK(sim.applyMeasurementToRegister(vals1, true) != 7);
164  }
165  DYNAMIC_SECTION("CTRLs {1,2} STATE VALUE=" << state){
166  sim.initRegister();
167  for(std::size_t ctrl_idx = 0; ctrl_idx < num_qubits; ctrl_idx++){
168  unsigned int window_select = (state >> ctrl_idx) & 0b1;
169  if(window_select == 1){
170  sim.applyGateX(vals2[ctrl_idx]);
171  }
172  }
173  sim.applyGateNCU(sim.getGateX(), vals2, 0, "X");
174  vals2.push_back(0);
175  if(state == (std::size_t) (0b1<<(num_qubits-1)) - 1)
176  CHECK(sim.applyMeasurementToRegister(vals2, true) == 7);
177  else
178  CHECK(sim.applyMeasurementToRegister(vals2, true) != 7);
179  }
180  }
181  }
182  }
183  //Even use case
184  else if(num_qubits == 4){
185  std::vector<std::size_t> vals0 {0,1,2}, vals1 {0,1,3}, vals2 {0,2};
186  SECTION("4 qubit test"){
187  for(std::size_t state = 0; state < (std::size_t) (0b1<<(num_qubits-1)); state++){
188  DYNAMIC_SECTION("CTRLs {0,1,2} STATE VALUE=" << state){
189  sim.initRegister();
190  for(std::size_t ctrl_idx = 0; ctrl_idx < num_qubits; ctrl_idx++){
191  unsigned int window_select = (state >> ctrl_idx) & 0b1;
192  if(window_select == 1){
193  sim.applyGateX(vals0[ctrl_idx]);
194  }
195  }
196  sim.applyGateNCU(sim.getGateX(), vals0, 3, "X");
197  vals0.push_back(3);
198  if(state == (std::size_t)(0b1<<(num_qubits-1)) - 1)
199  CHECK(sim.applyMeasurementToRegister(vals0, true) == 15);
200  else
201  CHECK(sim.applyMeasurementToRegister(vals0, true) != 15);
202  }
203  DYNAMIC_SECTION("CTRLs {0,1,3} STATE VALUE=" << state){
204  sim.initRegister();
205  for(std::size_t ctrl_idx = 0; ctrl_idx < num_qubits; ctrl_idx++){
206  unsigned int window_select = (state >> ctrl_idx) & 0b1;
207  if(window_select == 1){
208  sim.applyGateX(vals1[ctrl_idx]);
209  }
210  }
211  sim.applyGateNCU(sim.getGateX(), vals1, 2, "X");
212  vals1.push_back(2);
213 
214  if(state == (std::size_t) (0b1<<(num_qubits-1)) - 1)
215  CHECK(sim.applyMeasurementToRegister(vals1, true) == 15);
216  else
217  CHECK(sim.applyMeasurementToRegister(vals1, true) != 15);
218  }
219  }
220  }
221  }
222 
223  //Non-trivial odd use case
224  else if(num_qubits == 5){
225  std::vector<std::size_t> vals0 {0,1,2,3}, vals1 {0,1,3,4};
226  SECTION("5 qubit test"){
227  for(std::size_t state = 0; state < (std::size_t) (0b1<<(num_qubits-1)); state++){
228  DYNAMIC_SECTION("CTRLs {0,1,2,3} STATE VALUE=" << state){
229  sim.initRegister();
230  for(std::size_t ctrl_idx = 0; ctrl_idx < num_qubits; ctrl_idx++){
231  unsigned int window_select = (state >> ctrl_idx) & 0b1;
232  if(window_select == 1){
233  sim.applyGateX(vals0[ctrl_idx]);
234  }
235  }
236  sim.applyGateNCU(sim.getGateX(), vals0, 4, "X");
237  vals0.push_back(4);
238  if(state == (std::size_t)(0b1<<(num_qubits-1)) - 1)
239  CHECK(sim.applyMeasurementToRegister(vals0, true) == 31);
240  else
241  CHECK(sim.applyMeasurementToRegister(vals0, true) != 31);
242  }
243  DYNAMIC_SECTION("CTRLs {0,1,3,4} STATE VALUE=" << state){
244  sim.initRegister();
245  for(std::size_t ctrl_idx = 0; ctrl_idx < num_qubits; ctrl_idx++){
246  unsigned int window_select = (state >> ctrl_idx) & 0b1;
247  if(window_select == 1){
248  sim.applyGateX(vals1[ctrl_idx]);
249  }
250  }
251  sim.applyGateNCU(sim.getGateX(), vals1, 2, "X");
252  vals1.push_back(2);
253 
254  if(state == (std::size_t) (0b1<<(num_qubits-1)) - 1)
255  CHECK(sim.applyMeasurementToRegister(vals1, true) == 31);
256  else
257  CHECK(sim.applyMeasurementToRegister(vals1, true) != 31);
258  }
259  }
260  }
261  }
262  }
263 }
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.