Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

min_nr_powell.cpp

Go to the documentation of this file.
00001 //****************************************************
00002 //  April, 1993, University of Illinois
00003 // Copyright (C) 1993, 1994 Tianlin Wang
00004 /* Copyright (C) 1994-2003 Matvec Development Team. 
00005 
00006   This program is free software; you can redistribute it and/or
00007   modify it under the terms of the GNU Library General Public
00008   License as published by the Free Software Foundation; either
00009   version 2 of the License, or (at your option) any later version.
00010   
00011   This program is distributed in the hope that it will be useful,
00012   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014   Library General Public License for more details.
00015     
00016   You should have received a copy of the GNU Library General Public
00017   License along with this library; if not, write to the Free
00018   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00019   MA 02111-1307, USA 
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;   /* defining declarations */
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 } ///////// end of namespace matvec
00323 

Generated on Thu Jun 16 17:13:47 2005 for Matvec by doxygen1.2.16