Warning: this documentation for the development version is under construction.
00001 // Copyright (C) 2003-2009 Marc Duruflé 00002 // Copyright (C) 2001-2009 Vivien Mallet 00003 // 00004 // This file is part of the linear-algebra library Seldon, 00005 // http://seldon.sourceforge.net/. 00006 // 00007 // Seldon is free software; you can redistribute it and/or modify it under the 00008 // terms of the GNU Lesser General Public License as published by the Free 00009 // Software Foundation; either version 2.1 of the License, or (at your option) 00010 // any later version. 00011 // 00012 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY 00013 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00014 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 00015 // more details. 00016 // 00017 // You should have received a copy of the GNU Lesser General Public License 00018 // along with Seldon. If not, see http://www.gnu.org/licenses/. 00019 00020 00021 #ifndef SELDON_FILE_PERMUTATION_SCALING_MATRIX_CXX 00022 00023 /* 00024 Functions defined in this file: 00025 00026 ApplyInversePermutation(A, I, J) 00027 00028 ScaleMatrix(A, Drow, Dcol) 00029 00030 ScaleLeftMatrix(A, Drow) 00031 */ 00032 00033 namespace Seldon 00034 { 00035 00036 00038 00042 template<class T, class Prop, class Allocator> 00043 void ApplyInversePermutation(Matrix<T, Prop, RowSparse, Allocator>& A, 00044 const Vector<int>& row_perm, 00045 const Vector<int>& col_perm) 00046 { 00047 int i, j, k, l, nnz; 00048 int m = A.GetM(); 00049 int n = A.GetN(); 00050 int* ind = A.GetInd(); 00051 int* ptr = A.GetPtr(); 00052 T* data = A.GetData(); 00053 00054 /*** Permutation of the columns ***/ 00055 00056 Vector<T, VectFull, Allocator> row_data; 00057 // Column indexes of a given row. 00058 Vector<int> row_index; 00059 for (i = 0; i < m; i++) 00060 if ((nnz = ptr[i + 1] - ptr[i]) != 0) 00061 { 00062 row_index.Reallocate(nnz); 00063 row_data.Reallocate(nnz); 00064 for (k = 0, l = ptr[i]; k < nnz; k++, l++) 00065 { 00066 // Applies the permutation on the columns. 00067 row_index(k) = col_perm(ind[l]); 00068 row_data(k) = data[l]; 00069 } 00070 00071 // The columns must remain in increasing order. 00072 Sort(row_index, row_data); 00073 00074 // Putting back the data into the array. 00075 for (k = 0, l = ptr[i]; k < nnz; k++, l++) 00076 { 00077 ind[l] = row_index(k); 00078 data[l] = row_data(k); 00079 } 00080 } 00081 row_index.Clear(); 00082 row_data.Clear(); 00083 00084 /*** Perturbation of the rows ***/ 00085 00086 // Total number of non-zero elements. 00087 nnz = ptr[m]; 00088 00089 // 'row_perm' is const, so it must be copied. 00090 Vector<int> row_permutation(row_perm); 00091 // Row indexes in the origin matrix: prev_row_index(i) should be the 00092 // location of the i-th row (from the permuted matrix) in the matrix 00093 // before permutation. 00094 Vector<int> prev_row_index(m); 00095 prev_row_index.Fill(); 00096 00097 Sort(row_permutation, prev_row_index); 00098 row_permutation.Clear(); 00099 00100 // Description of the matrix after permutations. 00101 Vector<int, VectFull, CallocAlloc<int> > new_ptr(m + 1); 00102 Vector<int, VectFull, CallocAlloc<int> > new_ind(nnz); 00103 Vector<T, VectFull, Allocator> new_data(nnz); 00104 00105 int ptr_count = 0, length; 00106 for (i = 0; i < m; i++) 00107 { 00108 length = ptr[prev_row_index(i) + 1] - ptr[prev_row_index(i)]; 00109 for (j = 0; j < length; j++) 00110 { 00111 new_data(ptr_count + j) = data[ptr[prev_row_index(i)] + j]; 00112 new_ind(ptr_count + j) = ind[ptr[prev_row_index(i)] + j]; 00113 } 00114 new_ptr(i) = ptr_count; 00115 ptr_count += length; 00116 } 00117 new_ptr(m) = ptr_count; 00118 00119 A.SetData(m, n, new_data, new_ptr, new_ind); 00120 } 00121 00122 00124 00128 template<class T, class Prop, class Allocator> 00129 void ApplyInversePermutation(Matrix<T, Prop, ColSparse, Allocator>& A, 00130 const Vector<int>& row_perm, 00131 const Vector<int>& col_perm) 00132 { 00133 int i, j, k, l, nnz; 00134 int m = A.GetM(); 00135 int n = A.GetN(); 00136 int* ind = A.GetInd(); 00137 int* ptr = A.GetPtr(); 00138 T* data = A.GetData(); 00139 00140 /*** Permutation of the rows ***/ 00141 00142 Vector<T, VectFull, Allocator> col_data; 00143 // Row indexes of a given column. 00144 Vector<int> col_index; 00145 for (i = 0; i < n; i++) 00146 if ((nnz = ptr[i + 1] - ptr[i]) != 0) 00147 { 00148 col_index.Reallocate(nnz); 00149 col_data.Reallocate(nnz); 00150 for (k = 0, l = ptr[i]; k < nnz; k++, l++) 00151 { 00152 // Applies the permutation on the rows. 00153 col_index(k) = row_perm(ind[l]); 00154 col_data(k) = data[l]; 00155 } 00156 00157 // The rows must remain in increasing order. 00158 Sort(col_index, col_data); 00159 00160 // Putting back the data into the array. 00161 for (k = 0, l = ptr[i]; k < nnz; k++, l++) 00162 { 00163 ind[l] = col_index(k); 00164 data[l] = col_data(k); 00165 } 00166 } 00167 col_index.Clear(); 00168 col_data.Clear(); 00169 00170 /*** Perturbation of the columns ***/ 00171 00172 // Total number of non-zero elements. 00173 nnz = ptr[n]; 00174 00175 // 'col_perm' is const, so it must be copied. 00176 Vector<int> col_permutation(col_perm); 00177 // Column indexes in the origin matrix: prev_col_index(i) should be the 00178 // location of the i-th column (from the permuted matrix) in the matrix 00179 // before permutation. 00180 Vector<int> prev_col_index(n); 00181 prev_col_index.Fill(); 00182 00183 Sort(col_permutation, prev_col_index); 00184 col_permutation.Clear(); 00185 00186 // Description of the matrix after permutations. 00187 Vector<int, VectFull, CallocAlloc<int> > new_ptr(n + 1); 00188 Vector<int, VectFull, CallocAlloc<int> > new_ind(nnz); 00189 Vector<T, VectFull, Allocator> new_data(nnz); 00190 00191 int ptr_count = 0, length; 00192 for (i = 0; i < n; i++) 00193 { 00194 length = ptr[prev_col_index(i) + 1] - ptr[prev_col_index(i)]; 00195 for (j = 0; j < length; j++) 00196 { 00197 new_data(ptr_count + j) = data[ptr[prev_col_index(i)] + j]; 00198 new_ind(ptr_count + j) = ind[ptr[prev_col_index(i)] + j]; 00199 } 00200 new_ptr(i) = ptr_count; 00201 ptr_count += length; 00202 } 00203 new_ptr(n) = ptr_count; 00204 00205 A.SetData(m, n, new_data, new_ptr, new_ind); 00206 } 00207 00208 00210 00214 template<class T, class Prop, class Allocator> 00215 void ApplyInversePermutation(Matrix<T, Prop, ArrayRowSparse, Allocator>& A, 00216 const IVect& row_perm, const IVect& col_perm) 00217 { 00218 int m = A.GetM(), n, i, i_, j, i2; 00219 IVect ind_tmp, iperm(m), rperm(m); 00220 for (i = 0; i < m; i++) 00221 { 00222 iperm(i) = i; 00223 rperm(i) = i; 00224 } 00225 // A(rperm(i),:) will be the place where is the initial row i. 00226 00227 // Algorithm avoiding the allocation of another matrix. 00228 for (i = 0; i < m; i++) 00229 { 00230 // We get the index of row where the row initially placed on row i is. 00231 i2 = rperm(i); 00232 // We get the new index of this row. 00233 i_ = row_perm(i); 00234 00235 // We fill ind_tmp of the permuted indices of columns of row i. 00236 n = A.GetRowSize(i2); 00237 ind_tmp.Reallocate(n); 00238 for (j = 0; j < n; j++) 00239 ind_tmp(j) = col_perm(A.Index(i2,j)); 00240 00241 // We swap the two rows i and its destination row_perm(i). 00242 A.SwapRow(i2, i_); 00243 A.ReplaceIndexRow(i_, ind_tmp); 00244 00245 // We update the indices iperm and rperm in order to keep in memory 00246 // the place where the row row_perm(i) is. 00247 int i_tmp = iperm(i_); 00248 iperm(i_) = iperm(i2); 00249 iperm(i2) = i_tmp; 00250 rperm(iperm(i_)) = i_; 00251 rperm(iperm(i2)) = i2; 00252 00253 // We assemble the row i. 00254 A.AssembleRow(i_); 00255 } 00256 } 00257 00258 00260 00264 template<class T, class Prop, class Allocator> 00265 void 00266 ApplyInversePermutation(Matrix<T, Prop, ArrayColSymSparse, Allocator>& A, 00267 const IVect& row_perm, const IVect& col_perm) 00268 { 00269 // It is assumed that the permuted matrix is still symmetric! For example, 00270 // the user can provide row_perm = col_perm. 00271 int m = A.GetM(); 00272 int nnz = A.GetDataSize(); 00273 IVect IndRow(nnz), IndCol(nnz); 00274 Vector<T, VectFull, Allocator> Val(nnz); 00275 00276 // First we convert the matrix in coordinate format and we permute the 00277 // indices. 00278 // IndRow -> indices of the permuted rows 00279 // IndCol -> indices of the permuted columns 00280 int k = 0; 00281 for (int i = 0; i < m; i++) 00282 for (int j = 0; j < A.GetColumnSize(i); j++) 00283 { 00284 IndCol(k) = col_perm(i); 00285 Val(k) = A.Value(i,j); 00286 IndRow(k) = row_perm(A.Index(i, j)); 00287 if (IndCol(k) <= IndRow(k)) 00288 { 00289 // We store only the superior part of the symmetric matrix. 00290 int ind_tmp = IndRow(k); 00291 IndRow(k) = IndCol(k); 00292 IndCol(k) = ind_tmp; 00293 } 00294 k++; 00295 } 00296 00297 // We sort with respect to column numbers. 00298 Sort(nnz, IndCol, IndRow, Val); 00299 00300 // A is filled. 00301 k = 0; 00302 for (int i = 0; i < m; i++) 00303 { 00304 int first_index = k; 00305 // We get the size of the column i. 00306 while (k < nnz && IndCol(k) <= i) 00307 k++; 00308 00309 int size_column = k - first_index; 00310 // If column not empty. 00311 if (size_column > 0) 00312 { 00313 A.ReallocateColumn(i, size_column); 00314 k = first_index; 00315 Sort(k, k+size_column-1, IndRow, Val); 00316 for (int j = 0; j < size_column; j++) 00317 { 00318 A.Index(i,j) = IndRow(k); 00319 A.Value(i,j) = Val(k); 00320 k++; 00321 } 00322 } 00323 else 00324 A.ClearColumn(i); 00325 } 00326 } 00327 00328 00330 00334 template<class T, class Prop, class Allocator> 00335 void ApplyInversePermutation(Matrix<T, Prop, 00336 ArrayRowSymComplexSparse, Allocator>& A, 00337 const IVect& row_perm,const IVect& col_perm) 00338 { 00339 // It is assumed that the permuted matrix is still symmetric! For example, 00340 // the user can provide row_perm = col_perm. 00341 int m = A.GetM(); 00342 int nnz_real = A.GetRealDataSize(), nnz_imag = A.GetImagDataSize(); 00343 IVect IndRow(nnz_real), IndCol(nnz_real); 00344 Vector<T, VectFull, Allocator> Val(nnz_real); 00345 00346 // First we convert the matrix in coordinate format and we permute the 00347 // indices. 00348 // IndRow -> indices of the permuted rows 00349 // IndCol -> indices of the permuted columns 00350 int k = 0; 00351 for (int i = 0; i < m; i++) 00352 { 00353 for (int j = 0; j < A.GetRealRowSize(i); j++) 00354 { 00355 IndRow(k) = row_perm(i); 00356 Val(k) = A.ValueReal(i,j); 00357 IndCol(k) = col_perm(A.IndexReal(i, j)); 00358 if (IndCol(k) <= IndRow(k)) 00359 { 00360 // We store only the superior part of the symmetric matrix. 00361 int ind_tmp = IndRow(k); 00362 IndRow(k) = IndCol(k); 00363 IndCol(k) = ind_tmp; 00364 } 00365 k++; 00366 } 00367 } 00368 00369 // We sort by row number. 00370 Sort(nnz_real, IndRow, IndCol, Val); 00371 00372 // A is filled. 00373 k = 0; 00374 for (int i = 0; i < m; i++) 00375 { 00376 int first_index = k; 00377 // We get the size of the row i. 00378 while (k < nnz_real && IndRow(k) <= i) 00379 k++; 00380 00381 int size_row = k - first_index; 00382 // If row not empty. 00383 if (size_row > 0) 00384 { 00385 A.ReallocateRealRow(i, size_row); 00386 k = first_index; 00387 Sort(k, k+size_row-1, IndCol, Val); 00388 for (int j = 0; j < size_row; j++) 00389 { 00390 A.IndexReal(i,j) = IndCol(k); 00391 A.ValueReal(i,j) = Val(k); 00392 k++; 00393 } 00394 } 00395 else 00396 A.ClearRealRow(i); 00397 } 00398 00399 // Same procedure for imaginary part. 00400 00401 IndRow.Reallocate(nnz_imag); 00402 IndCol.Reallocate(nnz_imag); 00403 Val.Reallocate(nnz_imag); 00404 00405 // First we convert the matrix in coordinate format and we permute the 00406 // indices. 00407 // IndRow -> indices of the permuted rows 00408 // IndCol -> indices of the permuted columns 00409 k = 0; 00410 for (int i = 0; i < m; i++) 00411 { 00412 for (int j = 0; j < A.GetImagRowSize(i); j++) 00413 { 00414 IndRow(k) = row_perm(i); 00415 Val(k) = A.ValueImag(i,j); 00416 IndCol(k) = col_perm(A.IndexImag(i,j)); 00417 if (IndCol(k) <= IndRow(k)) 00418 { 00419 // We store only the superior part of the symmetric matrix. 00420 int ind_tmp = IndRow(k); 00421 IndRow(k) = IndCol(k); 00422 IndCol(k) = ind_tmp; 00423 } 00424 k++; 00425 } 00426 } 00427 // We sort by row number. 00428 Sort(nnz_imag, IndRow, IndCol, Val); 00429 00430 // A is filled 00431 k = 0; 00432 for (int i = 0; i < m; i++) 00433 { 00434 int first_index = k; 00435 // We get the size of the row i. 00436 while (k < nnz_imag && IndRow(k) <= i) 00437 k++; 00438 int size_row = k - first_index; 00439 // If row not empty. 00440 if (size_row > 0) 00441 { 00442 A.ReallocateImagRow(i, size_row); 00443 k = first_index; 00444 Sort(k, k+size_row-1, IndCol, Val); 00445 for (int j = 0; j < size_row; j++) 00446 { 00447 A.IndexImag(i,j) = IndCol(k); 00448 A.ValueImag(i,j) = Val(k); 00449 k++; 00450 } 00451 } 00452 else 00453 A.ClearImagRow(i); 00454 } 00455 } 00456 00457 00459 00463 template<class T, class Prop, class Allocator> 00464 void 00465 ApplyInversePermutation(Matrix<T, Prop, ArrayRowSymSparse, Allocator>& A, 00466 const IVect& row_perm, const IVect& col_perm) 00467 { 00468 // It is assumed that the permuted matrix is still symmetric! For example, 00469 // the user can provide row_perm = col_perm. 00470 int m = A.GetM(); 00471 int nnz = A.GetDataSize(); 00472 IVect IndRow(nnz), IndCol(nnz); 00473 Vector<T,VectFull,Allocator> Val(nnz); 00474 00475 // First we convert the matrix in coordinate format and we permute the 00476 // indices. 00477 // IndRow -> indices of the permuted rows 00478 // IndCol -> indices of the permuted columns 00479 int k = 0; 00480 for (int i = 0; i < m; i++) 00481 { 00482 for (int j = 0; j < A.GetRowSize(i); j++) 00483 { 00484 IndRow(k) = row_perm(i); 00485 Val(k) = A.Value(i, j); 00486 IndCol(k) = col_perm(A.Index(i, j)); 00487 if (IndCol(k) <= IndRow(k)) 00488 { 00489 // We store only the superior part of the symmetric matrix. 00490 int ind_tmp = IndRow(k); 00491 IndRow(k) = IndCol(k); 00492 IndCol(k) = ind_tmp; 00493 } 00494 k++; 00495 } 00496 } 00497 // We sort with respect to row numbers. 00498 Sort(nnz, IndRow, IndCol, Val); 00499 00500 // A is filled. 00501 k = 0; 00502 for (int i = 0; i < m; i++) 00503 { 00504 int first_index = k; 00505 // We get the size of the row i. 00506 while (k < nnz && IndRow(k) <= i) 00507 k++; 00508 int size_row = k - first_index; 00509 // If row not empty. 00510 if (size_row > 0) 00511 { 00512 A.ReallocateRow(i, size_row); 00513 k = first_index; 00514 Sort(k, k+size_row-1, IndCol, Val); 00515 for (int j = 0; j < size_row; j++) 00516 { 00517 A.Index(i,j) = IndCol(k); 00518 A.Value(i,j) = Val(k); 00519 k++; 00520 } 00521 } 00522 else 00523 A.ClearRow(i); 00524 } 00525 } 00526 00527 00529 00532 template<class Prop, class T1, class Allocator1, 00533 class T2, class Allocator2, class T3, class Allocator3> 00534 void ScaleMatrix(Matrix<T1, Prop, ArrayRowSparse, Allocator1>& A, 00535 const Vector<T2, VectFull, Allocator2>& scale_left, 00536 const Vector<T3, VectFull, Allocator3>& scale_right) 00537 { 00538 int m = A.GetM(); 00539 for (int i = 0; i < m; i++ ) 00540 for (int j = 0; j < A.GetRowSize(i); j++ ) 00541 A.Value(i,j) *= scale_left(i) * scale_right(A.Index(i, j)); 00542 00543 } 00544 00545 00547 00550 template<class Prop, class T1, class Allocator1, 00551 class T2, class Allocator2, class T3, class Allocator3> 00552 void ScaleMatrix(Matrix<T1, Prop, ArrayRowSymSparse, Allocator1>& A, 00553 const Vector<T2, VectFull, Allocator2>& scale_left, 00554 const Vector<T3, VectFull, Allocator3>& scale_right) 00555 { 00556 int m = A.GetM(); 00557 for (int i = 0; i < m; i++ ) 00558 for (int j = 0; j < A.GetRowSize(i); j++ ) 00559 A.Value(i,j) *= scale_left(i) * scale_right(A.Index(i, j)); 00560 00561 } 00562 00563 00565 00568 template<class Prop, class T1, class Allocator1, 00569 class T2, class Allocator2, class T3, class Allocator3> 00570 void ScaleMatrix(Matrix<T1, Prop, ArrayRowSymComplexSparse, Allocator1>& A, 00571 const Vector<T2, VectFull, Allocator2>& scale_left, 00572 const Vector<T3, VectFull, Allocator3>& scale_right) 00573 { 00574 int m = A.GetM(); 00575 for (int i = 0; i < m; i++ ) 00576 { 00577 for (int j = 0; j < A.GetRealRowSize(i); j++ ) 00578 A.ValueReal(i,j) *= scale_left(i) * scale_right(A.IndexReal(i, j)); 00579 00580 for (int j = 0; j < A.GetImagRowSize(i); j++ ) 00581 A.ValueImag(i,j) *= scale_left(i) * scale_right(A.IndexImag(i, j)); 00582 } 00583 } 00584 00585 00587 00590 template<class Prop, class T1, class Allocator1, 00591 class T2, class Allocator2, class T3, class Allocator3> 00592 void ScaleMatrix(Matrix<T1, Prop, ArrayRowComplexSparse, Allocator1>& A, 00593 const Vector<T2, VectFull, Allocator2>& scale_left, 00594 const Vector<T3, VectFull, Allocator3>& scale_right) 00595 { 00596 int m = A.GetM(); 00597 for (int i = 0; i < m; i++ ) 00598 { 00599 for (int j = 0; j < A.GetRealRowSize(i); j++ ) 00600 A.ValueReal(i,j) *= scale_left(i) * scale_right(A.IndexReal(i, j)); 00601 00602 for (int j = 0; j < A.GetImagRowSize(i); j++ ) 00603 A.ValueImag(i,j) *= scale_left(i) * scale_right(A.IndexImag(i, j)); 00604 } 00605 } 00606 00607 00609 00612 template<class T1, class Allocator1, 00613 class Prop, class T2, class Allocator2> 00614 void ScaleLeftMatrix(Matrix<T1, Prop, ArrayRowSparse, Allocator1>& A, 00615 const Vector<T2, VectFull, Allocator2>& scale) 00616 { 00617 int m = A.GetM(); 00618 for (int i = 0; i < m; i++ ) 00619 for (int j = 0; j < A.GetRowSize(i); j++ ) 00620 A.Value(i,j) *= scale(i); 00621 } 00622 00623 00625 00630 template<class T1, class Allocator1, 00631 class Prop, class T2, class Allocator2> 00632 void ScaleLeftMatrix(Matrix<T1, Prop, ArrayRowSymSparse, Allocator1>& A, 00633 const Vector<T2, VectFull, Allocator2>& scale) 00634 { 00635 int m = A.GetM(); 00636 for (int i = 0; i < m; i++ ) 00637 for (int j = 0; j < A.GetRowSize(i); j++ ) 00638 A.Value(i,j) *= scale(i); 00639 } 00640 00641 00643 00648 template<class T1, class Allocator1, 00649 class Prop, class T2, class Allocator2> 00650 void ScaleLeftMatrix(Matrix<T1, Prop, ArrayRowSymComplexSparse, Allocator1>& A, 00651 const Vector<T2, VectFull, Allocator2>& scale) 00652 { 00653 int m = A.GetM(); 00654 for (int i = 0; i < m; i++ ) 00655 { 00656 for (int j = 0; j < A.GetRealRowSize(i); j++ ) 00657 A.ValueReal(i,j) *= scale(i); 00658 00659 for (int j = 0; j < A.GetImagRowSize(i); j++ ) 00660 A.ValueImag(i,j) *= scale(i); 00661 } 00662 } 00663 00664 00666 00669 template<class T1, class Allocator1, 00670 class Prop, class T2, class Allocator2> 00671 void ScaleLeftMatrix(Matrix<T1, Prop, ArrayRowComplexSparse, Allocator1>& A, 00672 const Vector<T2, VectFull, Allocator2>& scale) 00673 { 00674 int m = A.GetM(); 00675 for (int i = 0; i < m; i++ ) 00676 { 00677 for (int j = 0; j < A.GetRealRowSize(i); j++ ) 00678 A.ValueReal(i,j) *= scale(i); 00679 00680 for (int j = 0; j < A.GetImagRowSize(i); j++ ) 00681 A.ValueImag(i,j) *= scale(i); 00682 } 00683 00684 } 00685 00686 00687 } // end namespace 00688 00689 #define SELDON_FILE_PERMUTATION_SCALING_MATRIX_CXX 00690 #endif