Skip to content

Commit

Permalink
Components (#6)
Browse files Browse the repository at this point in the history
* Renamed IMutationManager to IMutationProbabilityManager

* Added ProbabilityUtils

* Small fixes

* Initial components

* Added components PopulationGenerators

* Added SelectKRandomNumbers method

* Added K_PointCrossover

* Added SinglePointCrossoverManager

* Added UniformCrossoverManager

* Added BitStringMutationManager

* Added UniformMutationManager

* Removed NumberVector project

* Added documentation

* Update README.md

* Added GaussianMutationManager

* Added DoubleVectorChromosomePopulationGenerator

* Added "Int" to the int mutation managers

* Added DoubleBoundaryMutationManagerTest

* Added DoubleGaussianMutationManager and DoubleUniformMutationManager

* Changed Bit Vector Chromosomes to use bools

* Fixed bug

* Added Shrink Mutation Managers
  • Loading branch information
ZviRosenfeld authored Nov 9, 2019
1 parent 266a2b5 commit caee33b
Show file tree
Hide file tree
Showing 52 changed files with 1,605 additions and 189 deletions.
6 changes: 2 additions & 4 deletions EnvironmentGui/CrossoverManager.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using System;
using GeneticAlgorithm;
using GeneticAlgorithm.Interfaces;

namespace Environment
{
class CrossoverManager : ICrossoverManager
{
private readonly Random random = new Random();

public IChromosome Crossover(IChromosome chromosome1, IChromosome chromosome2)
{
var type1 = ((MyChromosome) chromosome1).Type;
Expand All @@ -17,7 +15,7 @@ public IChromosome Crossover(IChromosome chromosome1, IChromosome chromosome2)
if (type1 == ChromosomeType.Oc2Producer && type2 == ChromosomeType.Oc2Producer)
return new MyChromosome(ChromosomeType.Oc2Producer);

return new MyChromosome(random.NextDouble() < 0.5 ? ChromosomeType.OProducer : ChromosomeType.Oc2Producer);
return new MyChromosome(ProbabilityUtils.P(0.5) ? ChromosomeType.OProducer : ChromosomeType.Oc2Producer);
}
}
}
2 changes: 0 additions & 2 deletions EnvironmentGui/MyChromosome.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ namespace Environment
{
class MyChromosome : IChromosome
{
private readonly Random random = new Random();

public ChromosomeType Type { get; private set; }

public MyChromosome(ChromosomeType type)
Expand Down
5 changes: 2 additions & 3 deletions EnvironmentGui/PopulationGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
using System;
using System.Collections.Generic;
using GeneticAlgorithm;
using GeneticAlgorithm.Interfaces;

namespace Environment
{
class PopulationGenerator : IPopulationGenerator
{
private readonly Random random = new Random();

public IEnumerable<IChromosome> GeneratePopulation(int size)
{
var chromosomes = new IChromosome[size];
for (int i = 0; i < size; i++)
chromosomes[i] = new MyChromosome(random.NextDouble() < 0.5
chromosomes[i] = new MyChromosome(ProbabilityUtils.P(0.5)
? ChromosomeType.OProducer
: ChromosomeType.Oc2Producer);

Expand Down
13 changes: 13 additions & 0 deletions GUI/BasicEvaluator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Linq;
using GeneticAlgorithm.Components.Chromosomes;
using GeneticAlgorithm.Components.Interfaces;
using GeneticAlgorithm.Interfaces;

namespace GUI
{
class BasicEvaluator : IEvaluator
{
public double Evaluate(IChromosome chromosome) =>
((VectorChromosome<int>) chromosome).GetVector().Sum();
}
}
5 changes: 1 addition & 4 deletions GUI/GUI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BasicEvaluator.cs" />
<Compile Include="DoubleInputBox.cs">
<SubType>UserControl</SubType>
</Compile>
Expand Down Expand Up @@ -94,10 +95,6 @@
<Project>{5fadb04c-ee9d-4169-81a1-441ff61da671}</Project>
<Name>GeneticAlgorithm</Name>
</ProjectReference>
<ProjectReference Include="..\NumberVector\NumberVector.csproj">
<Project>{e84d6bd7-ff0d-4125-9e5c-36462247613a}</Project>
<Name>NumberVector</Name>
</ProjectReference>
<ProjectReference Include="..\UserControls\UserControls.csproj">
<Project>{77d37cc0-b19f-46a4-96c0-b9e49c3daf5e}</Project>
<Name>UserControls</Name>
Expand Down
17 changes: 12 additions & 5 deletions GUI/MainForm.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
using System.Windows.Forms;
using GeneticAlgorithm;
using GreatestVectorTests;
using GeneticAlgorithm.Components.CrossoverManagers;
using GeneticAlgorithm.Components.MutationManagers;
using GeneticAlgorithm.Components.PopulationGenerators;

namespace GUI
{
public partial class MainForm : Form
{
private const int POPULATION_SIZE = 20;
private const int VECTOR_SIZE = 10;
private const int GENERATION = int.MaxValue;


Expand All @@ -18,10 +21,14 @@ public MainForm()

private void InitializeEngine()
{
var engineBuilder = new GeneticSearchEngineBuilder(POPULATION_SIZE, GENERATION,
new NumberVectorCrossoverManager(),
new NumberVectorPopulationGenerator()).SetMutationProbability(MutationInputBox.GetValue)
.SetElitePercentage(ElitismInputBox.GetValue);
var mutationManager = new IntUniformMutationManager(0, 100);
var evaluator = new BasicEvaluator();
var populationGenerator =
new IntVectorChromosomePopulationGenerator(VECTOR_SIZE, 0, 1, mutationManager, evaluator);
var crossoverManager = new SinglePointCrossoverManager<int>(mutationManager, evaluator);
var engineBuilder =
new GeneticSearchEngineBuilder(POPULATION_SIZE, GENERATION, crossoverManager, populationGenerator)
.SetMutationProbability(MutationInputBox.GetValue).SetElitePercentage(ElitismInputBox.GetValue);
searchRunner1.SetEngineBuilder(engineBuilder);
}

Expand Down
3 changes: 0 additions & 3 deletions GUI/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace GUI
Expand Down
10 changes: 5 additions & 5 deletions GeneticAlgorithm.UnitTests/ChildrenGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public void TestMutationsHappen(double mutationProbability)
var crossoverManager = A.Fake<ICrossoverManager>();
A.CallTo(() => crossoverManager.Crossover(A<IChromosome>._, A<IChromosome>._))
.ReturnsLazily((IChromosome c1, IChromosome c2) => c1);
var childrenGenerator = new ChildrenGenerator(crossoverManager, new BassicMutationManager(mutationProbability), new RouletteWheelSelection());
var childrenGenerator = new ChildrenGenerator(crossoverManager, new BassicMutationProbabilityManager(mutationProbability), new RouletteWheelSelection());
childrenGenerator.GenerateChildren(population, populationSize, 0, null);

const double errorMargin = 0.05;
Expand All @@ -44,7 +44,7 @@ public void RetusnRightNumberOfChromosomes(int childrenCount)
{
const int count = 1500;
var crossoverManager = A.Fake<ICrossoverManager>();
var childrenGenerator = new ChildrenGenerator(crossoverManager, new BassicMutationManager(0), new RouletteWheelSelection());
var childrenGenerator = new ChildrenGenerator(crossoverManager, new BassicMutationProbabilityManager(0), new RouletteWheelSelection());
var children = childrenGenerator.GenerateChildren(GetPopulation(count), childrenCount, 0, null);
Assert.AreEqual(childrenCount, children.Length, "Didn't get enough children");
foreach (var chromosome in children)
Expand All @@ -57,7 +57,7 @@ public void RetusnRightNumberOfChromosomes(int childrenCount)
[ExpectedException(typeof(BadMutationProbabilityException))]
public void BadMutationProbability_ThrowException(double probability)
{
var mutationManager = A.Fake<IMutationManager>();
var mutationManager = A.Fake<IMutationProbabilityManager>();
A.CallTo(() => mutationManager.MutationProbability(A<Population>._, A<IEnvironment>._, A<int>._))
.Returns(probability);

Expand All @@ -71,7 +71,7 @@ public void BadMutationProbability_ThrowException(double probability)
[DataRow(-1)]
public void RequestBadNumberOfChildren_ThrowsException(int childrenCount)
{
var childrenGenerator = new ChildrenGenerator(A.Fake<ICrossoverManager>(), new BassicMutationManager(0),
var childrenGenerator = new ChildrenGenerator(A.Fake<ICrossoverManager>(), new BassicMutationProbabilityManager(0),
new RouletteWheelSelection());
childrenGenerator.GenerateChildren(GetPopulation(1), childrenCount, 0, null);
}
Expand All @@ -83,7 +83,7 @@ public void SelectionStrategyReturnsNull_ThrowsException()
{
var selectionStrategy = A.Fake<ISelectionStrategy>();
A.CallTo(() => selectionStrategy.SelectChromosome()).Returns(null);
var childrenGenerator = new ChildrenGenerator(A.Fake<ICrossoverManager>(), new BassicMutationManager(0),
var childrenGenerator = new ChildrenGenerator(A.Fake<ICrossoverManager>(), new BassicMutationProbabilityManager(0),
selectionStrategy);
childrenGenerator.GenerateChildren(GetPopulation(1), 1, 0, null);
}, typeof(GeneticAlgorithmException));
Expand Down
156 changes: 156 additions & 0 deletions GeneticAlgorithm.UnitTests/Components/CrossoverManagerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
using System.Collections.Generic;
using System.Linq;
using FakeItEasy;
using GeneticAlgorithm.Components.Chromosomes;
using GeneticAlgorithm.Components.CrossoverManagers;
using GeneticAlgorithm.Components.Interfaces;
using GeneticAlgorithm.Components.PopulationGenerators;
using GeneticAlgorithm.Interfaces;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace GeneticAlgorithm.UnitTests.Components
{
[TestClass]
public class CrossoverManagerTests
{
private const int TEST_RUNS = 20;
private const int SMALL_CHROMOSOME_SIZE = 10;
private const int LARGE_CHROMOSOME_SIZE = 20;

private readonly IPopulationGenerator smallPopulationGenerator1 =
new IntVectorChromosomePopulationGenerator(SMALL_CHROMOSOME_SIZE, 0, 10, A.Fake<IMutationManager<int>>(),
A.Fake<IEvaluator>());
private readonly IPopulationGenerator smallPopulationGenerator2 =
new IntVectorChromosomePopulationGenerator(SMALL_CHROMOSOME_SIZE, 11, 20, A.Fake<IMutationManager<int>>(),
A.Fake<IEvaluator>());
private readonly IPopulationGenerator largePopulationGenerator =
new IntVectorChromosomePopulationGenerator(LARGE_CHROMOSOME_SIZE, 21, 30, A.Fake<IMutationManager<int>>(),
A.Fake<IEvaluator>());

[TestMethod]
[DataRow(1)]
[DataRow(2)]
[DataRow(5)]
[DataRow(SMALL_CHROMOSOME_SIZE - 1)]
public void K_PointCrossoverTest(int k)
{
var crossoverManager = new K_PointCrossoverManager<int>(k, A.Fake<IMutationManager<int>>(), A.Fake<IEvaluator>());
for (int i = 0; i < TEST_RUNS; i++)
{
var chromosome1 = (VectorChromosome<int>) smallPopulationGenerator1.GeneratePopulation(1).First();
var chromosome2 = (VectorChromosome<int>) smallPopulationGenerator2.GeneratePopulation(1).First();
var newChromosome = (VectorChromosome<int>) crossoverManager.Crossover(chromosome1, chromosome2);

var crossoverPoints = K_CrossoverGetCrossoverPointsAndAssertThatGenomesAreRight(newChromosome, chromosome2, chromosome1);
Assert.AreEqual(k, crossoverPoints.Count,
$"Found wrong number of crossoverPoints. 1: {chromosome1}; 2 {chromosome2}; newChromosome {newChromosome}");
}
}

[TestMethod]
[DataRow(1)]
[DataRow(2)]
[DataRow(5)]
[DataRow(SMALL_CHROMOSOME_SIZE - 1)]
public void K_PointCrossover_ShortAndLongChromosomes(int k)
{
var crossoverManager = new K_PointCrossoverManager<int>(k, A.Fake<IMutationManager<int>>(), A.Fake<IEvaluator>());
for (int i = 0; i < TEST_RUNS; i++)
{
var chromosome1 = (VectorChromosome<int>)smallPopulationGenerator1.GeneratePopulation(1).First();
var chromosome2 = (VectorChromosome<int>)largePopulationGenerator.GeneratePopulation(1).First();
var newChromosome = (VectorChromosome<int>)crossoverManager.Crossover(chromosome1, chromosome2);

var crossoverPoints = K_CrossoverGetCrossoverPointsAndAssertThatGenomesAreRight(newChromosome, chromosome2, chromosome1);
Assert.AreEqual(k, crossoverPoints.Count,
$"Found wrong number of crossoverPoints. 1: {chromosome1}; 2 {chromosome2}; newChromosome {newChromosome}");
}
}

[TestMethod]
public void K_PointCrossover_CrossoverPointsAreDiffrent()
{
var crossoverPoints = new List<int>();
var crossoverManager = new K_PointCrossoverManager<int>(2, A.Fake<IMutationManager<int>>(), A.Fake<IEvaluator>());
for (int i = 0; i < 100; i++)
{
var chromosome1 = (VectorChromosome<int>)smallPopulationGenerator1.GeneratePopulation(1).First();
var chromosome2 = (VectorChromosome<int>)smallPopulationGenerator2.GeneratePopulation(1).First();
var newChromosome = (VectorChromosome<int>)crossoverManager.Crossover(chromosome1, chromosome2);

crossoverPoints.AddRange(K_CrossoverGetCrossoverPointsAndAssertThatGenomesAreRight(newChromosome, chromosome2, chromosome1));
}

for (int i = 1; i < SMALL_CHROMOSOME_SIZE; i++)
Assert.IsTrue(crossoverPoints.Contains(i), $"{nameof(crossoverPoints)} dosn't contain {i}");
}

[TestMethod]
public void SinglePointCrossoverManagerTest()
{
var crossoverManager = new SinglePointCrossoverManager<int>(A.Fake<IMutationManager<int>>(), A.Fake<IEvaluator>());
for (int i = 0; i < TEST_RUNS; i++)
{
var chromosome1 = (VectorChromosome<int>)smallPopulationGenerator1.GeneratePopulation(1).First();
var chromosome2 = (VectorChromosome<int>)smallPopulationGenerator2.GeneratePopulation(1).First();
var newChromosome = (VectorChromosome<int>)crossoverManager.Crossover(chromosome1, chromosome2);

var crossoverPoints = K_CrossoverGetCrossoverPointsAndAssertThatGenomesAreRight(newChromosome, chromosome2, chromosome1);
Assert.AreEqual(1, crossoverPoints.Count,
$"Found wrong number of crossoverPoints. 1: {chromosome1}; 2 {chromosome2}; newChromosome {newChromosome}");
}
}

[TestMethod]
public void UniformCrossoverManagerTest()
{
var crossoverManager = new UniformCrossoverManager<int>(A.Fake<IMutationManager<int>>(), A.Fake<IEvaluator>());
for (int i = 0; i < TEST_RUNS; i++)
{
var chromosome1 = (VectorChromosome<int>)smallPopulationGenerator1.GeneratePopulation(1).First();
var chromosome2 = (VectorChromosome<int>)smallPopulationGenerator2.GeneratePopulation(1).First();
var newChromosome = (VectorChromosome<int>)crossoverManager.Crossover(chromosome1, chromosome2);

K_CrossoverGetCrossoverPointsAndAssertThatGenomesAreRight(newChromosome, chromosome2, chromosome1);
}
}

private static List<int> K_CrossoverGetCrossoverPointsAndAssertThatGenomesAreRight(VectorChromosome<int> newChromosome, VectorChromosome<int> chromosome2,
VectorChromosome<int> chromosome1)
{
var crossoverPoints = new List<int>();
var takingFromFirstChromosome = true;
for (int i = 0; i < SMALL_CHROMOSOME_SIZE; i++)
{
if (takingFromFirstChromosome)
{
if (newChromosome[i] == chromosome2[i])
{
crossoverPoints.Add(i);
takingFromFirstChromosome = !takingFromFirstChromosome;
}
else if (newChromosome[i] != chromosome1[i])
Assert.Fail(
$"Got Genome that dosn't seem to have came from anywhere. 1: {chromosome1}; 2 {chromosome2}; newChromosome {newChromosome} ");
}
else
{
if (newChromosome[i] == chromosome1[i])
{
crossoverPoints.Add(i);
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} ");
}
}
for (int j = SMALL_CHROMOSOME_SIZE; j < LARGE_CHROMOSOME_SIZE && j < newChromosome.GetVector().Length; j++)
{
Assert.AreEqual(chromosome2[j], newChromosome[j]);
}

return crossoverPoints;
}
}
}
Loading

0 comments on commit caee33b

Please sign in to comment.