From d1afe518c11c7c49a9da002f9da403fd843f2e2b Mon Sep 17 00:00:00 2001 From: Samuel St-Jean <3030760+samuelstjean@users.noreply.github.com> Date: Thu, 22 May 2025 08:58:46 -0400 Subject: [PATCH 1/3] rename omp to ompursuit internally to prevent naming clash in c++20 --- spams/spams.py | 4 ++-- spams_wrap/spams.h | 4 ++-- spams_wrap/spams/decomp/decomp.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spams/spams.py b/spams/spams.py index 4669f2dd..62e50b9f 100644 --- a/spams/spams.py +++ b/spams/spams.py @@ -185,9 +185,9 @@ def omp(X,D,L=None,eps= None,lambda1 = None,return_reg_path = False, numThreads if str(type(lambda1)) != "": lambda1 = np.array([lambda1],dtype=X.dtype) if return_reg_path: - ((indptr,indices,data,shape),path) = spams_wrap.omp(X,D,return_reg_path,given_L,L,given_eps,eps,given_lambda1,lambda1,numThreads) + ((indptr,indices,data,shape),path) = spams_wrap.ompursuit(X,D,return_reg_path,given_L,L,given_eps,eps,given_lambda1,lambda1,numThreads) else: - (indptr,indices,data,shape) = spams_wrap.omp(X,D,return_reg_path,given_L,L,given_eps,eps,given_lambda1,lambda1,numThreads) + (indptr,indices,data,shape) = spams_wrap.ompursuit(X,D,return_reg_path,given_L,L,given_eps,eps,given_lambda1,lambda1,numThreads) alpha = ssp.csc_matrix((data,indices,indptr),shape) if return_reg_path: return (alpha,path) diff --git a/spams_wrap/spams.h b/spams_wrap/spams.h index f3e980c1..ce2a4cf4 100644 --- a/spams_wrap/spams.h +++ b/spams_wrap/spams.h @@ -279,10 +279,10 @@ SpMatrix *_omp(Matrix *X,Matrix *D,Matrix **path,bool return_reg_pat if(return_reg_path) { *path = new Matrix(K,scalar_L); (*path)->setZeros(); - omp((Matrix &)(*X),(Matrix &)(*D),(SpMatrix &)(*alpha),pL,pE,pLambda,vecL,vecEps,vecLambda,numThreads,*path); + ompursuit((Matrix &)(*X),(Matrix &)(*D),(SpMatrix &)(*alpha),pL,pE,pLambda,vecL,vecEps,vecLambda,numThreads,*path); } else { *path = NULL; - omp((Matrix &)(*X),(Matrix &)(*D),(SpMatrix &)(*alpha),pL,pE,pLambda,vecL,vecEps,vecLambda,numThreads); + ompursuit((Matrix &)(*X),(Matrix &)(*D),(SpMatrix &)(*alpha),pL,pE,pLambda,vecL,vecEps,vecLambda,numThreads); } return alpha; } diff --git a/spams_wrap/spams/decomp/decomp.h b/spams_wrap/spams/decomp/decomp.h index 2c8ccec5..a4e5f4f0 100644 --- a/spams_wrap/spams/decomp/decomp.h +++ b/spams_wrap/spams/decomp/decomp.h @@ -51,7 +51,7 @@ static char nonUnit='n'; /// * optimized for a large number of signals (precompute the Gramm matrix template -void omp(const Matrix& X, const Matrix& D, SpMatrix& spalpha, +void ompursuit(const Matrix& X, const Matrix& D, SpMatrix& spalpha, const int *L, const T* eps, const T* lambda, const bool vecL = false, const bool vecEps = false, const bool Lambda=false, const int numThreads=-1, Matrix* path = NULL); @@ -320,7 +320,7 @@ void coreSOMP(const Matrix& X, const Matrix& D, const Matrix& G, /// * optimized for a big number of signals (precompute the Gramm matrix template -void omp(const Matrix& X, const Matrix& D, SpMatrix& spalpha, +void ompursuit(const Matrix& X, const Matrix& D, SpMatrix& spalpha, const int* pL, const T* peps, const T* pLambda, const bool vecL, const bool vecEps, const bool vecLambda, const int numThreads, Matrix* path) { From 6d1d7c61b018e74c362b231b4584a4f1d22fe03f Mon Sep 17 00:00:00 2001 From: Samuel St-Jean <3030760+samuelstjean@users.noreply.github.com> Date: Thu, 22 May 2025 10:44:17 -0400 Subject: [PATCH 2/3] fix templating warning for c++20 --- spams/spams.py | 4 +- spams_wrap/spams/dictLearn/dicts.h | 89 +++--- spams_wrap/spams/linalg/linalg.h | 360 ++++++++++++------------ spams_wrap/spams/prox/fista.h | 436 ++++++++++++++--------------- 4 files changed, 444 insertions(+), 445 deletions(-) diff --git a/spams/spams.py b/spams/spams.py index 62e50b9f..4669f2dd 100644 --- a/spams/spams.py +++ b/spams/spams.py @@ -185,9 +185,9 @@ def omp(X,D,L=None,eps= None,lambda1 = None,return_reg_path = False, numThreads if str(type(lambda1)) != "": lambda1 = np.array([lambda1],dtype=X.dtype) if return_reg_path: - ((indptr,indices,data,shape),path) = spams_wrap.ompursuit(X,D,return_reg_path,given_L,L,given_eps,eps,given_lambda1,lambda1,numThreads) + ((indptr,indices,data,shape),path) = spams_wrap.omp(X,D,return_reg_path,given_L,L,given_eps,eps,given_lambda1,lambda1,numThreads) else: - (indptr,indices,data,shape) = spams_wrap.ompursuit(X,D,return_reg_path,given_L,L,given_eps,eps,given_lambda1,lambda1,numThreads) + (indptr,indices,data,shape) = spams_wrap.omp(X,D,return_reg_path,given_L,L,given_eps,eps,given_lambda1,lambda1,numThreads) alpha = ssp.csc_matrix((data,indices,indptr),shape) if return_reg_path: return (alpha,path) diff --git a/spams_wrap/spams/dictLearn/dicts.h b/spams_wrap/spams/dictLearn/dicts.h index 5a9f08c6..a2cb184e 100644 --- a/spams_wrap/spams/dictLearn/dicts.h +++ b/spams_wrap/spams/dictLearn/dicts.h @@ -1,5 +1,5 @@ -/* Software SPAMS v2.1 - Copyright 2009-2011 Julien Mairal +/* Software SPAMS v2.1 - Copyright 2009-2011 Julien Mairal * * This file is part of SPAMS. * @@ -70,7 +70,7 @@ void regul_error(char *buffer, int bufsize,const char *message) { // calculate size for(unsigned int i = 0;i < NBREGUL;i++) size += strlen(regul_table[i].name) + 1; - } + } if (size >= bufsize) { n1 = bufsize - 1; strncpy(buffer,"Invalid regularization\n",n1); @@ -90,7 +90,7 @@ void regul_error(char *buffer, int bufsize,const char *message) { template struct ParamDictLearn { public: - ParamDictLearn() : + ParamDictLearn() : mode(PENALTY), regul(FISTA::RIDGE), tol(1.e-4), @@ -131,7 +131,7 @@ template struct ParamDictLearn { updateD(true), updateW(true), updateTheta(true), - logName(NULL), + logName(NULL), iter_updateD(1) { }; ~ParamDictLearn() { delete[](logName); }; int iter; @@ -141,7 +141,7 @@ template struct ParamDictLearn { T tol; bool ista; bool fixed_step; - bool posAlpha; + bool posAlpha; constraint_type_D modeD; bool posD; mode_compute modeParam; @@ -192,17 +192,17 @@ template class Trainer { const int NUM_THREADS=-1); /// Constructor with existing structure Trainer(const Matrix& A, const Matrix& B, const Matrix& D, - const int itercount, const int batchsize, + const int itercount, const int batchsize, const int NUM_THREADS); /// train or retrain using the matrix X /* train with graph or tree */ void train(const Data& X, const ParamDictLearn& param); void train_fista(const Data& X, const ParamDictLearn& param, - const GraphStruct* graph_st = NULL, + const GraphStruct* graph_st = NULL, const TreeStruct* tree_st = NULL); void trainOffline(const Data& X, const ParamDictLearn& param); - + /// Accessors void getA(Matrix& A) const { A.copy(_A);}; void getB(Matrix& B) const { B.copy(_B);}; @@ -211,14 +211,14 @@ template class Trainer { private: /// Forbid lazy copies - explicit Trainer(const Trainer& trainer); + explicit Trainer(const Trainer& trainer); /// Forbid lazy copies Trainer& operator=(const Trainer& trainer); /// clean the dictionary void cleanDict(const Data& X, Matrix& G, const bool posD = false, - const constraint_type_D modeD = L2, const T gamma1 = 0, + const constraint_type_D modeD = L2, const T gamma1 = 0, const T gamma2 = 0, const T maxCorrel = 0.999999); @@ -238,7 +238,7 @@ template class Trainer { /// Empty constructor template Trainer::Trainer() : _k(0), _initialDict(false), - _itercount(0), _batchsize(256) { + _itercount(0), _batchsize(256) { _NUM_THREADS=1; #ifdef _OPENMP _NUM_THREADS = MIN(MAX_THREADS,omp_get_num_procs()); @@ -248,9 +248,9 @@ template Trainer::Trainer() : _k(0), _initialDict(false), /// Constructor with data template Trainer::Trainer(const int k, const - int batchsize, const int NUM_THREADS) : _k(k), - _initialDict(false), _itercount(0),_batchsize(batchsize), - _NUM_THREADS(NUM_THREADS) { + int batchsize, const int NUM_THREADS) : _k(k), + _initialDict(false), _itercount(0),_batchsize(batchsize), + _NUM_THREADS(NUM_THREADS) { if (_NUM_THREADS == -1) { _NUM_THREADS=1; #ifdef _OPENMP @@ -260,7 +260,7 @@ template Trainer::Trainer(const int k, const }; /// Constructor with initial dictionary -template Trainer::Trainer(const Matrix& D, +template Trainer::Trainer(const Matrix& D, const int batchsize, const int NUM_THREADS) : _k(D.n()), _initialDict(true),_itercount(0),_batchsize(batchsize), _NUM_THREADS(NUM_THREADS) { @@ -277,7 +277,7 @@ template Trainer::Trainer(const Matrix& D, /// Constructor with existing structure template Trainer::Trainer(const Matrix& A, const Matrix& - B, const Matrix& D, const int itercount, const int batchsize, + B, const Matrix& D, const int itercount, const int batchsize, const int NUM_THREADS) : _k(D.n()),_initialDict(true),_itercount(itercount), _batchsize(batchsize), _NUM_THREADS(NUM_THREADS) { @@ -293,7 +293,7 @@ template Trainer::Trainer(const Matrix& A, const Matrix& }; template -void Trainer::cleanDict(const Data& X, Matrix& G, +void Trainer::cleanDict(const Data& X, Matrix& G, const bool posD, const constraint_type_D modeD, const T gamma1, const T gamma2, @@ -364,9 +364,9 @@ void Trainer::train(const Data& X, const ParamDictLearn& param) { cout << "Online Dictionary Learning with exponential decay t0: " << t0 << " rho: " << rho << endl; } } - if (param.posD) + if (param.posD) cout << "Positivity constraints on D activated" << endl; - if (param.posAlpha) + if (param.posAlpha) cout << "Positivity constraints on alpha activated" << endl; if (param.modeD != L2) cout << "Sparse dictionaries, mode: " << param.modeD << ", gamma1: " << param.gamma1 << ", gamma2: " << param.gamma2 << endl; cout << "mode Alpha " << param.mode << endl; @@ -385,7 +385,7 @@ void Trainer::train(const Data& X, const ParamDictLearn& param) { const int M = X.n(); const int K = _k; const int n = X.m(); - const int L = param.mode == SPARSITY ? static_cast(param.lambda) : + const int L = param.mode == SPARSITY ? static_cast(param.lambda) : param.mode == PENALTY && param.lambda == 0 && param.lambda2 > 0 && !param.posAlpha ? K : MIN(n,K); const int batchsize= param.batch ? M : MIN(_batchsize,M); @@ -397,7 +397,7 @@ void Trainer::train(const Data& X, const ParamDictLearn& param) { flush(cout); } - if (_D.m() != n || _D.n() != K) + if (_D.m() != n || _D.n() != K) _initialDict=false; srandom(0); @@ -509,7 +509,7 @@ void Trainer::train(const Data& X, const ParamDictLearn& param) { flush(cout); } time.stop(); - if (param.iter < 0 && + if (param.iter < 0 && time.getElapsed() > T(-param.iter)) break; if (param.log) { int seconds=static_cast(floor(log(time.getElapsed())*5)); @@ -522,10 +522,10 @@ void Trainer::train(const Data& X, const ParamDictLearn& param) { } } time.start(); - + Matrix G; _D.XtX(G); - if (param.clean) + if (param.clean) this->cleanDict(X,G,param.posD, param.modeD,param.gamma1,param.gamma2); G.addDiag(MAX(param.lambda2,1e-10)); @@ -591,7 +591,7 @@ void Trainer::train(const Data& X, const ParamDictLearn& param) { } } int count2=0; - for (int k = 0; k::train(const Data& X, const ParamDictLearn& param) { Beven.scal(scal); Aodd.scal(scal); Bodd.scal(scal); - if ((_itercount > 0 && i*batchsize < M) - || (_itercount == 0 && t0 != 0 && + if ((_itercount > 0 && i*batchsize < M) + || (_itercount == 0 && t0 != 0 && i*batchsize < 10000)) { Aorig.scal(scal); Borig.scal(scal); @@ -738,7 +738,7 @@ void Trainer::train(const Data& X, const ParamDictLearn& param) { newd.normalize2(); di.copy(newd); } - } else if (param.clean && + } else if (param.clean && ((_itercount+i)*batchsize) > 10000) { _D.refCol(k,di); di.setZeros(); @@ -786,9 +786,9 @@ void Trainer::train_fista(const Data& X, const ParamDictLearn& param, cout << "Online Dictionary Learning with exponential decay t0: " << t0 << " rho: " << rho << endl; } } - if (param.posD) + if (param.posD) cout << "Positivity constraints on D activated" << endl; - if (param.posAlpha) + if (param.posAlpha) cout << "Positivity constraints on alpha activated" << endl; if (param.modeD != L2) cout << "Sparse dictionaries, mode: " << param.modeD << ", gamma1: " << param.gamma1 << ", gamma2: " << param.gamma2 << endl; cout << "mode Alpha " << param.mode << endl; @@ -807,7 +807,7 @@ void Trainer::train_fista(const Data& X, const ParamDictLearn& param, const int M = X.n(); const int K = _k; const int n = X.m(); - const int L = param.mode == SPARSITY ? static_cast(param.lambda) : + const int L = param.mode == SPARSITY ? static_cast(param.lambda) : param.mode == PENALTY && param.lambda == 0 && param.lambda2 > 0 && !param.posAlpha ? K : MIN(n,K); const int batchsize= param.batch ? M : MIN(_batchsize,M); @@ -819,7 +819,7 @@ void Trainer::train_fista(const Data& X, const ParamDictLearn& param, flush(cout); } - if (_D.m() != n || _D.n() != K) + if (_D.m() != n || _D.n() != K) _initialDict=false; srandom(0); @@ -958,7 +958,7 @@ void Trainer::train_fista(const Data& X, const ParamDictLearn& param, flush(cout); } time.stop(); - if (param.iter < 0 && + if (param.iter < 0 && time.getElapsed() > T(-param.iter)) break; if (param.log) { int seconds=static_cast(floor(log(time.getElapsed())*5)); @@ -971,10 +971,10 @@ void Trainer::train_fista(const Data& X, const ParamDictLearn& param, } } time.start(); - + // !! Matrix G; _D.XtX(G); - if (param.clean) + if (param.clean) this->cleanDict(X,G,param.posD, param.modeD,param.gamma1,param.gamma2); G.addDiag(MAX(param.lambda2,1e-10)); @@ -1038,7 +1038,7 @@ void Trainer::train_fista(const Data& X, const ParamDictLearn& param, losses[numT]->init(Xj); regularizers[numT]->reset(); // alpha.refCol(j,alphai); - FISTA::FISTA_Generic(*(losses[numT]),*(regularizers[numT]),alpha0i,alphai,optim_infoi,param_fista); + FISTA::FISTA_Generic(*(losses[numT]),*(regularizers[numT]),alpha0i,alphai,optim_infoi,param_fista); alphai.toSparse(spcoeffj); } else { if (param.mode == SPARSITY) { @@ -1051,7 +1051,7 @@ void Trainer::train_fista(const Data& X, const ParamDictLearn& param, } if(param.mode != FISTAMODE) { INTM count2=0; - for (int k = 0; k::train_fista(const Data& X, const ParamDictLearn& param, Beven.scal(scal); Aodd.scal(scal); Bodd.scal(scal); - if ((_itercount > 0 && i*batchsize < M) - || (_itercount == 0 && t0 != 0 && + if ((_itercount > 0 && i*batchsize < M) + || (_itercount == 0 && t0 != 0 && i*batchsize < 10000)) { Aorig.scal(scal); Borig.scal(scal); @@ -1199,7 +1199,7 @@ void Trainer::train_fista(const Data& X, const ParamDictLearn& param, newd.normalize2(); di.copy(newd); } - } else if (param.clean && + } else if (param.clean && ((_itercount+i)*batchsize) > 10000) { _D.refCol(k,di); di.setZeros(); @@ -1234,7 +1234,7 @@ void Trainer::train_fista(const Data& X, const ParamDictLearn& param, template -void writeLog(const Matrix& D, const T time, int iter, +void writeLog(const Matrix& D, const T time, int iter, char* name) { std::ofstream f; f.precision(12); @@ -1253,7 +1253,7 @@ void writeLog(const Matrix& D, const T time, int iter, template -void Trainer::trainOffline(const Data& X, +void Trainer::trainOffline(const Data& X, const ParamDictLearn& param) { int sparseD = param.modeD == L1L2 ? 2 : 6; @@ -1335,7 +1335,7 @@ void Trainer::trainOffline(const Data& X, for (int i = 0; i T(-J)) break; _D.XtX(G); - if (param.clean) + if (param.clean) this->cleanDict(X,G,param.posD, param.modeD,param.gamma1,param.gamma2); int j; @@ -1433,7 +1433,7 @@ void Trainer::trainOffline(const Data& X, } } _D.XtX(G); - if (param.clean) + if (param.clean) this->cleanDict(X,G,param.posD,param.modeD, param.gamma1,param.gamma2); time.printElapsed(); @@ -1447,4 +1447,3 @@ void Trainer::trainOffline(const Data& X, #endif - diff --git a/spams_wrap/spams/linalg/linalg.h b/spams_wrap/spams/linalg/linalg.h index 169735e1..8f842559 100755 --- a/spams_wrap/spams/linalg/linalg.h +++ b/spams_wrap/spams/linalg/linalg.h @@ -1,4 +1,4 @@ -/* Software SPAMS v2.1 - Copyright 2009-2011 Julien Mairal +/* Software SPAMS v2.1 - Copyright 2009-2011 Julien Mairal * * This file is part of SPAMS. * @@ -17,7 +17,7 @@ */ /* \file - * toolbox Linalg + * toolbox Linalg * * by Julien Mairal * julien.mairal@inria.fr @@ -66,12 +66,12 @@ typedef std::list< INTM > group; typedef std::list< group > list_groups; typedef std::vector< group > vector_groups; -template +template static inline bool isZero(const T lambda) { return static_cast(abs(lambda)) < 1e-99; } -template +template static inline bool isEqual(const T lambda1, const T lambda2) { return static_cast(abs(lambda1-lambda2)) < 1e-99; } @@ -145,23 +145,23 @@ template class AbstractMatrixB { const T alpha = 1.0, const T beta = 0.0) const = 0; /// perform b = alpha*A*x + beta*b, when x is sparse - virtual void mult(const SpVector& x, Vector& b, + virtual void mult(const SpVector& x, Vector& b, const T alpha = 1.0, const T beta = 0.0) const = 0; - virtual void mult(const Vector& x, Vector& b, + virtual void mult(const Vector& x, Vector& b, const T alpha = 1.0, const T beta = 0.0) const = 0; /// perform C = a*A*B + b*C, possibly transposing A or B. - virtual void mult(const Matrix& B, Matrix& C, + virtual void mult(const Matrix& B, Matrix& C, const bool transA = false, const bool transB = false, const T a = 1.0, const T b = 0.0) const = 0; - virtual void mult(const SpMatrix& B, Matrix& C, + virtual void mult(const SpMatrix& B, Matrix& C, const bool transA = false, const bool transB = false, const T a = 1.0, const T b = 0.0) const = 0; /// perform C = a*B*A + b*C, possibly transposing A or B. - virtual void multSwitch(const Matrix& B, Matrix& C, + virtual void multSwitch(const Matrix& B, Matrix& C, const bool transA = false, const bool transB = false, const T a = 1.0, const T b = 0.0) const = 0; @@ -177,8 +177,8 @@ template class AbstractMatrixB { void ridgeCG(const Vector& b, Vector& x, const T lambda, const T tol, const int itermax) const; void ridgeCG(const Vector& b, const Vector& delta, Vector& x, const T lambda, const T tol, const int itermax) const; - void ridgeCG(const Matrix& b, Matrix& x, const T lambda, const T tol, const int itermax, const int numThreads = -1) const; - void ridgeCG(const Matrix& b, const Matrix& delta, Matrix& x, const T lambda, const T tol, const int itermax, const int numThreads = -1) const; + void ridgeCG(const Matrix& b, Matrix& x, const T lambda, const T tol, const int itermax, const int numThreads = -1) const; + void ridgeCG(const Matrix& b, const Matrix& delta, Matrix& x, const T lambda, const T tol, const int itermax, const int numThreads = -1) const; virtual ~AbstractMatrixB() { }; }; @@ -247,7 +247,7 @@ template class Matrix : public Data, public AbstractMatrix, pu /// Reference the column i to i+n into the Matrix mat inline void refSubMat(INTM i, INTM n, Matrix& mat) const; /// extract a sub-matrix of a symmetric matrix - inline void subMatrixSym(const Vector& indices, + inline void subMatrixSym(const Vector& indices, Matrix& subMatrix) const; /// reference a modifiable reference to the data, DANGEROUS inline T* rawX() const { return _X; }; @@ -282,7 +282,7 @@ template class Matrix : public Data, public AbstractMatrix, pu inline void set(const T a); /// Clear the matrix inline void clear(); - /// Put white Gaussian noise in the matrix + /// Put white Gaussian noise in the matrix inline void setAleat(); /// set the matrix to the identity; inline void eye(); @@ -349,12 +349,12 @@ template class Matrix : public Data, public AbstractMatrix, pu /// using two iterations of the power method inline void eigLargestSymApprox(const Vector& u0, Vector& u) const; - /// find the eigenvector corresponding to the eivenvalue with the + /// find the eigenvector corresponding to the eivenvalue with the /// largest magnitude when the current matrix is symmetric, - /// using the power method. It - /// returns the eigenvalue. u0 is an initial guess for the + /// using the power method. It + /// returns the eigenvalue. u0 is an initial guess for the /// eigenvector. - inline T eigLargestMagnSym(const Vector& u0, + inline T eigLargestMagnSym(const Vector& u0, Vector& u) const; /// returns the value of the eigenvalue with the largest magnitude /// using the power iteration. @@ -370,17 +370,17 @@ template class Matrix : public Data, public AbstractMatrix, pu /// perform b = A'x, when x is sparse inline void multTrans(const SpVector& x, Vector& b, const T alpha =1.0, const T beta = 0.0) const; /// perform b = alpha*A*x+beta*b - inline void mult(const Vector& x, Vector& b, + inline void mult(const Vector& x, Vector& b, const T alpha = 1.0, const T beta = 0.0) const; /// perform b = alpha*A*x + beta*b, when x is sparse - inline void mult(const SpVector& x, Vector& b, + inline void mult(const SpVector& x, Vector& b, const T alpha = 1.0, const T beta = 0.0) const; /// perform C = a*A*B + b*C, possibly transposing A or B. - inline void mult(const Matrix& B, Matrix& C, + inline void mult(const Matrix& B, Matrix& C, const bool transA = false, const bool transB = false, const T a = 1.0, const T b = 0.0) const; /// perform C = a*B*A + b*C, possibly transposing A or B. - inline void multSwitch(const Matrix& B, Matrix& C, + inline void multSwitch(const Matrix& B, Matrix& C, const bool transA = false, const bool transB = false, const T a = 1.0, const T b = 0.0) const; /// perform C = A*B, when B is sparse @@ -399,7 +399,7 @@ template class Matrix : public Data, public AbstractMatrix, pu /// XXt = A*A' inline void XXt(Matrix& XXt) const; /// XXt = A*A' where A is an upper triangular matrix - inline void upperTriXXt(Matrix& XXt, + inline void upperTriXXt(Matrix& XXt, const INTM L) const; /// extract the diagonal inline void diag(Vector& d) const; @@ -508,7 +508,7 @@ template class Matrix : public Data, public AbstractMatrix, pu inline void NadarayaWatson(const Vector& ind, const T sigma); /// performs soft-thresholding of the vector inline void blockThrshold(const T nu, const INTM sizeGroup); - /// performs sparse projections of the columns + /// performs sparse projections of the columns inline void sparseProject(Matrix& out, const T thrs, const int mode = 1, const T lambda1 = 0, const T lambda2 = 0, const T lambda3 = 0, const bool pos = false, const int numThreads=-1); inline void transformFilter(); @@ -518,7 +518,7 @@ template class Matrix : public Data, public AbstractMatrix, pu inline void toSparse(SpMatrix& matrix) const; /// make a sparse copy of the current matrix inline void toSparseTrans(SpMatrix& matrixTrans); - /// make a reference of the matrix to a vector vec + /// make a reference of the matrix to a vector vec inline void toVect(Vector& vec) const; /// Accessor inline INTM V() const { return 1;}; @@ -532,7 +532,7 @@ template class Matrix : public Data, public AbstractMatrix, pu protected: /// Forbid lazy copies - explicit Matrix(const Matrix& matrix); + explicit Matrix(const Matrix& matrix); /// Forbid lazy copies Matrix& operator=(const Matrix& matrix); @@ -560,7 +560,7 @@ template class Vector { /// Constructor with existing data Vector(T* X, INTM n); /// Copy constructor - explicit Vector(const Vector& vec); + explicit Vector(const Vector& vec); /// Destructor virtual ~Vector(); @@ -611,7 +611,7 @@ template class Vector { inline void refSubVec(INTM i, INTM n, Vector& mat) const { mat.setData(_X+i,n); }; /// put a random permutation of size n (for integral vectors) - inline void randperm(int n); + inline void randperm(int n); /// put random values in the vector (White Gaussian Noise) inline void setAleat(); /// clear the vector @@ -661,15 +661,15 @@ template class Vector { inline void div(const Vector& x, const Vector& y); /// A <- x .^ 2 inline void sqr(const Vector& x); - /// A <- 1 ./ sqrt(x) + /// A <- 1 ./ sqrt(x) inline void sqr(); - /// A <- 1 ./ sqrt(A) + /// A <- 1 ./ sqrt(A) inline void Sqrt(const Vector& x); - /// A <- 1 ./ sqrt(x) + /// A <- 1 ./ sqrt(x) inline void Sqrt(); - /// A <- 1 ./ sqrt(x) + /// A <- 1 ./ sqrt(x) inline void Invsqrt(const Vector& x); - /// A <- 1 ./ sqrt(A) + /// A <- 1 ./ sqrt(A) inline void Invsqrt(); /// A <- 1./x inline void inv(const Vector& x); @@ -751,7 +751,7 @@ template class Vector { /// Conversion - /// make a sparse copy + /// make a sparse copy inline void toSparse(SpVector& vec) const; /// extract the rows of a matrix corresponding to a binary mask inline void copyMask(Vector& out, Vector& mask) const; @@ -759,7 +759,7 @@ template class Vector { private: - /// = operator, + /// = operator, Vector& operator=(const Vector& vec); /// if the data has been externally allocated @@ -848,10 +848,10 @@ template class SpMatrix : public Data, public AbstractMatrixB /// XAt <- X*A' inline void XAt(const Matrix& X, Matrix& XAt) const; /// XAt <- X(:,indices)*A(:,indices)' - inline void XAt(const Matrix& X, Matrix& XAt, + inline void XAt(const Matrix& X, Matrix& XAt, const Vector& indices) const; /// XAt <- sum_i w_i X(:,i)*A(:,i)' - inline void wXAt( const Vector& w, const Matrix& X, + inline void wXAt( const Vector& w, const Matrix& X, Matrix& XAt, const int numthreads=-1) const; inline void XtX(Matrix& XtX) const; @@ -861,17 +861,17 @@ template class SpMatrix : public Data, public AbstractMatrixB inline void multTrans(const SpVector& x, Vector& y, const T alpha = 1.0, const T beta = 0.0) const; /// perform b = alpha*A*x + beta*b, when x is sparse - inline void mult(const SpVector& x, Vector& b, + inline void mult(const SpVector& x, Vector& b, const T alpha = 1.0, const T beta = 0.0) const; /// perform b = alpha*A*x + beta*b, when x is sparse - inline void mult(const Vector& x, Vector& b, + inline void mult(const Vector& x, Vector& b, const T alpha = 1.0, const T beta = 0.0) const; /// perform C = a*A*B + b*C, possibly transposing A or B. - inline void mult(const Matrix& B, Matrix& C, + inline void mult(const Matrix& B, Matrix& C, const bool transA = false, const bool transB = false, const T a = 1.0, const T b = 0.0) const; /// perform C = a*B*A + b*C, possibly transposing A or B. - inline void multSwitch(const Matrix& B, Matrix& C, + inline void multSwitch(const Matrix& B, Matrix& C, const bool transA = false, const bool transB = false, const T a = 1.0, const T b = 0.0) const; /// perform C = a*B*A + b*C, possibly transposing A or B. @@ -919,7 +919,7 @@ template class SpMatrix : public Data, public AbstractMatrixB bool _externAlloc; /// data T* _v; - /// row indices + /// row indices INTM* _r; /// indices of the beginning of columns INTM* _pB; @@ -975,9 +975,9 @@ template class SpVector { inline T* rawX() const { return _v; }; inline INTM* rawR() const { return _r; }; - /// + /// inline INTM L() const { return _L; }; - /// + /// inline void setL(const INTM L) { _L=L; }; /// a <- a.^2 inline void sqr(); @@ -1006,7 +1006,7 @@ template class SpVector { explicit SpVector(const SpVector& vector); SpVector& operator=(const SpVector& vector); - /// external allocation + /// external allocation bool _externAlloc; /// data T* _v; @@ -1036,7 +1036,7 @@ template class ProdMatrix : public AbstractMatrix { /// set_matrices inline void setMatrices(const Matrix& D, const bool high_memory=true); - inline void setMatrices(const Matrix& D, + inline void setMatrices(const Matrix& D, const Matrix& X, const bool high_memory=true); /// compute DtX(:,i) inline void copyCol(const INTM i, Vector& DtXi) const; @@ -1070,7 +1070,7 @@ template class ProdMatrix : public AbstractMatrix { /* ************************************ - * Implementation of the class Matrix + * Implementation of the class Matrix * ************************************/ /// Constructor with existing data X of an m x n matrix @@ -1153,7 +1153,7 @@ template inline void Matrix::getData(Vector& x, const INTM i) this->copyCol(i,x); }; -template inline void Matrix::getGroup(Matrix& data, +template inline void Matrix::getGroup(Matrix& data, const vector_groups& groups, const INTM i) const { const group& gr = groups[i]; const INTM N = gr.size(); @@ -1172,7 +1172,7 @@ template inline void Matrix::refCol(INTM i, Vector& x) const x.clear(); x._X=_X+i*_m; x._n=_m; - x._externAlloc=true; + x._externAlloc=true; }; /// Reference the column i to i+n INTMo the Matrix mat @@ -1282,7 +1282,7 @@ template inline void Matrix::clear() { _externAlloc=true; }; -/// Put white Gaussian noise in the matrix +/// Put white Gaussian noise in the matrix template inline void Matrix::setAleat() { for (INTM i = 0; i<_n*_m; ++i) _X[i]=normalDistrib(); }; @@ -1307,7 +1307,7 @@ template inline void Matrix::normalize() { this->refCol(i,d); d.setAleat(); d.normalize(); - } + } } }; @@ -1318,7 +1318,7 @@ template inline void Matrix::normalize2() { if (norm > 1.0) { T invNorm=1.0/norm; cblas_scal(_m,invNorm,_X+_m*i,1); - } + } } }; @@ -1336,12 +1336,12 @@ template inline void Matrix::center() { template inline void Matrix::center_rows() { Vector mean_rows(_m); mean_rows.setZeros(); - for (INTM i = 0; i<_n; ++i) - for (INTM j = 0; j<_m; ++j) + for (INTM i = 0; i<_n; ++i) + for (INTM j = 0; j<_m; ++j) mean_rows[j] += _X[i*_m+j]; mean_rows.scal(T(1.0)/_n); - for (INTM i = 0; i<_n; ++i) - for (INTM j = 0; j<_m; ++j) + for (INTM i = 0; i<_n; ++i) + for (INTM j = 0; j<_m; ++j) _X[i*_m+j] -= mean_rows[j]; }; @@ -1546,7 +1546,7 @@ template inline void Matrix::addToCols( const Vector& cent) { Vector col; for (INTM i = 0; i<_n; ++i) { - this->refCol(i,col); + this->refCol(i,col); col.add(cent[i]); } }; @@ -1555,7 +1555,7 @@ template inline void Matrix::addVecToCols( const Vector& vec, const T a) { Vector col; for (INTM i = 0; i<_n; ++i) { - this->refCol(i,col); + this->refCol(i,col); col.add(vec,a); } }; @@ -1593,7 +1593,7 @@ template inline void Matrix::singularValues(Vector& u) const syev(no,lower,_n,XtX.rawX(),_n,u.rawX()); u.thrsPos(); u.Sqrt(); - } else if (_n > 10*_m) { + } else if (_n > 10*_m) { Matrix XXt; this->XXt(XXt); syev(no,lower,_m,XXt.rawX(),_m,u.rawX()); @@ -1623,7 +1623,7 @@ template inline void Matrix::svd(Matrix& U, Vector& S, Mat Vt.transpose(V); Vector inveigs; inveigs.copy(S); - for (INTM i = 0; i 1e-10) { inveigs[i]=T(1.0)/S[i]; } else { @@ -1638,7 +1638,7 @@ template inline void Matrix::svd(Matrix& U, Vector& S, Mat U.mult(*this,V,true,false); Vector inveigs; inveigs.copy(S); - for (INTM i = 0; i 1e-10) { inveigs[i]=T(1.0)/S[i]; } else { @@ -1693,10 +1693,10 @@ template inline void Matrix::eigLargestSymApprox( } }; -/// find the eigenvector corresponding to the eivenvalue with the +/// find the eigenvector corresponding to the eivenvalue with the /// largest magnitude when the current matrix is symmetric, -/// using the power method. It -/// returns the eigenvalue. u0 is an initial guess for the +/// using the power method. It +/// returns the eigenvalue. u0 is an initial guess for the /// eigenvector. template inline T Matrix::eigLargestMagnSym( const Vector& u0, Vector& u) const { @@ -1748,7 +1748,7 @@ template inline void Matrix::invSym() { }; /// perform b = alpha*A'x + beta*b -template inline void Matrix::multTrans(const Vector& x, +template inline void Matrix::multTrans(const Vector& x, Vector& b, const T a, const T c) const { b.resize(_n); // assert(x._n == _m && b._n == _n); @@ -1756,7 +1756,7 @@ template inline void Matrix::multTrans(const Vector& x, }; /// perform b = A'x, when x is sparse -template inline void Matrix::multTrans(const SpVector& x, +template inline void Matrix::multTrans(const SpVector& x, Vector& b, const T alpha, const T beta) const { b.resize(_n); Vector col; @@ -1788,7 +1788,7 @@ template inline void Matrix::multTrans( }; /// perform b = alpha*A*x+beta*b -template inline void Matrix::mult(const Vector& x, +template inline void Matrix::mult(const Vector& x, Vector& b, const T a, const T c) const { // assert(x._n == _n && b._n == _m); b.resize(_m); @@ -1796,7 +1796,7 @@ template inline void Matrix::mult(const Vector& x, }; /// perform b = alpha*A*x + beta*b, when x is sparse -template inline void Matrix::mult(const SpVector& x, +template inline void Matrix::mult(const SpVector& x, Vector& b, const T a, const T a2) const { if (!a2) { b.setZeros(); @@ -1815,7 +1815,7 @@ template inline void Matrix::mult(const SpVector& x, }; /// perform C = a*A*B + b*C, possibly transposing A or B. -template inline void Matrix::mult(const Matrix& B, +template inline void Matrix::mult(const Matrix& B, Matrix& C, const bool transA, const bool transB, const T a, const T b) const { CBLAS_TRANSPOSE trA,trB; @@ -1831,11 +1831,11 @@ template inline void Matrix::mult(const Matrix& B, } if (transB) { trB = CblasTrans; - n = B._m; + n = B._m; // assert(B._n == k); } else { trB = CblasNoTrans; - n = B._n; + n = B._n; // assert(B._m == k); } C.resize(m,n); @@ -1845,7 +1845,7 @@ template inline void Matrix::mult(const Matrix& B, /// perform C = a*B*A + b*C, possibly transposing A or B. template -inline void Matrix::multSwitch(const Matrix& B, Matrix& C, +inline void Matrix::multSwitch(const Matrix& B, Matrix& C, const bool transA, const bool transB, const T a, const T b) const { B.mult(*this,C,transB,transA,a,b); @@ -2098,7 +2098,7 @@ template inline T Matrix::asum() const { template inline T Matrix::trace() const { T sum=T(); INTM m = MIN(_n,_m); - for (INTM i = 0; i inline T Matrix::norm_inf_2_col() const { for (INTM i = 0; i<_n; ++i) { refCol(i,col); T norm_col = col.nrm2(); - if (norm_col > max) + if (norm_col > max) max = norm_col; } return max; @@ -2148,10 +2148,10 @@ template inline void Matrix::norm_2_rows( Vector& norms) const { norms.resize(_m); norms.setZeros(); - for (INTM i = 0; i<_n; ++i) - for (INTM j = 0; j<_m; ++j) + for (INTM i = 0; i<_n; ++i) + for (INTM j = 0; j<_m; ++j) norms[j] += _X[i*_m+j]*_X[i*_m+j]; - for (INTM j = 0; j<_m; ++j) + for (INTM j = 0; j<_m; ++j) norms[j]=sqrt(norms[j]); }; @@ -2160,8 +2160,8 @@ template inline void Matrix::norm_2sq_rows( Vector& norms) const { norms.resize(_m); norms.setZeros(); - for (INTM i = 0; i<_n; ++i) - for (INTM j = 0; j<_m; ++j) + for (INTM i = 0; i<_n; ++i) + for (INTM j = 0; j<_m; ++j) norms[j] += _X[i*_m+j]*_X[i*_m+j]; }; @@ -2192,8 +2192,8 @@ template inline void Matrix::norm_inf_cols(Vector& norms) con template inline void Matrix::norm_inf_rows(Vector& norms) const { norms.resize(_m); norms.setZeros(); - for (INTM i = 0; i<_n; ++i) - for (INTM j = 0; j<_m; ++j) + for (INTM i = 0; i<_n; ++i) + for (INTM j = 0; j<_m; ++j) norms[j] = MAX(abs(_X[i*_m+j]),norms[j]); }; @@ -2201,8 +2201,8 @@ template inline void Matrix::norm_inf_rows(Vector& norms) con template inline void Matrix::norm_l1_rows(Vector& norms) const { norms.resize(_m); norms.setZeros(); - for (INTM i = 0; i<_n; ++i) - for (INTM j = 0; j<_m; ++j) + for (INTM i = 0; i<_n; ++i) + for (INTM j = 0; j<_m; ++j) norms[j] += abs(_X[i*_m+j]); }; @@ -2219,7 +2219,7 @@ template inline void Matrix::norm_2sq_cols( } }; -template +template inline void Matrix::sum_cols(Vector& sum) const { sum.resize(_m); sum.setZeros(); @@ -2349,7 +2349,7 @@ template inline void Matrix::blockThrshold(const T nu, } } -template inline void Matrix::sparseProject(Matrix& Y, +template inline void Matrix::sparseProject(Matrix& Y, const T thrs, const int mode, const T lambda1, const T lambda2, const T lambda3, const bool pos, const int numThreads) { @@ -2361,7 +2361,7 @@ template inline void Matrix::sparseProject(Matrix& Y, } int i; -#pragma omp parallel for private(i) +#pragma omp parallel for private(i) for (i = 0; i< _n; ++i) { #ifdef _OPENMP int numT=omp_get_thread_num(); @@ -2417,7 +2417,7 @@ template inline void Matrix::rank1Update( }; template -inline void Matrix::rank1Update_mult(const Vector& vec1, +inline void Matrix::rank1Update_mult(const Vector& vec1, const Vector& vec1b, const SpVector& vec2, const T alpha) { @@ -2486,7 +2486,7 @@ template inline void Matrix::rank1Update( }; -/// compute x, such that b = Ax, +/// compute x, such that b = Ax, template inline void Matrix::conjugateGradient( const Vector& b, Vector& x, const T tol, const int itermax) const { Vector R,P,AP; @@ -2516,7 +2516,7 @@ template inline void Matrix::drop(char* fileName) const { f.open(fileName, ofstream::trunc); std::cout << "Matrix written in " << fileName << std::endl; for (INTM i = 0; i<_n; ++i) { - for (INTM j = 0; j<_m; ++j) + for (INTM j = 0; j<_m; ++j) f << _X[i*_m+j] << " "; f << std::endl; } @@ -2580,7 +2580,7 @@ template inline void Matrix::toSparse(SpMatrix& out) const { pB=new INTM[_n+1]; } INTM* pE=pB+1; - for (INTM i = 0; i<_n*_m; ++i) + for (INTM i = 0; i<_n*_m; ++i) if (_X[i] != 0) ++count; INTM* r; T* v; @@ -2621,7 +2621,7 @@ template inline void Matrix::toSparseTrans( pB=new INTM[_m+1]; } INTM* pE=pB+1; - for (INTM i = 0; i<_n*_m; ++i) + for (INTM i = 0; i<_n*_m; ++i) if (_X[i] != 0) ++count; INTM* r; T* v; @@ -2651,7 +2651,7 @@ template inline void Matrix::toSparseTrans( out._externAlloc=false; }; -/// make a reference of the matrix to a vector vec +/// make a reference of the matrix to a vector vec template inline void Matrix::toVect( Vector& vec) const { vec.clear(); @@ -2663,7 +2663,7 @@ template inline void Matrix::toVect( /// merge two dictionaries template inline void Matrix::merge(const Matrix& B, Matrix& C) const { - const INTM K =_n; + const INTM K =_n; Matrix G; this->mult(B,G,true,false); std::list list; @@ -2829,7 +2829,7 @@ inline void Vector::logspace(const INTM n, const T a, const T b) { template inline INTM Vector::nnz() const { INTM sum=0; - for (INTM i = 0; i<_n; ++i) + for (INTM i = 0; i<_n; ++i) if (_X[i] != T()) ++sum; return sum; }; @@ -2969,26 +2969,26 @@ template inline void Vector::hardThrshold(const T nu) { /// performs thresholding of the vector template inline void Vector::thrsmax(const T nu) { - for (INTM i = 0; i<_n; ++i) + for (INTM i = 0; i<_n; ++i) _X[i]=MAX(_X[i],nu); } /// performs thresholding of the vector template inline void Vector::thrsmin(const T nu) { - for (INTM i = 0; i<_n; ++i) + for (INTM i = 0; i<_n; ++i) _X[i]=MIN(_X[i],nu); } /// performs thresholding of the vector template inline void Vector::thrsabsmin(const T nu) { - for (INTM i = 0; i<_n; ++i) + for (INTM i = 0; i<_n; ++i) _X[i]=MAX(MIN(_X[i],nu),-nu); } /// performs thresholding of the vector template inline void Vector::thrshold(const T nu) { - for (INTM i = 0; i<_n; ++i) - if (abs(_X[i]) < nu) + for (INTM i = 0; i<_n; ++i) + if (abs(_X[i]) < nu) _X[i]=0; } /// performs soft-thresholding of the vector @@ -3368,7 +3368,7 @@ template inline T Vector::asum() const { template inline T Vector::lzero() const { INTM count=0; - for (INTM i = 0; i<_n; ++i) + for (INTM i = 0; i<_n; ++i) if (_X[i] != 0) ++count; return count; }; @@ -3384,7 +3384,7 @@ template inline T Vector::afused() const { /// returns the sum of the vector template inline T Vector::sum() const { T sum=T(); - for (INTM i = 0; i<_n; ++i) sum +=_X[i]; + for (INTM i = 0; i<_n; ++i) sum +=_X[i]; return sum; }; @@ -3393,7 +3393,7 @@ template inline void Vector::sign(Vector& signs) const { T* prSign=signs.rawX(); for (INTM i = 0; i<_n; ++i) { if (_X[i] == 0) { - prSign[i]=0.0; + prSign[i]=0.0; } else { prSign[i] = _X[i] > 0 ? 1.0 : -1.0; } @@ -3569,7 +3569,7 @@ inline void Vector::sparseProject(Vector& out, const T thrs, const int mod } else if (mode == 4) { /// min_u 0.5||b-u||_2^2 + lambda1||u||_1 / ||u||_2^2 <= thrs out.copy(*this); - if (pos) + if (pos) out.thrsPos(); out.softThrshold(lambda1); T nrm=out.nrm2sq(); @@ -3582,7 +3582,7 @@ inline void Vector::sparseProject(Vector& out, const T thrs, const int mod // if (nrm > thrs) // out.scal(sqr_alt(thrs/nrm)); // } else if (mode == 6) { - /// min_u 0.5||b-u||_2^2 + lambda1||u||_1 +lambda2 Fused(u) +0.5lambda_3 ||u||_2^2 + /// min_u 0.5||b-u||_2^2 + lambda1||u||_1 +lambda2 Fused(u) +0.5lambda_3 ||u||_2^2 this->fusedProjectHomotopy(out,lambda1,lambda2,lambda3,true); } else if (mode==6) { /// min_u ||b-u||_2^2 / lambda1||u||_1 +lambda2 Fused(u) + 0.5lambda3||u||_2^2 <= thrs @@ -3591,7 +3591,7 @@ inline void Vector::sparseProject(Vector& out, const T thrs, const int mod /// min_u ||b-u||_2^2 / (1-lambda1)*||u||_2^2 + lambda1||u||_1 <= thrs if (lambda1 < 1e-10) { out.copy(*this); - if (pos) + if (pos) out.thrsPos(); out.normalize2(); out.scal(sqrt(thrs)); @@ -3619,7 +3619,7 @@ inline void Vector::l1l2projectb(Vector& out, const T thrs, const T gamma, } else if (mode == 3) { /// min_u 0.5||b-u||_2^2 + gamma||u||_1 / ||u||_2^2 <= thrs out.copy(*this); - if (pos) + if (pos) out.thrsPos(); out.softThrshold(gamma); T nrm=out.nrm2(); @@ -3632,7 +3632,7 @@ inline void Vector::l1l2projectb(Vector& out, const T thrs, const T gamma, /// min_u ||b-u||_2^2 / ||u||_1 + (gamma/2) ||u||_2^2 <= thrs template inline void Vector::l1l2project(Vector& out, const T thrs, const T gamma, const bool pos) const { - if (gamma == 0) + if (gamma == 0) return this->l1project(out,thrs,pos); out.copy(*this); if (pos) { @@ -3713,7 +3713,7 @@ static inline T fusedHomotopyAux(const bool& sign1, }; template -inline void Vector::fusedProjectHomotopy(Vector& alpha, +inline void Vector::fusedProjectHomotopy(Vector& alpha, const T lambda1,const T lambda2,const T lambda3, const bool penalty) { T* pr_DtR=_X; @@ -3747,7 +3747,7 @@ inline void Vector::fusedProjectHomotopy(Vector& alpha, alpha.set(pr_gamma[0]); /// update DtR this->sub(alpha); - for (INTM j = K-2; j>=0; --j) + for (INTM j = K-2; j>=0; --j) pr_DtR[j] += pr_DtR[j+1]; pr_DtR[0]=0; @@ -3761,7 +3761,7 @@ inline void Vector::fusedProjectHomotopy(Vector& alpha, /// Solve the Lasso using simplified LARS for (INTM i = 1; i::fusedProjectHomotopy(Vector& alpha, /// Update pr_ind and pr_c if (newAtom) { INTM j; - for (j = 1; j currentInd) break; for (INTM k = i; k>j; --k) { pr_ind[k]=pr_ind[k-1]; @@ -3801,9 +3801,9 @@ inline void Vector::fusedProjectHomotopy(Vector& alpha, } pr_u[i] = pr_signs[i-1] ? -pr_c[i-1] : pr_c[i-1]; pr_u[i] += pr_signs[i] ? pr_c[i-1]+pr_c[i] : -pr_c[i-1]-pr_c[i]; - } + } - // Compute Du + // Compute Du pr_Du[0]=pr_u[0]; for (INTM k = 1; k::fusedProjectHomotopy(Vector& alpha, pr_Du[k]=pr_Du[pr_ind[j]]; } - /// Compute DDu + /// Compute DDu DDu.copy(Du); - for (INTM j = K-2; j>=0; --j) + for (INTM j = K-2; j>=0; --j) pr_DDu[j] += pr_DDu[j+1]; /// Check constraINTMs T max_step1 = INFINITY; if (penalty) { max_step1 = currentLambda-lambda2; - } + } /// Check changes of sign T max_step2 = INFINITY; @@ -3849,7 +3849,7 @@ inline void Vector::fusedProjectHomotopy(Vector& alpha, currentInd = scores.fmin(); max_step3 = pr_scores[currentInd]; T step = MIN(max_step1,MIN(max_step3,max_step2)); - if (step == 0 || step == INFINITY) break; + if (step == 0 || step == INFINITY) break; /// Update gamma, alpha, DtR, currentLambda for (INTM j = 0; j<=i; ++j) { @@ -3860,10 +3860,10 @@ inline void Vector::fusedProjectHomotopy(Vector& alpha, currentLambda -= step; if (step == max_step2) { /// Update signs,pr_ind, pr_c - for (INTM k = step_out; k<=i; ++k) + for (INTM k = step_out; k<=i; ++k) pr_ind[k]=pr_ind[k+1]; pr_ind[i]=K; - for (INTM k = step_out; k<=i; ++k) + for (INTM k = step_out; k<=i; ++k) pr_signs[k]=pr_signs[k+1]; pr_c[step_out-1]=T(1.0)/(pr_ind[step_out]-pr_ind[step_out-1]); pr_c[step_out]=T(1.0)/(pr_ind[step_out+1]-pr_ind[step_out]); @@ -3892,7 +3892,7 @@ inline void Vector::fusedProject(Vector& alpha, const T lambda1, const T l T total_alpha =alpha.sum(); /// Modification of beta - for (INTM i = K-2; i>=0; --i) + for (INTM i = K-2; i>=0; --i) pr_beta[i]+=pr_beta[i+1]; for (INTM i = 0; i::applyBayerPattern(const int offset) { }; -/// make a sparse copy +/// make a sparse copy template inline void Vector::toSparse( SpVector& vec) const { INTM L=0; @@ -4111,7 +4111,7 @@ inline void Matrix::copyMask(Matrix& out, Vector& mask) const { /* **************************** - * Implementation of SpMatrix + * Implementation of SpMatrix * ****************************/ @@ -4154,7 +4154,7 @@ template SpMatrix::~SpMatrix() { }; /// reference the column i INTMo vec -template inline void SpMatrix::refCol(INTM i, +template inline void SpMatrix::refCol(INTM i, SpVector& vec) const { if (vec._nzmax > 0) vec.clear(); vec._v=_v+_pB[i]; @@ -4192,7 +4192,7 @@ template void SpMatrix::getData(Vector& data, const INTM index) const { data.resize(_m); data.setZeros(); - for (INTM i = _pB[index]; i< _pB[index+1]; ++i) + for (INTM i = _pB[index]; i< _pB[index+1]; ++i) data[_r[i]]=_v[i]; }; @@ -4272,7 +4272,7 @@ template inline void SpMatrix::clear() { }; /// resize the matrix -template inline void SpMatrix::resize(const INTM m, +template inline void SpMatrix::resize(const INTM m, const INTM n, const INTM nzmax) { if (n == _n && m == _m && nzmax == _nzmax) return; this->clear(); @@ -4317,7 +4317,7 @@ inline void SpMatrix::multTrans(const Vector& x, Vector& y, /// perform b = alpha*A*x + beta*b, when x is sparse template -inline void SpMatrix::multTrans(const SpVector& x, Vector& y, +inline void SpMatrix::multTrans(const SpVector& x, Vector& y, const T alpha, const T beta) const { y.resize(_n); if (beta) { @@ -4356,7 +4356,7 @@ inline void SpMatrix::mult(const Vector& x, Vector& y, /// perform b = alpha*A*x + beta*b, when x is sparse template -inline void SpMatrix::mult(const SpVector& x, Vector& y, +inline void SpMatrix::mult(const SpVector& x, Vector& y, const T alpha, const T beta) const { y.resize(_m); if (beta) { @@ -4376,7 +4376,7 @@ inline void SpMatrix::mult(const SpVector& x, Vector& y, /// perform C = a*A*B + b*C, possibly transposing A or B. template -inline void SpMatrix::mult(const Matrix& B, Matrix& C, +inline void SpMatrix::mult(const Matrix& B, Matrix& C, const bool transA, const bool transB, const T a, const T b) const { if (transA) { @@ -4444,7 +4444,7 @@ inline void SpMatrix::mult(const Matrix& B, Matrix& C, /// perform C = a*A*B + b*C, possibly transposing A or B. template -inline void SpMatrix::mult(const SpMatrix& B, Matrix& C, +inline void SpMatrix::mult(const SpMatrix& B, Matrix& C, const bool transA, const bool transB, const T a, const T b) const { if (transA) { @@ -4512,7 +4512,7 @@ inline void SpMatrix::mult(const SpMatrix& B, Matrix& C, /// perform C = a*B*A + b*C, possibly transposing A or B. template -inline void SpMatrix::multSwitch(const Matrix& B, Matrix& C, +inline void SpMatrix::multSwitch(const Matrix& B, Matrix& C, const bool transA, const bool transB, const T a, const T b) const { B.mult(*this,C,transB,transA,a,b); @@ -4544,37 +4544,37 @@ inline void SpMatrix::copyRow(const INTM ind, Vector& x) const { } }; -template +template inline void SpMatrix::addVecToCols( const Vector& vec, const T a) { const T* pr_vec = vec.rawX(); if (isEqual(a,T(1.0))) { - for (INTM i = 0; i<_n; ++i) - for (INTM j = _pB[i]; j<_pE[i]; ++j) + for (INTM i = 0; i<_n; ++i) + for (INTM j = _pB[i]; j<_pE[i]; ++j) _v[j] += pr_vec[_r[j]]; } else { - for (INTM i = 0; i<_n; ++i) - for (INTM j = _pB[i]; j<_pE[i]; ++j) + for (INTM i = 0; i<_n; ++i) + for (INTM j = _pB[i]; j<_pE[i]; ++j) _v[j] += a*pr_vec[_r[j]]; } }; -template +template inline void SpMatrix::addVecToColsWeighted( const Vector& vec, const T* weights, const T a) { const T* pr_vec = vec.rawX(); if (isEqual(a,T(1.0))) { - for (INTM i = 0; i<_n; ++i) - for (INTM j = _pB[i]; j<_pE[i]; ++j) + for (INTM i = 0; i<_n; ++i) + for (INTM j = _pB[i]; j<_pE[i]; ++j) _v[j] += pr_vec[_r[j]]*weights[j-_pB[i]]; } else { - for (INTM i = 0; i<_n; ++i) - for (INTM j = _pB[i]; j<_pE[i]; ++j) + for (INTM i = 0; i<_n; ++i) + for (INTM j = _pB[i]; j<_pE[i]; ++j) _v[j] += a*pr_vec[_r[j]]*weights[j-_pB[i]]; } }; -template +template inline void SpMatrix::sum_cols(Vector& sum) const { sum.resize(_m); sum.setZeros(); @@ -4613,7 +4613,7 @@ template inline void SpMatrix::AAt(Matrix& aat) const { } cblas_copy(K*K,aatT,1,aat._X,1); - for (i = 1; i(K*K,1.0,aatT+K*K*i,1,aat._X,1); aat.fillSymmetric(); delete[](aatT); @@ -4663,7 +4663,7 @@ template inline void SpMatrix::AAt(Matrix& aat, } cblas_copy(K*K,aatT,1,aat._X,1); - for (i = 1; i(K*K,1.0,aatT+K*K*i,1,aat._X,1); aat.fillSymmetric(); delete[](aatT); @@ -4698,7 +4698,7 @@ template inline void SpMatrix::wAAt(const Vector& w, } cblas_copy(K*K,aatT,1,aat._X,1); - for (i = 1; i(K*K,1.0,aatT+K*K*i,1,aat._X,1); aat.fillSymmetric(); delete[](aatT); @@ -4732,7 +4732,7 @@ template inline void SpMatrix::XAt(const Matrix& X, } cblas_copy(n*K,XatT,1,XAt._X,1); - for (i = 1; i(n*K,1.0,XatT+n*K*i,1,XAt._X,1); delete[](XatT); }; @@ -4766,7 +4766,7 @@ template inline void SpMatrix::XAt(const Matrix& X, } cblas_copy(n*K,XatT,1,XAt._X,1); - for (i = 1; i(n*K,1.0,XatT+n*K*i,1,XAt._X,1); delete[](XatT); }; @@ -4805,7 +4805,7 @@ template inline void SpMatrix::wXAt(const Vector& w, } cblas_copy(n*K,XatT,1,XAt._X,1); - for (i = 1; i(n*K,1.0,XatT+n*K*i,1,XAt._X,1); delete[](XatT); }; @@ -4837,7 +4837,7 @@ template inline void SpMatrix::toFullTrans( /// use the data from v, r for _v, _r -template inline void SpMatrix::convert(const Matrix&vM, +template inline void SpMatrix::convert(const Matrix&vM, const Matrix& rM, const INTM K) { const INTM M = rM.n(); const INTM L = rM.m(); @@ -4914,7 +4914,7 @@ inline void SpMatrix::norm_1_cols(Vector& norms) const { /* *************************** - * Implementation of SpVector + * Implementation of SpVector * ***************************/ @@ -4973,13 +4973,13 @@ template inline void SpVector::print(const string& name) const { /// create a reference on the vector r template inline void SpVector::refIndices( Vector& indices) const { - indices.setPointer(_r,_L); + indices.setPointer(_r,_L); }; /// creates a reference on the vector val template inline void SpVector::refVal( Vector& val) const { - val.setPointer(_v,_L); + val.setPointer(_v,_L); }; /// a <- a.^2 @@ -5071,7 +5071,7 @@ template void inline SpVector::toSpMatrix( out_r[i]=_r[i]-col*m; } } - for (current_col++ ; current_col < n+1; ++current_col) + for (current_col++ ; current_col < n+1; ++current_col) out_pB[current_col]=_L; }; @@ -5088,9 +5088,9 @@ template void inline SpVector::toFull(Vector& out) * ****************************/ template ProdMatrix::ProdMatrix() { - _DtX= NULL; - _X=NULL; - _D=NULL; + _DtX= NULL; + _X=NULL; + _D=NULL; _high_memory=true; _n=0; _m=0; @@ -5114,7 +5114,7 @@ template ProdMatrix::ProdMatrix(const Matrix& D, const Matrix template inline void ProdMatrix::setMatrices(const Matrix& D, const Matrix& X, const bool high_memory) { _high_memory=high_memory; - _m = D.n(); + _m = D.n(); _n = X.n(); if (high_memory) { D.mult(X,*_DtX,true,false); @@ -5129,7 +5129,7 @@ template inline void ProdMatrix::setMatrices(const Matrix& D, template inline void ProdMatrix::setMatrices( const Matrix& D, const bool high_memory) { _high_memory=high_memory; - _m = D.n(); + _m = D.n(); _n = D.n(); if (high_memory) { D.XtX(*_DtX); @@ -5137,7 +5137,7 @@ template inline void ProdMatrix::setMatrices( _X=&D; _D=&D; _DtX=NULL; - } + } _addDiag=0; }; @@ -5150,7 +5150,7 @@ template inline void ProdMatrix::copyCol(const INTM i, Vector _X->refCol(i,Xi); _D->multTrans(Xi,DtXi); if (_addDiag && _m == _n) DtXi[i] += _addDiag; - } + } }; /// compute DtX(:,i) @@ -5163,7 +5163,7 @@ template inline void ProdMatrix::extract_rawCol(const INTM i,T* _X->refCol(i,Xi); _D->multTrans(Xi,vDtXi); if (_addDiag && _m == _n) DtXi[i] += _addDiag; - } + } }; template inline void ProdMatrix::add_rawCol(const INTM i,T* DtXi, @@ -5176,7 +5176,7 @@ template inline void ProdMatrix::add_rawCol(const INTM i,T* DtXi _X->refCol(i,Xi); _D->multTrans(Xi,vDtXi,a,T(1.0)); if (_addDiag && _m == _n) DtXi[i] += a*_addDiag; - } + } }; template void inline ProdMatrix::addDiag(const T diag) { @@ -5254,7 +5254,7 @@ template class SubMatrix : public AbstractMatrix { AbstractMatrix* _matrix; }; -template +template SubMatrix::SubMatrix(AbstractMatrix& G, Vector& indI, Vector& indJ) { _matrix = &G; _indicesI.copy(indI); @@ -5287,7 +5287,7 @@ template void inline SubMatrix::extract_rawCol(const INTM i, T* } }; -template inline void SubMatrix::copyCol(const INTM i, +template inline void SubMatrix::copyCol(const INTM i, Vector& DtXi) const { this->extract_rawCol(i,DtXi.rawX()); }; @@ -5309,7 +5309,7 @@ template void inline SubMatrix::diag(Vector& diag) const { } }; -template inline T SubMatrix::operator()(const INTM index1, +template inline T SubMatrix::operator()(const INTM index1, const INTM index2) const { return (*_matrix)(_indicesI[index1],_indicesJ[index2]); } @@ -5330,23 +5330,23 @@ template class ShiftMatrix : public AbstractMatrixB { const T alpha = 1.0, const T beta = 0.0) const; /// perform b = alpha*A*x + beta*b, when x is sparse - virtual void mult(const SpVector& x, Vector& b, + virtual void mult(const SpVector& x, Vector& b, const T alpha = 1.0, const T beta = 0.0) const; - virtual void mult(const Vector& x, Vector& b, + virtual void mult(const Vector& x, Vector& b, const T alpha = 1.0, const T beta = 0.0) const; /// perform C = a*A*B + b*C, possibly transposing A or B. - virtual void mult(const Matrix& B, Matrix& C, + virtual void mult(const Matrix& B, Matrix& C, const bool transA = false, const bool transB = false, const T a = 1.0, const T b = 0.0) const; - virtual void mult(const SpMatrix& B, Matrix& C, + virtual void mult(const SpMatrix& B, Matrix& C, const bool transA = false, const bool transB = false, const T a = 1.0, const T b = 0.0) const; /// perform C = a*B*A + b*C, possibly transposing A or B. - virtual void multSwitch(const Matrix& B, Matrix& C, + virtual void multSwitch(const Matrix& B, Matrix& C, const bool transA = false, const bool transB = false, const T a = 1.0, const T b = 0.0) const; @@ -5363,7 +5363,7 @@ template class ShiftMatrix : public AbstractMatrixB { virtual ~ShiftMatrix() { }; private: - void center() { + void center() { Vector ones(_m); ones.set(T(1.0)/_m); this->multTrans(ones,_means); @@ -5457,7 +5457,7 @@ template void ShiftMatrix::mult(const Matrix& cerr << "Shift Matrix is used in inadequate setting" << endl; } -template void ShiftMatrix::mult(const SpMatrix& B, Matrix& C, +template void ShiftMatrix::mult(const SpMatrix& B, Matrix& C, const bool transA, const bool transB, const T a, const T b) const { cerr << "Shift Matrix is used in inadequate setting" << endl; } @@ -5502,7 +5502,7 @@ template void ShiftMatrix::print(const string& name) const { /// Matrix with shifts template class DoubleRowMatrix : public AbstractMatrixB { public: - DoubleRowMatrix(const AbstractMatrixB& inputmatrix) : _inputmatrix(&inputmatrix) { + DoubleRowMatrix(const AbstractMatrixB& inputmatrix) : _inputmatrix(&inputmatrix) { _n=inputmatrix.n(); _m=2*inputmatrix.m(); }; @@ -5514,23 +5514,23 @@ template class DoubleRowMatrix : public AbstractMatrixB { const T alpha = 1.0, const T beta = 0.0) const; /// perform b = alpha*A*x + beta*b, when x is sparse - virtual void mult(const SpVector& x, Vector& b, + virtual void mult(const SpVector& x, Vector& b, const T alpha = 1.0, const T beta = 0.0) const; - virtual void mult(const Vector& x, Vector& b, + virtual void mult(const Vector& x, Vector& b, const T alpha = 1.0, const T beta = 0.0) const; /// perform C = a*A*B + b*C, possibly transposing A or B. - virtual void mult(const Matrix& B, Matrix& C, + virtual void mult(const Matrix& B, Matrix& C, const bool transA = false, const bool transB = false, const T a = 1.0, const T b = 0.0) const; - virtual void mult(const SpMatrix& B, Matrix& C, + virtual void mult(const SpMatrix& B, Matrix& C, const bool transA = false, const bool transB = false, const T a = 1.0, const T b = 0.0) const; /// perform C = a*B*A + b*C, possibly transposing A or B. - virtual void multSwitch(const Matrix& B, Matrix& C, + virtual void multSwitch(const Matrix& B, Matrix& C, const bool transA = false, const bool transB = false, const T a = 1.0, const T b = 0.0) const; @@ -5557,7 +5557,7 @@ template void DoubleRowMatrix::multTrans(const Vector& x, Vector& b, const T alpha, const T beta) const { const INTM mm = _inputmatrix->m(); Vector tmp(mm); - for (INTM i = 0; imultTrans(tmp,b,alpha,beta); }; @@ -5607,7 +5607,7 @@ template void DoubleRowMatrix::mult(const Matrix& cerr << "Double Matrix is used in inadequate setting" << endl; } -template void DoubleRowMatrix::mult(const SpMatrix& B, Matrix& C, +template void DoubleRowMatrix::mult(const SpMatrix& B, Matrix& C, const bool transA, const bool transB, const T a, const T b) const { FLAG(4) cerr << "Double Matrix is used in inadequate setting" << endl; @@ -5778,7 +5778,7 @@ template void AbstractMatrixB::ridgeCG(const Matrix& mb, init_omp(numThreads); const int num_probs=mb.n(); int i = 0; -#pragma omp parallel for private(i) +#pragma omp parallel for private(i) for (i =0; i b; mb.refCol(i,b); @@ -5794,7 +5794,7 @@ template void AbstractMatrixB::ridgeCG(const Matrix& mb, cons init_omp(numThreads); const int num_probs=mb.n(); int i = 0; -#pragma omp parallel for private(i) +#pragma omp parallel for private(i) for (i =0; i b; mb.refCol(i,b); diff --git a/spams_wrap/spams/prox/fista.h b/spams_wrap/spams/prox/fista.h index 22bd08c4..38e8b4c9 100644 --- a/spams_wrap/spams/prox/fista.h +++ b/spams_wrap/spams/prox/fista.h @@ -1,5 +1,5 @@ -/* Software SPAMS v2.1 - Copyright 2009-2011 Julien Mairal +/* Software SPAMS v2.1 - Copyright 2009-2011 Julien Mairal * * This file is part of SPAMS. * @@ -135,18 +135,18 @@ namespace FISTA { }; bool regul_for_matrices(const regul_t& regul) { - return regul==L1L2 || regul==L1LINF || regul==L1L2_L1 || regul==L1LINF_L1 + return regul==L1L2 || regul==L1LINF || regul==L1L2_L1 || regul==L1LINF_L1 || regul==TREEMULT || regul==GRAPHMULT || regul==L1LINFCR || regul==TRACE_NORM || regul==RANK; } - template struct ParamFISTA { - ParamFISTA() { num_threads=1; max_it=100; L0=T(0.1); gamma=T(1.5); tol=T(1e-10); + template struct ParamFISTA { + ParamFISTA() { num_threads=1; max_it=100; L0=T(0.1); gamma=T(1.5); tol=T(1e-10); it0=10; max_iter_backtracking=1000; loss=SQUARE; compute_gram=false; admm=false; lin_admm=false; - intercept=false; regul=RIDGE; resetflow=false; delta=0; lambda2=0; lambda3=0; verbose=false; + intercept=false; regul=RIDGE; resetflow=false; delta=0; lambda2=0; lambda3=0; verbose=false; pos=false; clever=true; a=T(1.0); b=T(0.0); c=T(1.0); log=false; logName=NULL; ista=false; subgrad=false; - length_names=30; + length_names=30; name_regul=new char[length_names]; name_loss=new char[length_names]; is_inner_weights=false; @@ -162,10 +162,10 @@ namespace FISTA { ngroups=0; linesearch_mode=0; } - ~ParamFISTA() { + ~ParamFISTA() { if (!copied) { - delete[](name_regul); - delete[](name_loss); + delete[](name_regul); + delete[](name_loss); } }; int num_threads; @@ -213,7 +213,7 @@ namespace FISTA { int linesearch_mode; }; - template struct ParamReg { + template struct ParamReg { ParamReg() { size_group=1; lambda2d1 = 0; lambda=0; lambda3d1 = 0; pos=false; intercept=false; num_cols=1; graph_st=NULL; tree_st=NULL; graph_path_st=NULL; resetflow=false; clever=false; linf=true; transpose=false; ngroups=0; groups=NULL; }; @@ -237,12 +237,12 @@ namespace FISTA { template bool param_for_admm(const ParamFISTA& param) { - return (param.admm) && (param.loss==SQUARE || param.loss == HINGE) + return (param.admm) && (param.loss==SQUARE || param.loss == HINGE) && (param.regul==GRAPH_L2 || param.regul==GRAPH || param.regul == NONE); }; - template , typename D = Vector , + template , typename D = Vector , typename E = Vector > class SplittingFunction { public: @@ -263,7 +263,7 @@ namespace FISTA { virtual void add_mult_design_matrix(const E& prim, E& out, const T fact) const { }; private: - explicit SplittingFunction(const SplittingFunction& loss); + explicit SplittingFunction(const SplittingFunction& loss); SplittingFunction& operator=(const SplittingFunction& loss); }; @@ -288,18 +288,18 @@ namespace FISTA { const bool intercept = false) const = 0; private: - explicit Loss(const Loss& dict); + explicit Loss(const Loss& dict); Loss& operator=(const Loss& dict); }; - template + template class SqLossMissing : public Loss { public: SqLossMissing(const AbstractMatrixB& D) : _D(&D) { }; virtual ~SqLossMissing() { }; - inline void init(const Vector& x) { - _x.copy(x); + inline void init(const Vector& x) { + _x.copy(x); _missingvalues.clear(); for (int i = 0; i<_x.n(); ++i) { if (isnan(_x[i])) { @@ -335,8 +335,8 @@ namespace FISTA { virtual T fenchel(const Vector& input) const { return 0.5*input.nrm2sq()+input.dot(_x); }; - virtual void var_fenchel(const Vector& x, - Vector& grad1, Vector& grad2, + virtual void var_fenchel(const Vector& x, + Vector& grad1, Vector& grad2, const bool intercept) const { grad1.copy(_x); SpVector spalpha(x.n()); @@ -351,25 +351,25 @@ namespace FISTA { }; private: - explicit SqLossMissing(const SqLossMissing& dict); + explicit SqLossMissing(const SqLossMissing& dict); SqLossMissing& operator=(const SqLossMissing& dict); const AbstractMatrixB* _D; Vector _x; List _missingvalues; }; - template + template class SqLoss : public Loss, public SplittingFunction { public: SqLoss(const AbstractMatrixB& D) : _D(&D) { _compute_gram = false; }; SqLoss(const AbstractMatrixB& D, const Matrix& G) : _D(&D), _G(&G) { _compute_gram = true; }; virtual ~SqLoss() { }; - inline void init(const Vector& x) { - _x.copy(x); + inline void init(const Vector& x) { + _x.copy(x); if (_compute_gram) { _D->multTrans(x,_DtX); - } + } }; inline T eval(const Vector& alpha) const { @@ -414,8 +414,8 @@ namespace FISTA { virtual T fenchel(const Vector& input) const { return 0.5*input.nrm2sq()+input.dot(_x); }; - virtual void var_fenchel(const Vector& x, - Vector& grad1, Vector& grad2, + virtual void var_fenchel(const Vector& x, + Vector& grad1, Vector& grad2, const bool intercept) const { grad1.copy(_x); SpVector spalpha(x.n()); @@ -460,7 +460,7 @@ namespace FISTA { prim_var.resize(_D->m()); prim_var.setZeros(); } - virtual void prox_prim_var(Vector& out,const Vector& dual_var, + virtual void prox_prim_var(Vector& out,const Vector& dual_var, const Vector& prim_var, const T c) const { const T gamma=T(1.0)/c; out.copy(dual_var); @@ -469,8 +469,8 @@ namespace FISTA { out.add(_x,gamma); out.scal(T(1.0)/(T(1.0)+gamma)); }; - inline void compute_new_prim(Vector& prim, const Vector& prim_var, - const Vector& dual_var, const T gamma, const T delta) const { + inline void compute_new_prim(Vector& prim, const Vector& prim_var, + const Vector& dual_var, const T gamma, const T delta) const { Vector tmp; _D->mult(prim,tmp); tmp.scal(-gamma); @@ -478,13 +478,13 @@ namespace FISTA { tmp.add(dual_var,gamma); _D->multTrans(tmp,prim,T(1.0),delta); }; - inline void add_mult_design_matrix(const Vector& prim, - Vector& out, const T fact) const { + inline void add_mult_design_matrix(const Vector& prim, + Vector& out, const T fact) const { _D->mult(prim,out,fact,T(1.0)); }; private: - explicit SqLoss(const SqLoss& dict); + explicit SqLoss(const SqLoss& dict); SqLoss& operator=(const SqLoss& dict); const AbstractMatrixB* _D; Vector _x; @@ -493,13 +493,13 @@ namespace FISTA { Vector _DtX; }; - template + template class HingeLoss : public SplittingFunction { public: HingeLoss(const AbstractMatrixB& X) : _X(&X) { }; virtual ~HingeLoss() { }; - inline void init(const Vector& y) { + inline void init(const Vector& y) { _y.copy(y); }; inline T eval(const Vector& w) const { @@ -533,7 +533,7 @@ namespace FISTA { prim_var.resize(_X->m()); prim_var.setZeros(); } -/* inline void prox_prim_var(Vector& out,const Vector& dual_var, +/* inline void prox_prim_var(Vector& out,const Vector& dual_var, const Vector& prim_var, const T lambda, const T c) const { const T gamma=T(1.0)/c; out.copy(dual_var); @@ -549,8 +549,8 @@ namespace FISTA { } } }*/ - inline void compute_new_prim(Vector& prim, const Vector& prim_var, - const Vector& dual_var, const T gamma, const T delta) const { + inline void compute_new_prim(Vector& prim, const Vector& prim_var, + const Vector& dual_var, const T gamma, const T delta) const { Vector tmp; _X->mult(prim,tmp); tmp.scal(-gamma); @@ -559,7 +559,7 @@ namespace FISTA { _X->multTrans(tmp,prim,T(1.0),delta); }; inline void add_mult_design_matrix(const Vector& prim, Vector& out, - const T fact) const { + const T fact) const { _X->mult(prim,out,fact,T(1.0)); }; inline void prox_split(Matrix& splitted_w, const T lambda) const { @@ -581,25 +581,25 @@ namespace FISTA { }; private: - explicit HingeLoss(const HingeLoss& dict); + explicit HingeLoss(const HingeLoss& dict); HingeLoss& operator=(const HingeLoss& dict); const AbstractMatrixB* _X; Vector _y; }; - template + template class LogLoss : public Loss { public: LogLoss(const AbstractMatrixB& X) : _X(&X) { }; virtual ~LogLoss() { }; - inline void init(const Vector& y) { + inline void init(const Vector& y) { _y.copy(y); if (weighted) { int countpos=0; for (int i = 0; i0) countpos++; + if (y[i]>0) countpos++; _weightpos=T(1.0)/countpos; _weightneg=T(1.0)/MAX(1e-3,(y.n()-countpos)); } @@ -677,7 +677,7 @@ namespace FISTA { _X->multTrans(grad1,grad2); }; private: - explicit LogLoss(const LogLoss& dict); + explicit LogLoss(const LogLoss& dict); LogLoss& operator=(const LogLoss& dict); const AbstractMatrixB* _X; @@ -686,14 +686,14 @@ namespace FISTA { T _weightneg; }; - template + template class MultiLogLoss : public Loss > { public: MultiLogLoss(const AbstractMatrixB& X) : _X(&X) { }; virtual ~MultiLogLoss() { }; - inline void init(const Vector& y) { + inline void init(const Vector& y) { _y.resize(y.n()); for (int i = 0; i(y[i]); @@ -788,20 +788,20 @@ namespace FISTA { _X->mult(grad1,grad2,true,true); }; private: - explicit MultiLogLoss(const MultiLogLoss& dict); + explicit MultiLogLoss(const MultiLogLoss& dict); MultiLogLoss& operator=(const MultiLogLoss& dict); const AbstractMatrixB* _X; Vector _y; }; - template + template class PoissonLoss : public Loss { public: PoissonLoss(const AbstractMatrixB& X, const T delta) : _X(&X), _delta(delta) { }; virtual ~PoissonLoss() { }; - inline void init(const Vector& y) { + inline void init(const Vector& y) { _y.copy(y); }; inline T eval(const Vector& w) const { @@ -845,7 +845,7 @@ namespace FISTA { } return sum; }; - virtual void var_fenchel(const Vector& w, Vector& grad1, + virtual void var_fenchel(const Vector& w, Vector& grad1, Vector& grad2, const bool intercept) const { grad1.resize(_X->m()); SpVector spw(w.n()); @@ -859,7 +859,7 @@ namespace FISTA { _X->multTrans(grad1,grad2); }; private: - explicit PoissonLoss(const PoissonLoss& dict); + explicit PoissonLoss(const PoissonLoss& dict); PoissonLoss& operator=(const PoissonLoss& dict); const AbstractMatrixB* _X; @@ -867,7 +867,7 @@ namespace FISTA { T _delta; }; - template + template class LossCur: public Loss, Matrix > { public: LossCur(const AbstractMatrixB& X) : _X(&X) { }; @@ -915,25 +915,25 @@ namespace FISTA { _X->mult(tmp,grad2,true,false); }; private: - explicit LossCur(const LossCur& dict); + explicit LossCur(const LossCur& dict); LossCur& operator=(const LossCur& dict); const AbstractMatrixB* _X; }; - template + template class SqLossMat : public Loss , Matrix > { public: SqLossMat(const AbstractMatrixB& D) : _D(&D) { _compute_gram = false; }; - SqLossMat(const AbstractMatrixB& D, const Matrix& G) : _D(&D), _G(&G) { + SqLossMat(const AbstractMatrixB& D, const Matrix& G) : _D(&D), _G(&G) { _compute_gram = true; }; virtual ~SqLossMat() { }; - virtual inline void init(const Matrix& x) { - _x.copy(x); + virtual inline void init(const Matrix& x) { + _x.copy(x); if (_compute_gram) { _D->mult(x,_DtX,true,false); - } + } }; inline T eval(const Matrix& alpha) const { @@ -991,7 +991,7 @@ namespace FISTA { }; private: - explicit SqLossMat(const SqLossMat& dict); + explicit SqLossMat(const SqLossMat& dict); SqLossMat& operator=(const SqLossMat& dict); const AbstractMatrixB* _D; Matrix _x; @@ -1005,7 +1005,7 @@ namespace FISTA { public: LossMatSup() { }; - virtual ~LossMatSup() { + virtual ~LossMatSup() { for (int i = 0; i<_N; ++i) { delete(_losses[i]); _losses[i]=NULL; @@ -1062,14 +1062,14 @@ namespace FISTA { }; virtual bool is_fenchel() const { bool ok=true; - for (int i = 0; i<_N; ++i) + for (int i = 0; i<_N; ++i) ok = ok && _losses[i]->is_fenchel(); return ok; }; virtual void dummy() = 0; private: - explicit LossMatSup(const LossMatSup& dict); + explicit LossMatSup(const LossMatSup& dict); LossMatSup& operator=(const LossMatSup& dict); int _m; @@ -1088,7 +1088,7 @@ namespace FISTA { this->_N=N; this->_losses=new LogLoss*[this->_N]; Vector col; - for (int i = 0; i_N; ++i) + for (int i = 0; i_N; ++i) this->_losses[i]=new LogLoss(X); } virtual void dummy() { }; @@ -1102,7 +1102,7 @@ namespace FISTA { this->_N=N; this->_losses=new SqLossMissing*[this->_N]; Vector col; - for (int i = 0; i_N; ++i) + for (int i = 0; i_N; ++i) this->_losses[i]=new SqLossMissing(X); } virtual void dummy() { }; @@ -1127,7 +1127,7 @@ namespace FISTA { class Regularizer { public: Regularizer() { }; - Regularizer(const ParamReg& param) : _id(NA) { + Regularizer(const ParamReg& param) : _id(NA) { _intercept=param.intercept; _pos=param.pos; } @@ -1152,7 +1152,7 @@ namespace FISTA { virtual bool is_concave() const { return false; }; // virtual bool is_none() const { return false; }; // virtual bool is_pos() const { return _pos; }; - + protected: bool _pos; @@ -1160,11 +1160,11 @@ namespace FISTA { regul_t _id; private: - explicit Regularizer(const Regularizer& reg); + explicit Regularizer(const Regularizer& reg); Regularizer& operator=(const Regularizer& reg); }; - template + template class Lasso : public Regularizer { public: Lasso(const ParamReg& param) : Regularizer(param) { this->_id = L1; }; @@ -1176,7 +1176,7 @@ namespace FISTA { y.softThrshold(lambda); if (this->_intercept) y[y.n()-1] = x[y.n()-1]; }; - T inline eval(const Vector& x) const { + T inline eval(const Vector& x) const { return (this->_intercept ? x.asum() - abs(x[x.n()-1]) : x.asum()); }; void inline fenchel(const Vector& input, T& val, T& scal) const { @@ -1186,10 +1186,10 @@ namespace FISTA { T mm = output.fmaxval(); scal= mm > 1.0 ? T(1.0)/mm : 1.0; val=0; - if (this->_intercept & (abs(output[output.n()-1]) > EPSILON)) val=INFINITY; + if (this->_intercept & (abs(output[output.n()-1]) > EPSILON)) val=INFINITY; }; virtual bool is_subgrad() const { return true; }; - virtual void sub_grad(const Vector& input, Vector& output) const { + virtual void sub_grad(const Vector& input, Vector& output) const { output.resize(input.n()); if (!this->_pos) { for (int i = 0; i + template class LassoConstraint : public Regularizer { public: - LassoConstraint(const ParamReg& param) : Regularizer(param) { + LassoConstraint(const ParamReg& param) : Regularizer(param) { _thrs=param.lambda; - this->_id = L1CONSTRAINT; + this->_id = L1CONSTRAINT; }; virtual ~LassoConstraint() { }; @@ -1227,7 +1227,7 @@ namespace FISTA { T inline eval(const Vector& x) const { return 0; }; - void inline fenchel(const Vector& input, T& val, T& scal) const { + void inline fenchel(const Vector& input, T& val, T& scal) const { scal=1.0; Vector output; output.copy(input); @@ -1239,7 +1239,7 @@ namespace FISTA { T _thrs; }; - template + template class Lzero : public Regularizer { public: Lzero(const ParamReg& param) : Regularizer(param) { }; @@ -1252,13 +1252,13 @@ namespace FISTA { y.hardThrshold(sqrt(2*lambda)); if (this->_intercept) y[y.n()-1] = x[y.n()-1]; }; - T inline eval(const Vector& x) const { + T inline eval(const Vector& x) const { return (this->_intercept ? x.lzero() - 1 : x.lzero()); }; void inline fenchel(const Vector& input, T& val, T& scal) const { }; }; - template + template class LogDC : public Regularizer { public: LogDC(const ParamReg& param) : Regularizer(param), _eps(param.lambda2d1) { }; @@ -1275,7 +1275,7 @@ namespace FISTA { for (int i = 0; i(x[i])+_eps); }; bool inline is_concave() const { return true; }; - T inline eval(const Vector& x) const { + T inline eval(const Vector& x) const { T tmp=0; for (int i = 0; i(abs(x[i])+_eps); return tmp; @@ -1287,7 +1287,7 @@ namespace FISTA { }; - template + template class None: public Regularizer, public SplittingFunction > { public: None() { }; @@ -1302,9 +1302,9 @@ namespace FISTA { void inline fenchel(const Vector& input, T& val, T& scal) const { }; virtual bool is_fenchel() const { return false; }; virtual bool is_subgrad() const { return true; }; - virtual void sub_grad(const Vector& input, Vector& output) const { + virtual void sub_grad(const Vector& input, Vector& output) const { output.setZeros(); - } + } virtual void reset() { }; virtual T eval_split(const SpMatrix& input) const { return 0; }; virtual int num_components() const { return 0; }; @@ -1314,7 +1314,7 @@ namespace FISTA { // virtual bool is_none() const { return true; }; }; - template + template class Ridge: public Regularizer { public: Ridge(const ParamReg& param) : Regularizer(param) { this->_id = RIDGE; }; @@ -1326,7 +1326,7 @@ namespace FISTA { y.scal(T(1.0/(1.0+lambda))); if (this->_intercept) y[y.n()-1] = x[y.n()-1]; }; - T inline eval(const Vector& x) const { + T inline eval(const Vector& x) const { return (this->_intercept ? 0.5*x.nrm2sq() - 0.5*x[x.n()-1]*x[x.n()-1] : 0.5*x.nrm2sq()); }; void inline fenchel(const Vector& input, T& val, T& scal) const { @@ -1335,10 +1335,10 @@ namespace FISTA { if (this->_pos) tmp.thrsPos(); val=this->eval(tmp); scal=T(1.0); - if (this->_intercept & (abs(tmp[tmp.n()-1]) > EPSILON)) val=INFINITY; + if (this->_intercept & (abs(tmp[tmp.n()-1]) > EPSILON)) val=INFINITY; }; virtual bool is_subgrad() const { return true; }; - virtual void sub_grad(const Vector& input, Vector& output) const { + virtual void sub_grad(const Vector& input, Vector& output) const { output.resize(input.n()); if (!this->_pos) { for (int i = 0; i + template class normL2: public Regularizer { public: normL2(const ParamReg& param) : Regularizer(param) { }; @@ -1370,9 +1370,9 @@ namespace FISTA { } if (this->_intercept) y[y.n()-1] = x[y.n()-1]; }; - T inline eval(const Vector& x) const { + T inline eval(const Vector& x) const { Vector xref(x.rawX(),this->_intercept ? x.n()-1 : x.n()); - return xref.nrm2(); + return xref.nrm2(); }; /// TODO add subgradient void inline fenchel(const Vector& input, T& val, T& scal) const { @@ -1382,11 +1382,11 @@ namespace FISTA { T mm = output.nrm2(); scal= mm > 1.0 ? T(1.0)/mm : 1.0; val=0; - if (this->_intercept & (abs(output[output.n()-1]) > EPSILON)) val=INFINITY; + if (this->_intercept & (abs(output[output.n()-1]) > EPSILON)) val=INFINITY; }; }; - template + template class normLINF: public Regularizer { public: normLINF(const ParamReg& param) : Regularizer(param) { }; @@ -1402,9 +1402,9 @@ namespace FISTA { y[j]=y[j]-row[j]; if (this->_intercept) y[y.n()-1] = x[y.n()-1]; }; - T inline eval(const Vector& x) const { + T inline eval(const Vector& x) const { Vector xref(x.rawX(),this->_intercept ? x.n()-1 : x.n()); - return xref.fmaxval(); + return xref.fmaxval(); }; /// TODO add subgradient void inline fenchel(const Vector& input, T& val, T& scal) const { @@ -1414,7 +1414,7 @@ namespace FISTA { T mm = output.asum(); scal= mm > 1.0 ? T(1.0)/mm : 1.0; val=0; - if (this->_intercept & (abs(output[output.n()-1]) > EPSILON)) val=INFINITY; + if (this->_intercept & (abs(output[output.n()-1]) > EPSILON)) val=INFINITY; }; }; @@ -1448,13 +1448,13 @@ namespace FISTA { } } }; - T inline eval(const D& x) const { + T inline eval(const D& x) const { return _regA->eval(x) + _lambda2d1*_regB->eval(x); }; virtual bool is_fenchel() const { return false; }; void inline fenchel(const D& input, T& val, T& scal) const { }; virtual bool is_subgrad() const { return _regA->is_subgrad() && _regB->is_subgrad(); }; - virtual void sub_grad(const D& input, D& output) const { + virtual void sub_grad(const D& input, D& output) const { _regA->sub_grad(input,output); D tmp; _regB->sub_grad(input,tmp); @@ -1471,7 +1471,7 @@ namespace FISTA { typedef ComposeProx< T, Vector, Lasso, Ridge, true > type; }; - template + template class FusedLasso: public Regularizer { public: FusedLasso(const ParamReg& param) : Regularizer(param) { @@ -1486,7 +1486,7 @@ namespace FISTA { copyx.copy(x); copyx.fusedProjectHomotopy(y,_lambda2d1*lambda,lambda,_lambda3d1*lambda,true); }; - T inline eval(const Vector& x) const { + T inline eval(const Vector& x) const { T sum = T(); const int maxn = this->_intercept ? x.n()-1 : x.n(); for (int i = 0; i + template class GraphLasso : public Regularizer, public SplittingFunction > { public: - GraphLasso(const ParamReg& param) : Regularizer(param) { + GraphLasso(const ParamReg& param) : Regularizer(param) { const bool resetflow = param.resetflow; const bool linf = param.linf; const bool clever = param.clever; @@ -1554,7 +1554,7 @@ namespace FISTA { _old_lambda=lambda; }; - T inline eval(const Vector& x) const { + T inline eval(const Vector& x) const { Graph* gr = const_cast* >(&_graph); gr->restore_capacities(); return gr->norm(x.rawX(),_work.rawX(),_weights.rawX(),_linf); @@ -1577,7 +1577,7 @@ namespace FISTA { gr->restore_flow(); scal= mm > 1.0 ? T(1.0)/mm : 1.0; val=0; - if (this->_intercept & (abs(input[input.n()-1]) > EPSILON)) val=INFINITY; + if (this->_intercept & (abs(input[input.n()-1]) > EPSILON)) val=INFINITY; }; virtual void init(const Vector& y) { }; @@ -1588,7 +1588,7 @@ namespace FISTA { if (_linf) { for (int i = 0; i res; res.copy(tmp); vAbs(res.n(),res.rawX(),res.rawX()); @@ -1598,7 +1598,7 @@ namespace FISTA { } else { for (int i = 0; i lambda*_weights[i]) { tmp.scal(T(1.0)-lambda*_weights[i]/nrm); @@ -1652,7 +1652,7 @@ namespace FISTA { typedef ComposeProx, GraphLasso, Ridge, true> type; }; - template + template class TreeLasso : public Regularizer { public: TreeLasso(const ParamReg& param) : Regularizer(param) { @@ -1677,7 +1677,7 @@ namespace FISTA { } _tree.proj(yp,_linf,lambda); }; - T inline eval(const Vector& x) const { + T inline eval(const Vector& x) const { return const_cast* >(&_tree)->val_norm(x.rawX(),0,_linf); }; void inline fenchel(const Vector& y, T& val, T& scal) const { @@ -1694,8 +1694,8 @@ namespace FISTA { T mm = const_cast* >(&_tree)->dual_norm_inf(yp2); scal= mm > 1.0 ? T(1.0)/mm : 1.0; val=0; - if (this->_intercept & (abs(y[y.n()-1]) > EPSILON)) val=INFINITY; - } + if (this->_intercept & (abs(y[y.n()-1]) > EPSILON)) val=INFINITY; + } }; virtual bool is_fenchel() const { return _linf; @@ -1711,7 +1711,7 @@ namespace FISTA { bool _linf; }; - template + template class TreeLzero : public Regularizer { public: TreeLzero(const ParamReg& param) : Regularizer(param) { @@ -1734,7 +1734,7 @@ namespace FISTA { } _tree.proj_zero(yp,lambda); }; - T inline eval(const Vector& x) const { + T inline eval(const Vector& x) const { return const_cast* >(&_tree)->val_zero(x.rawX(),0); }; virtual bool is_fenchel() const { return false; }; @@ -1747,7 +1747,7 @@ namespace FISTA { template class ProxMatToVec : public Regularizer { public: - ProxMatToVec(const ParamReg& param) : Regularizer(param) { + ProxMatToVec(const ParamReg& param) : Regularizer(param) { _size_group=param.size_group; ParamReg param2=param; param2.intercept=false; @@ -1792,12 +1792,12 @@ namespace FISTA { for (int i = 0; ipush_back(i); - } + for (int i = 0; ipush_back(i); + } _prox = new Reg(param2); } - virtual ~GroupProx() { - delete(_prox); + virtual ~GroupProx() { + delete(_prox); for (int i = 0; i(_groups.size()); ++i) delete(_groups[i]); }; @@ -1854,7 +1854,7 @@ namespace FISTA { return sum; } virtual bool is_fenchel() const { return _prox->is_fenchel(); }; - void inline fenchel(const Vector& x, T& val, T& scal) const { + void inline fenchel(const Vector& x, T& val, T& scal) const { const int maxn= this->_intercept ? x.n()-1 : x.n(); T val2; T scal2; @@ -1926,13 +1926,13 @@ namespace FISTA { for (int i = 0; i lambda) { T scal = (norm[i]-lambda)/norm[i]; - for (int j = 0; j_pos) y.thrsPos(); if (this->_intercept) - for (int j = 0; j& x) const { @@ -1941,7 +1941,7 @@ namespace FISTA { return this->_intercept ? norm.asum() - norm[norm.n() -1] : norm.asum(); } virtual bool is_subgrad() const { return true; }; - virtual void sub_grad(const Matrix& input, Matrix& output) const { + virtual void sub_grad(const Matrix& input, Matrix& output) const { Vector norm; input.norm_2_rows(norm); for (int i = 0; i 1.0 ? T(1.0)/mm : 1.0; + scal= mm > 1.0 ? T(1.0)/mm : 1.0; val=0; - if (this->_intercept & (abs(norm[norm.n()-1]) > EPSILON)) val=INFINITY; + if (this->_intercept & (abs(norm[norm.n()-1]) > EPSILON)) val=INFINITY; }; }; @@ -1991,7 +1991,7 @@ namespace FISTA { y(i,j) = row[j]-row2[j]; } } - T inline eval(const Matrix& x) const { + T inline eval(const Matrix& x) const { Vector norm; x.norm_inf_rows(norm); return this->_intercept ? norm.asum() - norm[norm.n() -1] : norm.asum(); @@ -2008,12 +2008,12 @@ namespace FISTA { } if (this->_intercept) norm[norm.n()-1]=0; T mm = norm.fmaxval(); - scal= mm > 1.0 ? T(1.0)/mm : 1.0; + scal= mm > 1.0 ? T(1.0)/mm : 1.0; val=0; - if (this->_intercept & (abs(norm[norm.n()-1]) > EPSILON)) val=INFINITY; + if (this->_intercept & (abs(norm[norm.n()-1]) > EPSILON)) val=INFINITY; }; virtual bool is_subgrad() const { return true; }; - virtual void sub_grad(const Matrix& input, Matrix& output) const { + virtual void sub_grad(const Matrix& input, Matrix& output) const { output.resize(input.m(),input.n()); output.setZeros(); const T maxm= this->_intercept ? input.m()-1 : input.m(); @@ -2024,12 +2024,12 @@ namespace FISTA { if (max > 1e-15) { int num_max=0; for (int j = 0; j(max-abs(row[j])) < 1e-15) + if (abs(max-abs(row[j])) < 1e-15) num_max++; } T add = T(1.0)/num_max; for (int j = 0; j(max-abs(row[j])) < 1e-15) + if (abs(max-abs(row[j])) < 1e-15) row[j] = row[j] > 0 ? add : -add; } output.setRow(i,row); @@ -2041,7 +2041,7 @@ namespace FISTA { template class TraceNorm : public Regularizer > { public: - TraceNorm(const ParamReg& param) : Regularizer >(param) { + TraceNorm(const ParamReg& param) : Regularizer >(param) { if (param.intercept) { cerr << "Trace norm implementation is not compatible with intercept, intercept deactivated" << endl; } @@ -2053,7 +2053,7 @@ namespace FISTA { virtual ~TraceNorm() { }; void inline prox(const Matrix& x, Matrix& y, const T lambda) { - //Matrix tmp; + //Matrix tmp; //tmp.copy(x); Matrix U; Matrix V; @@ -2113,7 +2113,7 @@ namespace FISTA { template class Rank : public Regularizer > { public: - Rank(const ParamReg& param) : Regularizer >(param) { + Rank(const ParamReg& param) : Regularizer >(param) { if (param.intercept) { cerr << "Rank implementation is not compatible with intercept, intercept deactivated" << endl; } @@ -2125,7 +2125,7 @@ namespace FISTA { virtual ~Rank() { }; void inline prox(const Matrix& x, Matrix& y, const T lambda) { - Matrix tmp; + Matrix tmp; tmp.copy(x); y.resize(x.m(),x.n()); y.setZeros(); @@ -2175,9 +2175,9 @@ namespace FISTA { int count_col=0; int count=0; pB[0]=0; - for (ListIterator*> it_path=paths.begin(); + for (ListIterator*> it_path=paths.begin(); it_path != paths.end(); ++it_path) { - for (const_iterator_int it = it_path->nodes.begin(); + for (const_iterator_int it = it_path->nodes.begin(); it != it_path->nodes.end(); ++it) { r[count]= *it; v[count++]= it_path->flow; @@ -2186,8 +2186,8 @@ namespace FISTA { } for (int i = 0; i + + template class GraphPathL0 : public Regularizer { public: GraphPathL0(const ParamReg& param) : Regularizer(param) { @@ -2195,33 +2195,33 @@ namespace FISTA { _graph.init_graph(graph); } virtual ~GraphPathL0() { }; - + void inline prox(const Vector& x, Vector& y, const T lambda) { // DEBUG y.copy(x); if (this->_pos) y.thrsPos(); _graph.proximal_l0(y.rawX(),lambda); }; - T inline eval(const Vector& x) const { + T inline eval(const Vector& x) const { return const_cast* >(&_graph)->eval_l0(x.rawX()); }; - T inline eval_paths(const Vector& x, SpMatrix& paths_mat) const { + T inline eval_paths(const Vector& x, SpMatrix& paths_mat) const { List*> paths; T val=const_cast* >(&_graph)->eval_l0(x.rawX(),&paths); convert_paths_to_mat(paths,paths_mat,_graph.n()); - for (ListIterator*> it_path=paths.begin(); + for (ListIterator*> it_path=paths.begin(); it_path != paths.end(); ++it_path) delete(*it_path); return val; }; - + virtual bool is_fenchel() const { return false; }; void inline fenchel(const Vector& input, T& val, T& scal) const { }; - + private: GraphPath _graph; }; - - template + + template class GraphPathConv : public Regularizer { public: GraphPathConv(const ParamReg& param) : Regularizer(param) { @@ -2229,27 +2229,27 @@ namespace FISTA { _graph.init_graph(graph); } virtual ~GraphPathConv() { }; - + void inline prox(const Vector& x, Vector& y, const T lambda) { y.copy(x); if (this->_pos) y.thrsPos(); _graph.proximal_conv(y.rawX(),lambda); }; - T inline eval(const Vector& x) const { + T inline eval(const Vector& x) const { return const_cast* >(&_graph)->eval_conv(x.rawX()); }; - T inline eval_dual_norm(const Vector& x) const { + T inline eval_dual_norm(const Vector& x) const { return const_cast* >(&_graph)->eval_dual_norm(x.rawX(),NULL); }; - T inline eval_paths(const Vector& x, SpMatrix& paths_mat) const { + T inline eval_paths(const Vector& x, SpMatrix& paths_mat) const { List*> paths; T val=const_cast* >(&_graph)->eval_conv(x.rawX(),&paths); convert_paths_to_mat(paths,paths_mat,_graph.n()); - for (ListIterator*> it_path=paths.begin(); + for (ListIterator*> it_path=paths.begin(); it_path != paths.end(); ++it_path) delete(*it_path); return val; }; - T inline eval_dual_norm_paths(const Vector& x, SpMatrix& paths_mat) const { + T inline eval_dual_norm_paths(const Vector& x, SpMatrix& paths_mat) const { Path path; T val=const_cast* >(&_graph)->eval_dual_norm(x.rawX(),&path.nodes); List*> paths; @@ -2273,7 +2273,7 @@ namespace FISTA { } scal= mm > 1.0 ? T(1.0)/mm : 1.0; val=0; - if (this->_intercept & (abs(input[input.n()-1]) > EPSILON)) val=INFINITY; + if (this->_intercept & (abs(input[input.n()-1]) > EPSILON)) val=INFINITY; }; private: GraphPath _graph; @@ -2283,29 +2283,29 @@ namespace FISTA { template class RegMat : public Regularizer > { public: - RegMat(const ParamReg& param) : Regularizer >(param) { + RegMat(const ParamReg& param) : Regularizer >(param) { _transpose=param.transpose; const int N = param.num_cols; _regs=new Reg*[N]; _N=N; - for (int i = 0; ireset(); }; void inline prox(const Matrix& x, Matrix& y, const T lambda) { y.copy(x); int i; if (_transpose) { -#pragma omp parallel for private(i) +#pragma omp parallel for private(i) for (i = 0; i<_N; ++i) { Vector colx, coly; x.copyRow(i,colx); @@ -2313,7 +2313,7 @@ namespace FISTA { y.setRow(i,coly); } } else { -#pragma omp parallel for private(i) +#pragma omp parallel for private(i) for (i = 0; i<_N; ++i) { Vector colx, coly; x.refCol(i,colx); @@ -2322,9 +2322,9 @@ namespace FISTA { } } }; - virtual bool is_subgrad() const { + virtual bool is_subgrad() const { bool ok=true; - for (int i = 0; i<_N; ++i) + for (int i = 0; i<_N; ++i) ok=ok && _regs[i]->is_subgrad(); return ok; }; @@ -2345,10 +2345,10 @@ namespace FISTA { } } }; - T inline eval(const Matrix& x) const { + T inline eval(const Matrix& x) const { T sum = 0; int i; -#pragma omp parallel for private(i) +#pragma omp parallel for private(i) for (i = 0; i<_N; ++i) { Vector col; if (_transpose) { @@ -2380,7 +2380,7 @@ namespace FISTA { }; virtual bool is_fenchel() const { bool ok=true; - for (int i = 0; i<_N; ++i) + for (int i = 0; i<_N; ++i) ok = ok && _regs[i]->is_fenchel(); return ok; }; @@ -2418,7 +2418,7 @@ namespace FISTA { y.toVect(yv); _graphlasso->prox(xv,yv,lambda); } - T inline eval(const Matrix& X) const { + T inline eval(const Matrix& X) const { Vector xv; X.toVect(xv); return _graphlasso->eval(xv); @@ -2440,7 +2440,7 @@ namespace FISTA { template class MixedL1LINFCR : public SpecGraphMat { public: - MixedL1LINFCR(const int m, const ParamReg& param) : SpecGraphMat(param) { + MixedL1LINFCR(const int m, const ParamReg& param) : SpecGraphMat(param) { const int n = param.num_cols; const T l2dl1 = param.lambda2d1; GraphStruct graph_st; @@ -2491,7 +2491,7 @@ namespace FISTA { template class TreeMult : public SpecGraphMat { public: - TreeMult(const ParamReg& param) : SpecGraphMat(param) { + TreeMult(const ParamReg& param) : SpecGraphMat(param) { const TreeStruct& tree_st=*(param.tree_st); const int N = param.num_cols; const T l1dl2 = param.lambda2d1; @@ -2575,7 +2575,7 @@ namespace FISTA { template class GraphMult : public SpecGraphMat { public: - GraphMult(const ParamReg& param) : SpecGraphMat(param) { + GraphMult(const ParamReg& param) : SpecGraphMat(param) { const GraphStruct& graph_st=*(param.graph_st); const int N = param.num_cols; const T l1dl2 = param.lambda2d1; @@ -2600,7 +2600,7 @@ namespace FISTA { for (int j = 0; j - T duality_gap(Loss& loss, Regularizer& regularizer, const D& x, + T duality_gap(Loss& loss, Regularizer& regularizer, const D& x, const T lambda, T& best_dual, const bool verbose = false) { if (!regularizer.is_fenchel() || !loss.is_fenchel()) { cerr << "Error: no duality gap available" << endl; @@ -2660,7 +2660,7 @@ namespace FISTA { T primal= loss.eval(x)+lambda*regularizer.eval(x); bool intercept=regularizer.is_intercept(); D grad1, grad2; - loss.var_fenchel(x,grad1,grad2,intercept); + loss.var_fenchel(x,grad1,grad2,intercept); T dual; grad2.scal(-T(1.0)/lambda); T val=0; @@ -2680,7 +2680,7 @@ namespace FISTA { } template - T duality_gap(Loss& loss, Regularizer& regularizer, const D& x, + T duality_gap(Loss& loss, Regularizer& regularizer, const D& x, const T lambda, const bool verbose = false) { T best_dual=-INFINITY; return duality_gap(loss,regularizer,x,lambda,best_dual,verbose); @@ -2688,7 +2688,7 @@ namespace FISTA { template void dualityGraph(const Matrix& X, const Matrix& D, const Matrix& alpha0, - Vector& res, const ParamFISTA& param, + Vector& res, const ParamFISTA& param, const GraphStruct* graph_st) { Regularizer* regularizer=new GraphLasso(*graph_st, param.intercept,param.resetflow,param.pos,param.clever); @@ -2725,7 +2725,7 @@ namespace FISTA { template - void subGradientDescent_Generic(Loss& loss, Regularizer& regularizer, const D& x0, D& x, + void subGradientDescent_Generic(Loss& loss, Regularizer& regularizer, const D& x0, D& x, Vector& optim_info, const ParamFISTA& param) { D grad; @@ -2743,13 +2743,13 @@ namespace FISTA { /// print loss if (param.verbose && ((it % it0) == 0)) { time.stop(); - T los=loss.eval(x) + lambda*regularizer.eval(x); + T los=loss.eval(x) + lambda*regularizer.eval(x); optim_info[0]=los; T sec=time.getElapsed(); cout << "Iter: " << it << ", loss: " << los << ", time: " << sec << " "; - if (param.log) + if (param.log) writeLog(it,sec,los,best_dual,param.logName); - if (param.verbose) + if (param.verbose) cout << endl; flush(cout); time.start(); @@ -2771,7 +2771,7 @@ namespace FISTA { } } if ((it % it0) != 0 || !param.verbose) { - T los=loss.eval(x) + lambda*regularizer.eval(x); + T los=loss.eval(x) + lambda*regularizer.eval(x); optim_info[0]=los; if (duality) { rel_duality_gap=duality_gap(loss,regularizer,x,lambda,best_dual,param.verbose); @@ -2817,7 +2817,7 @@ namespace FISTA { T sec=time.getElapsed(); cout << "Iter: " << it << ", loss: " << los << ", time: " << sec << ", L: " << L; flush(cout); - if (param.log) + if (param.log) writeLog(it,sec,los,best_dual,param.logName); time.start(); } @@ -2843,7 +2843,7 @@ namespace FISTA { break; } L *= param.gamma; - if (param.verbose && ((it % it0) == 0)) + if (param.verbose && ((it % it0) == 0)) cout << " " << L; ++iter; } @@ -2860,12 +2860,12 @@ namespace FISTA { regularizer.prox(prox,tmp,lambda/L); break; } - if (param.verbose && ((it % it0) == 0)) + if (param.verbose && ((it % it0) == 0)) cout << " " << L; ++iter; } } - if (param.verbose && ((it % it0) == 0)) + if (param.verbose && ((it % it0) == 0)) cout << endl; if (param.linesearch_mode==2) { sbb.copy(grad); @@ -2887,7 +2887,7 @@ namespace FISTA { if (sqrt(old.nrm2sq()/MAX(EPSILON,x.nrm2sq())) < param.tol) break; } } - T los=loss.eval(x) + lambda*regularizer.eval(x); + T los=loss.eval(x) + lambda*regularizer.eval(x); optim_info[0]=los; T sec=time.getElapsed(); if (param.verbose) { @@ -2931,12 +2931,12 @@ namespace FISTA { /// print loss if (param.verbose && ((it % it0) == 0)) { time.stop(); - T los=loss.eval(x) + lambda*regularizer.eval(x); + T los=loss.eval(x) + lambda*regularizer.eval(x); optim_info[0]=los; T sec=time.getElapsed(); cout << "Iter: " << it << ", loss: " << los << ", time: " << sec << ", L: " << L; flush(cout); - if (param.log) + if (param.log) writeLog(it,sec,los,best_dual,param.logName); time.start(); } @@ -2963,11 +2963,11 @@ namespace FISTA { regularizer.prox(prox,tmp,lambda/L); if ((param.linesearch_mode==2 && it > 1) || param.fixed_step || loss.test_backtracking(y,grad,tmp,L)) break; L *= param.gamma; - if (param.verbose && ((it % it0) == 0)) + if (param.verbose && ((it % it0) == 0)) cout << " " << L; ++iter; } - if (param.verbose && ((it % it0) == 0)) + if (param.verbose && ((it % it0) == 0)) cout << endl; prox.copy(x); @@ -3007,7 +3007,7 @@ namespace FISTA { }; template - T LagrangianADMM(const SplittingFunction >& loss, const SplittingFunction >& reg, + T LagrangianADMM(const SplittingFunction >& loss, const SplittingFunction >& reg, const T lambda, const T gamma, const Vector& w, const Matrix& splitted_loss, const SpMatrix& splitted_reg, const Matrix& multi_loss, const SpMatrix& multi_reg, T& los, const T* weights = NULL) { const int n_reg=reg.num_components(); @@ -3044,7 +3044,7 @@ namespace FISTA { splitted_w_loss.sum_cols(mean); w.copy(mean); multipliers_w_loss.sum_cols(mean); - w.add(mean,-T(1.0)/gamma); + w.add(mean,-T(1.0)/gamma); Vector number_occurences(w.n()); number_occurences.set(splitted_w_loss.n()); const int n_reg=splitted_w_reg.n(); @@ -3054,10 +3054,10 @@ namespace FISTA { for (int i = 0; i number_occurences(w.n()); number_occurences.set(splitted_w_loss.n()); const int n_reg=splitted_w_reg.n(); @@ -3094,11 +3094,11 @@ namespace FISTA { number_occurences[col.r(j)]+=inner_weights[j]*inner_weights[j]; } } - w.add(mean); + w.add(mean); mean.setZeros(); for (int i = 0; i - void ADMM(const SplittingFunction >& loss, const SplittingFunction >& reg, + void ADMM(const SplittingFunction >& loss, const SplittingFunction >& reg, const Vector& w0, Vector& w, Vector& optim_info, const ParamFISTA& param) { - const T gamma = param.c; + const T gamma = param.c; const int n_reg=reg.num_components(); const int it0 = MAX(1,param.it0); const T lambda=param.lambda; @@ -3151,7 +3151,7 @@ namespace FISTA { if (param.verbose) { cout << "Iter: " << it << ", loss: " << los << ", time: " << sec << endl; flush(cout); - if (param.log) + if (param.log) writeLog(it,sec,los,T(0),param.logName); } time.start(); @@ -3236,7 +3236,7 @@ namespace FISTA { for (int i = 0; i - void LinADMM(const SplittingFunction >& loss, const SplittingFunction >& reg, + void LinADMM(const SplittingFunction >& loss, const SplittingFunction >& reg, const Vector& w0, Vector& w, Vector& optim_info, const ParamFISTA& param) { - const T gamma = param.c; + const T gamma = param.c; const int n_reg=reg.num_components(); const int it0 = MAX(1,param.it0); const T lambda=param.lambda; @@ -3294,7 +3294,7 @@ namespace FISTA { if (param.verbose) { cout << "Iter: " << it << ", loss: " << los << ", time: " << sec << endl; flush(cout); - if (param.log) + if (param.log) writeLog(it,sec,los,T(0),param.logName); } time.start(); @@ -3465,7 +3465,7 @@ namespace FISTA { } else { cout << "ADMM algorithm" << endl; } - } + } } else { if (param.ista) { cout << "ISTA algorithm" << endl; @@ -3476,7 +3476,7 @@ namespace FISTA { } if ((param.regul == GRAPH || param.regul == TREEMULT || param.regul == GRAPHMULT || param.regul==L1LINFCR) && - param.clever) + param.clever) cout << "Projections with arc capacities" << endl; if (param.intercept) cout << "with intercept" << endl; if (param.pos) cout << "Non-negativity constraints" << endl; @@ -3497,9 +3497,9 @@ namespace FISTA { SplittingFunction >** losses, const ParamFISTA& param) { const int M = X.n(); optim_info.resize(4,M); - + int i1; -#pragma omp parallel for private(i1) +#pragma omp parallel for private(i1) for (i1 = 0; i1< M; ++i1) { #ifdef _OPENMP int numT=omp_get_thread_num(); @@ -3522,7 +3522,7 @@ namespace FISTA { } else { ADMM(*(losses[numT]),*(regularizers[numT]),alpha0i,alphai,optim_infoi,param); } - } + } } } @@ -3545,7 +3545,7 @@ namespace FISTA { optim_info.resize(4,M); int i1; -#pragma omp parallel for private(i1) +#pragma omp parallel for private(i1) for (i1 = 0; i1< M; ++i1) { #ifdef _OPENMP int numT=omp_get_thread_num(); @@ -3586,7 +3586,7 @@ namespace FISTA { optim_info.resize(4,M); int i2; -#pragma omp parallel for private(i2) +#pragma omp parallel for private(i2) for (i2 = 0; i2< M; ++i2) { #ifdef _OPENMP int numT=omp_get_thread_num(); @@ -3618,7 +3618,7 @@ namespace FISTA { template void solver(const Matrix& X, const AbstractMatrixB& D, const Matrix& alpha0, Matrix& alpha, const ParamFISTA& param1, Matrix& optim_info, - const GraphStruct* graph_st = NULL, + const GraphStruct* graph_st = NULL, const TreeStruct* tree_st = NULL, const GraphPathStruct* graph_path_st=NULL) { print_info_solver(param1); @@ -3665,9 +3665,9 @@ namespace FISTA { regularizers[i]=setRegularizerVectors(param,graph_st,tree_st,graph_path_st); switch (param.loss) { case SQUARE: if (param.compute_gram) { - losses[i]=new SqLoss(D,G); + losses[i]=new SqLoss(D,G); } else { - losses[i]=new SqLoss(D); + losses[i]=new SqLoss(D); } break; case POISSON: losses[i]=new PoissonLoss(D,param.delta); break; @@ -3717,16 +3717,16 @@ namespace FISTA { Regularizer >* regularizer; switch (param.loss) { case SQUARE: if (param.compute_gram) { - loss=new SqLossMat(D,G); + loss=new SqLossMat(D,G); } else { - loss=new SqLossMat(D); + loss=new SqLossMat(D); } break; case POISSON: loss=new LossMat >(X.n(),D,param.delta); break; case SQUARE_MISSING: loss=new LossMat >(X.n(),D); break; case LOG: loss = new LossMat >(X.n(),D); break; case LOGWEIGHT: loss = new LossMat >(X.n(),D); break; - case CUR: loss = new LossCur(D); break; + case CUR: loss = new LossCur(D); break; default: cerr << "Not implemented"; exit(1); } regularizer=setRegularizerMatrices(param,alpha0.m(),alpha0.n(),graph_st,tree_st,graph_path_st); @@ -3753,16 +3753,16 @@ namespace FISTA { template void PROX(const Matrix& alpha0, - Matrix& alpha, const ParamFISTA& param, + Matrix& alpha, const ParamFISTA& param, Vector& val_loss, - const GraphStruct* graph_st = NULL, + const GraphStruct* graph_st = NULL, const TreeStruct* tree_st = NULL, const GraphPathStruct* graph_path_st = NULL) { if (param.verbose) { print_regul(param.regul); if ((param.regul == GRAPH || param.regul == TREEMULT || param.regul == GRAPHMULT || param.regul==L1LINFCR) && - param.clever) + param.clever) cout << "Projections with arc capacities" << endl; if (param.intercept) cout << "with intercept" << endl; flush(cout); @@ -3777,13 +3777,13 @@ namespace FISTA { if (!regul_for_matrices(param.regul)) { Regularizer** regularizers= new Regularizer*[num_threads]; - for (int i = 0; i void EvalGraphPath(const Matrix& alpha0, - const ParamFISTA& param, + const ParamFISTA& param, Vector& val_loss, const GraphPathStruct* graph_path_st, SpMatrix* paths = NULL) { @@ -3836,12 +3836,12 @@ namespace FISTA { if (!regul_for_matrices(param.regul)) { Regularizer** regularizers= new Regularizer*[num_threads]; - for (int i = 0; i(param,NULL,NULL,graph_path_st); int i; val_loss.resize(M); -#pragma omp parallel for private(i) +#pragma omp parallel for private(i) for (i = 0; i< M; ++i) { #ifdef _OPENMP int numT=omp_get_thread_num(); From 22486fcfd072247bc1f872a29f3dcff7c8e63e9d Mon Sep 17 00:00:00 2001 From: Samuel St-Jean <3030760+samuelstjean@users.noreply.github.com> Date: Fri, 23 May 2025 07:44:30 -0400 Subject: [PATCH 3/3] Add changes to readme --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index aba4d536..67bc7fe8 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,14 @@ As such, I can probably help out with small stuff, but for technical and theoret You can find the original swig wrapper to re-generate these files on the branch swig_generator at https://github.com/samuelstjean/spams-python/tree/swig_generator This (unofficial) version includes pre-built wheels for python 3 on windows, mac (with openmp support) and linux and can be installed with ``pip install spams-bin``. + +# Improvements from the original version + ++ Automatic build system with meson ++ Pytest for testing ++ Newer swig wrappers ++ Fixed internal naming clash for newer openmp namespace and the orthogonal matching pursuit (omp) function ++ Fixed C++20 deprecation issues with templates ++ Fixed undefined behavior with openmp and passing 0 as the number of cores (it now defaults to 1) ++ Fixed a positivity bug with spams.lassoWeighted ++ Probably other stuff