matrix_sparse/Permutation_ScalingMatrix.cxx

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