Quantum Gate Decomposer  v1.3
Powerful decomposition of almost any unitary into U3 and CNOT gates
Sub_Matrix_Decomposition_Cost_Function.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 */
25 
26 
27 
28 
36 
37  // ********************************
38  // Extract Submatrices
39  // ********************************
40 
41  // number of submatrices
42  size_t submatrices_num = 4;
43 
44  size_t submatrices_num_row = 2;
45 
46 
47  // Extracting submatrices from the unitary
48  std::vector<Matrix, tbb::cache_aligned_allocator<Matrix>> submatrices(submatrices_num);
49 
50  tbb::parallel_for( tbb::blocked_range<size_t>(0, submatrices_num, 1), functor_extract_submatrices( matrix, &submatrices ));
51 
52  // ********************************
53  // Calculate the partial cost functions
54  // ********************************
55 
56 
57  size_t prod_num = submatrices_num*submatrices_num_row;
58  tbb::combinable<double> priv_prod_cost_functions{[](){return 0;}};
59 
60  tbb::parallel_for(0, (int) prod_num, 1, functor_submtx_cost_fnc( &submatrices, &priv_prod_cost_functions, prod_num ));
61 
62  // ********************************
63  // Calculate the total cost function
64  // ********************************
65 
66  // calculate the final cost function
67  double cost_function = 0;
68  priv_prod_cost_functions.combine_each([&cost_function](double a) {
69  cost_function = cost_function + a;
70  });
71 
72 
73 
74  return cost_function;
75 
76 }
77 
85 functor_extract_submatrices::functor_extract_submatrices( Matrix& matrix_in, std::vector<Matrix, tbb::cache_aligned_allocator<Matrix>>* submatrices_in ) {
86 
87  matrix = matrix_in;
88  submatrices = submatrices_in;
89 
90 
91 }
92 
97 void functor_extract_submatrices::operator()( tbb::blocked_range<size_t> r ) const {
98 
99  for ( size_t submtx_idx = r.begin(); submtx_idx != r.end(); submtx_idx++) {
100 
101  // The given Submatrix
102  Matrix& submatrix = (*submatrices)[ submtx_idx ];
103 
104  // number of submatrices
105  size_t submatrices_num_row = 2;
106 
107  // number of columns in the input matrix
108  size_t matrix_size = matrix.rows;
109 
110  // number of columns in the submatrices
111  size_t submatrix_size = matrix_size/2;
112 
113  // preallocate memory for the submatrix
114  submatrix = Matrix(submatrix_size, submatrix_size);
115 
116 
117  // extract the submatrix
118  size_t jdx = submtx_idx % submatrices_num_row;
119  size_t idx = (size_t) (submtx_idx-jdx)/submatrices_num_row;
120 
121  // copy memory to submatrices
122  for ( size_t row_idx=0; row_idx<submatrix_size; row_idx++ ) {
123 
124  size_t matrix_offset = idx*(matrix_size*submatrix_size) + jdx*(submatrix_size) + row_idx*matrix_size;
125  size_t submatrix_offset = row_idx*submatrix_size;
126  memcpy(submatrix.get_data()+submatrix_offset, matrix.get_data()+matrix_offset, submatrix_size*sizeof(QGD_Complex16));
127 
128  }
129 
130  }
131 
132 }
133 
134 
135 
136 
144 functor_submtx_cost_fnc::functor_submtx_cost_fnc( std::vector<Matrix, tbb::cache_aligned_allocator<Matrix>>* submatrices_in, tbb::combinable<double>* prod_cost_functions_in, size_t prod_num_in ) {
145 
146  submatrices = submatrices_in;
147  prod_cost_functions = prod_cost_functions_in;
148  prod_num = prod_num_in;
149 }
150 
155 void functor_submtx_cost_fnc::operator()( int product_idx ) const {
156 
157 
158 
159  // number of submatrices
160  size_t submatrices_num_row = 2;
161 
162  // select the given submatrices used to calculate the partial cost_function
163  size_t jdx = product_idx % submatrices_num_row;
164  size_t idx = (size_t) ( product_idx - jdx )/submatrices_num_row;
165 
166  // calculate the submatrix product
167  Matrix tmp = (*submatrices)[jdx];
168  tmp.transpose();
169  tmp.conjugate();
170  Matrix submatrix_prod = dot( (*submatrices)[idx], tmp);
171 
172 
173 
174  // number of elements in the matrix of submatrix products
175  size_t submatrix_size = submatrix_prod.rows;
176  size_t element_num = submatrix_size*submatrix_size;
177 
178  // subtract the corner element from the diagonal
179  QGD_Complex16 corner_element = submatrix_prod[0];
180  tbb::parallel_for( tbb::blocked_range<size_t>(0, submatrix_size, 1), [&](tbb::blocked_range<size_t> r){
181  for ( size_t row_idx=r.begin(); row_idx != r.end(); row_idx++) {
182  size_t element_idx = row_idx*submatrix_size+row_idx;
183  submatrix_prod[element_idx].real = submatrix_prod[element_idx].real - corner_element.real;
184  submatrix_prod[element_idx].imag = submatrix_prod[element_idx].imag - corner_element.imag;
185  }
186 
187  });
188 
189  // Calculate the |x|^2 value of the elements of the submatrixproducts and add to the partial cost function
190  tbb::parallel_for( tbb::blocked_range<size_t>(0, element_num, 1), [&](tbb::blocked_range<size_t> r){
191  for (size_t idx = r.begin(); idx != r.end(); idx ++) {
192 
193  // store the calculated value for the given submatrix product element
194  double &prod_cost_function_priv = prod_cost_functions->local();
195  prod_cost_function_priv = prod_cost_function_priv + submatrix_prod[idx].real*submatrix_prod[idx].real + submatrix_prod[idx].imag*submatrix_prod[idx].imag;
196  }
197  });
198 
199  // checking NaN
200  if (std::isnan(prod_cost_functions->local())) {
201  printf("cost function NaN on thread %d: exiting\n", product_idx);
202  exit(-1);
203  }
204 
205 
206 }
207 
208 
209 
210 
211 
212 
213 
214 
functor_extract_submatrices(Matrix &matrix_in, std::vector< Matrix, tbb::cache_aligned_allocator< Matrix >> *submatrices_in)
Constructor of the class.
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
Function operator class to calculate the partial cost function derived from the individual products o...
std::vector< Matrix, tbb::cache_aligned_allocator< Matrix > > * submatrices
container storing the submatrices
size_t rows
The number of rows.
Definition: matrix_base.h:23
void operator()(tbb::blocked_range< size_t > r) const
Operator to extract the sumbatrix indexed by submtx_idx.
void operator()(int product_idx) const
Operator to calculate the partial cost function labeled by product_idx.
scalar * get_data()
Call to get the pointer to the stored data.
Definition: matrix_base.h:221
matrix_size
Definition: example.py:41
Function operator class to extract the submatrices from a unitary.
double get_submatrix_cost_function(Matrix &matrix)
Call to calculate the cost function of a given matrix during the submatrix decomposition process.
functor_submtx_cost_fnc(std::vector< Matrix, tbb::cache_aligned_allocator< Matrix >> *submatrices_in, tbb::combinable< double > *prod_cost_functions_in, size_t prod_num_in)
Constructor of the class.
Structure type representing complex numbers in the QGD package.
Definition: QGDTypes.h:39
Class to store data of complex arrays and its properties.
Definition: matrix.h:12
void transpose()
Call to transpose (or un-transpose) the matrix for CBLAS functions.
Definition: matrix_base.h:209
Matrix matrix
The matrix from which submatrices would be extracted.
std::vector< Matrix, tbb::cache_aligned_allocator< Matrix > > * submatrices
preallocated container storing the submatrices
double real
the real part of a complex number
Definition: QGDTypes.h:41
void conjugate()
Call to conjugate (or un-conjugate) the matrix for CBLAS functions.
Definition: matrix_base.h:188
int prod_num
number of distinct submatix products
tbb::combinable< double > * prod_cost_functions
Header file for the paralleized calculation of the cost function of the subdecomposition (supporting ...
double imag
the imaginary part of a complex number
Definition: QGDTypes.h:43