Exemplo n.º 1
0
        /// <summary>
        /// Find the best common gamma. Use the same gamma for all kernels. This is a
        /// crude brute-force search. The range found should be refined using the
        /// "Brent Method", also provided in this class.
        /// </summary>
        ///
        /// <param name="low">The low gamma to begin the search with.</param>
        /// <param name="high">The high gamma to end the search with.</param>
        /// <param name="numberOfPoints">If you do set this to negative, set x2 and y2 to the correct values.</param>
        /// <param name="useLog">Should we progress "logarithmically" from low to high.</param>
        /// <param name="minError">We are done if the error is below this.</param>
        /// <param name="network">The network to evaluate.</param>
        public void FindBestRange(double low, double high,
                                  int numberOfPoints, bool useLog, double minError,
                                  ICalculationCriteria network)
        {
            int i, ibest;
            double x, y, rate, previous;
            bool firstPointKnown;

            // if the number of points is negative, then
            // we already know the first point. Don't recalculate it.
            if (numberOfPoints < 0)
            {
                numberOfPoints = -numberOfPoints;
                firstPointKnown = true;
            }
            else
            {
                firstPointKnown = false;
            }

            // Set the rate to go from high to low. We are either advancing
            // logarithmically, or linear.
            if (useLog)
            {
                rate = Math.Exp(Math.Log(high/low)/(numberOfPoints - 1));
            }
            else
            {
                rate = (high - low)/(numberOfPoints - 1);
            }

            // Start the search at the low.
            x = low;
            previous = 0.0d;
            ibest = -1;

            // keep track of if the error is getting worse.
            bool gettingWorse = false;

            // Try the specified number of points, between high and low.
            for (i = 0; i < numberOfPoints; i++)
            {
                // Determine the error. If the first point is known, then us y2 as
                // the error.
                if ((i > 0) || !firstPointKnown)
                {
                    y = network.CalcErrorWithSingleSigma(x);
                }
                else
                {
                    y = _y2;
                }

                // Have we found a new best candidate point?
                if ((i == 0) || (y < _y2))
                {
                    // yes, we found a new candidate point!
                    ibest = i;
                    _x2 = x;
                    _y2 = y;
                    _y1 = previous; // Function value to its left
                    gettingWorse = false; // Flag that min is not yet bounded
                }
                else if (i == (ibest + 1))
                {
                    // Things are getting worse!
                    // Might be the right neighbor of the best found.
                    _y3 = y;
                    gettingWorse = true;
                }

                // Track the left neighbour of the best.
                previous = y;

                // Is this good enough? Might be able to stop early
                if ((_y2 <= minError) && (ibest > 0) && gettingWorse)
                {
                    break;
                }

                // Decrease the rate either linearly or
                if (useLog)
                {
                    x *= rate;
                }
                else
                {
                    x += rate;
                }
            }

            /*
			 * At this point we have a minimum (within low,high) at (x2,y2). Compute
			 * x1 and x3, its neighbors. We already know y1 and y3 (unless the
			 * minimum is at an endpoint!).
			 */

            // We have now located a minimum! Yeah!!
            // Lets calculate the neighbors. x1 and x3, which are the sigmas.
            // We should already have y1 and y3 calculated, these are the errors,
            // and are expensive to recalculate.
            if (useLog)
            {
                _x1 = _x2/rate;
                _x3 = _x2*rate;
            }
            else
            {
                _x1 = _x2 - rate;
                _x3 = _x2 + rate;
            }

            // We are really done at this point. But for "extra credit", we check to
            // see if things were "getting worse".
            //
            // If NOT, and things were getting better, the user probably cropped the
            // gamma range a bit short. After all, it is hard to guess at a good
            // gamma range.
            //
            // To try and get the best common gamma that we can, we will actually
            // slip off the right-hand high-range and search for an even better
            // gamma.

            if (!gettingWorse)
            {
                // Search as far as needed! (endless loop)
                for (;;)
                {
                    // calculate at y3(the end point)
                    _y3 = network.CalcErrorWithSingleSigma(_x3);

                    // If we are not finding anything better, then stop!
                    // We are already outside the specified search range.
                    if (_y3 > _y2)
                    {
                        break;
                    }
                    if ((_y1 == _y2) && (_y2 == _y3))
                    {
                        break;
                    }

                    // Shift the points for the new range, as we have
                    // extended to the right.
                    _x1 = _x2;
                    _y1 = _y2;
                    _x2 = _x3;
                    _y2 = _y3;

                    // We want to step further each time. We can't search forever,
                    // and we are already outside of the area we were supposed to
                    // scan.
                    rate *= 3.0d;
                    if (useLog)
                    {
                        _x3 *= rate;
                    }
                    else
                    {
                        _x3 += rate;
                    }
                }
            }
                // We will also handle one more "bad situation", which results from a
                // bad gamma search range.
                //
                // What if the first gamma was tried, and that was the best it ever got?
                //
                // If this is the case, there MIGHT be better gammas to the left of the
                // search space. Lets try those.
            else if (ibest == 0)
            {
                // Search as far as needed! (endless loop)
                for (;;)
                {
                    // Calculate at y3(the begin point)
                    _y1 = network.CalcErrorWithSingleSigma(_x1);

                    if (_y1 < 0.0d)
                    {
                        return;
                    }

                    // If we are not finding anything better, then stop!
                    // We are already outside the specified search range.
                    if (_y1 > _y2)
                    {
                        break;
                    }
                    if ((_y1 == _y2) && (_y2 == _y3))
                    {
                        break;
                    }

                    // Shift the points for the new range, as we have
                    // extended to the left.
                    _x3 = _x2;
                    _y3 = _y2;
                    _x2 = _x1;
                    _y2 = _y1;

                    // We want to step further each time. We can't search forever,
                    // and we are already outside of the area we were supposed to
                    // scan.
                    rate *= 3.0d;
                    if (useLog)
                    {
                        _x1 /= rate;
                    }
                    else
                    {
                        _x1 -= rate;
                    }
                }
            }
            return;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Derive the minimum, using a conjugate gradient method.
        /// </summary>
        ///
        /// <param name="maxIterations">The max iterations.</param>
        /// <param name="maxError">Stop at this error rate.</param>
        /// <param name="eps">The machine's precision.</param>
        /// <param name="tol">The convergence tolerance.</param>
        /// <param name="network">The network to get the error from.</param>
        /// <param name="n">The number of variables.</param>
        /// <param name="x">The independent variable.</param>
        /// <param name="ystart">The start for y.</param>
        /// <param name="bs">Work vector, must have n elements.</param>
        /// <param name="direc">Work vector, must have n elements.</param>
        /// <param name="g">Work vector, must have n elements.</param>
        /// <param name="h">Work vector, must have n elements.</param>
        /// <param name="deriv2">Work vector, must have n elements.</param>
        /// <returns>The best error.</returns>
        public double Calculate(int maxIterations, double maxError,
                                double eps, double tol,
                                ICalculationCriteria network, int n, double[] x,
                                double ystart, double[] bs, double[] direc,
                                double[] g, double[] h, double[] deriv2)
        {
            var globalMinimum = new GlobalMinimumSearch();

            double fbest = network.CalcErrorWithMultipleSigma(x, direc, deriv2,
                                                              true);
            double prevBest = 1.0e30d;

            for (int i = 0; i < n; i++)
            {
                direc[i] = -direc[i];
            }

            EngineArray.ArrayCopy(direc, g);
            EngineArray.ArrayCopy(direc, h);

            int convergenceCounter = 0;
            int poorCj             = 0;

            // Main loop
            for (int iteration = 0; iteration < maxIterations; iteration++)
            {
                if (fbest < maxError)
                {
                    break;
                }

                EncogLogging.Log(EncogLogging.LevelInfo,
                                 "Beginning internal Iteration #" + iteration + ", currentError=" + fbest + ",target=" + maxError);

                // Check for convergence
                double toler;
                if (prevBest <= 1.0d)
                {
                    toler = tol;
                }
                else
                {
                    toler = tol * prevBest;
                }

                // Stop if there is little improvement
                if ((prevBest - fbest) <= toler)
                {
                    if (++convergenceCounter >= 3)
                    {
                        break;
                    }
                }
                else
                {
                    convergenceCounter = 0;
                }

                double dot2 = 0;
                double dlen = 0;
                double dot1 = dot2 = dlen = 0.0d;
                double high = 1.0e-4d;
                for (int i = 0; i < n; i++)
                {
                    bs[i] = x[i];
                    if (deriv2[i] > high)
                    {
                        high = deriv2[i];
                    }
                    dot1 += direc[i] * g[i];                 // Directional first derivative
                    dot2 += direc[i] * direc[i] * deriv2[i]; // and second
                    dlen += direc[i] * direc[i];             // Length of search vector
                }

                double scale;

                if (Math.Abs(dot2) < EncogFramework.DefaultDoubleEqual)
                {
                    scale = 0;
                }
                else
                {
                    scale = dot1 / dot2;
                }
                high = 1.5d / high;
                if (high < 1.0e-4d)
                {
                    high = 1.0e-4d;
                }

                if (scale < 0.0d)
                {
                    scale = high;
                }
                else if (scale < 0.1d * high)
                {
                    scale = 0.1d * high;
                }
                else if (scale > 10.0d * high)
                {
                    scale = 10.0d * high;
                }

                prevBest         = fbest;
                globalMinimum.Y2 = fbest;

                globalMinimum.FindBestRange(0.0d, 2.0d * scale, -3, false, maxError,
                                            network);

                if (globalMinimum.Y2 < maxError)
                {
                    if (globalMinimum.Y2 < fbest)
                    {
                        for (int i = 0; i < n; i++)
                        {
                            x[i] = bs[i] + globalMinimum.Y2 * direc[i];
                            if (x[i] < 1.0e-10d)
                            {
                                x[i] = 1.0e-10d;
                            }
                        }
                        fbest = globalMinimum.Y2;
                    }
                    else
                    {
                        for (int i = 0; i < n; i++)
                        {
                            x[i] = bs[i];
                        }
                    }
                    break;
                }

                if (convergenceCounter > 0)
                {
                    fbest = globalMinimum.Brentmin(20, maxError, eps, 1.0e-7d,
                                                   network, globalMinimum.Y2);
                }
                else
                {
                    fbest = globalMinimum.Brentmin(10, maxError, 1.0e-6d, 1.0e-5d,
                                                   network, globalMinimum.Y2);
                }

                for (int i = 0; i < n; i++)
                {
                    x[i] = bs[i] + globalMinimum.X2 * direc[i];
                    if (x[i] < 1.0e-10d)
                    {
                        x[i] = 1.0e-10d;
                    }
                }

                double improvement = (prevBest - fbest) / prevBest;

                if (fbest < maxError)
                {
                    break;
                }

                for (int i = 0; i < n; i++)
                {
                    direc[i] = -direc[i]; // negative gradient
                }

                double gam = Gamma(n, g, direc);

                if (gam < 0.0d)
                {
                    gam = 0.0d;
                }

                if (gam > 10.0d)
                {
                    gam = 10.0d;
                }

                if (improvement < 0.001d)
                {
                    ++poorCj;
                }
                else
                {
                    poorCj = 0;
                }

                if (poorCj >= 2)
                {
                    if (gam > 1.0d)
                    {
                        gam = 1.0d;
                    }
                }

                if (poorCj >= 6)
                {
                    poorCj = 0;
                    gam    = 0.0d;
                }

                FindNewDir(n, gam, g, h, direc);
            }

            return(fbest);
        }
        /// <summary>
        /// Find the best common gamma. Use the same gamma for all kernels. This is a
        /// crude brute-force search. The range found should be refined using the
        /// "Brent Method", also provided in this class.
        /// </summary>
        ///
        /// <param name="low">The low gamma to begin the search with.</param>
        /// <param name="high">The high gamma to end the search with.</param>
        /// <param name="numberOfPoints">If you do set this to negative, set x2 and y2 to the correct values.</param>
        /// <param name="useLog">Should we progress "logarithmically" from low to high.</param>
        /// <param name="minError">We are done if the error is below this.</param>
        /// <param name="network">The network to evaluate.</param>
        public void FindBestRange(double low, double high,
                                  int numberOfPoints, bool useLog, double minError,
                                  ICalculationCriteria network)
        {
            int    i, ibest;
            double x, y, rate, previous;
            bool   firstPointKnown;

            // if the number of points is negative, then
            // we already know the first point. Don't recalculate it.
            if (numberOfPoints < 0)
            {
                numberOfPoints  = -numberOfPoints;
                firstPointKnown = true;
            }
            else
            {
                firstPointKnown = false;
            }

            // Set the rate to go from high to low. We are either advancing
            // logarithmically, or linear.
            if (useLog)
            {
                rate = Math.Exp(Math.Log(high / low) / (numberOfPoints - 1));
            }
            else
            {
                rate = (high - low) / (numberOfPoints - 1);
            }

            // Start the search at the low.
            x        = low;
            previous = 0.0d;
            ibest    = -1;

            // keep track of if the error is getting worse.
            bool gettingWorse = false;

            // Try the specified number of points, between high and low.
            for (i = 0; i < numberOfPoints; i++)
            {
                // Determine the error. If the first point is known, then us y2 as
                // the error.
                if ((i > 0) || !firstPointKnown)
                {
                    y = network.CalcErrorWithSingleSigma(x);
                }
                else
                {
                    y = _y2;
                }

                // Have we found a new best candidate point?
                if ((i == 0) || (y < _y2))
                {
                    // yes, we found a new candidate point!
                    ibest        = i;
                    _x2          = x;
                    _y2          = y;
                    _y1          = previous; // Function value to its left
                    gettingWorse = false;    // Flag that min is not yet bounded
                }
                else if (i == (ibest + 1))
                {
                    // Things are getting worse!
                    // Might be the right neighbor of the best found.
                    _y3          = y;
                    gettingWorse = true;
                }

                // Track the left neighbour of the best.
                previous = y;

                // Is this good enough? Might be able to stop early
                if ((_y2 <= minError) && (ibest > 0) && gettingWorse)
                {
                    break;
                }

                // Decrease the rate either linearly or
                if (useLog)
                {
                    x *= rate;
                }
                else
                {
                    x += rate;
                }
            }

            /*
             * At this point we have a minimum (within low,high) at (x2,y2). Compute
             * x1 and x3, its neighbors. We already know y1 and y3 (unless the
             * minimum is at an endpoint!).
             */

            // We have now located a minimum! Yeah!!
            // Lets calculate the neighbors. x1 and x3, which are the sigmas.
            // We should already have y1 and y3 calculated, these are the errors,
            // and are expensive to recalculate.
            if (useLog)
            {
                _x1 = _x2 / rate;
                _x3 = _x2 * rate;
            }
            else
            {
                _x1 = _x2 - rate;
                _x3 = _x2 + rate;
            }

            // We are really done at this point. But for "extra credit", we check to
            // see if things were "getting worse".
            //
            // If NOT, and things were getting better, the user probably cropped the
            // gamma range a bit short. After all, it is hard to guess at a good
            // gamma range.
            //
            // To try and get the best common gamma that we can, we will actually
            // slip off the right-hand high-range and search for an even better
            // gamma.

            if (!gettingWorse)
            {
                // Search as far as needed! (endless loop)
                for (;;)
                {
                    // calculate at y3(the end point)
                    _y3 = network.CalcErrorWithSingleSigma(_x3);

                    // If we are not finding anything better, then stop!
                    // We are already outside the specified search range.
                    if (_y3 > _y2)
                    {
                        break;
                    }
                    if ((_y1 == _y2) && (_y2 == _y3))
                    {
                        break;
                    }

                    // Shift the points for the new range, as we have
                    // extended to the right.
                    _x1 = _x2;
                    _y1 = _y2;
                    _x2 = _x3;
                    _y2 = _y3;

                    // We want to step further each time. We can't search forever,
                    // and we are already outside of the area we were supposed to
                    // scan.
                    rate *= 3.0d;
                    if (useLog)
                    {
                        _x3 *= rate;
                    }
                    else
                    {
                        _x3 += rate;
                    }
                }
            }
            // We will also handle one more "bad situation", which results from a
            // bad gamma search range.
            //
            // What if the first gamma was tried, and that was the best it ever got?
            //
            // If this is the case, there MIGHT be better gammas to the left of the
            // search space. Lets try those.
            else if (ibest == 0)
            {
                // Search as far as needed! (endless loop)
                for (;;)
                {
                    // Calculate at y3(the begin point)
                    _y1 = network.CalcErrorWithSingleSigma(_x1);

                    if (_y1 < 0.0d)
                    {
                        return;
                    }

                    // If we are not finding anything better, then stop!
                    // We are already outside the specified search range.
                    if (_y1 > _y2)
                    {
                        break;
                    }
                    if ((_y1 == _y2) && (_y2 == _y3))
                    {
                        break;
                    }

                    // Shift the points for the new range, as we have
                    // extended to the left.
                    _x3 = _x2;
                    _y3 = _y2;
                    _x2 = _x1;
                    _y2 = _y1;

                    // We want to step further each time. We can't search forever,
                    // and we are already outside of the area we were supposed to
                    // scan.
                    rate *= 3.0d;
                    if (useLog)
                    {
                        _x1 /= rate;
                    }
                    else
                    {
                        _x1 -= rate;
                    }
                }
            }
            return;
        }
Exemplo n.º 4
0
        /// <summary>
        /// Use the "Brent Method" to find a better minimum.
        /// </summary>
        ///
        /// <param name="maxIterations">THe maximum number of iterations.</param>
        /// <param name="maxError">We can stop if we reach this error.</param>
        /// <param name="eps">The approximate machine precision.</param>
        /// <param name="tol">Brent's tolerance, must be >= sqrt( eps )</param>
        /// <param name="network">The network to obtain the error from.</param>
        /// <param name="y">The error at x2.</param>
        /// <returns>The best error.</returns>
        public double Brentmin(int maxIterations,
                               double maxError, double eps, double tol,
                               ICalculationCriteria network, double y)
        {
            double prevdist = 0.0d;
            double step = 0.0d;

            // xBest is the minimum function ordinate thus far.
            // also keep 2nd and 3rd
            double xbest = _x2;
            double x2ndBest = _x2;
            double x3rdBest = _x2;
            // Keep the minimum bracketed between xlow and xhigh.

            // Get the low and high from our previous "crude" search.
            double xlow = _x1;
            double xhigh = _x3;

            double fbest = y;
            double fsecbest = y;
            double fthirdbest = y;

            // Main loop.
            // We will go up to the specified number of iterations.
            // Hopefully we will "break out" long before that happens!
            for (int iter = 0; iter < maxIterations; iter++)
            {
                // Have we reached an acceptable error?
                if (fbest < maxError)
                {
                    break;
                }

                double xmid = 0.5d*(xlow + xhigh);
                double tol1 = tol*(Math.Abs(xbest) + eps);
                double tol2 = 2.0*tol1;

                // See if xlow is close relative to tol2,
                // Also, that that xbest is near the midpoint.
                if (Math.Abs(xbest - xmid) <= (tol2 - 0.5d*(xhigh - xlow)))
                {
                    break;
                }

                // Don't go to close to eps, the machine precision.
                if ((iter >= 2) && ((fthirdbest - fbest) < eps))
                {
                    break;
                }

                double xrecent = 0;

                // Try parabolic fit, if we moved far enough.
                if (Math.Abs(prevdist) > tol1)
                {
                    // Temps holders for the parabolic estimate
                    double t1 = (xbest - x2ndBest)*(fbest - fthirdbest);
                    double t2 = (xbest - x3rdBest)*(fbest - fsecbest);
                    double numer = (xbest - x3rdBest)*t2
                                   - (xbest - x2ndBest)*t1;
                    double denom = 2.0*(t1 - t2);
                    double testdist = prevdist;
                    prevdist = step;
                    // This is the parabolic estimate to min.
                    if (denom != 0.0d)
                    {
                        step = numer/denom;
                    }
                    else
                    {
                        // test failed.
                        step = 1.0e30d;
                    }

                    // If shrinking, and within bounds, then use the parabolic
                    // estimate.
                    if ((Math.Abs(step) < Math.Abs(0.5d*testdist))
                        && (step + xbest > xlow) && (step + xbest < xhigh))
                    {
                        xrecent = xbest + step;
                        // If very close to known bounds.
                        if ((xrecent - xlow < tol2) || (xhigh - xrecent < tol2))
                        {
                            if (xbest < xmid)
                            {
                                step = tol1;
                            }
                            else
                            {
                                step = -tol1;
                            }
                        }
                    }
                    else
                    {
                        // Parabolic estimate poor, so use golden section
                        prevdist = (xbest >= xmid) ? xlow - xbest : xhigh - xbest;
                        step = Cgold*prevdist;
                    }
                }
                else
                {
                    // prevdist did not exceed tol1: we did not move far
                    // enough
                    // to justify a parabolic fit. Use golden section.
                    prevdist = (xbest >= xmid) ? xlow - xbest : xhigh - xbest;
                    step = .3819660d*prevdist;
                }

                if (Math.Abs(step) >= tol1)
                {
                    xrecent = xbest + step; // another trial we must move a
                }
                else
                {
                    // decent distance.
                    if (step > 0.0)
                    {
                        xrecent = xbest + tol1;
                    }
                    else
                    {
                        xrecent = xbest - tol1;
                    }
                }

                /*
				 * At long last we have a trial point 'xrecent'. Evaluate the
				 * function.
				 */

                double frecent = network.CalcErrorWithSingleSigma(xrecent);

                if (frecent < 0.0d)
                {
                    break;
                }

                if (frecent <= fbest)
                {
                    // If we improved...
                    if (xrecent >= xbest)
                    {
                        xlow = xbest; // replacing the appropriate endpoint
                    }
                    else
                    {
                        xhigh = xbest;
                    }
                    x3rdBest = x2ndBest; // Update x and f values for best,
                    x2ndBest = xbest; // second and third best
                    xbest = xrecent;
                    fthirdbest = fsecbest;
                    fsecbest = fbest;
                    fbest = frecent;
                }
                else
                {
                    // We did not improve
                    if (xrecent < xbest)
                    {
                        xlow = xrecent; // replacing the appropriate endpoint
                    }
                    else
                    {
                        xhigh = xrecent;
                    }

                    if ((frecent <= fsecbest) || (x2ndBest == xbest))
                    {
                        x3rdBest = x2ndBest;

                        x2ndBest = xrecent;
                        fthirdbest = fsecbest;
                        fsecbest = frecent;
                    }
                    else if ((frecent <= fthirdbest) || (x3rdBest == xbest)
                             || (x3rdBest == x2ndBest))
                    {
                        x3rdBest = xrecent;
                        fthirdbest = frecent;
                    }
                }
            }

            // update the three sigmas.

            _x1 = xlow;
            _x2 = xbest;
            _x3 = xhigh;

            // return the best.
            return fbest;
        }
        /// <summary>
        /// Use the "Brent Method" to find a better minimum.
        /// </summary>
        ///
        /// <param name="maxIterations">THe maximum number of iterations.</param>
        /// <param name="maxError">We can stop if we reach this error.</param>
        /// <param name="eps">The approximate machine precision.</param>
        /// <param name="tol">Brent's tolerance, must be >= sqrt( eps )</param>
        /// <param name="network">The network to obtain the error from.</param>
        /// <param name="y">The error at x2.</param>
        /// <returns>The best error.</returns>
        public double Brentmin(int maxIterations,
                               double maxError, double eps, double tol,
                               ICalculationCriteria network, double y)
        {
            double prevdist = 0.0d;
            double step     = 0.0d;

            // xBest is the minimum function ordinate thus far.
            // also keep 2nd and 3rd
            double xbest    = _x2;
            double x2ndBest = _x2;
            double x3rdBest = _x2;
            // Keep the minimum bracketed between xlow and xhigh.

            // Get the low and high from our previous "crude" search.
            double xlow  = _x1;
            double xhigh = _x3;

            double fbest      = y;
            double fsecbest   = y;
            double fthirdbest = y;

            // Main loop.
            // We will go up to the specified number of iterations.
            // Hopefully we will "break out" long before that happens!
            for (int iter = 0; iter < maxIterations; iter++)
            {
                // Have we reached an acceptable error?
                if (fbest < maxError)
                {
                    break;
                }

                double xmid = 0.5d * (xlow + xhigh);
                double tol1 = tol * (Math.Abs(xbest) + eps);
                double tol2 = 2.0 * tol1;

                // See if xlow is close relative to tol2,
                // Also, that that xbest is near the midpoint.
                if (Math.Abs(xbest - xmid) <= (tol2 - 0.5d * (xhigh - xlow)))
                {
                    break;
                }

                // Don't go to close to eps, the machine precision.
                if ((iter >= 2) && ((fthirdbest - fbest) < eps))
                {
                    break;
                }

                double xrecent = 0;

                // Try parabolic fit, if we moved far enough.
                if (Math.Abs(prevdist) > tol1)
                {
                    // Temps holders for the parabolic estimate
                    double t1    = (xbest - x2ndBest) * (fbest - fthirdbest);
                    double t2    = (xbest - x3rdBest) * (fbest - fsecbest);
                    double numer = (xbest - x3rdBest) * t2
                                   - (xbest - x2ndBest) * t1;
                    double denom    = 2.0 * (t1 - t2);
                    double testdist = prevdist;
                    prevdist = step;
                    // This is the parabolic estimate to min.
                    if (denom != 0.0d)
                    {
                        step = numer / denom;
                    }
                    else
                    {
                        // test failed.
                        step = 1.0e30d;
                    }

                    // If shrinking, and within bounds, then use the parabolic
                    // estimate.
                    if ((Math.Abs(step) < Math.Abs(0.5d * testdist)) &&
                        (step + xbest > xlow) && (step + xbest < xhigh))
                    {
                        xrecent = xbest + step;
                        // If very close to known bounds.
                        if ((xrecent - xlow < tol2) || (xhigh - xrecent < tol2))
                        {
                            if (xbest < xmid)
                            {
                                step = tol1;
                            }
                            else
                            {
                                step = -tol1;
                            }
                        }
                    }
                    else
                    {
                        // Parabolic estimate poor, so use golden section
                        prevdist = (xbest >= xmid) ? xlow - xbest : xhigh - xbest;
                        step     = Cgold * prevdist;
                    }
                }
                else
                {
                    // prevdist did not exceed tol1: we did not move far
                    // enough
                    // to justify a parabolic fit. Use golden section.
                    prevdist = (xbest >= xmid) ? xlow - xbest : xhigh - xbest;
                    step     = .3819660d * prevdist;
                }

                if (Math.Abs(step) >= tol1)
                {
                    xrecent = xbest + step; // another trial we must move a
                }
                else
                {
                    // decent distance.
                    if (step > 0.0)
                    {
                        xrecent = xbest + tol1;
                    }
                    else
                    {
                        xrecent = xbest - tol1;
                    }
                }

                /*
                 * At long last we have a trial point 'xrecent'. Evaluate the
                 * function.
                 */

                double frecent = network.CalcErrorWithSingleSigma(xrecent);

                if (frecent < 0.0d)
                {
                    break;
                }

                if (frecent <= fbest)
                {
                    // If we improved...
                    if (xrecent >= xbest)
                    {
                        xlow = xbest; // replacing the appropriate endpoint
                    }
                    else
                    {
                        xhigh = xbest;
                    }
                    x3rdBest   = x2ndBest; // Update x and f values for best,
                    x2ndBest   = xbest;    // second and third best
                    xbest      = xrecent;
                    fthirdbest = fsecbest;
                    fsecbest   = fbest;
                    fbest      = frecent;
                }
                else
                {
                    // We did not improve
                    if (xrecent < xbest)
                    {
                        xlow = xrecent; // replacing the appropriate endpoint
                    }
                    else
                    {
                        xhigh = xrecent;
                    }

                    if ((frecent <= fsecbest) || (x2ndBest == xbest))
                    {
                        x3rdBest = x2ndBest;

                        x2ndBest   = xrecent;
                        fthirdbest = fsecbest;
                        fsecbest   = frecent;
                    }
                    else if ((frecent <= fthirdbest) || (x3rdBest == xbest) ||
                             (x3rdBest == x2ndBest))
                    {
                        x3rdBest   = xrecent;
                        fthirdbest = frecent;
                    }
                }
            }

            // update the three sigmas.

            _x1 = xlow;
            _x2 = xbest;
            _x3 = xhigh;

            // return the best.
            return(fbest);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Derive the minimum, using a conjugate gradient method.
        /// </summary>
        ///
        /// <param name="maxIterations">The max iterations.</param>
        /// <param name="maxError">Stop at this error rate.</param>
        /// <param name="eps">The machine's precision.</param>
        /// <param name="tol">The convergence tolerance.</param>
        /// <param name="network">The network to get the error from.</param>
        /// <param name="n">The number of variables.</param>
        /// <param name="x">The independent variable.</param>
        /// <param name="ystart">The start for y.</param>
        /// <param name="bs">Work vector, must have n elements.</param>
        /// <param name="direc">Work vector, must have n elements.</param>
        /// <param name="g">Work vector, must have n elements.</param>
        /// <param name="h">Work vector, must have n elements.</param>
        /// <param name="deriv2">Work vector, must have n elements.</param>
        /// <returns>The best error.</returns>
        public double Calculate(int maxIterations, double maxError,
            double eps, double tol,
            ICalculationCriteria network, int n, double[] x,
            double ystart, double[] bs, double[] direc,
            double[] g, double[] h, double[] deriv2)
        {
            var globalMinimum = new GlobalMinimumSearch();

            double fbest = network.CalcErrorWithMultipleSigma(x, direc, deriv2,
                                                              true);
            double prevBest = 1.0e30d;
            for (int i = 0; i < n; i++)
            {
                direc[i] = -direc[i];
            }

            EngineArray.ArrayCopy(direc, g);
            EngineArray.ArrayCopy(direc, h);

            int convergenceCounter = 0;
            int poorCj = 0;

            // Main loop
            for (int iteration = 0; iteration < maxIterations; iteration++)
            {
                if (fbest < maxError)
                {
                    break;
                }

                EncogLogging.Log(EncogLogging.LevelInfo,
                    "Beginning internal Iteration #" + iteration + ", currentError=" + fbest + ",target=" + maxError);

                // Check for convergence
                double toler;
                if (prevBest <= 1.0d)
                {
                    toler = tol;
                }
                else
                {
                    toler = tol*prevBest;
                }

                // Stop if there is little improvement
                if ((prevBest - fbest) <= toler)
                {
                    if (++convergenceCounter >= 3)
                    {
                        break;
                    }
                }
                else
                {
                    convergenceCounter = 0;
                }

                double dot2 = 0;
                double dlen = 0;
                double dot1 = dot2 = dlen = 0.0d;
                double high = 1.0e-4d;
                for (int i= 0; i < n; i++)
                {
                    bs[i] = x[i];
                    if (deriv2[i] > high)
                    {
                        high = deriv2[i];
                    }
                    dot1 += direc[i]*g[i]; // Directional first derivative
                    dot2 += direc[i]*direc[i]*deriv2[i]; // and second
                    dlen += direc[i]*direc[i]; // Length of search vector
                }

                double scale;

                if (Math.Abs(dot2) < EncogFramework.DefaultDoubleEqual)
                {
                    scale = 0;
                }
                else
                {
                    scale = dot1/dot2;
                }
                high = 1.5d/high;
                if (high < 1.0e-4d)
                {
                    high = 1.0e-4d;
                }

                if (scale < 0.0d)
                {
                    scale = high;
                }
                else if (scale < 0.1d*high)
                {
                    scale = 0.1d*high;
                }
                else if (scale > 10.0d*high)
                {
                    scale = 10.0d*high;
                }

                prevBest = fbest;
                globalMinimum.Y2 = fbest;

                globalMinimum.FindBestRange(0.0d, 2.0d*scale, -3, false, maxError,
                                            network);

                if (globalMinimum.Y2 < maxError)
                {
                    if (globalMinimum.Y2 < fbest)
                    {
                        for (int i = 0; i < n; i++)
                        {
                            x[i] = bs[i] + globalMinimum.Y2*direc[i];
                            if (x[i] < 1.0e-10d)
                            {
                                x[i] = 1.0e-10d;
                            }
                        }
                        fbest = globalMinimum.Y2;
                    }
                    else
                    {
                        for (int i = 0; i < n; i++)
                        {
                            x[i] = bs[i];
                        }
                    }
                    break;
                }

                if (convergenceCounter > 0)
                {
                    fbest = globalMinimum.Brentmin(20, maxError, eps, 1.0e-7d,
                                                   network, globalMinimum.Y2);
                }
                else
                {
                    fbest = globalMinimum.Brentmin(10, maxError, 1.0e-6d, 1.0e-5d,
                                                   network, globalMinimum.Y2);
                }

                for (int i = 0; i < n; i++)
                {
                    x[i] = bs[i] + globalMinimum.X2*direc[i];
                    if (x[i] < 1.0e-10d)
                    {
                        x[i] = 1.0e-10d;
                    }
                }

                double improvement = (prevBest - fbest)/prevBest;

                if (fbest < maxError)
                {
                    break;
                }

                for (int i = 0; i < n; i++)
                {
                    direc[i] = -direc[i]; // negative gradient
                }

                double gam = Gamma(n, g, direc);

                if (gam < 0.0d)
                {
                    gam = 0.0d;
                }

                if (gam > 10.0d)
                {
                    gam = 10.0d;
                }

                if (improvement < 0.001d)
                {
                    ++poorCj;
                }
                else
                {
                    poorCj = 0;
                }

                if (poorCj >= 2)
                {
                    if (gam > 1.0d)
                    {
                        gam = 1.0d;
                    }
                }

                if (poorCj >= 6)
                {
                    poorCj = 0;
                    gam = 0.0d;
                }

                FindNewDir(n, gam, g, h, direc);
            }

            return fbest;
        }
Exemplo n.º 7
0
 public double Brentmin(int maxIterations, double maxError, double eps, double tol, ICalculationCriteria network, double y)
 {
     // This item is obfuscated and can not be translated.
 }
Exemplo n.º 8
0
 public void FindBestRange(double low, double high, int numberOfPoints, bool useLog, double minError, ICalculationCriteria network)
 {
     int num;
     int num2;
     double num3;
     double num4;
     double num5;
     double num6;
     bool flag;
     bool flag2;
     if (numberOfPoints >= 0)
     {
         flag = false;
         if (((uint) num5) < 0)
         {
             if ((((uint) high) - ((uint) num6)) < 0)
             {
                 goto Label_0642;
             }
             if ((((uint) minError) - ((uint) useLog)) >= 0)
             {
                 goto Label_054D;
             }
             goto Label_0574;
         }
         goto Label_0782;
     }
     if ((((uint) high) - ((uint) flag)) >= 0)
     {
         numberOfPoints = -numberOfPoints;
         flag = true;
         goto Label_0782;
     }
     if (((uint) useLog) >= 0)
     {
         goto Label_0639;
     }
     if ((((uint) flag2) & 0) == 0)
     {
         goto Label_0355;
     }
     goto Label_0094;
     Label_0064:
     if (num2 == 0)
     {
         goto Label_01F4;
     }
     if ((((uint) num3) | 0x7fffffff) == 0)
     {
         goto Label_033B;
     }
     if ((((uint) num2) - ((uint) num2)) >= 0)
     {
         if (((uint) useLog) <= uint.MaxValue)
         {
             return;
         }
         goto Label_0639;
     }
     if ((((uint) useLog) - ((uint) num6)) >= 0)
     {
         goto Label_0355;
     }
     if ((((uint) flag) - ((uint) numberOfPoints)) >= 0)
     {
         goto Label_0222;
     }
     goto Label_0191;
     Label_0094:
     num5 *= 3.0;
     if (useLog)
     {
         this._x6650a9a61c6142e3 /= num5;
     }
     else
     {
         this._x6650a9a61c6142e3 -= num5;
     }
     goto Label_01F4;
     Label_0191:
     if (this._xaa76c33ed453ba57 > this._x9b9be9a08b5115a8)
     {
         return;
     }
     if (((((uint) numberOfPoints) + ((uint) flag2)) <= uint.MaxValue) || (((uint) num4) <= uint.MaxValue))
     {
         if ((this._xaa76c33ed453ba57 == this._x9b9be9a08b5115a8) && (this._x9b9be9a08b5115a8 == this._xb3a0be2328bf1529))
         {
             return;
         }
         this._xb6acbfc039c06679 = this._xe75e43d266eef799;
         this._xb3a0be2328bf1529 = this._x9b9be9a08b5115a8;
         this._xe75e43d266eef799 = this._x6650a9a61c6142e3;
         this._x9b9be9a08b5115a8 = this._xaa76c33ed453ba57;
         if (((uint) flag) <= uint.MaxValue)
         {
             goto Label_0094;
         }
         if (((uint) high) >= 0)
         {
             goto Label_0222;
         }
         if (0x7fffffff != 0)
         {
             goto Label_02E5;
         }
         if (((uint) minError) >= 0)
         {
             goto Label_0064;
         }
     }
     else
     {
         goto Label_0191;
     }
     Label_01F4:
     this._xaa76c33ed453ba57 = network.CalcErrorWithSingleSigma(this._x6650a9a61c6142e3);
     if (this._xaa76c33ed453ba57 >= 0.0)
     {
         goto Label_0191;
     }
     return;
     Label_0222:
     if (!flag2)
     {
         goto Label_0305;
     }
     goto Label_0064;
     Label_028F:
     this._x6650a9a61c6142e3 = this._xe75e43d266eef799;
     this._xaa76c33ed453ba57 = this._x9b9be9a08b5115a8;
     this._xe75e43d266eef799 = this._xb6acbfc039c06679;
     this._x9b9be9a08b5115a8 = this._xb3a0be2328bf1529;
     num5 *= 3.0;
     if ((((uint) num6) - ((uint) low)) >= 0)
     {
         if (((uint) num3) < 0)
         {
             goto Label_047F;
         }
         if (!useLog)
         {
             this._xb6acbfc039c06679 += num5;
         }
         else
         {
             this._xb6acbfc039c06679 *= num5;
         }
         goto Label_0305;
     }
     Label_02E5:
     if (this._x9b9be9a08b5115a8 != this._xb3a0be2328bf1529)
     {
         if ((((uint) num6) - ((uint) num5)) > uint.MaxValue)
         {
             goto Label_0488;
         }
         goto Label_028F;
     }
     return;
     Label_0305:
     this._xb3a0be2328bf1529 = network.CalcErrorWithSingleSigma(this._xb6acbfc039c06679);
     if (((uint) num) >= 0)
     {
         if (this._xb3a0be2328bf1529 > this._x9b9be9a08b5115a8)
         {
             return;
         }
     }
     else
     {
         return;
     }
     Label_033B:
     if (this._xaa76c33ed453ba57 != this._x9b9be9a08b5115a8)
     {
         goto Label_028F;
     }
     goto Label_02E5;
     Label_0355:
     if (((uint) minError) > uint.MaxValue)
     {
         goto Label_054D;
     }
     Label_036A:
     if ((((uint) num4) + ((uint) minError)) > uint.MaxValue)
     {
         goto Label_0305;
     }
     if ((((uint) numberOfPoints) & 0) != 0)
     {
         goto Label_058C;
     }
     this._xb6acbfc039c06679 = this._xe75e43d266eef799 + num5;
     goto Label_0222;
     Label_03CC:
     if ((((uint) num5) & 0) != 0)
     {
         goto Label_042D;
     }
     if ((((uint) flag2) | 3) == 0)
     {
         return;
     }
     goto Label_0415;
     Label_03FD:
     if ((((uint) high) - ((uint) num5)) < 0)
     {
         goto Label_03CC;
     }
     Label_0415:
     this._x6650a9a61c6142e3 = this._xe75e43d266eef799 - num5;
     goto Label_0355;
     Label_042D:
     if (useLog)
     {
         goto Label_045F;
     }
     goto Label_03FD;
     Label_0440:
     if (num < numberOfPoints)
     {
         goto Label_06F6;
     }
     if ((((uint) num2) + ((uint) num5)) <= uint.MaxValue)
     {
         goto Label_042D;
     }
     Label_045F:
     this._x6650a9a61c6142e3 = this._xe75e43d266eef799 / num5;
     this._xb6acbfc039c06679 = this._xe75e43d266eef799 * num5;
     goto Label_0222;
     Label_047F:
     if (useLog)
     {
         num3 *= num5;
     }
     else
     {
         num3 += num5;
     }
     Label_0488:
     num++;
     if ((((uint) num6) | 1) == 0)
     {
         goto Label_01F4;
     }
     if ((((uint) high) & 0) == 0)
     {
         goto Label_0440;
     }
     goto Label_047F;
     Label_04D8:
     num6 = num4;
     if (((this._x9b9be9a08b5115a8 <= minError) && (num2 > 0)) && flag2)
     {
         goto Label_042D;
     }
     goto Label_047F;
     Label_054D:
     if (num == (num2 + 1))
     {
         this._xb3a0be2328bf1529 = num4;
         flag2 = true;
         goto Label_04D8;
     }
     if ((((uint) num2) - ((uint) num6)) > uint.MaxValue)
     {
         goto Label_0574;
     }
     if ((((uint) num5) & 0) != 0)
     {
         if (((uint) num6) < 0)
         {
             goto Label_03CC;
         }
         goto Label_0732;
     }
     if (((uint) useLog) >= 0)
     {
         if ((((uint) flag) + ((uint) numberOfPoints)) <= uint.MaxValue)
         {
             goto Label_0661;
         }
         if ((((uint) num6) - ((uint) high)) <= uint.MaxValue)
         {
             goto Label_062D;
         }
         goto Label_05D2;
     }
     if ((((uint) useLog) & 0) != 0)
     {
         goto Label_054D;
     }
     Label_056C:
     if (num == 0)
     {
         if ((((uint) num6) + ((uint) flag)) < 0)
         {
             goto Label_068B;
         }
         goto Label_0639;
     }
     goto Label_058C;
     Label_0574:
     if ((((uint) numberOfPoints) + ((uint) high)) > uint.MaxValue)
     {
         goto Label_056C;
     }
     Label_058C:
     if (num4 < this._x9b9be9a08b5115a8)
     {
         goto Label_068B;
     }
     if (0 != 0)
     {
         goto Label_06CA;
     }
     goto Label_054D;
     Label_05D2:
     flag2 = false;
     if ((((uint) num2) | 0xff) == 0)
     {
         goto Label_036A;
     }
     goto Label_04D8;
     Label_062D:
     this._xaa76c33ed453ba57 = num6;
     goto Label_05D2;
     Label_0639:
     num2 = num;
     this._xe75e43d266eef799 = num3;
     Label_0642:
     this._x9b9be9a08b5115a8 = num4;
     if ((((uint) minError) - ((uint) flag)) <= uint.MaxValue)
     {
         goto Label_062D;
     }
     Label_0661:
     if ((((uint) numberOfPoints) | 0x80000000) != 0)
     {
         goto Label_04D8;
     }
     goto Label_03FD;
     Label_068B:
     if ((((uint) useLog) | 0x80000000) == 0)
     {
         goto Label_056C;
     }
     goto Label_0639;
     Label_06CA:
     num4 = network.CalcErrorWithSingleSigma(num3);
     goto Label_056C;
     Label_06F6:
     if (num > 0)
     {
         if ((((uint) num3) - ((uint) numberOfPoints)) <= uint.MaxValue)
         {
             goto Label_06CA;
         }
         goto Label_058C;
     }
     Label_0732:
     if (flag)
     {
         num4 = this._x9b9be9a08b5115a8;
         goto Label_056C;
     }
     if ((((uint) num4) | 15) != 0)
     {
         goto Label_06CA;
     }
     if (((uint) minError) <= uint.MaxValue)
     {
     }
     goto Label_06F6;
     Label_0782:
     if (useLog)
     {
         num5 = Math.Exp(Math.Log(high / low) / ((double) (numberOfPoints - 1)));
     }
     else
     {
         num5 = (high - low) / ((double) (numberOfPoints - 1));
     }
     num3 = low;
     num6 = 0.0;
     num2 = -1;
     flag2 = false;
     num = 0;
     goto Label_0440;
 }
Exemplo n.º 9
0
 public double Calculate(int maxIterations, double maxError, double eps, double tol, ICalculationCriteria network, int n, double[] x, double ystart, double[] bs, double[] direc, double[] g, double[] h, double[] deriv2)
 {
     double num;
     double num2;
     int num3;
     int num4;
     int num5;
     int num6;
     double num7;
     double num8;
     double num9;
     double num10;
     double num11;
     int num12;
     double num13;
     int num14;
     int num16;
     double num19;
     GlobalMinimumSearch search = new GlobalMinimumSearch();
     if ((((uint) ystart) | 8) != 0)
     {
         num = network.CalcErrorWithMultipleSigma(x, direc, deriv2, true);
         num2 = 1E+30;
         num3 = 0;
         goto Label_07E4;
     }
     goto Label_03E1;
     Label_003D:
     if (num6 >= maxIterations)
     {
         if ((((uint) num19) + ((uint) num11)) < 0)
         {
             if (((uint) num7) <= uint.MaxValue)
             {
                 goto Label_005E;
             }
             goto Label_003D;
         }
         if (((uint) maxError) < 0)
         {
             goto Label_0080;
         }
         if (((uint) num10) <= uint.MaxValue)
         {
             return num;
         }
         goto Label_039C;
     }
     Label_005E:
     if (num >= maxError)
     {
         goto Label_071B;
     }
     return num;
     Label_0080:
     if (num5 >= 6)
     {
         goto Label_0096;
     }
     Label_0085:
     xbfc8da7bffe4bca2(n, num19, g, h, direc);
     num6++;
     goto Label_003D;
     Label_0096:
     num5 = 0;
     num19 = 0.0;
     goto Label_0085;
     Label_009D:
     if (num5 < 2)
     {
         goto Label_0080;
     }
     Label_00A2:
     if (num19 <= 1.0)
     {
         goto Label_0080;
     }
     Label_00DF:
     num19 = 1.0;
     goto Label_0080;
     Label_0213:
     if (num16 < n)
     {
         x[num16] = bs[num16] + (search.X2 * direc[num16]);
         if (((((uint) num3) | 0xfffffffe) == 0) || (x[num16] < 1E-10))
         {
             x[num16] = 1E-10;
         }
         goto Label_0276;
     }
     double num17 = (num2 - num) / num2;
     if ((((uint) num10) - ((uint) ystart)) < 0)
     {
         goto Label_045B;
     }
     if ((((uint) num6) - ((uint) num14)) > uint.MaxValue)
     {
         goto Label_04C5;
     }
     if (num < maxError)
     {
         return num;
     }
     int index = 0;
     Label_019D:
     if (index < n)
     {
         direc[index] = -direc[index];
         if ((((uint) n) - ((uint) num13)) >= 0)
         {
             index++;
             goto Label_019D;
         }
     }
     else
     {
         num19 = xdf79f321ca5c3af5(n, g, direc);
     }
     if (4 != 0)
     {
         if (num19 < 0.0)
         {
             num19 = 0.0;
         }
         if (num19 > 10.0)
         {
             num19 = 10.0;
         }
         else if ((((uint) maxError) | 0xff) == 0)
         {
             goto Label_06FD;
         }
         if (num17 >= 0.001)
         {
             num5 = 0;
         }
         else
         {
             if ((((uint) num10) | 1) == 0)
             {
                 goto Label_0096;
             }
             num5++;
         }
         goto Label_009D;
     }
     if ((((uint) num12) & 0) == 0)
     {
         goto Label_029C;
     }
     Label_0276:
     num16++;
     if (0 == 0)
     {
         if (((uint) maxError) > uint.MaxValue)
         {
             goto Label_031E;
         }
         goto Label_0213;
     }
     Label_029C:
     num = search.Brentmin(10, maxError, 1E-06, 1E-05, network, search.Y2);
     Label_02C0:
     num16 = 0;
     if ((((uint) maxIterations) - ((uint) maxError)) > uint.MaxValue)
     {
         goto Label_07E9;
     }
     goto Label_0213;
     Label_031E:
     if (num4 > 0)
     {
         num = search.Brentmin(20, maxError, eps, 1E-07, network, search.Y2);
         goto Label_02C0;
     }
     if ((((uint) num16) + ((uint) num2)) <= uint.MaxValue)
     {
         goto Label_029C;
     }
     goto Label_0276;
     Label_0365:
     if (search.Y2 >= maxError)
     {
         goto Label_031E;
     }
     Label_039C:
     if (search.Y2 < num)
     {
         num14 = 0;
         goto Label_041C;
     }
     int num15 = 0;
     Label_0391:
     if (num15 < n)
     {
         x[num15] = bs[num15];
         num15++;
         if ((((uint) n) + ((uint) num15)) >= 0)
         {
             goto Label_0391;
         }
     }
     else
     {
         return num;
     }
     if ((((uint) num13) - ((uint) n)) >= 0)
     {
         goto Label_031E;
     }
     goto Label_0365;
     Label_03E1:
     x[num14] = bs[num14] + (search.Y2 * direc[num14]);
     if (x[num14] < 1E-10)
     {
         x[num14] = 1E-10;
     }
     num14++;
     Label_041C:
     if (num14 < n)
     {
         goto Label_03E1;
     }
     return search.Y2;
     Label_045B:
     num13 = 10.0 * num11;
     Label_0469:
     num2 = num;
     search.Y2 = num;
     search.FindBestRange(0.0, 2.0 * num13, -3, false, maxError, network);
     goto Label_0365;
     Label_04C5:
     num13 = num11;
     goto Label_0469;
     Label_04CB:
     if (num13 < 0.0)
     {
         goto Label_04C5;
     }
     if ((((uint) num17) + ((uint) maxIterations)) >= 0)
     {
         if (((uint) num9) >= 0)
         {
             if (num13 >= (0.1 * num11))
             {
                 if (num13 <= (10.0 * num11))
                 {
                     goto Label_0469;
                 }
             }
             else
             {
                 num13 = 0.1 * num11;
                 if ((((uint) num11) - ((uint) num16)) < 0)
                 {
                     goto Label_04CB;
                 }
                 goto Label_0469;
             }
         }
         goto Label_045B;
     }
     Label_04F0:
     num11 = 1.5 / num11;
     if (((((uint) tol) + ((uint) eps)) >= 0) && (num11 >= 0.0001))
     {
         goto Label_04CB;
     }
     Label_0516:
     num11 = 0.0001;
     goto Label_04CB;
     Label_05C6:
     if (num12 < n)
     {
         bs[num12] = x[num12];
         if (((uint) num8) > uint.MaxValue)
         {
             goto Label_009D;
         }
     }
     else
     {
         if (Math.Abs(num8) < 1E-07)
         {
             if ((((uint) num14) + ((uint) num4)) > uint.MaxValue)
             {
                 goto Label_07E4;
             }
             num13 = 0.0;
             if ((((uint) num19) - ((uint) ystart)) < 0)
             {
                 goto Label_0516;
             }
             goto Label_04F0;
         }
         num13 = num10 / num8;
         if ((((uint) num13) - ((uint) num15)) >= 0)
         {
             goto Label_04F0;
         }
         goto Label_05C6;
     }
     Label_0640:
     if (deriv2[num12] > num11)
     {
         num11 = deriv2[num12];
         if (((uint) num) < 0)
         {
             goto Label_00A2;
         }
     }
     num10 += direc[num12] * g[num12];
     if ((((uint) num8) + ((uint) num8)) > uint.MaxValue)
     {
         goto Label_071B;
     }
     num8 += (direc[num12] * direc[num12]) * deriv2[num12];
     num9 += direc[num12] * direc[num12];
     num12++;
     goto Label_05C6;
     Label_06B9:
     if (++num4 >= 3)
     {
         return num;
     }
     Label_06D9:
     num8 = 0.0;
     num9 = 0.0;
     num10 = num8 = num9 = 0.0;
     num11 = 0.0001;
     num12 = 0;
     goto Label_05C6;
     Label_06F7:
     num7 = tol * num2;
     Label_06FD:
     if ((num2 - num) > num7)
     {
         num4 = 0;
         if ((((uint) num14) & 0) != 0)
         {
             goto Label_06B9;
         }
         goto Label_06D9;
     }
     if (((uint) num9) <= uint.MaxValue)
     {
         goto Label_06B9;
     }
     return num;
     Label_071B:
     if (num2 > 1.0)
     {
         if ((((uint) num7) + ((uint) eps)) < 0)
         {
             goto Label_003D;
         }
         if ((((uint) num8) - ((uint) num14)) <= uint.MaxValue)
         {
             goto Label_06F7;
         }
     }
     else
     {
         num7 = tol;
         goto Label_06FD;
     }
     Label_0762:
     num5 = 0;
     num6 = 0;
     goto Label_003D;
     Label_07D7:
     direc[num3] = -direc[num3];
     num3++;
     Label_07E4:
     if (num3 < n)
     {
         goto Label_07D7;
     }
     Label_07E9:
     if (((uint) num15) > uint.MaxValue)
     {
         if ((((uint) num11) + ((uint) num13)) < 0)
         {
             goto Label_0640;
         }
         goto Label_00DF;
     }
     do
     {
         EngineArray.ArrayCopy(direc, g);
         EngineArray.ArrayCopy(direc, h);
         if ((((uint) num5) + ((uint) maxError)) < 0)
         {
             goto Label_06F7;
         }
         num4 = 0;
         if ((((uint) num5) - ((uint) num10)) <= uint.MaxValue)
         {
             goto Label_0762;
         }
     }
     while ((((uint) index) - ((uint) num17)) > uint.MaxValue);
     goto Label_07D7;
 }