3 #ifndef DISTNTF_DISTNTFNES_HPP_ 4 #define DISTNTF_DISTNTFNES_HPP_ 26 const int NUM_INNER_ITERS = 20;
28 double stop_iter_time;
33 inline double get_lambda(
double L,
double mu) {
47 inline double get_alpha(
double alpha,
double q) {
53 b = alpha * alpha - q;
55 D = b * b - 4 * a * c;
56 x = (-b + sqrt(D)) / 2;
60 bool stop_iter(
const int mode) {
63 double local_absmax, local_min, global_absmax, global_min;
65 if (m_nls_sizes[mode] > 0) {
67 (arma::abs(m_grad_t.
factor(mode) % m_acc_t.
factor(mode))).max();
69 MPI_Allreduce(&local_absmax, &global_absmax, 1, MPI_DOUBLE, MPI_MAX,
73 if (m_nls_sizes[mode] > 0) {
74 local_min = (m_grad_t.
factor(mode)).min();
76 MPI_Allreduce(&local_min, &global_min, 1, MPI_DOUBLE, MPI_MIN,
79 if (global_absmax <= delta1 && global_min >= -delta2) stop =
true;
86 if (iter > acc_start) {
87 int num_modes = m_prox_t.
modes();
90 double acc_step = std::pow(iter + 1, (1.0 / acc_exp));
94 int lowrank = m_prox_t.
rank();
95 MAT scalecur = arma::eye<MAT>(lowrank, lowrank);
96 MAT scaleprev = arma::eye<MAT>(lowrank, lowrank);
97 for (
int mode = 0; mode < num_modes; mode++) {
98 if (mode == num_modes - 1) {
99 scalecur = arma::diagmat(this->m_local_ncp_factors.lambda());
100 scaleprev = arma::diagmat(m_prev_t.
lambda());
104 acc_mat = (scalecur * this->m_local_ncp_factors_t.factor(mode)) -
105 (scaleprev * m_prev_t.
factor(mode));
107 acc_mat += (scalecur * this->m_local_ncp_factors_t.factor(mode));
109 if (m_nls_sizes[mode] == 0) {
112 m_acc_t.
set(mode, acc_mat);
113 m_acc_t.distributed_normalize_rows(mode);
117 double acc_err = this->computeError(m_acc_t, 0);
120 if (acc_err < cur_err) {
122 for (
int mode = 0; mode < num_modes; mode++) {
123 m_prox_t.
set(mode, m_acc_t.
factor(mode));
124 m_prox_t.distributed_normalize_rows(mode);
126 PRINTROOT(
"Acceleration Successful::relative_error::" << acc_err);
129 this->
reset(m_prox_t,
true);
131 if (acc_fails > fail_limit) {
135 PRINTROOT(
"Acceleration Failed::relative_error::" << acc_err);
140 MAT update(
const int mode) {
141 double L, mu,
lambda, q, alpha, alpha_prev, beta;
147 m_prev_t.
set(mode, m_prox_t.
factor(mode));
150 m_acc_t.
set(mode, Ht);
151 modified_gram = this->global_gram;
153 VEC eigval = arma::eig_sym(modified_gram);
157 lambda = get_lambda(L, mu);
158 modified_gram.diag() +=
lambda;
162 MAT modified_local_mttkrp_t =
163 (-1 *
lambda) * m_acc_t.
factor(mode) - this->ncp_local_mttkrp_t[mode];
169 while (iter < NUM_INNER_ITERS) {
170 m_grad_t.
set(mode, modified_local_mttkrp_t +
171 (modified_gram * m_acc_t.
factor(mode)));
172 if (stop_iter(mode))
break;
179 Ht.for_each([](MAT::elem_type &val) { val = val > 0.0 ? val : 0.0; });
182 alpha = get_alpha(alpha_prev, q);
184 (alpha_prev * (1 - alpha_prev)) / (alpha + alpha_prev * alpha_prev);
185 m_acc_t.
set(mode, Ht + beta * (Ht - Htprev));
187 if (m_nls_sizes[mode] == 0) {
189 m_grad_t.
set(mode, Ht);
191 PRINTROOT(
"Nesterov Update::mode::" << mode
192 <<
"::outer_iter::" << outer_iter
193 <<
"::NLS inner_iter::" << iter);
194 m_prox_t.
set(mode, Ht);
196 m_prox_t.distributed_normalize_rows(mode);
203 const UVEC &i_global_dims,
const UVEC &i_local_dims,
204 const UVEC &i_nls_sizes,
const UVEC &i_nls_idxs,
206 :
DistAUNTF(i_tensor, i_k, i_algo, i_global_dims, i_local_dims,
207 i_nls_sizes, i_nls_idxs, i_mpicomm),
208 m_prox_t(i_nls_sizes, i_k, true),
209 m_acc_t(i_nls_sizes, i_k, true),
210 m_grad_t(i_nls_sizes, i_k, true),
211 m_prev_t(i_nls_sizes, i_k, true) {
216 modified_gram.zeros(i_k, i_k);
224 stop_iter_time = 0.0;
231 PRINTROOT(
"::eigen time::" << eig_time <<
"::stop_iter_time::" 232 << stop_iter_time <<
"::proj_time::" << proj_time
233 <<
"::norm_time::" << norm_time);
239 #endif // DISTNTF_DISTNTFNES_HPP_ void accelerated(const bool &set_acceleration)
Does the algorithm need acceleration?
Data is stored such that the unfolding is column major.
#define EPSILON_1EMINUS16
void reset(const NCPFactors &new_factors, bool trans=false)
This function will completely reset all the factors and the state of AUNTF.
VEC lambda() const
returns the lambda vector
DistNTFNES(const Tensor &i_tensor, const int i_k, algotype i_algo, const UVEC &i_global_dims, const UVEC &i_local_dims, const UVEC &i_nls_sizes, const UVEC &i_nls_idxs, const NTFMPICommunicator &i_mpicomm)
void set(const int i_n, const MAT &i_factor)
Set the mode i_n with the given factor matrix.
int current_it() const
Returns the current outer iteration of the computeNTF.
void set_lambda(const VEC &new_lambda)
sets the lambda vector
double current_error() const
Returns the current error.
int rank() const
returns low rank
int modes() const
returns number of modes
void zeros()
this is for reinitializing zeros across different processors.
ncp_factors contains the factors of the ncp every ith factor is of size n_i * k number of factors is ...
MAT & factor(const int i_n) const
factor matrix of a mode i_n
VEC lambda()
Returns the lambda of the NCP factors.