#ifndef LINREG_OVGLASSO_ADMM_H
#define LINREG_OVGLASSO_ADMM_H

#include <RcppArmadillo.h>
#include "ADMMutilsLM.h"

#define DOUBLE_EPS 2.220446e-16
#define ARMA_64BIT_WORD 1
#define SAFE_LOG(a) (((a) <= 0.0) ? log(DOUBLE_EPS) : log(a))
#define SAFE_ZERO(a) ((a) == 0 ? DOUBLE_EPS : (a))
#define SQRT_DOUBLE_EPS sqrt(DOUBLE_EPS)

using std::pow;
using std::exp;
using std::sqrt;
using std::log;

using namespace Rcpp;
using namespace arma;

/*
    Overlap Group-LASSO via ADMM, wrap functions
                                                  */

Rcpp::List admm_ovglasso(const arma::mat& A,
                         const arma::colvec& b,
                         const arma::mat& groups,
                         const arma::vec& group_weights,
                         const arma::vec& var_weights,
                         arma::colvec& u,
                         arma::colvec& z,
                         const double lambda,
                         const bool rho_adaptation,
                         double rho,
                         const double tau,
                         const double mu,
                         const double reltol,
                         const double abstol,
                         const int maxiter,
                         const int ping);

Rcpp::List admm_ovglasso_smo(const arma::mat& A,
                             const arma::colvec& b,
                             const arma::mat& groups,
                             const arma::vec& group_weights,
                             const arma::vec& var_weights,
                             arma::colvec& u,
                             arma::colvec& z,
                             const double lambda,
                             const double lambda2,
                             const int diff_order,
                             const bool rho_adaptation,
                             double rho,
                             const double tau,
                             const double mu,
                             const double reltol,
                             const double abstol,
                             const int maxiter,
                             const int ping);

Rcpp::List admm_ovglasso_cov(const arma::mat& W,
                             const arma::mat& Z,
                             const arma::vec& y,
                             arma::colvec& u,
                             arma::colvec& z,
                             const arma::mat& groups,
                             const arma::vec& group_weights,
                             const arma::vec& var_weights,
                             const double lambda,
                             const bool rho_adaptation,
                             double rho,
                             const double tau,
                             const double mu,
                             const double reltol,
                             const double abstol,
                             const int maxiter,
                             const int ping);

Rcpp::List admm_ovglasso_cov_smo(const arma::mat& W,
                                 const arma::mat& Z,
                                 const arma::vec& y,
                                 arma::colvec& u,
                                 arma::colvec& z,
                                 const arma::mat& groups,
                                 const arma::vec& group_weights,
                                 const arma::vec& var_weights,
                                 const double lambda,
                                 const double lambda2,
                                 const int diff_order,
                                 const bool rho_adaptation,
                                 double rho,
                                 const double tau,
                                 const double mu,
                                 const double reltol,
                                 const double abstol,
                                 const int maxiter,
                                 const int ping);

/*
    Overlap group-LASSO via ADMM: wrap functions, fast routines
                                                    */
Rcpp::List admm_ovglasso_fast(const arma::mat& A,
                              const arma::vec& b,
                              const arma::mat& groups,
                              const arma::vec& group_weights,
                              const arma::vec& var_weights,
                              const arma::vec& lambda,
                              const bool rho_adaptation,
                              double rho,
                              const double tau,
                              const double mu,
                              const double reltol,
                              const double abstol,
                              const int maxiter,
                              const int ping);

Rcpp::List admm_ovglasso_smo_fast(const arma::mat& A,
                                  const arma::vec& b,
                                  const arma::mat& groups,
                                  const arma::vec& group_weights,
                                  const arma::vec& var_weights,
                                  const arma::vec& lambda,
                                  const arma::vec& lambda2,
                                  const int diff_order,
                                  const bool rho_adaptation,
                                  double rho,
                                  const double tau,
                                  const double mu,
                                  const double reltol,
                                  const double abstol,
                                  const int maxiter,
                                  const int ping);

Rcpp::List admm_ovglasso_cov_fast(const arma::mat& W,
                                  const arma::mat& Z,
                                  const arma::vec& y,
                                  const arma::mat& groups,
                                  const arma::vec& group_weights,
                                  const arma::vec& var_weights,
                                  const arma::vec& lambda,
                                  const bool rho_adaptation,
                                  double rho,
                                  const double tau,
                                  const double mu,
                                  const double reltol,
                                  const double abstol,
                                  const int maxiter,
                                  const int ping);

Rcpp::List admm_ovglasso_cov_smo_fast(const arma::mat& W,
                                      const arma::mat& Z,
                                      const arma::vec& y,
                                      const arma::mat& groups,
                                      const arma::vec& group_weights,
                                      const arma::vec& var_weights,
                                      const arma::vec& lambda,
                                      const arma::vec& lambda2,
                                      const int diff_order,
                                      const bool rho_adaptation,
                                      double rho,
                                      const double tau,
                                      const double mu,
                                      const double reltol,
                                      const double abstol,
                                      const int maxiter,
                                      const int ping);

/*
    Sparse Overlap Group-LASSO via ADMM: wrap functions, to be used
                                  to fit the model once (single lambda)     */

/* ADMM with sparse OVGLASSO                                         */
Rcpp::List admm_spovglasso(const arma::mat& A,
                           const arma::colvec& b,
                           const arma::mat& groups,
                           const arma::vec& group_weights,
                           const arma::vec& var_weights,
                           const arma::vec& var_weights_L1,
                           arma::colvec& u,
                           arma::colvec& z,
                           const double lambda,
                           const double alpha,
                           const bool rho_adaptation,
                           double rho,
                           const double tau,
                           const double mu,
                           const double reltol,
                           const double abstol,
                           const int maxiter,
                           const int ping);

/* ADMM with OVGLASSO with covariates           */
Rcpp::List admm_spovglasso_cov(const arma::mat& W,
                               const arma::mat& Z,
                               const arma::vec& y,
                               arma::colvec& u,
                               arma::colvec& z,
                               const arma::mat& groups,
                               const arma::vec& group_weights,
                               const arma::vec& var_weights,
                               const arma::vec& var_weights_L1,
                               const double lambda,
                               const double alpha,
                               const bool rho_adaptation,
                               double rho,
                               const double tau,
                               const double mu,
                               const double reltol,
                               const double abstol,
                               const int maxiter,
                               const int ping);

/*
    Sparse Overlap Group-LASSO via ADMM: wrap functions, fast routines
                                  to be used to fit several times
                                  (multiple lambdas)                  */

/* ADMM with OVGLASSO, fast wrap                                         */
Rcpp::List admm_spovglasso_fast(const arma::mat& A,
                                const arma::vec& b,
                                const arma::mat& groups,
                                const arma::vec& group_weights,
                                const arma::vec& var_weights,
                                const arma::vec& var_weights_L1,
                                const arma::vec& lambda,
                                const double alpha,
                                const bool rho_adaptation,
                                double rho,
                                const double tau,
                                const double mu,
                                const double reltol,
                                const double abstol,
                                const int maxiter,
                                const int ping);

/* ADMM with OVGLASSO, fast wrap with covariates      */
Rcpp::List admm_spovglasso_cov_fast(const arma::mat& W,
                                    const arma::mat& Z,
                                    const arma::vec& y,
                                    const arma::mat& groups,
                                    const arma::vec& group_weights,
                                    const arma::vec& var_weights,
                                    const arma::vec& var_weights_L1,
                                    const arma::vec& lambda,
                                    const double alpha,
                                    const bool rho_adaptation,
                                    double rho,
                                    const double tau,
                                    const double mu,
                                    const double reltol,
                                    const double abstol,
                                    const int maxiter,
                                    const int ping);

/*
    Overlap Group-LASSO via ADMM: main functions, to be used
                                  to fit the model once (single lambda)     */

Rcpp::List admm_ovglasso_large_m(const arma::mat& A,
                                 const arma::colvec& b,
                                 const arma::mat& groups,
                                 const arma::vec& group_weights,
                                 const arma::vec& var_weights,
                                 arma::colvec& u,
                                 arma::colvec& z,
                                 const double lambda,
                                 const bool rho_adaptation,
                                 double rho,
                                 const double tau,
                                 const double mu,
                                 const double reltol,
                                 const double abstol,
                                 const int maxiter,
                                 const int ping);

Rcpp::List admm_ovglasso_smo_large_m(const arma::mat& A,
                                     const arma::colvec& b,
                                     const arma::mat& groups,
                                     const arma::vec& group_weights,
                                     const arma::vec& var_weights,
                                     arma::colvec& u,
                                     arma::colvec& z,
                                     const double lambda,
                                     const double lambda2,
                                     const int diff_order,
                                     const bool rho_adaptation,
                                     double rho,
                                     const double tau,
                                     const double mu,
                                     const double reltol,
                                     const double abstol,
                                     const int maxiter,
                                     const int ping);

Rcpp::List admm_ovglasso_large_n(const arma::mat& A,
                                 const arma::colvec& b,
                                 const arma::mat& groups,
                                 const arma::vec& group_weights,
                                 const arma::vec& var_weights,
                                 arma::colvec& u,
                                 arma::colvec& z,
                                 const double lambda,
                                 const bool rho_adaptation,
                                 double rho,
                                 const double tau,
                                 const double mu,
                                 const double reltol,
                                 const double abstol,
                                 const int maxiter,
                                 const int ping);

Rcpp::List admm_ovglasso_smo_large_n(const arma::mat& A,
                                     const arma::colvec& b,
                                     const arma::mat& groups,
                                     const arma::vec& group_weights,
                                     const arma::vec& var_weights,
                                     arma::colvec& u,
                                     arma::colvec& z,
                                     const double lambda,
                                     const double lambda2,
                                     const int diff_order,
                                     const bool rho_adaptation,
                                     double rho,
                                     const double tau,
                                     const double mu,
                                     const double reltol,
                                     const double abstol,
                                     const int maxiter,
                                     const int ping);

Rcpp::List admm_ovglasso_cov_large_m(const arma::mat& W,
                                     const arma::mat& Z,
                                     const arma::vec& y,
                                     arma::colvec& u,
                                     arma::colvec& z,
                                     const arma::mat& groups,
                                     const arma::vec& group_weights,
                                     const arma::vec& var_weights,
                                     const double lambda,
                                     const bool rho_adaptation,
                                     double rho,
                                     const double tau,
                                     const double mu,
                                     const double reltol,
                                     const double abstol,
                                     const int maxiter,
                                     const int ping);

Rcpp::List admm_ovglasso_cov_smo_large_m(const arma::mat& W,
                                         const arma::mat& Z,
                                         const arma::vec& y,
                                         arma::colvec& u,
                                         arma::colvec& z,
                                         const arma::mat& groups,
                                         const arma::vec& group_weights,
                                         const arma::vec& var_weights,
                                         const double lambda,
                                         const double lambda2,
                                         const int diff_order,
                                         const bool rho_adaptation,
                                         double rho,
                                         const double tau,
                                         const double mu,
                                         const double reltol,
                                         const double abstol,
                                         const int maxiter,
                                         const int ping);

Rcpp::List admm_ovglasso_cov_large_n(const arma::mat& W,
                                     const arma::mat& Z,
                                     const arma::vec& y,
                                     arma::colvec& u,
                                     arma::colvec& z,
                                     const arma::mat& groups,
                                     const arma::vec& group_weights,
                                     const arma::vec& var_weights,
                                     const double lambda,
                                     const bool rho_adaptation,
                                     double rho,
                                     const double tau,
                                     const double mu,
                                     const double reltol,
                                     const double abstol,
                                     const int maxiter,
                                     const int ping);

Rcpp::List admm_ovglasso_cov_smo_large_n(const arma::mat& W,
                                         const arma::mat& Z,
                                         const arma::vec& y,
                                         arma::colvec& u,
                                         arma::colvec& z,
                                         const arma::mat& groups,
                                         const arma::vec& group_weights,
                                         const arma::vec& var_weights,
                                         const double lambda,
                                         const double lambda2,
                                         const int diff_order,
                                         const bool rho_adaptation,
                                         double rho,
                                         const double tau,
                                         const double mu,
                                         const double reltol,
                                         const double abstol,
                                         const int maxiter,
                                         const int ping);

/*
    Overlap Group-LASSO via ADMM: main functions, to be used
                                  to fit the model several times
                                  (multiple lambdas)                  */

Rcpp::List admm_ovglasso_large_m_fast(const arma::mat& A,
                                      const arma::vec& b,
                                      const arma::mat& groups,
                                      const arma::vec& group_weights,
                                      const arma::vec& var_weights,
                                      const arma::vec& lambda,
                                      const bool rho_adaptation,
                                      const double rho,
                                      const double tau,
                                      const double mu,
                                      const double reltol,
                                      const double abstol,
                                      const int maxiter,
                                      const int ping);

Rcpp::List admm_ovglasso_smo_large_m_fast(const arma::mat& A,
                                          const arma::vec& b,
                                          const arma::mat& groups,
                                          const arma::vec& group_weights,
                                          const arma::vec& var_weights,
                                          const arma::vec& lambda,
                                          const arma::vec& lambda2,
                                          const int diff_order,
                                          const bool rho_adaptation,
                                          double rho,
                                          const double tau,
                                          const double mu,
                                          const double reltol,
                                          const double abstol,
                                          const int maxiter,
                                          const int ping);

Rcpp::List admm_ovglasso_large_n_fast(const arma::mat& A,
                                      const arma::vec& b,
                                      const arma::mat& groups,
                                      const arma::vec& group_weights,
                                      const arma::vec& var_weights,
                                      const arma::vec& lambda,
                                      const bool rho_adaptation,
                                      double rho,
                                      const double tau,
                                      const double mu,
                                      const double reltol,
                                      const double abstol,
                                      const int maxiter,
                                      const int ping);

Rcpp::List admm_ovglasso_smo_large_n_fast(const arma::mat& A,
                                          const arma::vec& b,
                                          const arma::mat& groups,
                                          const arma::vec& group_weights,
                                          const arma::vec& var_weights,
                                          const arma::vec& lambda,
                                          const arma::vec& lambda2,
                                          const int diff_order,
                                          const bool rho_adaptation,
                                          double rho,
                                          const double tau,
                                          const double mu,
                                          const double reltol,
                                          const double abstol,
                                          const int maxiter,
                                          const int ping);

Rcpp::List admm_ovglasso_cov_large_m_fast(const arma::mat& W,
                                          const arma::mat& Z,
                                          const arma::vec& y,
                                          const arma::mat& groups,
                                          const arma::vec& group_weights,
                                          const arma::vec& var_weights,
                                          const arma::vec lambda,
                                          const bool rho_adaptation,
                                          double rho,
                                          const double tau,
                                          const double mu,
                                          const double reltol,
                                          const double abstol,
                                          const int maxiter,
                                          const int ping);

Rcpp::List admm_ovglasso_cov_smo_large_m_fast(const arma::mat& W,
                                              const arma::mat& Z,
                                              const arma::vec& y,
                                              const arma::mat& groups,
                                              const arma::vec& group_weights,
                                              const arma::vec& var_weights,
                                              const arma::vec& lambda,
                                              const arma::vec& lambda2,
                                              const int diff_order,
                                              bool rho_adaptation,
                                              double rho,
                                              const double tau,
                                              const double mu,
                                              const double reltol,
                                              const double abstol,
                                              const int maxiter,
                                              const int ping);

Rcpp::List admm_ovglasso_cov_large_n_fast(const arma::mat& W,
                                          const arma::mat& Z,
                                          const arma::vec& y,
                                          const arma::mat& groups,
                                          const arma::vec& group_weights,
                                          const arma::vec& var_weights,
                                          const arma::vec& lambda,
                                          const bool rho_adaptation,
                                          double rho,
                                          const double tau,
                                          const double mu,
                                          const double reltol,
                                          const double abstol,
                                          const int maxiter,
                                          const int ping);

Rcpp::List admm_ovglasso_cov_smo_large_n_fast(const arma::mat& W,
                                              const arma::mat& Z,
                                              const arma::vec& y,
                                              const arma::mat& groups,
                                              const arma::vec& group_weights,
                                              const arma::vec& var_weights,
                                              const arma::vec& lambda,
                                              const arma::vec& lambda2,
                                              const int diff_order,
                                              const bool rho_adaptation,
                                              double rho,
                                              const double tau,
                                              const double mu,
                                              const double reltol,
                                              const double abstol,
                                              const int maxiter,
                                              const int ping);

/*
    Overlap Group-LASSO via ADMM: functions to fit a single lambda
*/

Rcpp::List admm_ovglasso_large_m_update_1lambda(const arma::mat& A,
                                                const arma::vec& b,
                                                const arma::colvec& Glen,
                                                const arma::mat& groups,
                                                const arma::vec& group_weights,
                                                const arma::vec& var_weights,
                                                const arma::sp_mat& F,
                                                const arma::mat& FTF,
                                                const arma::mat& ATA,
                                                const arma::mat& ATA_CHOL_U,
                                                const arma::colvec& ATb,
                                                const double b2,
                                                const int m,
                                                const int n,
                                                const int G,
                                                arma::colvec& u,
                                                arma::colvec& z,
                                                const double lambda,
                                                const bool rho_adaptation,
                                                double rho,
                                                const double tau,
                                                const double mu,
                                                const double reltol,
                                                const double abstol,
                                                const int maxiter,
                                                const int ping);

Rcpp::List admm_ovglasso_smo_large_m_update_1lambda(const arma::mat& A,
                                                    const arma::vec& b,
                                                    const arma::colvec& Glen,
                                                    const arma::mat& groups,
                                                    const arma::vec& group_weights,
                                                    const arma::vec& var_weights,
                                                    const arma::sp_mat& F,
                                                    const arma::mat& FTF,
                                                    const arma::mat& DTD,
                                                    const arma::mat& ATA,
                                                    const arma::mat& ATA_CHOL_U,
                                                    const arma::colvec& ATb,
                                                    const double b2,
                                                    const int m,
                                                    const int n,
                                                    const int G,
                                                    arma::colvec& u,
                                                    arma::colvec& z,
                                                    const double lambda,
                                                    const double lambda2,
                                                    bool rho_adaptation,
                                                    double rho,
                                                    const double tau,
                                                    const double mu,
                                                    const double reltol,
                                                    const double abstol,
                                                    const int maxiter,
                                                    const int ping);

Rcpp::List admm_ovglasso_large_n_update_1lambda(const arma::mat& A,
                                                const arma::vec& b,
                                                const arma::colvec& Glen,
                                                const arma::mat& groups,
                                                const arma::vec& group_weights,
                                                const arma::vec& var_weights,
                                                const arma::sp_mat& F,
                                                const arma::mat& FTF_INV,
                                                const arma::mat& AFTF_INVA,
                                                const arma::mat& ATA_CHOL_U,
                                                const arma::colvec& ATb,
                                                const double b2,
                                                const int m,
                                                const int n,
                                                const int G,
                                                arma::colvec& u,
                                                arma::colvec& z,
                                                const double lambda,
                                                const bool rho_adaptation,
                                                double rho,
                                                const double tau,
                                                const double mu,
                                                const double reltol,
                                                const double abstol,
                                                const int maxiter,
                                                const int ping);

Rcpp::List admm_ovglasso_smo_large_n_update_1lambda(const arma::mat& A,
                                                    const arma::vec& b,
                                                    const arma::colvec& Glen,
                                                    const arma::mat& groups,
                                                    const arma::vec& group_weights,
                                                    const arma::vec& var_weights,
                                                    const arma::sp_mat& F,
                                                    const arma::mat& FTF_INV,
                                                    const arma::mat& At,
                                                    const arma::mat& AtFTF_INVAt,
                                                    const arma::mat& ATA_CHOL_U,
                                                    const arma::colvec& ATb,
                                                    const double b2,
                                                    const int m,
                                                    const int n,
                                                    const int G,
                                                    arma::colvec& u,
                                                    arma::colvec& z,
                                                    const double lambda,
                                                    const double lambda2,
                                                    const bool rho_adaptation,
                                                    double rho,
                                                    const double tau,
                                                    const double mu,
                                                    const double reltol,
                                                    const double abstol,
                                                    const int maxiter,
                                                    const int ping);

Rcpp::List admm_ovglasso_cov_large_m_update_1lambda(const arma::mat& W,
                                                    const arma::mat& Z,
                                                    const arma::vec& y,
                                                    const arma::colvec& Glen,
                                                    const arma::mat& groups,
                                                    const arma::vec& group_weights,
                                                    const arma::vec& var_weights,
                                                    const int G,
                                                    const arma::sp_mat& F,
                                                    const arma::mat& FTF,
                                                    const arma::mat& WMW,
                                                    const arma::vec& WMy,
                                                    const arma::vec& v_LS,
                                                    const arma::mat& P_ZW,
                                                    const arma::mat& WW_CHOL_U,
                                                    const arma::colvec& Wy,
                                                    const double y2,
                                                    const arma::mat& ZZ_CHOL_U,
                                                    const arma::colvec& Zy,
                                                    const arma::mat& ZW,
                                                    arma::colvec& u,
                                                    arma::colvec& z,
                                                    const double lambda,
                                                    const bool rho_adaptation,
                                                    double rho,
                                                    const double tau,
                                                    const double mu,
                                                    const double reltol,
                                                    const double abstol,
                                                    const int maxiter,
                                                    const int ping);

Rcpp::List admm_ovglasso_cov_smo_large_m_update_1lambda(const arma::mat& W,
                                                        const arma::mat& Z,
                                                        const arma::vec& y,
                                                        const arma::colvec& Glen,
                                                        const arma::mat& groups,
                                                        const arma::vec& group_weights,
                                                        const arma::vec& var_weights,
                                                        const int G,
                                                        const arma::sp_mat& F,
                                                        const arma::mat& FTF,
                                                        const arma::mat& DTD,
                                                        const arma::mat& WMW,
                                                        const arma::vec& WMy,
                                                        const arma::vec& v_LS,
                                                        const arma::mat& P_ZW,
                                                        const arma::mat& WW_CHOL_U,
                                                        const arma::colvec& Wy,
                                                        const double y2,
                                                        const arma::mat& ZZ_CHOL_U,
                                                        const arma::colvec& Zy,
                                                        const arma::mat& ZW,
                                                        arma::colvec& u,
                                                        arma::colvec& z,
                                                        const double lambda,
                                                        const double lambda2,
                                                        bool rho_adaptation,
                                                        double rho,
                                                        const double tau,
                                                        const double mu,
                                                        const double reltol,
                                                        const double abstol,
                                                        const int maxiter,
                                                        const int ping);

Rcpp::List admm_ovglasso_cov_large_n_update_1lambda(const arma::mat& W,
                                                    const arma::mat& Z,
                                                    const arma::vec& y,
                                                    const arma::colvec& Glen,
                                                    const arma::mat& groups,
                                                    const arma::vec& group_weights,
                                                    const arma::vec& var_weights,
                                                    const int G,
                                                    const arma::sp_mat& F,
                                                    const arma::mat& FF_INV,
                                                    const arma::mat& M_ZZW,
                                                    const arma::mat& M_ZZW2,
                                                    const arma::mat& WMW,
                                                    const arma::vec& WMy,
                                                    const arma::vec& v_LS,
                                                    const arma::mat& P_ZW,
                                                    const arma::mat& WW_CHOL_U,
                                                    const arma::colvec& Wy,
                                                    const double y2,
                                                    const arma::mat& ZZ_CHOL_U,
                                                    const arma::colvec& Zy,
                                                    const arma::mat& ZW,
                                                    arma::colvec& u,
                                                    arma::colvec& z,
                                                    const double lambda,
                                                    const bool rho_adaptation,
                                                    double rho,
                                                    const double tau,
                                                    const double mu,
                                                    const double reltol,
                                                    const double abstol,
                                                    const int maxiter,
                                                    const int ping);

Rcpp::List admm_ovglasso_cov_smo_large_n_update_1lambda(const arma::mat& W,
                                                        const arma::mat& Z,
                                                        const arma::vec& y,
                                                        const arma::colvec& Glen,
                                                        const arma::mat& groups,
                                                        const arma::vec& group_weights,
                                                        const arma::vec& var_weights,
                                                        const int G,
                                                        const arma::sp_mat& F,
                                                        const arma::mat& FTF_INV,
                                                        const arma::mat& DTD,
                                                        const arma::mat& At,
                                                        const arma::mat& AtFTF_INVAt,
                                                        const arma::mat& M_ZZW,
                                                        const arma::mat& WMW,
                                                        const arma::vec& WMy,
                                                        const arma::vec& v_LS,
                                                        const arma::mat& P_ZW,
                                                        const arma::mat& WW_CHOL_U,
                                                        const arma::colvec& Wy,
                                                        const double y2,
                                                        const arma::mat& ZZ_CHOL_U,
                                                        const arma::colvec& Zy,
                                                        const arma::mat& ZW,
                                                        arma::colvec& u,
                                                        arma::colvec& z,
                                                        const double lambda,
                                                        const double lambda2,
                                                        const bool rho_adaptation,
                                                        double rho,
                                                        const double tau,
                                                        const double mu,
                                                        const double reltol,
                                                        const double abstol,
                                                        const int maxiter,
                                                        const int ping);

/*
    Sparse Overlap Group-LASSO via ADMM: main functions, to be used
                                  to fit the model once (single lambda)     */

Rcpp::List admm_spovglasso_large_m(const arma::mat& A,
                                   const arma::vec& b,
                                   const arma::mat& groups,
                                   const arma::vec& group_weights,
                                   const arma::vec& var_weights,
                                   const arma::vec& var_weights_L1,
                                   arma::colvec& u,
                                   arma::colvec& z,
                                   const double lambda1,
                                   const double lambda2,
                                   const bool rho_adaptation,
                                   double rho,
                                   const double tau,
                                   const double mu,
                                   const double reltol,
                                   const double abstol,
                                   const int maxiter,
                                   const int ping);

Rcpp::List admm_spovglasso_large_n(const arma::mat& A,
                                   const arma::vec& b,
                                   const arma::mat& groups,
                                   const arma::vec& group_weights,
                                   const arma::vec& var_weights,
                                   const arma::vec& var_weights_L1,
                                   arma::colvec& u,
                                   arma::colvec& z,
                                   const double lambda1,
                                   const double lambda2,
                                   const bool rho_adaptation,
                                   double rho,
                                   const double tau,
                                   const double mu,
                                   const double reltol,
                                   const double abstol,
                                   const int maxiter,
                                   const int ping);

Rcpp::List admm_spovglasso_cov_large_m(const arma::mat& W,
                                       const arma::mat& Z,
                                       const arma::vec& y,
                                       arma::colvec& u,
                                       arma::colvec& z,
                                       const arma::mat& groups,
                                       const arma::vec& group_weights,
                                       const arma::vec& var_weights,
                                       const arma::vec& var_weights_L1,
                                       const double lambda,
                                       const double alpha,
                                       const bool rho_adaptation,
                                       double rho,
                                       const double tau,
                                       const double mu,
                                       const double reltol,
                                       const double abstol,
                                       const int maxiter,
                                       const int ping);

Rcpp::List admm_spovglasso_cov_large_n(const arma::mat& W,
                                       const arma::mat& Z,
                                       const arma::vec& y,
                                       arma::colvec& u,
                                       arma::colvec& z,
                                       const arma::mat& groups,
                                       const arma::vec& group_weights,
                                       const arma::vec& var_weights,
                                       const arma::vec& var_weights_L1,
                                       const double lambda,
                                       const double alpha,
                                       const bool rho_adaptation,
                                       double rho,
                                       const double tau,
                                       const double mu,
                                       const double reltol,
                                       const double abstol,
                                       const int maxiter,
                                       const int ping);

/*
    Sparse Overlap Group-LASSO via ADMM: main functions, to be used
                                  to fit the model several times
                                  (multiple lambdas)                  */

Rcpp::List admm_spovglasso_large_m_fast(const arma::mat& A,
                                        const arma::vec& b,
                                        const arma::mat& groups,
                                        const arma::vec& group_weights,
                                        const arma::vec& var_weights,
                                        const arma::vec& var_weights_L1,
                                        const arma::vec& lambda,
                                        const double alpha,
                                        const bool rho_adaptation,
                                        double rho,
                                        const double tau,
                                        const double mu,
                                        const double reltol,
                                        const double abstol,
                                        const int maxiter,
                                        const int ping);

Rcpp::List admm_spovglasso_large_n_fast(const arma::mat& A,
                                        const arma::vec& b,
                                        const arma::mat& groups,
                                        const arma::vec& group_weights,
                                        const arma::vec& var_weights,
                                        const arma::vec& var_weights_L1,
                                        const arma::vec& lambda,
                                        const double alpha,
                                        const bool rho_adaptation,
                                        double rho,
                                        const double tau,
                                        const double mu,
                                        const double reltol,
                                        const double abstol,
                                        const int maxiter,
                                        const int ping);

Rcpp::List admm_spovglasso_cov_large_m_fast(const arma::mat& W,
                                            const arma::mat& Z,
                                            const arma::vec& y,
                                            const arma::mat& groups,
                                            const arma::vec& group_weights,
                                            const arma::vec& var_weights,
                                            const arma::vec& var_weights_L1,
                                            const arma::vec& lambda,
                                            const double alpha,
                                            const bool rho_adaptation,
                                            double rho,
                                            const double tau,
                                            const double mu,
                                            const double reltol,
                                            const double abstol,
                                            const int maxiter,
                                            const int ping);

Rcpp::List admm_spovglasso_cov_large_n_fast(const arma::mat& W,
                                            const arma::mat& Z,
                                            const arma::vec& y,
                                            const arma::mat& groups,
                                            const arma::vec& group_weights,
                                            const arma::vec& var_weights,
                                            const arma::vec& var_weights_L1,
                                            const arma::vec& lambda,
                                            const double alpha,
                                            const bool rho_adaptation,
                                            double rho,
                                            const double tau,
                                            const double mu,
                                            const double reltol,
                                            const double abstol,
                                            const int maxiter,
                                            const int ping);

/*
    Overlap Group-LASSO via ADMM: functions to fit a single lambda
*/

Rcpp::List admm_spovglasso_large_m_update_1lambda(const arma::mat& A,
                                                  const arma::vec& b,
                                                  const arma::mat& groups,
                                                  const arma::vec& group_weights,
                                                  const arma::vec& var_weights,
                                                  const arma::vec& var_weights_L1,
                                                  const arma::sp_mat& F,
                                                  const arma::mat& FTF,
                                                  const arma::mat& ATA,
                                                  const arma::mat& ATA_CHOL_U,
                                                  const arma::colvec& ATb,
                                                  const double b2,
                                                  const int m,
                                                  const int n,
                                                  const int G,
                                                  arma::colvec& u,
                                                  arma::colvec& z,
                                                  const double lambda,
                                                  const double alpha,
                                                  const bool rho_adaptation,
                                                  double rho,
                                                  const double tau,
                                                  const double mu,
                                                  const double reltol,
                                                  const double abstol,
                                                  const int maxiter,
                                                  const int ping);

Rcpp::List admm_spovglasso_large_n_update_1lambda(const arma::mat& A,
                                                  const arma::vec& b,
                                                  const arma::mat& groups,
                                                  const arma::vec& group_weights,
                                                  const arma::vec& var_weights,
                                                  const arma::vec& var_weights_L1,
                                                  const arma::sp_mat& F,
                                                  const arma::mat& FTF_INV,
                                                  const arma::mat& AFTF_INVA,
                                                  const arma::mat& ATA_CHOL_U,
                                                  const arma::colvec& ATb,
                                                  const double b2,
                                                  const int m,
                                                  const int n,
                                                  const int G,
                                                  arma::colvec& u,
                                                  arma::colvec& z,
                                                  const double lambda,
                                                  const double alpha,
                                                  const bool rho_adaptation,
                                                  double rho,
                                                  const double tau,
                                                  const double mu,
                                                  const double reltol,
                                                  const double abstol,
                                                  const int maxiter,
                                                  const int ping);

Rcpp::List admm_spovglasso_cov_large_m_update_1lambda(const arma::mat& W,
                                                      const arma::mat& Z,
                                                      const arma::vec& y,
                                                      const arma::mat& groups,
                                                      const arma::vec& group_weights,
                                                      const arma::vec& var_weights,
                                                      const arma::vec& var_weights_L1,
                                                      const int G,
                                                      const arma::sp_mat& F,
                                                      const arma::mat& FTF,
                                                      const arma::mat& WMW,
                                                      const arma::vec& WMy,
                                                      const arma::vec& v_LS,
                                                      const arma::mat& P_ZW,
                                                      const arma::mat& WW_CHOL_U,
                                                      const arma::colvec& Wy,
                                                      const double y2,
                                                      const arma::mat& ZZ_CHOL_U,
                                                      const arma::colvec& Zy,
                                                      const arma::mat& ZW,
                                                      arma::colvec& u,
                                                      arma::colvec& z,
                                                      const double lambda,
                                                      const double alpha,
                                                      const bool rho_adaptation,
                                                      double rho,
                                                      const double tau,
                                                      const double mu,
                                                      const double reltol,
                                                      const double abstol,
                                                      const int maxiter,
                                                      const int ping);

Rcpp::List admm_spovglasso_cov_large_n_update_1lambda(const arma::mat& W,
                                                      const arma::mat& Z,
                                                      const arma::vec& y,
                                                      const arma::mat& groups,
                                                      const arma::vec& group_weights,
                                                      const arma::vec& var_weights,
                                                      const arma::vec& var_weights_L1,
                                                      const int G,
                                                      const arma::sp_mat& F,
                                                      const arma::mat& FF_INV,
                                                      const arma::mat& M_ZZW,
                                                      const arma::mat& M_ZZW2,
                                                      const arma::mat& WMW,
                                                      const arma::vec& WMy,
                                                      const arma::vec& v_LS,
                                                      const arma::mat& P_ZW,
                                                      const arma::mat& WW_CHOL_U,
                                                      const arma::colvec& Wy,
                                                      const double y2,
                                                      const arma::mat& ZZ_CHOL_U,
                                                      const arma::colvec& Zy,
                                                      const arma::mat& ZW,
                                                      arma::colvec& u,
                                                      arma::colvec& z,
                                                      const double lambda,
                                                      const double alpha,
                                                      const bool rho_adaptation,
                                                      double rho,
                                                      const double tau,
                                                      const double mu,
                                                      const double reltol,
                                                      const double abstol,
                                                      const int maxiter,
                                                      const int ping);


















#endif
