#include #include #include #include "c_optim.h" namespace rstpm2 { using namespace Rcpp; using namespace arma; // typedefs typedef bool constraintfn(int, double *, void *); // Hadamard element-wise multiplication for the _columns_ of a matrix with a vector mat rmult(mat m, vec v) { mat out(m); out.each_col() %= v; return out; } mat lmult(vec v, mat m) { return rmult(m,v); } // element-wise multiplication and division for NumericVector and arma::vec NumericVector ew_mult(NumericVector nv, vec v) { return as(wrap(as(wrap(nv)) % v)); } NumericVector ew_div(NumericVector nv, vec v) { return as(wrap(as(wrap(nv)) / v)); } void Rprint(NumericMatrix m) { for (int i=0; i(wrap(pnorm(as(wrap(x)),0.0,1.0))); } vec qnorm01(vec x) { vec out(x.size()); for (size_t i=0; i out; for (iy = y.begin(), igroup = group.begin(); iy != y.end(); ++iy, ++igroup) { out[*igroup] += *iy; } return wrap(out); } // Q: do we need parscale, trace, reltol and criterion in these structs? class stpm2 { public: stpm2(SEXP sexp) { List list = as(sexp); init = as(list["init"]); X = as(list["X"]); XD = as(list["XD"]); bhazard = as(list["bhazard"]); wt = as(list["wt"]); event = as(list["event"]); time = as(list["time"]); delayed = as(list["delayed"]); X0.set_size(1,1); X0.fill(0.0); wt0.set_size(1); wt0.fill(0.0); if (delayed == 1) { X0 = as(list["X0"]); // optional XD0 = as(list["XD0"]); // optional wt0 = as(list["wt0"]); // optional } parscale = as(list["parscale"]); reltol = as(list["reltol"]); kappa = as(list["kappa"]); trace = as(list["trace"]); } // defaults are for the PH model virtual vec link(vec S) { return log(-log(S)); } virtual vec ilink(vec x) { return exp(-exp(x)); } virtual vec h(vec eta, vec etaD) { return etaD % exp(eta); } virtual vec H(vec eta, vec etaD) { return exp(eta); } virtual mat gradH(vec eta, vec etaD, mat X, mat XD) { return rmult(X,exp(eta)); } virtual mat gradh(vec eta, vec etaD, mat X, mat XD) { return rmult(XD, exp(eta)) + rmult(X, etaD % exp(eta)); } virtual double negll(NumericVector beta); virtual void grad_negll(NumericVector beta); NumericVector init; mat X, XD, X0, XD0; vec bhazard,wt,wt0,event,time,parscale; double reltol, kappa; int delayed, trace; }; double stpm2::negll(NumericVector beta) { int n = init.size(); vec vbeta(&beta[0],n); vbeta = vbeta % parscale; vec eta = X * vbeta; vec etaD = XD * vbeta; vec h = this->h(eta,etaD) + bhazard; vec H = this->H(eta,etaD) + bhazard; double constraint = kappa/2.0 * sum(h % h % (h<0)); // sum(h^2 | h<0) vec eps = h*0.0 + 1.0e-16; h = max(h,eps); double ll = sum(wt % event % log(h)) - sum(wt % H) - constraint; if (delayed == 1) { vec eta0 = X0 * vbeta; vec etaD0 = XD0 * vbeta; mat H0 = this->H(eta0,etaD0); ll += sum(wt0 % H0); } return -ll; } void stpm2::grad_negll(NumericVector beta) { int n = beta.size(); vec vbeta = as(wrap(beta)); vbeta = vbeta % parscale; vec eta = X * vbeta; vec etaD = XD * vbeta; vec h = this->h(eta,etaD) + bhazard; // vec H = exp(eta); mat gradH = this->gradH(eta,etaD,X,XD); mat gradh = this->gradh(eta,etaD,X,XD); mat Xgrad = -gradH + rmult(gradh, event / h); mat Xconstraint = - kappa*rmult(gradh,h); vec eps = h*0.0 + 1.0e-16; // hack //Xgrad.rows(h<=eps) = Xconstraint.rows(h<=eps); Xgrad = rmult(Xgrad,wt); rowvec vgr = sum(Xgrad,0); if (delayed == 1) { vec eta0 = X0 * vbeta; vec etaD0 = XD0 * vbeta; mat gradH0 = this->gradH(eta0, etaD0, X0, XD0); vgr += sum(rmult(gradH0, wt0),0); } for (int i = 0; i std::vector read_smoothers(List lsmooth) {} template<> std::vector read_smoothers(List lsmooth) { std::vector smooth; for(int i=0; i(lsmooth[i]); List lsmoothiS = as(lsmoothi["S"]); SmoothLogH smoothi = { as(lsmoothi["first.para"]) - 1, as(lsmoothi["last.para"]) - 1, as(lsmoothiS[0]) }; smooth.push_back(smoothi); } return smooth; } template<> std::vector read_smoothers(List lsmooth) { std::vector smooth; for(int i=0; i(lsmooth[i]); SmoothHaz smoothi = { as(lsmoothi["X0"]), as(lsmoothi["X1"]), as(lsmoothi["X2"]), as(lsmoothi["X3"]), as(lsmoothi["w"]), as(lsmoothi["lambda"]) }; smooth.push_back(smoothi); } return smooth; } template class pstpm2 : public Stpm2 { public: pstpm2(SEXP sexp) : Stpm2(sexp) { List list = as(sexp); List lsmooth = as(list["smooth"]); sp = as(list["sp"]); reltol_search = as(list["reltol_search"]); // reltol = as(list["reltol"]); alpha = as(list["alpha"]); criterion = as(list["criterion"]); smooth = read_smoothers(lsmooth); } NumericVector sp; double alpha, reltol_search; int criterion; std::vector smooth; }; /** Extension of stpm2 and pstpm2 to include shared frailties with a cluster variable **/ template class stpm2Shared : public Stpm2 { public: stpm2Shared(SEXP sexp) : Stpm2(sexp) { List list = as(sexp); IntegerVector cluster = as(list["cluster"]); // wragged array indexed by a map of vectors for (int i=0; i > clusters; }; /** Extension to the BFGS class optim() and calc_hessian() assume that data->parscale is an array/vector/NumericVector optimWithConstraint() further assumes that data->kappa is a double with an initial value */ template class BFGS2 : public BFGS { public: void optim(optimfn fn, optimgr gr, NumericVector init, void * ex, bool apply_parscale = true) { Data * data = (Data *) ex; n = init.size(); if (apply_parscale) for (int i = 0; iparscale[i]; BFGS::optim(fn,gr,init,ex); if (apply_parscale) for (int i = 0; iparscale[i]; hessian = calc_hessian(gr, ex); } void optimWithConstraint(optimfn fn, optimgr gr, NumericVector init, void * ex, constraintfn constraint, bool apply_parscale = true) { Data * data = (Data *) ex; n = init.size(); if (apply_parscale) for (int i = 0; iparscale[i]; bool satisfied; do { BFGS::optim(fn,gr,init,ex); satisfied = constraint(n,&coef[0],ex); if (!satisfied) data->kappa *= 2.0; } while ((!satisfied)&& data->kappa < 1.0e3); if (apply_parscale) for (int i = 0; iparscale[i]; hessian = calc_hessian(gr, ex); // Rprintf("kappa=%f\n",data->kappa); } NumericMatrix calc_hessian(optimgr gr, void * ex) { Data * data = (Data *) ex; vec parscale(n); for (int i=0; iparscale[i]; data->parscale[i] = 1.0; } NumericMatrix hessian = BFGS::calc_hessian(gr,ex); for (int i=0; iparscale[i] = parscale[i]; return hessian; } }; template double fminfn(int n, double * beta, void *ex) { Data * data = (Data *) ex; vec vbeta(beta,n); vbeta = vbeta % data->parscale; vec eta = data->X * vbeta; vec etaD = data->XD * vbeta; vec h = data->h(eta,etaD) + data->bhazard; vec H = data->H(eta,etaD); double constraint = data->kappa/2.0 * sum(h % h % (h<0)) + data->kappa/2.0 * sum((H/data->time) % (H/data->time) % (H<0)); vec eps = h*0.0 + 1.0e-16; h = max(h,eps); H = max(H,eps); double ll = sum(data->wt % data->event % log(h)) - sum(data->wt % H) - constraint; if (data->delayed == 1) { vec eta0 = data->X0 * vbeta; vec etaD0 = data->XD0 * vbeta; mat H0 = data->H(eta0,etaD0); ll += sum(data->wt0 % H0); } return -ll; } /** Objective function for a Gamma shared frailty Assumes that weights == 1. The implementation is incomplete, requiring either the use of optimisation without gradients or the calculation of the gradients. **/ template double fminfnShared(int n, double * beta, void *ex) { typedef std::vector Index; typedef std::map IndexMap; Data * data = (Data *) ex; vec vbeta(beta,n-1); // theta is the last parameter in beta double theta = beta[n-1]; vbeta = vbeta % data->parscale; vec eta = data->X * vbeta; vec etaD = data->XD * vbeta; vec h = data->h(eta,etaD) + data->bhazard; vec H = data->H(eta,etaD) + data->bhazard; double constraint = data->kappa/2.0 * sum(h % h % (h<0)); // sum(h^2 | h<0) vec eps = h*0.0 + 1.0e-16; h = max(h,eps); mat H0; //double ll = sum(data->wt % data->event % log(h)) - sum(data->wt % H) - constraint; if (data->delayed == 1) { vec eta0 = data->X0 * vbeta; vec etaD0 = data->XD0 * vbeta; H0 = data->H(eta0,etaD0); //ll += sum(data->wt0 % H0); } double ll; for (IndexMap::iterator it=data->clusters.begin(); it!=data->clusters.end(); ++it) { int mi=0; double sumH = 0.0, sumHenter = 0.0; for (Index::iterator j=it->second.begin(); j!=it->second.end(); ++j) { if (data->event(*j)==1) { mi++; ll += log(h(*j)); } sumH += H(*j); if (data->delayed == 1) sumHenter += H0(*j); } ll -= (1.0/theta+mi)*log(1.0+theta*sumH); if (data->delayed == 1) ll += 1.0/theta*log(1.0+theta*sumHenter); if (mi>0) { int k=1; for (Index::iterator j=it->second.begin(); j!=it->second.end(); ++j) { if (data->event(*j)==1) { ll += log(1.0+theta*(mi-k)); k++; } } } } ll -= constraint; return -ll; } /** Utility function for calculating a gamma frailty log-likelihood within R code **/ RcppExport SEXP llgammafrailty(SEXP _theta, SEXP _h, SEXP _H, SEXP _d, SEXP _cluster) { double theta = as(_theta); NumericVector h = as(_h); NumericVector H = as(_H); IntegerVector d = as(_d); IntegerVector cluster = as(_cluster); double ll = 0.0; // wragged array indexed by a map of vectors typedef std::vector Index; typedef std::map IndexMap; IndexMap clusters; for (int i=0; isecond.begin(); j!=it->second.end(); ++j) { if (d[*j]==1) { mi++; ll += log(h[*j]); } sumH += H[*j]; // sumHenter += Henter[*j]; } ll -= (1.0/theta+mi)*log(1.0+theta*sumH); // ll += 1.0/theta*log(1.0+theta*sumHenter); if (mi>0) { int k=1; for (Index::iterator j=it->second.begin(); j!=it->second.end(); ++j) { if (d[*j]==1) { ll += log(1.0+theta*(mi-k)); k++; } } } } return wrap(ll); } /** Utility function for calculating a gamma frailty log-likelihood within R code **/ RcppExport SEXP llgammafrailtydelayed(SEXP _theta, SEXP _h, SEXP _H, SEXP _H0, SEXP _d, SEXP _cluster) { double theta = as(_theta); NumericVector h = as(_h); NumericVector H = as(_H); NumericVector H0 = as(_H0); // assumes that _H0 is zero for data not left truncated IntegerVector d = as(_d); IntegerVector cluster = as(_cluster); double ll = 0.0; // wragged array indexed by a map of vectors typedef std::vector Index; typedef std::map IndexMap; IndexMap clusters; for (int i=0; isecond.begin(); j!=it->second.end(); ++j) { if (d[*j]==1) { mi++; ll += log(h[*j]); } sumH += H[*j]; sumHenter += H0[*j]; } ll -= (1.0/theta+mi)*log(1.0+theta*sumH); ll += 1.0/theta*log(1.0+theta*sumHenter); if (mi>0) { int k=1; for (Index::iterator j=it->second.begin(); j!=it->second.end(); ++j) { if (d[*j]==1) { ll += log(1.0+theta*(mi-k)); k++; } } } } return wrap(ll); } struct CureModel { int n0, n1, n2; mat Xshape, Xscale, Xcure; vec time, status; }; double fminfn_cureModel(int n, double * beta, void *ex) { double ll = 0.0; CureModel * data = (CureModel *) ex; vec vbeta(beta,n); vec shape = exp(data->Xshape * vbeta(span(0,data->n0-1))); vec scale = exp(data->Xscale * vbeta(span(data->n0,data->n1-1))); vec cure = 1.0/(1.0+exp(-data->Xcure * vbeta(span(data->n1,data->n2-1)))); for (size_t i=0; i < data->time.size(); ++i) { ll += data->status(i)==1.0 ? log(1.0-cure(i)) + R::dweibull(data->time(i),shape(i),scale(i),1) : log(cure(i)+(1.0-cure(i)) * R::pweibull(data->time(i),shape(i),scale(i),0,0)); } R_CheckUserInterrupt(); /* be polite -- did the user hit ctrl-C? */ return -ll; } RcppExport SEXP fitCureModel(SEXP stime, SEXP sstatus, SEXP sXshape, SEXP sXscale, SEXP sXcure, SEXP sbeta) { mat Xshape = as(sXshape); mat Xscale = as(sXscale); mat Xcure = as(sXcure); vec time = as(stime); vec status = as(sstatus); NumericVector init = as(sbeta); int n0=Xshape.n_cols; int n1=n0+Xscale.n_cols; int n2=n1+Xcure.n_cols; CureModel data = {n0,n1,n2,Xshape,Xscale,Xcure,time,status}; NelderMead nm; nm.reltol = 1.0e-8; nm.maxit = 1000; nm.optim(& fminfn_cureModel, init, (void *) &data); for (int i = 0; i bool fminfn_constraint(int n, double * beta, void *ex) { Data * data = (Data *) ex; vec vbeta(beta,n); vbeta = vbeta % data->parscale; vec eta = data->X * vbeta; vec etaD = data->XD * vbeta; vec h = data->h(eta, etaD) + data->bhazard; vec H = data->H(eta, etaD); return all((h>0) % (H>0)); } template void fminfn_nlm(int n, double * beta, double * f, void *ex) { *f = fminfn(n, beta, ex); }; // log H penalty - using penalty matrices from mgcv template double pfminfn_SmoothLogH(int n, double * beta, void *ex) { typedef SmoothLogH Smooth; typedef pstpm2 Data; double ll = -fminfn(n,beta,ex); Data * data = (Data *) ex; vec vbeta(beta,n); vbeta = vbeta % data->parscale; for (size_t i=0; i < data->smooth.size(); ++i) { Smooth smoothi = data->smooth[i]; ll -= (data->sp)[i]/2 * dot(vbeta.subvec(smoothi.first_para,smoothi.last_para), smoothi.S * vbeta.subvec(smoothi.first_para,smoothi.last_para)); } return -ll; } // hazard penalty template double pfminfn_SmoothHaz(int n, double * beta, void *ex) { typedef SmoothHaz Smooth; typedef pstpm2 Data; double ll = -fminfn(n,beta,ex); Data * data = (Data *) ex; vec vbeta(beta,n); vbeta = vbeta % data->parscale; for (size_t i=0; i < data->smooth.size(); ++i) { Smooth obj = data->smooth[i]; vec s0 = obj.X0 * vbeta; vec s1 = obj.X1 * vbeta; vec s2 = obj.X2 * vbeta; vec s3 = obj.X3 * vbeta; vec h2 = exp(s0) % (s3 + 3*s1%s2 + s1%s1%s1); ll -= (data->sp)[i]/2 * obj.lambda * sum(obj.w % h2 % h2); } return -ll; }; template void grfn(int n, double * beta, double * gr, void *ex) { Data * data = (Data *) ex; vec vbeta(beta,n); // if (data->trace) Rprint(vbeta); vbeta = vbeta % data->parscale; vec eta = data->X * vbeta; vec etaD = data->XD * vbeta; vec h = data->h(eta,etaD) + data->bhazard; vec H = data->H(eta,etaD); vec one = ones(h.size()); vec eps = h*0.0 + 1.0e-16; mat gradH = data->gradH(eta,etaD,data->X,data->XD); mat gradh = data->gradh(eta,etaD,data->X,data->XD); mat Xgrad = -rmult(gradH, one % (H>eps)) + rmult(gradh, data->event / h % (h>eps)); mat Xconstraint = data->kappa * rmult(gradh,h%(hkappa * rmult(gradH,H / data->time / data->time % (Htrace) Rprint(dconstraint); Xgrad = rmult(Xgrad,data->wt); rowvec vgr = sum(Xgrad,0); if (data->delayed == 1) { vec eta0 = data->X0 * vbeta; vec etaD0 = data->XD0 * vbeta; mat gradH0 = data->gradH(eta0, etaD0, data->X0, data->XD0); vgr += sum(rmult(gradH0, data->wt0),0); } for (int i = 0; iparscale[i] + dconstraint[i]; } } template void pgrfn_SmoothLogH(int n, double * beta, double * gr, void *ex) { typedef SmoothLogH Smooth; typedef pstpm2 Data; grfn(n, beta, gr, ex); Data * data = (Data *) ex; vec vbeta(beta,n); vbeta = vbeta % data->parscale; vec eta = data->X * vbeta; vec etaD = data->XD * vbeta; vec h = data->h(eta,etaD) + data->bhazard; vec H = data->H(eta,etaD); mat gradh = data->gradh(eta,etaD,data->X,data->XD); mat gradH = data->gradH(eta,etaD,data->X,data->XD); rowvec vgr(n, fill::zeros); for (size_t i=0; i < data->smooth.size(); ++i) { SmoothLogH smoothi = data->smooth[i]; vgr.subvec(smoothi.first_para,smoothi.last_para) += (data->sp)[i] * (smoothi.S * vbeta.subvec(smoothi.first_para,smoothi.last_para)).t(); } for (int i = 0; iparscale[i]; } template void pgrfn_SmoothHaz(int n, double * beta, double * gr, void *ex) { typedef SmoothHaz Smooth; typedef pstpm2 Data; grfn(n, beta, gr, ex); Data * data = (Data *) ex; vec vbeta(beta,n); vbeta = vbeta % data->parscale; rowvec vgr(n, fill::zeros); for (size_t i=0; i < data->smooth.size(); ++i) { Smooth obj = data->smooth[i]; vec s0 = obj.X0 * vbeta; vec s1 = obj.X1 * vbeta; vec s2 = obj.X2 * vbeta; vec s3 = obj.X3 * vbeta; vec h2 = exp(s0) % (s3 + 3*s1%s2 + s1%s1%s1); mat dh2sq_dbeta = 2*lmult(h2 % exp(s0), obj.X3+3*(rmult(obj.X1,s2)+rmult(obj.X2,s1))+3*lmult(s1%s1,obj.X1))+ 2*lmult(h2 % h2,obj.X0); vgr += (data->sp)[i]*obj.lambda*sum(lmult(obj.w, dh2sq_dbeta),0); } for (int i = 0; iparscale[i]; } // oh, for partial template specialisation for functions... template double pfminfn(int n, double * beta, void *ex) { return 0.0; } template<> double pfminfn(int n, double * beta, void *ex) { return pfminfn_SmoothLogH(n, beta, ex); } template<> double pfminfn(int n, double * beta, void *ex) { return pfminfn_SmoothLogH(n, beta, ex); } template<> double pfminfn(int n, double * beta, void *ex) { return pfminfn_SmoothLogH(n, beta, ex); } template<> double pfminfn(int n, double * beta, void *ex) { return pfminfn_SmoothLogH(n, beta, ex); } template<> double pfminfn(int n, double * beta, void *ex) { return pfminfn_SmoothHaz(n, beta, ex); } template<> double pfminfn(int n, double * beta, void *ex) { return pfminfn_SmoothHaz(n, beta, ex); } template<> double pfminfn(int n, double * beta, void *ex) { return pfminfn_SmoothHaz(n, beta, ex); } template void pgrfn(int n, double * beta, double * gr, void *ex) { } template<> void pgrfn(int n, double * beta, double * gr, void *ex) { pgrfn_SmoothLogH(n, beta, gr, ex); } template<> void pgrfn(int n, double * beta, double * gr, void *ex) { pgrfn_SmoothLogH(n, beta, gr, ex); } template<> void pgrfn(int n, double * beta, double * gr, void *ex) { pgrfn_SmoothLogH(n, beta, gr, ex);} template<> void pgrfn(int n, double * beta, double * gr, void *ex) { pgrfn_SmoothLogH(n, beta, gr, ex); } template<> void pgrfn(int n, double * beta, double * gr, void *ex) { pgrfn_SmoothHaz(n, beta, gr, ex); } template<> void pgrfn(int n, double * beta, double * gr, void *ex) { pgrfn_SmoothHaz(n, beta, gr, ex); } template<> void pgrfn(int n, double * beta, double * gr, void *ex) { pgrfn_SmoothHaz(n, beta, gr, ex); } template SEXP optim_stpm2(SEXP args) { Stpm2 data(args); BFGS2 bfgs; bfgs.reltol = data.reltol; bfgs.optimWithConstraint(fminfn, grfn, data.init, (void *) &data, fminfn_constraint); return List::create(_("fail")=bfgs.fail, _("coef")=wrap(bfgs.coef), _("hessian")=wrap(bfgs.hessian)); } RcppExport SEXP optim_stpm2_ph(SEXP args) { return optim_stpm2(args); } RcppExport SEXP optim_stpm2_po(SEXP args) { return optim_stpm2(args); } RcppExport SEXP optim_stpm2_probit(SEXP args) { return optim_stpm2(args); } RcppExport SEXP optim_stpm2_ah(SEXP args) { return optim_stpm2(args); } RcppExport SEXP optim_stpm2_nlm(SEXP args) { stpm2 data(args); data.init = ew_div(data.init,data.parscale); int n = data.init.size(); Nlm nlm; nlm.gradtl = nlm.steptl = data.reltol; //nlm.method=2; nlm.stepmx=0.0; bool satisfied; do { nlm.optim(& fminfn_nlm, & grfn, data.init, (void *) &data); satisfied = fminfn_constraint(n,&nlm.coef[0],(void *) &data); if (!satisfied) data.kappa *= 2.0; } while (!satisfied && data.kappa<1.0e5); nlm.coef = ew_mult(nlm.coef, data.parscale); return List::create(_("itrmcd")=wrap(nlm.itrmcd), _("niter")=wrap(nlm.itncnt), _("coef")=wrap(nlm.coef), _("hessian")=wrap(nlm.hessian)); } template double pstpm2_step_first(double logsp, void * ex) { typedef pstpm2 Data; Data * data = (Data *) ex; data->sp[0] = exp(logsp); BFGS2 bfgs; bfgs.reltol = data->reltol; bfgs.optimWithConstraint(pfminfn, pgrfn, data->init, ex, fminfn_constraint, false); // do not apply parscale b4/after NumericMatrix hessian0 = bfgs.calc_hessian(grfn, ex); if (data->trace > 0) { Rprintf("Debug on trace calculation. Coef:\n"); Rprint(bfgs.coef); Rprintf("Hessian0:\n"); Rprint(hessian0); Rprintf("Hessian:\n"); Rprint(bfgs.hessian); } double edf = trace(solve(as(bfgs.hessian),as(hessian0))); double negll = bfgs.calc_objective(fminfn,ex); double gcv = negll + data->alpha*edf; double bic = negll + data->alpha*edf*log(sum(data->event)); data->init = bfgs.coef; if (data->trace > 0) Rprintf("sp=%f\tedf=%f\tnegll=%f\tgcv=%f\tbic=%f\talpha=%f\n",data->sp[0],edf,negll,gcv,bic,data->alpha); return data->criterion==1 ? gcv : bic; } template double pstpm2_step_multivariate(int n, double * logsp, void * ex) { typedef pstpm2 Data; Data * data = (Data *) ex; double lsp = -9.0, usp = 9.0; for (int i=0; i < data->sp.size(); ++i) //data->sp[i] = exp(logsp[i]); data->sp[i] = exp(bound(logsp[i],lsp,usp)); if (data->trace > 0) { for (int i = 0; i < data->sp.size(); ++i) Rprintf("sp[%i]=%f\t",i,data->sp[i]); } BFGS2 bfgs; bfgs.reltol = data->reltol_search; bfgs.optimWithConstraint(pfminfn, pgrfn, data->init, ex, fminfn_constraint, false); // do not apply parscale b4/after NumericMatrix hessian0 = bfgs.calc_hessian(grfn, ex); double edf = trace(solve(as(bfgs.hessian),as(hessian0))); double negll = bfgs.calc_objective(fminfn, ex); double gcv = negll + data->alpha*edf; double bic = 2.0*negll + data->alpha*edf*log(sum(data->event)); data->init = bfgs.coef; // simple boundary constraints double constraint = 0.0; // double kappa = 1.0; for (int i=0; i < data->sp.size(); ++i) { if (logsp[i] < lsp) constraint += pow(logsp[i]-lsp,2.0); if (logsp[i] > usp) constraint += pow(logsp[i]-usp,2.0); } double objective = data->criterion==1 ? gcv + data->kappa/2.0*constraint : bic + data->kappa/2.0*constraint; if (data->trace > 0) { Rprintf("edf=%f\tnegll=%f\tgcv=%f\tbic=%f\tobjective=%f\n",edf,negll,gcv,bic,objective); } return objective; } template void pstpm2_step_multivariate_nlm(int n, double * logsp, double * f, void *ex) { *f = pstpm2_step_multivariate(n, logsp, ex); }; template SEXP optim_pstpm2_first(SEXP args) { typedef pstpm2 Data; Data data(args); int n = data.init.size(); for (int i=0; i,&data,1.0e-2)); data.sp[0] = opt_sp; for (int i=0; i bfgs; bfgs.coef = data.init; bfgs.reltol = data.reltol; bfgs.optimWithConstraint(pfminfn, pgrfn, data.init, (void *) &data, fminfn_constraint); NumericMatrix hessian0 = bfgs.calc_hessian(grfn, (void *) &data); double edf = trace(solve(as(bfgs.hessian),as(hessian0))); return List::create(_("sp")=wrap(opt_sp), _("coef")=wrap(bfgs.coef), _("hessian")=wrap(bfgs.hessian), _("edf")=wrap(edf)); } RcppExport SEXP optim_pstpm2LogH_first_ph(SEXP args) { return optim_pstpm2_first(args); } RcppExport SEXP optim_pstpm2Haz_first_ph(SEXP args) { return optim_pstpm2_first(args); } RcppExport SEXP optim_pstpm2LogH_first_po(SEXP args) { return optim_pstpm2_first(args); } RcppExport SEXP optim_pstpm2Haz_first_po(SEXP args) { return optim_pstpm2_first(args); } RcppExport SEXP optim_pstpm2LogH_first_probit(SEXP args) { return optim_pstpm2_first(args); } RcppExport SEXP optim_pstpm2Haz_first_probit(SEXP args) { return optim_pstpm2_first(args); } RcppExport SEXP optim_pstpm2LogH_first_ah(SEXP args) { return optim_pstpm2_first(args); } template SEXP optim_pstpm2_multivariate(SEXP args) { typedef pstpm2 Data; Data data(args); int n = data.init.size(); data.kappa = 10.0; NelderMead nm; nm.reltol = 1.0e-5; nm.maxit = 500; nm.hessianp = false; for (int i=0; i, logsp, (void *) &data); satisfied = true; for (int i=0; i < data.sp.size(); ++i) if (logsp[i]< -7.0 || logsp[i] > 7.0) satisfied = false; if (!satisfied) data.kappa *= 2.0; } while (!satisfied && data.kappa<1.0e5); for (int i=0; i bfgs; bfgs.coef = data.init; bfgs.reltol = data.reltol; data.kappa = 1.0; bfgs.optimWithConstraint(pfminfn, pgrfn, data.init, (void *) &data, fminfn_constraint); NumericMatrix hessian0 = bfgs.calc_hessian(grfn, (void *) &data); double edf = trace(solve(as(bfgs.hessian),as(hessian0))); return List::create(_("sp")=wrap(data.sp), _("coef")=wrap(bfgs.coef), _("hessian")=wrap(bfgs.hessian), _("edf")=wrap(edf)); } RcppExport SEXP optim_pstpm2LogH_multivariate_ph(SEXP args) { return optim_pstpm2_multivariate(args); } RcppExport SEXP optim_pstpm2Haz_multivariate_ph(SEXP args) { return optim_pstpm2_multivariate(args); } RcppExport SEXP optim_pstpm2LogH_multivariate_po(SEXP args) { return optim_pstpm2_multivariate(args); } RcppExport SEXP optim_pstpm2Haz_multivariate_po(SEXP args) { return optim_pstpm2_multivariate(args); } RcppExport SEXP optim_pstpm2LogH_multivariate_probit(SEXP args) { return optim_pstpm2_multivariate(args); } RcppExport SEXP optim_pstpm2Haz_multivariate_probit(SEXP args) { return optim_pstpm2_multivariate(args); } RcppExport SEXP optim_pstpm2LogH_multivariate_ah(SEXP args) { return optim_pstpm2_multivariate(args); } template SEXP optim_pstpm2_multivariate_nlm(SEXP args) { typedef pstpm2 Data; Data data(args); int n = data.init.size(); data.kappa = 10.0; Nlm nlm; nlm.iagflg = 0; nlm.gradtl = 1.0e-4; nlm.steptl = 1.0e-4; nlm.msg = 9 + 4; nlm.hessianp = false; for (int i=0; i, (fcn_p) 0, logsp, (void *) &data); satisfied = true; for (int i=0; i < data.sp.size(); ++i) if (logsp[i]< -7.0 || logsp[i] > 7.0) satisfied = false; if (!satisfied) data.kappa *= 2.0; } while (!satisfied && data.kappa<1.0e5); for (int i=0; i bfgs; bfgs.coef = data.init; bfgs.reltol = data.reltol; data.kappa = 1.0; bfgs.optimWithConstraint(pfminfn, pgrfn, data.init, (void *) &data, fminfn_constraint); NumericMatrix hessian0 = bfgs.calc_hessian(grfn, (void *) &data); double edf = trace(solve(as(bfgs.hessian),as(hessian0))); return List::create(_("sp")=wrap(data.sp), _("coef")=wrap(bfgs.coef), _("hessian")=wrap(bfgs.hessian), _("edf")=wrap(edf)); } RcppExport SEXP optim_pstpm2LogH_multivariate_ph_nlm(SEXP args) { return optim_pstpm2_multivariate_nlm(args); } RcppExport SEXP optim_pstpm2Haz_multivariate_ph_nlm(SEXP args) { return optim_pstpm2_multivariate_nlm(args); } RcppExport SEXP optim_pstpm2LogH_multivariate_po_nlm(SEXP args) { return optim_pstpm2_multivariate_nlm(args); } RcppExport SEXP optim_pstpm2Haz_multivariate_po_nlm(SEXP args) { return optim_pstpm2_multivariate_nlm(args); } RcppExport SEXP optim_pstpm2LogH_multivariate_probit_nlm(SEXP args) { return optim_pstpm2_multivariate_nlm(args); } RcppExport SEXP optim_pstpm2Haz_multivariate_probit_nlm(SEXP args) { return optim_pstpm2_multivariate_nlm(args); } template SEXP optim_pstpm2_fixedsp(SEXP args) { typedef pstpm2 Data; Data data(args); BFGS2 bfgs; bfgs.coef = data.init; bfgs.reltol = data.reltol; bfgs.optimWithConstraint(pfminfn, pgrfn, data.init, (void *) &data, fminfn_constraint); NumericMatrix hessian0 = bfgs.calc_hessian(grfn, (void *) &data); double edf = trace(solve(as(bfgs.hessian),as(hessian0))); return List::create(_("sp")=wrap(data.sp), _("coef")=wrap(bfgs.coef), _("hessian")=wrap(bfgs.hessian), _("edf")=wrap(edf)); } RcppExport SEXP optim_pstpm2LogH_fixedsp_ph(SEXP args) { return optim_pstpm2_fixedsp(args); } RcppExport SEXP optim_pstpm2Haz_fixedsp_ph(SEXP args) { return optim_pstpm2_fixedsp(args); } RcppExport SEXP optim_pstpm2LogH_fixedsp_po(SEXP args) { return optim_pstpm2_fixedsp(args); } RcppExport SEXP optim_pstpm2Haz_fixedsp_po(SEXP args) { return optim_pstpm2_fixedsp(args); } RcppExport SEXP optim_pstpm2LogH_fixedsp_probit(SEXP args) { return optim_pstpm2_fixedsp(args); } RcppExport SEXP optim_pstpm2Haz_fixedsp_probit(SEXP args) { return optim_pstpm2_fixedsp(args); } RcppExport SEXP optim_pstpm2LogH_fixedsp_ah(SEXP args) { return optim_pstpm2_fixedsp(args); } template SEXP test_pstpm2(SEXP args) { pstpm2 data(args); int n = data.init.size(); NumericVector init = ew_div(data.init,data.parscale); double pfmin = pfminfn(n,&init[0],(void *) &data); NumericVector gr(n); pgrfn(n,&init[0], &gr[0], (void *) &data); init = ew_mult(init,data.parscale); return List::create(_("sp")=wrap(data.sp), _("pfmin")=wrap(pfmin), _("gr")=wrap(gr) ); } RcppExport SEXP test_pstpm2LogH(SEXP args) { return test_pstpm2(args); } RcppExport SEXP test_pstpm2Haz(SEXP args) { return test_pstpm2(args); } // R CMD INSTALL ~/src/R/microsimulation // R -q -e "require(microsimulation); .Call('test_nmmin',1:2,PACKAGE='microsimulation')" // .Call("optim_stpm2",init,X,XD,rep(bhazard,nrow(X)),wt,ifelse(event,1,0),package="rstpm2") } // anonymous namespace