Search code examples
optimizationilnumerics

ILNumerics: Returns unexpected minimum when optimizing a function


I am running a trial of ILNumerics (newest version as of posting) but get the wrong minimum when running a Optimization.fmin optimizer.

The minimum should be at f(-5.218) = -3.342 with search bounds at -10 <= x <= 10.

private void Compute()
    {
        //var function = new Func<double, double>(input =>
        //{
        //    var output = Math.Pow(input, 3) / Math.Exp(Math.Pow(input, 0.8));
        //    return output;
        //});

        Array<double> bounds = new double[] {-10.0, 10.0};
        Array<double> start = new double[] {1};
        Array<double> y = Optimization.fmin(myfunc, start, lowerBound: bounds[0], upperBound: bounds[1]);

        Console.WriteLine("The minimum is found at");
        Console.WriteLine("{0}", y);
        Console.WriteLine("The value is");
        Console.WriteLine("{0}", myfunc(y));

        Console.ReadLine();

        return;


    }

    static RetArray<double> myfunc(InArray<double> x)
    {
        var input = x.GetValue(0);
        var output = Math.Pow(input, 3) / Math.Exp(Math.Pow(input, 0.8));
        return output;
    }

Solution

  • Your objective function returns NaN at negative positions. You can check this easily:

    First, add sample values over the target range (-10...10) and compute the result of the objective function.

    Array<double> bounds = new double[] { -10.0, 10.0 };
    Array<double> start = new double[] { 1 };
    Array<double> y = Optimization.fmin(myfunc, start, lowerBound: bounds[0], upperBound: bounds[1]);
    
    Array<double> range = linspace(-10.0, 10, 100); 
    Array<double> YinRange = apply(range, range, (a,b) => (double)myfunc(a));
    
    Console.WriteLine("The minimum is found at");
    Console.WriteLine("{0}", y);
    Console.WriteLine("The value is");
    Console.WriteLine("{0}", myfunc(y));
    

    Now the actual values can be visualized during a debug session, using the ArrayVisualizer:

    ObjectiveFunction in ArrayVizualizer

    fmin returned roughly 0 which seems reasonable, given that it tries to ignore NaN values. According to this plot 0 in fact is the minimum and the minimizer.

    See also: MSDN on Math.Pow