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); }
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) }); }