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

trcg() private method

private trcg ( double delta, double g, double s, double r ) : int
delta double
g double
s double
r double
return int
        int trcg(double delta, double[] g, double[] s, double[] r)
        {
            int n = NumberOfVariables;
            double[] d = new double[n];

            for (int i = 0; i < g.Length; i++)
            {
                s[i] = 0;
                r[i] = -g[i];
                d[i] = r[i];
            }


            double cgtol = 0; // cgtol = 0.1 * dnrm2_(&n, g, &inc);
            for (int j = 0; j < g.Length; j++)
                cgtol += g[j] * g[j];
            cgtol = 0.1 * Math.Sqrt(cgtol);

            int cg_iter = 0;

            double rTr = 0; // rTr = ddot_(&n, r, &inc, r, &inc);
            for (int j = 0; j < r.Length; j++)
                rTr += r[j] * r[j];

            while (true)
            {
                // rn = dnrm2_(&n, r, &inc)
                double rn = 0;
                for (int j = 0; j < r.Length; j++)
                    rn += r[j] * r[j];
                rn = Math.Sqrt(rn);

                if (rn <= cgtol)
                    break;

                cg_iter++;

                double[] Hd = Hessian(d);

                double dHd = 0; // ddot_(&n, d, &inc, Hd, &inc)
                for (int j = 0; j < d.Length; j++)
                    dHd += d[j] * Hd[j];

                double alpha = rTr / dHd;

                // daxpy_(&n, &alpha, d, &inc, s, &inc);
                for (int j = 0; j < d.Length; j++)
                    s[j] += alpha * d[j];

                double sn = 0; // dnrm2_(&n, s, &inc)
                for (int j = 0; j < s.Length; j++)
                    sn += s[j] * s[j];
                sn = Math.Sqrt(sn);

                if (sn > delta)
                {
                    Trace.WriteLine("cg reaches trust region boundary");
                    alpha = -alpha;

                    // daxpy_(&n, &alpha, d, &inc, s, &inc);
                    for (int j = 0; j < d.Length; j++)
                        s[j] += alpha * d[j];

                    double std = 0; // ddot_(&n, s, &inc, d, &inc);
                    for (int j = 0; j < s.Length; j++)
                        std += s[j] * d[j];

                    double sts = 0; // ddot_(&n, s, &inc, s, &inc);
                    for (int j = 0; j < s.Length; j++)
                        sts += s[j] * s[j];

                    double dtd = 0;// ddot_(&n, d, &inc, d, &inc);
                    for (int j = 0; j < d.Length; j++)
                        dtd += d[j] * d[j];

                    double dsq = delta * delta;
                    double rad = Math.Sqrt(std * std + dtd * (dsq - sts));


                    if (std >= 0)
                        alpha = (dsq - sts) / (std + rad);
                    else
                        alpha = (rad - std) / dtd;

                    // daxpy_(&n, &alpha, d, &inc, s, &inc);
                    for (int j = 0; j < d.Length; j++)
                        s[j] += alpha * d[j];

                    alpha = -alpha;

                    // daxpy_(&n, &alpha, Hd, &inc, r, &inc);
                    for (int j = 0; j < r.Length; j++)
                        r[j] += alpha * Hd[j];

                    break;
                }

                alpha = -alpha;

                // daxpy_(&n, &alpha, Hd, &inc, r, &inc);
                for (int j = 0; j < r.Length; j++)
                    r[j] += alpha * Hd[j];

                // ddot_(&n, r, &inc, r, &inc);
                double rnewTrnew = 0.0;
                for (int j = 0; j < r.Length; j++)
                    rnewTrnew += r[j] * r[j];

                double beta = rnewTrnew / rTr;

                // dscal_(&n, &beta, d, &inc);
                for (int j = 0; j < d.Length; j++)
                    d[j] *= beta;

                // daxpy_(&n, &one, r, &inc, d, &inc);
                for (int j = 0; j < d.Length; j++)
                    d[j] += r[j];

                rTr = rnewTrnew;
            }

            return cg_iter;
        }