lin_alg.h

Go to the documentation of this file.
00001 /* MLPACK 0.2
00002  *
00003  * Copyright (c) 2008, 2009 Alexander Gray,
00004  *                          Garry Boyer,
00005  *                          Ryan Riegel,
00006  *                          Nikolaos Vasiloglou,
00007  *                          Dongryeol Lee,
00008  *                          Chip Mappus, 
00009  *                          Nishant Mehta,
00010  *                          Hua Ouyang,
00011  *                          Parikshit Ram,
00012  *                          Long Tran,
00013  *                          Wee Chin Wong
00014  *
00015  * Copyright (c) 2008, 2009 Georgia Institute of Technology
00016  *
00017  * This program is free software; you can redistribute it and/or
00018  * modify it under the terms of the GNU General Public License as
00019  * published by the Free Software Foundation; either version 2 of the
00020  * License, or (at your option) any later version.
00021  *
00022  * This program is distributed in the hope that it will be useful, but
00023  * WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  * General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU General Public License
00028  * along with this program; if not, write to the Free Software
00029  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00030  * 02110-1301, USA.
00031  */
00040 #ifndef LIN_ALG_H
00041 #define LIN_ALG_H
00042 
00043 #include "fastlib/fastlib.h"
00044 
00045 #define max_rand_i 100000
00046 
00047 
00059 namespace linalg__private {
00060 
00061 
00066   void SaveCorrectly(const char *filename, Matrix a) {
00067     Matrix a_transpose;
00068     la::TransposeInit(a, &a_transpose);
00069     data::Save(filename, a_transpose);
00070   }
00071 
00075   double ExpArg(double x, double arg) {
00076     return exp(x * arg);
00077   }
00078 
00082   double Inv(double x, double arg) {
00083     return 1 / x;
00084   }
00085 
00089   double Square(double x, double arg) {
00090     return x * x;
00091   }
00092 
00096   double SquareArg(double x, double arg) {
00097     return arg * x * x;
00098   }
00099 
00103   double TanhArg(double x, double arg) {
00104     return tanh(arg * x);
00105   }
00106 
00110   double Times(double x, double arg) {
00111     return arg * x;
00112   }
00113 
00117   double Plus(double x, double arg) {
00118     return x + arg;
00119   }
00120 
00124   double MinusArg(double x, double arg) {
00125     return x - arg;
00126   }
00127 
00131   double ArgMinus(double x, double arg) {
00132     return arg - x;
00133   }
00134 
00138   Matrix* DiagMatrixInit(index_t n, double value, Matrix *diag_matrix) {
00139     diag_matrix -> Init(n, n);
00140     diag_matrix -> SetZero();
00141     for(index_t i = 0; i < n; i++) {
00142       diag_matrix -> set(i, i, value);
00143     }
00144 
00145     return diag_matrix;
00146   }
00147 
00151   Matrix* ColVector(index_t n, double value, Matrix *col_vector) {
00152     col_vector -> Init(n, 1);
00153     col_vector -> SetAll(value);
00154   
00155     return col_vector;
00156   }
00157 
00163   Matrix* Sum(const Matrix* const A, Matrix *sum_vector) {
00164     index_t n_rows = A -> n_rows();
00165     index_t n_cols = A -> n_cols();
00166 
00167     sum_vector -> Init(1, n_cols);
00168 
00169     const double *A_col_j;
00170     for(index_t j = 0; j < n_cols; j++) {
00171       A_col_j = A -> GetColumnPtr(j);
00172       double sum = 0;
00173       for(index_t i = 0; i < n_rows; i++) {
00174         sum += A_col_j[i];
00175       }
00176       (*sum_vector).set(0, j, sum);
00177     }
00178 
00179     return sum_vector;
00180   }
00181 
00186   double Sum(Vector *v) {
00187     index_t n = v -> length();
00188 
00189     double sum = 0;
00190     for(index_t i = 0; i < n; i++) {
00191       sum += (*v)[i];
00192     }
00193 
00194     return sum;
00195   }
00196 
00203   Matrix* MatrixMapSum(double (*function)(double,double),
00204                        double arg,
00205                        const Matrix* const A,
00206                        Matrix *sum_vector) {
00207     index_t n_rows = A -> n_rows();
00208     index_t n_cols = A -> n_cols();
00209 
00210     sum_vector -> Init(1, n_cols);
00211 
00212     const double *A_col_j;
00213     for(index_t j = 0; j < n_cols; j++) {
00214       A_col_j = A -> GetColumnPtr(j);
00215       double sum = 0;
00216       for(index_t i = 0; i < n_rows; i++) {
00217         sum += function(A_col_j[i], arg);
00218       }
00219       (*sum_vector).set(0, j, sum);
00220     }
00221 
00222     return sum_vector;
00223   }
00224 
00230   double VectorMapSum(double (*function)(double,double),
00231                       double arg,
00232                       const Vector* const v) {
00233     index_t n = v -> length();
00234 
00235     double sum = 0;
00236     for(index_t i = 0; i < n; i++) {
00237       sum += function((*v)[i], arg);
00238     }
00239   
00240     return sum;
00241   }
00242 
00248   Matrix* DotMultiplyInit(const Matrix* const A, const Matrix* const B,
00249                           Matrix* C) {
00250     index_t n_rows = A -> n_rows();
00251     index_t n_cols = A -> n_cols();
00252 
00253     C -> Init(n_rows, n_cols);
00254 
00255     const double *A_col_j;
00256     const double *B_col_j;
00257     double *C_col_j;
00258     for(index_t j = 0; j < n_cols; j++) {
00259       A_col_j = A -> GetColumnPtr(j);
00260       B_col_j = B -> GetColumnPtr(j);
00261       C_col_j = C -> GetColumnPtr(j);
00262       for(index_t i = 0; i < n_rows; i++) {
00263         C_col_j[i] = A_col_j[i] * B_col_j[i];
00264       }
00265     }
00266 
00267     return C;
00268   }
00269 
00275   Matrix* DotMultiplyOverwrite(const Matrix* const A, Matrix* const B) {
00276     index_t n_rows = A -> n_rows();
00277     index_t n_cols = A -> n_cols();
00278 
00279     const double *A_col_j;
00280     double *B_col_j;
00281     for(index_t j = 0; j < n_cols; j++) {
00282       A_col_j = A -> GetColumnPtr(j);
00283       B_col_j = B -> GetColumnPtr(j);
00284       for(index_t i = 0; i < n_rows; i++) {
00285         B_col_j[i] *= A_col_j[i];
00286       }
00287     }
00288 
00289     return B;
00290   }
00291 
00297   Vector* DotMultiplyInit(const Vector* const u, const Vector* const v,
00298                           Vector* w) {
00299     index_t n = u -> length();
00300   
00301     (*w).Init(n);
00302 
00303     for(index_t i = 0; i < n; i++) {
00304       (*w)[i] = (*u)[i] * (*v)[i];
00305     }
00306 
00307     return w;
00308   }
00309 
00315   Vector* DotMultiplyOverwrite(const Vector* const u, Vector* const v) {
00316     index_t n = u -> length();
00317   
00318     for(index_t i = 0; i < n; i++) {
00319       (*v)[i] *= (*u)[i];
00320     }
00321 
00322     return v;
00323   }
00324 
00330   Matrix* DotMultiplySum(const Matrix* const A, const Matrix* const B,
00331                          Matrix* sum_vector) {
00332     index_t n_rows = A -> n_rows();
00333     index_t n_cols = A -> n_cols();
00334 
00335     sum_vector -> Init(1, n_cols);
00336 
00337     const double *A_col_j;
00338     const double *B_col_j;
00339     for(index_t j = 0; j < n_cols; j++) {
00340       A_col_j = A -> GetColumnPtr(j);
00341       B_col_j = B -> GetColumnPtr(j);
00342       double sum = 0;
00343       for(index_t i = 0; i < n_rows; i++) {
00344         sum += A_col_j[i] * B_col_j[i];
00345       }
00346       (*sum_vector).set(0, j, sum);
00347     }
00348 
00349     return sum_vector;
00350   }
00351   
00356   Matrix* VectorToDiag(const Matrix* const diag_vector, Matrix* diag_matrix) {
00357 
00358     index_t n = diag_vector -> n_cols();
00359     diag_matrix -> Init(n, n);
00360     diag_matrix -> SetZero();
00361 
00362     for(index_t i = 0; i < n; i++) {
00363       diag_matrix -> set(i, i, diag_vector -> get(0, i));
00364     }
00365 
00366     return diag_matrix;
00367   }
00368 
00373   Matrix* VectorToDiag(const Vector* const diag_vector, Matrix* diag_matrix) {
00374 
00375     diag_matrix -> InitDiagonal(*diag_vector);
00376 
00377     return diag_matrix;
00378   }
00379 
00384   Vector* DiagToVector(const Matrix* const diag_matrix, Vector* diag_vector) {
00385 
00386     index_t n = diag_matrix -> n_rows();
00387 
00388     diag_vector -> Init(n);
00389 
00390     for(index_t i = 0; i < n; i++) {
00391       (*diag_vector)[i] = diag_matrix -> get(i, i);
00392     }
00393 
00394     return diag_vector;
00395   }
00396 
00401   Matrix* Scale(double alpha, Matrix *A) {
00402     la::Scale(alpha, A);
00403     return A;
00404   }
00405 
00410   Vector* Scale(double alpha, Vector* v) {
00411     la::Scale(alpha, v);
00412     return v;
00413   }
00414 
00419   Matrix* ScaleInit(double alpha, const Matrix* const A, Matrix* B) {
00420     la::ScaleInit(alpha, *A, B);
00421     return B;
00422   }
00423 
00428   Vector* ScaleInit(double alpha, const Vector* const u, Vector* v) {
00429     la::ScaleInit(alpha, *u, v);
00430     return v;
00431   }
00432 
00437   Matrix* MulInit(const Matrix* const A, const Matrix* const B,
00438                   Matrix* const C) {
00439     la::MulInit(*A, *B, C);
00440     return C;
00441   }
00442 
00447   Vector* MulInit(const Matrix* const A, const Vector* const u,
00448                   Vector* const v) {
00449     la::MulInit(*A, *u, v);
00450     return v;
00451   }
00452 
00457   Vector* MulInit(const Vector* const u, const Matrix* const A,
00458                   Vector* const v) {
00459     la::MulInit(*u, *A, v);
00460     return v;
00461   }
00462 
00467   Matrix* MulOverwrite(const Matrix* const A, const Matrix* const B,
00468                        Matrix* const C) {
00469     la::MulOverwrite(*A, *B, C);
00470     return C;
00471   }
00472 
00477   Matrix* MulTransAInit(const Matrix* const A, const Matrix* const B,
00478                         Matrix* C) {
00479     la::MulTransAInit(*A, *B, C);
00480     return C;
00481   }
00482 
00487   Matrix* MulTransAOverwrite(const Matrix* const A, const Matrix* const B,
00488                              Matrix* const C) {
00489     la::MulTransAOverwrite(*A, *B, C);
00490     return C;
00491   }
00492 
00497   Matrix* MulTransBInit(const Matrix* const A, const Matrix* const B,
00498                         Matrix* C) {
00499     la::MulTransBInit(*A, *B, C);
00500     return C;
00501   }
00502 
00507   Matrix* MulTransBOverwrite(const Matrix* const A, Matrix* const B,
00508                              Matrix* const C) {
00509     la::MulTransBOverwrite(*A, *B, C);
00510     return C;
00511   }
00512 
00517   Matrix* SubInit(const Matrix* const A, const Matrix* const B, Matrix* C) {
00518     la::SubInit(*B, *A, C);
00519     return C;
00520   }
00521 
00526   Vector* SubInit(const Vector* const u, const Vector* const v, Vector* w) {
00527     la::SubInit(*v, *u, w);
00528     return w;
00529   }
00530 
00535   Matrix* SubOverwrite(const Matrix* const A, const Matrix* const B,
00536                        Matrix* const C) {
00537     la::SubOverwrite(*B, *A, C);
00538     return C;
00539   }
00540 
00545   Matrix* SubFrom(const Matrix* const A, Matrix* const B) {
00546     la::SubFrom(*A, B);
00547     return B;
00548   }
00549 
00554   Vector* SubFrom(const Vector* const u, Vector* const v) {
00555     la::SubFrom(*u, v);
00556     return v;
00557   }
00558 
00563   Matrix* AddTo(const Matrix* const A, Matrix* const B) {
00564     la::AddTo(*A, B);
00565     return B;
00566   }
00567 
00572   Vector* AddTo(const Vector* const u, Vector* const v) {
00573     la::AddTo(*u, v);
00574     return v;
00575   }
00576 
00581   Matrix* AddExpert(double alpha, const Matrix* const A, Matrix* const B) {
00582     la::AddExpert(alpha, *A, B);
00583 
00584     return B;
00585   }
00586 
00591   Vector* AddExpert(double alpha, const Vector* const u, Vector* const v) {
00592     la::AddExpert(alpha, *u, v);
00593 
00594     return v;
00595   }
00596 
00602   Matrix* MapOverwrite(double (*function)(double,double),
00603                        double arg,
00604                        Matrix *A) {
00605     index_t n_rows = A -> n_rows();
00606     index_t n_cols = A -> n_cols();
00607 
00608     double *A_col_j;
00609     for(index_t j = 0; j < n_cols; j++) {
00610       A_col_j = A -> GetColumnPtr(j);
00611       for(index_t i = 0; i < n_rows; i++) {
00612         A_col_j[i] = function(A_col_j[i], arg);
00613       }
00614     }
00615 
00616     return A;
00617   }
00618 
00624   Vector* MapOverwrite(double (*function)(double,double),
00625                        double arg,
00626                        Vector* const v) {
00627     index_t n = v -> length();
00628 
00629     for(index_t i = 0; i < n; i++) {
00630       (*v)[i] = function((*v)[i], arg);
00631     }
00632 
00633     return v;
00634   }
00635 
00641   Matrix* MapInit(double (*function)(double,double),
00642                   double arg,
00643                   const Matrix* const A,
00644                   Matrix *B) {
00645     index_t n_rows = A -> n_rows();
00646     index_t n_cols = A -> n_cols();
00647 
00648     B -> Init(n_rows, n_cols);
00649 
00650     const double *A_col_j;
00651     double *B_col_j;
00652     for(index_t j = 0; j < n_cols; j++) {
00653       A_col_j = A -> GetColumnPtr(j);
00654       B_col_j = B -> GetColumnPtr(j);
00655       for(index_t i = 0; i < n_rows; i++) {
00656         B_col_j[i] = function(A_col_j[i], arg);
00657       }
00658     }
00659 
00660     return B;
00661   }
00662 
00668   Vector* MapInit(double (*function)(double,double),
00669                   double arg,
00670                   const Vector* const u,
00671                   Vector *v) {
00672     index_t n = u -> length();
00673     v -> Init(n);
00674   
00675     for(index_t i = 0; i < n; i++) {
00676       (*v)[i] = function((*u)[i], arg);
00677     }
00678 
00679     return v;
00680   }
00681 
00685   void RandMatrix(index_t n_rows, index_t n_cols, Matrix *A) {
00686     A -> Init(n_rows, n_cols);
00687 
00688     for(index_t j = 0; j < n_cols; j++) {
00689       for(index_t i = 0; i < n_rows; i++) {
00690         A -> set(i, j, drand48());
00691       }
00692     }
00693   }
00694 
00698   void MakeSubMatrixByColumns(Vector column_indices, Matrix A, Matrix *A_sub) {
00699   
00700     index_t num_selected = column_indices.length();
00701 
00702     A_sub -> Init(A.n_rows(), num_selected);
00703   
00704     for(index_t i = 0; i < num_selected; i++) {
00705       index_t index = (index_t) column_indices[i];
00706       Vector A_col_index_i, A_sub_col_i;
00707       A.MakeColumnVector(index, &A_col_index_i);
00708       A_sub -> MakeColumnVector(i, &A_sub_col_i);
00709       A_sub_col_i.CopyValues(A_col_index_i);
00710     }
00711   }
00712 
00717   void Center(Matrix X, Matrix* X_centered) {
00718     Vector col_vector_sum;
00719     col_vector_sum.Init(X.n_rows());
00720     col_vector_sum.SetZero();
00721   
00722     index_t n = X.n_cols();
00723  
00724     for(index_t i = 0; i < n; i++) {
00725       Vector cur_col_vector;
00726       X.MakeColumnVector(i, &cur_col_vector);
00727       la::AddTo(cur_col_vector, &col_vector_sum);
00728     }
00729 
00730     la::Scale(1/(double) n, &col_vector_sum);
00731 
00732     X_centered -> Copy(X);
00733 
00734     for(index_t i = 0; i < n; i++) {
00735       Vector cur_col_vector;
00736       X_centered -> MakeColumnVector(i, &cur_col_vector);
00737       la::SubFrom(col_vector_sum, &cur_col_vector);
00738     }
00739 
00740   }
00741 
00747   void WhitenUsingSVD(Matrix X, Matrix* X_whitened, Matrix* whitening_matrix) {
00748   
00749     Matrix cov_X, U, VT, inv_S_matrix, temp1;
00750     Vector S_vector;
00751   
00752     Scale(1 / (double) (X.n_cols() - 1),
00753           MulTransBInit(&X, &X, &cov_X));
00754   
00755     la::SVDInit(cov_X, &S_vector, &U, &VT);
00756   
00757     index_t d = S_vector.length();
00758     inv_S_matrix.Init(d, d);
00759     inv_S_matrix.SetZero();
00760     for(index_t i = 0; i < d; i++) {
00761       double inv_sqrt_val = 1 / sqrt(S_vector[i]);
00762       inv_S_matrix.set(i, i, inv_sqrt_val);
00763     }
00764 
00765     MulTransBInit(MulTransAInit(&VT, &inv_S_matrix, &temp1),
00766                   &U,
00767                   whitening_matrix);
00768   
00769     MulInit(whitening_matrix, &X, X_whitened);
00770   
00771   }
00772 
00778   void WhitenUsingEig(Matrix X, Matrix* X_whitened, Matrix* whitening_matrix) {
00779     Matrix cov_X, D, D_inv, E;
00780     Vector D_vector;
00781 
00782     Scale(1 / (double) (X.n_cols() - 1),
00783           MulTransBInit(&X, &X, &cov_X));
00784     
00785 
00786     la::EigenvectorsInit(cov_X, &D_vector, &E);
00787 
00788     //E.set(0, 1, -E.get(0, 1));
00789     //E.set(1, 1, -E.get(1, 1));
00790 
00791     
00792 
00793     index_t d = D_vector.length();
00794     D.Init(d, d);
00795     D.SetZero();
00796     D_inv.Init(d, d);
00797     D_inv.SetZero();
00798     for(index_t i = 0; i < d; i++) {
00799       double sqrt_val = sqrt(D_vector[i]);
00800       D.set(i, i, sqrt_val);
00801       D_inv.set(i, i, 1 / sqrt_val);
00802     }
00803 
00804     la::MulTransBInit(D_inv, E, whitening_matrix);
00805     la::MulInit(*whitening_matrix, X, X_whitened);
00806   }
00807 
00811   void RandVector(Vector &v) {
00812     index_t d = v.length();
00813     v.SetZero();
00814   
00815     for(index_t i = 0; i+1 < d; i+=2) {
00816       double a = drand48();
00817       double b = drand48();
00818       double first_term = sqrt(-2 * log(a));
00819       double second_term = 2 * M_PI * b;
00820       v[i] =   first_term * cos(second_term);
00821       v[i+1] = first_term * sin(second_term);
00822     }
00823   
00824     if((d % 2) == 1) {
00825       v[d - 1] = sqrt(-2 * log(drand48())) * cos(2 * M_PI * drand48());
00826     }
00827   
00828     la::Scale(1/sqrt(la::Dot(v, v)), &v);
00829   
00830   }
00831 
00835   Matrix* RandNormalInit(index_t d, index_t n, Matrix* A) {
00836 
00837     double* A_elements = A -> ptr();
00838 
00839     index_t num_elements = d * n;
00840 
00841     for(index_t i = 0; i+1 < num_elements; i+=2) {
00842       double a = drand48();
00843       double b = drand48();
00844       double first_term = sqrt(-2 * log(a));
00845       double second_term = 2 * M_PI * b;
00846       A_elements[i] =   first_term * cos(second_term);
00847       A_elements[i+1] = first_term * sin(second_term);
00848     }
00849   
00850     if((d % 2) == 1) {
00851       A_elements[d - 1] = sqrt(-2 * log(drand48())) * cos(2 * M_PI * drand48());
00852     }
00853 
00854     return A;
00855   }
00856 
00861   Matrix* RepeatMatrix(index_t num_row_reps, index_t num_col_reps,
00862                        Matrix base_matrix, Matrix* new_matrix) {
00863 
00864     index_t num_rows = base_matrix.n_rows();
00865     index_t num_cols = base_matrix.n_cols();
00866 
00867     new_matrix -> Init(num_rows * num_row_reps, num_cols * num_col_reps);
00868   
00869     double* base_elements;
00870     double* new_elements = new_matrix -> ptr();
00871     
00872     for(index_t col_rep = 0; col_rep < num_col_reps; col_rep++) {
00873       base_elements = base_matrix.ptr();
00874       for(index_t col_num = 0; col_num < num_cols; col_num++) {
00875         for(index_t row_rep = 0; row_rep < num_row_reps; row_rep++) {
00876           memcpy(new_elements, base_elements, num_rows * sizeof(double));
00877           new_elements += num_rows;
00878         }
00879         base_elements += num_rows;
00880       }
00881     }
00882 
00883     return new_matrix;
00884   }
00885 
00890   void Orthogonalize(const Matrix W_old, Matrix *W) {
00891     Matrix W_squared, W_squared_inv_sqrt;
00892     
00893     la::MulTransAInit(W_old, W_old, &W_squared);
00894     
00895     Matrix D, E, E_times_D;
00896     Vector D_vector;
00897     
00898     la::EigenvectorsInit(W_squared, &D_vector, &E);
00899     D.InitDiagonal(D_vector);
00900     
00901     index_t d = D.n_rows();
00902     for(index_t i = 0; i < d; i++) {
00903       D.set(i, i, 1 / sqrt(D.get(i, i)));
00904     }
00905     
00906     la::MulInit(E, D, &E_times_D);
00907     la::MulTransBInit(E_times_D, E, &W_squared_inv_sqrt);
00908     
00909     // note that up until this point, W == W_old
00910     la::MulOverwrite(W_old, W_squared_inv_sqrt, W);
00911   }
00912 }; /* namespace linalg__private */
00913 
00914 #endif /* LIN_ALG_H */
Generated on Mon Jan 24 12:04:37 2011 for FASTlib by  doxygen 1.6.3