void tron(double[] w)
{
// Parameters for updating the iterates.
double eta0 = 1e-4, eta1 = 0.25, eta2 = 0.75;
// Parameters for updating the trust region size delta.
double sigma1 = 0.25, sigma2 = 0.5, sigma3 = 4;
int n = NumberOfVariables;
int cg_iter;
double alpha, fnew, prered, actred;
int search = 1, iter = 1;
double[] s = new double[n];
double[] r = new double[n];
double[] w_new = new double[n];
double f = Function(w);
double[] g = Gradient(w);
// delta = dnrm2_(&n, g, &inc);
double delta = 0;
for (int j = 0; j < g.Length; j++)
delta += g[j] * g[j];
delta = Math.Sqrt(delta);
double gnorm1 = delta;
double gnorm = gnorm1;
if (gnorm <= eps * gnorm1)
search = 0;
iter = 1;
while (iter <= max_iter && search == 1)
{
if (Token.IsCancellationRequested)
break;
cg_iter = trcg(delta, g, s, r);
for (int j = 0; j < w_new.Length; j++)
w_new[j] = w[j] + s[j];
double gs = 0;
for (int j = 0; j < g.Length; j++)
gs += g[j] * s[j];
double t = 0;
for (int j = 0; j < s.Length; j++)
t += s[j] * r[j];
prered = -0.5 * (gs - t);
fnew = Function(w_new);
// Compute the actual reduction.
actred = f - fnew;
// On the first iteration, adjust the initial step bound.
double snorm = 0;
for (int j = 0; j < s.Length; j++)
snorm += s[j] * s[j];
snorm = Math.Sqrt(snorm);
if (iter == 1)
delta = Math.Min(delta, snorm);
// Compute prediction alpha*snorm of the step.
if (fnew - f - gs <= 0)
alpha = sigma3;
else
alpha = Math.Max(sigma1, -0.5 * (gs / (fnew - f - gs)));
// Update the trust region bound according to the ratio of actual to predicted reduction.
if (actred < eta0 * prered)
delta = Math.Min(Math.Max(alpha, sigma1) * snorm, sigma2 * delta);
else if (actred < eta1 * prered)
delta = Math.Max(sigma1 * delta, Math.Min(alpha * snorm, sigma2 * delta));
else if (actred < eta2 * prered)
delta = Math.Max(sigma1 * delta, Math.Min(alpha * snorm, sigma3 * delta));
else
delta = Math.Max(delta, Math.Min(alpha * snorm, sigma3 * delta));
Trace.WriteLine(String.Format(
"iter {0} act {1:E03} pre {2:E03} delta {3:E03} f {4:E03} |g| {5:E03} CG {6}",
iter, actred, prered, delta, f, gnorm, cg_iter));
if (actred > eta0 * prered)
{
iter++;
for (int j = 0; j < w.Length; j++)
w[j] = w_new[j];
f = fnew;
g = Gradient(w);
gnorm = 0;
for (int j = 0; j < g.Length; j++)
gnorm += g[j];
gnorm = Math.Sqrt(gnorm);
if (gnorm <= eps * gnorm1)
break;
}
// TODO: Use these status codes in a TrustRegionNewtonMethodStatus enumeration
if (f < -1.0e+32)
{
Trace.WriteLine("WARNING: f < -1.0e+32");
break;
}
if (Math.Abs(actred) <= 0 && prered <= 0)
{
Trace.WriteLine("WARNING: actred and prered <= 0");
break;
}
if (Math.Abs(actred) <= 1.0e-12 * Math.Abs(f) &&
Math.Abs(prered) <= 1.0e-12 * Math.Abs(f))
{
Trace.WriteLine("WARNING: actred and prered too small");
break;
}
}
}