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, source_position;
00106     for (i = 0; i < m; i++)
00107       {
00108         length = ptr[prev_row_index(i) + 1] - ptr[prev_row_index(i)];
00109         source_position = ptr[prev_row_index(i)];
00110         for (j = 0; j < length; j++)
00111           {
00112             new_data(ptr_count + j) = data[ptr[prev_row_index(i)] + j];
00113             new_ind(ptr_count + j) = ind[ptr[prev_row_index(i)] + j];
00114           }
00115         new_ptr(i) = ptr_count;
00116         ptr_count += length;
00117       }
00118     new_ptr(m) = ptr_count;
00119 
00120     A.SetData(m, n, new_data, new_ptr, new_ind);
00121   }
00122 
00123 
00125 
00129   template<class T, class Prop, class Allocator>
00130   void ApplyInversePermutation(Matrix<T, Prop, ColSparse, Allocator>& A,
00131                                const Vector<int>& row_perm,
00132                                const Vector<int>& col_perm)
00133   {
00134     int i, j, k, l, nnz;
00135     int m = A.GetM();
00136     int n = A.GetN();
00137     int* ind = A.GetInd();
00138     int* ptr = A.GetPtr();
00139     T* data = A.GetData();
00140 
00141     /*** Permutation of the rows ***/
00142 
00143     Vector<T, VectFull, Allocator> col_data;
00144     // Row indexes of a given column.
00145     Vector<int> col_index;
00146     for (i = 0; i < n; i++)
00147       if ((nnz = ptr[i + 1] - ptr[i]) != 0)
00148         {
00149           col_index.Reallocate(nnz);
00150           col_data.Reallocate(nnz);
00151           for (k = 0, l = ptr[i]; k < nnz; k++, l++)
00152             {
00153               // Applies the permutation on the rows.
00154               col_index(k) = row_perm(ind[l]);
00155               col_data(k) = data[l];
00156             }
00157 
00158           // The rows must remain in increasing order.
00159           Sort(col_index, col_data);
00160 
00161           // Putting back the data into the array.
00162           for (k = 0, l = ptr[i]; k < nnz; k++, l++)
00163             {
00164               ind[l] = col_index(k);
00165               data[l] = col_data(k);
00166             }
00167         }
00168     col_index.Clear();
00169     col_data.Clear();
00170 
00171     /*** Perturbation of the columns ***/
00172 
00173     // Total number of non-zero elements.
00174     nnz = ptr[n];
00175 
00176     // 'col_perm' is const, so it must be copied.
00177     Vector<int> col_permutation(col_perm);
00178     // Column indexes in the origin matrix: prev_col_index(i) should be the
00179     // location of the i-th column (from the permuted matrix) in the matrix
00180     // before permutation.
00181     Vector<int> prev_col_index(n);
00182     prev_col_index.Fill();
00183 
00184     Sort(col_permutation, prev_col_index);
00185     col_permutation.Clear();
00186 
00187     // Description of the matrix after permutations.
00188     Vector<int, VectFull, CallocAlloc<int> > new_ptr(n + 1);
00189     Vector<int, VectFull, CallocAlloc<int> > new_ind(nnz);
00190     Vector<T, VectFull, Allocator> new_data(nnz);
00191 
00192     int ptr_count = 0, length, source_position;
00193     for (i = 0; i < n; i++)
00194       {
00195         length = ptr[prev_col_index(i) + 1] - ptr[prev_col_index(i)];
00196         source_position = ptr[prev_col_index(i)];
00197         for (j = 0; j < length; j++)
00198           {
00199             new_data(ptr_count + j) = data[ptr[prev_col_index(i)] + j];
00200             new_ind(ptr_count + j) = ind[ptr[prev_col_index(i)] + j];
00201           }
00202         new_ptr(i) = ptr_count;
00203         ptr_count += length;
00204       }
00205     new_ptr(n) = ptr_count;
00206 
00207     A.SetData(m, n, new_data, new_ptr, new_ind);
00208   }
00209 
00210 
00212 
00216   template<class T, class Prop, class Allocator>
00217   void ApplyInversePermutation(Matrix<T, Prop, ArrayRowSparse, Allocator>& A,
00218                                const IVect& row_perm, const IVect& col_perm)
00219   {
00220     int m = A.GetM(), n, i, i_, j, i2;
00221     IVect ind_tmp, iperm(m), rperm(m);
00222     for (i = 0; i < m; i++)
00223       {
00224         iperm(i) = i;
00225         rperm(i) = i;
00226       }
00227     // A(rperm(i),:) will be the place where is the initial row i.
00228 
00229     // Algorithm avoiding the allocation of another matrix.
00230     for (i = 0; i < m; i++)
00231       {
00232         // We get the index of row where the row initially placed on row i is.
00233         i2 = rperm(i);
00234         // We get the new index of this row.
00235         i_ = row_perm(i);
00236 
00237         // We fill ind_tmp of the permuted indices of columns of row i.
00238         n = A.GetRowSize(i2);
00239         ind_tmp.Reallocate(n);
00240         for (j = 0; j < n; j++)
00241           ind_tmp(j) = col_perm(A.Index(i2,j));
00242 
00243         // We swap the two rows i and its destination row_perm(i).
00244         A.SwapRow(i2, i_);
00245         A.ReplaceIndexRow(i_, ind_tmp);
00246 
00247         // We update the indices iperm and rperm in order to keep in memory
00248         // the place where the row row_perm(i) is.
00249         int i_tmp = iperm(i_);
00250         iperm(i_) = iperm(i2);
00251         iperm(i2) = i_tmp;
00252         rperm(iperm(i_)) = i_;
00253         rperm(iperm(i2)) = i2;
00254 
00255         // We assemble the row i.
00256         A.AssembleRow(i_);
00257       }
00258   }
00259 
00260 
00262 
00266   template<class T, class Prop, class Allocator>
00267   void
00268   ApplyInversePermutation(Matrix<T, Prop, ArrayColSymSparse, Allocator>& A,
00269                           const IVect& row_perm, const IVect& col_perm)
00270   {
00271     // It is assumed that the permuted matrix is still symmetric! For example,
00272     // the user can provide row_perm = col_perm.
00273     int m = A.GetM();
00274     int nnz = A.GetDataSize();
00275     IVect IndRow(nnz), IndCol(nnz);
00276     Vector<T, VectFull, Allocator> Val(nnz);
00277 
00278     // First we convert the matrix in coordinate format and we permute the
00279     // indices.
00280     // IndRow -> indices of the permuted rows
00281     // IndCol -> indices of the permuted columns
00282     int k = 0;
00283     for (int i = 0; i < m; i++)
00284       for (int j = 0; j < A.GetColumnSize(i); j++)
00285         {
00286           IndCol(k) = col_perm(i);
00287           Val(k) = A.Value(i,j);
00288           IndRow(k) = row_perm(A.Index(i, j));
00289           if (IndCol(k) <= IndRow(k))
00290             {
00291               // We store only the superior part of the symmetric matrix.
00292               int ind_tmp = IndRow(k);
00293               IndRow(k) = IndCol(k);
00294               IndCol(k) = ind_tmp;
00295             }
00296           k++;
00297         }
00298 
00299     // We sort with respect to column numbers.
00300     Sort(nnz, IndCol, IndRow, Val);
00301 
00302     // A is filled.
00303     k = 0;
00304     for (int i = 0; i < m; i++)
00305       {
00306         int first_index = k;
00307         // We get the size of the column i.
00308         while (k < nnz && IndCol(k) <= i)
00309           k++;
00310 
00311         int size_column = k - first_index;
00312         // If column not empty.
00313         if (size_column > 0)
00314           {
00315             A.ReallocateColumn(i, size_column);
00316             k = first_index;
00317             Sort(k, k+size_column-1, IndRow, Val);
00318             for (int j = 0; j < size_column; j++)
00319               {
00320                 A.Index(i,j) = IndRow(k);
00321                 A.Value(i,j) = Val(k);
00322                 k++;
00323               }
00324           }
00325         else
00326           A.ClearColumn(i);
00327       }
00328   }
00329 
00330 
00332 
00336   template<class T, class Prop, class Allocator>
00337   void ApplyInversePermutation(Matrix<T, Prop,
00338                                ArrayRowSymComplexSparse, Allocator>& A,
00339                                const IVect& row_perm,const IVect& col_perm)
00340   {
00341     // It is assumed that the permuted matrix is still symmetric! For example,
00342     // the user can provide row_perm = col_perm.
00343     int m = A.GetM();
00344     int nnz_real = A.GetRealDataSize(), nnz_imag = A.GetImagDataSize();
00345     IVect IndRow(nnz_real), IndCol(nnz_real);
00346     Vector<T, VectFull, Allocator> Val(nnz_real);
00347 
00348     // First we convert the matrix in coordinate format and we permute the
00349     // indices.
00350     // IndRow -> indices of the permuted rows
00351     // IndCol -> indices of the permuted columns
00352     int k = 0;
00353     for (int i = 0; i < m; i++)
00354       {
00355         for (int j = 0; j < A.GetRealRowSize(i); j++)
00356           {
00357             IndRow(k) = row_perm(i);
00358             Val(k) = A.ValueReal(i,j);
00359             IndCol(k) = col_perm(A.IndexReal(i, j));
00360             if (IndCol(k) <= IndRow(k))
00361               {
00362                 // We store only the superior part of the symmetric matrix.
00363                 int ind_tmp = IndRow(k);
00364                 IndRow(k) = IndCol(k);
00365                 IndCol(k) = ind_tmp;
00366               }
00367             k++;
00368           }
00369       }
00370 
00371     // We sort by row number.
00372     Sort(nnz_real, IndRow, IndCol, Val);
00373 
00374     // A is filled.
00375     k = 0;
00376     for (int i = 0; i < m; i++)
00377       {
00378         int first_index = k;
00379         // We get the size of the row i.
00380         while (k < nnz_real && IndRow(k) <= i)
00381           k++;
00382 
00383         int size_row = k - first_index;
00384         // If row not empty.
00385         if (size_row > 0)
00386           {
00387             A.ReallocateRealRow(i, size_row);
00388             k = first_index;
00389             Sort(k, k+size_row-1, IndCol, Val);
00390             for (int j = 0; j < size_row; j++)
00391               {
00392                 A.IndexReal(i,j) = IndCol(k);
00393                 A.ValueReal(i,j) = Val(k);
00394                 k++;
00395               }
00396           }
00397         else
00398           A.ClearRealRow(i);
00399       }
00400 
00401     // Same procedure for imaginary part.
00402 
00403     IndRow.Reallocate(nnz_imag);
00404     IndCol.Reallocate(nnz_imag);
00405     Val.Reallocate(nnz_imag);
00406 
00407     // First we convert the matrix in coordinate format and we permute the
00408     // indices.
00409     // IndRow -> indices of the permuted rows
00410     // IndCol -> indices of the permuted columns
00411     k = 0;
00412     for (int i = 0; i < m; i++)
00413       {
00414         for (int j = 0; j < A.GetImagRowSize(i); j++)
00415           {
00416             IndRow(k) = row_perm(i);
00417             Val(k) = A.ValueImag(i,j);
00418             IndCol(k) = col_perm(A.IndexImag(i,j));
00419             if (IndCol(k) <= IndRow(k))
00420               {
00421                 // We store only the superior part of the symmetric matrix.
00422                 int ind_tmp = IndRow(k);
00423                 IndRow(k) = IndCol(k);
00424                 IndCol(k) = ind_tmp;
00425               }
00426             k++;
00427           }
00428       }
00429     // We sort by row number.
00430     Sort(nnz_imag, IndRow, IndCol, Val);
00431 
00432     // A is filled
00433     k = 0;
00434     for (int i = 0; i < m; i++)
00435       {
00436         int first_index = k;
00437         // We get the size of the row i.
00438         while (k < nnz_imag && IndRow(k) <= i)
00439           k++;
00440         int size_row = k - first_index;
00441         // If row not empty.
00442         if (size_row > 0)
00443           {
00444             A.ReallocateImagRow(i, size_row);
00445             k = first_index;
00446             Sort(k, k+size_row-1, IndCol, Val);
00447             for (int j = 0; j < size_row; j++)
00448               {
00449                 A.IndexImag(i,j) = IndCol(k);
00450                 A.ValueImag(i,j) = Val(k);
00451                 k++;
00452               }
00453           }
00454         else
00455           A.ClearImagRow(i);
00456       }
00457   }
00458 
00459 
00461 
00465   template<class T, class Prop, class Allocator>
00466   void
00467   ApplyInversePermutation(Matrix<T, Prop, ArrayRowSymSparse, Allocator>& A,
00468                           const IVect& row_perm, const IVect& col_perm)
00469   {
00470     // It is assumed that the permuted matrix is still symmetric! For example,
00471     // the user can provide row_perm = col_perm.
00472     int m = A.GetM();
00473     int nnz = A.GetDataSize();
00474     IVect IndRow(nnz), IndCol(nnz);
00475     Vector<T,VectFull,Allocator> Val(nnz);
00476 
00477     // First we convert the matrix in coordinate format and we permute the
00478     // indices.
00479     // IndRow -> indices of the permuted rows
00480     // IndCol -> indices of the permuted columns
00481     int k = 0;
00482     for (int i = 0; i < m; i++)
00483       {
00484         for (int j = 0; j < A.GetRowSize(i); j++)
00485           {
00486             IndRow(k) = row_perm(i);
00487             Val(k) = A.Value(i, j);
00488             IndCol(k) = col_perm(A.Index(i, j));
00489             if (IndCol(k) <= IndRow(k))
00490               {
00491                 // We store only the superior part of the symmetric matrix.
00492                 int ind_tmp = IndRow(k);
00493                 IndRow(k) = IndCol(k);
00494                 IndCol(k) = ind_tmp;
00495               }
00496             k++;
00497           }
00498       }
00499     // We sort with respect to row numbers.
00500     Sort(nnz, IndRow, IndCol, Val);
00501 
00502     // A is filled.
00503     k = 0;
00504     for (int i = 0; i < m; i++)
00505       {
00506         int first_index = k;
00507         // We get the size of the row i.
00508         while (k < nnz && IndRow(k) <= i)
00509           k++;
00510         int size_row = k - first_index;
00511         // If row not empty.
00512         if (size_row > 0)
00513           {
00514             A.ReallocateRow(i, size_row);
00515             k = first_index;
00516             Sort(k, k+size_row-1, IndCol, Val);
00517             for (int j = 0; j < size_row; j++)
00518               {
00519                 A.Index(i,j) = IndCol(k);
00520                 A.Value(i,j) = Val(k);
00521                 k++;
00522               }
00523           }
00524         else
00525           A.ClearRow(i);
00526       }
00527   }
00528 
00529 
00531 
00534   template<class Prop, class T1, class Allocator1,
00535            class T2, class Allocator2, class T3, class Allocator3>
00536   void ScaleMatrix(Matrix<T1, Prop, ArrayRowSparse, Allocator1>& A,
00537                    const Vector<T2, VectFull, Allocator2>& scale_left,
00538                    const Vector<T3, VectFull, Allocator3>& scale_right)
00539   {
00540     int m = A.GetM();
00541     for (int i = 0; i < m; i++ )
00542       for (int j = 0; j < A.GetRowSize(i); j++ )
00543         A.Value(i,j) *= scale_left(i) * scale_right(A.Index(i, j));
00544 
00545   }
00546 
00547 
00549 
00552   template<class Prop, class T1, class Allocator1,
00553            class T2, class Allocator2, class T3, class Allocator3>
00554   void ScaleMatrix(Matrix<T1, Prop, ArrayRowSymSparse, Allocator1>& A,
00555                    const Vector<T2, VectFull, Allocator2>& scale_left,
00556                    const Vector<T3, VectFull, Allocator3>& scale_right)
00557   {
00558     int m = A.GetM();
00559     for (int i = 0; i < m; i++ )
00560       for (int j = 0; j < A.GetRowSize(i); j++ )
00561         A.Value(i,j) *= scale_left(i) * scale_right(A.Index(i, j));
00562 
00563   }
00564 
00565 
00567 
00570   template<class Prop, class T1, class Allocator1,
00571            class T2, class Allocator2, class T3, class Allocator3>
00572   void ScaleMatrix(Matrix<T1, Prop, ArrayRowSymComplexSparse, Allocator1>& A,
00573                    const Vector<T2, VectFull, Allocator2>& scale_left,
00574                    const Vector<T3, VectFull, Allocator3>& scale_right)
00575   {
00576     int m = A.GetM();
00577     for (int i = 0; i < m; i++ )
00578       {
00579         for (int j = 0; j < A.GetRealRowSize(i); j++ )
00580           A.ValueReal(i,j) *= scale_left(i) * scale_right(A.IndexReal(i, j));
00581 
00582         for (int j = 0; j < A.GetImagRowSize(i); j++ )
00583           A.ValueImag(i,j) *= scale_left(i) * scale_right(A.IndexImag(i, j));
00584       }
00585   }
00586 
00587 
00589 
00592   template<class Prop, class T1, class Allocator1,
00593            class T2, class Allocator2, class T3, class Allocator3>
00594   void ScaleMatrix(Matrix<T1, Prop, ArrayRowComplexSparse, Allocator1>& A,
00595                    const Vector<T2, VectFull, Allocator2>& scale_left,
00596                    const Vector<T3, VectFull, Allocator3>& scale_right)
00597   {
00598     int m = A.GetM();
00599     for (int i = 0; i < m; i++ )
00600       {
00601         for (int j = 0; j < A.GetRealRowSize(i); j++ )
00602           A.ValueReal(i,j) *= scale_left(i) * scale_right(A.IndexReal(i, j));
00603 
00604         for (int j = 0; j < A.GetImagRowSize(i); j++ )
00605           A.ValueImag(i,j) *= scale_left(i) * scale_right(A.IndexImag(i, j));
00606       }
00607   }
00608 
00609 
00611 
00614   template<class T1, class Allocator1,
00615            class Prop, class T2, class Allocator2>
00616   void ScaleLeftMatrix(Matrix<T1, Prop, ArrayRowSparse, Allocator1>& A,
00617                        const Vector<T2, VectFull, Allocator2>& scale)
00618   {
00619     int m = A.GetM();
00620     for (int i = 0; i < m; i++ )
00621       for (int j = 0; j < A.GetRowSize(i); j++ )
00622         A.Value(i,j) *= scale(i);
00623   }
00624 
00625 
00627 
00632   template<class T1, class Allocator1,
00633            class Prop, class T2, class Allocator2>
00634   void ScaleLeftMatrix(Matrix<T1, Prop, ArrayRowSymSparse, Allocator1>& A,
00635                        const Vector<T2, VectFull, Allocator2>& scale)
00636   {
00637     int m = A.GetM();
00638     for (int i = 0; i < m; i++ )
00639       for (int j = 0; j < A.GetRowSize(i); j++ )
00640         A.Value(i,j) *= scale(i);
00641   }
00642 
00643 
00645 
00650   template<class T1, class Allocator1,
00651            class Prop, class T2, class Allocator2>
00652   void ScaleLeftMatrix(Matrix<T1, Prop, ArrayRowSymComplexSparse, Allocator1>& A,
00653                        const Vector<T2, VectFull, Allocator2>& scale)
00654   {
00655     int m = A.GetM();
00656     for (int i = 0; i < m; i++ )
00657       {
00658         for (int j = 0; j < A.GetRealRowSize(i); j++ )
00659           A.ValueReal(i,j) *= scale(i);
00660 
00661         for (int j = 0; j < A.GetImagRowSize(i); j++ )
00662           A.ValueImag(i,j) *= scale(i);
00663       }
00664   }
00665 
00666 
00668 
00671   template<class T1, class Allocator1,
00672            class Prop, class T2, class Allocator2>
00673   void ScaleLeftMatrix(Matrix<T1, Prop, ArrayRowComplexSparse, Allocator1>& A,
00674                        const Vector<T2, VectFull, Allocator2>& scale)
00675   {
00676     int m = A.GetM();
00677     for (int i = 0; i < m; i++ )
00678       {
00679         for (int j = 0; j < A.GetRealRowSize(i); j++ )
00680           A.ValueReal(i,j) *= scale(i);
00681 
00682         for (int j = 0; j < A.GetImagRowSize(i); j++ )
00683           A.ValueImag(i,j) *= scale(i);
00684       }
00685 
00686   }
00687 
00688 
00689 } // end namespace
00690 
00691 #define SELDON_FILE_PERMUTATION_SCALING_MATRIX_CXX
00692 #endif