/// <summary> /// Demonstrate the crossover splice operator. Two offspring will be created by swapping three /// segments of the parents (two cut points). Some genes may repeat. /// </summary> public static void Splice() { Console.WriteLine("Crossover Splice"); // Create a random number generator IGenerateRandom rnd = new MersenneTwisterGenerateRandom(); // Create a new population. IPopulation pop = new BasicPopulation(); pop.GenomeFactory = new IntegerArrayGenomeFactory(10); // Create a trainer with a very simple score function. We do not care // about the calculation of the score, as they will never be calculated. IEvolutionaryAlgorithm train = new BasicEA(pop, new NullScore()); // Create a splice operator, length = 5. Use it 1.0 (100%) of the time. var opp = new Splice(5); train.AddOperation(1.0, opp); // Create two parents, the genes are set to 1,2,3,4,5,7,8,9,10 // and 10,9,8,7,6,5,4,3,2,1. var parents = new IntegerArrayGenome[2]; parents[0] = (IntegerArrayGenome) pop.GenomeFactory.Factor(); parents[1] = (IntegerArrayGenome) pop.GenomeFactory.Factor(); for (int i = 1; i <= 10; i++) { parents[0].Data[i - 1] = i; parents[1].Data[i - 1] = 11 - i; } // Create an array to hold the offspring. var offspring = new IntegerArrayGenome[2]; // Perform the operation opp.PerformOperation(rnd, parents, 0, offspring, 0); // Display the results Console.WriteLine("Parent 1: " + string.Join(",", parents[0].Data)); Console.WriteLine("Parent 2: " + string.Join(",", parents[1].Data)); Console.WriteLine("Offspring 1: " + string.Join(",", offspring[0].Data)); Console.WriteLine("Offspring 2: " + string.Join(",", offspring[1].Data)); }
/// <summary> /// The entry point for this example. If you would like to make this example /// stand alone, then add to its own project and rename to Main. /// </summary> /// <param name="args">Not used.</param> public static void ExampleMain(string[] args) { // Create a new population. IPopulation pop = new BasicPopulation(); ISpecies species = pop.CreateSpecies(); // Create 1000 genomes, assign the score to be the index number. for (int i = 0; i < 1000; i++) { IGenome genome = new IntegerArrayGenome(1); genome.Score = i; genome.AdjustedScore = i; pop.Species[0].Add(genome); } IGenerateRandom rnd = new MersenneTwisterGenerateRandom(); // Create a trainer with a very simple score function. We do not care // about the calculation of the score, as they will never be calculated. // We only care that we are maximizing. IEvolutionaryAlgorithm train = new BasicEA(pop, new NullScore()); // Perform the test for round counts between 1 and 10. for (int roundCount = 1; roundCount <= 10; roundCount++) { var selection = new TournamentSelection(train, roundCount); int sum = 0; int count = 0; for (int i = 0; i < 100000; i++) { int genomeID = selection.PerformSelection(rnd, species); IGenome genome = species.Members[genomeID]; sum += (int) genome.AdjustedScore; count++; } sum /= count; Console.WriteLine("Rounds: " + roundCount + ", Avg Score: " + sum); } }
/// <summary> /// Display the cities in the final path. /// </summary> /// <param name="solution">The solution to display.</param> public void DisplaySolution(IntegerArrayGenome solution) { bool first = true; int[] path = solution.Data; foreach (int aPath in path) { if (!first) Console.Write(">"); Console.Write("" + aPath); first = false; } Console.WriteLine(); }
/// <summary> /// Generate a random path through cities. /// </summary> /// <param name="rnd">Random number generator.</param> /// <returns>A genome.</returns> private IntegerArrayGenome RandomGenome(IGenerateRandom rnd) { var result = new IntegerArrayGenome(_cities.Length); int[] organism = result.Data; var taken = new bool[_cities.Length]; for (int i = 0; i < organism.Length - 1; i++) { int icandidate; do { icandidate = rnd.NextInt(0, organism.Length); } while (taken[icandidate]); organism[i] = icandidate; taken[icandidate] = true; if (i == organism.Length - 2) { icandidate = 0; while (taken[icandidate]) { icandidate++; } organism[i + 1] = icandidate; } } return result; }
/// <summary> /// Get a list of the genes that have not been taken before. This is useful /// if you do not wish the same gene to appear more than once in a /// genome. /// </summary> /// <param name="source">The pool of genes to select from.</param> /// <param name="taken"> An array of the taken genes.</param> /// <returns>Those genes in source that are not taken.</returns> private static int GetNotTaken(IntegerArrayGenome source, HashSet<int> taken) { foreach (int trial in source.Data) { if (!taken.Contains(trial)) { taken.Add(trial); return trial; } } throw new AIFHError("Ran out of integers to select."); }
/// <summary> /// Construct the genome by copying another. /// </summary> /// <param name="other">The other genome.</param> public IntegerArrayGenome(IntegerArrayGenome other) { _data = (int[]) other.Data.Clone(); }
/// <summary> /// Construct the genome by copying another. /// </summary> /// <param name="other">The other genome.</param> public IntegerArrayGenome(IntegerArrayGenome other) { _data = (int[])other.Data.Clone(); }