public override FunctionPoint FindMinimum(Vector startPoint)
        {
            // Find potential minimum with linear interpolation of derivative (so quadric interpolation of function)
            // f'(x) = f'(x0) + f''(x0) * (x - x0) = 0
            // dx = -f'(x0) / f''(x0)

            double        lastValue = Function(startPoint);
            double        newValue  = lastValue;
            Vector        point     = (Vector)startPoint.Clone();
            FunctionPoint result;

            do
            {
                double df  = NumericalDerivative.First(Function, point, Direction);
                double df2 = NumericalDerivative.Second(Function, point, Direction);

                if (Math.Abs(df) < MaxError)
                {
                    // We are at point f'(x) ~= 0
                    if (df2 > 0.0) // Ad we have minumum, so we're good
                    {
                        return(new FunctionPoint()
                        {
                            Point = point,
                            Value = Function(point)
                        });
                    }
                    else
                    {
                        // let's move a bit in arbitrary direction
                        df = 1.0;
                    }
                }
                else if (Math.Abs(df2) * 1000.0 < Math.Abs(df))
                {
                    // We are at point f''(x) ~= 0, so we may assume function is linear (at least localy)
                    // If so it has no minima, so lets pick arbitrary step of -df
                    df2 = 1.0;
                }

                double dx = -df / df2;

                if (dx > 0.0)
                {
                    base.leftInt  = point[Direction];
                    base.rightInt = point[Direction] + dx;
                }
                else
                {
                    base.leftInt  = point[Direction] + dx;
                    base.rightInt = point[Direction];
                }
                result = base.FindMinimum(point);
                point  = result.Point;

                lastValue = newValue;
                newValue  = result.Value;
            }while (Math.Abs(lastValue - newValue) > MaxError);

            return(result);
        }
Exemple #2
0
        public override FunctionPoint FindMinimum(Vector startPoint)
        {
            // Find potential minimum with linear interpolation of derivative (so quadric interpolation of function)
            // f'(x) = f'(x0) + f''(x0) * (x - x0) = 0
            // dx = -f'(x0) / f''(x0)

            Vector point = (Vector)startPoint.Clone();
            double lastPosition, lastValue;
            int    iteration = 0;

            do
            {
                lastPosition = point[Direction];
                lastValue    = Function(point);
                iteration++;
                iterations1++;

                double df   = NumericalDerivative.First(Function, point, Direction, MaxError / 100);
                double df2  = NumericalDerivative.Second(Function, point, Direction, MaxError / 100);
                double step = Math.Abs(df / df2);

                if (Math.Abs(df) < MaxError || step < MinPointChange)
                {
                    // We are at point f'(x) ~= 0
                    double fhl = NumericalDerivative.fhLeft(Function, point, Direction, MaxError);
                    double fhr = NumericalDerivative.fhRight(Function, point, Direction, MaxError);

                    // We cound check if f''(x) > 0, but due to non-continous derivative of penalty function sometimes it may fail
                    if (fhl > lastValue && fhr > lastValue)
                    {
                        return(new FunctionPoint()
                        {
                            Point = point,
                            Value = lastValue
                        });
                    }
                    else if (!DisableModTwo)
                    {
                        // Most probably we are close to maximum and function is quite flat. To give it a kick lets use golden section.
                        point = useGoldenSection(point, lastValue, step, fhl, fhr);
                    }
                }
                else
                {
                    if (Math.Abs(df2) < df2_error)
                    {
                        df2 = 1.0;
                    }
                    if (df > 0.0) // Move in direction which minimizes f(x)
                    {
                        point[Direction] -= Math.Abs(df / df2);
                    }
                    else
                    {
                        point[Direction] += Math.Abs(df / df2);
                    }

                    double newValue = Function(point);
                    throwOnInvalidValue(newValue, point, lastPosition, Direction);
                }
            }while (iteration < MaxIterations &&
                    (Math.Abs(lastValue - Function(point)) > MaxError ||
                     Math.Abs(lastPosition - point[Direction]) > MinPointChange));

            if (iteration == MaxIterations)
            {
                // It doesnt converge
            }

            return(new FunctionPoint()
            {
                Point = point,
                Value = Function(point)
            });
        }