Accord.Math.Optimization.TrustRegionNewtonMethod.tron C# (CSharp) Method

tron() private method

private tron ( double w ) : void
w double
return void
        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;
                }
            }
        }