Files
mlpack/fastlib/branches/fastlib-cmake/contrib/pram/sparsepca/sparsepca.cc
T

1013 lines
25 KiB
C++

/**
* @author Parikshit Ram (pram@cc.gatech.edu)
* @file sparsepca.cc
*
* Implementation of the functions of the class SparsePCA
* declared in the file 'sparsepca.h'
*
*/
#include "sparsepca.h"
void SparsePCA::SparsifyMicroArray() {
Matrix alpha_mat, beta_mat, temp_mat;
index_t k = fx_param_int_req(spca_module_, "K");
index_t d = fx_param_int_req(spca_module_, "D");
index_t MAX_ITERS = fx_param_int(spca_module_, "MAX_ITERS", 200);
double EPS = fx_param_double(spca_module_, "EPS", 1.0e-3);
// alpha <- V[:,1:k]
v().MakeColumnSlice(0, k, &temp_mat);
alpha_mat.Copy(temp_mat);
beta_mat.Init(d, k);
beta_mat.SetZero();
// for i <- 1 to K
// y <- X_centered^T * X_centered * alpha_i ;
// beta_i <- Soft_(y, lambda_1i);
for (index_t i = 0; i < k; i++) {
Vector alpha_i_vec, beta_i_vec, y_vec, temp_vec;
alpha_mat.MakeColumnVector(i, &alpha_i_vec);
la::MulInit(alpha_i_vec, x_centered(), &temp_vec);
la::MulInit(x_centered(), temp_vec, &y_vec);
beta_mat.MakeColumnVector(i, &beta_i_vec);
Soft_(y_vec, &beta_i_vec, lambda_L1(i));
}
Matrix x_trans_x_mat, temp_beta_mat, temp_x_trans_mat;
la::TransposeInit(x_centered(), &temp_x_trans_mat);
la::MulInit(x_centered(), temp_x_trans_mat, &x_trans_x_mat);
// temp_beta_i = beta_i / || beta_i ||, i = 1, 2, ..., K
temp_beta_mat.Copy(beta_mat);
for (index_t i = 1; i < k; i++) {
Vector temp_beta_i_vec;
temp_beta_mat.MakeColumnVector(i, &temp_beta_i_vec);
double norm_temp_beta_i = sqrt(la::Dot(temp_beta_i_vec,
temp_beta_i_vec));
if (norm_temp_beta_i == 0.0) {
norm_temp_beta_i = 1;
}
la::Scale(norm_temp_beta_i, &temp_beta_i_vec);
}
index_t iters = 0;
double difference = 1.0;
while ((iters < MAX_ITERS) && (difference > EPS)) {
++iters;
// U * L * V^T = SVD(X^T * X * beta)
// alpha <- U * V^T
Matrix u_mat, v_t_mat;
Vector dummy_vec;
la::MulOverwrite(x_trans_x_mat, beta_mat, &alpha_mat);
success_t svd_op = la::SVDInit(alpha_mat, &dummy_vec,
&u_mat, &v_t_mat);
DEBUG_ASSERT_MSG(svd_op == SUCCESS_PASS,
"SVD of X^T*X*beta failed\n");
la::MulOverwrite(u_mat, v_t_mat, &alpha_mat);
// for i <- 1 to K
// y = X_centered^T * X_centered * alpha_i
// beta_i <- Soft_(y, lambda_1i);
for (index_t i = 0; i < k; i++) {
Vector alpha_i_vec, beta_i_vec, y_vec, temp_vec;
alpha_mat.MakeColumnVector(i, &alpha_i_vec);
la::MulInit(alpha_i_vec, x_centered(), &temp_vec);
la::MulInit(x_centered(), temp_vec, &y_vec);
beta_mat.MakeColumnVector(i, &beta_i_vec);
Soft_(y_vec, &beta_i_vec, lambda_L1(i));
}
// beta_2_i = beta_i / || beta_i ||, i = 1, 2, ..., K
Matrix beta_2_mat;
beta_2_mat.Copy(beta_mat);
for (index_t i = 1; i < k; i++) {
Vector beta_2_i_vec;
beta_2_mat.MakeColumnVector(i, &beta_2_i_vec);
double norm_beta_i = sqrt(la::Dot(beta_2_i_vec,
beta_2_i_vec));
if (norm_beta_i == 0.0) {
norm_beta_i = 1;
}
la::Scale(norm_beta_i, &beta_2_i_vec);
}
// Noting the difference between previous beta
// and the present beta
// difference <- max( |beta_2 - temp_beta| );
la::SubFrom(beta_2_mat, &temp_beta_mat);
difference = MaxAbsValue_(temp_beta_mat);
// temp_beta <- beta_2
temp_beta_mat.CopyValues(beta_2_mat);
}
set_v_sparse(temp_beta_mat);
// R <- qr.R(qr(X_centered * V_sparse))
// explainedvariance <- sum(diag(R^2))
Matrix x_centered_v_sparse_mat, q_mat, r_mat;
la::MulInit(temp_x_trans_mat, v_sparse(), &x_centered_v_sparse_mat);
success_t qr_op = la::QRInit(x_centered_v_sparse_mat, &q_mat, &r_mat);
DEBUG_ASSERT_MSG(qr_op == SUCCESS_PASS,
"Sparsify() : Q * R = X * V_sparse failed\n");
DEBUG_ASSERT_MSG(k == r_mat.n_cols(), "Sparsify() : K != dim(R)\n");
double var = 0.0;
for (index_t i = 0; i < r_mat.n_cols(); i++) {
double temp_var = r_mat.get(i, i);
var += temp_var * temp_var;
}
set_var_explained(var);
return;
}
void SparsePCA::Soft_(Vector& a_vec, Vector *beta_vec, double lambda_1) {
Vector temp_beta_vec, a_sign_vec;
Matrix temp_a_sign_mat;
index_t vec_length = a_vec.length();
// beta <- |a| - lambda_1 / 2
// beta <- (beta + |beta|) / 2
temp_beta_vec.Init(vec_length);
for (index_t i = 0; i < vec_length; i++) {
temp_beta_vec.ptr()[i] = fabs(a_vec.get(i)) - lambda_1 / 2;
temp_beta_vec.ptr()[i] = fabs(temp_beta_vec.get(i)) + temp_beta_vec.get(i);
}
la::Scale(0.5, &temp_beta_vec);
// beta <- sign(a) * beta
a_sign_vec.Init(vec_length);
for (index_t i = 0; i < vec_length; i++) {
a_sign_vec.ptr()[i] = a_vec.get(i) > 0 ? 1 : -1;
}
temp_a_sign_mat.Init(vec_length, vec_length);
temp_a_sign_mat.SetZero();
temp_a_sign_mat.SetDiagonal(a_sign_vec);
la::MulOverwrite(temp_a_sign_mat, temp_beta_vec, beta_vec);
return;
}
void SparsePCA::Sparsify() {
Matrix alpha_mat, beta_mat, temp_mat;
index_t k = fx_param_int_req(spca_module_, "K");
index_t d = fx_param_int_req(spca_module_, "D");
index_t MAX_ITERS = fx_param_int(spca_module_, "MAX_ITERS", 200);
double EPS = fx_param_double(spca_module_, "EPS", 1.0e-3);
// alpha <- V[:,1:k]
v().MakeColumnSlice(0, k, &temp_mat);
alpha_mat.Copy(temp_mat);
beta_mat.Init(d, k);
beta_mat.SetZero();
// for i <- 1 to K
// y <- X_centered * alpha_i ;
// beta_i <- SolveForBeta_(X_centered, y, lambda_2, lambda_1i);
for (index_t i = 0; i < k; i++) {
Vector alpha_i_vec, beta_i_vec, y_vec;
alpha_mat.MakeColumnVector(i, &alpha_i_vec);
la::MulInit(alpha_i_vec, x_centered(), &y_vec);
beta_mat.MakeColumnVector(i, &beta_i_vec);
SolveForBeta_(y_vec, &beta_i_vec, lambda_quad(), lambda_L1(i));
}
Matrix x_trans_x_mat, temp_beta_mat, temp_x_trans_mat;
la::TransposeInit(x_centered(), &temp_x_trans_mat);
la::MulInit(x_centered(), temp_x_trans_mat, &x_trans_x_mat);
// temp_beta_i = beta_i / || beta_i ||, i = 1, 2, ..., K
temp_beta_mat.Copy(beta_mat);
for (index_t i = 1; i < k; i++) {
Vector temp_beta_i_vec;
temp_beta_mat.MakeColumnVector(i, &temp_beta_i_vec);
double norm_temp_beta_i = sqrt(la::Dot(temp_beta_i_vec,
temp_beta_i_vec));
if (norm_temp_beta_i == 0.0) {
norm_temp_beta_i = 1;
}
la::Scale(norm_temp_beta_i, &temp_beta_i_vec);
}
index_t iters = 0;
double difference = 1.0;
while ((iters < MAX_ITERS) && (difference > EPS)) {
++iters;
// U * L * V^T = SVD(X^T * X * beta)
// alpha <- U * V^T
Matrix u_mat, v_t_mat;
Vector dummy_vec;
la::MulOverwrite(x_trans_x_mat, beta_mat, &alpha_mat);
success_t svd_op = la::SVDInit(alpha_mat, &dummy_vec,
&u_mat, &v_t_mat);
DEBUG_ASSERT_MSG(svd_op == SUCCESS_PASS,
"SVD of X^T*X*beta failed\n");
la::MulOverwrite(u_mat, v_t_mat, &alpha_mat);
// for i <- 1 to K
// y = X_centered * alpha_i
// beta_i <- SolveForBeta_(X_centered, y, lambda_2, lambda_1i);
for (index_t i = 0; i < k; i++) {
Vector alpha_i_vec, beta_i_vec, y_vec;
alpha_mat.MakeColumnVector(i, &alpha_i_vec);
la::MulInit(alpha_i_vec, x_centered(), &y_vec);
beta_mat.MakeColumnVector(i, &beta_i_vec);
SolveForBeta_(y_vec, &beta_i_vec, lambda_quad(), lambda_L1(i));
}
// beta_2_i = beta_i / || beta_i ||, i = 1, 2, ..., K
Matrix beta_2_mat;
beta_2_mat.Copy(beta_mat);
for (index_t i = 1; i < k; i++) {
Vector beta_2_i_vec;
beta_2_mat.MakeColumnVector(i, &beta_2_i_vec);
double norm_beta_i = sqrt(la::Dot(beta_2_i_vec,
beta_2_i_vec));
if (norm_beta_i == 0.0) {
norm_beta_i = 1;
}
la::Scale(norm_beta_i, &beta_2_i_vec);
}
// Noting the difference between previous beta
// and the present beta
// difference <- max( |beta_2 - temp_beta| );
la::SubFrom(beta_2_mat, &temp_beta_mat);
difference = MaxAbsValue_(temp_beta_mat);
// temp_beta <- beta_2
temp_beta_mat.CopyValues(beta_2_mat);
}
set_v_sparse(temp_beta_mat);
// R <- qr.R(qr(X_centered * V_sparse))
// explainedvariance <- sum(diag(R^2))
Matrix x_centered_v_sparse_mat, q_mat, r_mat;
la::MulInit(temp_x_trans_mat, v_sparse(), &x_centered_v_sparse_mat);
success_t qr_op = la::QRInit(x_centered_v_sparse_mat, &q_mat, &r_mat);
DEBUG_ASSERT_MSG(qr_op == SUCCESS_PASS,
"Sparsify() : Q * R = X * V_sparse failed\n");
DEBUG_ASSERT_MSG(k == r_mat.n_cols(), "Sparsify() : K != dim(R)\n");
double var = 0.0;
for (index_t i = 0; i < r_mat.n_cols(); i++) {
double temp_var = r_mat.get(i, i);
var += temp_var * temp_var;
}
set_var_explained(var);
return;
}
void SparsePCA::SolveForBeta_(Vector& y_vec, Vector *beta_vec,
double lambda_2, double lambda_1) {
datanode *solver_module = fx_submodule(spca_module_, "BetaSolver");
index_t n = x_centered().n_cols(), d = x_centered().n_rows();
index_t max_vars = -1;
double d1 = sqrt(lambda_2), d2 = 1.0 / sqrt(1 + lambda_2);
Vector c_vec, residual_1_vec, residual_2_vec;
double EPS = fx_param_double(solver_module, "EPS", 1.0e-3);
ArrayList<double> penalties;
c_vec.Init(d);
residual_1_vec.Init(n);
residual_2_vec.Init(d);
if (lambda_2 > 0) {
max_vars = d;
}
if (lambda_2 == 0) {
if (d == n) {
max_vars = d;
}
else {
max_vars = (d < n - 1) ? d : n - 1;
}
}
index_t MAX_STEPS = fx_param_int(solver_module, "MAX_STEPS", 50*max_vars);
// Cvec <- X^T * y / sqrt(1 + lambda_2);
la::MulExpert(d2, x_centered(), y_vec, 0.0, &c_vec);
// residuals <- [ y 0_D ]
residual_1_vec.CopyValues(y_vec);
residual_2_vec.SetZero();
// penalty <- max(abs(Cvec))
penalties.Init(1);
penalties[0] = MaxAbsValue_(c_vec);
if (penalties[0] * 2 / d2 <= lambda_1) {
beta_vec->SetZero();
}
else {
beta_vec->SetZero();
// active <- EMPTY, ignore <- EMPTY
index_t active = 1, ignore = 2, inactive = 0, undecided = 3;
index_t *beta_var_state;
ArrayList<index_t> active_set;
beta_var_state = (index_t*) malloc (d * sizeof(index_t));
for (index_t i = 0; i < d; i++) {
beta_var_state[i] = inactive;
}
active_set.Init(0);
// Sign <- NULL
double *beta_sign;
beta_sign = (double*) malloc (d * sizeof(double));
for (index_t i = 0; i < d; i++) {
beta_sign[i] = 0;
}
// R <- NULL
Matrix r_mat;
r_mat.Init(0, 0);
index_t rank_r = 0;
// drops = FALSE
bool drops = 0;
index_t iters = 0;
Vector c_inactive_vec;
c_inactive_vec.Init(0);
Matrix x_trans_mat, x_active_mat;
la::TransposeInit(x_centered(), &x_trans_mat);
x_active_mat.Init(0,0);
// while iters < MAX_STEPS & |A| < max_vars - |I|
while ((iters < MAX_STEPS) &&
(SubsetLength_(beta_var_state, d, active)
< max_vars - SubsetLength_(beta_var_state, d, ignore))) {
++iters;
// INACTIVE_SET <- (A union I)^C
// C_INACTIVE <- {C_j}, j \in INACTIVE_SET
// C_MAX <- max(abs(C_INACTIVE))
MakeSubvector_(c_vec, beta_var_state, inactive, &c_inactive_vec);
// index_t c_max_index;
double c_max = MaxAbsValue_(c_inactive_vec);
if (!drops) {
// new_indices <- {j : j \in INACTIVE_SET & |C_j| == C_MAX}
// C_INACTIVE <- C_INACTIVE - {C_j : j \in new_indices}
ArrayList<index_t> new_indices;
new_indices.Init(0);
for (index_t i = 0, j = 0; i < d; i++) {
if (beta_var_state[i] == inactive) {
if (fabs(c_inactive_vec.get(j)) == c_max) {
beta_var_state[i] = undecided;
*(new_indices.AddBack()) = i;
}
j++;
}
}
MakeSubvector_(c_vec, beta_var_state, inactive, &c_inactive_vec);
for (index_t i = 0; i < new_indices.size(); i++) {
// R <- updateR(x_i, X_ACTIVE, R, lambda_2)
MakeSubmatrix_(x_trans_mat, active_set, &x_active_mat);
Vector x_i_vec;
x_trans_mat.MakeColumnVector(new_indices[i], &x_i_vec);
UpdateR_(x_i_vec, x_active_mat, lambda_2, &rank_r, &r_mat);
// if rank(R) == |A|
if(rank_r == SubsetLength_(beta_var_state, d, active)) {
// IGNORE <- IGNORE union {new_indices[i]}
DEBUG_ASSERT_MSG(beta_var_state[new_indices[i]] == undecided,
"SolveForBeta_() : Addition to Ignore list failed\n");
beta_var_state[new_indices[i]] = ignore;
}
else {
// ACTIVE <- ACTIVE union {new_indices[i]}
DEBUG_ASSERT_MSG(beta_var_state[new_indices[i]] == undecided,
"SolveForBeta_() : Addition to Active list failed\n");
beta_var_state[new_indices[i]] = active;
*(active_set.AddBack()) = new_indices[i];
// Sign <- Sign union sign(Cvec[new_indices[i]])
DEBUG_ASSERT_MSG(c_vec.get(new_indices[i]) != 0.0,
"SolveForBeta() : C_vec(i) == 0\n");
beta_sign[new_indices[i]] = c_vec.get(new_indices[i]) > 0 ? 1 : -1;
}
} // end for
} // end if
// G_i <- v such that R^T * R * v = Sign_ACTIVE
Vector beta_sign_vec, beta_sign_active_vec;
Matrix r_trans_mat, r_trans_r_mat;
Vector g_i_vec;
beta_sign_vec.Copy(beta_sign, d);
beta_sign_active_vec.Init(0);
la::TransposeInit(r_mat, &r_trans_mat);
la::MulInit(r_trans_mat, r_mat, &r_trans_r_mat);
// Making Sign_ACTIVE
MakeSubvector_(beta_sign_vec, active_set, &beta_sign_active_vec);
success_t solve_op = la::SolveInit(r_trans_r_mat,
beta_sign_active_vec, &g_i_vec);
DEBUG_ASSERT_MSG(solve_op == SUCCESS_PASS,
"SolveForBeta_() : R^T * R * G_i = Sign_ACTIVE failed\n");
// A <- 1 / sqrt( sum_{j=1}^{|ACTIVE|} G_i_j * Sign_ACTIVE_j
Matrix diag_g_i_mat;
Vector one_vec, temp_g_i_sign_vec;
double a, temp_sum_g_i_sign;
diag_g_i_mat.Init(active_set.size(), active_set.size());
diag_g_i_mat.SetDiagonal(g_i_vec);
one_vec.Init(active_set.size());
one_vec.SetAll(1.0);
la::MulInit(diag_g_i_mat, beta_sign_active_vec, &temp_g_i_sign_vec);
temp_sum_g_i_sign = la::Dot(temp_g_i_sign_vec, one_vec);
a = 1 / sqrt(temp_sum_g_i_sign);
// w <- A * G_i
Vector w_vec;
la::ScaleInit(a, g_i_vec, &w_vec);
// u1 <- X_ACTIVE * w * d2
// u2 <- [0]_m
// u2_ACTIVE <- d1 * d2 * w
Vector u1_vec, u2_vec;
MakeSubmatrix_(x_trans_mat, active_set, &x_active_mat);
la::MulInit(x_active_mat, w_vec, &u1_vec);
la::Scale(d2, &u1_vec);
u2_vec.Init(d);
u2_vec.SetZero();
for (index_t i = 0; i < active_set.size(); i++) {
u2_vec.ptr()[active_set[i]] = d1 * d2 * w_vec.get(i);
}
if (lambda_2 > 0) {
max_vars = d - SubsetLength_(beta_var_state, d, ignore);
}
if (lambda_2 == 0) {
max_vars = (d - SubsetLength_(beta_var_state, d, ignore)) < (n - 1) ?
(d - SubsetLength_(beta_var_state, d, ignore)) : (n - 1);
}
double gam_hat;
Vector a_vec;
a_vec.Init(SubsetLength_(beta_var_state, d, inactive));
if (SubsetLength_(beta_var_state, d, active) ==
max_vars - SubsetLength_(beta_var_state, d, ignore)) {
gam_hat = c_max / a;
}
else {
// a <- u1 * X_INACTIVE + d1 * u2_INACTIVE * d2
Matrix x_inactive_mat;
Vector u2_inactive_vec;
x_inactive_mat.Init(0, 0);
u2_inactive_vec.Init(0);
MakeSubmatrix_(x_trans_mat, beta_var_state, inactive, &x_inactive_mat);
la::MulOverwrite(u1_vec, x_inactive_mat, &a_vec);
MakeSubvector_(u2_vec, beta_var_state, inactive, &u2_inactive_vec);
la::AddExpert(d1 * d2, u2_inactive_vec, &a_vec);
// gam <- { (Cmax - c_i)/(A - a_i), (Cmax + c_i)/(A + a_i) }
// for all i in INACTIVE
// gam_hat <- min( gam (gam > EPS), Cmax / A)
double temp_val, gam = FLT_MAX;
for (index_t i = 0; i < a_vec.length(); i++) {
temp_val = (c_max - c_inactive_vec.get(i)) / (a - a_vec.get(i));
if (temp_val > EPS) {
if (temp_val < gam) {
gam = temp_val;
}
}
temp_val = (c_max + c_inactive_vec.get(i)) / (a - a_vec.get(i));
if (temp_val > EPS) {
if (temp_val < gam) {
gam = temp_val;
}
}
}
temp_val = c_max / a;
if (temp_val > gam) {
gam_hat = gam;
}
else {
gam_hat = temp_val;
}
}
// z1 <- - beta_ACTIVE / w
// zmin <- min (z1[z1 > EPS], gam_hat)
// if zmin < gam_hat
// gam_hat <- zmin
// drop_indices <- z1 == zmin
// drop <- TRUE
// else
// drop <- FALSE
Vector beta_active_vec, z1_vec;
beta_active_vec.Init(0);
z1_vec.Init(SubsetLength_(beta_var_state, d, active));
MakeSubvector_(*beta_vec, active_set, &beta_active_vec);
for (index_t i = 0; i < z1_vec.length(); i++) {
z1_vec.ptr()[i] = - beta_active_vec.get(i) / w_vec.get(i);
}
double zmin = gam_hat;
for (index_t i = 0; i < z1_vec.length(); i++) {
if (z1_vec.get(i) > EPS) {
if (z1_vec.get(i) < zmin) {
zmin = z1_vec.get(i);
}
}
}
ArrayList<index_t> drop_indices;
drop_indices.Init(0);
if (zmin < gam_hat) {
drops = 1;
gam_hat = zmin;
for (index_t i = 0; i < z1_vec.length(); i++) {
if (zmin == z1_vec.get(i)) {
*(drop_indices.AddBack()) = i;
}
}
}
else {
drops = 0;
}
// temp_beta <- beta
Vector temp_beta_vec;
temp_beta_vec.Copy(*beta_vec);
// beta_ACTIVE <- beta_ACTIVE + gam_hat * w
for (index_t i = 0; i < active_set.size(); i++) {
beta_vec->ptr()[active_set[i]] =
beta_vec->get(active_set[i]) + gam_hat * w_vec.get(i);
}
// residuals <- residuals - gam_hat * u
la::AddExpert(-gam_hat, u1_vec, &residual_1_vec);
la::AddExpert(-gam_hat, u2_vec, &residual_2_vec);
// Cvec <- residuals[1:N] * X + d1 * residuals[N+1:N+D] * d2
la::MulOverwrite(residual_1_vec, x_trans_mat, &c_vec);
la::AddExpert(d1 * d2, residual_2_vec, &c_vec);
// penalties <- penalties union penalties[k-1] - abs(gam_hat*A)
*(penalties.AddBack()) = penalties[iters - 1] - fabs(gam_hat * a);
// exit strategy
if (*(penalties.end()) * 2 / d2 <= lambda_1) {
double s1 = *(penalties.PopBackPtr()) * 2 / d2;
double s2 = *(penalties.end()) * 2 / d2;
double factor_1 = (s2 - lambda_1) / (s2 - s1);
double factor_2 = (lambda_1 - s1) / (s2 - s1);
la::Scale(factor_1, beta_vec);
la::AddExpert(factor_2, temp_beta_vec, beta_vec);
la::Scale(d2, beta_vec);
return;
}
// if drops
// for i in reverse(drop_indices)
// drop i in active set
// drop i from sign set
// downdateR(R, i)
if (drops) {
for (index_t i = drop_indices.size(); i > 0; i--) {
index_t id = drop_indices[i - 1];
DowndateR_(&r_mat, id);
--rank_r;
}
ArrayList<index_t> temp_active_set;
temp_active_set.Init(active_set.size() - drop_indices.size());
for (index_t i = 0, j = 0; i < active_set.size(); i++) {
if (j < drop_indices.size()) {
if (i == drop_indices[j]) {
beta_vec->ptr()[active_set[i]] = 0;
beta_sign[active_set[i]] = 0;
beta_var_state[active_set[i]] = inactive;
j++;
}
else {
temp_active_set[i - j] = active_set[i];
}
}
else {
temp_active_set[i - j] = active_set[i];
}
}
active_set.Destruct();
active_set.Init(temp_active_set.size());
for (index_t i = 0; i < active_set.size(); i++) {
active_set[i] = temp_active_set[i];
}
}// end if
}// end while
}// end else
return;
}
void SparsePCA::UpdateR_(Vector& a_vec, Matrix& old_mat,
double lambda, index_t *rank_r, Matrix *r_mat) {
double a_trans_a = (la::Dot(a_vec, a_vec) + lambda) / (1 + lambda);
double a_norm = sqrt(a_trans_a);
double EPS = 1.0e-5;
if (*rank_r == 0) {
r_mat->Destruct();
r_mat->Init(1, 1);
r_mat->set(0, 0, a_norm);
*rank_r = 1;
return;
}
Vector a_old_vec;
la::MulInit(a_vec, old_mat, &a_old_vec);
Matrix r_trans_mat;
la::TransposeInit(*r_mat, &r_trans_mat);
Vector r_vec;
success_t solve_op = la::SolveInit(r_trans_mat, a_old_vec, &r_vec);
DEBUG_ASSERT_MSG(solve_op == SUCCESS_PASS,
"UpdateR_():system of equation could not be solved\n");
double rpp = a_trans_a - la::Dot(r_vec, r_vec);
if (rpp < EPS) {
return;
}
else {
rpp = sqrt(rpp);
*rank_r = *rank_r + 1;
}
Matrix temp_r_mat;
temp_r_mat.Init(*rank_r, *rank_r);
temp_r_mat.SetZero();
for (index_t i = 0; i < *rank_r - 1; i++) {
for(index_t j = 0; j < i + 1; j++) {
temp_r_mat.set(j, i, r_mat->get(j, i));
}
}
for (index_t i = 0; i < *rank_r - 1; i++) {
temp_r_mat.set(i, *rank_r - 1, r_vec.get(i));
}
temp_r_mat.set(*rank_r - 1, *rank_r - 1, rpp);
r_mat->Destruct();
r_mat->Copy(temp_r_mat);
return;
}
void SparsePCA::DowndateR_(Matrix *r_mat, index_t col_id) {
index_t rank = r_mat->n_cols();
if(rank == 1) {
r_mat->Destruct();
r_mat->Init(0, 0);
return;
}
else {
Matrix temp_r_mat;
temp_r_mat.Init(rank - 1, rank - 1);
temp_r_mat.SetZero();
for (index_t i = 0; i < col_id; i++) {
for (index_t j = 0; j < i + 1; j++) {
temp_r_mat.set(j, i, r_mat->get(j, i));
}
}
for (index_t i = col_id + 1; i < rank; i++) {
double a = r_mat->get(i - 1, i);
double b = r_mat->get(i, i);
double x, y, z;
if (fabs(b) > fabs(a)) {
x = - a / b;
y = 1 / sqrt(1 + x*x);
z = x * y;
}
else {
x = -b / a;
z = 1 / sqrt(1 + x*x);
y = z * x;
}
r_mat->set(i - 1, i, (z*a - y*b));
r_mat->set(i, i, (y*a - z*b));
for (index_t j = i + 1; j < rank; ++j) {
a = r_mat->get(i - 1, j);
b = r_mat->get(i, j);
r_mat->set(i - 1, j, (z*a - y*b));
r_mat->set(i, j, (y*a - z*b));
}
}
for (index_t i = col_id; i < rank - 1; i++) {
for (index_t j = 0; j < i + 1; j++) {
temp_r_mat.set(j, i, r_mat->get(j, i+1));
}
}
r_mat->Destruct();
r_mat->Copy(temp_r_mat);
return;
}
}
double SparsePCA::MaxAbsValue_(Matrix& mat) {
double max_val = 0.0;
double *ptr_mat, *ptr_end;
ptr_mat = mat.ptr();
ptr_end = mat.ptr() + mat.n_elements();
for (; ptr_mat < ptr_end; ptr_mat++) {
if (max_val < fabs(*ptr_mat)) {
max_val = fabs(*ptr_mat);
}
}
return max_val;
}
double SparsePCA::MaxAbsValue_(Vector& vec) {
double max_val = 0.0;
double *ptr_vec, *ptr_end;
ptr_vec = vec.ptr();
ptr_end = vec.ptr() + vec.length();
for (; ptr_vec < ptr_end; ptr_vec++) {
if (max_val < fabs(*ptr_vec)) {
max_val = fabs(*ptr_vec);
}
}
return max_val;
}
double SparsePCA::MaxAbsValue_(Vector& vec, index_t *max_index) {
double max_val = 0.0;
double *ptr_vec, *ptr_end;
ptr_vec = vec.ptr();
ptr_end = vec.ptr() + vec.length();
for (index_t i = 0; ptr_vec < ptr_end; ptr_vec++, i++) {
if (max_val < fabs(*ptr_vec)) {
max_val = fabs(*ptr_vec);
*max_index = i;
}
}
return max_val;
}
index_t SparsePCA::SubsetLength_(index_t *set, index_t set_size,
index_t subset_marker) {
index_t length = 0;
for (index_t i = 0; i < set_size; i++) {
if (set[i] == subset_marker) {
++length;
}
}
return length;
}
void SparsePCA::MakeSubvector_(Vector& vec, index_t *set,
index_t subset_marker, Vector *subvec) {
index_t set_length = vec.length();
double *subarray;
subarray = (double*)malloc(set_length * sizeof(double));
index_t j = 0;
for (index_t i = 0; i < set_length; i++) {
if (set[i] == subset_marker) {
subarray[j] = vec.get(i);
++j;
}
}
subvec->Destruct();
subvec->Copy(subarray, j);
return;
}
void SparsePCA::MakeSubvector_(Vector& vec,
ArrayList<index_t>& set, Vector *subvec) {
if (set.size() == 0) {
subvec->Destruct();
subvec->Init(0);
return;
}
else {
double *subarray;
subarray = (double*)malloc(set.size() * sizeof(double));
for (index_t i = 0; i < set.size(); i++) {
subarray[i] = vec.get(set[i]);
}
subvec->Destruct();
subvec->Copy(subarray, set.size());
return;
}
}
void SparsePCA::MakeSubmatrix_(Matrix& mat, index_t *set,
index_t subset_marker, Matrix *submatrix) {
index_t set_length = mat.n_cols(), col_length = mat.n_rows(), subset_length;
double *submatrix_array;
subset_length = SubsetLength_(set, set_length, subset_marker);
submatrix_array =
(double*)malloc(col_length * subset_length * sizeof(double));
index_t j = 0;
for (index_t i = 0; i < set_length; i++) {
if (set[i] == subset_marker) {
double *col_ptr;
col_ptr = mat.GetColumnPtr(i);
index_t start = j * col_length;
for (index_t k = 0; k < col_length; k++) {
submatrix_array[k + start] = col_ptr[k];
}
++j;
}
}
DEBUG_ASSERT_MSG(j == subset_length, "MakeSubmatrix_(): X_A.n_cols() != |A|\n");
submatrix->Destruct();
submatrix->Copy(submatrix_array, col_length, subset_length);
return;
}
void SparsePCA::MakeSubmatrix_(Matrix& mat,
ArrayList<index_t>& set, Matrix *submatrix) {
if (set.size() == 0) {
submatrix->Destruct();
submatrix->Init(0, 0);
return;
}
else {
index_t set_length = set.size(), col_length = mat.n_rows();
double *submatrix_array;
submatrix_array =
(double*)malloc(col_length * set_length * sizeof(double));
for (index_t i = 0; i < set_length; i++) {
double *col_ptr;
col_ptr = mat.GetColumnPtr(set[i]);
index_t start = i * col_length;
for (index_t k = 0; k < col_length; k++) {
submatrix_array[k + start] = col_ptr[k];
}
}
submatrix->Destruct();
submatrix->Copy(submatrix_array, col_length, set_length);
return;
}
}