Quantum Gate Decomposer  v1.3
Powerful decomposition of almost any unitary into U3 and CNOT gates
common.cpp
Go to the documentation of this file.
1 /*
2 Created on Fri Jun 26 14:13:26 2020
3 Copyright (C) 2020 Peter Rakyta, Ph.D.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see http://www.gnu.org/licenses/.
17 
18 @author: Peter Rakyta, Ph.D.
19 */
24 //
25 // @brief A base class responsible for constructing matrices of C-NOT, U3
26 // gates acting on the N-qubit space
27 
28 #include "qgd/common.h"
29 
30 
31 
38 void* qgd_calloc( size_t element_num, size_t size, size_t alignment ) {
39 
40  void* ret = scalable_aligned_malloc( size*element_num, CACHELINE);
41  memset(ret, 0, element_num*size);
42  return ret;
43 }
44 
54 void* qgd_realloc(void* aligned_ptr, size_t element_num, size_t size, size_t alignment ) {
55 
56  void* ret = scalable_aligned_realloc(aligned_ptr, size*element_num, CACHELINE);
57  return ret;
58 
59 }
60 
61 
62 
66 void qgd_free( void* ptr ) {
67 
68  // preventing double free corruption
69  if (ptr != NULL ) {
70  scalable_aligned_free(ptr);
71  }
72  ptr = NULL;
73 }
74 
75 
81 int Power_of_2(int n) {
82  if (n == 0) return 1;
83  if (n == 1) return 2;
84 
85  return 2 * Power_of_2(n-1);
86 }
87 
88 
89 
95 void add_unique_elelement( std::vector<int> &involved_qbits, int qbit ) {
96 
97  if ( involved_qbits.size() == 0 ) {
98  involved_qbits.push_back( qbit );
99  }
100 
101  for(std::vector<int>::iterator it = involved_qbits.begin(); it != involved_qbits.end(); ++it) {
102 
103  int current_val = *it;
104 
105  if (current_val == qbit) {
106  return;
107  }
108  else if (current_val > qbit) {
109  involved_qbits.insert( it, qbit );
110  return;
111  }
112 
113  }
114 
115  // add the qbit to the end if neither of the conditions were satisfied
116  involved_qbits.push_back( qbit );
117 
118  return;
119 
120 }
121 
122 
129 
131  memset(mtx.get_data(), 0, mtx.size()*sizeof(QGD_Complex16) );
132 
133  // setting the diagonal elelments to identity
134  for(int idx = 0; idx < matrix_size; ++idx)
135  {
136  int element_index = idx*matrix_size + idx;
137  mtx[element_index].real = 1.0;
138  }
139 
140  return mtx;
141 
142 }
143 
144 
145 
153 
154  memset( matrix, 0, matrix_size*matrix_size*sizeof(QGD_Complex16) );
155 
156  // setting the diagonal elelments to identity
157  for(int idx = 0; idx < matrix_size; ++idx)
158  {
159  int element_index = idx*matrix_size + idx;
160  matrix[element_index].real = 1.0;
161  }
162 
163  return 0;
164 
165 }
166 
167 
176 
177  // parameters alpha and beta for the cblas_zgemm3m function
178  QGD_Complex16 alpha;
179  alpha.real = 1.0;
180  alpha.imag = 0.0;
181  QGD_Complex16 beta;
182  beta.real = 0.0;
183  beta.imag = 0.0;
184 
185  // preallocate array for the result
186  QGD_Complex16 C;
187 
188  // calculate the product of A and B
189 #ifdef CBLAS
190  cblas_zgemm3m (CblasRowMajor, CblasNoTrans, CblasConjTrans, 1, 1, vector_size, &alpha, A, vector_size, B, vector_size, &beta, &C, 1);
191 #else
192  cblas_zgemm (CblasRowMajor, CblasNoTrans, CblasConjTrans, 1, 1, vector_size, &alpha, A, vector_size, B, vector_size, &beta, &C, 1);
193 #endif
194 
195  return C;
196 }
197 
198 
199 
208 
209  // parameters alpha and beta for the cblas_zgemm3m function
210  QGD_Complex16 alpha;
211  alpha.real = 1.0;
212  alpha.imag = 0.0;
213  QGD_Complex16 beta;
214  beta.real = 0.0;
215  beta.imag = 0.0;
216 
217  // calculate the product of A and B
218 #ifdef CBLAS
219  cblas_zgemm3m (CblasRowMajor, CblasNoTrans, CblasConjTrans, matrix_size, matrix_size, matrix_size, &alpha, A, matrix_size, B, matrix_size, &beta, C, matrix_size);
220 #else
221  cblas_zgemm (CblasRowMajor, CblasNoTrans, CblasConjTrans, matrix_size, matrix_size, matrix_size, &alpha, A, matrix_size, B, matrix_size, &beta, C, matrix_size);
222 #endif
223 
224  return 0;
225 }
226 
227 
228 
237 
238  // parameters alpha and beta for the cblas_zgemm3m function
239  QGD_Complex16 alpha;
240  alpha.real = 1.0;
241  alpha.imag = 0.0;
242  QGD_Complex16 beta;
243  beta.real = 0.0;
244  beta.imag = 0.0;
245 
246  // preallocate array for the result
248 
249  // calculate the product of A and B
250 #ifdef CBLAS
251  cblas_zgemm3m (CblasRowMajor, CblasNoTrans, CblasNoTrans, matrix_size, matrix_size, matrix_size, &alpha, A, matrix_size, B, matrix_size, &beta, C, matrix_size);
252 #else
253  cblas_zgemm (CblasRowMajor, CblasNoTrans, CblasNoTrans, matrix_size, matrix_size, matrix_size, &alpha, A, matrix_size, B, matrix_size, &beta, C, matrix_size);
254 #endif
255 
256  return C;
257 }
258 
259 
269 
270  // parameters alpha and beta for the cblas_zgemm3m function
271  QGD_Complex16 alpha;
272  alpha.real = 1.0;
273  alpha.imag = 0.0;
274  QGD_Complex16 beta;
275  beta.real = 0.0;
276  beta.imag = 0.0;
277 
278  // calculate the product of A and B
279 #ifdef CBLAS
280  cblas_zgemm3m (CblasRowMajor, CblasNoTrans, CblasNoTrans, matrix_size, matrix_size, matrix_size, &alpha, A, matrix_size, B, matrix_size, &beta, C, matrix_size);
281 #else
282  cblas_zgemm (CblasRowMajor, CblasNoTrans, CblasNoTrans, matrix_size, matrix_size, matrix_size, &alpha, A, matrix_size, B, matrix_size, &beta, C, matrix_size);
283 #endif
284 
285  return 0;
286 }
287 
288 
289 
296 Matrix
297 reduce_zgemm( std::vector<Matrix>& mtxs ) {
298 
299 
300 
301  if (mtxs.size() == 0 ) {
302  return Matrix();
303  }
304 
305  // pointers to matrices to be used in the multiplications
306  Matrix A;
307  Matrix B;
308  Matrix C;
309 
310  // the iteration number
311  int iteration = 0;
312 
313 
314  A = *mtxs.begin();
315 
316  // calculate the product of complex matrices
317  for(std::vector<Matrix>::iterator it=++mtxs.begin(); it != mtxs.end(); ++it) {
318 
319  iteration++;
320  B = *it;
321 
322  if ( iteration>1 ) {
323  A = C;
324  }
325 
326  // calculate the product of A and B
327  C = dot(A, B);
328 /*
329 A.print_matrix();
330 B.print_matrix();
331 C.print_matrix();
332 */
333  }
334 
335  //C.print_matrix();
336  return C;
337 
338 }
339 
340 
346 void subtract_diag( Matrix& mtx, QGD_Complex16 scalar ) {
347 
348  size_t matrix_size = mtx.rows;
349 
350  for(size_t idx = 0; idx < matrix_size; idx++) {
351  size_t element_idx = idx*matrix_size+idx;
352  mtx[element_idx].real = mtx[element_idx].real - scalar.real;
353  mtx[element_idx].imag = mtx[element_idx].imag - scalar.imag;
354  }
355 
356 }
357 
358 
359 
360 
368 
369  QGD_Complex16 ret;
370  ret.real = a.real*b.real - a.imag*b.imag;
371  ret.imag = a.real*b.imag + a.imag*b.real;
372 
373  return ret;
374 
375 }
376 
384 
385  QGD_Complex16 ret;
386  ret.real = a*b.real;
387  ret.imag = a*b.imag;
388 
389  return ret;
390 
391 }
392 
393 
394 
400 void mult( QGD_Complex16 a, Matrix& b ) {
401 
402  size_t element_num = b.size();
403 
404  for (size_t idx=0; idx<element_num; idx++) {
405  QGD_Complex16 tmp = b[idx];
406  b[idx].real = a.real*tmp.real - a.imag*tmp.imag;
407  b[idx].imag = a.real*tmp.imag + a.imag*tmp.real;
408  }
409 
410  return;
411 
412 }
413 
414 
415 
Matrix dot(Matrix &A, Matrix &B)
Call to calculate the product of two complex matrices by calling method zgemm3m from the CBLAS librar...
Definition: dot.cpp:20
size_t rows
The number of rows.
Definition: matrix_base.h:23
void * qgd_calloc(size_t element_num, size_t size, size_t alignment)
custom defined memory allocation function.
Definition: common.cpp:38
void qgd_free(void *ptr)
custom defined memory release function.
Definition: common.cpp:66
scalar * get_data()
Call to get the pointer to the stored data.
Definition: matrix_base.h:221
QGD_Complex16 mult(QGD_Complex16 a, QGD_Complex16 b)
Call to calculate the product of two complex scalars.
Definition: common.cpp:367
#define CACHELINE
Definition: QGDTypes.h:34
QGD_Complex16 * zgemm3m_wrapper(QGD_Complex16 *A, QGD_Complex16 *B, int matrix_size)
Call to calculate the product of two square shaped complex matrices using function cblas_zgemm3m or c...
Definition: common.cpp:236
Matrix reduce_zgemm(std::vector< Matrix > &mtxs)
Calculate the product of several square shaped complex matrices stored in a vector.
Definition: common.cpp:297
int zgemm3m_wrapper_adj(QGD_Complex16 *A, QGD_Complex16 *B, QGD_Complex16 *C, int matrix_size)
Call to calculate the product of a square shaped complex matrix and a complex transpose of a second s...
Definition: common.cpp:207
void * qgd_realloc(void *aligned_ptr, size_t element_num, size_t size, size_t alignment)
custom defined memory reallocation function.
Definition: common.cpp:54
matrix_size
Definition: example.py:41
Structure type representing complex numbers in the QGD package.
Definition: QGDTypes.h:39
int Power_of_2(int n)
Calculates the n-th power of 2.
Definition: common.cpp:81
Class to store data of complex arrays and its properties.
Definition: matrix.h:12
void subtract_diag(Matrix &mtx, QGD_Complex16 scalar)
Call to subtract a scalar from the diagonal of a complex matrix.
Definition: common.cpp:346
Matrix create_identity(int matrix_size)
Call to create an identity matrix.
Definition: common.cpp:128
Header file for commonly used functions and wrappers to CBLAS functions.
void add_unique_elelement(std::vector< int > &involved_qbits, int qbit)
Add an integer to a vector of integers if the integer is not already an element of the vector.
Definition: common.cpp:95
double real
the real part of a complex number
Definition: QGDTypes.h:41
size_t size()
Call to get the number of the allocated elements.
Definition: matrix_base.h:374
QGD_Complex16 scalar_product(QGD_Complex16 *A, QGD_Complex16 *B, int vector_size)
Call to calculate the scalar product of two complex vectors using function cblas_zgemm3m or cblas_zge...
Definition: common.cpp:175
double imag
the imaginary part of a complex number
Definition: QGDTypes.h:43