예제 #1
0
        public virtual double[] Minimize(IDiffFunction dFunction, double functionTolerance, double[] initial, int maxIterations)
        {
            // check for derivatives
            int dimension = dFunction.DomainDimension();
            //lastXx = 1.0;
            // evaluate function
            double fp = dFunction.ValueAt(initial);

            double[] xi = CopyArray(dFunction.DerivativeAt(initial));
            // make some vectors
            double[] g = new double[dimension];
            double[] h = new double[dimension];
            double[] p = new double[dimension];
            for (int j = 0; j < dimension; j++)
            {
                g[j]  = -xi[j];
                xi[j] = g[j];
                h[j]  = g[j];
                p[j]  = initial[j];
            }
            // iterations
            bool simpleGDStep = false;

            for (int iterations = 1; iterations < maxIterations; iterations++)
            {
                if (!silent)
                {
                    log.Info("Iter " + iterations + ' ');
                }
                // do a line min along descent direction
                //log.info("Minimizing from ("+p[0]+","+p[1]+") along ("+xi[0]+","+xi[1]+")\n");
                //log.info("Current is "+fp);
                double[] p2  = LineMinimize(dFunction, p, xi);
                double   fp2 = dFunction.ValueAt(p2);
                //log.info("Result is "+fp2+" (from "+fp+") at ("+p2[0]+","+p2[1]+")\n");
                //log.info(fp2+"|"+(int)(Math.log((fabs(fp2-fp)+1e-100)/(fabs(fp)+fabs(fp2)+1e-100))/Math.log(10)));
                if (!silent)
                {
                    System.Console.Error.Printf(" %s (delta: %s)\n", nf.Format(fp2), nf.Format(fp - fp2));
                }
                if (monitor != null)
                {
                    double monitorReturn = monitor.ValueAt(p2);
                    if (monitorReturn < functionTolerance)
                    {
                        return(p2);
                    }
                }
                // check convergence
                if (2.0 * Fabs(fp2 - fp) <= functionTolerance * (Fabs(fp2) + Fabs(fp) + Eps))
                {
                    // convergence
                    if (!checkSimpleGDConvergence || simpleGDStep || simpleGD)
                    {
                        return(p2);
                    }
                    simpleGDStep = true;
                }
                else
                {
                    //log.info("Switched to GD for a step.");
                    //if (!simpleGD)
                    //log.info("Switching to CGD.");
                    simpleGDStep = false;
                }
                // shift variables
                for (int j_1 = 0; j_1 < dimension; j_1++)
                {
                    xi[j_1] = p2[j_1] - p[j_1];
                    p[j_1]  = p2[j_1];
                }
                fp = fp2;
                // find the new gradient
                xi = CopyArray(dFunction.DerivativeAt(p));
                if (iterationCallbackFunction != null)
                {
                    iterationCallbackFunction.Callback(p2, iterations, fp2, xi);
                }
                //log.info("mx "+arrayMax(xi)+" mn "+arrayMin(xi));
                if (!simpleGDStep && !simpleGD && (iterations % resetFrequency != 0))
                {
                    // do the magic -- part i
                    // (calculate some dot products we'll need)
                    double dgg = 0.0;
                    double gg  = 0.0;
                    for (int j_2 = 0; j_2 < dimension; j_2++)
                    {
                        // g dot g
                        gg += g[j_2] * g[j_2];
                        // grad dot grad
                        // FR method is:
                        // dgg += x[j]*x[j];
                        // PR method is:
                        dgg += (xi[j_2] + g[j_2]) * xi[j_2];
                    }
                    // check for miraculous convergence
                    if (gg == 0.0)
                    {
                        return(p);
                    }
                    // magic part ii
                    // (update the sequence in a way that tries to preserve conjugacy)
                    double gam = dgg / gg;
                    for (int j_3 = 0; j_3 < dimension; j_3++)
                    {
                        g[j_3]  = -xi[j_3];
                        h[j_3]  = g[j_3] + gam * h[j_3];
                        xi[j_3] = h[j_3];
                    }
                }
                else
                {
                    // miraculous simpleGD convergence
                    double xixi = 0.0;
                    for (int j_2 = 0; j_2 < dimension; j_2++)
                    {
                        xixi += xi[j_2] * xi[j_2];
                    }
                    // reset cgd
                    for (int j_3 = 0; j_3 < dimension; j_3++)
                    {
                        g[j_3]  = -xi[j_3];
                        xi[j_3] = g[j_3];
                        h[j_3]  = g[j_3];
                    }
                    if (xixi == 0.0)
                    {
                        return(p);
                    }
                }
            }
            // too many iterations
            log.Info("Warning: exiting minimize because ITER exceeded!");
            return(p);
        }