Clone wiki

GAF / Using a Separate Assembly for Fitness

Using a Separate Assembly for Fitness

It may, on occasions be desirable to place the fitness function within its own, separate, assembly that can be loaded at run time. This can be acheived by creating a class within a dll that implements the IFitness interface.

Start by creating a library project that contains a single class that implements the IFitness Interface. Add the fitness and any helper methods needed, to the class. Compile this into its own assembly.

For example the class below is based on the fitness function from the Solving the Travelling Salesman Problem.

public class TravellingSalesman : IFitness
{

  public double EvaluateFitness (Chromosome chromosome)
  {
    var distanceToTravel = CalculateDistance(chromosome);

    //experience suggests that 1200 is just less than the shortest possible distance
    var fitness = 1200/distanceToTravel;

    return fitness > 1.0 ? 1.0 : fitness;

  }

  public static double CalculateDistance(Chromosome chromosome)
  {
    var distanceToTravel = 0.0;
    City previousCity = null;

    //run through each city in the order specified in the chromosome
    foreach (var gene in chromosome.Genes)
    {
      var currentCity = (City)gene.ObjectValue;

      if (previousCity != null)
      {
        var distance = previousCity.GetDistanceFromPosition(currentCity.Latitude,
        currentCity.Longitude);

        distanceToTravel += distance;
      }

      previousCity = currentCity;
    }

    return distanceToTravel;
  }
}

The following class is a simple method of extracting the fitness function from an assembly that implements the IFitness interface. Simply pass the path of the assembly containing the fitness function, to the constructor of the class and read the fitness function from the FitnessFunction property. E.g.

var fitnessAssembly = new FitnessAssembly ("Example.IFitness.dll");
var ga = new GeneticAlgorithm (population, fitnessAssembly.FitnessFunction);

Please note that this particular example is written for .Net 4.5.

public class FitnessAssembly
{
    public FitnessAssembly (string assemblyPath)
    {
        var fitnessDll = Assembly.LoadFile (assemblyPath);
        var type = typeof (GAF.IFitness);
        var types = fitnessDll.DefinedTypes.Where (type.IsAssignableFrom).ToList ();

        if (types.Count == 0) {
            throw new ApplicationException (string.Format ("Fitness function not found within the specified dll [{0}].", assemblyPath));
        }

        var consumerFunctions = types [0];

        //get method inf objects based on method names as defined in IConsumerFunctions
        var fitnessMethodInfo = consumerFunctions.GetDeclaredMethod ("EvaluateFitness");
        var typeAsInstance = Activator.CreateInstance (consumerFunctions);

        FitnessFunction =
             (FitnessFunction)Delegate.CreateDelegate (typeof (FitnessFunction), typeAsInstance, fitnessMethodInfo);

    }

    public FitnessFunction FitnessFunction { private set; get; }

}

Typically the path for the dll would be retrieved from config or selected in some other way at runtime rather than compile time. This allows a greater flexibilty when building solutions for end users.

A full example of using this class can be found within the [https://bitbucket.org/johnnewcombe/gaf source code] of the example projects.

Updated