Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
apply_kernel_to_state_vector_input.cpp
Go to the documentation of this file.
1 /*
2 Created on Fri Jun 26 14:13:26 2020
3 Copyright 2020 Peter Rakyta, Ph.D.
4 
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8 
9  http://www.apache.org/licenses/LICENSE-2.0
10 
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 
17 @author: Peter Rakyta, Ph.D.
18 */
25 //#include <immintrin.h>
26 #include "tbb/tbb.h"
27 #include <type_traits>
28 #include <utility>
29 
30 template<typename MatrixT>
31 using StateVecComplexT = typename std::remove_reference<decltype(std::declval<MatrixT&>()[0])>::type;
32 
33 template<typename MatrixT>
34 void
35 apply_kernel_to_state_vector_input_impl(MatrixT& u3_1qbit, MatrixT& input, const bool& deriv, const int& target_qbit, const int& control_qbit, const int& matrix_size) {
36 
46  using ComplexT = StateVecComplexT<MatrixT>;
47 
48 
49  int index_step_target = 1 << target_qbit;
50  int current_idx = 0;
51 
52 
53  for ( int current_idx_pair=current_idx + index_step_target; current_idx_pair<matrix_size; current_idx_pair=current_idx_pair+(index_step_target << 1) ) {
54 
55  for (int idx = 0; idx < index_step_target; idx++) {
56  //tbb::parallel_for(0, index_step_target, 1, [&](int idx) {
57 
58  int current_idx_loc = current_idx + idx;
59  int current_idx_pair_loc = current_idx_pair + idx;
60 
61  int row_offset = current_idx_loc * input.stride;
62  int row_offset_pair = current_idx_pair_loc * input.stride;
63 
64  if (control_qbit < 0 || ((current_idx_loc >> control_qbit) & 1)) {
65 
66  ComplexT element = input[row_offset];
67  ComplexT element_pair = input[row_offset_pair];
68 
69  ComplexT tmp1 = mult(u3_1qbit[0], element);
70  ComplexT tmp2 = mult(u3_1qbit[1], element_pair);
71 
72  input[row_offset].real = tmp1.real + tmp2.real;
73  input[row_offset].imag = tmp1.imag + tmp2.imag;
74 
75  tmp1 = mult(u3_1qbit[2], element);
76  tmp2 = mult(u3_1qbit[3], element_pair);
77 
78  input[row_offset_pair].real = tmp1.real + tmp2.real;
79  input[row_offset_pair].imag = tmp1.imag + tmp2.imag;
80 
81 
82 
83  }
84  else if (deriv) {
85  // when calculating derivatives, the constant element should be zeros
86  memset(input.get_data() + row_offset, 0, input.cols * sizeof(ComplexT));
87  memset(input.get_data() + row_offset_pair, 0, input.cols * sizeof(ComplexT));
88  }
89  else {
90  // leave the state as it is
91  continue;
92  }
93 
94 
95  //std::cout << current_idx_target << " " << current_idx_target_pair << std::endl;
96 
97 
98  //});
99  }
100 
101 
102  current_idx = current_idx + (index_step_target << 1);
103 
104 
105  }
106 }
107 
108 
109 void
110 apply_kernel_to_state_vector_input(Matrix& u3_1qbit, Matrix& input, const bool& deriv, const int& target_qbit, const int& control_qbit, const int& matrix_size) {
111  apply_kernel_to_state_vector_input_impl(u3_1qbit, input, deriv, target_qbit, control_qbit, matrix_size);
112 }
113 
114 
115 void
116 apply_kernel_to_state_vector_input(Matrix_float& u3_1qbit, Matrix_float& input, const bool& deriv, const int& target_qbit, const int& control_qbit, const int& matrix_size) {
117  apply_kernel_to_state_vector_input_impl(u3_1qbit, input, deriv, target_qbit, control_qbit, matrix_size);
118 }
119 
120 
121 
122 
123 
133 template<typename MatrixT>
134 void
135 apply_kernel_to_state_vector_input_parallel_impl(MatrixT& u3_1qbit, MatrixT& input, const bool& deriv, const int& target_qbit, const int& control_qbit, const int& matrix_size) {
136 
137  using ComplexT = StateVecComplexT<MatrixT>;
138 
139 
140  int index_step_target = 1 << target_qbit;
141 
142  int parallel_outer_cycles = matrix_size/(index_step_target << 1);
143  int outer_grain_size;
144  if ( index_step_target <= 2 ) {
145  outer_grain_size = 64;
146  }
147  else if ( index_step_target <= 4 ) {
148  outer_grain_size = 32;
149  }
150  else if ( index_step_target <= 8 ) {
151  outer_grain_size = 16;
152  }
153  else if ( index_step_target <= 16 ) {
154  outer_grain_size = 8;
155  }
156  else {
157  outer_grain_size = 2;
158  }
159 
160  int inner_grain_size = 64;
161 
162  tbb::parallel_for( tbb::blocked_range<int>(0, parallel_outer_cycles, outer_grain_size), [&](tbb::blocked_range<int> r) {
163 
164  int current_idx = r.begin()*(index_step_target << 1);
165  int current_idx_pair = index_step_target + r.begin()*(index_step_target << 1);
166 
167  for (int rdx=r.begin(); rdx<r.end(); rdx++) {
168 
169 
170  tbb::parallel_for( tbb::blocked_range<int>(0,index_step_target,inner_grain_size), [&](tbb::blocked_range<int> r) {
171  for (int idx=r.begin(); idx<r.end(); ++idx) {
172 
173 
174 
175  int current_idx_loc = current_idx + idx;
176  int current_idx_pair_loc = current_idx_pair + idx;
177 
178  int row_offset = current_idx_loc * input.stride;
179  int row_offset_pair = current_idx_pair_loc * input.stride;
180 
181  if (control_qbit < 0 || ((current_idx_loc >> control_qbit) & 1)) {
182 
183  ComplexT element = input[row_offset];
184  ComplexT element_pair = input[row_offset_pair];
185 
186  ComplexT tmp1 = mult(u3_1qbit[0], element);
187  ComplexT tmp2 = mult(u3_1qbit[1], element_pair);
188 
189  input[row_offset].real = tmp1.real + tmp2.real;
190  input[row_offset].imag = tmp1.imag + tmp2.imag;
191 
192  tmp1 = mult(u3_1qbit[2], element);
193  tmp2 = mult(u3_1qbit[3], element_pair);
194 
195  input[row_offset_pair].real = tmp1.real + tmp2.real;
196  input[row_offset_pair].imag = tmp1.imag + tmp2.imag;
197 
198 
199 
200  }
201  else if (deriv) {
202  // when calculating derivatives, the constant element should be zeros
203  memset(input.get_data() + row_offset, 0, input.cols * sizeof(ComplexT));
204  memset(input.get_data() + row_offset_pair, 0, input.cols * sizeof(ComplexT));
205  }
206  else {
207  // leave the state as it is
208  continue;
209  }
210 
211 
212  //std::cout << current_idx_target << " " << current_idx_target_pair << std::endl;
213 
214 
215  }
216  });
217 
218 
219 
220  current_idx = current_idx + (index_step_target << 1);
221  current_idx_pair = current_idx_pair + (index_step_target << 1);
222 
223  }
224  });
225 
226 
227 
228 
229 }
230 
231 
232 void
233 apply_kernel_to_state_vector_input_parallel(Matrix& u3_1qbit, Matrix& input, const bool& deriv, const int& target_qbit, const int& control_qbit, const int& matrix_size) {
234  apply_kernel_to_state_vector_input_parallel_impl(u3_1qbit, input, deriv, target_qbit, control_qbit, matrix_size);
235 }
236 
237 
238 void
239 apply_kernel_to_state_vector_input_parallel(Matrix_float& u3_1qbit, Matrix_float& input, const bool& deriv, const int& target_qbit, const int& control_qbit, const int& matrix_size) {
240  apply_kernel_to_state_vector_input_parallel_impl(u3_1qbit, input, deriv, target_qbit, control_qbit, matrix_size);
241 }
242 
243 
244 template<typename MatrixT>
245 void apply_large_state_vector_2q_impl(MatrixT& two_qbit_unitary, MatrixT& input, const int& inner_qbit, const int& outer_qbit, const int& matrix_size) {
246 
247  int index_step_outer = 1 << outer_qbit;
248  int index_step_inner = 1 << inner_qbit;
249  int current_idx = 0;
250 
251  for (int current_idx_pair_outer = current_idx + index_step_outer; current_idx_pair_outer < input.rows; current_idx_pair_outer = current_idx_pair_outer + (index_step_outer << 1)) {
252 
253  for (int current_idx_inner = 0; current_idx_inner < index_step_outer; current_idx_inner = current_idx_inner + (index_step_inner << 1)) {
254 
255  for (int idx = 0; idx < index_step_inner; idx++) {
256 
257  int current_idx_outer_loc = current_idx + current_idx_inner + idx;
258  int current_idx_inner_loc = current_idx + current_idx_inner + idx + index_step_inner;
259  int current_idx_outer_pair_loc = current_idx_pair_outer + idx + current_idx_inner;
260  int current_idx_inner_pair_loc = current_idx_pair_outer + idx + current_idx_inner + index_step_inner;
261  int indexes[4] = {current_idx_outer_loc, current_idx_inner_loc, current_idx_outer_pair_loc, current_idx_inner_pair_loc};
262 
263  StateVecComplexT<MatrixT> element_outer = input[current_idx_outer_loc];
264  StateVecComplexT<MatrixT> element_outer_pair = input[current_idx_outer_pair_loc];
265  StateVecComplexT<MatrixT> element_inner = input[current_idx_inner_loc];
266  StateVecComplexT<MatrixT> element_inner_pair = input[current_idx_inner_pair_loc];
267 
272  for (int mult_idx = 0; mult_idx < 4; mult_idx++) {
273 
274  tmp1 = mult(two_qbit_unitary[mult_idx * 4], element_outer);
275  tmp2 = mult(two_qbit_unitary[mult_idx * 4 + 1], element_inner);
276  tmp3 = mult(two_qbit_unitary[mult_idx * 4 + 2], element_outer_pair);
277  tmp4 = mult(two_qbit_unitary[mult_idx * 4 + 3], element_inner_pair);
278  input[indexes[mult_idx]].real = tmp1.real + tmp2.real + tmp3.real + tmp4.real;
279  input[indexes[mult_idx]].imag = tmp1.imag + tmp2.imag + tmp3.imag + tmp4.imag;
280  }
281  }
282  }
283  current_idx = current_idx + (index_step_outer << 1);
284  }
285 
286  (void)matrix_size;
287 }
288 
289 template<typename MatrixT>
290 void apply_large_state_vector_3q_impl(MatrixT& unitary, MatrixT& input, std::vector<int> involved_qbits, const int& matrix_size) {
291 
292  int index_step_inner = 1 << involved_qbits[0];
293  int index_step_middle = 1 << involved_qbits[1];
294  int index_step_outer = 1 << involved_qbits[2];
295  int current_idx = 0;
296 
297  for (int current_idx_pair_outer = current_idx + index_step_outer; current_idx_pair_outer < input.rows; current_idx_pair_outer = current_idx_pair_outer + (index_step_outer << 1)) {
298 
299  for (int current_idx_middle = 0; current_idx_middle < index_step_outer; current_idx_middle = current_idx_middle + (index_step_middle << 1)) {
300 
301  for (int current_idx_inner = 0; current_idx_inner < index_step_middle; current_idx_inner = current_idx_inner + (index_step_inner << 1)) {
302 
303  for (int idx = 0; idx < index_step_inner; idx++) {
304 
305  int current_idx_loc = current_idx + current_idx_middle + current_idx_inner + idx;
306  int current_idx_pair_loc = current_idx_pair_outer + idx + current_idx_inner + current_idx_middle;
307 
308  int current_idx_outer_loc = current_idx_loc;
309  int current_idx_inner_loc = current_idx_loc + index_step_inner;
310 
311  int current_idx_middle_loc = current_idx_loc + index_step_middle;
312  int current_idx_middle_inner_loc = current_idx_loc + index_step_middle + index_step_inner;
313 
314  int current_idx_outer_pair_loc = current_idx_pair_loc;
315  int current_idx_inner_pair_loc = current_idx_pair_loc + index_step_inner;
316 
317  int current_idx_middle_pair_loc = current_idx_pair_loc + index_step_middle;
318  int current_idx_middle_inner_pair_loc = current_idx_pair_loc + index_step_middle + index_step_inner;
319 
320  int indexes[8] = {current_idx_outer_loc, current_idx_inner_loc, current_idx_middle_loc, current_idx_middle_inner_loc, current_idx_outer_pair_loc, current_idx_inner_pair_loc, current_idx_middle_pair_loc, current_idx_middle_inner_pair_loc};
321  StateVecComplexT<MatrixT> element_outer = input[current_idx_outer_loc];
322  StateVecComplexT<MatrixT> element_outer_pair = input[current_idx_outer_pair_loc];
323 
324  StateVecComplexT<MatrixT> element_inner = input[current_idx_inner_loc];
325  StateVecComplexT<MatrixT> element_inner_pair = input[current_idx_inner_pair_loc];
326 
327  StateVecComplexT<MatrixT> element_middle = input[current_idx_middle_loc];
328  StateVecComplexT<MatrixT> element_middle_pair = input[current_idx_middle_pair_loc];
329 
330  StateVecComplexT<MatrixT> element_middle_inner = input[current_idx_middle_inner_loc];
331  StateVecComplexT<MatrixT> element_middle_inner_pair = input[current_idx_middle_inner_pair_loc];
332 
341  for (int mult_idx = 0; mult_idx < 8; mult_idx++) {
342  tmp1 = mult(unitary[mult_idx * 8], element_outer);
343  tmp2 = mult(unitary[mult_idx * 8 + 1], element_inner);
344  tmp3 = mult(unitary[mult_idx * 8 + 2], element_middle);
345  tmp4 = mult(unitary[mult_idx * 8 + 3], element_middle_inner);
346  tmp5 = mult(unitary[mult_idx * 8 + 4], element_outer_pair);
347  tmp6 = mult(unitary[mult_idx * 8 + 5], element_inner_pair);
348  tmp7 = mult(unitary[mult_idx * 8 + 6], element_middle_pair);
349  tmp8 = mult(unitary[mult_idx * 8 + 7], element_middle_inner_pair);
350  input[indexes[mult_idx]].real = tmp1.real + tmp2.real + tmp3.real + tmp4.real + tmp5.real + tmp6.real + tmp7.real + tmp8.real;
351  input[indexes[mult_idx]].imag = tmp1.imag + tmp2.imag + tmp3.imag + tmp4.imag + tmp5.imag + tmp6.imag + tmp7.imag + tmp8.imag;
352  }
353  }
354  }
355  }
356  current_idx = current_idx + (index_step_outer << 1);
357  }
358 
359  (void)matrix_size;
360 }
361 
362 template<typename MatrixT>
363 void apply_large_state_vector_4q_impl(MatrixT& unitary, MatrixT& input, std::vector<int> involved_qbits, const int& matrix_size) {
364 
365  int index_step_q0 = 1 << involved_qbits[0];
366  int index_step_q1 = 1 << involved_qbits[1];
367  int index_step_q2 = 1 << involved_qbits[2];
368  int index_step_q3 = 1 << involved_qbits[3];
369 
370  int current_idx = 0;
371 
372  for (int current_idx_pair_q3 = current_idx + index_step_q3; current_idx_pair_q3 < input.rows; current_idx_pair_q3 += (index_step_q3 << 1)) {
373  for (int current_idx_q2 = 0; current_idx_q2 < index_step_q3; current_idx_q2 += (index_step_q2 << 1)) {
374  for (int current_idx_q1 = 0; current_idx_q1 < index_step_q2; current_idx_q1 += (index_step_q1 << 1)) {
375  for (int current_idx_q0 = 0; current_idx_q0 < index_step_q1; current_idx_q0 += (index_step_q0 << 1)) {
376  for (int idx = 0; idx < index_step_q0; idx++) {
377 
378  int current_idx_loc = current_idx + current_idx_q2 + current_idx_q1 + current_idx_q0 + idx;
379  int current_idx_pair_loc = current_idx_pair_q3 + idx + current_idx_q1 + current_idx_q2 + current_idx_q0;
380 
381  int current_idx_q0_0_loc = current_idx_loc;
382  int current_idx_q0_1_loc = current_idx_loc + index_step_q0;
383  int current_idx_q1_0_loc = current_idx_loc + index_step_q1;
384  int current_idx_q1_1_loc = current_idx_loc + index_step_q1 + index_step_q0;
385  int current_idx_q2_0_loc = current_idx_loc + index_step_q2;
386  int current_idx_q2_1_loc = current_idx_loc + index_step_q2 + index_step_q0;
387  int current_idx_q2_q1_0_loc = current_idx_loc + index_step_q2 + index_step_q1;
388  int current_idx_q2_q1_1_loc = current_idx_loc + index_step_q2 + index_step_q1 + index_step_q0;
389 
390  int current_idx_q3_q0_0_pair_loc = current_idx_pair_loc;
391  int current_idx_q3_q0_1_pair_loc = current_idx_pair_loc + index_step_q0;
392  int current_idx_q3_q1_0_pair_loc = current_idx_pair_loc + index_step_q1;
393  int current_idx_q3_q1_1_pair_loc = current_idx_pair_loc + index_step_q1 + index_step_q0;
394  int current_idx_q3_q2_0_pair_loc = current_idx_pair_loc + index_step_q2;
395  int current_idx_q3_q2_1_pair_loc = current_idx_pair_loc + index_step_q2 + index_step_q0;
396  int current_idx_q3_q2_q1_0_pair_loc = current_idx_pair_loc + index_step_q2 + index_step_q1;
397  int current_idx_q3_q2_q1_1_pair_loc = current_idx_pair_loc + index_step_q2 + index_step_q1 + index_step_q0;
398 
399  int indexes[16] = {
400  current_idx_q0_0_loc, current_idx_q0_1_loc, current_idx_q1_0_loc, current_idx_q1_1_loc,
401  current_idx_q2_0_loc, current_idx_q2_1_loc, current_idx_q2_q1_0_loc, current_idx_q2_q1_1_loc,
402  current_idx_q3_q0_0_pair_loc, current_idx_q3_q0_1_pair_loc, current_idx_q3_q1_0_pair_loc, current_idx_q3_q1_1_pair_loc,
403  current_idx_q3_q2_0_pair_loc, current_idx_q3_q2_1_pair_loc, current_idx_q3_q2_q1_0_pair_loc, current_idx_q3_q2_q1_1_pair_loc
404  };
405 
406  StateVecComplexT<MatrixT> element_0 = input[current_idx_q0_0_loc];
407  StateVecComplexT<MatrixT> element_1 = input[current_idx_q0_1_loc];
408  StateVecComplexT<MatrixT> element_2 = input[current_idx_q1_0_loc];
409  StateVecComplexT<MatrixT> element_3 = input[current_idx_q1_1_loc];
410  StateVecComplexT<MatrixT> element_4 = input[current_idx_q2_0_loc];
411  StateVecComplexT<MatrixT> element_5 = input[current_idx_q2_1_loc];
412  StateVecComplexT<MatrixT> element_6 = input[current_idx_q2_q1_0_loc];
413  StateVecComplexT<MatrixT> element_7 = input[current_idx_q2_q1_1_loc];
414  StateVecComplexT<MatrixT> element_8 = input[current_idx_q3_q0_0_pair_loc];
415  StateVecComplexT<MatrixT> element_9 = input[current_idx_q3_q0_1_pair_loc];
416  StateVecComplexT<MatrixT> element_10 = input[current_idx_q3_q1_0_pair_loc];
417  StateVecComplexT<MatrixT> element_11 = input[current_idx_q3_q1_1_pair_loc];
418  StateVecComplexT<MatrixT> element_12 = input[current_idx_q3_q2_0_pair_loc];
419  StateVecComplexT<MatrixT> element_13 = input[current_idx_q3_q2_1_pair_loc];
420  StateVecComplexT<MatrixT> element_14 = input[current_idx_q3_q2_q1_0_pair_loc];
421  StateVecComplexT<MatrixT> element_15 = input[current_idx_q3_q2_q1_1_pair_loc];
422 
423  for (int mult_idx = 0; mult_idx < 16; mult_idx++) {
424  StateVecComplexT<MatrixT> tmp0 = mult(unitary[mult_idx * 16], element_0);
425  StateVecComplexT<MatrixT> tmp1 = mult(unitary[mult_idx * 16 + 1], element_1);
426  StateVecComplexT<MatrixT> tmp2 = mult(unitary[mult_idx * 16 + 2], element_2);
427  StateVecComplexT<MatrixT> tmp3 = mult(unitary[mult_idx * 16 + 3], element_3);
428  StateVecComplexT<MatrixT> tmp4 = mult(unitary[mult_idx * 16 + 4], element_4);
429  StateVecComplexT<MatrixT> tmp5 = mult(unitary[mult_idx * 16 + 5], element_5);
430  StateVecComplexT<MatrixT> tmp6 = mult(unitary[mult_idx * 16 + 6], element_6);
431  StateVecComplexT<MatrixT> tmp7 = mult(unitary[mult_idx * 16 + 7], element_7);
432  StateVecComplexT<MatrixT> tmp8 = mult(unitary[mult_idx * 16 + 8], element_8);
433  StateVecComplexT<MatrixT> tmp9 = mult(unitary[mult_idx * 16 + 9], element_9);
434  StateVecComplexT<MatrixT> tmp10 = mult(unitary[mult_idx * 16 + 10], element_10);
435  StateVecComplexT<MatrixT> tmp11 = mult(unitary[mult_idx * 16 + 11], element_11);
436  StateVecComplexT<MatrixT> tmp12 = mult(unitary[mult_idx * 16 + 12], element_12);
437  StateVecComplexT<MatrixT> tmp13 = mult(unitary[mult_idx * 16 + 13], element_13);
438  StateVecComplexT<MatrixT> tmp14 = mult(unitary[mult_idx * 16 + 14], element_14);
439  StateVecComplexT<MatrixT> tmp15 = mult(unitary[mult_idx * 16 + 15], element_15);
440 
441  input[indexes[mult_idx]].real = tmp0.real + tmp1.real + tmp2.real + tmp3.real
442  + tmp4.real + tmp5.real + tmp6.real + tmp7.real
443  + tmp8.real + tmp9.real + tmp10.real + tmp11.real
444  + tmp12.real + tmp13.real + tmp14.real + tmp15.real;
445 
446  input[indexes[mult_idx]].imag = tmp0.imag + tmp1.imag + tmp2.imag + tmp3.imag
447  + tmp4.imag + tmp5.imag + tmp6.imag + tmp7.imag
448  + tmp8.imag + tmp9.imag + tmp10.imag + tmp11.imag
449  + tmp12.imag + tmp13.imag + tmp14.imag + tmp15.imag;
450  }
451  }
452  }
453  }
454  }
455  current_idx += (index_step_q3 << 1);
456  }
457 
458  (void)matrix_size;
459 }
460 
461 template<typename MatrixT>
462 void apply_large_state_vector_5q_impl(MatrixT& unitary, MatrixT& input, std::vector<int> involved_qbits, const int& matrix_size) {
463 
464  int index_step_q0 = 1 << involved_qbits[0];
465  int index_step_q1 = 1 << involved_qbits[1];
466  int index_step_q2 = 1 << involved_qbits[2];
467  int index_step_q3 = 1 << involved_qbits[3];
468  int index_step_q4 = 1 << involved_qbits[4];
469 
470  int current_idx = 0;
471 
472  for (int current_idx_pair_q4 = current_idx + index_step_q4; current_idx_pair_q4 < input.rows; current_idx_pair_q4 += (index_step_q4 << 1)) {
473  for (int current_idx_q3 = 0; current_idx_q3 < index_step_q4; current_idx_q3 += (index_step_q3 << 1)) {
474  for (int current_idx_q2 = 0; current_idx_q2 < index_step_q3; current_idx_q2 += (index_step_q2 << 1)) {
475  for (int current_idx_q1 = 0; current_idx_q1 < index_step_q2; current_idx_q1 += (index_step_q1 << 1)) {
476  for (int current_idx_q0 = 0; current_idx_q0 < index_step_q1; current_idx_q0 += (index_step_q0 << 1)) {
477  for (int idx = 0; idx < index_step_q0; idx++) {
478 
479  int current_idx_loc = current_idx + current_idx_q3 + current_idx_q2 + current_idx_q1 + current_idx_q0 + idx;
480  int current_idx_pair_q4_loc = current_idx_pair_q4 + idx + current_idx_q1 + current_idx_q2 + current_idx_q3 + current_idx_q0;
481 
482  int current_idx_q0_0_loc = current_idx_loc;
483  int current_idx_q0_1_loc = current_idx_loc + index_step_q0;
484  int current_idx_q1_0_loc = current_idx_loc + index_step_q1;
485  int current_idx_q1_1_loc = current_idx_loc + index_step_q1 + index_step_q0;
486  int current_idx_q2_0_loc = current_idx_loc + index_step_q2;
487  int current_idx_q2_1_loc = current_idx_loc + index_step_q2 + index_step_q0;
488  int current_idx_q2_q1_0_loc = current_idx_loc + index_step_q2 + index_step_q1;
489  int current_idx_q2_q1_1_loc = current_idx_loc + index_step_q2 + index_step_q1 + index_step_q0;
490  int current_idx_q3_0_loc = current_idx_loc + index_step_q3;
491  int current_idx_q3_1_loc = current_idx_loc + index_step_q3 + index_step_q0;
492  int current_idx_q3_q1_0_loc = current_idx_loc + index_step_q3 + index_step_q1;
493  int current_idx_q3_q1_1_loc = current_idx_loc + index_step_q3 + index_step_q1 + index_step_q0;
494  int current_idx_q3_q2_0_loc = current_idx_loc + index_step_q3 + index_step_q2;
495  int current_idx_q3_q2_1_loc = current_idx_loc + index_step_q3 + index_step_q2 + index_step_q0;
496  int current_idx_q3_q2_q1_0_loc = current_idx_loc + index_step_q3 + index_step_q2 + index_step_q1;
497  int current_idx_q3_q2_q1_1_loc = current_idx_loc + index_step_q3 + index_step_q2 + index_step_q1 + index_step_q0;
498 
499  int current_idx_q4_q0_0_pair_loc = current_idx_pair_q4_loc;
500  int current_idx_q4_q0_1_pair_loc = current_idx_pair_q4_loc + index_step_q0;
501  int current_idx_q4_q1_0_pair_loc = current_idx_pair_q4_loc + index_step_q1;
502  int current_idx_q4_q1_1_pair_loc = current_idx_pair_q4_loc + index_step_q1 + index_step_q0;
503  int current_idx_q4_q2_0_pair_loc = current_idx_pair_q4_loc + index_step_q2;
504  int current_idx_q4_q2_1_pair_loc = current_idx_pair_q4_loc + index_step_q2 + index_step_q0;
505  int current_idx_q4_q2_q1_0_pair_loc = current_idx_pair_q4_loc + index_step_q2 + index_step_q1;
506  int current_idx_q4_q2_q1_1_pair_loc = current_idx_pair_q4_loc + index_step_q2 + index_step_q1 + index_step_q0;
507  int current_idx_q4_q3_0_pair_loc = current_idx_pair_q4_loc + index_step_q3;
508  int current_idx_q4_q3_1_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q0;
509  int current_idx_q4_q3_q1_0_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q1;
510  int current_idx_q4_q3_q1_1_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q1 + index_step_q0;
511  int current_idx_q4_q3_q2_0_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q2;
512  int current_idx_q4_q3_q2_1_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q2 + index_step_q0;
513  int current_idx_q4_q3_q2_q1_0_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q2 + index_step_q1;
514  int current_idx_q4_q3_q2_q1_1_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q2 + index_step_q1 + index_step_q0;
515 
516  int indexes[32] = {
517  current_idx_q0_0_loc, current_idx_q0_1_loc, current_idx_q1_0_loc, current_idx_q1_1_loc,
518  current_idx_q2_0_loc, current_idx_q2_1_loc, current_idx_q2_q1_0_loc, current_idx_q2_q1_1_loc,
519  current_idx_q3_0_loc, current_idx_q3_1_loc, current_idx_q3_q1_0_loc, current_idx_q3_q1_1_loc,
520  current_idx_q3_q2_0_loc, current_idx_q3_q2_1_loc, current_idx_q3_q2_q1_0_loc, current_idx_q3_q2_q1_1_loc,
521  current_idx_q4_q0_0_pair_loc, current_idx_q4_q0_1_pair_loc, current_idx_q4_q1_0_pair_loc, current_idx_q4_q1_1_pair_loc,
522  current_idx_q4_q2_0_pair_loc, current_idx_q4_q2_1_pair_loc, current_idx_q4_q2_q1_0_pair_loc, current_idx_q4_q2_q1_1_pair_loc,
523  current_idx_q4_q3_0_pair_loc, current_idx_q4_q3_1_pair_loc, current_idx_q4_q3_q1_0_pair_loc, current_idx_q4_q3_q1_1_pair_loc,
524  current_idx_q4_q3_q2_0_pair_loc, current_idx_q4_q3_q2_1_pair_loc, current_idx_q4_q3_q2_q1_0_pair_loc, current_idx_q4_q3_q2_q1_1_pair_loc
525  };
526 
527  StateVecComplexT<MatrixT> element_0 = input[current_idx_q0_0_loc];
528  StateVecComplexT<MatrixT> element_1 = input[current_idx_q0_1_loc];
529  StateVecComplexT<MatrixT> element_2 = input[current_idx_q1_0_loc];
530  StateVecComplexT<MatrixT> element_3 = input[current_idx_q1_1_loc];
531  StateVecComplexT<MatrixT> element_4 = input[current_idx_q2_0_loc];
532  StateVecComplexT<MatrixT> element_5 = input[current_idx_q2_1_loc];
533  StateVecComplexT<MatrixT> element_6 = input[current_idx_q2_q1_0_loc];
534  StateVecComplexT<MatrixT> element_7 = input[current_idx_q2_q1_1_loc];
535  StateVecComplexT<MatrixT> element_8 = input[current_idx_q3_0_loc];
536  StateVecComplexT<MatrixT> element_9 = input[current_idx_q3_1_loc];
537  StateVecComplexT<MatrixT> element_10 = input[current_idx_q3_q1_0_loc];
538  StateVecComplexT<MatrixT> element_11 = input[current_idx_q3_q1_1_loc];
539  StateVecComplexT<MatrixT> element_12 = input[current_idx_q3_q2_0_loc];
540  StateVecComplexT<MatrixT> element_13 = input[current_idx_q3_q2_1_loc];
541  StateVecComplexT<MatrixT> element_14 = input[current_idx_q3_q2_q1_0_loc];
542  StateVecComplexT<MatrixT> element_15 = input[current_idx_q3_q2_q1_1_loc];
543  StateVecComplexT<MatrixT> element_16 = input[current_idx_q4_q0_0_pair_loc];
544  StateVecComplexT<MatrixT> element_17 = input[current_idx_q4_q0_1_pair_loc];
545  StateVecComplexT<MatrixT> element_18 = input[current_idx_q4_q1_0_pair_loc];
546  StateVecComplexT<MatrixT> element_19 = input[current_idx_q4_q1_1_pair_loc];
547  StateVecComplexT<MatrixT> element_20 = input[current_idx_q4_q2_0_pair_loc];
548  StateVecComplexT<MatrixT> element_21 = input[current_idx_q4_q2_1_pair_loc];
549  StateVecComplexT<MatrixT> element_22 = input[current_idx_q4_q2_q1_0_pair_loc];
550  StateVecComplexT<MatrixT> element_23 = input[current_idx_q4_q2_q1_1_pair_loc];
551  StateVecComplexT<MatrixT> element_24 = input[current_idx_q4_q3_0_pair_loc];
552  StateVecComplexT<MatrixT> element_25 = input[current_idx_q4_q3_1_pair_loc];
553  StateVecComplexT<MatrixT> element_26 = input[current_idx_q4_q3_q1_0_pair_loc];
554  StateVecComplexT<MatrixT> element_27 = input[current_idx_q4_q3_q1_1_pair_loc];
555  StateVecComplexT<MatrixT> element_28 = input[current_idx_q4_q3_q2_0_pair_loc];
556  StateVecComplexT<MatrixT> element_29 = input[current_idx_q4_q3_q2_1_pair_loc];
557  StateVecComplexT<MatrixT> element_30 = input[current_idx_q4_q3_q2_q1_0_pair_loc];
558  StateVecComplexT<MatrixT> element_31 = input[current_idx_q4_q3_q2_q1_1_pair_loc];
559 
560  for (int mult_idx = 0; mult_idx < 32; mult_idx++) {
561  StateVecComplexT<MatrixT> tmp1 = mult(unitary[mult_idx * 32], element_0);
562  StateVecComplexT<MatrixT> tmp2 = mult(unitary[mult_idx * 32 + 1], element_1);
563  StateVecComplexT<MatrixT> tmp3 = mult(unitary[mult_idx * 32 + 2], element_2);
564  StateVecComplexT<MatrixT> tmp4 = mult(unitary[mult_idx * 32 + 3], element_3);
565  StateVecComplexT<MatrixT> tmp5 = mult(unitary[mult_idx * 32 + 4], element_4);
566  StateVecComplexT<MatrixT> tmp6 = mult(unitary[mult_idx * 32 + 5], element_5);
567  StateVecComplexT<MatrixT> tmp7 = mult(unitary[mult_idx * 32 + 6], element_6);
568  StateVecComplexT<MatrixT> tmp8 = mult(unitary[mult_idx * 32 + 7], element_7);
569  StateVecComplexT<MatrixT> tmp9 = mult(unitary[mult_idx * 32 + 8], element_8);
570  StateVecComplexT<MatrixT> tmp10 = mult(unitary[mult_idx * 32 + 9], element_9);
571  StateVecComplexT<MatrixT> tmp11 = mult(unitary[mult_idx * 32 + 10], element_10);
572  StateVecComplexT<MatrixT> tmp12 = mult(unitary[mult_idx * 32 + 11], element_11);
573  StateVecComplexT<MatrixT> tmp13 = mult(unitary[mult_idx * 32 + 12], element_12);
574  StateVecComplexT<MatrixT> tmp14 = mult(unitary[mult_idx * 32 + 13], element_13);
575  StateVecComplexT<MatrixT> tmp15 = mult(unitary[mult_idx * 32 + 14], element_14);
576  StateVecComplexT<MatrixT> tmp16 = mult(unitary[mult_idx * 32 + 15], element_15);
577  StateVecComplexT<MatrixT> tmp17 = mult(unitary[mult_idx * 32 + 16], element_16);
578  StateVecComplexT<MatrixT> tmp18 = mult(unitary[mult_idx * 32 + 17], element_17);
579  StateVecComplexT<MatrixT> tmp19 = mult(unitary[mult_idx * 32 + 18], element_18);
580  StateVecComplexT<MatrixT> tmp20 = mult(unitary[mult_idx * 32 + 19], element_19);
581  StateVecComplexT<MatrixT> tmp21 = mult(unitary[mult_idx * 32 + 20], element_20);
582  StateVecComplexT<MatrixT> tmp22 = mult(unitary[mult_idx * 32 + 21], element_21);
583  StateVecComplexT<MatrixT> tmp23 = mult(unitary[mult_idx * 32 + 22], element_22);
584  StateVecComplexT<MatrixT> tmp24 = mult(unitary[mult_idx * 32 + 23], element_23);
585  StateVecComplexT<MatrixT> tmp25 = mult(unitary[mult_idx * 32 + 24], element_24);
586  StateVecComplexT<MatrixT> tmp26 = mult(unitary[mult_idx * 32 + 25], element_25);
587  StateVecComplexT<MatrixT> tmp27 = mult(unitary[mult_idx * 32 + 26], element_26);
588  StateVecComplexT<MatrixT> tmp28 = mult(unitary[mult_idx * 32 + 27], element_27);
589  StateVecComplexT<MatrixT> tmp29 = mult(unitary[mult_idx * 32 + 28], element_28);
590  StateVecComplexT<MatrixT> tmp30 = mult(unitary[mult_idx * 32 + 29], element_29);
591  StateVecComplexT<MatrixT> tmp31 = mult(unitary[mult_idx * 32 + 30], element_30);
592  StateVecComplexT<MatrixT> tmp32 = mult(unitary[mult_idx * 32 + 31], element_31);
593 
594  input[indexes[mult_idx]].real = tmp1.real + tmp2.real + tmp3.real + tmp4.real
595  + tmp5.real + tmp6.real + tmp7.real + tmp8.real + tmp9.real + tmp10.real
596  + tmp11.real + tmp12.real + tmp13.real + tmp14.real + tmp15.real + tmp16.real
597  + tmp17.real + tmp18.real + tmp19.real + tmp20.real + tmp21.real + tmp22.real
598  + tmp23.real + tmp24.real + tmp25.real + tmp26.real + tmp27.real + tmp28.real
599  + tmp29.real + tmp30.real + tmp31.real + tmp32.real;
600 
601  input[indexes[mult_idx]].imag = tmp1.imag + tmp2.imag + tmp3.imag + tmp4.imag
602  + tmp5.imag + tmp6.imag + tmp7.imag + tmp8.imag + tmp9.imag + tmp10.imag
603  + tmp11.imag + tmp12.imag + tmp13.imag + tmp14.imag + tmp15.imag + tmp16.imag
604  + tmp17.imag + tmp18.imag + tmp19.imag + tmp20.imag + tmp21.imag + tmp22.imag
605  + tmp23.imag + tmp24.imag + tmp25.imag + tmp26.imag + tmp27.imag + tmp28.imag
606  + tmp29.imag + tmp30.imag + tmp31.imag + tmp32.imag;
607  }
608  }
609  }
610  }
611  }
612  }
613  current_idx += (index_step_q4 << 1);
614  }
615 
616  (void)matrix_size;
617 }
618 
619 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) {
620  apply_large_state_vector_2q_impl(two_qbit_unitary, input, inner_qbit, outer_qbit, matrix_size);
621 }
622 
623 void apply_2qbit_kernel_to_state_vector_input(Matrix_float& two_qbit_unitary, Matrix_float& input, const int& inner_qbit, const int& outer_qbit, const int& matrix_size) {
624  apply_large_state_vector_2q_impl(two_qbit_unitary, input, inner_qbit, outer_qbit, matrix_size);
625 }
626 
627 void apply_3qbit_kernel_to_state_vector_input(Matrix& unitary, Matrix& input, std::vector<int> involved_qbits, const int& matrix_size) {
628  apply_large_state_vector_3q_impl(unitary, input, involved_qbits, matrix_size);
629 }
630 
631 void apply_3qbit_kernel_to_state_vector_input(Matrix_float& unitary, Matrix_float& input, std::vector<int> involved_qbits, const int& matrix_size) {
632  apply_large_state_vector_3q_impl(unitary, input, involved_qbits, matrix_size);
633 }
634 
635 void apply_4qbit_kernel_to_state_vector_input(Matrix& unitary, Matrix& input, std::vector<int> involved_qbits, const int& matrix_size) {
636  apply_large_state_vector_4q_impl(unitary, input, involved_qbits, matrix_size);
637 }
638 
639 void apply_4qbit_kernel_to_state_vector_input(Matrix_float& unitary, Matrix_float& input, std::vector<int> involved_qbits, const int& matrix_size) {
640  apply_large_state_vector_4q_impl(unitary, input, involved_qbits, matrix_size);
641 }
642 
643 void apply_5qbit_kernel_to_state_vector_input(Matrix& unitary, Matrix& input, std::vector<int> involved_qbits, const int& matrix_size) {
644  apply_large_state_vector_5q_impl(unitary, input, involved_qbits, matrix_size);
645 }
646 
647 void apply_5qbit_kernel_to_state_vector_input(Matrix_float& unitary, Matrix_float& input, std::vector<int> involved_qbits, const int& matrix_size) {
648  apply_large_state_vector_5q_impl(unitary, input, involved_qbits, matrix_size);
649 }
650 
651 
652 
void apply_kernel_to_state_vector_input_parallel_impl(MatrixT &u3_1qbit, MatrixT &input, const bool &deriv, const int &target_qbit, const int &control_qbit, const int &matrix_size)
Call to apply a gate kernel on a state vector.
void apply_large_state_vector_5q_impl(MatrixT &unitary, MatrixT &input, std::vector< int > involved_qbits, const int &matrix_size)
void apply_4qbit_kernel_to_state_vector_input(Matrix &unitary, Matrix &input, std::vector< int > involved_qbits, const int &matrix_size)
void apply_large_state_vector_4q_impl(MatrixT &unitary, MatrixT &input, std::vector< int > involved_qbits, const int &matrix_size)
QGD_Complex16 mult(QGD_Complex16 &a, QGD_Complex16 &b)
Call to calculate the product of two complex scalars.
Definition: common.cpp:298
void apply_large_state_vector_3q_impl(MatrixT &unitary, MatrixT &input, std::vector< int > involved_qbits, const int &matrix_size)
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_state_vector_2q_impl(MatrixT &two_qbit_unitary, MatrixT &input, const int &inner_qbit, const int &outer_qbit, const int &matrix_size)
matrix_size
[load Umtx]
Definition: example.py:58
typename std::remove_reference< decltype(std::declval< MatrixT & >()[0])>::type StateVecComplexT
void apply_3qbit_kernel_to_state_vector_input(Matrix &unitary, Matrix &input, std::vector< int > involved_qbits, const int &matrix_size)
void apply_5qbit_kernel_to_state_vector_input(Matrix &unitary, Matrix &input, std::vector< int > involved_qbits, const int &matrix_size)
Double-precision complex matrix (float64).
Definition: matrix.h:38
Single-precision complex matrix (float32).
Definition: matrix_float.h:41
void apply_kernel_to_state_vector_input(Matrix &u3_1qbit, Matrix &input, const bool &deriv, const int &target_qbit, const int &control_qbit, const int &matrix_size)
Call to apply a gate kernel on a state vector.
void apply_kernel_to_state_vector_input_impl(MatrixT &u3_1qbit, MatrixT &input, const bool &deriv, const int &target_qbit, const int &control_qbit, const int &matrix_size)
void apply_kernel_to_state_vector_input_parallel(Matrix &u3_1qbit, Matrix &input, const bool &deriv, const int &target_qbit, const int &control_qbit, const int &matrix_size)
Call to apply a gate kernel on a state vector.