Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates 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 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 */
24 #include <tbb/blocked_range.h>
25 #include <tbb/parallel_for.h>
26 
27 
28 
36 
37  // ********************************
38  // Extract Submatrices
39  // ********************************
40 
41  // number of submatrices
42  int submatrices_num = 4;
43 
44  int 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<int>(0, submatrices_num, 1), functor_extract_submatrices( matrix, &submatrices ));
51 
52 
53 
54 
55  // ********************************
56  // Calculate the partial cost functions
57  // ********************************
58 
59 
60  int prod_num = submatrices_num*submatrices_num_row;
61  tbb::combinable<double> priv_prod_cost_functions{[](){return 0;}};
62 
63  tbb::parallel_for(0, (int) prod_num, 1, functor_submtx_cost_fnc( &submatrices, &priv_prod_cost_functions, prod_num ));
64 
65  // ********************************
66  // Calculate the total cost function
67  // ********************************
68 
69  // calculate the final cost function
70  double cost_function = 0;
71  priv_prod_cost_functions.combine_each([&cost_function](double a) {
72  cost_function = cost_function + a;
73  });
74 
75 
76  return cost_function;
77 
78 }
79 
87 functor_extract_submatrices::functor_extract_submatrices( Matrix& matrix_in, std::vector<Matrix, tbb::cache_aligned_allocator<Matrix>>* submatrices_in ) {
88 
89  matrix = matrix_in;
90  submatrices = submatrices_in;
91 
92 
93 }
94 
99 void functor_extract_submatrices::operator()( tbb::blocked_range<int> r ) const {
100 
101  // number of submatrices
102  int submatrices_num_row = 2;
103 
104  // number of columns in the input matrix
105  int matrix_size = matrix.rows;
106 
107  // number of columns in the submatrices
108  int submatrix_size = matrix_size/2;
109 
110  for ( int submtx_idx = r.begin(); submtx_idx != r.end(); submtx_idx++) {
111 
112  // The given Submatrix
113  Matrix& submatrix = (*submatrices)[ submtx_idx ];
114 
115 
116  // create submarix data by striding the original matrix
117  int jdx = submtx_idx % submatrices_num_row;
118  int idx = (int) (submtx_idx-jdx)/submatrices_num_row;
119  int matrix_offset = idx*(matrix.stride*submatrix_size) + jdx*(submatrix_size);
120  submatrix = Matrix(matrix.get_data()+matrix_offset, submatrix_size, submatrix_size, matrix.stride);
121 
122 
123 /*
124  // preallocate memory for the submatrix
125  submatrix = Matrix(submatrix_size, submatrix_size);
126 
127 
128  // extract the submatrix
129  int jdx = submtx_idx % submatrices_num_row;
130  int idx = (int) (submtx_idx-jdx)/submatrices_num_row;
131 
132  // copy memory to submatrices
133  for ( int row_idx=0; row_idx<submatrix_size; row_idx++ ) {
134 
135  int matrix_offset = idx*(matrix_size*submatrix_size) + jdx*(submatrix_size) + row_idx*matrix_size;
136  int submatrix_offset = row_idx*submatrix_size;
137  memcpy(submatrix.get_data()+submatrix_offset, matrix.get_data()+matrix_offset, submatrix_size*sizeof(QGD_Complex16));
138 
139  }
140 */
141 #ifdef DEBUG
142  if (submatrix.isnan()) {
143  std::stringstream sstream;
144  sstream << "Submatrix contains NaN." << std::endl;
145  print(sstream, 1);
146  }
147 #endif
148 
149  }
150 
151 }
152 
153 
154 
155 
163 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, int prod_num_in ) {
164 
165  submatrices = submatrices_in;
166  prod_cost_functions = prod_cost_functions_in;
167  prod_num = prod_num_in;
168 }
169 
174 void functor_submtx_cost_fnc::operator()( int product_idx ) const {
175 
176  // number of submatrices
177  int submatrices_num_row = 2;
178 
179  // select the given submatrices used to calculate the partial cost_function
180  int jdx = product_idx % submatrices_num_row;
181  int idx = (int) ( product_idx - jdx )/submatrices_num_row;
182 
183  // calculate the submatrix product
184  Matrix tmp = (*submatrices)[jdx];
185  tmp.transpose();
186  tmp.conjugate();
187  Matrix submatrix_prod = dot( (*submatrices)[idx], tmp );
188 // Matrix submatrix_prod = dot( tmp, (*submatrices)[idx] );
189 
190 #ifdef DEBUG
191  if (submatrix_prod.isnan()) {
192  std::stringstream sstream;
193  sstream << "functor_submtx_cost_fnc::operator: Submatrix product contains NaN. Exiting" << std::endl;
194  print(sstream, 1);
195  }
196 #endif
197 
198 
199 //std::cout << idx << " " << jdx << std::endl;
200 //submatrix_prod.print_matrix();
201 
202  // number of elements in the matrix of submatrix products
203  int submatrix_size = submatrix_prod.rows;
204  int element_num = submatrix_size*submatrix_size;
205 
206  // subtract the corner element from the diagonal
207  QGD_Complex16 corner_element = submatrix_prod[0];
208  //tbb::parallel_for( tbb::blocked_range<int>(0, submatrix_size, 1), [&](tbb::blocked_range<int> r){
209 // for ( int row_idx=r.begin(); row_idx != r.end(); row_idx++) {
210  for ( int row_idx=0; row_idx < submatrix_size; row_idx++) {
211  int element_idx = row_idx*submatrix_prod.stride+row_idx;
212  submatrix_prod[element_idx].real = submatrix_prod[element_idx].real - corner_element.real;
213  submatrix_prod[element_idx].imag = submatrix_prod[element_idx].imag - corner_element.imag;
214  }
215 
216  //});
217 
218  // Calculate the |x|^2 value of the elements of the submatrixproducts and add to the partial cost function
219  //tbb::parallel_for( tbb::blocked_range<int>(0, element_num, 1), [&](tbb::blocked_range<int> r){
220 // for (int idx = r.begin(); idx != r.end(); idx ++) {
221  for (int idx = 0; idx < element_num; idx++) {
222 
223  // store the calculated value for the given submatrix product element
224  double &prod_cost_function_priv = prod_cost_functions->local();
225  prod_cost_function_priv = prod_cost_function_priv + submatrix_prod[idx].real*submatrix_prod[idx].real + submatrix_prod[idx].imag*submatrix_prod[idx].imag;
226  }
227  //});
228 
229 
230  // checking NaN
231  if (std::isnan(prod_cost_functions->local())) {
232  std::stringstream sstream;
233  sstream << "cost function NaN on cost function product "<< product_idx << std::endl;
234  print(sstream, 1);
235  }
236 
237 
238 }
239 
240 
241 
242 
243 
244 
245 
246 
functor_extract_submatrices(Matrix &matrix_in, std::vector< Matrix, tbb::cache_aligned_allocator< Matrix >> *submatrices_in)
Constructor of the class.
bool isnan()
Call to check the array for NaN entries.
Definition: matrix.cpp:128
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:38
Function operator class to calculate the partial cost function derived from the individual products o...
void print(const std::stringstream &sstream, int verbose_level=1) const
Call to print output messages in the function of the verbosity level.
Definition: logging.cpp:55
int stride
The column stride of the array. (The array elements in one row are a_0, a_1, ... a_{cols-1}, 0, 0, 0, 0. The number of zeros is stride-cols)
Definition: matrix_base.hpp:46
void operator()(int product_idx) const
Operator to calculate the partial cost function labeled by product_idx.
functor_submtx_cost_fnc(std::vector< Matrix, tbb::cache_aligned_allocator< Matrix >> *submatrices_in, tbb::combinable< double > *prod_cost_functions_in, int prod_num_in)
Constructor of the class.
scalar * get_data() const
Call to get the pointer to the stored data.
int rows
The number of rows.
Definition: matrix_base.hpp:42
matrix_size
[load Umtx]
Definition: example.py:58
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...
void operator()(tbb::blocked_range< int > r) const
Operator to extract the sumbatrix indexed by submtx_idx.
Structure type representing complex numbers in the SQUANDER package.
Definition: QGDTypes.h:38
Class to store data of complex arrays and its properties.
Definition: matrix.h:38
void transpose()
Call to transpose (or un-transpose) the matrix for CBLAS functions.
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:40
void conjugate()
Call to conjugate (or un-conjugate) the matrix for CBLAS 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:42