C# Simulated Annealing Example

← All NMath Code Examples

 

using System;

using CenterSpace.NMath.Core;
using CenterSpace.NMath.Analysis;

namespace CenterSpace.NMath.Analysis.Examples.CSharp
{
  class SimulatedAnnealingExample
  {
    /// <summary>
    /// A .NET example in C# showing how to find the minimum of a function using simulated annealing.
    /// </summary>
    static void Main( string[] args )
    {
      // The function 0.25x^4 - 0.1x^3 - 20x^2 + 10x + 0.25y^4 - 0.1y^3 - 20y^2 + 10y
      // has a global minimum near (-6.3, -6.3) and three local minima.

      // Using Powell's Method starting at (-1, -1), we always find the global minimum.
      var powell = new PowellMinimizer();
      var minimum = powell.Minimize( bumpyFunction, new DoubleVector( -1.0, -1.0 ) );

      string formatString = "G5";
      Console.WriteLine();

      Console.WriteLine( "PowellMinimizer starting at (-1, -1) found global minimum: " + bumpyFunction.Evaluate( minimum ).ToString( formatString ) );
      Console.WriteLine();

      // However, if you're not sure what a good starting point is, you might start
      // at (0, 0 ). In this case, Powell's Method always finds a local minimum.
      minimum = powell.Minimize( bumpyFunction, new DoubleVector( 0.0, 0.0 ) );
      Console.WriteLine( "But PowellMinimizer starting at (0, 0) found local minimum: " + bumpyFunction.Evaluate( minimum ).ToString( formatString ) );
      Console.WriteLine();

      // Using simulated annealing, with 10 steps of 100 iterations each, a
      // starting temperature of 10, and a starting point of (0, 0), we sometimes find
      // the global minimum.
      AnnealingScheduleBase schedule = new LinearAnnealingSchedule( 3, 100, 3 );
      var annealing = new AnnealingMinimizer( schedule );
     
      // Set keep history flag to true in order to get enough data to improve our annealing schedule.
      annealing.KeepHistory = true;

      int global = 0;
      int reps = 100;
      for ( int i = 0; i < reps; i++ )
      {
        minimum = annealing.Minimize( bumpyFunction, new DoubleVector( -1.0, -1.0 ) );
        if ( bumpyFunction.Evaluate( minimum ) < -874 )
        {
          global++;
        }
      }

      Console.WriteLine( "AnnealingMinimizer starting at (0, 0) found global minimum " + global + " times " );
      Console.WriteLine( "in " + reps + " repetitions." );
      Console.WriteLine();

      Console.WriteLine( "Annealing history... " );
      Console.WriteLine();
      Console.WriteLine( annealing.History.ToString( formatString ) );
      Console.WriteLine();

      // After analysis of the annealing history (annealing.History), we can improve the schedule 
      // with a higher starting temperature to try and get us over the hump between the local and 
      // global minima.
      annealing.Schedule = new LinearAnnealingSchedule( 100, 20, 30 );

      // Let's increase the steps to 100, the iterations to 20 and the starting
      // temperature to 30.
      global = 0;
      for ( int i = 0; i < reps; i++ )
      {
        minimum = annealing.Minimize( bumpyFunction, new DoubleVector( -1.0, -1.0 ) );
        if ( bumpyFunction.Evaluate( minimum ) < -874 )
        {
          global++;
        }
      }
      Console.WriteLine( "AnnealingMinimizer starting at (0, 0) found global minimum " + global + " times " );
      Console.WriteLine( "in " + reps + " repetitions." );

      Console.WriteLine();
      Console.WriteLine( "Press Enter Key" );
      Console.Read();
    }

    private static MultiVariableFunction bumpyFunction = new MultiVariableFunction( new Func<DoubleVector, double>( Bumpy ) );

    private static double Bumpy( DoubleVector v )
    {
      double x = v[0];
      double y = v[1];
      double xTerm = 0.25 * Math.Pow( x, 4 ) - 0.1 * Math.Pow( x, 3 ) - 20 * Math.Pow( x, 2 ) + 10 * x;
      double yTerm = 0.25 * Math.Pow( y, 4 ) - 0.1 * Math.Pow( y, 3 ) - 20 * Math.Pow( y, 2 ) + 10 * y;
      return xTerm + yTerm;
    }

  }  // class

} // namespace


← All NMath Code Examples
Top