public Population(int size, IFitnessFunction fitnessFunction, IReproduction reproductionFunction, INodeMutator mutator, ISelection selection) { this.populationSize = size; this.fitnessFunction = fitnessFunction; this.reproductionFunction = reproductionFunction; this.mutator = mutator; this.selector = selection; this.fitnessFunction.Initialise(); // Create the initial population for (int i = 0; i < size; i++) { try { NodeContext zeroContext = new NodeContext(); zeroContext.AvailableCollections = fitnessFunction.GetCollections(); zeroContext.AvailableInputs = fitnessFunction.GetInputs(); INode candidateNode = NodeFactory.GenerateNode(zeroContext); // Make sure we have a decent candidate (i.e. not too large) double fitness = this.fitnessFunction.CalculateFitness(candidateNode); if (fitness == Double.MaxValue) continue; this.population.Add(NodeFactory.GenerateNode(zeroContext)); } catch (StackOverflowException) { } } }
public object Clone() { NodeContext result = new NodeContext(); result.DepthLevel = this.DepthLevel; result.AvailableCollections = new List<int>(this.AvailableCollections); result.AvailableInputs = new List<int>(this.AvailableInputs); return result; }
public static INode GenerateNode(NodeContext context) { INode result = null; if (context.DepthLevel > 20) { result = new ConstantNode(context.GenerateNewLevel()); return result; } int probability = 10; while (result == null) { if (RandomUtil.Random.Next(100) < probability) { result = new AddNode(context.GenerateNewLevel()); } else if (RandomUtil.Random.Next(100) < probability) { result = new SubtractNode(context.GenerateNewLevel()); } else if (RandomUtil.Random.Next(100) < probability) { result = new MultiplyNode(context.GenerateNewLevel()); } else if (RandomUtil.Random.Next(100) < probability) { result = new DivideNode(context.GenerateNewLevel()); } else if (RandomUtil.Random.Next(100) < probability) { result = new InputSizeNode(context.GenerateNewLevel()); } else if (RandomUtil.Random.Next(100) < probability) { result = new CollectionSizeNode(context.GenerateNewLevel()); } else if (RandomUtil.Random.Next(100) < probability && context.AvailableInputs.Count > 0) { result = new InputVariableNode(context.GenerateNewLevel()); } else if (RandomUtil.Random.Next(100) < probability && context.AvailableCollections.Count > 0) { result = new SumNode(context.GenerateNewLevel()); } } //NodeFactory.SimplifyNode(ref result); return result; }
/// <summary> /// Generate a new population based on the fitness of the previous population's /// individuals /// </summary> public void ProcessGeneration() { NodeContext zeroContext = new NodeContext(); zeroContext.AvailableCollections = fitnessFunction.GetCollections(); zeroContext.AvailableInputs = fitnessFunction.GetInputs(); // Create a new set of tests fitnessFunction.Initialise(); Console.WriteLine("Calculate"); // Get the fitness measure for each individual var fitnesses = new ThreadSafeDictionary<int, double>(); for (int i = 0; i < this.population.Count; ++i) { fitnesses[i] = this.fitnessFunction.CalculateFitness(this.population[i]); fitnesses[i] = Math.Abs(fitnesses[i]); } //var loopResult = Parallel.For(0, this.population.Count, delegate(int i) //{ // fitnesses[i] = Math.Abs(this.fitnessFunction.CalculateFitness(this.population[i])); // //fitnesses[i] = Math.Abs(fitnesses[i]); //}); //if (!loopResult.IsCompleted) //{ // Console.WriteLine("Loop failed"); //} this.selector.Initialise(this.population, fitnesses); var bestIndividuals = from k in fitnesses.Keys orderby fitnesses[k] ascending select this.population[k]; INode best = bestIndividuals.FirstOrDefault(); this.BestIndividual = best; // Update the best fitness this.BestFitness = fitnesses.Values.Min(); this.AverageFitness = fitnesses.Values.Sum(f => f < Double.MaxValue ? f : 0)/fitnesses.Values.Count(f => f < Double.MaxValue); Console.WriteLine("Best fitness: {0} {1}", fitnesses.Values.Min(), best); this.PrintAverageTreeSize(); List<INode> newPopulation = new List<INode>(); // Always keep the best 10% newPopulation.AddRange(bestIndividuals.Take(this.populationSize / 10)); while (newPopulation.Count < this.populationSize) { INode parentA = this.selector.SelectNode(); INode parentB = this.selector.SelectNode(); INode child = this.reproductionFunction.Reproduce(parentA, parentB); //INode child = (INode) this.selector.SelectNode().Clone(); this.mutator.Mutate(ref child, zeroContext); newPopulation.Add(child); } // Replace the old population); this.population = newPopulation; }