From bffc489ed020fcf34c13e206688e06742176502a Mon Sep 17 00:00:00 2001 From: ZviRosenfeld Date: Fri, 10 Jan 2020 14:21:37 +0200 Subject: [PATCH] 1.3.2 content --- .../AlternatingPositionCrossoverTests.cs | 25 ++++++ .../CycleCrossoverManagerTests.cs | 14 +--- .../OrderBasedCrossoverTests.cs | 25 ++++++ .../CrossoverManagers/OrderCrossoverTests.cs | 38 +-------- .../PartiallyMappedCrossoverTests.cs | 37 +-------- .../PositionBasedCrossoverManagerTests.cs | 25 ++++++ .../Components/CrossoverManagers/Utils.cs | 45 ++++++++++- .../DisplacementMutationManagerTests.cs | 26 ++++++ ...sts.cs => ExchangeMutationManagerTests.cs} | 41 +++++----- .../InsertionMutationManagerTests.cs | 56 +++++++++++++ .../InversionMutationManagerTests.cs | 26 ++++++ .../ScrambleMutationManagerTests.cs | 26 ++++++ .../SimpleInversionMutationManagerTests.cs | 79 +++++++++++++++++++ .../Components/MutationManagers/Utils.cs | 39 +++++++++ GeneticAlgorithm/Components/ComponetsUtils.cs | 15 ++++ .../AlternatingPositionCrossover.cs | 68 ++++++++++++++++ .../CycleCrossoverManager.cs | 2 + .../CrossoverManagers/OrderBasedCrossover.cs | 74 +++++++++++++++++ .../CrossoverManagers/OrderCrossover.cs | 24 +++--- .../PositionBasedCrossoverManager.cs | 71 +++++++++++++++++ .../Components/CrossoverManagers/Utils.cs | 14 +--- .../DisplacementMutationBase.cs | 50 ++++++++++++ .../DisplacementMutationManager.cs | 18 +++++ .../DoubleBoundaryMutationManager.cs | 2 +- .../DoubleUniformMutationManager.cs | 2 +- ...nManager.cs => ExchangeMutationManager.cs} | 5 +- .../InsertionMutationManager.cs | 44 +++++++++++ .../IntBoundaryMutationManager.cs | 2 +- .../IntUniformMutationManager.cs | 2 +- .../InversionMutationManager.cs | 18 +++++ .../ScrambleMutationManager.cs | 31 ++++++++ .../SimpleInversionMutationManager.cs | 29 +++++++ GeneticAlgorithm/GeneticAlgorithm.nuspec | 2 +- .../SelectionStrategies/ChromosomePool.cs | 23 +----- .../StochasticUniversalSampling.cs | 2 +- README.md | 25 ++++-- TravellingSalesman/Program.cs | 2 +- 37 files changed, 868 insertions(+), 159 deletions(-) create mode 100644 GeneticAlgorithm.UnitTests/Components/CrossoverManagers/AlternatingPositionCrossoverTests.cs create mode 100644 GeneticAlgorithm.UnitTests/Components/CrossoverManagers/OrderBasedCrossoverTests.cs create mode 100644 GeneticAlgorithm.UnitTests/Components/CrossoverManagers/PositionBasedCrossoverManagerTests.cs create mode 100644 GeneticAlgorithm.UnitTests/Components/MutationManagers/DisplacementMutationManagerTests.cs rename GeneticAlgorithm.UnitTests/Components/MutationManagers/{SingleSwapMutationManagerTests.cs => ExchangeMutationManagerTests.cs} (51%) create mode 100644 GeneticAlgorithm.UnitTests/Components/MutationManagers/InsertionMutationManagerTests.cs create mode 100644 GeneticAlgorithm.UnitTests/Components/MutationManagers/InversionMutationManagerTests.cs create mode 100644 GeneticAlgorithm.UnitTests/Components/MutationManagers/ScrambleMutationManagerTests.cs create mode 100644 GeneticAlgorithm.UnitTests/Components/MutationManagers/SimpleInversionMutationManagerTests.cs create mode 100644 GeneticAlgorithm/Components/ComponetsUtils.cs create mode 100644 GeneticAlgorithm/Components/CrossoverManagers/AlternatingPositionCrossover.cs create mode 100644 GeneticAlgorithm/Components/CrossoverManagers/OrderBasedCrossover.cs create mode 100644 GeneticAlgorithm/Components/CrossoverManagers/PositionBasedCrossoverManager.cs create mode 100644 GeneticAlgorithm/Components/MutationManagers/DisplacementMutationBase.cs create mode 100644 GeneticAlgorithm/Components/MutationManagers/DisplacementMutationManager.cs rename GeneticAlgorithm/Components/MutationManagers/{SingleSwapMutationManager.cs => ExchangeMutationManager.cs} (67%) create mode 100644 GeneticAlgorithm/Components/MutationManagers/InsertionMutationManager.cs create mode 100644 GeneticAlgorithm/Components/MutationManagers/InversionMutationManager.cs create mode 100644 GeneticAlgorithm/Components/MutationManagers/ScrambleMutationManager.cs create mode 100644 GeneticAlgorithm/Components/MutationManagers/SimpleInversionMutationManager.cs diff --git a/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/AlternatingPositionCrossoverTests.cs b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/AlternatingPositionCrossoverTests.cs new file mode 100644 index 0000000..1d15121 --- /dev/null +++ b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/AlternatingPositionCrossoverTests.cs @@ -0,0 +1,25 @@ +using GeneticAlgorithm.Components.CrossoverManagers; +using GeneticAlgorithm.Interfaces; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace GeneticAlgorithm.UnitTests.Components.CrossoverManagers +{ + [TestClass] + public class AlternatingPositionCrossoverTests + { + private readonly ICrossoverManager crossoverManager = new AlternatingPositionCrossover(null, null); + + [TestMethod] + [DataRow(20)] + public void OrderCrossover_AllElementsInEachVector(int vectors) + { + crossoverManager.TestThatAllElementsInEachVector(vectors); + } + + [TestMethod] + public void OrderCrossover_ChildChanged() + { + crossoverManager.TestThatChildChanged(); + } + } +} diff --git a/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/CycleCrossoverManagerTests.cs b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/CycleCrossoverManagerTests.cs index 90d5d45..635bcc7 100644 --- a/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/CycleCrossoverManagerTests.cs +++ b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/CycleCrossoverManagerTests.cs @@ -1,8 +1,5 @@ -using System.Collections.Generic; -using System.Linq; -using GeneticAlgorithm.Components.Chromosomes; +using GeneticAlgorithm.Components.Chromosomes; using GeneticAlgorithm.Components.CrossoverManagers; -using GeneticAlgorithm.Components.PopulationGenerators; using GeneticAlgorithm.Interfaces; using GeneticAlgorithm.UnitTests.TestUtils; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -12,8 +9,6 @@ namespace GeneticAlgorithm.UnitTests.Components.CrossoverManagers [TestClass] public class CycleCrossoverManagerTests { - private static readonly List elements = new List() { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; - private readonly IPopulationGenerator generator = new AllElementsVectorChromosomePopulationGenerator(elements, null, null); private readonly ICrossoverManager crossoverManager = new CycleCrossoverManager(null, null); [TestMethod] @@ -60,12 +55,7 @@ public void CycleCrossoverTest() [DataRow(20)] public void CycleCrossover_AllElementsInEachVector(int vectors) { - for (int i = 0; i < vectors; i++) - { - var parentChromosomes = generator.GeneratePopulation(2); - var child = (VectorChromosome)crossoverManager.Crossover(parentChromosomes.ElementAt(0), parentChromosomes.ElementAt(1)); - child.AssertContainSameElements(elements); - } + crossoverManager.TestThatAllElementsInEachVector(vectors); } private void TestCycleCrossover(string[] parent1, string[] parent2, string[] expectedChild) diff --git a/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/OrderBasedCrossoverTests.cs b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/OrderBasedCrossoverTests.cs new file mode 100644 index 0000000..324dc14 --- /dev/null +++ b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/OrderBasedCrossoverTests.cs @@ -0,0 +1,25 @@ +using GeneticAlgorithm.Components.CrossoverManagers; +using GeneticAlgorithm.Interfaces; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace GeneticAlgorithm.UnitTests.Components.CrossoverManagers +{ + [TestClass] + public class OrderBassedCrossoverTests + { + private readonly ICrossoverManager crossoverManager = new OrderBasedCrossover(null, null); + + [TestMethod] + [DataRow(20)] + public void OrderBasedCrossover_AllElementsInEachVector(int vectors) + { + crossoverManager.TestThatAllElementsInEachVector(vectors); + } + + [TestMethod] + public void OrderBasedCrossover_ChildChanged() + { + crossoverManager.TestThatChildChanged(); + } + } +} diff --git a/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/OrderCrossoverTests.cs b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/OrderCrossoverTests.cs index 431fd26..170db98 100644 --- a/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/OrderCrossoverTests.cs +++ b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/OrderCrossoverTests.cs @@ -1,11 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using GeneticAlgorithm.Components.Chromosomes; -using GeneticAlgorithm.Components.CrossoverManagers; -using GeneticAlgorithm.Components.PopulationGenerators; +using GeneticAlgorithm.Components.CrossoverManagers; using GeneticAlgorithm.Interfaces; -using GeneticAlgorithm.UnitTests.TestUtils; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace GeneticAlgorithm.UnitTests.Components.CrossoverManagers @@ -13,45 +7,19 @@ namespace GeneticAlgorithm.UnitTests.Components.CrossoverManagers [TestClass] public class OrderCrossoverTests { - private static readonly List elements = new List() { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; - private readonly IPopulationGenerator generator = new AllElementsVectorChromosomePopulationGenerator(elements, null, null); private readonly ICrossoverManager crossoverManager = new OrderCrossover(null, null); [TestMethod] [DataRow(20)] public void OrderCrossover_AllElementsInEachVector(int vectors) { - for (int i = 0; i < vectors; i++) - { - var parentChromosomes = generator.GeneratePopulation(2); - var child = (VectorChromosome)crossoverManager.Crossover(parentChromosomes.ElementAt(0), parentChromosomes.ElementAt(1)); - child.AssertContainSameElements(elements); - } + crossoverManager.TestThatAllElementsInEachVector(vectors); } [TestMethod] public void OrderCrossover_ChildChanged() { - // Since there's a certain chance that this test will fail, I want to run it twice - var passed = false; - for (int i = 0; i < 2; i++) - { - var parentChromosomes = generator.GeneratePopulation(2); - var child = (VectorChromosome) crossoverManager.Crossover(parentChromosomes.ElementAt(0), - parentChromosomes.ElementAt(1)); - - try - { - ((VectorChromosome)parentChromosomes.ElementAt(0)).AssertAreNotTheSame(child); - ((VectorChromosome)parentChromosomes.ElementAt(1)).AssertAreNotTheSame(child); - passed = true; - } - catch - { - // Do nothing - } - } - Assert.IsTrue(passed); + crossoverManager.TestThatChildChanged(); } } } diff --git a/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/PartiallyMappedCrossoverTests.cs b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/PartiallyMappedCrossoverTests.cs index 9aee408..a589d8d 100644 --- a/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/PartiallyMappedCrossoverTests.cs +++ b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/PartiallyMappedCrossoverTests.cs @@ -1,10 +1,5 @@ -using System.Collections.Generic; -using System.Linq; -using GeneticAlgorithm.Components.Chromosomes; -using GeneticAlgorithm.Components.CrossoverManagers; -using GeneticAlgorithm.Components.PopulationGenerators; +using GeneticAlgorithm.Components.CrossoverManagers; using GeneticAlgorithm.Interfaces; -using GeneticAlgorithm.UnitTests.TestUtils; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace GeneticAlgorithm.UnitTests.Components.CrossoverManagers @@ -12,45 +7,19 @@ namespace GeneticAlgorithm.UnitTests.Components.CrossoverManagers [TestClass] public class PartiallyMappedCrossoverTests { - private static readonly List elements = new List() { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; - private readonly IPopulationGenerator generator = new AllElementsVectorChromosomePopulationGenerator(elements, null, null); private readonly ICrossoverManager crossoverManager = new PartiallyMappedCrossover(null, null); [TestMethod] [DataRow(20)] public void PartiallyMatchedCrossover_AllElementsInEachVector(int vectors) { - for (int i = 0; i < vectors; i++) - { - var parentChromosomes = generator.GeneratePopulation(2); - var child = (VectorChromosome)crossoverManager.Crossover(parentChromosomes.ElementAt(0), parentChromosomes.ElementAt(1)); - child.AssertContainSameElements(elements); - } + crossoverManager.TestThatAllElementsInEachVector(vectors); } [TestMethod] public void PartiallyMatchedCrossover_ChildChanged() { - // Since there's a certain chance that this test will fail, I want to run it twice - var passed = false; - for (int i = 0; i < 2; i++) - { - var parentChromosomes = generator.GeneratePopulation(2); - var child = (VectorChromosome)crossoverManager.Crossover(parentChromosomes.ElementAt(0), - parentChromosomes.ElementAt(1)); - - try - { - ((VectorChromosome)parentChromosomes.ElementAt(0)).AssertAreNotTheSame(child); - ((VectorChromosome)parentChromosomes.ElementAt(1)).AssertAreNotTheSame(child); - passed = true; - } - catch - { - // Do nothing - } - } - Assert.IsTrue(passed); + crossoverManager.TestThatChildChanged(); } } } diff --git a/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/PositionBasedCrossoverManagerTests.cs b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/PositionBasedCrossoverManagerTests.cs new file mode 100644 index 0000000..4f569f8 --- /dev/null +++ b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/PositionBasedCrossoverManagerTests.cs @@ -0,0 +1,25 @@ +using GeneticAlgorithm.Components.CrossoverManagers; +using GeneticAlgorithm.Interfaces; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace GeneticAlgorithm.UnitTests.Components.CrossoverManagers +{ + [TestClass] + public class PositionBasedCrossoverManagerTests + { + private readonly ICrossoverManager crossoverManager = new PositionBasedCrossoverManager(null, null); + + [TestMethod] + [DataRow(20)] + public void PositionBasedCrossover_AllElementsInEachVector(int vectors) + { + crossoverManager.TestThatAllElementsInEachVector(vectors); + } + + [TestMethod] + public void PositionBasedCrossover_ChildChanged() + { + crossoverManager.TestThatChildChanged(); + } + } +} diff --git a/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/Utils.cs b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/Utils.cs index c9dcf32..6f01a49 100644 --- a/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/Utils.cs +++ b/GeneticAlgorithm.UnitTests/Components/CrossoverManagers/Utils.cs @@ -1,5 +1,9 @@ using System.Collections.Generic; +using System.Linq; using GeneticAlgorithm.Components.Chromosomes; +using GeneticAlgorithm.Components.PopulationGenerators; +using GeneticAlgorithm.Interfaces; +using GeneticAlgorithm.UnitTests.TestUtils; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace GeneticAlgorithm.UnitTests.Components.CrossoverManagers @@ -30,7 +34,7 @@ public static List K_CrossoverGetCrossoverPointsAndAssertThatGenomesAreRigh takingFromFirstChromosome = !takingFromFirstChromosome; } else if (newChromosome[i] != chromosome2[i]) - Assert.Fail($"Got Genome that dosn't seem to have came from anywhere. 1: {chromosome1}; 2 {chromosome2}; newChromosome {newChromosome} "); + Assert.Fail($"Got Genome that doesn't seem to have came from anywhere. 1: {chromosome1}; 2 {chromosome2}; newChromosome {newChromosome} "); } } for (int j = chromosome1.Length; j < chromosome2.Length && j < newChromosome.GetVector().Length; j++) @@ -38,5 +42,44 @@ public static List K_CrossoverGetCrossoverPointsAndAssertThatGenomesAreRigh return crossoverPoints; } + + public static void TestThatAllElementsInEachVector(this ICrossoverManager crossoverManager, int testRuns) + { + var elements = new List() { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; + var generator = new AllElementsVectorChromosomePopulationGenerator(elements, null, null); + for (int i = 0; i < testRuns; i++) + { + var parentChromosomes = generator.GeneratePopulation(2); + var child = (VectorChromosome)crossoverManager.Crossover(parentChromosomes.ElementAt(0), parentChromosomes.ElementAt(1)); + child.AssertContainSameElements(elements); + } + } + + public static void TestThatChildChanged(this ICrossoverManager crossoverManager) + { + var elements = new List() { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; + var generator = new AllElementsVectorChromosomePopulationGenerator(elements, null, null); + + // Since there's a certain chance that this test will fail, I want to run it twice + var passed = false; + for (int i = 0; i < 2; i++) + { + var parentChromosomes = generator.GeneratePopulation(2); + var child = (VectorChromosome)crossoverManager.Crossover(parentChromosomes.ElementAt(0), + parentChromosomes.ElementAt(1)); + + try + { + ((VectorChromosome)parentChromosomes.ElementAt(0)).AssertAreNotTheSame(child); + ((VectorChromosome)parentChromosomes.ElementAt(1)).AssertAreNotTheSame(child); + passed = true; + } + catch + { + // Do nothing + } + } + Assert.IsTrue(passed); + } } } diff --git a/GeneticAlgorithm.UnitTests/Components/MutationManagers/DisplacementMutationManagerTests.cs b/GeneticAlgorithm.UnitTests/Components/MutationManagers/DisplacementMutationManagerTests.cs new file mode 100644 index 0000000..4c8eb72 --- /dev/null +++ b/GeneticAlgorithm.UnitTests/Components/MutationManagers/DisplacementMutationManagerTests.cs @@ -0,0 +1,26 @@ +using GeneticAlgorithm.Components.Interfaces; +using GeneticAlgorithm.Components.MutationManagers; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace GeneticAlgorithm.UnitTests.Components.MutationManagers +{ + [TestClass] + public class DisplacementMutationManagerTests + { + private readonly IMutationManager mutationManager = new DisplacementMutationManager(); + + [TestMethod] + [DataRow(20)] + public void DisplacementMutationManager_AllElementsInEachVector(int vectors) + { + mutationManager.TestAllElementsInEachVector(vectors); + } + + // This test is probabilistic, so there's a certain chance that this test will fail even if the code is okay. + [TestMethod] + public void DisplacementMutationManager_ChromosomeChanged() + { + mutationManager.TestChromosomeChanged(); + } + } +} diff --git a/GeneticAlgorithm.UnitTests/Components/MutationManagers/SingleSwapMutationManagerTests.cs b/GeneticAlgorithm.UnitTests/Components/MutationManagers/ExchangeMutationManagerTests.cs similarity index 51% rename from GeneticAlgorithm.UnitTests/Components/MutationManagers/SingleSwapMutationManagerTests.cs rename to GeneticAlgorithm.UnitTests/Components/MutationManagers/ExchangeMutationManagerTests.cs index 3f9a6fe..ea96a92 100644 --- a/GeneticAlgorithm.UnitTests/Components/MutationManagers/SingleSwapMutationManagerTests.cs +++ b/GeneticAlgorithm.UnitTests/Components/MutationManagers/ExchangeMutationManagerTests.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using GeneticAlgorithm.Components.Chromosomes; +using GeneticAlgorithm.Components.Interfaces; using GeneticAlgorithm.Components.MutationManagers; using GeneticAlgorithm.Components.PopulationGenerators; using GeneticAlgorithm.UnitTests.TestUtils; @@ -9,34 +11,37 @@ namespace GeneticAlgorithm.UnitTests.Components.MutationManagers { [TestClass] - public class SingleSwapMutationManagerTests + public class ExchangeMutationManagerTests { + private readonly IMutationManager mutationManager = new ExchangeMutationManager(); + [TestMethod] [DataRow(20)] - public void SingleSwapMutationManager_AllElementsInEachVector(int vectors) + public void ExchangeMutationManager_AllElementsInEachVector(int vectors) { - var elements = new List() { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; - var generator = new AllElementsVectorChromosomePopulationGenerator(elements, null, null); - var mutationManager = new SingleSwapMutationManager(); - for (int i = 0; i < vectors; i++) - { - var before = ((VectorChromosome)generator.GeneratePopulation(1).First()).GetVector(); - var after = mutationManager.Mutate(before.ToArray()); - before.AssertContainSameElements(after); - } + mutationManager.TestAllElementsInEachVector(vectors); } // This test is probabilistic, so there's a certain chance that this test will fail even if the code is okay. [TestMethod] - public void SingleSwapMutationManager_ChromosomeChanged() + public void ExchangeMutationManager_ChromosomeChanged() { - var elements = new List() { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; - var generator = new AllElementsVectorChromosomePopulationGenerator(elements, null, null); - var mutationManager = new SingleSwapMutationManager(); - var before = ((VectorChromosome)generator.GeneratePopulation(1).First()).GetVector(); - var after = mutationManager.Mutate(before.ToArray()); + mutationManager.TestChromosomeChanged(); + } - before.AssertAreNotTheSame(after); + [TestMethod] + [DataRow(20)] + public void ExchangeMutationManager_ExactlyTwoGenomesAreDiffrent(int vectors) + { + var elements = new List { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; + var generator = new AllElementsVectorChromosomePopulationGenerator(elements, null, null); + for (int i = 0; i < vectors; i++) + { + var before = ((VectorChromosome)generator.GeneratePopulation(1).First()).GetVector(); + var after = mutationManager.Mutate(before.ToArray()); + var diffrentGenomes = before.Where((t, j) => t != after[j]).Count(); + Assert.IsTrue(diffrentGenomes == 0 || diffrentGenomes == 2); + } } } } diff --git a/GeneticAlgorithm.UnitTests/Components/MutationManagers/InsertionMutationManagerTests.cs b/GeneticAlgorithm.UnitTests/Components/MutationManagers/InsertionMutationManagerTests.cs new file mode 100644 index 0000000..e43850d --- /dev/null +++ b/GeneticAlgorithm.UnitTests/Components/MutationManagers/InsertionMutationManagerTests.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Linq; +using GeneticAlgorithm.Components.Chromosomes; +using GeneticAlgorithm.Components.Interfaces; +using GeneticAlgorithm.Components.MutationManagers; +using GeneticAlgorithm.Components.PopulationGenerators; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace GeneticAlgorithm.UnitTests.Components.MutationManagers +{ + [TestClass] + public class InsertionMutationManagerTests + { + private readonly IMutationManager mutationManager = new InsertionMutationManager(); + + [TestMethod] + [DataRow(20)] + public void InsertionMutationManager_AllElementsInEachVector(int vectors) + { + mutationManager.TestAllElementsInEachVector(vectors); + } + + // This test is probabilistic, so there's a certain chance that this test will fail even if the code is okay. + [TestMethod] + public void InsertionMutationManager_ChromosomeChanged() + { + mutationManager.TestChromosomeChanged(); + } + + [TestMethod] + [DataRow(20)] + public void InsertionMutationManager_OneGenomeInserted(int vectors) + { + var elements = new List { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; + var generator = new AllElementsVectorChromosomePopulationGenerator(elements, null, null); + for (int i = 0; i < vectors; i++) + { + var before = ((VectorChromosome)generator.GeneratePopulation(1).First()).GetVector(); + var after = mutationManager.Mutate(before.ToArray()); + var length = after.Length; + + var removedGenomes = 0; + + // The only genome that should meet these conditions is the removed one + if (after[0] != before[0] && after[0] != before[1]) removedGenomes++; + if (after[length - 1] != before[length - 1] && after[length - 1] != before[length - 2]) + removedGenomes++; + for (int k = 1; k < after.Length - 1; k++) + if (after[k] != before[k] && after[k] != before[k - 1] && after[k] != before[k + 1]) + removedGenomes++; + + Assert.IsTrue(removedGenomes <= 1, "Only one genome should have been removed"); + } + } + } +} diff --git a/GeneticAlgorithm.UnitTests/Components/MutationManagers/InversionMutationManagerTests.cs b/GeneticAlgorithm.UnitTests/Components/MutationManagers/InversionMutationManagerTests.cs new file mode 100644 index 0000000..7a8670f --- /dev/null +++ b/GeneticAlgorithm.UnitTests/Components/MutationManagers/InversionMutationManagerTests.cs @@ -0,0 +1,26 @@ +using GeneticAlgorithm.Components.Interfaces; +using GeneticAlgorithm.Components.MutationManagers; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace GeneticAlgorithm.UnitTests.Components.MutationManagers +{ + [TestClass] + public class InversionMutationManagerTests + { + private readonly IMutationManager mutationManager = new InversionMutationManager(); + + [TestMethod] + [DataRow(20)] + public void DisplacementMutationManager_AllElementsInEachVector(int vectors) + { + mutationManager.TestAllElementsInEachVector(vectors); + } + + // This test is probabilistic, so there's a certain chance that this test will fail even if the code is okay. + [TestMethod] + public void DisplacementMutationManager_ChromosomeChanged() + { + mutationManager.TestChromosomeChanged(); + } + } +} diff --git a/GeneticAlgorithm.UnitTests/Components/MutationManagers/ScrambleMutationManagerTests.cs b/GeneticAlgorithm.UnitTests/Components/MutationManagers/ScrambleMutationManagerTests.cs new file mode 100644 index 0000000..1ffcd73 --- /dev/null +++ b/GeneticAlgorithm.UnitTests/Components/MutationManagers/ScrambleMutationManagerTests.cs @@ -0,0 +1,26 @@ +using GeneticAlgorithm.Components.Interfaces; +using GeneticAlgorithm.Components.MutationManagers; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace GeneticAlgorithm.UnitTests.Components.MutationManagers +{ + [TestClass] + public class ScrambleMutationManagerTests + { + private readonly IMutationManager mutationManager = new ScrambleMutationManager(); + + [TestMethod] + [DataRow(20)] + public void ScrambleMutationManager_AllElementsInEachVector(int vectors) + { + mutationManager.TestAllElementsInEachVector(vectors); + } + + // This test is probabilistic, so there's a certain chance that this test will fail even if the code is okay. + [TestMethod] + public void ScrambleMutationManager_ChromosomeChanged() + { + mutationManager.TestChromosomeChanged(); + } + } +} diff --git a/GeneticAlgorithm.UnitTests/Components/MutationManagers/SimpleInversionMutationManagerTests.cs b/GeneticAlgorithm.UnitTests/Components/MutationManagers/SimpleInversionMutationManagerTests.cs new file mode 100644 index 0000000..b34f4eb --- /dev/null +++ b/GeneticAlgorithm.UnitTests/Components/MutationManagers/SimpleInversionMutationManagerTests.cs @@ -0,0 +1,79 @@ +using System.Collections.Generic; +using System.Linq; +using GeneticAlgorithm.Components.Chromosomes; +using GeneticAlgorithm.Components.Interfaces; +using GeneticAlgorithm.Components.MutationManagers; +using GeneticAlgorithm.Components.PopulationGenerators; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace GeneticAlgorithm.UnitTests.Components.MutationManagers +{ + [TestClass] + public class SimpleInversionMutationManagerTests + { + private readonly IMutationManager mutationManager = new SimpleInversionMutationManager(); + + [TestMethod] + [DataRow(20)] + public void SimpleInversionMutationManager_AllElementsInEachVector(int vectors) + { + mutationManager.TestAllElementsInEachVector(vectors); + } + + // This test is probabilistic, so there's a certain chance that this test will fail even if the code is okay. + [TestMethod] + public void SimpleInversionMutationManager_ChromosomeChanged() + { + mutationManager.TestChromosomeChanged(); + } + + [TestMethod] + [DataRow(20)] + public void SimpleInversionMutationManager_OneScratchInversed(int vectors) + { + var elements = new List { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; + var generator = new AllElementsVectorChromosomePopulationGenerator(elements, null, null); + for (int i = 0; i < vectors; i++) + { + var before = ((VectorChromosome)generator.GeneratePopulation(1).First()).GetVector(); + var after = mutationManager.Mutate(before.ToArray()); + + var (start, end) = GetStartAndEndInversionPoints(before, after); + AssertInversionIsCorrect(start, end, before, after); + } + } + + private void AssertInversionIsCorrect(int start, int end, string[] before, string[] after) + { + for (int i = 0; i < start; i++) + Assert.AreEqual(before[i], after[i]); + for (int addTo = start, addFrom = end - 1; addTo < end; addTo++, addFrom--) + Assert.AreEqual(before[addFrom], after[addTo]); + for (int i = end; i < after.Length; i++) + Assert.AreEqual(before[i], after[i]); + } + + private (int, int) GetStartAndEndInversionPoints(string[] before, string[] after) + { + int start = -1, end = -1, j = 0; + for (; j < after.Length; j++) + if (before[j] != after[j]) + { + start = j; + break; + } + for (; j < after.Length; j++) + if (before[j] == after[j] && (j + 1 >= after.Length || before[j + 1] == after[j + 1])) + { + end = j; + break; + } + if (end == -1) + end = after.Length; + if (start == -1) + start = after.Length; + + return (start, end); + } + } +} diff --git a/GeneticAlgorithm.UnitTests/Components/MutationManagers/Utils.cs b/GeneticAlgorithm.UnitTests/Components/MutationManagers/Utils.cs index 960e6a7..deae609 100644 --- a/GeneticAlgorithm.UnitTests/Components/MutationManagers/Utils.cs +++ b/GeneticAlgorithm.UnitTests/Components/MutationManagers/Utils.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using GeneticAlgorithm.Components.Chromosomes; using GeneticAlgorithm.Components.Interfaces; +using GeneticAlgorithm.Components.PopulationGenerators; using GeneticAlgorithm.UnitTests.TestUtils; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -71,5 +73,42 @@ public static void AssertValuesAreScattered(this IMutationManager mutation Assert.IsTrue(values.Count > 8, $"We only got {values.Count} diffrent values"); } + + public static void TestChromosomeChanged(this IMutationManager mutationManager) + { + var elements = new List { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; + var generator = new AllElementsVectorChromosomePopulationGenerator(elements, null, null); + + // Since there's a certain chance that this test will fail, I want to run it twice + var passed = false; + for (int i = 0; i < 2; i++) + { + try + { + var before = ((VectorChromosome) generator.GeneratePopulation(1).First()).GetVector(); + var after = mutationManager.Mutate(before.ToArray()); + + before.AssertAreNotTheSame(after); + passed = true; + } + catch + { + // Do nothing + } + } + Assert.IsTrue(passed); + } + + public static void TestAllElementsInEachVector(this IMutationManager mutationManager, int testRuns) + { + var elements = new List { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; + var generator = new AllElementsVectorChromosomePopulationGenerator(elements, null, null); + for (int i = 0; i < testRuns; i++) + { + var before = ((VectorChromosome)generator.GeneratePopulation(1).First()).GetVector(); + var after = mutationManager.Mutate(before.ToArray()); + before.AssertContainSameElements(after); + } + } } } diff --git a/GeneticAlgorithm/Components/ComponetsUtils.cs b/GeneticAlgorithm/Components/ComponetsUtils.cs new file mode 100644 index 0000000..cfcd27c --- /dev/null +++ b/GeneticAlgorithm/Components/ComponetsUtils.cs @@ -0,0 +1,15 @@ +using System; + +namespace GeneticAlgorithm.Components +{ + static class ComponetsUtils + { + public static (int, int) GetTwoRandomNumbers(this Random random, int max) + { + var num1 = random.Next(max); + var num2 = random.Next(max); + + return (Math.Min(num1, num2), Math.Max(num1, num2)); + } + } +} diff --git a/GeneticAlgorithm/Components/CrossoverManagers/AlternatingPositionCrossover.cs b/GeneticAlgorithm/Components/CrossoverManagers/AlternatingPositionCrossover.cs new file mode 100644 index 0000000..3005207 --- /dev/null +++ b/GeneticAlgorithm/Components/CrossoverManagers/AlternatingPositionCrossover.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using GeneticAlgorithm.Components.Chromosomes; +using GeneticAlgorithm.Components.Interfaces; +using GeneticAlgorithm.Interfaces; + +namespace GeneticAlgorithm.Components.CrossoverManagers +{ + /// + /// AlternatingPositionCrossover Works on chromosomes of type VectorChromosome<T>. + /// It assumes that both parents are of the same length, that every genome appears only once in each parent, + /// and that both parents contain the same genomes (but probably in different orders). + /// If one of these conditions isn't met, AlternatingPositionCrossover may throw an exception. + /// Also, the Equals method must be implemented for type T. + /// + /// In AlternatingPositionCrossover, we alternately select the next element of the first parent and the next element of the second parent, + /// omitting the elements already present in the offspring. + /// This guarantees that the child contains each genome exactly once. + /// + public class AlternatingPositionCrossover : ICrossoverManager + { + private readonly Random random = new Random(); + private readonly IMutationManager mutationManager; + private readonly IEvaluator evaluator; + + /// + /// AlternatingPositionCrossover Works on chromosomes of type VectorChromosome<T>. + /// It assumes that both parents are of the same length, that every genome appears only once in each parent, + /// and that both parents contain the same genomes (but probably in different orders). + /// If one of these conditions isn't met, AlternatingPositionCrossover may throw an exception. + /// + /// Also, the Equals method must be implemented for type T. + /// + public AlternatingPositionCrossover(IMutationManager mutationManager, IEvaluator evaluator) + { + this.mutationManager = mutationManager; + this.evaluator = evaluator; + } + + public IChromosome Crossover(IChromosome chromosome1, IChromosome chromosome2) + { + var vector1 = ((VectorChromosome)chromosome1).GetVector(); + var vector2 = ((VectorChromosome)chromosome2).GetVector(); + var length = vector1.Length; + + var addedElements = new HashSet(); + var newVector = new T[length]; + var indexToAddAt = 0; + for (int i = 0; i < length; i++) + { + if (!addedElements.Contains(vector1[i])) + { + newVector[indexToAddAt] = vector1[i]; + addedElements.Add(vector1[i]); + indexToAddAt++; + } + if (!addedElements.Contains(vector2[i])) + { + newVector[indexToAddAt] = vector2[i]; + addedElements.Add(vector2[i]); + indexToAddAt++; + } + } + + return new VectorChromosome(newVector, mutationManager, evaluator); + } + } +} diff --git a/GeneticAlgorithm/Components/CrossoverManagers/CycleCrossoverManager.cs b/GeneticAlgorithm/Components/CrossoverManagers/CycleCrossoverManager.cs index fa9184b..d694a35 100644 --- a/GeneticAlgorithm/Components/CrossoverManagers/CycleCrossoverManager.cs +++ b/GeneticAlgorithm/Components/CrossoverManagers/CycleCrossoverManager.cs @@ -15,6 +15,8 @@ namespace GeneticAlgorithm.Components.CrossoverManagers /// The Cycle Crossover operator identifies a number of so-called cycles between two parent chromosomes. /// Then, to form Child 1, cycle one is copied from parent 1, cycle 2 from parent 2, cycle 3 from parent 1, and so on. /// + /// In Cycle Crossover, the child is guaranteed to contain each genome exactly once. + /// /// See: http://www.rubicite.com/Tutorials/GeneticAlgorithms/CrossoverOperators/CycleCrossoverOperator.aspx /// public class CycleCrossoverManager : ICrossoverManager diff --git a/GeneticAlgorithm/Components/CrossoverManagers/OrderBasedCrossover.cs b/GeneticAlgorithm/Components/CrossoverManagers/OrderBasedCrossover.cs new file mode 100644 index 0000000..c67ab59 --- /dev/null +++ b/GeneticAlgorithm/Components/CrossoverManagers/OrderBasedCrossover.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using GeneticAlgorithm.Components.Chromosomes; +using GeneticAlgorithm.Components.Interfaces; +using GeneticAlgorithm.Interfaces; + +namespace GeneticAlgorithm.Components.CrossoverManagers +{ + /// + /// OrderBasedCrossover Works on chromosomes of type VectorChromosome<T>. + /// It assumes that both parents are of the same length, that every genome appears only once in each parent, + /// and that both parents contain the same genomes (but probably in different orders). + /// If one of these conditions isn't met, OrderBasedCrossover may throw an exception. + /// Also, the Equals method must be implemented for type T. + /// + /// In OrderBasedCrossover, several positions are selected at random from the second parent. + /// Let A be the list of elements at the selected indexes in parent2. + /// All elements that aren't A are copied as is from parent1. + /// The missing elements are added in the order in which they appear in parent2 + /// + /// In OrderBasedCrossover, the child is guaranteed to contain each genome exactly once. + /// + public class OrderBasedCrossover : ICrossoverManager + { + private readonly Random random = new Random(); + private readonly IMutationManager mutationManager; + private readonly IEvaluator evaluator; + + /// + /// OrderBasedCrossover Works on chromosomes of type VectorChromosome<T>. + /// It assumes that both parents are of the same length, that every genome appears only once in each parent, + /// and that both parents contain the same genomes (but probably in different orders). + /// If one of these conditions isn't met, OrderBasedCrossover may throw an exception. + /// + /// Also, the Equals method must be implemented for type T. + /// + public OrderBasedCrossover(IMutationManager mutationManager, IEvaluator evaluator) + { + this.mutationManager = mutationManager; + this.evaluator = evaluator; + } + + public IChromosome Crossover(IChromosome chromosome1, IChromosome chromosome2) + { + var vector1 = ((VectorChromosome)chromosome1).GetVector(); + var vector2 = ((VectorChromosome)chromosome2).GetVector(); + var length = vector1.Length; + var indexes = ProbabilityUtils.SelectKRandomNumbers(length, random.Next(length)); + + var elementsFromParent2 = new HashSet(); + var elementsFromParent2OrderedByIndex = new List(); + foreach (var index in indexes) + { + elementsFromParent2.Add(vector2[index]); + elementsFromParent2OrderedByIndex.Add(vector2[index]); + } + + var newVector = new T[length]; + for (int index = 0, addedElementsFromParent2 = 0; index < length; index++) + { + var elementInParent1 = vector1[index]; + if (!elementsFromParent2.Contains(elementInParent1)) + newVector[index] = elementInParent1; + else + { + newVector[index] = elementsFromParent2OrderedByIndex[addedElementsFromParent2]; + addedElementsFromParent2++; + } + } + + return new VectorChromosome(newVector, mutationManager, evaluator); + } + } +} diff --git a/GeneticAlgorithm/Components/CrossoverManagers/OrderCrossover.cs b/GeneticAlgorithm/Components/CrossoverManagers/OrderCrossover.cs index 148454f..26a57a9 100644 --- a/GeneticAlgorithm/Components/CrossoverManagers/OrderCrossover.cs +++ b/GeneticAlgorithm/Components/CrossoverManagers/OrderCrossover.cs @@ -41,34 +41,34 @@ public OrderCrossover(IMutationManager mutationManager, IEvaluator evaluator) public IChromosome Crossover(IChromosome chromosome1, IChromosome chromosome2) { - var vectorChromosome1 = (VectorChromosome) chromosome1; - var vectorChromosome2 = (VectorChromosome) chromosome2; - var length = vectorChromosome1.Length; + var vector1 = ((VectorChromosome) chromosome1).GetVector(); + var vector2 = ((VectorChromosome) chromosome2).GetVector(); + var length = vector1.Length; (var start, var end) = random.GetTwoRandomNumbers(length + 1); - var genomesFromChromosome1 = new List(); + var genomesFromChromosome1 = new HashSet(); for (int i = start; i < end; i++) - genomesFromChromosome1.Add(vectorChromosome1[i]); + genomesFromChromosome1.Add(vector1[i]); - T[] newVector = new T[length]; - int lastAddedIndexFromChromsome2 = 0; + var newVector = new T[length]; + var lastAddedIndexFromChromsome2 = 0; for (int i = 0; i < start; i++) { - while (genomesFromChromosome1.Contains(vectorChromosome2[lastAddedIndexFromChromsome2])) + while (genomesFromChromosome1.Contains(vector2[lastAddedIndexFromChromsome2])) lastAddedIndexFromChromsome2++; - newVector[i] = vectorChromosome2[lastAddedIndexFromChromsome2]; + newVector[i] = vector2[lastAddedIndexFromChromsome2]; lastAddedIndexFromChromsome2++; } for (int i = start; i < end; i++) - newVector[i] = vectorChromosome1[i]; + newVector[i] = vector1[i]; for (int i = end; i < length; i++) { - while (genomesFromChromosome1.Contains(vectorChromosome2[lastAddedIndexFromChromsome2])) + while (genomesFromChromosome1.Contains(vector2[lastAddedIndexFromChromsome2])) lastAddedIndexFromChromsome2++; - newVector[i] = vectorChromosome2[lastAddedIndexFromChromsome2]; + newVector[i] = vector2[lastAddedIndexFromChromsome2]; lastAddedIndexFromChromsome2++; } diff --git a/GeneticAlgorithm/Components/CrossoverManagers/PositionBasedCrossoverManager.cs b/GeneticAlgorithm/Components/CrossoverManagers/PositionBasedCrossoverManager.cs new file mode 100644 index 0000000..f0aac30 --- /dev/null +++ b/GeneticAlgorithm/Components/CrossoverManagers/PositionBasedCrossoverManager.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using GeneticAlgorithm.Components.Chromosomes; +using GeneticAlgorithm.Components.Interfaces; +using GeneticAlgorithm.Interfaces; + +namespace GeneticAlgorithm.Components.CrossoverManagers +{ + /// + /// PositionBasedCrossover Works on chromosomes of type VectorChromosome<T>. + /// It assumes that both parents are of the same length, that every genome appears only once in each parent, + /// and that both parents contain the same genomes (but probably in different orders). + /// If one of these conditions isn't met, PositionBasedCrossover may throw an exception. + /// Also, the Equals method must be implemented for type T. + /// + /// In PositionBasedCrossover, several positions are selected at random from the first parent. + /// The genomes in those positions are copied as-is from the first parent. + /// The rest of the genomes are coped from the second parent in order as long as the genome hasn't already been copied from parent1. + /// + /// In PositionBasedCrossover, the child is guaranteed to contain each genome exactly once. + /// + public class PositionBasedCrossoverManager : ICrossoverManager + { + private readonly Random random = new Random(); + private readonly IMutationManager mutationManager; + private readonly IEvaluator evaluator; + + /// + /// PositionBasedCrossover Works on chromosomes of type VectorChromosome<T>. + /// It assumes that both parents are of the same length, that every genome appears only once in each parent, + /// and that both parents contain the same genomes (but probably in different orders). + /// If one of these conditions isn't met, OrderBasedCrossover may throw an exception. + /// + /// Also, the Equals method must be implemented for type T. + /// + public PositionBasedCrossoverManager(IMutationManager mutationManager, IEvaluator evaluator) + { + this.mutationManager = mutationManager; + this.evaluator = evaluator; + } + + public IChromosome Crossover(IChromosome chromosome1, IChromosome chromosome2) + { + var vector1 = ((VectorChromosome)chromosome1).GetVector(); + var vector2 = ((VectorChromosome)chromosome2).GetVector(); + var length = vector1.Length; + var indexesToTakeFromParent1 = ProbabilityUtils.SelectKRandomNumbers(length, random.Next(length)); + + var genomesFromChromosome1 = new HashSet(); + var newVector = new T[length]; + foreach (var index in indexesToTakeFromParent1) + { + newVector[index] = vector1[index]; + genomesFromChromosome1.Add(vector1[index]); + } + + int lastAddedIndexFromChromsome2 = 0; + for (int i = 0; i < length; i++) + { + if (indexesToTakeFromParent1.Contains(i)) continue; + while (genomesFromChromosome1.Contains(vector2[lastAddedIndexFromChromsome2])) + lastAddedIndexFromChromsome2++; + + newVector[i] = vector2[lastAddedIndexFromChromsome2]; + lastAddedIndexFromChromsome2++; + } + + return new VectorChromosome(newVector, mutationManager, evaluator); + } + } +} diff --git a/GeneticAlgorithm/Components/CrossoverManagers/Utils.cs b/GeneticAlgorithm/Components/CrossoverManagers/Utils.cs index 2adbbaa..4491fb5 100644 --- a/GeneticAlgorithm/Components/CrossoverManagers/Utils.cs +++ b/GeneticAlgorithm/Components/CrossoverManagers/Utils.cs @@ -1,6 +1,4 @@ -using System; -using GeneticAlgorithm.Components.Chromosomes; -using GeneticAlgorithm.Exceptions; +using GeneticAlgorithm.Components.Chromosomes; using GeneticAlgorithm.Interfaces; namespace GeneticAlgorithm.Components.CrossoverManagers @@ -8,7 +6,7 @@ namespace GeneticAlgorithm.Components.CrossoverManagers static class Utils { /// - /// Returns the shroter chromorose as the first, and the longer chromosome second + /// Returns the shorter chromosome as the first, and the longer chromosome second /// public static (VectorChromosome, VectorChromosome) OrderChromosomes(IChromosome chromosome1, IChromosome chromosome2) @@ -19,13 +17,5 @@ public static (VectorChromosome, VectorChromosome) OrderChromosomes(ICh ? (vectorChromosome1, vectorChromosome2) : (vectorChromosome2, vectorChromosome1); } - - public static (int, int) GetTwoRandomNumbers(this Random random, int max) - { - var num1 = random.Next(max); - var num2 = random.Next(max); - - return (Math.Min(num1, num2), Math.Max(num1, num2)); - } } } diff --git a/GeneticAlgorithm/Components/MutationManagers/DisplacementMutationBase.cs b/GeneticAlgorithm/Components/MutationManagers/DisplacementMutationBase.cs new file mode 100644 index 0000000..e6ce34f --- /dev/null +++ b/GeneticAlgorithm/Components/MutationManagers/DisplacementMutationBase.cs @@ -0,0 +1,50 @@ +using System; +using GeneticAlgorithm.Components.Interfaces; + +namespace GeneticAlgorithm.Components.MutationManagers +{ + /// + /// A base class that will be used for DisplacementMutationManager and InversionMutationManager. + /// Both managers removes a stretch of genomes from the chromosome, and inserts them in a new location. + /// The difference is that while DisplacementMutationManager just inserts the stretch at a new location, + /// InversionMutationManager reverses the stretch before inserting it. + /// + /// For instance, if the original chromosome was 1 2 3 4 5 6 7. We might chose to remove the stretch 3 4 5 and insert it at index 1. + /// In this case DisplacementMutationManager 1 3 4 5 2 6 7, while InversionMutationManager would give 1 5 4 3 2 6 7. + /// + class DisplacementMutationBase : IMutationManager + { + private readonly Random random = new Random(); + private readonly bool inversionSttretch; + + public DisplacementMutationBase(bool inversionSttretch) + { + this.inversionSttretch = inversionSttretch; + } + + public T[] Mutate(T[] vector) + { + (var start, var end) = random.GetTwoRandomNumbers(vector.Length + 1); + var insertionIndex = random.Next(vector.Length - (end - start)); + var vectorWithoutStretch = new T[vector.Length - (end - start)]; + for (int i = 0; i < start; i++) + vectorWithoutStretch[i] = vector[i]; + for (int addTo = start, addFrom = end; addFrom < vector.Length; addFrom++, addTo++) + vectorWithoutStretch[addTo] = vector[addFrom]; + + var newVector = new T[vector.Length]; + for (int i = 0; i < insertionIndex; i++) + newVector[i] = vectorWithoutStretch[i]; + if (inversionSttretch) + for (int addTo = insertionIndex, addFrom = end - 1; addFrom >= start; addFrom--, addTo++) + newVector[addTo] = vector[addFrom]; + else + for (int addTo = insertionIndex, addFrom = start; addFrom < end; addFrom++, addTo++) + newVector[addTo] = vector[addFrom]; + for (int addTo = insertionIndex + (end - start), addFrom = insertionIndex; addTo < vector.Length; addFrom++, addTo++) + newVector[addTo] = vectorWithoutStretch[addFrom]; + + return newVector; + } + } +} diff --git a/GeneticAlgorithm/Components/MutationManagers/DisplacementMutationManager.cs b/GeneticAlgorithm/Components/MutationManagers/DisplacementMutationManager.cs new file mode 100644 index 0000000..ea9e7ca --- /dev/null +++ b/GeneticAlgorithm/Components/MutationManagers/DisplacementMutationManager.cs @@ -0,0 +1,18 @@ +using GeneticAlgorithm.Components.Interfaces; + +namespace GeneticAlgorithm.Components.MutationManagers +{ + /// + /// Removes a stretch of genomes from the chromosome, and inserts them in a new location. + /// For instance, if the original chromosome was 1 2 3 4 5 6 7. We might chose to remove the stretch 3 4 5 and insert it at index 1. + /// This would result in the chromosome 1 3 4 5 2 6 7. + /// + /// DisplacementMutationManager guarantees that if the original chromosome contained each genome exactly once, so will the mutated chromosome. + /// + public class DisplacementMutationManager : IMutationManager + { + private readonly DisplacementMutationBase displacementMutationBase = new DisplacementMutationBase(false); + + public T[] Mutate(T[] vector) => displacementMutationBase.Mutate(vector); + } +} diff --git a/GeneticAlgorithm/Components/MutationManagers/DoubleBoundaryMutationManager.cs b/GeneticAlgorithm/Components/MutationManagers/DoubleBoundaryMutationManager.cs index 81c71cb..556d2ae 100644 --- a/GeneticAlgorithm/Components/MutationManagers/DoubleBoundaryMutationManager.cs +++ b/GeneticAlgorithm/Components/MutationManagers/DoubleBoundaryMutationManager.cs @@ -4,7 +4,7 @@ namespace GeneticAlgorithm.Components.MutationManagers { /// /// This mutation operator replaces the genome with either lower or upper bound randomly. - /// The probability of a bit being replaced is 1 / . + /// The probability of a bit being replaced is 1 / vector-length. /// public class DoubleBoundaryMutationManager : IMutationManager { diff --git a/GeneticAlgorithm/Components/MutationManagers/DoubleUniformMutationManager.cs b/GeneticAlgorithm/Components/MutationManagers/DoubleUniformMutationManager.cs index cff8ab2..946d207 100644 --- a/GeneticAlgorithm/Components/MutationManagers/DoubleUniformMutationManager.cs +++ b/GeneticAlgorithm/Components/MutationManagers/DoubleUniformMutationManager.cs @@ -5,7 +5,7 @@ namespace GeneticAlgorithm.Components.MutationManagers { /// /// This mutation operator replaces the genome with a random value between the lower and upper bound. - /// The probability of a bit being replaced is 1 / . + /// The probability of a bit being replaced is 1 / vector-length. /// public class DoubleUniformMutationManager : IMutationManager { diff --git a/GeneticAlgorithm/Components/MutationManagers/SingleSwapMutationManager.cs b/GeneticAlgorithm/Components/MutationManagers/ExchangeMutationManager.cs similarity index 67% rename from GeneticAlgorithm/Components/MutationManagers/SingleSwapMutationManager.cs rename to GeneticAlgorithm/Components/MutationManagers/ExchangeMutationManager.cs index 0178a9b..618c0f9 100644 --- a/GeneticAlgorithm/Components/MutationManagers/SingleSwapMutationManager.cs +++ b/GeneticAlgorithm/Components/MutationManagers/ExchangeMutationManager.cs @@ -4,9 +4,10 @@ namespace GeneticAlgorithm.Components.MutationManagers { /// - /// Swaps two genomes in the chromosome + /// Swaps two genomes in the chromosome. + /// ExchangeMutationManager guarantees that if the original chromosome contained each genome exactly once, so will the mutated chromosome. /// - public class SingleSwapMutationManager : IMutationManager + public class ExchangeMutationManager : IMutationManager { private readonly Random random = new Random(); diff --git a/GeneticAlgorithm/Components/MutationManagers/InsertionMutationManager.cs b/GeneticAlgorithm/Components/MutationManagers/InsertionMutationManager.cs new file mode 100644 index 0000000..488b475 --- /dev/null +++ b/GeneticAlgorithm/Components/MutationManagers/InsertionMutationManager.cs @@ -0,0 +1,44 @@ +using System; +using GeneticAlgorithm.Components.Interfaces; + +namespace GeneticAlgorithm.Components.MutationManagers +{ + /// + /// Removes a random genome and inserts it at a new location. + /// InsertionMutationManager guarantees that if the original chromosome contained each genome exactly once, so will the mutated chromosome. + /// + public class InsertionMutationManager : IMutationManager + { + private readonly Random random = new Random(); + + public T[] Mutate(T[] vector) + { + var toRemove = random.Next(vector.Length); + var insertAt = random.Next(vector.Length); + + var newVector = new T[vector.Length]; + if (toRemove < insertAt) + { + for (int i = 0; i < toRemove; i++) + newVector[i] = vector[i]; + for (int i = toRemove; i < insertAt; i++) + newVector[i] = vector[i + 1]; + newVector[insertAt] = vector[toRemove]; + for (int i = insertAt + 1; i < vector.Length; i++) + newVector[i] = vector[i]; + } + else + { + for (int i = 0; i < insertAt; i++) + newVector[i] = vector[i]; + newVector[insertAt] = vector[toRemove]; + for (int i = insertAt + 1; i <= toRemove; i++) + newVector[i] = vector[i - 1]; + for (int i = toRemove + 1; i < vector.Length; i++) + newVector[i] = vector[i]; + } + + return newVector; + } + } +} diff --git a/GeneticAlgorithm/Components/MutationManagers/IntBoundaryMutationManager.cs b/GeneticAlgorithm/Components/MutationManagers/IntBoundaryMutationManager.cs index f21bf49..fe5ee94 100644 --- a/GeneticAlgorithm/Components/MutationManagers/IntBoundaryMutationManager.cs +++ b/GeneticAlgorithm/Components/MutationManagers/IntBoundaryMutationManager.cs @@ -4,7 +4,7 @@ namespace GeneticAlgorithm.Components.MutationManagers { /// /// This mutation operator replaces the genome with either lower or upper bound randomly. - /// The probability of a bit being replaced is 1 / . + /// The probability of a bit being replaced is 1 / vector-length. /// public class IntBoundaryMutationManager : IMutationManager { diff --git a/GeneticAlgorithm/Components/MutationManagers/IntUniformMutationManager.cs b/GeneticAlgorithm/Components/MutationManagers/IntUniformMutationManager.cs index a673f1b..f0bbc9b 100644 --- a/GeneticAlgorithm/Components/MutationManagers/IntUniformMutationManager.cs +++ b/GeneticAlgorithm/Components/MutationManagers/IntUniformMutationManager.cs @@ -5,7 +5,7 @@ namespace GeneticAlgorithm.Components.MutationManagers { /// /// This mutation operator replaces the genome with a random value between the lower and upper bound. - /// The probability of a bit being replaced is 1 / . + /// The probability of a bit being replaced is 1 / vector-length. /// public class IntUniformMutationManager : IMutationManager { diff --git a/GeneticAlgorithm/Components/MutationManagers/InversionMutationManager.cs b/GeneticAlgorithm/Components/MutationManagers/InversionMutationManager.cs new file mode 100644 index 0000000..f0ca2be --- /dev/null +++ b/GeneticAlgorithm/Components/MutationManagers/InversionMutationManager.cs @@ -0,0 +1,18 @@ +using GeneticAlgorithm.Components.Interfaces; + +namespace GeneticAlgorithm.Components.MutationManagers +{ + /// + /// Removes a stretch of genomes from the chromosome, inverses them, and inserts them in a new location. + /// For instance, if the original chromosome was 1 2 3 4 5 6 7. We might chose to remove the stretch 3 4 5 and insert it at index 1. + /// This would result in the chromosome 1 5 4 3 2 6 7. + /// + /// DisplacementMutationManager guarantees that if the original chromosome contained each genome exactly once, so will the mutated chromosome. + /// + public class InversionMutationManager : IMutationManager + { + private readonly DisplacementMutationBase displacementMutationBase = new DisplacementMutationBase(true); + + public T[] Mutate(T[] vector) => displacementMutationBase.Mutate(vector); + } +} diff --git a/GeneticAlgorithm/Components/MutationManagers/ScrambleMutationManager.cs b/GeneticAlgorithm/Components/MutationManagers/ScrambleMutationManager.cs new file mode 100644 index 0000000..8bd4c1f --- /dev/null +++ b/GeneticAlgorithm/Components/MutationManagers/ScrambleMutationManager.cs @@ -0,0 +1,31 @@ +using System; +using System.Linq; +using GeneticAlgorithm.Components.Interfaces; + +namespace GeneticAlgorithm.Components.MutationManagers +{ + /// + /// Selects a random two cut points in the string, and scrambles the substring between these two cut points. + /// ScrambleMutationManager guarantees that if the original chromosome contained each genome exactly once, so will the mutated chromosome. + /// + public class ScrambleMutationManager : IMutationManager + { + private readonly Random random = new Random(); + + public T[] Mutate(T[] vector) + { + (var start, var end) = random.GetTwoRandomNumbers(vector.Length + 1); + var scrambledGenomes = vector.Skip(start).Take(end - start).ToArray().Shuffle(random); + + var newVector = new T[vector.Length]; + for (int i = 0; i < start; i++) + newVector[i] = vector[i]; + for (int addTo = start, addFrom = 0; addTo < end; addTo++, addFrom++) + newVector[addTo] = scrambledGenomes[addFrom]; + for (int i = end; i < vector.Length; i++) + newVector[i] = vector[i]; + + return newVector; + } + } +} diff --git a/GeneticAlgorithm/Components/MutationManagers/SimpleInversionMutationManager.cs b/GeneticAlgorithm/Components/MutationManagers/SimpleInversionMutationManager.cs new file mode 100644 index 0000000..c73005f --- /dev/null +++ b/GeneticAlgorithm/Components/MutationManagers/SimpleInversionMutationManager.cs @@ -0,0 +1,29 @@ +using System; +using GeneticAlgorithm.Components.Interfaces; + +namespace GeneticAlgorithm.Components.MutationManagers +{ + /// + /// Selects a random two cut points in the string, and reverses the substring between these two cut points. + /// SimpleInversionMutationManager guarantees that if the original chromosome contained each genome exactly once, so will the mutated chromosome. + /// + public class SimpleInversionMutationManager : IMutationManager + { + private readonly Random random = new Random(); + + public T[] Mutate(T[] vector) + { + (var start, var end) = random.GetTwoRandomNumbers(vector.Length + 1); + + var newVector = new T[vector.Length]; + for (int i = 0; i < start; i++) + newVector[i] = vector[i]; + for (int addTo = start, addFrom = end - 1; addTo < end; addTo++, addFrom--) + newVector[addTo] = vector[addFrom]; + for (int i = end; i < vector.Length; i++) + newVector[i] = vector[i]; + + return newVector; + } + } +} diff --git a/GeneticAlgorithm/GeneticAlgorithm.nuspec b/GeneticAlgorithm/GeneticAlgorithm.nuspec index edf9158..04a30c3 100644 --- a/GeneticAlgorithm/GeneticAlgorithm.nuspec +++ b/GeneticAlgorithm/GeneticAlgorithm.nuspec @@ -2,7 +2,7 @@ GeneticAlgorithm - 1.3.1 + 1.3.2 A parallel Genetic Algorithm Engine A parallel Genetic Algorithm Engine. GeneticAlgorithm was created to be easily customized and simple to use. Zvi Rosenfeld diff --git a/GeneticAlgorithm/SelectionStrategies/ChromosomePool.cs b/GeneticAlgorithm/SelectionStrategies/ChromosomePool.cs index 517bdc7..50df41c 100644 --- a/GeneticAlgorithm/SelectionStrategies/ChromosomePool.cs +++ b/GeneticAlgorithm/SelectionStrategies/ChromosomePool.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using GeneticAlgorithm.Interfaces; namespace GeneticAlgorithm.SelectionStrategies @@ -14,31 +13,15 @@ namespace GeneticAlgorithm.SelectionStrategies /// public class ChromosomePool { - private IChromosome[] chromosomes; + private readonly Random random = new Random(); + private readonly IChromosome[] chromosomes; private int counter = -1; public ChromosomePool(IChromosome[] chromosomes) { - this.chromosomes = Shuffle(chromosomes); + this.chromosomes = chromosomes.Shuffle(random); } - private IChromosome[] Shuffle(IChromosome[] chromosome) - { - var random = new Random(); - var n = chromosome.Length; - var shuffledChromosomes = chromosome.ToArray(); // Clone - while (n > 1) - { - n--; - int k = random.Next(n + 1); - IChromosome value = shuffledChromosomes[k]; - shuffledChromosomes[k] = shuffledChromosomes[n]; - shuffledChromosomes[n] = value; - } - - return shuffledChromosomes; - } - /// /// Note that GetChromosome can only be called chromosomes.Length times /// diff --git a/GeneticAlgorithm/SelectionStrategies/StochasticUniversalSampling.cs b/GeneticAlgorithm/SelectionStrategies/StochasticUniversalSampling.cs index ef2a7b4..5a8337d 100644 --- a/GeneticAlgorithm/SelectionStrategies/StochasticUniversalSampling.cs +++ b/GeneticAlgorithm/SelectionStrategies/StochasticUniversalSampling.cs @@ -42,7 +42,7 @@ public void SetPopulation(Population population, int requestedChromosomes) private void FillPool(int requestedChromosomes, IChromosome[] chromosomes, double[] evaluations) { var pointer = random.NextDouble() / requestedChromosomes; - var increment = 1.0 / (double) requestedChromosomes; + var increment = 1.0 / requestedChromosomes; var sum = 0.0; var chromosomeIndex = -1; var poolChromosomes = new IChromosome[requestedChromosomes]; diff --git a/README.md b/README.md index 20e8cc0..8cbb45a 100644 --- a/README.md +++ b/README.md @@ -287,8 +287,7 @@ VectorChromosome expects an [IMutationManager](#mutationmanagers) and [IEvalu You can create your own MutationManager by implementing the IMutationManager interface, or use an existing managers. Existing managers: -- [SingleSwapMutationManager\](/GeneticAlgorithm/Components/MutationManagers/SingleSwapMutationManager.cs): Swaps two genomes in the chromosome. -- [BitStringMutationManager](/GeneticAlgorithm/Components/MutationManagers/BitStringMutationManager.cs): This mutation only works on binary chromosomes (represented as type VectorChromosome). It flips bits at random (that is replaces 1 with 0 and 0 with 1). The probability of a bit being flipped is 1 / \\. +- [BitStringMutationManager](/GeneticAlgorithm/Components/MutationManagers/BitStringMutationManager.cs): This mutation only works on binary chromosomes (represented as type VectorChromosome\). It flips bits at random (that is replaces 1 with 0 and 0 with 1). The probability of a bit being flipped is 1 / \\. - [IntBoundaryMutationManager](/GeneticAlgorithm/Components/MutationManagers/IntBoundaryMutationManager.cs): This mutation operator replaces the genome with either lower or upper bound randomly (works only on integer-vector chromosomes). The probability of a bit being replaced is 1 / \\. - [DoubleBoundaryMutationManager](/GeneticAlgorithm/Components/MutationManagers/DoubleBoundaryMutationManager.cs): This mutation operator replaces the genome with either lower or upper bound randomly (works only on double-vector chromosomes). The probability of a bit being replaced is 1 / \\. - [IntUniformMutationManager](/GeneticAlgorithm/Components/MutationManagers/IntUniformMutationManager.cs): This mutation operator replaces the genome with a random value between the lower and upper bound (works only on integer-vector chromosomes). The probability of a bit being replaced is 1 / \\. @@ -298,6 +297,17 @@ Existing managers: - [IntShrinkMutationManager](/GeneticAlgorithm/Components/MutationManagers/IntShrinkMutationManager.cs): This operator adds a random number taken from a Gaussian distribution with mean equal to the original genome (works only on integer-vector chromosomes). If it falls outside of the user-specified lower or upper bounds for that gene, the new gene value is clipped. - [DoubleShrinkMutationManager](/GeneticAlgorithm/Components/MutationManagers/DoubleShrinkMutationManager.cs): This operator adds a random number taken from a Gaussian distribution with mean equal to the original genome (works only on double-vector chromosomes). If it falls outside of the user-specified lower or upper bounds for that gene, the new gene value is clipped. +In some problems, it's impotent to insure that all chromosomes contain each genome exactly once. +The following list contains mutation managers with the guarantee that if the original chromosome contained each genome exactly once, so will the mutated chromosome. + +- [ExchangeMutationManager\ (EM)](/GeneticAlgorithm/Components/MutationManagers/ExchangeMutationManager.cs): Swaps two genomes in the chromosome (available since 1.3.2). +- [SingleSwapMutationManager\](/GeneticAlgorithm/Components/MutationManagers/SingleSwapMutationManager.cs): Swaps two genomes in the chromosome (available only in 1.3.1 - in 1.3.2 this was renamed to ExchangeMutationManager). +- [DisplacementMutationManager\ (DM)](/GeneticAlgorithm/Components/MutationManagers/DisplacementMutationManager.cs): Removes a stretch of genomes from the chromosome, and inserts them in a new location. (Available since 1.3.2). +- [InversionMutationManager\ (DM)](/GeneticAlgorithm/Components/MutationManagers/InversionMutationManager.cs): Like DisplacementMutationManager, only that this mutation inverts the stretch before re-inserting it. (Available since 1.3.2). +- [InsertionMutationManager\ (ISM)](/GeneticAlgorithm/Components/MutationManagers/InsertionMutationManager.cs): Removes a random genome and inserts it at a new location. (Available since 1.3.2). +- [SimpleInversionMutationManager\ (SIM)](/GeneticAlgorithm/Components/MutationManagers/SimpleInversionMutationManager.cs): Selects a random two cut points in the string, and reverses the substring between these two cut points. (Available since 1.3.2). +- [ScrambleMutationManager\ (SIM)](/GeneticAlgorithm/Components/MutationManagers/ScrambleMutationManager.cs): Selects a random two cut points in the string, and scrambles the substring between these two cut points. (Available since 1.3.2). + ### CrossoverManagers The CrossoverManagers are implementations of the [ICrossoverManager](#icrossovermanager) interface. @@ -311,9 +321,12 @@ The following list contains crossover managers that *must* be used on chromosome There managers will ensure that the children also contain each genome exactly once. Note that for these crossover managers to work, the Equals method must be implemented for type T. -- [OrderCrossover\](/GeneticAlgorithm/Components/CrossoverManagers/OrderCrossover.cs): See [this](https://stackoverflow.com/questions/26518393/order-crossover-ox-genetic-algorithm/26521576). Ordered crossover Works on chromosomes of type VectorChromosome\. In ordered crossover, we randomly select a subset of the first parent string and then fill the remainder of the route with the genes from the second parent in the order in which they appear. This insures that if no genome was repeated in the parents, no genome will be repeated in the child either. -- [PartiallyMappedCrossover\](/GeneticAlgorithm/Components/CrossoverManagers/PartiallyMappedCrossover.cs): See [this](http://www.rubicite.com/Tutorials/GeneticAlgorithms/CrossoverOperators/PMXCrossoverOperator.aspx). -- [CycleCrossoverManager\](/GeneticAlgorithm/Components/CrossoverManagers/CycleCrossoverManager.cs): See [this](http://www.rubicite.com/Tutorials/GeneticAlgorithms/CrossoverOperators/CycleCrossoverOperator.aspx). The Cycle Crossover operator identifies a number of so-called cycles between two parent chromosomes. Then, to form Child 1, cycle one is copied from parent 1, cycle 2 from parent 2, cycle 3 from parent 1, and so on. +- [OrderCrossover\ (OX1)](/GeneticAlgorithm/Components/CrossoverManagers/OrderCrossover.cs): See [this](https://stackoverflow.com/questions/26518393/order-crossover-ox-genetic-algorithm/26521576). Ordered crossover Works on chromosomes of type VectorChromosome\. In ordered crossover, we randomly select a subset of the first parent string and then fill the remainder of the route with the genes from the second parent in the order in which they appear. This insures that if no genome was repeated in the parents, no genome will be repeated in the child either. (Available since 1.3.1) +- [OrderBasedCrossover\ (OX2)](/GeneticAlgorithm/Components/CrossoverManagers/OrderBasedCrossover.cs): In OrderBasedCrossover, several positions are selected at random from the second parent. Let A be the list of elements at the selected indexes in parent2. All elements that aren't A are copied as is from parent1. The missing elements are added in the order in which they appear in parent2(Available since 1.3.2) +- [PartiallyMappedCrossover\ (PMX)](/GeneticAlgorithm/Components/CrossoverManagers/PartiallyMappedCrossover.cs): See [this](http://www.rubicite.com/Tutorials/GeneticAlgorithms/CrossoverOperators/PMXCrossoverOperator.aspx). (Available since 1.3.1) +- [CycleCrossoverManager\ (CX)](/GeneticAlgorithm/Components/CrossoverManagers/CycleCrossoverManager.cs): See [this](http://www.rubicite.com/Tutorials/GeneticAlgorithms/CrossoverOperators/CycleCrossoverOperator.aspx). The Cycle Crossover operator identifies a number of so-called cycles between two parent chromosomes. Then, to form the child, cycle one is copied from parent 1, cycle 2 from parent 2, cycle 3 from parent 1, and so on. (Available since 1.3.1) +- [PositionBasedCrossoverManager\ (POS)](/GeneticAlgorithm/Components/CrossoverManagers/PositionBasedCrossoverManager.cs): In PositionBasedCrossover, several positions are selected at random from the first parent. The genomes in those positions are copied as-is from the first parent. The rest of the genomes are coped from the second parent in order as long as the genome hasn't already been copied from parent1. (Available since 1.3.2) +- [AlternatingPositionCrossover\ (AP)](/GeneticAlgorithm/Components/CrossoverManagers/AlternatingPositionCrossover.cs): In AlternatingPositionCrossover, we alternately select the next element of the first parent and the next element of the second parent, omitting the elements already present in the offspring. This guarantees that the child contains each genome exactly once.(Available since 1.3.2) ### PopulationGenerators @@ -322,7 +335,7 @@ PopulationGenerators are implementations of the [IPopulationGenerator](#ipopulat - [IntVectorChromosomePopulationGenerator](/GeneticAlgorithm/Components/PopulationGenerators/IntVectorChromosomePopulationGenerator.cs): Generates a population of type VectorChromosome\ within some min and max bounds. - [DoubleVectorChromosomePopulationGenerator](/GeneticAlgorithm/Components/PopulationGenerators/DoubleVectorChromosomePopulationGenerator.cs): Generates a population of type VectorChromosome\ within some min and max bounds. - [BinaryVectorChromosomePopulationGenerator](/GeneticAlgorithm/Components/PopulationGenerators/BinaryVectorChromosomePopulationGenerator.cs): Generates binary chromosomes (chromosomes of type VectorChromosome\). -- [AllElementsVectorChromosomePopulationGenerator\](/GeneticAlgorithm/Components/PopulationGenerators/AllElementsVectorChromosomePopulationGenerator.cs): Generates a population of chromosomes of type VectorChromosome\ in which each chromosome contains every element exactly once (a list of the elements is provided in the constructor). +- [AllElementsVectorChromosomePopulationGenerator\](/GeneticAlgorithm/Components/PopulationGenerators/AllElementsVectorChromosomePopulationGenerator.cs): Generates a population of chromosomes of type VectorChromosome\ in which each chromosome contains every element exactly once (a list of the elements is provided in the constructor). (Available since 1.3.1) ### Example of Using Components diff --git a/TravellingSalesman/Program.cs b/TravellingSalesman/Program.cs index 1d3d845..8330c16 100644 --- a/TravellingSalesman/Program.cs +++ b/TravellingSalesman/Program.cs @@ -33,7 +33,7 @@ static void Main(string[] args) { Console.WriteLine("Started!"); - IMutationManager mutationManager = new SingleSwapMutationManager(); + IMutationManager mutationManager = new ExchangeMutationManager(); IEvaluator evaluator = new DistanceEvaluator(locations); ICrossoverManager crossoverManager = new OrderCrossover(mutationManager, evaluator); IPopulationGenerator populationGenerator =