Esempio n. 1
0
//' Fast addition of vector to each row of matrix
//'
//' @description Fast addition of vector to each row of a matrix. This corresponds to t(t(x) + v)
//' @param x A matrix with dimensions n*k.
//' @param v A vector of length k.
//' @return A matrix of dimension n*k where v is added to each row of x
//' @author Claus Ekstrom <claus@@rprimer.dk>
//' @examples
//'
//' A <- matrix(1:12, ncol=3)
//' B <- c(1, 2, 3)
//'
//' add_torows(A, B)
//'
//' @export
// [[Rcpp::export]]
arma::mat add_torows(const arma::mat &x, const arma::rowvec &v) {

  if (x.n_cols != v.n_elem) {
     stop("Non-conformable objects. Length of v does not match columns in x");
  }

  arma::mat m = x.each_row() + v;
  
  return (m);
}
arma::cx_mat generate_visibilities_from_local_skymodel(arma::mat& skymodel, arma::mat& uvw_baselines)
{
    arma::cx_mat model_vis(uvw_baselines.n_rows, 1);
    model_vis.zeros();

    skymodel.each_row([&](arma::rowvec& src_entry) {
        model_vis += visibilities_for_point_source(uvw_baselines, src_entry[0], src_entry[1], src_entry[2]);
    });

    return std::move(model_vis);
}
Esempio n. 3
0
unsigned int optCoef(arma::mat& weights, const arma::icube& obs, const arma::cube& emission,
    const arma::mat& initk, const arma::cube& beta, const arma::mat& scales, arma::mat& coef,
    const arma::mat& X, const arma::ivec& cumsumstate, const arma::ivec& numberOfStates,
    int trace) {

  int iter = 0;
  double change = 1.0;
  while ((change > 1e-10) & (iter < 100)) {
    arma::vec tmpvec(X.n_cols * (weights.n_rows - 1));
    bool solve_ok = arma::solve(tmpvec, hCoef(weights, X),
        gCoef(obs, beta, scales, emission, initk, weights, X, cumsumstate, numberOfStates));
    if (solve_ok == false) {
      return (4);
    }

    arma::mat coefnew(coef.n_rows, coef.n_cols - 1);
    for (unsigned int i = 0; i < (weights.n_rows - 1); i++) {
      coefnew.col(i) = coef.col(i + 1) - tmpvec.subvec(i * X.n_cols, (i + 1) * X.n_cols - 1);
    }
    change = arma::accu(arma::abs(coef.submat(0, 1, coef.n_rows - 1, coef.n_cols - 1) - coefnew))
        / coefnew.n_elem;
    coef.submat(0, 1, coef.n_rows - 1, coef.n_cols - 1) = coefnew;
    iter++;
    if (trace == 3) {
      Rcout << "coefficient optimization iter: " << iter;
      Rcout << " new coefficients: " << std::endl << coefnew << std::endl;
      Rcout << " relative change: " << change << std::endl;
    }
    weights = exp(X * coef).t();
    if (!weights.is_finite()) {
      return (5);
    }
    weights.each_row() /= sum(weights, 0);

  }
  return (0);
}
Esempio n. 4
0
///
/// \brief Vespucci::MathDimensionReduction::plsregress PLS Regression Using SIMPLS algorithm.
/// This is essentially a line-for-line rewrite of plsregress from the Octave
/// statistics package.
/// Copyright (C) 2012 Fernando Damian Nieuwveldt <*****@*****.**>
/// This is an implementation of the SIMPLS algorithm:
/// Reference: SIMPLS: An alternative approach to partial least squares regression.
/// Chemometrics and Intelligent Laboratory Systems (1993)
/// \param x
/// \param y
/// \param components Number of PLS components
/// \param x_loadings "Output" values
/// \param y_loadings
/// \param x_scores
/// \param y_scores
/// \param coefficients
/// \param fitted_data
/// \return
///
bool Vespucci::Math::DimensionReduction::plsregress(arma::mat X, arma::mat Y,
                                                    int components, arma::mat &X_loadings,
                                                    arma::mat &Y_loadings,
                                                    arma::mat &X_scores,
                                                    arma::mat &Y_scores,
                                                    arma::mat &coefficients,
                                                    arma::mat &percent_variance,
                                                    arma::mat &fitted)
{
    using namespace arma;
    uword observations = X.n_rows;
    uword predictors = X.n_cols;
    uword responses = Y.n_cols;
    //Mean centering
    mat Xmeans = arma::mean(X);
    mat Ymeans = arma::mean(Y);
    //Octave does below with bsxfun. After optimization, this should hopefully not
    // be slower.
    X.each_row() -= Xmeans; //element-wise subtraction of mean
    Y.each_row() -= Ymeans; //same

    mat S = trans(X) * Y;
    mat R = zeros(predictors, components);
    mat P = R;
    mat V = R;
    mat T = zeros(observations, components);
    mat U = T;
    mat Q = zeros(responses, components);
    mat eigvec;
    vec eigval;

    mat q;
    mat r;
    mat t;
    mat nt;
    mat p;
    mat u;
    mat v;
    double max_eigval;
    for (int i = 0; i < components; ++i){
        eig_sym(eigval, eigvec, (trans(S) * S));
        max_eigval = eigval.max();
        uvec dom_index = find(eigval >= max_eigval);
        uword dominant_index = dom_index(0);

        q = eigvec.col(dominant_index);

        r = S*q; //X block factor weights
        t = X*r; //X block factor weights
        t.each_row() -= mean(t); //center t
        nt = arma::sqrt(t.t()*t); //compute norm (is arma::norm() the same?)
        t.each_row() /= nt;
        r.each_row() /= nt; //normalize

        p = X.t()*t; //X block factor loadings
        q = Y.t()*t; //Y block factor loadings
        u = Y*q; //Y block factor scores
        v = p;

        //Ensure orthogonality
        if (i > 0){
            v = v - V*(V.t()*p);
            u = u - T*(T.t()*u);
        }
        v.each_row() /= arma::sqrt(trans(v) * v); //normalize orthogonal loadings
        S = S - v * (trans(v)*S); //deflate S wrt loadings
        R.col(i) = r;
        T.col(i) = t;
        P.col(i) = p;
        Q.col(i) = q;
        U.col(i) = u;
        V.col(i) = v;
    }

    //Regression coefficients
    mat B = R*trans(Q);
    fitted = T*trans(Q);
    fitted.each_row() += Ymeans;

    //Octave creates copies from inputs before sending to output. Doing same
    //here just to be safe.
    coefficients = B;
    X_scores = T;
    X_loadings = P;
    Y_scores = U;
    Y_loadings = Q;
    //projection = R;
    percent_variance.set_size(2, coefficients.n_cols);
    percent_variance.row(0) = sum(arma::abs(P)%arma::abs(P)) / sum(sum(arma::abs(X)%arma::abs(X)));
    percent_variance.row(1) = sum(arma::abs(Q)%arma::abs(Q)) / sum(sum(arma::abs(Y)%arma::abs(Y)));
    return true;

}
Esempio n. 5
0
//[[Rcpp::export(.emplik_intern)]]
List emplik_intern(arma::mat z, arma::colvec mu, arma::vec lam, double eps,
	double M = 1e30, double thresh = 1e-12, int itermax = 1000){
//(arma::mat z, arma::vec mu  = vec(z.n_cols,fill::zeros), double eps = 1/z.nrows, double M = datum::inf);
// # Backtracking line search parameters [Tweak only with extreme caution.]
// # See Boyd and Vandenberghe, pp 464-466.
double ALPHA = 0.3; // seems better than 0.01 on some 2d test data (sometimes fewer iters)
double BETA  = 0.8;
// # We need  0 < ALPHA < 1/2   and 0 < BETA < 1
// # Backtrack threshold: you can miss by this much.
double BACKEPS = 0;
// # Consider replacing 0 by 1e-10 if backtracking seems to be
// # failing due to round off.
int n = z.n_rows;
int d = z.n_cols;
 z.each_row() -= trans(mu);
//  Use lam = 0 or initial lam, whichever is best
arma::vec onen = arma::vec(n,arma::fill::ones);
arma::mat init0 = mllog(onen, eps, M, 2);
arma::mat init(init0.n_rows, init0.n_cols);
if(!any(lam)){
  init = init0;
} else {
  init = mllog(onen+z*lam, eps, M, 2);
	if(sum(init0.col(0) < sum(init.col(0)))){
    lam = arma::rowvec(z.n_cols,arma::fill::zeros);
    init = init0;
  }
}
// # Initial f, g
double fold = sum(init.col(0));
arma::rowvec gold = sum(z.each_col() % init.col(1),0);
bool converged = false;
int iter = 0;
arma::mat oldvals = init;
arma::mat newvals(oldvals.n_rows, oldvals.n_cols);
arma::vec rootllpp;
arma::mat zt(z.n_rows, z.n_cols);
arma::vec yt(z.n_rows);
arma::vec wts;
double fnew; double targ;
double logelr;
arma::vec step(z.n_cols);
int s; double ndec; double gradnorm;
bool backtrack = false;
while(!converged){
  iter += 1;
  //   # Get Newton Step
  rootllpp = sqrt(oldvals.col(2));  //# sqrt 2nd deriv of -llog lik
  zt = z;
     for(int j=0; j<d; j++){
      zt.col(j) %= rootllpp;
    }
    yt   = oldvals.col(1) / rootllpp;
    step = -svdlm(zt,yt);
    backtrack = false;
    s = 1;
    while(!backtrack){
         newvals = mllog(onen + z * (lam+s*step), eps, M, 2);
        fnew = sum(newvals.col(0));
        targ = fold + ALPHA * s * sum(trans(gold) % step) + BACKEPS; // (BACKEPS for roundoff, should not be needed)
         if(fnew <= targ){ // backtracking has converged
          backtrack = true;
          oldvals = newvals;
          fold = fnew;
     			gold = sum(z.each_col() % oldvals.col(1),0);
          lam = lam + s*step;
         } else{
          s = s * BETA;
         }
       }
    //   # Newton decrement and gradient norm
      ndec     = sqrt(sum(square(step % trans(gold))));
      gradnorm = sqrt(sum(square(gold)));
      converged = (ndec * ndec <= thresh);
       if( iter > itermax )
       	break;
     }
     wts = pow(1 + z * lam, -1)/n;
		logelr = sum(mllog(onen + z * lam, eps, M, 0).col(0));
    return Rcpp::List::create(Named("logelr")=logelr, Named("lam") = lam, Named("wts") = wts,
        Named("conv") = converged, Named("niter") = iter,Named("ndec") = ndec, Named("gradnorm") = gradnorm);
     }
Esempio n. 6
0
//' Map N(0,1) stochastic perturbations to an LNA path.
//'
//' @param pathmat matrix where the LNA path should be stored
//' @param draws matrix of N(0,1) draws to be mapped to an LNA path
//' @param lna_times vector of interval endpoint times
//' @param lna_pars numeric matrix of parameters, constants, and time-varying
//'   covariates at each of the lna_times
//' @param init_start index in the parameter vector where the initial compartment
//'   volumes start
//' @param param_update_inds logical vector indicating at which of the times the
//'   LNA parameters need to be updated.
//' @param stoich_matrix stoichiometry matrix giving the changes to compartments
//'   from each reaction
//' @param forcing_inds logical vector of indicating at which times in the
//'   time-varying covariance matrix a forcing is applied.
//' @param forcing_matrix matrix containing the forcings.
//' @param svd_d vector in which to store SVD singular values
//' @param svd_U matrix in which to store the U matrix of the SVD
//' @param svd_V matrix in which to store the V matrix of the SVD
//' @param step_size initial step size for the ODE solver (adapted internally,
//' but too large of an initial step can lead to failure in stiff systems).
//' @param lna_pointer external pointer to LNA integration function.
//' @param set_pars_pointer external pointer to the function for setting the LNA
//'   parameters.
//'
//' @return fill out pathmat with the LNA path corresponding to the stochastic
//'   perturbations.
//'
//' @export
// [[Rcpp::export]]
void map_draws_2_lna(arma::mat& pathmat,
                     const arma::mat& draws,
                     const arma::rowvec& lna_times,
                     const Rcpp::NumericMatrix& lna_pars,
                     Rcpp::NumericVector& lna_param_vec,
                     const Rcpp::IntegerVector& lna_param_inds,
                     const Rcpp::IntegerVector& lna_tcovar_inds,
                     const int init_start,
                     const Rcpp::LogicalVector& param_update_inds,
                     const arma::mat& stoich_matrix,
                     const Rcpp::LogicalVector& forcing_inds,
                     const arma::uvec& forcing_tcov_inds,
                     const arma::mat& forcings_out,
                     const arma::cube& forcing_transfers,
                     arma::vec& svd_d,
                     arma::mat& svd_U,
                     arma::mat& svd_V,
                     double step_size,
                     SEXP lna_pointer,
                     SEXP set_pars_pointer) {

        // get the dimensions of various objects
        int n_events = stoich_matrix.n_cols;         // number of transition events, e.g., S2I, I2R
        int n_comps  = stoich_matrix.n_rows;         // number of model compartments (all strata)
        int n_odes   = n_events + n_events*n_events; // number of ODEs
        int n_times  = lna_times.n_elem;             // number of times at which the LNA must be evaluated
        int n_tcovar = lna_tcovar_inds.size();       // number of time-varying covariates or parameters
        int n_forcings = forcing_tcov_inds.n_elem;   // number of forcings
        
        // for use with forcings
        double forcing_flow = 0;
        arma::vec forcing_distvec(n_comps, arma::fill::zeros);
        
        // initialize the objects used in each time interval
        double t_L = 0;
        double t_R = 0;

        // vector of parameters, initial compartment columes, constants, and time-varying covariates
        std::copy(lna_pars.row(0).begin(), lna_pars.row(0).end(), lna_param_vec.begin());

        CALL_SET_ODE_PARAMS(lna_param_vec, set_pars_pointer); // set the parameters in the odeintr namespace

        // initial state vector - copy elements from the current parameter vector
        arma::vec init_volumes(lna_param_vec.begin() + init_start, n_comps);

        // initialize the LNA objects
        bool good_svd = true;

        Rcpp::NumericVector lna_state_vec(n_odes); // the vector for storing the current state of the LNA ODEs

        arma::vec lna_drift(n_events, arma::fill::zeros);               // incidence mean vector (log scale)
        arma::mat lna_diffusion(n_events, n_events, arma::fill::zeros); // diffusion matrix

        arma::vec log_lna(n_events, arma::fill::zeros);  // LNA increment, log scale
        arma::vec nat_lna(n_events, arma::fill::zeros);  // LNA increment, natural scale

        // apply forcings if called for - applied after censusing at the first time
        if(forcing_inds[0]) {
              
              // distribute the forcings proportionally to the compartment counts in the applicable states
              for(int j=0; j < n_forcings; ++j) {
                    
                    forcing_flow       = lna_pars(0, forcing_tcov_inds[j]);
                    forcing_distvec    = forcing_flow * normalise(forcings_out.col(j) % init_volumes, 1);
                    init_volumes      += forcing_transfers.slice(j) * forcing_distvec;
              }
        }

        // iterate over the time sequence, solving the LNA over each interval
        for(int j=0; j < (n_times-1); ++j) {

                // set the times of the interval endpoints
                t_L = lna_times[j];
                t_R = lna_times[j+1];

                // Reset the LNA state vector and integrate the LNA ODEs over the next interval to 0
                std::fill(lna_state_vec.begin(), lna_state_vec.end(), 0.0);
                CALL_INTEGRATE_STEM_ODE(lna_state_vec, t_L, t_R, step_size, lna_pointer);

                // transfer the elements of the lna_state_vec to the process objects
                std::copy(lna_state_vec.begin(), lna_state_vec.begin() + n_events, lna_drift.begin());
                std::copy(lna_state_vec.begin() + n_events, lna_state_vec.end(), lna_diffusion.begin());

                // ensure symmetry of the diffusion matrix
                lna_diffusion = arma::symmatu(lna_diffusion);

                // map the stochastic perturbation to the LNA path on its natural scale
                try{
                        if(lna_drift.has_nan() || lna_diffusion.has_nan()) {
                                good_svd = false;
                                throw std::runtime_error("Integration failed.");
                        } else {
                                good_svd = arma::svd(svd_U, svd_d, svd_V, lna_diffusion); // compute the SVD
                        }

                        if(!good_svd) {
                                throw std::runtime_error("SVD failed.");

                        } else {
                                svd_d.elem(arma::find(svd_d < 0)).zeros();          // zero out negative sing. vals
                                svd_V.each_row() %= arma::sqrt(svd_d).t();          // multiply rows of V by sqrt(d)
                                svd_U *= svd_V.t();                                 // complete svd_sqrt
                                svd_U.elem(arma::find(lna_diffusion == 0)).zeros(); // zero out numerical errors

                                log_lna = lna_drift + svd_U * draws.col(j);         // map the LNA draws
                        }

                } catch(std::exception & err) {

                        // reinstatiate the SVD objects
                        arma::vec svd_d(n_events, arma::fill::zeros);
                        arma::mat svd_U(n_events, n_events, arma::fill::zeros);
                        arma::mat svd_V(n_events, n_events, arma::fill::zeros);

                        // forward the exception
                        forward_exception_to_r(err);

                } catch(...) {
                        ::Rf_error("c++ exception (unknown reason)");
                }

                // compute the LNA increment
                nat_lna = arma::vec(expm1(Rcpp::NumericVector(log_lna.begin(), log_lna.end())));

                // save the LNA increment
                pathmat(j+1, arma::span(1, n_events)) = nat_lna.t();

                // update the initial volumes
                init_volumes += stoich_matrix * nat_lna;

                // if any increments or volumes are negative, throw an error
                try{
                        if(any(nat_lna < 0)) {
                                throw std::runtime_error("Negative increment.");
                        }

                        if(any(init_volumes < 0)) {
                                throw std::runtime_error("Negative compartment volumes.");
                        }

                } catch(std::runtime_error &err) {

                        forward_exception_to_r(err);

                } catch(...) {
                        ::Rf_error("c++ exception (unknown reason)");
                }
                
                // apply forcings if called for - applied after censusing the path
                if(forcing_inds[j+1]) {
                      
                      // distribute the forcings proportionally to the compartment counts in the applicable states
                      for(int s=0; s < n_forcings; ++s) {
                            
                            forcing_flow       = lna_pars(j+1, forcing_tcov_inds[s]);
                            forcing_distvec    = forcing_flow * normalise(forcings_out.col(s) % init_volumes, 1);
                            init_volumes      += forcing_transfers.slice(s) * forcing_distvec;
                      }
                      
                      // throw errors for negative negative volumes
                      try{
                            if(any(init_volumes < 0)) {
                                  throw std::runtime_error("Negative compartment volumes.");
                            }
                            
                      } catch(std::exception &err) {
                            
                            forward_exception_to_r(err);
                            
                      } catch(...) {
                            ::Rf_error("c++ exception (unknown reason)");
                      }
                }

                // update the parameters if they need to be updated
                if(param_update_inds[j+1]) {
                      
                      // time-varying covariates and parameters
                      std::copy(lna_pars.row(j+1).end() - n_tcovar,
                                lna_pars.row(j+1).end(),
                                lna_param_vec.end() - n_tcovar);
                }

                // copy the new initial volumes into the vector of parameters
                std::copy(init_volumes.begin(), init_volumes.end(), lna_param_vec.begin() + init_start);

                // set the lna parameters and reset the LNA state vector
                CALL_SET_ODE_PARAMS(lna_param_vec, set_pars_pointer);
        }
}
Esempio n. 7
0
// [[Rcpp::export]]
List solveHierBasis(arma::mat design_mat,
                  arma::vec y,
                  arma::vec ak,arma::mat weights,
                  int n, double lam_min_ratio, int nlam,
                  double max_lambda) {

  // This function returns the argmin of the following function:
  // (0.5) * ||y - X %*% beta||_2^2 + P(beta), where
  // P(\beta) = \sum_{j=1}^{J_n} weights[j, lam_indx] * norm(beta[j:J_n])
  // where j indexes the basis function and lam_indx indexes the different
  // lambda values.
  //
  // Args:
  //    design_mat: A design matrix of size n * J_n, where J_n is number of
  //                basis functions. This matrix should be centered.
  //    y: The centered response vector.
  //    ak: A J_n-vector of weights where ak[j] = j^m - (j-1)^m for a smoothness
  //        level m.
  //    weights: A J_n * nlam matrix which is simply the concatenation [ak,ak,...,ak].
  //    n: The number of observations, equal to length(y).
  //    lam_min_ratio: Ratio of min_lambda to max_lambda.
  //    nlam: Number of lambda values.
  //    max_lambda: A double specifying the maximum lambda, if NA then function
  //                selects a max_lambda.
  // Returns:
  //    beta_hat2: The solution matrix, a J_n * nlam  matrix.
  //    lambdas: Sequence of lambda values used for fitting.

  // Generate the x_mat, this is our orthonormal design matrix.
  arma::mat x_mat, R_mat;
  arma::qr_econ(x_mat, R_mat, design_mat);

  x_mat = x_mat * sqrt(n);
  R_mat  = R_mat / sqrt(n);
  // arma::sp_mat R_mat2 = sp_mat(R_mat / sqrt(n));


  // Note that for a orthogonal design with X^T %*% X = nI the
  // two problems are equivalent:
  // 1. (1/2n)*|Y - X %*% beta|^2 + lambda * Pen(beta),
  // 2. (1/2)*|t(X) %*% Y/n - beta|^2 + lambda * Pen(beta).
  //
  // Thus all we need, is to solve the proximal problem.
  // Define v_temp = t(X) %*% Y/n for the prox problem.

  arma::vec v_temp = x_mat.t() * (y /n);

  // We evaluate a max_lambda value if not specified by user.
  if(R_IsNA(max_lambda)) {
    // Followed by the maximum lambda value.
     max_lambda = max(abs(v_temp) / ak);
    // max_lambda = norm(v_temp, 2);
  }

  // Generate the full lambda sequence.
  arma::vec lambdas = linspace<vec>(log10(max_lambda),
                                    log10(max_lambda * lam_min_ratio),
                                    nlam);
  lambdas = exp10(lambdas);

  // Generate matrix of weights.
  weights.each_row() %= lambdas.t();

  // Obtain beta.hat, solve prox problem.
  arma::sp_mat beta_hat =  GetProx(v_temp, weights);

  // Take the inverse of the R_mat to obtain solution on the original scale
  arma::mat beta_hat2 = solve(trimatu(R_mat), mat(beta_hat));

  ///////////// Removed after version 0.7.1, moved to a different R function.//////////

  // We also obtain the DOF for the different methods.
  //arma::vec dof = getDof(x_mat, weights, beta_hat, nlam, n);

  //////////// Removed after version 0.7.1, moved to a different R function.//////////


  // Return fitted values.
  arma::mat yhat = x_mat * mat(beta_hat);

  return List::create(Named("beta") = beta_hat2,
                      Named("lambdas") = lambdas,
                      //Named("dof") = dof,
                      Named("yhat") = yhat,
                      Named(".beta_ortho") = beta_hat);
}
Esempio n. 8
0
// [[Rcpp::export]]
List solveHierLogistic(arma::mat design_mat,
                       arma::vec y,
                       arma::vec ak,arma::mat weights,
                       int n, int nlam, int J,
                       double max_lambda, double lam_min_ratio,
                       double tol, int max_iter,
                       double tol_inner, int max_iter_inner) {

  // This function returns the argmin of the following function:
  // -L(beta) + P(beta), where
  // P(\beta) = \sum_{j=1}^{J_n} weights[j, lam_indx] * norm(beta[j:J_n])
  // where j indexes the basis function and lam_indx indexes the different
  // lambda values. 'L' in this case is the log-likelihood for a binomial model.
  //
  // Args:
  //    design_mat: A design matrix of size n * J_n, where J_n is number of
  //                basis functions.
  //    y: The response vector.
  //    ak: A J_n-vector of weights where ak[j] = j^m - (j-1)^m for a smoothness
  //        level m.
  //    weights: A J_n * nlam matrix which is simply the concatenation [ak,ak,...,ak].
  //    n: The number of observations, equal to length(y).
  //    lam_min_ratio: Ratio of min_lambda to max_lambda.
  //    nlam: Number of lambda values.
  //    max_lambda: A double specifying the maximum lambda. A max lambda needs to
  //                be specified for logistic regression.
  //    tol, tol_inner: The tolerance for the outer and inner loop respectively.
  //    max_iter, max_iter_inner: The maximum number of iterations for outer and
  //                              inner loops respectively.
  // Returns:
  //    beta_final: The sparse solution matrix, a J_n * nlam  matrix.
  //    intercept: The vector of fitted intercepts of size nlam.
  //    lambdas: Sequence of lambda values used for fitting.
  //    fitted: The fitted probabilities.
  //

  // Generate the x_mat, this is our orthonormal design matrix.
  arma::mat x_mat, R_mat;
  arma::qr_econ(x_mat, R_mat, design_mat);

  x_mat = x_mat * sqrt(n);
  R_mat  = R_mat / sqrt(n);

  // We evaluate a max_lambda value if not specified by user.
  if(R_IsNA(max_lambda)) {

    // A simple calculation to evelaute the max lambda,
    // If we wish to find a max lambda, then beta = 0 and hence the
    // temp fitted probabilities are 0.5. The current quadratic approximation
    // is given by
    // y_tilde =  intercept + X * beta + (y - p_hat)/(p_jhat * (1 - p_hat)).
    // In this case this is simply 4 * (y - 0.5).
    // Finally max_lambda is give  first finding
    // v_temp = t(x_mat) * (4 * (y - 0.5))/n followed by
    // max(abs(v_temp)) / (4*ak).
    arma::vec v_temp = x_mat.t() * ((y - 0.5) / n);

    // Followed by the maximum lambda value.
    max_lambda = max(abs(v_temp) / ak);
  }


  // Generate the full lambda sequence.
  arma::vec lambdas = linspace<vec>(log10(max_lambda),
                                    log10(max_lambda * lam_min_ratio),
                                    nlam);
  lambdas = exp10(lambdas);

  // Generate matrix of weights.
  weights.each_row() %= lambdas.t();

  // The final matrix we will use to store beta values.
  arma::mat beta_ans(J, nlam);
  // The final vector to store values for the intercept.
  arma::vec intercept_ans(nlam);

  // The vectors we will use to check convergence.
  // We also use this for the sake of warm starts.
  arma::vec beta(J, fill::zeros);
  //  arma::vec beta_new(J, fill::zeros);


  double intercept = 0;
  //  double intercept_new = 0;

  // The full parameter vector which containts the intercept + covariates.
  arma::vec pars(J + 1, fill::zeros);
  arma::vec pars_new(J + 1, fill::zeros);

  // For each lambda and each middle iteration number,
  // We design a new vector of probabilities and consequently a new
  // response vector.
  arma::vec temp_prob;
  arma::vec temp_resp;

  // We also store a temporary linear part, given by X * beta.
  arma::vec temp_xbeta;

  // Begin outer loop to decrement lambdas.
  for(int i = 0; i < nlam; ++i) {
    //Rcout << "Solving for Lambda num: " << i <<"\n";

    // Begin middle loop to update quadratic approximation of
    // log-likelihood.
    bool converge = false;
    int counter = 0;
    while(!converge && counter < max_iter) {

      temp_xbeta = x_mat * beta;
      temp_prob = 1 / (1 + exp(-1 * (intercept + temp_xbeta)));
      // Note that the optimization problem is actually given by
      // (1/4) * (1/2) * ||y - beta_inter - X %*% beta||_2^2 + lam * Pen(beta),
      // where the 1/4 comes from the weighted least squares part and beta_inter
      // is the intercept term. Unlike linear models, we cannot ignore the intercept
      // term now.
      // Hence we use a simple coordinate descent algorithm.



      temp_resp = intercept + temp_xbeta +
        (y - temp_prob) / (temp_prob % (1 - temp_prob));


      pars(0) = intercept;
      pars.subvec(1, J) = beta;
      // Obtain updated parameter.
      pars_new = innerLoop(temp_resp, beta, intercept,
                           tol_inner, max_iter_inner,
                           x_mat, n, weights.col(i));



      // Rcout << "Lambda"<< i<< ": "<< norm(pars_new - pars)/norm(pars_new)  << "\n";
      if(norm(pars_new - pars) / norm(pars_new)  < tol) {

        beta_ans.col(i) = pars_new.subvec(1, J);
        intercept_ans(i) = pars_new(0);
        beta = beta_ans.col(i);
        intercept = pars_new(0);
        converge = true;
      } else {
        beta = pars_new.subvec(1, J);
        intercept = pars_new(0);
        counter = counter + 1;
        if(counter == max_iter) {
          beta_ans.col(i) = beta;
          intercept_ans(i) = intercept;

          Function warning("warning");
          warning("Function did not converge for some lambda.");
        }
      }
    }
  }

  // Generate matrix of intercepts, this will be a n*nlam martrix for the
  // nlam different fitted models.
  arma::mat inters_mat(n, nlam, fill::eye);
  inters_mat.each_row() %= trans(intercept_ans);

  arma::mat fit_xbeta = inters_mat + x_mat * beta_ans;
  arma::mat fit_prob = 1 / (1 + exp(-1 * fit_xbeta));


  // Now return beta to the original scale.
  arma::mat beta_hat2 = solve(trimatu(R_mat), beta_ans);

  arma::sp_mat beta_final = sp_mat(beta_hat2);


  return List::create(Named("beta") = beta_final,
                      Named("intercept") = intercept_ans,
                      Named("lambdas") = lambdas,
                      Named("fitted") = fit_prob);

}