Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
apply_kernel_test.cpp
Go to the documentation of this file.
1 #include <vector>
2 #include <iostream>
3 #include <cassert>
4 #include <cmath>
5 #include <algorithm>
6 #include <iomanip>
7 #include "matrix.h"
8 #include "Gates_block.h"
9 #include "common.h"
13 #include "apply_kernel_to_input.h"
15 #include "Gates_block.h"
16 
17 
19  std::mt19937 rng;
20 
21  Matrix generateRandomState(int num_qubits){
22  int size = 1 << num_qubits;
23  Matrix state(size, 1);
24  std::uniform_real_distribution<double> dist(-1.0, 1.0);
25 
26  double norm_sq = 0.0;
27  for (int i = 0; i < size; i++) {
28  state[i].real = dist(rng);
29  state[i].imag = dist(rng);
30  norm_sq += state[i].real*state[i].real + state[i].imag*state[i].imag;
31  }
32 
33  double inv_norm = 1.0 / std::sqrt(norm_sq);
34  for (int i = 0; i < size; i++){
35  state[i].real *= inv_norm;
36  state[i].imag *= inv_norm;
37  }
38  return state;
39  }
40 
41  double fidelity(const Matrix& s1, const Matrix& s2) {
42  double real_sum = 0.0, imag_sum = 0.0;
43  for (int i = 0; i < s1.rows; i++) {
44  real_sum += s1[i].real*s2[i].real + s1[i].imag*s2[i].imag;
45  imag_sum += s1[i].real*s2[i].imag - s1[i].imag*s2[i].real;
46  }
47  return std::sqrt(real_sum*real_sum + imag_sum*imag_sum);
48  }
49 
50 std::vector<std::vector<int>> generate_combinations(int n, int k) {
51  std::vector<std::vector<int>> combinations;
52  std::vector<bool> selector(n);
53  std::fill(selector.end() - k, selector.end(), true);
54 
55  do {
56  std::vector<int> combination;
57  for (int i = 0; i < n; ++i) {
58  if (selector[i]) {
59  combination.push_back(i);
60  }
61  }
62  // Ensure combination is sorted (should already be due to iteration order)
63  std::sort(combination.begin(), combination.end());
64  combinations.push_back(combination);
65  } while (std::next_permutation(selector.begin(), selector.end()));
66 
67  // Sort combinations lexicographically for consistent ordering
68  std::sort(combinations.begin(), combinations.end());
69  return combinations;
70 }
71 
72 public:
73 
75  const int num_qubits = 10;
76  const int k = 2;
77 
78  std::cout << "Testing all " << k << "-qubit gates on " << num_qubits << "-qubit system..." << std::endl;
79 
80  auto combinations = generate_combinations(num_qubits, k);
81  std::cout << "Total combinations to test: " << combinations.size() << std::endl;
82 
83  int passed_regular = 0;
84  int failed_regular = 0;
85  int passed_avx = 0;
86  int failed_avx = 0;
87 
88  for (size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
89  const auto& qubits = combinations[combo_idx];
90 
91  Matrix state = generateRandomState(num_qubits);
92  Matrix test_state = state.copy();
93  Matrix test_state_avx = state.copy();
94  Matrix_real params = Matrix_real(1, 1);
95 
96  Matrix Umtx = create_identity(1 << k);
97  memset(params.get_data(), 0.0, params.size() * sizeof(double));
98 
99  // Apply GHZ circuit to full system
100  Gates_block GHZ_circ = Gates_block(num_qubits);
101  GHZ_circ.add_h(qubits[0]);
102  GHZ_circ.add_cnot(qubits[1], qubits[0]);
103  GHZ_circ.apply_to(params, state);
104 
105  // Create corresponding unitary matrix
106  Gates_block GHZ_circ_mini = Gates_block(k);
107  GHZ_circ_mini.add_h(0);
108  GHZ_circ_mini.add_cnot(1, 0);
109  GHZ_circ_mini.apply_to(params, Umtx);
110 
111  // Test regular kernel
112  apply_2qbit_kernel_to_state_vector_input(Umtx, test_state, qubits[0], qubits[1], 1 << num_qubits);
113 
114  double fid = fidelity(state, test_state);
115 
116  if (std::abs(fid - 1.0) < 1e-10) {
117  passed_regular++;
118  } else {
119  failed_regular++;
120  std::cout << "REGULAR FAILED: Qubits {" << qubits[0] << "," << qubits[1]
121  << "} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
122  }
123 
124  #ifdef USE_AVX
125  // Test AVX kernel
126  apply_large_kernel_to_input_AVX(Umtx, test_state_avx, qubits, 1 << num_qubits);
127  double fid_avx = fidelity(state, test_state_avx);
128 
129  if (std::abs(fid_avx - 1.0) < 1e-10) {
130  passed_avx++;
131  } else {
132  failed_avx++;
133  std::cout << "AVX FAILED: Qubits {" << qubits[0] << "," << qubits[1]
134  << "} - Fidelity: " << std::fixed << std::setprecision(12) << fid_avx << std::endl;
135  }
136  #endif
137  }
138 
139  std::cout << "2-qubit gate test results:" << std::endl;
140  std::cout << " Regular kernel: " << passed_regular << " passed, " << failed_regular << " failed" << std::endl;
141  #ifdef USE_AVX
142  std::cout << " AVX kernel: " << passed_avx << " passed, " << failed_avx << " failed" << std::endl;
143  #endif
144 
145  assert(failed_regular == 0);
146  #ifdef USE_AVX
147  assert(failed_avx == 0);
148  #endif
149 }
150 
152  const int num_qubits = 10;
153  const int k = 3;
154 
155  std::cout << "Testing all " << k << "-qubit gates on " << num_qubits << "-qubit system..." << std::endl;
156 
157  auto combinations = generate_combinations(num_qubits, k);
158  std::cout << "Total combinations to test: " << combinations.size() << std::endl;
159 
160  int passed_regular = 0;
161  int failed_regular = 0;
162  int passed_avx = 0;
163  int failed_avx = 0;
164 
165  for (size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
166  const auto& qubits = combinations[combo_idx];
167 
168  Matrix state = generateRandomState(num_qubits);
169  Matrix test_state = state.copy();
170  Matrix test_state_avx = state.copy();
171  Matrix_real params = Matrix_real(1, 1);
172 
173  Matrix Umtx = create_identity(1 << k);
174  memset(params.get_data(), 0.0, params.size() * sizeof(double));
175 
176  // Apply GHZ circuit to full system
177  Gates_block GHZ_circ = Gates_block(num_qubits);
178  GHZ_circ.add_h(qubits[0]);
179  GHZ_circ.add_cnot(qubits[1], qubits[0]);
180  GHZ_circ.add_cnot(qubits[2], qubits[0]);
181  GHZ_circ.apply_to(params, state);
182 
183  // Create corresponding unitary matrix
184  Gates_block GHZ_circ_mini = Gates_block(k);
185  GHZ_circ_mini.add_h(0);
186  GHZ_circ_mini.add_cnot(1, 0);
187  GHZ_circ_mini.add_cnot(2, 0);
188  GHZ_circ_mini.apply_to(params, Umtx);
189 
190  // Test regular kernel
191  apply_3qbit_kernel_to_state_vector_input(Umtx, test_state, qubits, 1 << num_qubits);
192 
193  double fid = fidelity(state, test_state);
194 
195  if (std::abs(fid - 1.0) < 1e-10) {
196  passed_regular++;
197  } else {
198  failed_regular++;
199  std::cout << "REGULAR FAILED: Qubits {" << qubits[0] << "," << qubits[1] << "," << qubits[2]
200  << "} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
201  }
202 
203  #ifdef USE_AVX
204  // Test AVX kernel
205  apply_large_kernel_to_input_AVX(Umtx, test_state_avx, qubits, 1 << num_qubits);
206  double fid_avx = fidelity(state, test_state_avx);
207 
208  if (std::abs(fid_avx - 1.0) < 1e-10) {
209  passed_avx++;
210  } else {
211  failed_avx++;
212  std::cout << "AVX FAILED: Qubits {" << qubits[0] << "," << qubits[1] << "," << qubits[2]
213  << "} - Fidelity: " << std::fixed << std::setprecision(12) << fid_avx << std::endl;
214  }
215  #endif
216  }
217 
218  std::cout << "3-qubit gate test results:" << std::endl;
219  std::cout << " Regular kernel: " << passed_regular << " passed, " << failed_regular << " failed" << std::endl;
220  #ifdef USE_AVX
221  std::cout << " AVX kernel: " << passed_avx << " passed, " << failed_avx << " failed" << std::endl;
222  #endif
223 
224  assert(failed_regular == 0);
225  #ifdef USE_AVX
226  assert(failed_avx == 0);
227  #endif
228 }
229 
231  const int num_qubits = 10;
232  const int k = 4;
233 
234  std::cout << "Testing all " << k << "-qubit gates on " << num_qubits << "-qubit system..." << std::endl;
235 
236  auto combinations = generate_combinations(num_qubits, k);
237  std::cout << "Total combinations to test: " << combinations.size() << std::endl;
238 
239  int passed_regular = 0;
240  int failed_regular = 0;
241  int passed_avx = 0;
242  int failed_avx = 0;
243 
244  for (size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
245  const auto& qubits = combinations[combo_idx];
246 
247  Matrix state = generateRandomState(num_qubits);
248  Matrix test_state = state.copy();
249  Matrix test_state_avx = state.copy();
250  Matrix_real params = Matrix_real(1, 1);
251 
252  Matrix Umtx = create_identity(1 << k);
253  memset(params.get_data(), 0.0, params.size() * sizeof(double));
254 
255  // Apply GHZ circuit to full system
256  Gates_block GHZ_circ = Gates_block(num_qubits);
257  GHZ_circ.add_h(qubits[0]);
258  for (int i = 1; i < k; ++i) {
259  GHZ_circ.add_cnot(qubits[i], qubits[0]);
260  }
261  GHZ_circ.apply_to(params, state);
262 
263  // Create corresponding unitary matrix
264  Gates_block GHZ_circ_mini = Gates_block(k);
265  GHZ_circ_mini.add_h(0);
266  for (int i = 1; i < k; ++i) {
267  GHZ_circ_mini.add_cnot(i, 0);
268  }
269  GHZ_circ_mini.apply_to(params, Umtx);
270 
271  // Test regular kernel
272  apply_4qbit_kernel_to_state_vector_input(Umtx, test_state, qubits, 1 << num_qubits);
273 
274  double fid = fidelity(state, test_state);
275 
276  if (std::abs(fid - 1.0) < 1e-10) {
277  passed_regular++;
278  } else {
279  failed_regular++;
280  std::cout << "REGULAR FAILED: Qubits {";
281  for (size_t i = 0; i < qubits.size(); ++i) {
282  std::cout << qubits[i];
283  if (i < qubits.size() - 1) std::cout << ",";
284  }
285  std::cout << "} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
286  }
287  #ifdef USE_AVX
288  // Test AVX kernel
289  apply_large_kernel_to_input_AVX(Umtx, test_state_avx, qubits, 1 << num_qubits);
290  double fid_avx = fidelity(state, test_state_avx);
291 
292  if (std::abs(fid_avx - 1.0) < 1e-10) {
293  passed_avx++;
294  } else {
295  failed_avx++;
296  std::cout << "AVX FAILED: Qubits {";
297  for (size_t i = 0; i < qubits.size(); ++i) {
298  std::cout << qubits[i];
299  if (i < qubits.size() - 1) std::cout << ",";
300  }
301  std::cout << "} - Fidelity: " << std::fixed << std::setprecision(12) << fid_avx << std::endl;
302  }
303  #endif
304 
305  }
306 
307  std::cout << "4-qubit gate test results:" << std::endl;
308  std::cout << " Regular kernel: " << passed_regular << " passed, " << failed_regular << " failed" << std::endl;
309  #ifdef USE_AVX
310  std::cout << " AVX kernel: " << passed_avx << " passed, " << failed_avx << " failed" << std::endl;
311  #endif
312 
313  assert(failed_regular == 0);
314  #ifdef USE_AVX
315  assert(failed_avx == 0);
316  #endif
317 }
318 
320  const int num_qubits = 10;
321  const int k = 5;
322 
323  std::cout << "Testing all " << k << "-qubit gates on " << num_qubits << "-qubit system..." << std::endl;
324 
325  auto combinations = generate_combinations(num_qubits, k);
326  std::cout << "Total combinations to test: " << combinations.size() << std::endl;
327 
328  int passed_regular = 0;
329  int failed_regular = 0;
330  int passed_avx = 0;
331  int failed_avx = 0;
332 
333  for (size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
334  const auto& qubits = combinations[combo_idx];
335 
336  Matrix state = generateRandomState(num_qubits);
337  Matrix test_state = state.copy();
338  Matrix test_state_avx = state.copy();
339  Matrix_real params = Matrix_real(1, 1);
340 
341  Matrix Umtx = create_identity(1 << k);
342  memset(params.get_data(), 0.0, params.size() * sizeof(double));
343 
344  // Apply GHZ circuit to full system
345  Gates_block GHZ_circ = Gates_block(num_qubits);
346  GHZ_circ.add_h(qubits[0]);
347  for (int i = 1; i < k; ++i) {
348  GHZ_circ.add_cnot(qubits[i], qubits[0]);
349  }
350  GHZ_circ.apply_to(params, state);
351 
352  // Create corresponding unitary matrix
353  Gates_block GHZ_circ_mini = Gates_block(k);
354  GHZ_circ_mini.add_h(0);
355  for (int i = 1; i < k; ++i) {
356  GHZ_circ_mini.add_cnot(i, 0);
357  }
358  GHZ_circ_mini.apply_to(params, Umtx);
359 
360  // Test regular kernel
361  apply_5qbit_kernel_to_state_vector_input(Umtx, test_state, qubits, 1 << num_qubits);
362 
363  double fid = fidelity(state, test_state);
364 
365  if (std::abs(fid - 1.0) < 1e-10) {
366  passed_regular++;
367  } else {
368  failed_regular++;
369  std::cout << "REGULAR FAILED: Qubits {";
370  for (size_t i = 0; i < qubits.size(); ++i) {
371  std::cout << qubits[i];
372  if (i < qubits.size() - 1) std::cout << ",";
373  }
374  std::cout << "} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
375  }
376 
377  #ifdef USE_AVX
378  // Test AVX kernel
379  apply_large_kernel_to_input_AVX(Umtx, test_state_avx, qubits, 1 << num_qubits);
380  double fid_avx = fidelity(state, test_state_avx);
381 
382  if (std::abs(fid_avx - 1.0) < 1e-10) {
383  passed_avx++;
384  } else {
385  failed_avx++;
386  std::cout << "AVX FAILED: Qubits {";
387  for (size_t i = 0; i < qubits.size(); ++i) {
388  std::cout << qubits[i];
389  if (i < qubits.size() - 1) std::cout << ",";
390  }
391  std::cout << "} - Fidelity: " << std::fixed << std::setprecision(12) << fid_avx << std::endl;
392  }
393  #endif
394 
395 
396  }
397 
398  std::cout << "5-qubit gate test results:" << std::endl;
399  std::cout << " Regular kernel: " << passed_regular << " passed, " << failed_regular << " failed" << std::endl;
400  #ifdef USE_AVX
401  std::cout << " AVX kernel: " << passed_avx << " passed, " << failed_avx << " failed" << std::endl;
402  #endif
403 
404  assert(failed_regular == 0);
405  #ifdef USE_AVX
406  assert(failed_avx == 0);
407  #endif
408 }
409 
410 
412  int num_qubits = 10;
413  Matrix state = generateRandomState(num_qubits);
414  Matrix_real params = Matrix_real(1,1);
415  Matrix test_state = state.copy();
416  Matrix test_state2 = state.copy();
417  std::vector<int> qubits = {0,4,7};
418  Matrix Umtx = create_identity(1<<qubits.size());
419  memset(params.get_data(), 0.0, params.size()*sizeof(double) );
420 
421  Gates_block GHZ_circ = Gates_block(10);
422  GHZ_circ.add_h(qubits[0]);
423  GHZ_circ.add_cnot(qubits[1], qubits[0]);
424  GHZ_circ.add_cnot(qubits[2], qubits[0]);
425  GHZ_circ.apply_to(params,state);
426 
427  Gates_block GHZ_circ_mini = Gates_block(3);
428  GHZ_circ_mini.add_h(0);
429  GHZ_circ_mini.add_cnot(1,0);
430  GHZ_circ_mini.add_cnot(2,0);
431 
432  GHZ_circ_mini.apply_to(params,Umtx);
433  apply_large_kernel_to_input_AVX(Umtx, test_state, qubits, 1 << num_qubits);
434  double fid = fidelity(state, test_state);
435  std::cout << num_qubits <<"-qubit GHZ gate fidelity: " << fid << std::endl;
436  assert(std::abs(fid - 1.0) < 1e-10);
437 
438 }
439 
441  int num_qubits = 4;
442 
443  Matrix state = generateRandomState(num_qubits);
444  Matrix test_state = state.copy();
445 
446  Gates_block circuit(num_qubits);
447  Gates_block* circuit_inner = new Gates_block(num_qubits);
448  Gates_block* circuit_inner_2 = new Gates_block(num_qubits);
449 
450  circuit_inner->add_u3(2);
451  circuit_inner->add_u3(0);
452  circuit_inner->add_u3(1);
453 
454  circuit_inner->add_cry(0, 1);
455  circuit_inner->add_cry(1, 2);
456  circuit_inner_2->add_cry(2, 3);
457 
458  circuit_inner_2->add_u3(3);
459  circuit_inner_2->add_u3(0);
460 
461  // circuit.fragment_circuit();
462  circuit.add_gate(circuit_inner);
463  circuit.add_gate(circuit_inner_2);
464 
465  int num_params = circuit.get_parameter_num();
466  Matrix_real parameters(num_params, 1);
467  for (int i = 0; i < num_params; i++) {
468  parameters[i] = (i+1) / (M_PI*2);
469  }
470 
471  circuit.set_min_fusion(-1);
472  circuit_inner->set_min_fusion(-1);
473  circuit_inner_2->set_min_fusion(-1);
474 
475  circuit.apply_to(parameters, state);
476 
477  circuit.set_min_fusion(0);
478  circuit_inner->set_min_fusion(0);
479  circuit_inner_2->set_min_fusion(0);
480 
481  circuit.apply_to(parameters, test_state);
482 
483  double fid = fidelity(state, test_state);
484  std::cout << "Identity circuit fidelity (should be 1.0): " << fid << std::endl;
485  assert(std::abs(fid - 1.0) < 1e-10);
486 }
487 
488 
489 
491  int num_qubits = 20;
492  Matrix state = generateRandomState(num_qubits);
493  Matrix test_state = state.copy();
494  Matrix test_state2 = state.copy();
495  int offset = 4;
496  for (int n=2; n<6; n++){
497  std::vector<int> qubits;
498  for (int qubit=offset;qubit<offset+n;qubit++){
499  qubits.push_back(qubit);
500  }
501  Matrix Umtx = create_identity(1<<qubits.size());
502 
503  int samples = 500;
504  /*double dedicated_kernel_time = 0.0;
505  tbb::tick_count dedicated_kernel_start = tbb::tick_count::now();
506  for (int idx=0; idx<samples;idx++){
507  apply_large_kernel_to_input(Umtx, test_state, qubits, 1 << num_qubits);
508  }
509  tbb::tick_count dedicated_kernel_end = tbb::tick_count::now();
510  dedicated_kernel_time = (dedicated_kernel_end-dedicated_kernel_start).seconds()/samples;
511  std::cout << qubits.size()<<" qubit dedicated kernel time "<< dedicated_kernel_time << std::endl;*/
512 
513 
514  #ifdef USE_AVX
515  double dedicated_kernel_AVX_time = 0.0;
516  tbb::tick_count dedicated_kernel_AVX_start = tbb::tick_count::now();
517  for (int idx=0; idx<samples;idx++){
518  apply_large_kernel_to_input_AVX_TBB(Umtx, test_state, qubits, 1 << num_qubits);
519  }
520  tbb::tick_count dedicated_kernel_AVX_end = tbb::tick_count::now();
521 
522  dedicated_kernel_AVX_time = (dedicated_kernel_AVX_time + (dedicated_kernel_AVX_end-dedicated_kernel_AVX_start).seconds())/samples;
523 
524  std::cout << qubits.size()<<" qubit dedicated AVX kernel time "<< dedicated_kernel_AVX_time << std::endl;
525  #endif
526  }
527 }
528 
530 
531  //test single qubit X gate
532  int num_qubits = 10;
533  Matrix state = generateRandomState(num_qubits);
534  Matrix test_state = state.copy();
535  Matrix test_state2 = state.copy();
536  auto combinations = generate_combinations(num_qubits, 1);
537  for (size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
538  const auto& qubits = combinations[combo_idx];
539  std::vector<int> target_qbits = {qubits[0]};
540  std::vector<int> control_qbits = {};
541  apply_X_kernel_to_input(test_state, target_qbits, control_qbits, 1 << num_qubits);
542  Gates_block X_gate = Gates_block(num_qubits);
543  X_gate.add_x(qubits[0]);
544  Matrix_real params = Matrix_real(1, 1);
545  X_gate.apply_to(params, test_state2);
546  double fid = fidelity(test_state, test_state2);
547  if (std::abs(fid - 1.0) >= 1e-10) {
548  std::cout << "X gate FAILED: Qubit {" << qubits[0]
549  << "} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
550  }
551  assert(std::abs(fid - 1.0) < 1e-10);
552 
553  }
554  //test 2 qubit X gate
555  combinations = generate_combinations(num_qubits, 2);
556  for (size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
557  const auto& qubits = combinations[combo_idx];
558  std::vector<int> target_qbits = {qubits[0]};
559  std::vector<int> control_qbits = {qubits[1]};
560  apply_X_kernel_to_input(test_state, target_qbits, control_qbits, 1 << num_qubits);
561  Gates_block X_gate = Gates_block(num_qubits);
562  X_gate.add_cnot(qubits[0],qubits[1]);
563  Matrix_real params = Matrix_real(1, 1);
564  X_gate.apply_to(params, test_state2);
565  double fid = fidelity(test_state, test_state2);
566  if (std::abs(fid - 1.0) >= 1e-10) {
567  std::cout << "2 qubit X gate FAILED: Qubits {" << qubits[0] << "," << qubits[1]
568  << "} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
569  }
570  }
571  for (size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
572  const auto& qubits = combinations[combo_idx];
573  std::vector<int> target_qbits = {qubits[1]};
574  std::vector<int> control_qbits = {qubits[0]};
575  apply_X_kernel_to_input(test_state, target_qbits, control_qbits, 1 << num_qubits);
576  Gates_block X_gate = Gates_block(num_qubits);
577  X_gate.add_cnot(qubits[1],qubits[0]);
578  Matrix_real params = Matrix_real(1, 1);
579  X_gate.apply_to(params, test_state2);
580  double fid = fidelity(test_state, test_state2);
581  if (std::abs(fid - 1.0) >= 1e-10) {
582  std::cout << "2 qubit X gate FAILED: Qubits {" << qubits[0] << "," << qubits[1]
583  << "} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
584  }
585  }
586  int failed = 0;
587  // test troffoli X gate
588  combinations = generate_combinations(num_qubits, 3);
589  for (size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
590  const auto& qubits = combinations[combo_idx];
591  std::vector<int> target_qbits = {qubits[0]};
592  std::vector<int> control_qbits = {qubits[1], qubits[2]};
593  apply_X_kernel_to_input(test_state, target_qbits, control_qbits, 1 << num_qubits);
595  Umtx[6*8 + 6].real = 0.0;
596  Umtx[7*8 + 7].real = 0.0;
597  Umtx[6*8 + 7].real = 1.0;
598  Umtx[7*8 + 6].real = 1.0;
599  apply_3qbit_kernel_to_state_vector_input(Umtx, test_state2, qubits, 1 << num_qubits);
600  double fid = fidelity(test_state, test_state2);
601  if (std::abs(fid - 1.0) >= 1e-10) {
602  failed++;
603  std::cout << "Toffoli X gate FAILED: Qubits {" << qubits[0] << "," << qubits[1] << "," << qubits[2]
604  << "} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
605  }
606  }
607  std::cout << "Toffoli X gate failed cases: " << failed/combinations.size() << std::endl;
608 }
609 
610 
611 };
612 int main() {
613  ApplyKernelTestSuite suite;
614  suite.test2QubitGate();
615  suite.test3QubitGate();
616  suite.test4QubitGate();
617  suite.test5QubitGate();
618  #ifdef USE_AVX
619  //suite.testNQubitGate_Parallel_GHZ();
620  //suite.testNQubit_Gate_speed();
621  #endif
622  suite.testSmallCircuit();
623  suite.testXgateKernel();
624  return 0;
625 }
void apply_X_kernel_to_input(Matrix &input, const std::vector< int > &target_qbits, const std::vector< int > &control_qbits, const int &matrix_size)
Applies the X gate kernel to the input matrix.
void apply_4qbit_kernel_to_state_vector_input(Matrix &unitary, Matrix &input, std::vector< int > involved_qbits, const int &matrix_size)
void apply_large_kernel_to_input_AVX_TBB(Matrix &unitary, Matrix &input, std::vector< int > involved_qbits, const int &matrix_size)
Apply multi-qubit gate kernel to an input matrix using AVX optimization and TBB parallelization.
void add_h(int target_qbit)
Append a Hadamard gate to the list of gates.
void add_x(int target_qbit)
Append a X gate to the list of gates.
void add_gate(Gate *gate)
Append a general gate to the list of gates.
Header file for a class responsible for grouping gates into subcircuits. (Subcircuits can be nested) ...
void add_cnot(int target_qbit, int control_qbit)
Append a CNOT gate gate to the list of gates.
std::vector< std::vector< int > > generate_combinations(int n, int k)
scalar * get_data() const
Call to get the pointer to the stored data.
void apply_2qbit_kernel_to_state_vector_input(Matrix &two_qbit_unitary, Matrix &input, const int &inner_qbit, const int &outer_qbit, const int &matrix_size)
void apply_large_kernel_to_input_AVX(Matrix &unitary, Matrix &input, std::vector< int > involved_qbits, const int &matrix_size)
Apply multi-qubit gate kernel to an input matrix using AVX optimization.
int rows
The number of rows.
Definition: matrix_base.hpp:42
#define M_PI
Definition: qgd_math.h:42
void add_u3(int target_qbit)
Append a U3 gate to the list of gates.
Umtx
The unitary to be decomposed.
Definition: example.py:53
Header file of complex array storage array with automatic and thread safe reference counting...
void apply_3qbit_kernel_to_state_vector_input(Matrix &unitary, Matrix &input, std::vector< int > involved_qbits, const int &matrix_size)
virtual void apply_to(Matrix_real &parameters_mtx, Matrix &input, int parallel=0) override
Call to apply the gate on the input array/matrix Gates_block*input.
void set_min_fusion(int min_fusion)
void apply_5qbit_kernel_to_state_vector_input(Matrix &unitary, Matrix &input, std::vector< int > involved_qbits, const int &matrix_size)
Matrix copy() const
Call to create a copy of the matrix.
Definition: matrix.h:57
Double-precision complex matrix (float64).
Definition: matrix.h:38
int size() const
Call to get the number of the allocated elements.
void add_cry(int target_qbit, int control_qbit)
Append a CRY gate to the list of gates.
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
Definition: Gates_block.h:44
Header file for AVX-optimized implementations for applying multi-qubit gate kernels to quantum state ...
double fidelity(const Matrix &s1, const Matrix &s2)
Matrix generateRandomState(int num_qubits)
Matrix create_identity(int matrix_size)
Call to create an identity matrix.
Definition: common.cpp:182
Header file for commonly used functions and wrappers to CBLAS functions.
int main()
int get_parameter_num() override
Call to get the number of free parameters.
Class to store data of complex arrays and its properties.
Definition: matrix_real.h:41