PageRenderTime 48ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/toolkits/collaborative_filtering/eigen_wrapper.hpp

https://github.com/michaelkook/GraphLab-2
C++ Header | 624 lines | 560 code | 28 blank | 36 comment | 50 complexity | 00d4146167c1f0642621a7a095e20e57 MD5 | raw file
Possible License(s): ISC, Apache-2.0
  1. /**
  2. * Copyright (c) 2009 Carnegie Mellon University.
  3. * All rights reserved.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing,
  12. * software distributed under the License is distributed on an "AS
  13. * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  14. * express or implied. See the License for the specific language
  15. * governing permissions and limitations under the License.
  16. *
  17. * For more about this software visit:
  18. *
  19. * http://graphlab.org
  20. *
  21. */
  22. /**
  23. * Code by Danny Bickson, CMU
  24. */
  25. #ifndef EIGEN_WRAPPER
  26. #define EIGEN_WRAPPER
  27. /**
  28. * SET OF WRAPPER FUNCTIONS FOR EIGEN
  29. *
  30. *
  31. */
  32. #include <iostream>
  33. #include <fstream>
  34. #include <ostream>
  35. #include "Eigen/Dense"
  36. #define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
  37. #include "Eigen/Sparse"
  38. #include "Eigen/Cholesky"
  39. #include "Eigen/Eigenvalues"
  40. #include "Eigen/SVD"
  41. #define EIGEN_DONT_PARALLELIZE //eigen parallel for loop interfers with ours.
  42. using namespace Eigen;
  43. typedef MatrixXd mat;
  44. typedef VectorXd vec;
  45. typedef VectorXi ivec;
  46. typedef MatrixXi imat;
  47. typedef Matrix<size_t, Dynamic, Dynamic> matst;
  48. typedef SparseVector<double> sparse_vec;
  49. inline void debug_print_vec(const char * name,const vec& _vec, int len){
  50. printf("%s ) ", name);
  51. for (int i=0; i< len; i++)
  52. if (_vec[i] == 0)
  53. printf(" 0 ");
  54. else printf("%12.4g ", _vec[i]);
  55. printf("\n");
  56. }
  57. inline void debug_print_vec(const char * name,const double* _vec, int len){
  58. printf("%s ) ", name);
  59. for (int i=0; i< len; i++)
  60. if (_vec[i] == 0)
  61. printf(" 0 ");
  62. else printf("%12.4g ", _vec[i]);
  63. printf("\n");
  64. }
  65. mat randn1(int dx, int dy, int col);
  66. template<typename mat, typename data>
  67. inline void set_val(mat &A, int row, int col, data val){
  68. A(row, col) = val;
  69. }
  70. inline double get_val(const mat &A, int row, int col){
  71. return A(row, col);
  72. }
  73. inline int get_val(const imat &A, int row, int col){
  74. return A(row, col);
  75. }
  76. inline vec get_col(const mat& A, int col){
  77. return A.col(col);
  78. }
  79. inline vec get_row(const mat& A, int row){
  80. return A.row(row);
  81. }
  82. inline void set_col(mat& A, int col, const vec & val){
  83. A.col(col) = val;
  84. }
  85. inline void set_row(mat& A, int row, const vec & val){
  86. A.row(row) = val;
  87. }
  88. inline mat eye(int size){
  89. return mat::Identity(size, size);
  90. }
  91. inline vec ones(int size){
  92. return vec::Ones(size);
  93. }
  94. inline vec init_vec(const double * array, int size){
  95. vec ret(size);
  96. memcpy(ret.data(), array, size*sizeof(double));
  97. return ret;
  98. }
  99. inline mat init_mat(const char * string, int row, int col){
  100. mat out(row, col);
  101. char buf[2056];
  102. strcpy(buf, string);
  103. char *pch = strtok(buf," \r\n\t;");
  104. for (int i=0; i< row; i++){
  105. for (int j=0; j< col; j++){
  106. out(i,j) = atof(pch);
  107. pch = strtok (NULL, " \r\n\t;");
  108. }
  109. }
  110. return out;
  111. }
  112. inline imat init_imat(const char * string, int row, int col){
  113. imat out(row, col);
  114. char buf[2056];
  115. strcpy(buf, string);
  116. char *pch = strtok(buf," \r\n\t;");
  117. for (int i=0; i< row; i++){
  118. for (int j=0; j< col; j++){
  119. out(i,j) = atol(pch);
  120. pch = strtok (NULL, " \r\n\t;");
  121. }
  122. }
  123. return out;
  124. }
  125. inline vec init_vec(const char * string, int size){
  126. vec out(size);
  127. char buf[2056];
  128. strcpy(buf, string);
  129. char *pch = strtok (buf," \r\n\t;");
  130. int i=0;
  131. while (pch != NULL)
  132. {
  133. out(i) =atof(pch);
  134. pch = strtok (NULL, " \r\n\t;");
  135. i++;
  136. }
  137. assert(i == size);
  138. return out;
  139. }
  140. inline vec init_dbl_vec(const char * string, int size){
  141. return init_vec(string, size);
  142. }
  143. inline vec zeros(int size){
  144. return vec::Zero(size);
  145. }
  146. inline mat zeros(int rows, int cols){
  147. return mat::Zero(rows, cols);
  148. }
  149. inline vec head(const vec& v, int num){
  150. return v.head(num);
  151. }
  152. inline vec mid(const vec&v, int start, int num){
  153. return v.segment(start, std::min(num, (int)(v.size()-start)));
  154. }
  155. inline vec tail(const vec&v, int num){
  156. return v.segment(v.size() - num, num);
  157. }
  158. inline ivec head(const ivec& v, int num){
  159. return v.head(num);
  160. }
  161. inline void sort(ivec &a){
  162. std::sort(a.data(), a.data()+a.size());
  163. }
  164. inline void sort(vec & a){
  165. std::sort(a.data(), a.data()+a.size());
  166. }
  167. inline ivec sort_index(const vec&a){
  168. ivec ret(a.size());
  169. std::vector<std::pair<double,int> > D;
  170. //
  171. D.reserve(a.size());
  172. for (int i=0;i<a.size();i++)
  173. D.push_back(std::make_pair<double,int>(a.coeff(i),i));
  174. std::sort(D.begin(),D.end());
  175. for (int i=0;i<a.size();i++)
  176. {
  177. ret[i]=D[i].second;
  178. }
  179. return ret;
  180. }
  181. inline void dot2(const vec& x1, const vec& x3, mat & Q, int j, int len){
  182. for (int i=0; i< len; i++){
  183. Q(i,j) = (x1(i) * x3(i));
  184. }
  185. }
  186. inline bool ls_solve_chol(const mat &A, const vec &b, vec &result){
  187. //result = A.jacobiSvd(ComputeThinU | ComputeThinV).solve(b);
  188. result = A.ldlt().solve(b);
  189. return true;
  190. }
  191. inline bool ls_solve(const mat &A, const vec &b, vec &result){
  192. //result = A.jacobiSvd(ComputeThinU | ComputeThinV).solve(b);
  193. result = A.ldlt().solve(b);
  194. return true;
  195. }
  196. inline bool chol(mat& sigma, mat& out){
  197. out = sigma.llt().matrixLLT();
  198. return true;
  199. }
  200. inline bool backslash(const mat& A, const vec & b, vec & x){
  201. x = A.jacobiSvd(ComputeThinU | ComputeThinV).solve(b);
  202. return true;
  203. }
  204. inline mat transpose(mat & A){
  205. return A.transpose();
  206. }
  207. inline mat randn(int dx, int dy){
  208. return randn1(dx,dy,-1);
  209. }
  210. inline void set_diag(mat &A, vec & v){
  211. A.diagonal()=v;
  212. }
  213. inline mat diag(vec & v){
  214. return v.asDiagonal();
  215. }
  216. template<typename mat>
  217. inline double sumsum(const mat & A){
  218. return A.sum();
  219. }
  220. inline double norm(const mat &A, int pow=2){
  221. return A.squaredNorm();
  222. }
  223. inline mat inv(const mat&A){
  224. return A.inverse();
  225. }
  226. inline bool inv(const mat&A, mat &out){
  227. out = A.inverse();
  228. return true;
  229. }
  230. inline mat outer_product(const vec&a, const vec&b){
  231. return a*b.transpose();
  232. }
  233. //Eigen does not sort eigenvalues, as done in matlab
  234. inline bool eig_sym(const mat & T, vec & eigenvalues, mat & eigenvectors){
  235. //
  236. //Column of the returned matrix is an eigenvector corresponding to eigenvalue number as returned by eigenvalues(). The eigenvectors are normalized to have (Euclidean) norm equal to one.
  237. SelfAdjointEigenSolver<mat> solver(T);
  238. eigenvectors = solver.eigenvectors();
  239. eigenvalues = solver.eigenvalues();
  240. ivec index = sort_index(eigenvalues);
  241. sort(eigenvalues);
  242. vec eigenvalues2 = eigenvalues.reverse();
  243. mat T2 = zeros(eigenvectors.rows(), eigenvectors.cols());
  244. for (int i=0; i< eigenvectors.cols(); i++){
  245. set_col(T2, index[i], get_col(eigenvectors, i));
  246. }
  247. eigenvectors = T2;
  248. eigenvalues = eigenvalues2;
  249. return true;
  250. }
  251. inline vec elem_mult(const vec&a, const vec&b){
  252. vec ret = a;
  253. for (int i=0; i<b.size(); i++)
  254. ret(i) *= b(i);
  255. return ret;
  256. }
  257. inline sparse_vec elem_mult(const sparse_vec&a, const sparse_vec&b){
  258. return a.cwiseProduct(b);
  259. }
  260. inline double sum(const vec & a){
  261. return a.sum();
  262. }
  263. inline double min(const vec &a){
  264. return a.minCoeff();
  265. }
  266. inline double max(const vec & a){
  267. return a.maxCoeff();
  268. }
  269. inline vec randu(int size){
  270. return vec::Random(size);
  271. }
  272. inline double randu(){
  273. return vec::Random(1)(0);
  274. }
  275. inline ivec randi(int size, int from, int to){
  276. ivec ret(size);
  277. for (int i=0; i<size; i++)
  278. ret[i]= internal::random<int>(from,to);
  279. return ret;
  280. }
  281. inline int randi(int from, int to){
  282. return internal::random<int>(from,to);
  283. }
  284. inline ivec concat(const ivec&a, const ivec&b){
  285. ivec ret(a.size()+b.size());
  286. ret << a,b;
  287. return ret;
  288. }
  289. inline void del(ivec&a, int i){
  290. memcpy(a.data()+i, a.data() + i+1, (a.size() - i - 1)*sizeof(int));
  291. a.conservativeResize(a.size() - 1); //resize without deleting values!
  292. }
  293. inline mat get_cols(const mat&A, ivec & cols){
  294. mat a(A.rows(), cols.size());
  295. for (int i=0; i< cols.size(); i++)
  296. set_col(a, i, get_col(A, cols[i]));
  297. return a;
  298. }
  299. inline mat get_cols(const mat&A, int start_col, int end_col){
  300. assert(end_col > start_col);
  301. assert(end_col <= A.cols());
  302. assert(start_col >= 0);
  303. mat a(A.rows(), end_col-start_col);
  304. for (int i=0; i< end_col-start_col; i++)
  305. set_col(a, i, get_col(A, i));
  306. return a;
  307. }
  308. inline void set_val(vec & v, int pos, double val){
  309. v(pos) = val;
  310. }
  311. inline double dot(const vec&a, const vec& b){
  312. return a.dot(b);
  313. }
  314. inline vec reverse(vec& a){
  315. return a.reverse();
  316. }
  317. inline ivec reverse(ivec& a){
  318. return a.reverse();
  319. }
  320. inline const double * data(const mat &A){
  321. return A.data();
  322. }
  323. inline const int * data(const imat &A){
  324. return A.data();
  325. }
  326. inline const double * data(const vec &v){
  327. return v.data();
  328. }
  329. class it_file{
  330. std::fstream fb;
  331. public:
  332. it_file(const char * name){
  333. fb.open(name, std::fstream::in);
  334. fb.close();
  335. if (fb.fail()){
  336. fb.clear(std::fstream::failbit);
  337. fb.open(name, std::fstream::out | std::fstream::trunc );
  338. }
  339. else {
  340. fb.open(name, std::fstream::in);
  341. }
  342. if (!fb.is_open()){
  343. perror("Failed opening file ");
  344. printf("filename is: %s\n", name);
  345. assert(false);
  346. }
  347. };
  348. std::fstream & operator<<(const std::string str){
  349. int size = str.size();
  350. fb.write((char*)&size, sizeof(int));
  351. assert(!fb.fail());
  352. fb.write(str.c_str(), size);
  353. return fb;
  354. }
  355. std::fstream &operator<<(mat & A){
  356. int rows = A.rows(), cols = A.cols();
  357. fb.write( (const char*)&rows, sizeof(int));
  358. fb.write( (const char *)&cols, sizeof(int));
  359. for (int i=0; i< A.rows(); i++)
  360. for (int j=0; j< A. cols(); j++){
  361. double val = A(i,j);
  362. fb.write( (const char *)&val, sizeof(double));
  363. assert(!fb.fail());
  364. }
  365. return fb;
  366. }
  367. std::fstream &operator<<(const vec & v){
  368. int size = v.size();
  369. fb.write( (const char*)&size, sizeof(int));
  370. assert(!fb.fail());
  371. for (int i=0; i< v.size(); i++){
  372. double val = v(i);
  373. fb.write( (const char *)&val, sizeof(double));
  374. assert(!fb.fail());
  375. }
  376. return fb;
  377. }
  378. std::fstream & operator<<(const double &v){
  379. fb.write((const char*)&v, sizeof(double));
  380. return fb;
  381. }
  382. std::fstream & operator>>(std::string str){
  383. int size = -1;
  384. fb.read((char*)&size, sizeof(int));
  385. if (fb.fail() || fb.eof()){
  386. perror("Failed reading file");
  387. assert(false);
  388. }
  389. char buf[256];
  390. fb.read(buf, std::min(256,size));
  391. assert(!fb.fail());
  392. assert(!strncmp(str.c_str(), buf, std::min(256,size)));
  393. return fb;
  394. }
  395. std::fstream &operator>>(mat & A){
  396. int rows, cols;
  397. fb.read( (char *)&rows, sizeof(int));
  398. assert(!fb.fail());
  399. fb.read( (char *)&cols, sizeof(int));
  400. assert(!fb.fail());
  401. A = mat(rows, cols);
  402. double val;
  403. for (int i=0; i< A.rows(); i++)
  404. for (int j=0; j< A. cols(); j++){
  405. fb.read((char*)&val, sizeof(double));
  406. assert(!fb.fail());
  407. A(i,j) = val;
  408. }
  409. return fb;
  410. }
  411. std::fstream &operator>>(vec & v){
  412. int size;
  413. fb.read((char*)&size, sizeof(int));
  414. assert(!fb.fail());
  415. assert(size >0);
  416. v = vec(size);
  417. double val;
  418. for (int i=0; i< v.size(); i++){
  419. fb.read((char*)& val, sizeof(double));
  420. assert(!fb.fail());
  421. v(i) = val;
  422. }
  423. return fb;
  424. }
  425. std::fstream &operator>>(double &v){
  426. fb.read((char*)&v, sizeof(double));
  427. assert(!fb.fail());
  428. return fb;
  429. }
  430. void close(){
  431. fb.close();
  432. }
  433. };
  434. #define Name(a) std::string(a)
  435. inline void set_size(sparse_vec &v, int size){
  436. //did not find a way to declare vector dimension, yet
  437. }
  438. inline void set_new(sparse_vec&v, int ind, double val){
  439. v.insert(ind) = val;
  440. }
  441. inline int nnz(sparse_vec& v){
  442. return v.nonZeros();
  443. }
  444. inline int get_nz_index(sparse_vec &v, sparse_vec::InnerIterator& i){
  445. return i.index();
  446. }
  447. inline double get_nz_data(sparse_vec &v, sparse_vec::InnerIterator& i){
  448. return i.value();
  449. }
  450. #define FOR_ITERATOR(i,v) \
  451. for (sparse_vec::InnerIterator i(v); i; ++i)
  452. template<typename T>
  453. inline double sum_sqr(const T& a);
  454. template<>
  455. inline double sum_sqr<vec>(const vec & a){
  456. vec ret = a.array().pow(2);
  457. return ret.sum();
  458. }
  459. template<>
  460. inline double sum_sqr<sparse_vec>(const sparse_vec & a){
  461. double sum=0;
  462. FOR_ITERATOR(i,a){
  463. sum+= powf(i.value(),2);
  464. }
  465. return sum;
  466. }
  467. inline double trace(const mat & a){
  468. return a.trace();
  469. }
  470. inline double get_nz_data(sparse_vec &v, int i){
  471. assert(nnz(v) > i);
  472. int cnt=0;
  473. FOR_ITERATOR(j, v){
  474. if (cnt == i){
  475. return j.value();
  476. }
  477. cnt++;
  478. }
  479. return 0.0;
  480. }
  481. inline void print(sparse_vec & vec){
  482. int cnt = 0;
  483. FOR_ITERATOR(i, vec){
  484. std::cout<<get_nz_index(vec, i)<<":"<< get_nz_data(vec, i) << " ";
  485. cnt++;
  486. if (cnt >= 20)
  487. break;
  488. }
  489. std::cout<<std::endl;
  490. }
  491. inline vec pow(const vec&v, int exponent){
  492. vec ret = vec(v.size());
  493. for (int i=0; i< v.size(); i++)
  494. ret[i] = powf(v[i], exponent);
  495. return ret;
  496. }
  497. inline double dot_prod(sparse_vec &v1, sparse_vec & v2){
  498. return v1.dot(v2);
  499. }
  500. inline double dot_prod(const vec &v1, const vec & v2){
  501. return v1.dot(v2);
  502. }
  503. inline double dot_prod(sparse_vec &v1, const vec & v2){
  504. double sum = 0;
  505. for (int i=0; i< v2.size(); i++){
  506. sum+= v2[i] * v1.coeffRef(i);
  507. }
  508. return sum;
  509. }
  510. inline vec cumsum(vec& v){
  511. vec ret = v;
  512. for (int i=1; i< v.size(); i++)
  513. for (int j=0; j< i; j++)
  514. ret(i) += v(j);
  515. return ret;
  516. }
  517. inline double get_val(sparse_vec & v1, int i){ //TODO optimize performance
  518. for (sparse_vec::InnerIterator it(v1); it; ++it)
  519. if (it.index() == i)
  520. return it.value();
  521. return 0;
  522. }
  523. inline double get_val(vec & v1, int i){
  524. return v1(i);
  525. }
  526. inline void set_div(sparse_vec&v, sparse_vec::InnerIterator i, double val){
  527. v.coeffRef(i.index()) /= val;
  528. }
  529. inline sparse_vec minus(sparse_vec &v1,sparse_vec &v2){
  530. return v1-v2;
  531. }
  532. inline vec minus( sparse_vec &v1, vec &v2){
  533. vec ret = -v2;
  534. FOR_ITERATOR(i, v1){
  535. ret[i.index()] += i.value();
  536. }
  537. return ret;
  538. }
  539. inline void plus( vec &v1, sparse_vec &v2){
  540. FOR_ITERATOR(i, v2){
  541. v1[i.index()] += i.value();
  542. }
  543. }
  544. inline void minus( vec &v1, sparse_vec &v2){
  545. FOR_ITERATOR(i, v2){
  546. v1[i.index()] -= i.value();
  547. }
  548. }
  549. inline sparse_vec fabs( sparse_vec & dvec1){
  550. sparse_vec ret = dvec1;
  551. FOR_ITERATOR(i, ret){
  552. ret.coeffRef(i.index()) = fabs(i.value());
  553. }
  554. return ret;
  555. };
  556. inline vec fabs( const vec & dvec1){
  557. vec ret(dvec1.size());
  558. for (int i=0; i< dvec1.size(); i++){
  559. ret(i) = fabs(dvec1(i));
  560. }
  561. return ret;
  562. };
  563. inline double abs_sum(const mat& A){
  564. double sum =0;
  565. for (int i=0; i< A.rows(); i++)
  566. for (int j=0; j< A.cols(); j++)
  567. sum += fabs(A(i,j));
  568. return sum;
  569. }
  570. inline double abs_sum(const vec &v){
  571. double sum =0;
  572. for (int i=0; i< v.size(); i++)
  573. sum += fabs(v(i));
  574. return sum;
  575. }
  576. inline double sum(const sparse_vec &v){
  577. double sum =0;
  578. FOR_ITERATOR(i, v){
  579. sum += i.value();
  580. }
  581. return sum;
  582. }
  583. inline vec sqrt(const vec & v){
  584. vec ret(v.size());
  585. for (int i=0; i< v.size(); i++){
  586. ret[i] = std::sqrt(v(i));
  587. }
  588. return ret;
  589. }
  590. inline void svd(const mat & A, mat & U, mat & V, vec & singular_values){
  591. Eigen::JacobiSVD<mat> svdEigen(A, Eigen::ComputeFullU | Eigen::ComputeFullV);
  592. U= svdEigen.matrixU();
  593. V= svdEigen.matrixV();
  594. singular_values =svdEigen.singularValues();
  595. }
  596. #endif