HDIM  1.0.0
Packages for High Dimensional Linear Regression
generics.hpp
Go to the documentation of this file.
1 #ifndef FOS_GENERICS_H
2 #define FOS_GENERICS_H
3 
4 // C System-Headers
5 #include <fenv.h>
6 
7 #ifdef __linux__
8 #include <tgmath.h>
9 #elif _WIN32
10 #include <ctgmath>
11 #endif
12 
13 // C++ System headers
14 #include <chrono>
15 #include <fstream> // std::ifstream
16 #include <vector>
17 // Eigen Headers
18 #include <eigen3/Eigen/Dense>
19 // OpenMP
20 //
21 // Project Specific Headers
22 //
23 
28 namespace hdim {
29 
30 template < typename T >
31 T StdDev( const Eigen::Matrix< T, Eigen::Dynamic, 1 >& vect ) {
32  if( vect.size() == 0 ) {
33  return static_cast<T>( 0 );
34  }
35 
36  T K = vect( 0 );
37  T n = static_cast<T>(0.0);
38  T sum = static_cast<T>(0.0);
39  T sum_sqr = static_cast<T>(0.0);
40  T variance = static_cast<T>(0.0);
41 
42  for( unsigned int i = 0; i < vect.size() ; i ++ ) {
43 
44  n = n + static_cast<T>(1.0);
45 
46  T x = vect( i );
47 
48  sum += x - K;
49  sum_sqr += ( x - K ) * ( x - K );
50  variance = ( sum_sqr - (sum*sum)/n)/( n - static_cast<T>(1.0) );
51 
52  }
53 
54  return std::sqrt( variance );
55 }
56 
57 template < typename T >
67 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> Normalize(
68  const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& mat ) {
69 
70  auto mean = mat.colwise().mean();
71  auto std = ((mat.rowwise() - mean).array().square().colwise().sum() / (mat.rows() - 1)).sqrt();
72 
73  return (mat.rowwise() - mean).array().rowwise() / std.array();
74 }
75 
76 template< typename T >
77 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> Normalize(
78  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& mat ) {
79 
80  auto mean = mat.colwise().mean();
81  auto std = ((mat.rowwise() - mean).array().square().colwise().sum() / (mat.rows() - 1)).sqrt();
82 
83  return (mat.rowwise() - mean).array().rowwise() / std.array();
84 }
85 
86 template < typename T >
91 Eigen::Matrix<T, Eigen::Dynamic, 1 > Normalize(
92  const Eigen::Matrix<T, Eigen::Dynamic, 1 >& mat ) {
93 
94  auto mean = mat.colwise().mean();
95  auto std = ((mat.rowwise() - mean).array().square().colwise().sum() / (mat.rows() - 1)).sqrt();
96 
97  return (mat.rowwise() - mean).array().rowwise() / std.array();
98 }
99 
100 template < typename T >
105 Eigen::Matrix<T, Eigen::Dynamic, 1 > Normalize(
106  Eigen::Matrix<T, Eigen::Dynamic, 1 >& mat ) {
107 
108  auto mean = mat.colwise().mean();
109  auto std = ((mat.rowwise() - mean).array().square().colwise().sum() / (mat.rows() - 1)).sqrt();
110 
111  return (mat.rowwise() - mean).array().rowwise() / std.array();
112 }
113 
114 template< typename T >
131 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> build_matrix( unsigned int num_rows, unsigned int num_cols, T (*mat_func)(unsigned int,unsigned int) ) {
132 
133  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> mat( num_rows, num_cols );
134 
135  for( unsigned int i = 0; i < num_rows ; i ++ ) {
136 
137  for( unsigned int j = 0; j < num_cols ; j++ ) {
138  mat( i, j ) = (*mat_func)( i, j );
139  }
140  }
141 
142  return mat;
143 }
144 
145 template< typename T >
150 void sweep_matrix( Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& mat, T (*mat_func)(unsigned int,unsigned int) ) {
151 
152  for( unsigned int i = 0; i < mat.rows() ; i ++ ) {
153 
154  for( unsigned int j = 0; j < mat.cols() ; j++ ) {
155  mat( i, j ) = (*mat_func)( i, j );
156  }
157  }
158 }
159 
160 template < typename T>
169 T square( T& val ) {
170  return val * val;
171 }
172 
173 template < typename T >
198 std::vector < T > LogScaleVector( T lower_bound, T upper_bound, unsigned int num_elements ) {
199 
200  T min_elem = static_cast<T>( log10(lower_bound) );
201  T max_elem = static_cast<T>( log10(upper_bound) );
202  T delta = max_elem - min_elem;
203 
204  std::vector < T > log_space_vector;
205  log_space_vector.reserve( num_elements );
206 
207  for ( unsigned int i = 0; i < num_elements ; i ++ ) {
208 
209  T step = static_cast<T>( i )/static_cast<T>( num_elements - 1 );
210  auto lin_step = delta*step + min_elem;
211 
212  log_space_vector.push_back( static_cast<T>( std::pow( 10.0, lin_step ) ) );
213  }
214 
215  return log_space_vector;
216 }
217 
218 template < typename T >
224 struct Binarize {
225 
226  typedef T result_type;
227  T operator()( T x ) const {
228  return static_cast<T>( x == static_cast<T>( 0 ) );
229  }
230 
231 };
232 
233 template <typename T>
246 T sgn(T val) {
247  return static_cast<T>( T(0) < val ) - ( val < T(0) );
248 }
249 
250 template < typename T >
262 T pos_part( T x ) {
263  return std::max( x, static_cast<T>(0.0) );
264 }
265 
266 template < typename T >
276 T soft_threshold( T x, T y ) {
277  T sgn_T = static_cast<T>( sgn(x) );
278  return sgn_T*pos_part( std::abs(x) - y );
279 }
280 
281 template < typename T >
288 struct SoftThres {
289 
300  SoftThres( T lambda_in ) : lambda( lambda_in ) {}
301 
302  typedef T result_type;
303  T operator()( T x ) const {
304  return soft_threshold<T>( x, lambda );
305  }
306 
307  private:
308  T lambda;
309 };
310 
311 template < typename T >
315 inline T prox( T x, T lambda ) {
316  return ( std::abs(x) >= lambda )?( x - sgn( x )*lambda ):( 0 );
317 }
318 
319 template < typename T >
320 Eigen::Matrix< T, Eigen::Dynamic, 1 > soft_threshold_mat(
321  const Eigen::Matrix< T, Eigen::Dynamic, 1 >& mat,
322  const T lambda ) {
323 
324  Eigen::Matrix<T, Eigen::Dynamic, 1 > mat_x( mat.rows() );
325 
326 // #pragma omp parallel for collapse(2)
327  for( unsigned int i = 0; i < mat.rows() ; i ++ ) {
328  mat_x( i ) = prox( mat( i ), lambda );
329  }
330 
331  return mat_x;
332 }
333 
334 template < typename T >
335 struct SupportSift {
336 
337  SupportSift( T C, T r_tilde, T n ) : cut_off( std::abs( static_cast<T>( 6 )*C*r_tilde/n ) ) {}
338 
339  typedef T result_type;
340  T operator()( T x ) const {
341  return ( std::abs(x) >= cut_off )?( static_cast<T>( 1 ) ):( static_cast<T>( 0 ) );
342  }
343 
344  private:
345  T cut_off;
346 };
347 
348 template< typename T >
349 Eigen::Matrix< int, Eigen::Dynamic, 1 > GenerateSupport(
350  const Eigen::Matrix<T, Eigen::Dynamic, 1 >& coefficients,
351  T cut_off ) {
352 
353  Eigen::Matrix< int, Eigen::Dynamic, 1 > support( coefficients.rows() );
354 
355  for( unsigned int i = 0; i < coefficients.size() ; i ++ ) {
356  T x = coefficients( i );
357  support( i ) = ( std::abs( x ) >= cut_off );
358  }
359 
360  return support;
361 }
362 
363 template < typename T >
364 Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > negative_index(
365  const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& mat_in,
366  int index ) {
367 
368  unsigned int n = mat_in.rows();
369  unsigned int p = mat_in.cols();
370 
371  // MatrixT A_negative_i ( n, p - 1 );
372 
373  // if( i > 0 ) {
374  // A_negative_i << X.block( 0, 0, n, i ), X.block( 0, i + 1, n, p - i - 1 );
375  // } else {
376  // A_negative_i << X.block( 0, 1, n, p - 1 );
377  // }
378 
379  // VectorT x_negative_i( p - 1 );
380 
381  // if( i > 0 ) {
382  // x_negative_i << Beta.head( i ), Beta.segment( i + 1, p - i - 1 );
383  // } else {
384  // x_negative_i << Beta.tail( p - 1 );
385  // }
386 
387  Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > left_half = mat_in.block( 0, 0, n, index - 1 );
388  Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > right_half = mat_in.block( 0, index + 1, n, p );
389 
390  Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > out ( n, p - 1 );
391  out << left_half, right_half;
392 
393  return out;
394 }
395 
396 template < typename T >
397 T duality_gap ( const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X, \
398  const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y, \
399  const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta, \
400  T r_stats_it ) {
401 
402  //Computation of Primal Objective
403 
404  Eigen::Matrix< T, Eigen::Dynamic, 1 > error = X*Beta - Y;
405  T error_sqr_norm = error.squaredNorm();
406 
407  T f_beta = error_sqr_norm + r_stats_it*Beta.template lpNorm < 1 >();
408 
409  //Computation of Dual Objective
410 
411  //Compute dual point
412 
413  T alternative = r_stats_it /( ( 2.0*X.transpose()*error ).template lpNorm< Eigen::Infinity >() );
414  T alt_part_1 = static_cast<T>( Y.transpose()*error );
415  T alternative_0 = alt_part_1/( error_sqr_norm );
416 
417  T s = std::min( std::max( alternative, alternative_0 ), -alternative );
418 
419  Eigen::Matrix< T, Eigen::Dynamic, 1 > nu_part = ( - 2.0*s / r_stats_it ) * error + 2.0/r_stats_it*Y;
420 
421  T d_nu = 0.25*square( r_stats_it )*nu_part.squaredNorm() - Y.squaredNorm();
422 
423  return f_beta + d_nu;
424 }
425 
426 template < typename T >
427 Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > slice (
428  const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& org,
429  const std::vector< unsigned int >& indices ) {
430 
431  Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > sliced ( org.rows(), indices.size() );
432 
433  for( unsigned int j = 0 ; j < indices.size() ; j++ ) {
434  sliced.col( j ) = org.col( indices[ j ] );
435  }
436 
437  return sliced;
438 
439 }
440 
441 template < typename T >
442 Eigen::Matrix< T, Eigen::Dynamic, 1 > slice (
443  const Eigen::Matrix< T, Eigen::Dynamic, 1 >& org,
444  const std::vector< unsigned int >& indices ) {
445 
446  Eigen::Matrix< T, Eigen::Dynamic, 1 > sliced ( indices.size() );
447 
448  for( unsigned int j = 0 ; j < indices.size() ; j++ ) {
449  sliced[ j ] = org[ indices[ j ] ];
450  }
451 
452  return sliced;
453 
454 }
455 
456 }
457 
458 #endif // FOS_GENERICS_H
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > Normalize(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &mat)
Set the mean of a matrix to 0 and the standard deviation to 1.
Definition: generics.hpp:67
Definition: fos.hpp:18
T prox(T x, T lambda)
A functional equivalent of hdim::soft_threshold, but possibly faster.
Definition: generics.hpp:315
std::vector< T > LogScaleVector(T lower_bound, T upper_bound, unsigned int num_elements)
Generate a vector of logarithmically equally spaced points.
Definition: generics.hpp:198
T sgn(T val)
The sign function defined as.
Definition: generics.hpp:246
Functor to convert vector of values into support vector.
Definition: generics.hpp:224
SoftThres(T lambda_in)
Initialize proximal operator, note that the term lambda_in takes the place of &#39;y&#39; in the definition o...
Definition: generics.hpp:300
Soft Threshold functor used to apply hdim::soft_threshold to each element in a matrix or vector...
Definition: generics.hpp:288
void sweep_matrix(Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &mat, T(*mat_func)(unsigned int, unsigned int))
sweep_matrix
Definition: generics.hpp:150
T square(T &val)
Compute the square of a value.
Definition: generics.hpp:169
T soft_threshold(T x, T y)
The proximal ( soft thresholding ) operator defined as.
Definition: generics.hpp:276
T pos_part(T x)
The positive part function defined as.
Definition: generics.hpp:262
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > build_matrix(unsigned int num_rows, unsigned int num_cols, T(*mat_func)(unsigned int, unsigned int))
Generate a matrix using a function that depends on row and column indices.
Definition: generics.hpp:131