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

matvec::Minimizer Class Reference

#include <minimizer.h>

Inheritance diagram for matvec::Minimizer:

matvec::Model matvec::GLMM List of all members.

Public Methods

 Minimizer (void)
virtual ~Minimizer (void)
virtual double minfun (const Vector< double > &x, const int n)=0
void min_prtlevel (const int pl)
double praxis (Vector< double > &x, const int n, int &maxfun, const double tol=1.0e-16, const double epsilon=1.0e-8, const int pl=2)

Protected Attributes

int minfun_indx

Private Methods

void min_first_dir (const int j, const int nits, double *d2, double *x1, double f1, const int fk, Vector< double > &x, const int n, const Matrix< double > &v, Vector< double > &w, Matrix< double > &q01)
void quadratic (Vector< double > &x, const int n, const Matrix< double > &v, Vector< double > &w, Matrix< double > &q01)

Private Attributes

int prtlevel

Constructor & Destructor Documentation

matvec::Minimizer::Minimizer void    [inline]
 

Definition at line 46 of file minimizer.h.

References minfun_indx, and prtlevel.

00046 {prtlevel = 2; minfun_indx = 0;}

virtual matvec::Minimizer::~Minimizer void    [inline, virtual]
 

Definition at line 47 of file minimizer.h.

00047 {;}


Member Function Documentation

void matvec::Minimizer::min_first_dir const int    j,
const int    nits,
double *    d2,
double *    x1,
double    f1,
const int    fk,
Vector< double > &    x,
const int    n,
const Matrix< double > &    v,
Vector< double > &    w,
Matrix< double > &    q01
[private]
 

Definition at line 406 of file min_praxis.cpp.

References matvec::dmin, matvec::flin(), matvec::fx, matvec::h, matvec::ldt, matvec::m2, matvec::m4, matvec::macheps, minfun(), matvec::nf, matvec::nl, matvec::SmaLL, and matvec::t.

Referenced by praxis(), and quadratic().

00410 {
00411    int k, i, dz;
00412    double x2, xm, f0, f2, fm, d1, t2, s, sf1, sx1;
00413 
00414    sf1 = f1; sx1 = *x1;
00415    k = 0; xm = 0.0; fm = f0 = fx; dz = *d2 < macheps;
00416    ///////////////////////////////////
00417    //        find step size        //
00418    //////////////////////////////////
00419    s = 0;
00420    for (i=0; i<n; i++) s += x[i]*x[i];
00421    s = std::sqrt(s);
00422    if (dz) { t2 = m4*std::sqrt(std::fabs(fx)/dmin + s*ldt) + m2*ldt; }
00423    else    { t2 = m4*std::sqrt(std::fabs(fx)/(*d2) + s*ldt) + m2*ldt; }
00424    s = s*m4 + t;
00425    if (dz && t2 > s) t2 = s;
00426    if (t2 < SmaLL) t2 = SmaLL;
00427    if (t2 > 0.01*h) t2 = 0.01 * h;
00428    if (fk && f1 <= fm) {
00429       xm = *x1;
00430       fm = f1;
00431    }
00432    if (!fk || std::fabs(*x1) < t2) {
00433       *x1 = (*x1 > 0 ? t2 : -t2);
00434       flin(*x1, j,x,n,v,w,q01);
00435       nf++;
00436       f1 = minfun(w,n);
00437    }
00438    if (f1 <= fm) {
00439       xm = *x1;
00440       fm = f1;
00441    }
00442 next:
00443    if (dz) {
00444       x2 = (f0 < f1 ? -(*x1) : 2*(*x1));
00445       flin(x2, j,x,n,v,w,q01);
00446       nf++;
00447       f2 = minfun(w,n);
00448       if (f2 <= fm) {
00449          xm = x2;
00450          fm = f2;
00451       }
00452       *d2 = (x2*(f1-f0) - (*x1)*(f2-f0))/((*x1)*x2*((*x1)-x2));
00453    }
00454    d1 = (f1-f0)/(*x1) - *x1**d2; dz = 1;
00455    if (*d2 <= SmaLL) { x2 = (d1 < 0 ? h : -h); }
00456    else              { x2 = - 0.5*d1/(*d2); }
00457    if (std::fabs(x2) > h) x2 = (x2 > 0 ? h : -h);
00458 tryit:
00459    flin(x2, j,x,n,v,w,q01);
00460    nf++;
00461    f2 = minfun(w,n);
00462    if ((k < nits) && (f2 > f0)) {
00463       k++;
00464       if ((f0 < f1) && (*x1*x2 > 0.0)) goto next;
00465       x2 *= 0.5;
00466       goto tryit;
00467    }
00468    nl++;
00469    if (f2 > fm) x2 = xm; else fm = f2;
00470    if (std::fabs(x2*(x2-*x1)) > SmaLL) {
00471       *d2 = (x2*(f1-f0) - *x1*(fm-f0))/(*x1*x2*(*x1-x2));
00472    }
00473    else {
00474       if (k > 0) *d2 = 0;
00475    }
00476    if (*d2 <= SmaLL) *d2 = SmaLL;
00477    *x1 = x2; fx = fm;
00478    if (sf1 < fx) {
00479       fx = sf1;
00480       *x1 = sx1;
00481    }
00482    if (j != -1) for (i=0; i<n; i++) x[i] += (*x1)*v[i][j];
00483 }

void matvec::Minimizer::min_prtlevel const int    pl [inline]
 

Definition at line 50 of file minimizer.h.

References prtlevel.

00050 {prtlevel = pl;}

virtual double matvec::Minimizer::minfun const Vector< double > &    x,
const int    n
[pure virtual]
 

Implemented in matvec::Model.

Referenced by min_first_dir(), and praxis().

double matvec::Minimizer::praxis Vector< double > &    x,
const int    n,
int &    maxfun,
const double    tol = 1.0e-16,
const double    epsilon = 1.0e-8,
const int    pl = 2
 

Definition at line 88 of file min_praxis.cpp.

References matvec::Vector< T >::begin(), matvec::Matrix< T >::begin(), matvec::dmin, matvec::fx, matvec::h, matvec::large, matvec::ldt, matvec::m2, matvec::m4, matvec::macheps, min_first_dir(), minfun(), matvec::nf, matvec::nl, matvec::Matrix< T >::print(), matvec::Vector< T >::print(), matvec::print(), prtlevel, matvec::qd, matvec::qf1, matvec::ranf(), matvec::SmaLL, matvec::sort(), matvec::svd(), matvec::t, matvec::vlarge, and matvec::vsmall.

Referenced by matvec::Model::multipoint_ml_estimate(), and matvec::Model::vce_dfreml().

00090 {
00091    ////////////////////////////////////////////////////////////////////
00092    // references:
00093    //  - powell, m.j.d., 1964. an efficient method for finding
00094    //    the minimum of a function in several variables without
00095    //    calculating derivatives, computer journal, 7, 155-162
00096    //  - brent, r.p., 1973. algorithms for minimization without
00097    //    derivatives, prentice hall, englewood cliffs.
00098    //
00099    //  problems, suggestions or improvements are always wellcome
00100    //                    karl gegenfurtner   07/08/87
00101    //                                        c - version
00102    //  On Thu Oct 21 19:56:35 CDT 1993, Tianlin made it into C++ version
00103    //  note that lots of globel variables have been removed.
00104    //
00105    //
00106    // usage: min = praxis(fun, x, n);
00107    //
00108    // fun       the function to be minimized. fun is called from
00109    //           praxis with x and n as arguments
00110    // x         a double array containing the initial guesses for
00111    //           the minimum, which will contain the solution on
00112    //           return
00113    // n         an integer specifying the number of unknown
00114    //           parameters
00115    // min       praxis returns the least calculated value of fun
00116    //
00117    // some additional global variables control some more aspects of
00118    // the inner workings of praxis. setting them is optional, they
00119    // are all set to some reasonable default values given below.
00120    //
00121    //  prin      controls the printed output from the routine.
00122    //            0 -> no output
00123    //            1 -> print only starting and final values
00124    //            2 -> detailed map of the minimization process
00125    //            3 -> print also eigenvalues and vectors of the
00126    //                 search directions
00127    //            the default value is 1
00128    // tol        is the tolerance allowed for the precision of the
00129    //            solution. praxis returns if the criterion
00130    //            2 * ||x[k]-x[k-1]|| <= sqrt(macheps) * ||x[k]|| + tol
00131    //            is fulfilled more than ktm times.
00132    //            the default value 1.0e-16
00133    //            tol is usually equal to  EPISILON*EPISILON
00134    //            where
00135    // ktm        see just above. default is 1, and a value of 4 leads
00136    //            to a very(!) cautious stopping criterion.
00137    // step       is a steplength parameter and should be set equal
00138    //            to the expected distance from the solution.
00139    //            exceptionally small or large values of step lead to
00140    //            slower convergence on the first few iterations
00141    //            the default value for step is 1.0
00142    // scbd       is a scaling parameter. 1.0 is the default and
00143    //            indicates no scaling. if the scales for the different
00144    //            parameters are very different, scbd should be set to
00145    //            a value of about 10.0.
00146    // illc       should be set to true (1) if the problem is known to
00147    //            be ill-conditioned. the default is false (0). this
00148    //            variable is automatically set, when praxis finds
00149    //            the problem to be ill-conditioned during iterations.
00150    // maxfun     is the maximum number of calls to fun allowed. praxis
00151    //            will return after maxfun calls to fun even when the
00152    //            minimum is not yet found. the default value of 0
00153    //            indicates no limit on the number of calls.
00154    //            this return condition is only checked every n
00155    //            iterations.
00156    //
00157    //////////////////////////////////////////////////////////////////////
00158    int i,j,k,k2, W = 6 + 6;
00159 
00160    int  ktm = 1;
00161    int illc = 0;
00162    double scbd = 1.0;
00163    double step = 10.0;         // after the first n*10 loop, step reset to 1
00164    Vector<double> y(n);
00165    Vector<double> z(n);
00166    Vector<double> d(n);
00167 //   d[0] = 0.0;
00168 
00169    Vector<double> w(n);              // working space for flin
00170    Matrix<double> v(n,n);
00171    Matrix<double> q01(2,n);
00172 
00173    qd[0] = 0.0;
00174    prtlevel = pl;
00175    macheps = epsilon;
00176    SmaLL = macheps*macheps;
00177    vsmall = SmaLL*SmaLL;
00178    large = 1.0/SmaLL;
00179    vlarge = 1.0/vsmall;
00180    m2 = std::sqrt(macheps); m4 = std::sqrt(m2);
00181 
00182    nl = 0;
00183    nf = 1;
00184    double t2,sl,dn,df,sf,lds,f1,s;
00185    h = step;
00186 
00187    dmin = SmaLL;
00188    t2 = SmaLL + std::fabs(tol);
00189    t = t2;
00190    double ldfac = (illc ? 0.1 : 0.01);
00191    int kt = 0;
00192    int kl;
00193 
00194    fx = minfun(x, n);
00195    qf1 = fx;
00196 
00197    if (h < 100.0*t) h = 100.0*t;
00198    ldt = h;
00199    for (i=0; i<n; i++) for (j=0; j<n; j++) v[i][j] = (i == j ? 1.0 : 0.0);
00200    for (i=0; i<n; i++) q01[1][i] = x[i];
00201    if (prtlevel > 1) {
00202       std::cout << "\n------------- enter function praxis -----------\n";
00203       std::cout << "-- current parameter settings\n";
00204       std::cout << "-- scaling: " << std::setw(W) << scbd   << "\n";
00205       std::cout << "-- tol    : " << std::setw(W) << t      << "\n";
00206       std::cout << "-- maxstep: " << std::setw(W) << h      << "\n";
00207       std::cout << "-- illc   : " << std::setw(W) << illc   << "\n";
00208       std::cout << "-- ktm    : " << std::setw(W) << ktm    << "\n";
00209       std::cout << "-- maxite : " << std::setw(W) << maxfun << "\n";
00210    }
00211    if (prtlevel) print(n,x);
00212 
00213 mloop:
00214    sf = d[0];
00215    s = d[0] = 0.0;
00216 
00217    /* minimize along first direction */
00218    min_first_dir(0,2,&d[0],&s,fx,0,x,n,v,w,q01);
00219    if (s <= 0.0) for (i=0; i < n; i++) v[i][0] = -v[i][0];
00220    if ((sf <= (0.9 * d[0])) || ((0.9 * sf) >= d[0])) {
00221       for (i=1; i<n; i++) d[i] = 0.0;
00222    }
00223    for (k=1; k<n; k++) {
00224       for (i=0; i<n; i++) y[i] = x[i];
00225       sf = fx;
00226       illc = illc || (kt > 0);
00227 next:
00228       kl = k;
00229       df = 0.0;
00230       if (illc) {        /* random step to get off resolution valley */
00231          for (i=0; i<n; i++) {
00232             z[i] = (0.1*ldt + t2*pow(10.0,(double)kt))*(ranf()-0.5);
00233             s = z[i];
00234             for (j=0; j < n; j++) x[j] += s * v[j][i];
00235          }
00236          fx = minfun(x, n);
00237          nf++;
00238       }
00239        /* minimize along non-conjugate directions */
00240       for (k2=k; k2<n; k2++) {
00241          sl = fx;
00242          s = 0.0;
00243          min_first_dir(k2,2,&d[k2],&s,fx,0,x,n,v,w,q01);
00244          if (illc) {
00245             s = d[k2] * (s + z[k2]) * (s + z[k2]);
00246          }
00247          else
00248             s = sl - fx;
00249          if (df < s) {
00250             df = s;
00251             kl = k2;
00252          }
00253       }
00254 
00255       if (!illc && (df < std::fabs(100.0 * macheps * fx))) {
00256          illc = 1;
00257          goto next;
00258       }
00259       if (k == 1 && prtlevel > 1) {
00260          std::cout << "\n-- New Direction:\n";
00261          d.print();
00262       }
00263        // minimize along conjugate directions
00264       for (k2=0; k2<=k-1; k2++) {
00265          s = 0.0;
00266          min_first_dir(k2,2,&d[k2],&s,fx,0,x,n,v,w,q01);
00267       }
00268       f1 = fx;
00269       fx = sf;
00270       lds = 0.0;
00271       for (i=0; i<n; i++) {
00272          sl = x[i];
00273          x[i] = y[i];
00274          y[i] = sl - y[i];
00275          sl = y[i];
00276          lds = lds + sl*sl;
00277       }
00278       lds = std::sqrt(lds);
00279       if (lds > SmaLL) {
00280          for (i=kl-1; i>=k; i--) {
00281             for (j=0; j < n; j++) v[j][i+1] = v[j][i];
00282             d[i+1] = d[i];
00283          }
00284          d[k] = 0.0;
00285          for (i=0; i < n; i++) v[i][k] = y[i] / lds;
00286          min_first_dir(k,4,&d[k],&lds,f1,1,x,n,v,w,q01);
00287          if (lds <= 0.0) {
00288             lds = -lds;
00289             for (i=0; i<n; i++) v[i][k] = -v[i][k];
00290          }
00291       }
00292       ldt = ldfac * ldt;
00293       if (ldt < lds) ldt = lds;
00294       if (prtlevel > 1) print(n,x);
00295       t2 = 0.0;
00296       for (i=0; i<n; i++) t2 += x[i]*x[i];
00297       t2 = m2 * std::sqrt(t2) + t;
00298       if (ldt > (0.5 * t2))
00299          kt = 0;
00300       else
00301          kt++;
00302       if (kt > ktm) goto fret;
00303    }
00304    /////////////////////////////////////////////
00305    //  try quadratic extrapolation in case    //
00306    //  we are stuck in a curved valley        //
00307    /////////////////////////////////////////////
00308    quadratic(x,n,v,w,q01);
00309    dn = 0.0;
00310    for (i=0; i<n; i++) {
00311       d[i] = 1.0 / std::sqrt(d[i]);
00312       if (dn < d[i]) dn = d[i];
00313    }
00314    if (prtlevel > 2) {
00315       std::cout << "\n-- New Matrix of Directions:\n";
00316       v.print();
00317    }
00318 
00319    for (j=0; j<n; j++) {
00320       s = d[j] / dn;
00321       for (i=0; i < n; i++) v[i][j] *= s;
00322    }
00323    if (scbd > 1.0) {               // scale axis to reduce condition number
00324       s = vlarge;
00325       for (i=0; i<n; i++) {
00326          sl = 0.0;
00327          for (j=0; j < n; j++) sl += v[i][j]*v[i][j];
00328          z[i] = std::sqrt(sl);
00329          if (z[i] < m4) z[i] = m4;
00330          if (s > z[i]) s = z[i];
00331       }
00332       for (i=0; i<n; i++) {
00333          sl = s / z[i];
00334          z[i] = 1.0 / sl;
00335          if (z[i] > scbd) {
00336             sl = 1.0 / scbd;
00337             z[i] = scbd;
00338          }
00339       }
00340    }
00341    for (i=1; i<n; i++) {
00342       for (j=0; j<=i-1; j++) {
00343          s = v[i][j];
00344          v[i][j] = v[j][i];
00345          v[j][i] = s;
00346       }
00347    }
00348    svd(n, macheps, vsmall, v.begin(), d.begin());
00349    if (scbd > 1.0) {
00350       for (i=0; i<n; i++) {
00351          s = z[i];
00352          for (j=0; j<n; j++) v[i][j] *= s;
00353       }
00354       for (i=0; i<n; i++) {
00355          s = 0.0;
00356          for (j=0; j<n; j++) s += v[j][i]*v[j][i];
00357          s = std::sqrt(s);
00358          d[i] *= s;
00359          s = 1.0 / s;
00360          for (j=0; j<n; j++) v[j][i] *= s;
00361       }
00362    }
00363    for (i=0; i<n; i++) {
00364       if ((dn * d[i]) > large)
00365          d[i] = vsmall;
00366       else if ((dn * d[i]) < SmaLL)
00367          d[i] = vlarge;
00368       else
00369          d[i] = pow(dn * d[i],-2.0);
00370    }
00371    sort(n,d.begin(),v.begin());               // the new eigenvalues and eigenvectors
00372    dmin = d[n-1];
00373    if (dmin < SmaLL) dmin = SmaLL;
00374    illc = (m2 * d[0]) > dmin;
00375    if (prtlevel > 2 && scbd > 1.0) {
00376       std::cout << "\n-- Scale Factors:\n";
00377       z.print();
00378    }
00379    if (prtlevel > 2) {
00380       std::cout << "\n-- Eigenvalues of A:\n";
00381       d.print();
00382       std::cout << "\n-- Eigenvectors of A:\n";
00383       v.print();
00384    }
00385 
00386    if (maxfun > 0 && nl > maxfun) {
00387       if (prtlevel) std::cout << "\n-- maxiimum # of function calls reached \n";
00388       goto fret;
00389    }
00390    if (nf > n*10) step = 1.0;
00391    goto mloop;   // back to main loop
00392 
00393 fret:
00394    if (prtlevel > 0) {
00395       std::cout << "\n--after " << nf << " function calls\n";
00396       std::cout << "-- your function f(x) has finally been minimized to "
00397            << std::setprecision(W) << fx << "\n";
00398       std::cout.precision(6);
00399       std::cout << "-- with final x:\n";
00400       x.print();
00401    }
00402    maxfun = nf;
00403    return fx;
00404 }

void matvec::Minimizer::quadratic Vector< double > &    x,
const int    n,
const Matrix< double > &    v,
Vector< double > &    w,
Matrix< double > &    q01
[private]
 

Definition at line 485 of file min_praxis.cpp.

References matvec::fx, min_first_dir(), matvec::nl, matvec::qd, and matvec::qf1.

00487 {                               // look for a minimum along the curve q0, q1 //
00488    int i;
00489    double l, s,qa,qb,qc;
00490    s = fx; fx = qf1; qf1 = s;   // swap fx and qf1
00491    qd[1] = 0.0;
00492    for (i=0; i<n; i++) {
00493        s = x[i]; l = q01[1][i]; x[i] = l; q01[1][i] = s;
00494        qd[1] += (s-l)*(s-l);
00495    }
00496    s = 0.0; qd[1] = std::sqrt(qd[1]); l = qd[1];
00497    if ( qd[0]>0.0 && qd[1]>0.0 && nl>=3*n*n ) {
00498       min_first_dir(-1,2, &s,&l,qf1,1,x, n,v,w,q01);
00499       qa = l*(l-qd[1])/(qd[0]*(qd[0]+qd[1]));
00500       qb = (l+qd[0])*(qd[1]-l)/(qd[0]*qd[1]);
00501       qc = l*(l+qd[0])/(qd[1]*(qd[0]+qd[1]));
00502    }
00503    else { qa = qb = 0.0; qc = 1.0; }
00504    qd[0] = qd[1];
00505    for (i=0; i<n; i++) {
00506       s = q01[0][i]; q01[0][i] = x[i];
00507       x[i] = qa*s + qb*x[i] + qc*q01[1][i];
00508    }
00509 }


Member Data Documentation

int matvec::Minimizer::minfun_indx [protected]
 

Definition at line 43 of file minimizer.h.

Referenced by matvec::Model::minfun(), Minimizer(), matvec::Model::multipoint_ml_estimate(), and matvec::Model::vce_dfreml().

int matvec::Minimizer::prtlevel [private]
 

Definition at line 36 of file minimizer.h.

Referenced by min_prtlevel(), Minimizer(), and praxis().


The documentation for this class was generated from the following files:
Generated on Thu Jun 16 17:14:36 2005 for Matvec by doxygen1.2.16