| 319 | }; |
| 320 | |
| 321 | void get_A(T4 &X, T1 &y, Eigen::VectorXi &A, Eigen::VectorXi &I, int &C_max, T2 &beta, T3 &coef0, |
| 322 | Eigen::VectorXd &bd, int T0, Eigen::VectorXd &weights, Eigen::VectorXi &g_index, Eigen::VectorXi &g_size, |
| 323 | int N, double tau, double &train_loss) { |
| 324 | // Universal set: |
| 325 | // We only consider splicing on a set `U`, |
| 326 | // which may not contain all groups, but we hope all "useful" groups are included. |
| 327 | // We need to extract these groups out, e.g. `X`->`X_U`, `A`->`A_U`, |
| 328 | // and they have a new index from 0 to `U_size`-1. |
| 329 | Eigen::VectorXi U(this->U_size); |
| 330 | Eigen::VectorXi U_ind; |
| 331 | Eigen::VectorXi g_index_U(this->U_size); |
| 332 | Eigen::VectorXi g_size_U(this->U_size); |
| 333 | T4 *X_U = new T4; |
| 334 | T2 beta_U; |
| 335 | Eigen::VectorXi A_U(T0); |
| 336 | Eigen::VectorXi I_U(this->U_size - T0); |
| 337 | Eigen::VectorXi always_select_U(this->always_select.size()); |
| 338 | |
| 339 | if (this->U_size == N) { |
| 340 | // If `U_size` == `N`, focus on all groups. |
| 341 | U = Eigen::VectorXi::LinSpaced(N, 0, N - 1); |
| 342 | } else { |
| 343 | // If `U_size` < `N`, focus on `U_size` groups with larger sacrifices. |
| 344 | U = max_k(bd, this->U_size, true); |
| 345 | } |
| 346 | |
| 347 | // int p = X.cols(); |
| 348 | int n = X.rows(); |
| 349 | int C = C_max; |
| 350 | |
| 351 | // The outer iteration: |
| 352 | // 1. extract data from U |
| 353 | // 2. splicing & fitting on U (inner iteration), update active set |
| 354 | // 3. update U |
| 355 | // 4. if U changed, exit |
| 356 | int iter = 0; |
| 357 | while (iter++ < this->max_iter) { |
| 358 | // mapping |
| 359 | if (this->U_size == N) { |
| 360 | // If consider all groups, it is no need to map or give a new index. |
| 361 | delete X_U; |
| 362 | X_U = &X; |
| 363 | U_ind = Eigen::VectorXi::LinSpaced((this->beta).rows(), 0, (this->beta).rows() - 1); |
| 364 | beta_U = beta; |
| 365 | g_size_U = g_size; |
| 366 | g_index_U = g_index; |
| 367 | A_U = A; |
| 368 | I_U = I; |
| 369 | always_select_U = this->always_select; |
| 370 | } else { |
| 371 | // Extract `X`, `beta`, `g_index`, `g_size`, `always_select` on U, |
| 372 | // give them new index (from 0 to U_size-1), |
| 373 | // and name as `X_U`, `beta_U`, `g_index_U`, `g_size_U`, `always_select_U` respectively. |
| 374 | U_ind = find_ind(U, g_index, g_size, (this->beta).rows(), N); |
| 375 | *X_U = X_seg(X, n, U_ind, this->model_type); |
| 376 | slice(beta, U_ind, beta_U); |
| 377 | |
| 378 | int pos = 0; |