00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
00789
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
00910 la::MulOverwrite(W_old, W_squared_inv_sqrt, W);
00911 }
00912 };
00913
00914 #endif