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
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
#include <cstdlib>
00042
#include "plapack.h"
00043
#include <algorithm>
00044
#include "random.h"
00045
00046
namespace PLearn {
00047
using namespace std;
00048
00049 int eigen_SymmMat(
Mat& in,
Vec& e_value,
Mat& e_vector,
int& n_evalues_found,
00050
bool compute_all,
int nb_eigen,
bool compute_vectors,
bool largest_evalues)
00051 {
00052
PLWARNING(
"eigen_SymmMat is deprecated: use eigenVecOfSymmMat or lapackEIGEN instead");
00053
00054
#ifndef USE_BLAS_SPECIALISATIONS
00055
PLERROR(
"eigen_SymmMat: LAPACK not available on this system!");
00056
return 0;
00057
#else
00058
if (!in.
isSymmetric())
00059
PLERROR(
"eigen_SymmMat: Your input matrix is not symmetric\n");
00060
00061
00062
if (nb_eigen < 1 || nb_eigen > in.
length())
00063
PLERROR(
"The number of desired eigenvalues (%d) must be in range [1,%d]", nb_eigen, in.
length());
00064
00065
if (compute_all)
00066 {
00067
if (e_vector.
length() != in.
length() || e_vector.
width() != in.
width())
00068 e_vector.
resize(in.
length(), in.
width());
00069
if (in.
length() != e_value.
length())
00070 e_value.
resize(in.
length());
00071 }
00072
else
00073 {
00074
if (e_vector.
length() != nb_eigen || e_vector.
width() != in.
width())
00075 e_vector.
resize(nb_eigen, in.
width());
00076
if (nb_eigen != e_value.
length())
00077 e_value.
resize(nb_eigen);
00078 }
00079
00080
00081
if (in.
mod() != in.
width())
00082
PLERROR(
"The input matrix cannot be a sub-matrix...");
00083
00084
00085
00086
00087
00088
int INFO = 1;
00089
if (compute_all)
00090 {
00091
char* JOBZ;
00092
if (compute_vectors)
00093 JOBZ =
"V";
00094
else
00095 JOBZ =
"N";
00096
char* UPLO =
"U";
00097
int N = in.
length();
00098
real* A = in.
data();
00099
int LDA = N;
00100
real* W =
new real[N];
00101
int LWORK = 3*N;
00102 real* WORK =
new real[LWORK];
00103
00104
00105
#ifdef USEFLOAT
00106
ssyev_(JOBZ, UPLO, &N, A, &LDA, W, WORK, &LWORK, &INFO);
00107
#endif
00108
#ifdef USEDOUBLE
00109
dsyev_(JOBZ, UPLO, &N, A, &LDA, W, WORK, &LWORK, &INFO);
00110
#endif
00111
00112
if (INFO != 0)
00113 {
00114
PLWARNING(
"eigen_SymmMat: something in ssyev got wrong. Error code %d",INFO);
00115 n_evalues_found = 0;
00116 }
00117
else
00118 {
00119 n_evalues_found = N;
00120
for (
int i=0; i<N; i++)
00121 e_value[i] = W[i];
00122
00123
if (compute_vectors)
00124 {
00125 real* p_evector = e_vector.
data();
00126 real* p_a = A;
00127
for (
int i=0; i<N; i++)
00128
for (
int j=0; j<N; j++, p_evector++, p_a++)
00129 *p_evector = *p_a;
00130 }
00131 }
00132
delete[] W;
00133
delete[] WORK;
00134 }
00135
else
00136 {
00137
char* JOBZ;
00138
if (compute_vectors)
00139 JOBZ =
"V";
00140
else
00141 JOBZ =
"N";
00142
char* RANGE =
"I";
00143
char* UPLO =
"U";
00144
int N = in.
length();
00145
real* A = in.
data();
00146
int LDA = N;
00147
real VL, VU;
00148
int IL,IU;
00149
if (largest_evalues)
00150 {
00151 IL = N - nb_eigen + 1;
00152 IU = N;
00153 }
00154
else
00155 {
00156 IL = 1;
00157 IU = nb_eigen;
00158 }
00159
real ABSTOL = 1e-10;
00160
int M;
00161
real* W=
new real[N];
00162
int LDZ = N;
00163 real* Z =
new real[LDZ*nb_eigen];
00164
int LWORK = 8*N;
00165 real* WORK =
new real[LWORK];
00166
int* IWORK =
new int[5*N];
00167
int* IFAIL =
new int[N];
00168
00169
00170
lapack_Xsyevx_(JOBZ, RANGE, UPLO, &N, A, &LDA, &VL, &VU, &IL, &IU, &ABSTOL, &M, W, Z, &LDZ, WORK, &LWORK, IWORK, IFAIL, &INFO);
00171
00172 n_evalues_found = M;
00173
if (M != nb_eigen)
00174 cout <<
"eigen_SymmMat: something in ssyevx got wrong." <<
endl
00175 <<
"The number of eigenvalues found (" << M
00176 <<
") is different from what we asked (" << nb_eigen <<
")." <<
endl;
00177
00178
if (INFO != 0)
00179 {
00180
00181
00182
00183 }
00184
else
00185 {
00186
for (
int i=0; i<M; i++)
00187 e_value[i] = W[i];
00188
00189
if (compute_vectors)
00190 {
00191 real* p_evector = e_vector.
data();
00192 real* p_z = Z;
00193
for (
int i=0; i<M; i++)
00194
for (
int j=0; j<N; j++, p_evector++, p_z++)
00195 *p_evector = *p_z;
00196 }
00197 }
00198
delete[] W;
00199
delete[] WORK;
00200
delete[] IWORK;
00201
delete[] IFAIL;
00202 }
00203
return INFO;
00204
#endif
00205
}
00206
00207 int eigen_SymmMat_decreasing(
Mat& in,
Vec& e_value,
Mat& e_vector,
int& n_evalues_found,
00208
bool compute_all,
int nb_eigen,
bool compute_vectors,
bool largest_evalues)
00209 {
00210
PLWARNING(
"eigen_SymmMat_decreasing is deprecated: use eigenVecOfSymmMat or lapackEIGEN instead");
00211
00212
int res =
eigen_SymmMat(in, e_value, e_vector, n_evalues_found,
00213 compute_all, nb_eigen, compute_vectors, largest_evalues);
00214 e_value.
swap();
00215 e_vector.
swapUpsideDown();
00216
return res;
00217 }
00218
00219 int matInvert(
Mat& in,
Mat& inverse)
00220 {
00221
#ifndef USE_BLAS_SPECIALISATIONS
00222
PLERROR(
"eigen_SymmMat: LAPACK not available on this system!");
00223
return 0;
00224
#else
00225
00226
00227
00228
if (in.
length() != in.
width())
00229
PLERROR(
"The input matrix [%dx%d] must be square!", in.
length(), in.
width());
00230
00231
if (in.
mod() != in.
width())
00232
PLERROR(
"The input matrix cannot be a sub-matrix...");
00233
00234
int M = in.
length();
00235
int N = in.
length();
00236
real* A = in.
data();
00237
int LDA = N;
00238
int* IPIV =
new int[N];
00239
int INFO;
00240
00241
#ifdef USEFLOAT
00242
sgetrf_(&M, &N, A, &LDA, IPIV, &INFO);
00243
#endif
00244
#ifdef USEDOUBLE
00245
dgetrf_(&M, &N, A, &LDA, IPIV, &INFO);
00246
#endif
00247
00248
if (INFO != 0)
00249 {
00250 cout <<
"In matInvert: Error doing the inversion." <<
endl
00251 <<
"Check the man page of <sgetrf> with error code " << INFO
00252 <<
" for more details." <<
endl;
00253
00254
delete[] IPIV;
00255
return INFO;
00256 }
00257
00258
int LWORK = N;
00259
real* WORK =
new real[LWORK];
00260
00261
#ifdef USEFLOAT
00262
sgetri_(&N, A, &LDA, IPIV, WORK, &LWORK, &INFO);
00263
#endif
00264
#ifdef USEDOUBLE
00265
dgetri_(&N, A, &LDA, IPIV, WORK, &LWORK, &INFO);
00266
#endif
00267
00268
if (INFO != 0)
00269 {
00270 cout <<
"In matInvert: Error doing the inversion." <<
endl
00271 <<
"Check the man page of <sgetri> with error code " << INFO
00272 <<
" for more details." <<
endl;
00273
00274
delete[] IPIV;
00275
delete[] WORK;
00276
return INFO;
00277 }
00278
00279
delete[] IPIV;
00280
delete[] WORK;
00281
00282 real* p_inverse =
inverse.data();
00283 real* p_A = A;
00284
for (
int i=0; i<N; i++)
00285
for (
int j=0; j<M; j++, p_inverse++, p_A++)
00286 *p_inverse = *p_A;
00287
00288
return INFO;
00289
#endif
00290
}
00291
00292
00293 int lapackSolveLinearSystem(
Mat& At,
Mat& Bt,
TVec<int>& pivots)
00294 {
00295
#ifdef BOUNDCHECK
00296
if(At.
width() != Bt.
width())
00297
PLERROR(
"In lapackSolveLinearSystem: Incompatible dimensions");
00298
#endif
00299
00300
int INFO;
00301
#ifndef USE_BLAS_SPECIALISATIONS
00302
PLERROR(
"lapackSolveLinearSystem: can't be called unless PLearn linked with LAPACK");
00303
#else
00304
int N = At.
width();
00305
int NRHS = Bt.
length();
00306
real* Aptr = At.
data();
00307
int LDA = At.
mod();
00308
if(pivots.
length()!=N)
00309 pivots.
resize(N);
00310
int* IPIVptr = pivots.
data();
00311
real* Bptr = Bt.
data();
00312
int LDB = Bt.
mod();
00313
#ifdef USEFLOAT
00314
sgesv_(&N, &NRHS, Aptr, &LDA, IPIVptr, Bptr, &LDB, &INFO);
00315
#endif
00316
#ifdef USEDOUBLE
00317
dgesv_(&N, &NRHS, Aptr, &LDA, IPIVptr, Bptr, &LDB, &INFO);
00318
#endif
00319
#endif
00320
return INFO;
00321 }
00322
00323
00324
00325 void solveLinearSystem(
const Mat& A,
const Mat& Y,
Mat& X)
00326 {
00327
PLERROR(
"solveLinearSystem: not implemented yet");
00328 }
00329
00330
00331
00332 void solveTransposeLinearSystem(
const Mat& A,
const Mat& Y,
Mat& X)
00333 {
00334
PLERROR(
"solveTransposeLinearSystem: not implemented yet");
00335 }
00336
00337 Mat solveLinearSystem(
const Mat& A,
const Mat& B)
00338 {
00339
Mat Bt =
transpose(B);
00340
Mat At =
transpose(A);
00341
TVec<int> pivots(A.
length());
00342
int status =
lapackSolveLinearSystem(At,Bt,pivots);
00343
if(status<0)
00344
PLERROR(
"Illegal value in argument of lapackSolveLinearSystem");
00345
else if(status>0)
00346
PLERROR(
"In solveLinearSystem: The factorization has been completed, but the factor U is exactly singular, so the solution could not be computed.");
00347
return transpose(Bt);
00348 }
00349
00350 Vec solveLinearSystem(
const Mat& A,
const Vec& b)
00351 {
return solveLinearSystem(A,b.
toMat(b.
length(),1)).toVec(); }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 Vec constrainedLinearRegression(
const Mat& Xt,
const Vec& Y,
real lambda)
00376 {
00377
if(Y.
length()!=Xt.
width())
00378
PLERROR(
"In hyperplane_distance, incompatible dimensions");
00379
00380
int n = Xt.
length();
00381
Mat A(n+1,n+1);
00382
Vec b(n+1);
00383
00384
for(
int i=0; i<n; i++)
00385 {
00386 A(n,i) = 0.5;
00387 A(i,n) = 0.5;
00388 b[i] =
dot(Y,Xt(i));
00389
for(
int j=0; j<n; j++)
00390 {
00391
real dotprod =
dot(Xt(i),Xt(j));
00392
if(i!=j)
00393 A(i,j) = dotprod;
00394
else
00395 A(i,j) = dotprod + lambda;
00396 }
00397 }
00398 A(n,n) = 0.;
00399 b[n] = 0.5;
00400
00401
00402
00403
00404
00405
Vec w_and_l =
solveLinearSystem(A,b);
00406
return w_and_l.
subVec(0,n);
00407 }
00408
00409
00410
00411 Mat multivariate_normal(
const Vec& mu,
const Mat& A,
int N)
00412 {
00413
Vec e_values;
00414
Mat e_vectors;
00415
Mat A_copy = A.
copy();
00416
int nb_evalues_found;
00417
eigen_SymmMat(A_copy, e_values, e_vectors, nb_evalues_found,
true, mu.
length(),
true);
00418
Mat samples(0,mu.
length());
00419
for (
int i = 0; i < N; i++)
00420 samples.
appendRow(
multivariate_normal(mu, e_values, e_vectors));
00421
return samples;
00422 }
00423
00424 Vec multivariate_normal(
const Vec& mu,
const Mat& A)
00425 {
00426
return multivariate_normal(mu, A, 1).
toVec();
00427 }
00428
00429 Vec multivariate_normal(
const Vec& mu,
const Vec& e_values,
const Mat& e_vectors)
00430 {
00431
int n = mu.
length();
00432
Vec z(n),
x(n);
00433
for (
int i = 0; i < n; i++)
00434 z[i] =
gaussian_01();
00435
for (
int i = 0; i < n; i++)
00436 {
00437
for (
int j = 0; j < n; j++)
00438
x[i] += e_vectors[j][i] *
sqrt(e_values[j]) * z[j];
00439
x[i] += mu[i];
00440 }
00441
return x;
00442 }
00443
00444 void multivariate_normal(
Vec& x,
const Vec& mu,
const Vec& e_values,
const Mat& e_vectors,
Vec& z)
00445 {
00446
int n = mu.
length();
00447 z.
resize(n);
00448
x.resize(n);
00449
x.clear();
00450
for (
int i = 0; i < n; i++)
00451 z[i] =
gaussian_01();
00452
for (
int i = 0; i < n; i++)
00453 {
00454
for (
int j = 0; j < n; j++)
00455
x[i] += e_vectors[j][i] *
sqrt(e_values[j]) * z[j];
00456
x[i] += mu[i];
00457 }
00458 }
00459
00460 void affineNormalization(
Mat data,
Mat W,
Vec bias,
real regularizer)
00461 {
00462
int d=data.
width();
00463
Vec& mu = bias;
00464
Mat covar(d,d);
00465
computeMeanAndCovar(data,mu,covar);
00466
Vec evalues(d);
00467
if (regularizer!=0)
00468
for (
int i=0;i<d;i++)
00469 covar(i,i) += regularizer;
00470
int nev=0;
00471
eigen_SymmMat(covar,evalues,W,nev,
true,d,
true,
true);
00472
for (
int i=0;i<d;i++)
00473 W(i) *=
real(1.0 /
sqrt(evalues[i]));
00474 mu *= -
real(1.0);
00475 }
00476
00477
00478 }