void dcauchy(int n, double *x, double *xl, double *xu, double *A, double *g, double delta, double *alpha, double *s)
{
/*
c     **********
c
c     Subroutine dcauchy
c
c     This subroutine computes a Cauchy step that satisfies a trust
c     region constraint and a sufficient decrease condition.
c
c     The Cauchy step is computed for the quadratic
c
c           q(s) = 0.5*s'*A*s + g'*s,
c
c     where A is a symmetric matrix , and g is a vector. Given a 
c     parameter alpha, the Cauchy step is
c
c           s[alpha] = P[x - alpha*g] - x,
c
c     with P the projection onto the n-dimensional interval [xl,xu].
c     The Cauchy step satisfies the trust region constraint and the
c     sufficient decrease condition
c
c           || s || <= delta,      q(s) <= mu_0*(g'*s),
c
c     where mu_0 is a constant in (0,1).
c
c	parameters:
c
c       n is an integer variable.
c         On entry n is the number of variables.
c         On exit n is unchanged.
c
c       x is a double precision array of dimension n.
c         On entry x specifies the vector x.
c         On exit x is unchanged.
c
c       xl is a double precision array of dimension n.
c         On entry xl is the vector of lower bounds.
c         On exit xl is unchanged.
c
c       xu is a double precision array of dimension n.
c         On entry xu is the vector of upper bounds.
c         On exit xu is unchanged.
c
c       A is a double precision array of dimension n*n.
c         On entry A specifies the matrix A.
c         On exit A is unchanged.
c
c       g is a double precision array of dimension n.
c         On entry g specifies the gradient g.
c         On exit g is unchanged.
c
c       delta is a double precision variable.
c         On entry delta is the trust region size.
c         On exit delta is unchanged.
c
c       alpha is a double precision variable.
c         On entry alpha is the current estimate of the step.
c         On exit alpha defines the Cauchy step s[alpha].
c
c       s is a double precision array of dimension n.
c         On entry s need not be specified.
c         On exit s is the Cauchy step s[alpha].
c
c     **********
*/

	double one = 1, zero = 0;

	/* Constant that defines sufficient decrease.
	Interpolation and extrapolation factors. */
	double mu0 = 0.01, interpf = 0.1, extrapf = 10;
	
	int search, interp, nbrpt, nsteps = 1, i, inc = 1;
	double alphas, brptmax, brptmin, gts, q; 
	double *wa = (double *) xmalloc(sizeof(double)*n);
	
	/* Find the minimal and maximal break-point on x - alpha*g. */
	for (i=0;i<n;i++)
		wa[i] = -g[i];
	dbreakpt(n, x, xl, xu, wa, &nbrpt, &brptmin, &brptmax);
	
	/* Evaluate the initial alpha and decide if the algorithm
	must interpolate or extrapolate. */
	dgpstep(n, x, xl, xu, -(*alpha), g, s);
	if (dnrm2_(&n, s, &inc) > delta)
		interp = 1;
	else
	{
		dsymv_("U", &n, &one, A, &n, s, &inc, &zero, wa, &inc);
		gts = ddot_(&n, g, &inc, s, &inc);
		q = 0.5*ddot_(&n, s, &inc, wa, &inc) + gts;
		interp = q >= mu0*gts ? 1 : 0;
	}
	
	/* Either interpolate or extrapolate to find a successful step. */
	if (interp)
	{

		/* Reduce alpha until a successful step is found. */
		search = 1;
		while (search)
		{

			/* This is a crude interpolation procedure that
			will be replaced in future versions of the code. */
			nsteps++;
			(*alpha) *= interpf;
			dgpstep(n, x, xl, xu, -(*alpha), g, s);
			if (dnrm2_(&n, s, &inc) <= delta)
			{
				dsymv_("U", &n, &one, A, &n, s, &inc, &zero, wa, &inc);
				gts = ddot_(&n, g, &inc, s, &inc);
				q = 0.5*ddot_(&n, s, &inc, wa, &inc) + gts;
				search = q > mu0*gts ? 1 : 0;
			} 			
		}	
	}
	else
	{
		search = 1;
		alphas = *alpha;
	
		/* Increase alpha until a successful step is found. */
		while (search && (*alpha) <= brptmax)
		{
		
			/* This is a crude extrapolation procedure that
			will be replaced in future versions of the code. */
			nsteps++;
			alphas = *alpha;
			(*alpha) *= extrapf;
			dgpstep(n, x, xl, xu, -(*alpha), g, s);
			if (dnrm2_(&n, s, &inc) <= delta)
			{
				dsymv_("U", &n, &one, A, &n, s, &inc, &zero, wa, &inc);
				gts = ddot_(&n, g, &inc, s, &inc);
				q = 0.5*ddot_(&n, s, &inc, wa, &inc) + gts;
				search = q < mu0*gts ? 1 : 0;
			}
			else
				search = 0;					
		}
		*alpha = alphas;
		dgpstep(n, x, xl, xu, -(*alpha), g, s);
	}

	free(wa);
}
Example #2
0
void dprsrch(int n, double *x, double *xl, double *xu, double *A, double *g, double *w)
{
/*
c     **********
c
c     Subroutine dprsrch
c
c     This subroutine uses a projected search to compute a step
c     that satisfies a sufficient decrease condition for the quadratic
c
c           q(s) = 0.5*s'*A*s + g'*s,
c
c     where A is a symmetric matrix and g is a vector. Given the 
c     parameter alpha, the step is
c
c           s[alpha] = P[x + alpha*w] - x,
c
c     where w is the search direction and P the projection onto the 
c     n-dimensional interval [xl,xu]. The final step s = s[alpha] 
c     satisfies the sufficient decrease condition
c
c           q(s) <= mu_0*(g'*s),
c
c     where mu_0 is a constant in (0,1).
c
c     The search direction w must be a descent direction for the
c     quadratic q at x such that the quadratic is decreasing
c     in the ray  x + alpha*w for 0 <= alpha <= 1.
c
c	parameters:
c
c       n is an integer variable.
c         On entry n is the number of variables.
c         On exit n is unchanged.
c
c       x is a double precision array of dimension n.
c         On entry x specifies the vector x.
c         On exit x is set to the final point P[x + alpha*w].
c
c       xl is a double precision array of dimension n.
c         On entry xl is the vector of lower bounds.
c         On exit xl is unchanged.
c
c       xu is a double precision array of dimension n.
c         On entry xu is the vector of upper bounds.
c         On exit xu is unchanged.
c
c       A is a double precision array of dimension n*n.
c         On entry A specifies the matrix A
c         On exit A is unchanged.
c
c       g is a double precision array of dimension n.
c         On entry g specifies the vector g.
c         On exit g is unchanged.
c
c       w is a double prevision array of dimension n.
c         On entry w specifies the search direction.
c         On exit w is the step s[alpha].
c
c     **********
*/

	double one = 1, zero = 0;

	/* Constant that defines sufficient decrease. */
	/* Interpolation factor. */
	double mu0 = 0.01, interpf = 0.5;
	
	double *wa1 = (double *) xmalloc(sizeof(double)*n);
	double *wa2 = (double *) xmalloc(sizeof(double)*n);

	/* Set the initial alpha = 1 because the quadratic function is 
	decreasing in the ray x + alpha*w for 0 <= alpha <= 1 */
	double alpha = 1, brptmin, brptmax, gts, q;
	int search = 1, nbrpt, nsteps = 0, i, inc = 1;	

	/* Find the smallest break-point on the ray x + alpha*w. */
	dbreakpt(n, x, xl, xu, w, &nbrpt, &brptmin, &brptmax);

	/* Reduce alpha until the sufficient decrease condition is
	satisfied or x + alpha*w is feasible. */
	while (search && alpha > brptmin)
	{

		/* Calculate P[x + alpha*w] - x and check the sufficient
		decrease condition. */
		nsteps++;
		dgpstep(n, x, xl, xu, alpha, w, wa1);
		F77_CALL(dsymv)("U", &n, &one, A, &n, wa1, &inc, &zero, wa2, &inc);
		gts = F77_CALL(ddot)(&n, g, &inc, wa1, &inc);
		q = 0.5*F77_CALL(ddot)(&n, wa1, &inc, wa2, &inc) + gts;
		if (q <= mu0*gts)
			search = 0;
		else
		
			/* This is a crude interpolation procedure that
			will be replaced in future versions of the code. */
			alpha *= interpf;
	}

	/* Force at least one more constraint to be added to the active
	set if alpha < brptmin and the full step is not successful. 
	There is sufficient decrease because the quadratic function 
	is decreasing in the ray x + alpha*w for 0 <= alpha <= 1. */
	if (alpha < 1 && alpha < brptmin)
		alpha = brptmin;

	/* Compute the final iterate and step. */
	dgpstep(n, x, xl, xu, alpha, w, wa1);
	F77_CALL(daxpy)(&n, &alpha, w, &inc, x, &inc);
	for (i=0;i<n;i++)
		x[i] = mymax(xl[i], mymin(x[i], xu[i]));
	memcpy(w, wa1, sizeof(double)*n);

	free(wa1);
	free(wa2);
}