00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "model.h"
00023 #include "data.h"
00024
00025
00026 namespace matvec {
00027 static void linmin(double *p,double *xi,int n,double& fret);
00028 static double f1dim(double x);
00029 static double brent(double ax,double bx,double cx,double (*f)(double),
00030 double tol, double& xmin);
00031 static void mnbrak(double& ax,double& bx,double& cx,double& fa,
00032 double& fb,double& fc, double (*func)(double));
00033
00034 static Data *myD;
00035 static Model *myM;
00036 static int nfunk;
00037
00038 static double funk(Vector<double> &x)
00039 {
00040 int i,k;
00041 unsigned nterms = myM->nterm();
00042 myM->vec2var(x);
00043 if (!myM->residual_var.psd()) return 1.0e30;
00044 for (i=0; i<nterms; i++) {
00045 if (myM->term[i].classi() == 'R' || myM->term[i].classi() == 'P') {
00046 k = myM->term[i].prior->var_matrix()->psd();
00047 if (!k) return (1.0e30 + 1.0e10*(i+1));
00048 }
00049 }
00050 nfunk++;
00051 double log_likelihood = myM->restricted_log_likelihood();
00052 if ( (nfunk % 3) == 0) {
00053 std::cout << " powell...# of log_likelihood evaluations = " << nfunk << ", "
00054 << "and its current value = " << log_likelihood << std::endl;
00055 myM->info(std::cout);
00056 }
00057 return log_likelihood*(-1.0);
00058 }
00059
00060 static double sqrarg;
00061 #define SQR(a) (sqrarg=(a),sqrarg*sqrarg)
00062
00063 double nr_powell(Data* D,Model* M,Vector<double> &p,Matrix<double> &xi,int n,int& iter,
00064 double ftol)
00065 {
00066 myD = D;
00067 myM = M;
00068 nfunk = 0;
00069
00070 int i,ibig,j;
00071 double t,fptt,fp,del,fret;
00072 int maxiter = iter;
00073
00074 Vector<double> pt(n);
00075 Vector<double> ptt(n);
00076 Vector<double> xit(n);
00077
00078 fret = funk(p);
00079 for (j=0; j<n; j++) pt[j]=p[j];
00080 for (iter=1; ;iter++) {
00081 fp = fret;
00082 ibig = 0;
00083 del = 0.0;
00084 for (i=0; i<n; i++) {
00085 for (j=0; j<n; j++) xit[j] = xi[j][i];
00086 fptt = fret;
00087 linmin(p.begin(),xit.begin(),n,fret);
00088 if (fabs(fptt-fret) > del) {
00089 del = fabs(fptt-fret);
00090 ibig = i;
00091 }
00092 }
00093 if (2.0*fabs(fp-fret) <= ftol*(fabs(fp)+fabs(fret))) {
00094 iter = nfunk;
00095 return fret;
00096 }
00097 if (iter == maxiter) {
00098 warning(" Too many iterations in routine POWELL\n"
00099 "%d out of %d",iter,maxiter);
00100 return fret;
00101 }
00102 for (j=0; j<n; j++) {
00103 ptt[j] = 2.0*p[j] - pt[j];
00104 xit[j] = p[j] - pt[j];
00105 pt[j] = p[j];
00106 }
00107 fptt = funk(ptt);
00108 if (fptt < fp) {
00109 t = 2.0*(fp-2.0*fret+fptt)*SQR(fp-fret-del)-del*SQR(fp-fptt);
00110 if (t < 0.0) {
00111 linmin(p.begin(),xit.begin(),n,fret);
00112 for (j=0; j<n; j++) xi[j][ibig] = xit[j];
00113 }
00114 }
00115 }
00116 }
00117 #undef SQR
00118
00119 #define TOL 2.0e-8
00120 int ncom=0;
00121 double *pcom = 0;
00122 double *xicom = 0;
00123
00124 static void linmin(double *p,double *xi,int n,double& fret)
00125 {
00126 int j;
00127 double xx,xmin,fx,fb,fa,bx,ax;
00128
00129 ncom = n;
00130
00131 if(n>0){
00132 pcom = new double [n];
00133 }
00134 else {
00135 pcom = 0;
00136 }
00137 if(n>0){
00138 xicom = new double [n];
00139 }
00140 else {
00141 xicom = 0;
00142 }
00143 for (j=0; j<n; j++) {
00144 pcom[j] = p[j];
00145 xicom[j] = xi[j];
00146 }
00147 ax=0.0;
00148 xx=1.0;
00149 bx=0.0; fa=0.0; fx=0.0; fb=0.0; xmin=0.0;
00150 mnbrak(ax,xx,bx,fa,fx,fb,f1dim);
00151 fret = brent(ax,xx,bx,f1dim,TOL,xmin);
00152 for (j=0; j<n; j++) {
00153 xi[j] *= xmin;
00154 p[j] += xi[j];
00155 }
00156 if(xicom){
00157 delete [] xicom;
00158 xicom=0;
00159 }
00160 if(pcom){
00161 delete [] pcom;
00162 pcom=0;
00163 }
00164 }
00165 #undef TOL
00166
00167 static double f1dim(double x)
00168 {
00169 Vector<double> xt(ncom);
00170 for (int j=0; j<ncom; j++) xt[j] = pcom[j] + x*xicom[j];
00171 double f = funk(xt);
00172 return f;
00173 }
00174
00175 #define GOLD 1.618034
00176 #define GLIMIT 200.0
00177 #define TINY 1.0e-20
00178 #define MAX(a,b) ((a) > (b) ? (a) : (b))
00179 #define SIGN(a,b) ((b) > 0.0 ? fabs(a) : -fabs(a))
00180 #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
00181
00182 static void mnbrak(double& ax,double& bx,double& cx,double& fa,
00183 double& fb,double& fc,double (*func)(double))
00184 {
00185 double ulim,u,r,q,fu,dum;
00186
00187 fa=(*func)(ax);
00188 fb=(*func)(bx);
00189 if (fb > fa) {
00190 SHFT(dum,ax,bx,dum)
00191 SHFT(dum,fb,fa,dum)
00192 }
00193 cx = bx+GOLD*(bx-ax);
00194 fc = (*func)(cx);
00195 while (fb > fc) {
00196 r=(bx-ax)*(fb-fc);
00197 q=(bx-cx)*(fb-fa);
00198 u=(bx)-((bx-cx)*q-(bx-ax)*r)/
00199 (2.0*SIGN(MAX(fabs(q-r),TINY),q-r));
00200 ulim = bx+GLIMIT*(cx-bx);
00201 if ((bx-u)*(u-cx) > 0.0) {
00202 fu=(*func)(u);
00203 if (fu < fc) {
00204 ax = bx;
00205 bx = u;
00206 fa = fb;
00207 fb = fu;
00208 return;
00209 } else if (fu > fb) {
00210 cx = u;
00211 fc = fu;
00212 return;
00213 }
00214 u= cx +GOLD*(cx-bx);
00215 fu=(*func)(u);
00216 } else if ((cx-u)*(u-ulim) > 0.0) {
00217 fu=(*func)(u);
00218 if (fu < fc) {
00219 SHFT(bx,cx,u,cx+GOLD*(cx-bx))
00220 SHFT(fb,fc,fu,(*func)(u))
00221 }
00222 } else if ((u-ulim)*(ulim-cx) >= 0.0) {
00223 u=ulim;
00224 fu=(*func)(u);
00225 } else {
00226 u=(cx)+GOLD*(cx-bx);
00227 fu=(*func)(u);
00228 }
00229 SHFT(ax,bx,cx,u)
00230 SHFT(fa,fb,fc,fu)
00231 }
00232 }
00233
00234 #undef GOLD
00235 #undef GLIMIT
00236 #undef TINY
00237 #undef MAX
00238 #undef SIGN
00239 #undef SHFT
00240
00241
00242 #define ITMAX 200
00243 #define CGOLD 0.3819660
00244 #define ZEPS 1.0e-10
00245 #define SIGN(a,b) ((b) > 0.0 ? fabs(a) : -fabs(a))
00246 #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
00247
00248 static double brent(double ax,double bx,double cx,double (*f)(double),double tol,double& xmin)
00249 {
00250 int iter;
00251 double a,b,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm;
00252 double e=0.0;
00253 double d=0.0;
00254
00255 a=((ax < cx) ? ax : cx);
00256 b=((ax > cx) ? ax : cx);
00257 x=w=v=bx;
00258 fw=fv=fx=(*f)(x);
00259 for (iter=1;iter<=ITMAX;iter++) {
00260 xm=0.5*(a+b);
00261 tol2=2.0*(tol1=tol*fabs(x)+ZEPS);
00262 if (fabs(x-xm) <= (tol2-0.5*(b-a))) {
00263 xmin=x;
00264 return fx;
00265 }
00266 if (fabs(e) > tol1) {
00267 r=(x-w)*(fx-fv);
00268 q=(x-v)*(fx-fw);
00269 p=(x-v)*q-(x-w)*r;
00270 q=2.0*(q-r);
00271 if (q > 0.0) p = -p;
00272 q=fabs(q);
00273 etemp=e;
00274 e=d;
00275 if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x))
00276 d=CGOLD*(e=(x >= xm ? a-x : b-x));
00277 else {
00278 d=p/q;
00279 u=x+d;
00280 if (u-a < tol2 || b-u < tol2)
00281 d=SIGN(tol1,xm-x);
00282 }
00283 } else {
00284 d=CGOLD*(e=(x >= xm ? a-x : b-x));
00285 }
00286 u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d));
00287 fu=(*f)(u);
00288 if (fu <= fx) {
00289 if (u >= x) {
00290 a=x;
00291 } else {
00292 b=x;
00293 }
00294 SHFT(v,w,x,u)
00295 SHFT(fv,fw,fx,fu)
00296 } else {
00297 if (u < x) {
00298 a=u;
00299 } else {
00300 b=u;
00301 }
00302 if (fu <= fw || w == x) {
00303 v=w;
00304 w=u;
00305 fv=fw;
00306 fw=fu;
00307 } else if (fu <= fv || v == x || v == w) {
00308 v=u;
00309 fv=fu;
00310 }
00311 }
00312 }
00313 warning(" Too many iterations in BRENT");
00314 xmin=x;
00315 return fx;
00316 }
00317
00318 #undef ITMAX
00319 #undef CGOLD
00320 #undef ZEPS
00321 #undef SIGN
00322 }
00323