Wiki

Clone wiki

GAF / Implementing IRemoteFitness

Implementing GAF.Network.IRemoteFitness

The GAF.Network.IRemoteFitness interface derives from IFitness and is defined as follows.

public interface IRemoteFitness : IFitness
{
    List<Type> GetKnownTypes ();
}
public interface IFitness
{
    double EvaluateFitness (Chromosome chromosome);
}

I most cases all that is required to implement the interface is to implement the EvaluateFitness method and return an empty collection within the GetKnownTypes method. The GetKnownTypes method would typically only be required if the Chromosome was object based. See below.

Object Based Genes

For the Cromosome to be evaluated remotely, the Genes collection has to be serialised for transport over the network. The DataContractSerializer is used for this purpose. Therefore, any custom classes used within the Genes collection will need to be marked with DataContract and DataMember attributes. In addition custom types should be returned from the GetKnownTypes method of the IRemoteFitness implementation.

Example

The following code shows an implementation of IRemoteFitness for the Travelling Salesman example. The listing shows the DataContract and DataMember attributes and an implementation of GetKnownTypes.

using System;
using System.Collections.Generic;
using System.Linq;
using GAF.Extensions;
using System.Text;
using GAF.Network.Serialization;
using GAF;

namespace Example.IRemoteFitness
{

    public class TravellingSalesman : GAF.Network.IRemoteFitness
    {    
        public double EvaluateFitness (Chromosome chromosome)
        {
            var distanceToTravel = CalculateDistance (chromosome);

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

            return fitness > 1.0 ? 1.0 : fitness;

        }

        public List<Type> GetKnownTypes ()
        {
            var knownTypes = new List<Type> ();
            knownTypes.Add (typeof (City));

            return knownTypes;
        }

        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) {
                    distanceToTravel += previousCity.GetDistanceFromPosition (currentCity.Latitude,
                                                                        currentCity.Longitude);
                }

                previousCity = currentCity;
            }

            //add distance back to the starting point
            var firstCity = (City)chromosome.Genes [0].ObjectValue;
            distanceToTravel += previousCity.GetDistanceFromPosition (firstCity.Latitude,
                                                    firstCity.Longitude);

            return distanceToTravel;
        }

        private static IEnumerable<City> CreateCities ()
        {
            var cities = new List<City> {
                new City ("Birmingham", 52.486125, -1.890507),
                new City ("Bristol", 51.460852, -2.588139),
                new City ("London", 51.512161, -0.116215),
                new City ("Leeds", 53.803895, -1.549931),
                new City ("Manchester", 53.478239, -2.258549),
                new City ("Liverpool", 53.409532, -3.000126),
                new City ("Hull", 53.751959, -0.335941),
                new City ("Newcastle", 54.980766, -1.615849),
                new City ("Carlisle", 54.892406, -2.923222),
                new City ("Edinburgh", 55.958426, -3.186893),
                new City ("Glasgow", 55.862982, -4.263554),
                new City ("Cardiff", 51.488224, -3.186893),
                new City ("Swansea", 51.624837, -3.94495),
                new City ("Exeter", 50.726024, -3.543949),
                new City ("Falmouth", 50.152266, -5.065556),
                new City ("Canterbury", 51.289406, 1.075802)
            };

            return cities;
        }
    }
}

This code and the compiled assembly is available via Docker and BitBucket.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace Example.IRemoteFitness
{

    [DataContract]
    public class City
    {
        public City(string name, double latitude, double longitude)
        {
            Name = name;
            Latitude = latitude;
            Longitude = longitude;
        }

        [DataMember]
        public string Name { set; get; }

        [DataMember]
        public double Latitude { get; set; }

        [DataMember]
        public double Longitude { get; set; }

        /// <summary> 
        /// Returns the distance in Km between this City and the specified location. 
        ///<summary> 
        public double GetDistanceFromPosition(double latitude, double longitude)
        {
            var R = 6371;
            // radius of the earth in km 
            var dLat = DegreesToRadians(latitude - Latitude);
            var dLon = DegreesToRadians(longitude - Longitude);
            var a = System.Math.Sin(dLat/2)*System.Math.Sin(dLat/2) +
                    System.Math.Cos(DegreesToRadians(Latitude))*System.Math.Cos(DegreesToRadians(latitude))*
                    System.Math.Sin(dLon/2)*System.Math.Sin(dLon/2);
            var c = 2*System.Math.Atan2(System.Math.Sqrt(a), System.Math.Sqrt(1 - a));
            var d = R*c;
            // distance in km 
            return d;
        }

        private static double DegreesToRadians(double deg)
        {
            return deg*(System.Math.PI/180);
        }

        public override string ToString ()
        {
            return Name;
        }
    }
}

Updated