Пример #1
0
int newton_min_func(double (*funcpt)(double *,int),double *xi,int N,double *dx,double fsval,double *xf) {
	int rcode,iter;
	int i,siter,retval;
	double gtol,stol;
	double fx,num,den,stop0,maxstep,fxf;
	double *jac,*hess,*scheck,*xc,*L,*step;
	
	jac = (double*) malloc(sizeof(double) *N);
	scheck = (double*) malloc(sizeof(double) *N);
	xc = (double*) malloc(sizeof(double) *N);
	step = (double*) malloc(sizeof(double) *N);
	hess = (double*) malloc(sizeof(double) *N * N);
	L = (double*) malloc(sizeof(double) *N * N);
	
	rcode = 0;
	iter = 0;
	siter = (int) SETITER;
	gtol = pow((double) FDVAL,1.0/3.0);
	stol = gtol * gtol;
	fx = funcpt(xi,N);
	jacobian_fd(funcpt,xi,N,jac);
	
	//set values
	maxstep = 1.0;
	
	for(i = 0; i < N;++i) {
		dx[i] = 1.0 / dx[i];
	}
	
	//Check Stop0
	if (fabs(fx) > fabs(fsval)) {
			den = fabs(fx);
	} else {
			den = fabs(fsval);
	}
	for(i = 0; i < N;++i) {
		if (fabs(xi[i]) > 1.0 / fabs(dx[i])) {
			num = fabs(xi[i]);
		} else {
			num = 1.0 / fabs(dx[i]);
		}
		scheck[i] = fabs(jac[i]) * num / den;
	}
	
	stop0 = array_max_abs(scheck,N);
	
	if (stop0 <= gtol * 1e-03) {
		rcode = 1;
		for(i = 0; i < N;++i) {
			xf[i] = xi[i];
		}
		return rcode;
	}
	
	hessian_fd(funcpt,xi,N,hess);
	
	for(i = 0; i < N;++i) {
		xc[i] = xi[i];
	}
	
	while (rcode == 0 && iter < siter) {
		modelhess(hess,N,dx,L);
		scale(jac,1,N,-1.0);
		linsolve_lower(L,N,jac,step);
		scale(jac,1,N,-1.0);
		retval = lnsrch(funcpt,xc,jac,step,N,maxstep,dx,stol,xf); 
		fxf = funcpt(xf,N);
		jacobian_fd(funcpt,xf,N,jac);
		rcode = stopcheck(fxf,N,xc,xf,jac,dx,fsval,gtol,stol,retval);
		hessian_fd(funcpt,xf,N,hess);
		for(i = 0; i < N;++i) {
			xc[i] = xf[i];
		}
	}
	
	free(jac);
	free(hess);
	free(scheck);
	free(xc);
	free(L);
	free(step);
	return rcode;
}
void ML_multi_QuasiNewton::dfpmin(v_ratep_type& p,
                                  const double gtol,
                                  int& iter,
                                  double& fret,
                                  ptr_eval_func func,
                                  ptr_eval_gradient_func dfunc
                                  // double func(const v_ratep_type& p),
                                  // void dfunc(const v_ratep_type& in,
                                  //            v_ratep_type& out)
                                 )
{
    // from Press et al 2002
    const int ITMAX = 200;
    const double EPS=std::numeric_limits<double>::epsilon();
    const double TOLX = 4.0*EPS, STPMX = 100.0;
    bool check;
    int i, its, j;
    double den, fac, fad, fae, fp, stpmax, sum=0.0, sumdg, sumxi, temp, test;

    int n = p.size();
    v_ratep_type dg(n), g(n), hdg(n), pnew(n), xi(n);
    std::vector<v_ratep_type> hessin;
    hessin.resize(n);
    for (int i = 0; i < n; ++i) hessin[i].resize(n);
    fp = (this->*func)(p);  // fp = func(p);
    (this->*dfunc)(p, g);   // dfunc(p, g);
    for (i = 0; i < n; ++i) {
        for (j = 0; j < n; ++j) hessin[i][j] = 0.0;
        hessin[i][i] = 1.0;
        xi[i] = -g[i];
        sum += p[i]*p[i];
    }
    stpmax = STPMX * MAX(std::sqrt(sum), double(n));
    for (its = 0; its < ITMAX; ++its) {
        iter = its;
        lnsrch(p, fp, g, xi, pnew, fret, stpmax, check, func);
        fp = fret;
        for (i = 0; i < n; ++i) {
            xi[i] = pnew[i] - p[i];
            p[i] = pnew[i];
        }
        test = 0.0;
        for (i = 0; i < n; ++i) {
            temp = std::abs(xi[i]) / MAX(std::abs(p[i]), 1.0);
            if (temp > test) test = temp;
        }
        if (test < TOLX)
            return;
        for (i = 0; i < n; ++i) dg[i] = g[i];
        (this->*dfunc)(p, g);  // dfunc(p, g);
        test = 0.0;
        den = MAX(fret, 1.0);
        for (i = 0; i < n; ++i) {
            temp = std::abs(g[i])*MAX(std::abs(p[i]), 1.0)/den;
            if (temp > test) test = temp;
        }
        if (test < gtol)
            return;
        for (i = 0; i < n; ++i) dg[i] = g[i] - dg[i];
        for (i = 0; i < n; ++i) {
            hdg[i] = 0.0;
            for (j = 0; j < n; ++j) hdg[i] += hessin[i][j]*dg[j];
        }
        fac = fae = sumdg = sumxi = 0.0;
        for (i = 0; i < n; ++i) {
            fac += dg[i]*xi[i];
            fae += dg[i]*hdg[i];
            sumdg += SQR(dg[i]);
            sumxi += SQR(xi[i]);
        }
        if (fac > std::sqrt(EPS*sumdg*sumxi)) {
            fac = 1.0 / fac;
            fad = 1.0 / fae;
            for (i = 0; i < n; ++i) dg[i] = fac*xi[i] - fad*hdg[i];
            for (i = 0; i < n; ++i) {
                for (j = i; j < n; ++j) {
                    hessin[i][j] += fac*xi[i]*xi[j] -
                                    fad*hdg[i]*hdg[j] +
                                    fae*dg[i]*dg[j];
                    hessin[j][i] = hessin[i][j];
                }
            }
        }
        for (i = 0; i < n; ++i) {
            xi[i] = 0.0;
            for (j = 0; j < n; ++j) xi[i] -= hessin[i][j]*g[j];
        }
    }
    std::cerr << "dfpmin(): too many iterations" << std::endl;
    assert(false);
}