├── .gitignore ├── UnitTesting ├── nunit.framework.dll └── nunit.framework.extensions.dll ├── EvolvingPythagoreansTheorem ├── ProblemInterfaces │ ├── ICanScore.cs │ └── IGenePoolConfiguration.cs ├── GenomeEvaluation │ ├── IExpression.cs │ ├── IEvaluatable.cs │ ├── SymbolReader.cs │ ├── Operand.cs │ ├── GenomeConverter.cs │ └── DirectGenomeEvaluator.cs ├── MathExtensions.cs ├── EnumerableExtensions.cs ├── ProblemsToSolve │ └── PythagoreanTheorem │ │ ├── TwoInputGenomeEvaluator.cs │ │ ├── PythagoreanTheoremSolverConfiguration.cs │ │ └── PythagoreanProblemDescription.cs ├── BreedingSelection │ ├── BreedingSelectionProcess.cs │ ├── ScoreCard.cs │ └── ScoreCards.cs ├── EnvironmentInteractions │ ├── GeneGod.cs │ ├── GeneGrotto.cs │ ├── GeneMutator.cs │ └── GeneLifeCycle.cs ├── Properties │ └── AssemblyInfo.cs └── EvolvingPythagoreansTheorem.csproj ├── GPRunner ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── GPRunner.csproj ├── Tests ├── TestHarness.cs ├── When_mating_genes.cs ├── When_populating_the_gene_pool.cs ├── Properties │ └── AssemblyInfo.cs ├── When_fitness_testing_genomes.cs ├── When_mutating_a_gene.cs ├── Tests.csproj ├── DirectGenomeEvaluator_Tests.cs └── When_evaluating_a_genome.cs └── EvolvingPythagoreansTheorem.sln /.gitignore: -------------------------------------------------------------------------------- 1 | _ReSharper* 2 | *.resharper* 3 | bin 4 | obj 5 | *.suo 6 | *.zip 7 | *.cache 8 | *.user -------------------------------------------------------------------------------- /UnitTesting/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcbozonier/GeneticProgrammingWithSimpleMath/master/UnitTesting/nunit.framework.dll -------------------------------------------------------------------------------- /UnitTesting/nunit.framework.extensions.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcbozonier/GeneticProgrammingWithSimpleMath/master/UnitTesting/nunit.framework.extensions.dll -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/ProblemInterfaces/ICanScore.cs: -------------------------------------------------------------------------------- 1 | namespace EvolvingPythagoreansTheorem.ProblemInterfaces 2 | { 3 | public interface ICanScore 4 | { 5 | double ScoreThis(string genome); 6 | } 7 | } -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/GenomeEvaluation/IExpression.cs: -------------------------------------------------------------------------------- 1 | namespace EvolvingPythagoreansTheorem.GenomeEvaluation 2 | { 3 | public interface IExpression : IEvaluatable 4 | { 5 | void Add(IExpression expression); 6 | void SetLiteral(string character); 7 | void SetOperator(Operators symbol); 8 | } 9 | } -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/GenomeEvaluation/IEvaluatable.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace EvolvingPythagoreansTheorem.GenomeEvaluation 4 | { 5 | public interface IEvaluatable 6 | { 7 | double Evaluate(IDictionary variableList); 8 | int GetOperableGeneLength(); 9 | } 10 | } -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/ProblemInterfaces/IGenePoolConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace EvolvingPythagoreansTheorem.ProblemInterfaces 4 | { 5 | public interface IGenePoolConfiguration 6 | { 7 | IEnumerable GeneGrammar { get; } 8 | int GenerationRunCount { get; } 9 | int KeepTheTopNPerformersEachGeneration { get; } 10 | int MaximumGeneLength { get; } 11 | int PopulationSizeToMaintain { get; } 12 | double ProbabilityOfMutation { get; } 13 | double StopIfScoreIsAtLeastThisHigh { get; } 14 | ICanScore GetProblemDescription(); 15 | } 16 | } -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/MathExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace EvolvingPythagoreansTheorem 7 | { 8 | public static class MathExtensions 9 | { 10 | public static int Ceiling(this double x) 11 | { 12 | return (int) Math.Ceiling(x); 13 | } 14 | 15 | public static double Squared(this int x) 16 | { 17 | return Math.Pow(x, 2); 18 | } 19 | 20 | public static double Squared(this double x) 21 | { 22 | return Math.Pow(x, 2); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/GenomeEvaluation/SymbolReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EvolvingPythagoreansTheorem.GenomeEvaluation 4 | { 5 | public class SymbolReader 6 | { 7 | readonly string _Genome; 8 | int _CurrentIndex = -1; 9 | 10 | public SymbolReader(string genome) 11 | { 12 | _Genome = genome; 13 | } 14 | 15 | public string ReadNextSymbol() 16 | { 17 | _CurrentIndex++; 18 | return _Genome[_CurrentIndex].ToString(); 19 | } 20 | 21 | public bool IsEndOfSymbols() 22 | { 23 | return _CurrentIndex + 1 >= _Genome.Length; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/EnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace EvolvingPythagoreansTheorem 5 | { 6 | public static class EnumerableExtensions 7 | { 8 | public static IEnumerable Until(this int inclusiveStart, int exclusiveEnd) 9 | { 10 | for (var i = inclusiveStart; i < exclusiveEnd; i++) 11 | { 12 | yield return i; 13 | } 14 | } 15 | 16 | public static void ForEach(this IEnumerable list, Action action) 17 | { 18 | foreach (var item in list) 19 | { 20 | action(item); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/ProblemsToSolve/PythagoreanTheorem/TwoInputGenomeEvaluator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using EvolvingPythagoreansTheorem.GenomeEvaluation; 3 | 4 | namespace EvolvingPythagoreansTheorem.ProblemsToSolve.PythagoreanTheorem 5 | { 6 | public class TwoInputGenomeEvaluator 7 | { 8 | readonly IEvaluatable _GenomeAst; 9 | 10 | public TwoInputGenomeEvaluator(string genome) 11 | { 12 | _GenomeAst = new GenomeConverter().Convert(genome); 13 | } 14 | 15 | public double Evaluate(int a, int b) 16 | { 17 | return _GenomeAst.Evaluate(new Dictionary() { { "a", a }, { "b", b } }); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /GPRunner/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EvolvingPythagoreansTheorem.EnvironmentInteractions; 3 | using EvolvingPythagoreansTheorem.ProblemsToSolve.PythagoreanTheorem; 4 | 5 | namespace GPRunner 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | new GeneLifeCycle() 12 | .Go(new PythagoreanTheoremSolverConfiguration(), 13 | (bestGene, 14 | score) => 15 | { 16 | Console.WriteLine("Best Gene: " + bestGene); 17 | Console.WriteLine("Score: " + score); 18 | }); 19 | Console.Read(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/BreedingSelection/BreedingSelectionProcess.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using EvolvingPythagoreansTheorem.ProblemInterfaces; 3 | 4 | namespace EvolvingPythagoreansTheorem.BreedingSelection 5 | { 6 | public class BreedingSelectionProcess 7 | { 8 | readonly ICanScore _FitnessTester; 9 | 10 | public BreedingSelectionProcess(ICanScore fitnessTester) 11 | { 12 | _FitnessTester = fitnessTester; 13 | } 14 | 15 | public IEnumerable ChooseTopNPerformers(IEnumerable genes, int numberToKeep) 16 | { 17 | var genesToBreed = new ScoreCards(genes, _FitnessTester).GetTop(numberToKeep); 18 | return genesToBreed; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Tests/TestHarness.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EvolvingPythagoreansTheorem.EnvironmentInteractions; 3 | using EvolvingPythagoreansTheorem.ProblemsToSolve.PythagoreanTheorem; 4 | using NUnit.Framework; 5 | 6 | namespace Tests 7 | { 8 | [TestFixture] 9 | public class TestHarness 10 | { 11 | [Ignore] 12 | [Test] 13 | public void RunSimulation() 14 | { 15 | var lifeCycle = new GeneLifeCycle(); 16 | lifeCycle.Go(new PythagoreanTheoremSolverConfiguration(), 17 | (bestGene, score)=> 18 | { 19 | Console.WriteLine("Best Gene: " + bestGene); 20 | Console.WriteLine("Score: " + score); 21 | }); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/BreedingSelection/ScoreCard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EvolvingPythagoreansTheorem.BreedingSelection 4 | { 5 | public class ScoreCard : IComparable 6 | { 7 | public double Score { get; private set; } 8 | public string Genome { get; private set; } 9 | 10 | public ScoreCard(string genome, 11 | double genomeScore) 12 | { 13 | Genome = genome; 14 | Score = genomeScore; 15 | } 16 | 17 | public int CompareTo(object obj) 18 | { 19 | var typedObj = obj as ScoreCard; 20 | if (typedObj == null) 21 | throw new ArgumentException("Must be a score card!"); 22 | 23 | return Score.CompareTo(typedObj.Score); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/BreedingSelection/ScoreCards.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using EvolvingPythagoreansTheorem.ProblemInterfaces; 4 | 5 | namespace EvolvingPythagoreansTheorem.BreedingSelection 6 | { 7 | public class ScoreCards 8 | { 9 | readonly IEnumerable _Scores; 10 | 11 | public ScoreCards(IEnumerable genomes, ICanScore genomeScorer) 12 | { 13 | _Scores = genomes.Select(genome => new ScoreCard(genome, genomeScorer.ScoreThis(genome))); 14 | } 15 | 16 | public string GetBestGene() 17 | { 18 | return _Scores.Max(x => x).Genome; 19 | } 20 | 21 | public IEnumerable GetTop(int numberToKeep) 22 | { 23 | var orderedScores = _Scores.OrderByDescending(x => x.Score); 24 | 25 | return orderedScores 26 | .Take(numberToKeep) 27 | .Select(x=>x.Genome) 28 | .ToArray(); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/EnvironmentInteractions/GeneGod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace EvolvingPythagoreansTheorem.EnvironmentInteractions 6 | { 7 | public class GeneGod 8 | { 9 | readonly string[] _GeneGrammar; 10 | readonly Random _Randomizer; 11 | readonly int _MaxGeneSize; 12 | 13 | public GeneGod(IEnumerable geneGrammar, int maxGeneSize) 14 | { 15 | _GeneGrammar = geneGrammar.ToArray(); 16 | _MaxGeneSize = maxGeneSize; 17 | _Randomizer = new Random(DateTime.Now.Millisecond); 18 | } 19 | 20 | public IEnumerable CreateCountOfGenes(int countToCreate) 21 | { 22 | return 0.Until(countToCreate).Select(x => GetRandomizedMutantGene()).ToArray(); 23 | } 24 | 25 | string GetRandomizedMutantGene() 26 | { 27 | 28 | var maxGeneLength = _Randomizer.Next(3, _MaxGeneSize); 29 | return 0.Until(maxGeneLength) 30 | .Select(x => _GeneGrammar[_Randomizer.Next(0, _GeneGrammar.Length)]) 31 | .Aggregate((x, y) => x + y); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Tests/When_mating_genes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using EvolvingPythagoreansTheorem.EnvironmentInteractions; 6 | using NUnit.Framework; 7 | 8 | namespace Tests 9 | { 10 | [TestFixture] 11 | public class When_mating_genes 12 | { 13 | GeneGrotto TheGeneGrotto; 14 | string[] TheGenes; 15 | IEnumerable BabyGenes; 16 | 17 | [Test] 18 | public void Each_gene_should_be_smaller_than_max_gene_size() 19 | { 20 | Assert.That(BabyGenes.All(x=>x.Length<=4), Is.True); 21 | } 22 | 23 | [Test] 24 | public void Each_gene_should_be_different() 25 | { 26 | Assert.That(BabyGenes.Intersect(BabyGenes).Count(), Is.EqualTo(4)); 27 | } 28 | 29 | [Test] 30 | public void It_should_create_a_gene_cross_product_result() 31 | { 32 | Assert.That(BabyGenes.Count(), Is.EqualTo(4)); 33 | } 34 | 35 | [SetUp] 36 | public void Context() 37 | { 38 | TheGenes = new[] {"+ab", "-cd"}; 39 | TheGeneGrotto = new GeneGrotto(4); 40 | BabyGenes = TheGeneGrotto.GetItOn(TheGenes); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Tests/When_populating_the_gene_pool.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using EvolvingPythagoreansTheorem.EnvironmentInteractions; 4 | using NUnit.Framework; 5 | 6 | namespace Tests 7 | { 8 | [TestFixture] 9 | public class When_populating_the_gene_pool 10 | { 11 | GeneGod God; 12 | IEnumerable CreatedGenes; 13 | int RequestedGeneCount; 14 | string[] GeneGrammar; 15 | 16 | [Test] 17 | public void The_genes_should_only_contain_charcters_from_the_grammar() 18 | { 19 | Assert.That(CreatedGenes.All(x => x.All(y => GeneGrammar.ToList().Contains(y.ToString()))), Is.True); 20 | } 21 | 22 | [Test] 23 | public void It_should_create_the_correct_number_of_genes() 24 | { 25 | Assert.That(CreatedGenes.Count(), Is.EqualTo(RequestedGeneCount)); 26 | } 27 | 28 | [SetUp] 29 | public void Setup() 30 | { 31 | RequestedGeneCount = 10; 32 | GeneGrammar = new[] {"a", "b", "c"}; 33 | God = new GeneGod(GeneGrammar, 5); 34 | Because(); 35 | } 36 | 37 | void Because() 38 | { 39 | CreatedGenes = God.CreateCountOfGenes(RequestedGeneCount); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/ProblemsToSolve/PythagoreanTheorem/PythagoreanTheoremSolverConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using EvolvingPythagoreansTheorem.ProblemInterfaces; 4 | 5 | namespace EvolvingPythagoreansTheorem.ProblemsToSolve.PythagoreanTheorem 6 | { 7 | public class PythagoreanTheoremSolverConfiguration : IGenePoolConfiguration 8 | { 9 | public PythagoreanTheoremSolverConfiguration() 10 | { 11 | GeneGrammar = new[] { "+", "-", "/", "*", "r", "a", "b" }; 12 | GenerationRunCount = 1000000; 13 | MaximumGeneLength = 15; 14 | ProbabilityOfMutation = .25; 15 | PopulationSizeToMaintain = 625; 16 | KeepTheTopNPerformersEachGeneration = 5; 17 | StopIfScoreIsAtLeastThisHigh = 1.032; 18 | } 19 | 20 | public IEnumerable GeneGrammar{ get; private set; } 21 | public int GenerationRunCount { get; private set; } 22 | public int KeepTheTopNPerformersEachGeneration { get; private set; } 23 | public int MaximumGeneLength { get; private set; } 24 | public int PopulationSizeToMaintain { get; private set; } 25 | public double ProbabilityOfMutation { get; private set; } 26 | public double StopIfScoreIsAtLeastThisHigh { get; private set; } 27 | public ICanScore GetProblemDescription() 28 | { 29 | return new PythagoreanProblemDescription(MaximumGeneLength); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2009")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("79a5fc09-be21-4665-a16c-545e7d3ad31f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /GPRunner/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("GPRunner")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("GPRunner")] 13 | [assembly: AssemblyCopyright("Copyright © 2009")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("9756578d-de42-4626-bb69-5d5565fd4200")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("EvolvingPythagoreansTheorem")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("EvolvingPythagoreansTheorem")] 13 | [assembly: AssemblyCopyright("Copyright © 2009")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c085bb99-2155-485f-bb90-67c072342ab7")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/EnvironmentInteractions/GeneGrotto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace EvolvingPythagoreansTheorem.EnvironmentInteractions 7 | { 8 | public class GeneGrotto 9 | { 10 | readonly int _MaxGeneSize; 11 | static Random _Randomizer = new Random(DateTime.Now.Millisecond); 12 | 13 | public GeneGrotto(int maxGeneSize) 14 | { 15 | _MaxGeneSize = maxGeneSize; 16 | } 17 | 18 | public IEnumerable GetItOn(IEnumerable genes) 19 | { 20 | return genes.SelectMany(x => genes.Select(y => _BreedWith(x, y, _MaxGeneSize))); 21 | } 22 | 23 | static string _BreedWith(string geneA, 24 | string geneB, 25 | int maxGeneSize) 26 | { 27 | var newGene = new StringBuilder(); 28 | var geneToSwapFirst = _Randomizer.Next(0, 1); 29 | 30 | for (var i = 0; i < geneA.Length; i++) 31 | { 32 | if(i < geneB.Length) 33 | if (i % 2 == geneToSwapFirst) 34 | newGene.Append(geneA[i]); 35 | else 36 | newGene.Append(geneB[i]); 37 | else 38 | newGene.Append(geneA[i]); 39 | } 40 | 41 | return _TruncateToMaxGeneSize(newGene.ToString(), maxGeneSize); 42 | } 43 | 44 | static string _TruncateToMaxGeneSize(string gene, 45 | int size) 46 | { 47 | return gene.Length <= size 48 | ? gene 49 | : gene.Remove(size - 1); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EvolvingPythagoreansTheorem", "EvolvingPythagoreansTheorem\EvolvingPythagoreansTheorem.csproj", "{3032C51B-B9B1-4CD9-95FE-884F45F0AB85}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{0253E400-7D7D-4AC9-A4D1-8822CD6E8FAF}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GPRunner", "GPRunner\GPRunner.csproj", "{F37D90B1-01EC-4461-8B51-624FF832D828}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {3032C51B-B9B1-4CD9-95FE-884F45F0AB85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {3032C51B-B9B1-4CD9-95FE-884F45F0AB85}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {3032C51B-B9B1-4CD9-95FE-884F45F0AB85}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {3032C51B-B9B1-4CD9-95FE-884F45F0AB85}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {0253E400-7D7D-4AC9-A4D1-8822CD6E8FAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {0253E400-7D7D-4AC9-A4D1-8822CD6E8FAF}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {0253E400-7D7D-4AC9-A4D1-8822CD6E8FAF}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {0253E400-7D7D-4AC9-A4D1-8822CD6E8FAF}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {F37D90B1-01EC-4461-8B51-624FF832D828}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {F37D90B1-01EC-4461-8B51-624FF832D828}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {F37D90B1-01EC-4461-8B51-624FF832D828}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {F37D90B1-01EC-4461-8B51-624FF832D828}.Release|Any CPU.Build.0 = Release|Any CPU 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /Tests/When_fitness_testing_genomes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using EvolvingPythagoreansTheorem.BreedingSelection; 5 | using EvolvingPythagoreansTheorem.ProblemsToSolve.PythagoreanTheorem; 6 | using NUnit.Framework; 7 | 8 | namespace Tests 9 | { 10 | [TestFixture] 11 | public class When_fitness_testing_a_genome_that_goes_to_infinity 12 | { 13 | IEnumerable Genes; 14 | string PythagoreanGenome; 15 | BreedingSelectionProcess BreederSelector; 16 | 17 | [Test] 18 | public void It_should_return_the_best_fit() 19 | { 20 | Assert.That(Genes.Single(), Is.EqualTo(PythagoreanGenome)); 21 | } 22 | 23 | [SetUp] 24 | public void Setup() 25 | { 26 | BreederSelector = new BreedingSelectionProcess(new PythagoreanProblemDescription(8)); 27 | PythagoreanGenome = "r+**aabb"; 28 | Genes = new[] { "/ab", PythagoreanGenome }; 29 | Because(); 30 | } 31 | 32 | void Because() 33 | { 34 | Genes = BreederSelector.ChooseTopNPerformers(Genes, 1); 35 | } 36 | } 37 | 38 | [TestFixture] 39 | public class When_fitness_testing_genomes 40 | { 41 | IEnumerable Genes; 42 | string PythagoreanGenome; 43 | BreedingSelectionProcess BreederSelector; 44 | 45 | [Test] 46 | public void It_should_return_the_best_fit() 47 | { 48 | Assert.That(Genes.Single(), Is.EqualTo(PythagoreanGenome)); 49 | } 50 | 51 | [SetUp] 52 | public void Setup() 53 | { 54 | BreederSelector = new BreedingSelectionProcess(new PythagoreanProblemDescription(8)); 55 | PythagoreanGenome = "r+**aabb"; 56 | Genes = new[] { "+ab", PythagoreanGenome }; 57 | Because(); 58 | } 59 | 60 | void Because() 61 | { 62 | Genes = BreederSelector.ChooseTopNPerformers(Genes, 1); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/EnvironmentInteractions/GeneMutator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace EvolvingPythagoreansTheorem.EnvironmentInteractions 7 | { 8 | public class GeneMutator 9 | { 10 | static Random _Randomizer = new Random(DateTime.Now.Millisecond); 11 | readonly string[] _GeneGrammar; 12 | readonly double _MutationProbability; 13 | int _MaxGeneSize; 14 | 15 | public GeneMutator(IEnumerable geneGrammar, 16 | double mutationProbability, 17 | int size) 18 | { 19 | _GeneGrammar = geneGrammar.ToArray(); 20 | _MutationProbability = mutationProbability; 21 | _MaxGeneSize = size; 22 | } 23 | 24 | public string Mutate(string gene) 25 | { 26 | if (!_ShouldMutate()) 27 | return gene; 28 | 29 | var randomGrammarIndexer = new Random(DateTime.Now.Millisecond); 30 | var randomizedMutantGene = new StringBuilder(); 31 | 0.Until(gene.Length) 32 | .Select(x => _GeneGrammar[randomGrammarIndexer.Next(0, _GeneGrammar.Length)]) 33 | .ForEach(x=>randomizedMutantGene.Append(x)); 34 | 35 | return _Mix(gene, randomizedMutantGene.ToString()); 36 | } 37 | 38 | string _Mix(string gene, string mutantGene) 39 | { 40 | var mutatedGene = new StringBuilder(mutantGene.Length); 41 | for (var i = 0; i < gene.Length; i++) 42 | { 43 | if(_ShouldMutate()) 44 | mutatedGene.Append(mutantGene[i]); 45 | else 46 | mutatedGene.Append(gene[i]); 47 | } 48 | 49 | return _ShouldMutate() 50 | ? mutatedGene.ToString() 51 | : mutatedGene.ToString() + mutatedGene; 52 | } 53 | 54 | bool _ShouldMutate() 55 | { 56 | var rdm = _Randomizer; 57 | var chosenNumber = rdm.Next(1, 1000) / 1000.0; 58 | 59 | return chosenNumber <= _MutationProbability; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/GenomeEvaluation/Operand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace EvolvingPythagoreansTheorem.GenomeEvaluation 5 | { 6 | public enum Operators 7 | { 8 | Plus, Minus, Multiply, Divide, Sqrt, Operand, None 9 | } 10 | 11 | public class Operand : IExpression 12 | { 13 | readonly List _Operands; 14 | Operators _Operator = Operators.None; 15 | string _Literal; 16 | 17 | public Operand() 18 | { 19 | _Operands = new List(); 20 | } 21 | 22 | public void Add(IExpression operand) 23 | { 24 | _Operands.Add(operand); 25 | } 26 | 27 | public double Evaluate(IDictionary variableList) 28 | { 29 | switch (_Operator) 30 | { 31 | case Operators.Plus: 32 | return _Operands[0].Evaluate(variableList) + _Operands[1].Evaluate(variableList); 33 | case Operators.Minus: 34 | return _Operands[0].Evaluate(variableList) - _Operands[1].Evaluate(variableList); 35 | case Operators.Multiply: 36 | return _Operands[0].Evaluate(variableList) * _Operands[1].Evaluate(variableList); 37 | case Operators.Divide: 38 | return _Operands[0].Evaluate(variableList) / _Operands[1].Evaluate(variableList); 39 | case Operators.Sqrt: 40 | return Math.Sqrt(_Operands[0].Evaluate(variableList)); 41 | default: 42 | return _Operator != Operators.None ? variableList[_Literal] : 0.0; 43 | } 44 | } 45 | 46 | public int GetOperableGeneLength() 47 | { 48 | throw new NotImplementedException(); 49 | } 50 | 51 | public void SetLiteral(string character) 52 | { 53 | if (String.IsNullOrEmpty(character)) 54 | throw new ArgumentNullException("The literal can never be null or empty!!!"); 55 | 56 | _Literal = character; 57 | } 58 | 59 | public void SetOperator(Operators theOperator) 60 | { 61 | _Operator = theOperator; 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /Tests/When_mutating_a_gene.cs: -------------------------------------------------------------------------------- 1 | using EvolvingPythagoreansTheorem.EnvironmentInteractions; 2 | using NUnit.Framework; 3 | 4 | namespace Tests 5 | { 6 | [TestFixture] 7 | public class When_mutating_a_gene_that_does_mutate 8 | { 9 | GeneMutator Mutator; 10 | string TheGene; 11 | string TheMutatedGene; 12 | int MaxGeneSize; 13 | 14 | [Test] 15 | public void It_should_NOT_match_the_gene_offered_for_mutation() 16 | { 17 | Assert.That(TheMutatedGene, Is.Not.EqualTo(TheGene)); 18 | } 19 | 20 | [Test] 21 | public void It_should_be_the_same_length() 22 | { 23 | Assert.That(TheMutatedGene.Length, Is.EqualTo(TheGene.Length)); 24 | } 25 | 26 | [Test] 27 | public void It_should_be_somewhat_randomized() 28 | { 29 | Assert.That(TheMutatedGene.IndexOf(TheGene), Is.Not.EqualTo(0)); 30 | } 31 | 32 | [Test] 33 | public void It_should_not_have_a_copy_of_itself_at_its_tail() 34 | { 35 | Assert.That(TheMutatedGene.LastIndexOf(TheGene), Is.Not.EqualTo(3)); 36 | } 37 | 38 | [SetUp] 39 | public void Context() 40 | { 41 | TheGene = "+xy"; 42 | MaxGeneSize = 5; 43 | Mutator = new GeneMutator(new[] { "+", "-", "/", "*", "r", "a", "b" }, 1, MaxGeneSize); 44 | Because(); 45 | } 46 | 47 | void Because() 48 | { 49 | TheMutatedGene = Mutator.Mutate(TheGene); 50 | } 51 | } 52 | 53 | [TestFixture] 54 | public class When_mutating_a_gene_that_does_not_mutate 55 | { 56 | GeneMutator Mutator; 57 | string TheGene; 58 | string TheMutatedGene; 59 | int MaxGeneSize; 60 | 61 | [Test] 62 | public void It_should_match_the_gene_offered_for_mutation() 63 | { 64 | Assert.That(TheMutatedGene, Is.EqualTo(TheGene)); 65 | } 66 | 67 | [SetUp] 68 | public void Context() 69 | { 70 | TheGene = "+xy"; 71 | MaxGeneSize = 4; 72 | Mutator = new GeneMutator(new[] { "+", "-", "/", "*", "r", "a", "b" }, 0, MaxGeneSize); 73 | Because(); 74 | } 75 | 76 | void Because() 77 | { 78 | TheMutatedGene = Mutator.Mutate(TheGene); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /GPRunner/GPRunner.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {F37D90B1-01EC-4461-8B51-624FF832D828} 9 | Exe 10 | Properties 11 | GPRunner 12 | GPRunner 13 | v3.5 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 3.5 37 | 38 | 39 | 3.5 40 | 41 | 42 | 3.5 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | {3032C51B-B9B1-4CD9-95FE-884F45F0AB85} 54 | EvolvingPythagoreansTheorem 55 | 56 | 57 | 58 | 65 | -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/GenomeEvaluation/GenomeConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace EvolvingPythagoreansTheorem.GenomeEvaluation 4 | { 5 | public class GenomeConverter 6 | { 7 | public IEvaluatable Convert(string genome) 8 | { 9 | var symbolReader = new SymbolReader(genome); 10 | 11 | var root = new Operand(); 12 | var fillList = new List {root}; 13 | 14 | while(fillList.Count > 0) 15 | fillList = _FillErUp(fillList, symbolReader); 16 | 17 | return root; 18 | } 19 | 20 | static List _FillErUp(IEnumerable nodes, SymbolReader symbolReader) 21 | { 22 | var childrenForNextLevel = new List(); 23 | 24 | foreach(var node in nodes) 25 | { 26 | if(symbolReader.IsEndOfSymbols()) 27 | break; 28 | 29 | var symbol = symbolReader.ReadNextSymbol(); 30 | var theOperator = _GetOperator(symbol); 31 | node.SetLiteral(symbol); 32 | node.SetOperator(theOperator); 33 | 34 | var childrenToCreateCount = _GetNumberOfChildrenFor(theOperator); 35 | 36 | for(var i=0; i _OperatorLookup = new Dictionary() 48 | { 49 | {"*", Operators.Multiply}, 50 | {"/", Operators.Divide}, 51 | {"+", Operators.Plus}, 52 | {"-", Operators.Minus}, 53 | {"r", Operators.Sqrt} 54 | }; 55 | 56 | static Operators _GetOperator(string symbol) 57 | { 58 | return _OperatorLookup.ContainsKey(symbol) 59 | ? _OperatorLookup[symbol] 60 | : Operators.Operand; 61 | } 62 | 63 | static int _GetNumberOfChildrenFor(Operators symbol) 64 | { 65 | switch(symbol) 66 | { 67 | case Operators.Multiply: 68 | case Operators.Divide: 69 | case Operators.Plus: 70 | case Operators.Minus: 71 | return 2; 72 | case Operators.Sqrt: 73 | return 1; 74 | default: 75 | return 0; 76 | } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/EnvironmentInteractions/GeneLifeCycle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using EvolvingPythagoreansTheorem.ProblemInterfaces; 5 | 6 | namespace EvolvingPythagoreansTheorem.EnvironmentInteractions 7 | { 8 | public class GeneLifeCycle 9 | { 10 | public string Go(IGenePoolConfiguration configuration, Action statusReport) 11 | { 12 | var probabilityOfMutation = configuration.ProbabilityOfMutation; 13 | var generationsToRunFor = configuration.GenerationRunCount; 14 | var maxGeneSize = configuration.MaximumGeneLength; 15 | var populationSizeToMaintain = configuration.PopulationSizeToMaintain; 16 | var keepTopNPerformers = configuration.KeepTheTopNPerformersEachGeneration; 17 | 18 | var god = new GeneGod(configuration.GeneGrammar, maxGeneSize); 19 | var breedingSelector = new BreedingSelection.BreedingSelectionProcess(configuration.GetProblemDescription()); 20 | var mutator = new GeneMutator(configuration.GeneGrammar, probabilityOfMutation, maxGeneSize); 21 | var grotto = new GeneGrotto(maxGeneSize); 22 | 23 | 24 | var population = god.CreateCountOfGenes(populationSizeToMaintain); 25 | var veryBestGene = ""; 26 | 27 | foreach (var generation in 0.Until(generationsToRunFor)) 28 | { 29 | population = breedingSelector.ChooseTopNPerformers(population, keepTopNPerformers); 30 | veryBestGene = population.First(); 31 | 32 | var topScore = configuration.GetProblemDescription().ScoreThis(veryBestGene); 33 | statusReport(veryBestGene, topScore); 34 | if(topScore >= configuration.StopIfScoreIsAtLeastThisHigh) 35 | break; 36 | 37 | while(population.Count() < populationSizeToMaintain) 38 | { 39 | population = grotto.GetItOn(population); 40 | population = population.Select(x => mutator.Mutate(x)); 41 | } 42 | 43 | population = _RemoveSurplusOrganisms(populationSizeToMaintain, population); 44 | 45 | 46 | } 47 | 48 | return veryBestGene; 49 | } 50 | 51 | static IEnumerable _RemoveSurplusOrganisms(int populationSizeToMaintain, 52 | IEnumerable population) { 53 | if(population.Count() > populationSizeToMaintain) 54 | { 55 | var populace = population.ToList(); 56 | var numberToRemove = populace.Count - populationSizeToMaintain; 57 | var indexDistance = populace.Count/numberToRemove; 58 | var indicesToRemove = 0.Until(numberToRemove).Select(x => x*indexDistance); 59 | indicesToRemove.Reverse().ForEach(populace.RemoveAt); 60 | 61 | population = populace; 62 | } 63 | return population; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Tests/Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {0253E400-7D7D-4AC9-A4D1-8822CD6E8FAF} 9 | Library 10 | Properties 11 | Tests 12 | Tests 13 | v3.5 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | False 36 | ..\UnitTesting\nunit.framework.dll 37 | 38 | 39 | 40 | 3.5 41 | 42 | 43 | 3.5 44 | 45 | 46 | 3.5 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | {3032C51B-B9B1-4CD9-95FE-884F45F0AB85} 64 | EvolvingPythagoreansTheorem 65 | 66 | 67 | 68 | 75 | -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/EvolvingPythagoreansTheorem.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {3032C51B-B9B1-4CD9-95FE-884F45F0AB85} 9 | Library 10 | Properties 11 | EvolvingPythagoreansTheorem 12 | EvolvingPythagoreansTheorem 13 | v3.5 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 3.5 37 | 38 | 39 | 3.5 40 | 41 | 42 | 3.5 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 78 | -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/GenomeEvaluation/DirectGenomeEvaluator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace EvolvingPythagoreansTheorem.GenomeEvaluation 5 | { 6 | public class DirectGenomeEvaluator : IEvaluatable 7 | { 8 | readonly string _Genome; 9 | 10 | public DirectGenomeEvaluator(string gene) 11 | { 12 | _Genome = gene; 13 | } 14 | 15 | public int GetGeneLength() 16 | { 17 | return _Genome.Length; 18 | } 19 | 20 | public double Evaluate(IDictionary variableList) 21 | { 22 | var operandQueue = new Queue(); 23 | 24 | var indexValidAt = _GetIndexToCalculateTo(_Genome); 25 | 26 | if (indexValidAt < 0) 27 | return double.NaN; 28 | 29 | for (var i = indexValidAt; i >= 0; i--) 30 | { 31 | var theCharacter = _Genome[i]; 32 | if (!_IsOperator(theCharacter)) 33 | operandQueue.Enqueue(variableList[theCharacter.ToString()]); 34 | else 35 | { 36 | if(_GetNumberOfChildrenFor(theCharacter) > operandQueue.Count) 37 | return double.NaN; 38 | switch (theCharacter) 39 | { 40 | case '*': 41 | operandQueue.Enqueue(operandQueue.Dequeue() * operandQueue.Dequeue()); 42 | break; 43 | case '/': 44 | operandQueue.Enqueue(operandQueue.Dequeue() / operandQueue.Dequeue()); 45 | break; 46 | case '-': 47 | operandQueue.Enqueue(operandQueue.Dequeue() - operandQueue.Dequeue()); 48 | break; 49 | case '+': 50 | operandQueue.Enqueue(operandQueue.Dequeue() + operandQueue.Dequeue()); 51 | break; 52 | case 'r': 53 | operandQueue.Enqueue(Math.Sqrt(operandQueue.Dequeue())); 54 | break; 55 | default: 56 | throw new NotImplementedException("This is NOT an operator!!! '" + theCharacter + "'"); 57 | } 58 | 59 | } 60 | 61 | } 62 | 63 | return operandQueue.Dequeue(); 64 | } 65 | 66 | public int GetOperableGeneLength() 67 | { 68 | return _GetIndexToCalculateTo(_Genome) + 1; 69 | } 70 | 71 | static int _GetIndexToCalculateTo(string genome) { 72 | var genomeLength = genome.Length; 73 | var indexValidAt = genomeLength - 1; 74 | var currentScore = 1; 75 | for (var i = 0; i < genomeLength; i++ ) 76 | { 77 | var theCharacter = genome[i]; 78 | currentScore += _GetNumberOfChildrenFor(theCharacter) - 1; 79 | 80 | if(currentScore == 0) 81 | { 82 | indexValidAt = i; 83 | break; 84 | } 85 | } 86 | return indexValidAt; 87 | } 88 | 89 | static int _GetNumberOfChildrenFor(char symbol) 90 | { 91 | switch (symbol) 92 | { 93 | case '*': 94 | case '/': 95 | case '+': 96 | case '-': 97 | return 2; 98 | case 'r': 99 | return 1; 100 | default: 101 | return 0; 102 | } 103 | } 104 | 105 | static bool _IsOperator(char character) 106 | { 107 | return character == '+' || 108 | character == '-' || 109 | character == '*' || 110 | character == '/' || 111 | character == 'r'; 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /EvolvingPythagoreansTheorem/ProblemsToSolve/PythagoreanTheorem/PythagoreanProblemDescription.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using EvolvingPythagoreansTheorem.GenomeEvaluation; 4 | using EvolvingPythagoreansTheorem.ProblemInterfaces; 5 | 6 | namespace EvolvingPythagoreansTheorem.ProblemsToSolve.PythagoreanTheorem 7 | { 8 | public class PythagoreanProblemDescription : ICanScore 9 | { 10 | IDictionary _Parameters; 11 | int _MaxGeneLength; 12 | 13 | public PythagoreanProblemDescription(int length) 14 | { 15 | _MaxGeneLength = length; 16 | } 17 | 18 | public double ScoreThis(string genome) 19 | { 20 | var genomeEvaluator = new DirectGenomeEvaluator(genome); //new GenomeConverter().Convert(genome); 21 | _Parameters = new Dictionary() {{"a", 0.0}, {"b", 0.0}}; 22 | 23 | var score = _GetScoreByInferenceOfRules(genomeEvaluator); 24 | //var score = _GetScoreByEvaluatingClosenessToRealDeal(genomeEvaluator); 25 | 26 | return score; 27 | } 28 | 29 | public double Evaluate(IEvaluatable node, int a, int b) 30 | { 31 | _Parameters["a"] = a; 32 | _Parameters["b"] = b; 33 | 34 | return node.Evaluate(_Parameters); 35 | } 36 | 37 | double _GetScoreByEvaluatingClosenessToRealDeal(IEvaluatable node) 38 | { 39 | var aggregateResult = 0.0; 40 | 41 | for(var a=100; a < 105; a++) 42 | { 43 | for(var b=100; b<105; b++) 44 | { 45 | var geneResult = Evaluate(node, a, b); 46 | var actualResult = Math.Sqrt(a.Squared() + b.Squared()); 47 | 48 | aggregateResult += - Math.Abs(geneResult - actualResult); 49 | } 50 | } 51 | 52 | return aggregateResult / 100; 53 | } 54 | 55 | double _GetScoreByInferenceOfRules(IEvaluatable genomeEvaluator) { 56 | var score = 0.0; 57 | 58 | { 59 | score += (.08)*(1 - genomeEvaluator.GetOperableGeneLength()/_MaxGeneLength); 60 | } 61 | 62 | // Hypoteneuse must be longer than leg a 63 | { 64 | var a = 6; 65 | var b = 9; 66 | var c = Evaluate(genomeEvaluator, a, b); 67 | 68 | score += c > a ? .16 : 0; 69 | } 70 | 71 | // Hypoteneuse must be longer than leg b 72 | { 73 | var a = 1; 74 | var b = 20; 75 | var c = Evaluate(genomeEvaluator, a, b); 76 | 77 | score += c > b ? .16 : 0; 78 | } 79 | 80 | // Hypoteneuse must be shorter than leg a + leg b 81 | { 82 | var a = 3; 83 | var b = 4; 84 | var c = Evaluate(genomeEvaluator, a, b); 85 | 86 | score += c < a + b ? .16 : 0; 87 | } 88 | 89 | // Hypoteneuse is a if b == 0 90 | { 91 | var a = 3; 92 | var b = 0; 93 | var c = Evaluate(genomeEvaluator, a, b); 94 | 95 | score += c == a ? .16 : 0; 96 | } 97 | 98 | // Hypoteneuse is b if a == 0 99 | { 100 | var a = 0; 101 | var b = 4; 102 | var c = Evaluate(genomeEvaluator, a, b); 103 | 104 | score += c == b ? .16 : 0; 105 | } 106 | 107 | // Hypoteneuse is 0 if a == 0 && b == 0 108 | { 109 | var a = 0; 110 | var b = 0; 111 | var c = Evaluate(genomeEvaluator, a, b); 112 | 113 | score += c == b ? .16 : 0; 114 | } 115 | 116 | // Hypoteneuse is a*sqrt(2) if a == b 117 | { 118 | var a = 1; 119 | var b = a; 120 | var c = Evaluate(genomeEvaluator, a, b); 121 | 122 | score += -Math.Abs(2*a.Squared() - c.Squared()); 123 | } 124 | 125 | if (double.IsInfinity(score)) 126 | score = double.MinValue; 127 | return score; 128 | } 129 | } 130 | } -------------------------------------------------------------------------------- /Tests/DirectGenomeEvaluator_Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using EvolvingPythagoreansTheorem.GenomeEvaluation; 4 | using NUnit.Framework; 5 | 6 | namespace Tests 7 | { 8 | [TestFixture] 9 | public class DirectGenomeEvaluator_Tests5 10 | { 11 | DirectGenomeEvaluator Evaluator; 12 | Dictionary Parameters; 13 | double Result; 14 | 15 | [Test] 16 | public void It_should_return_the_right_answer() 17 | { 18 | Assert.That(Result, Is.EqualTo(double.NaN)); 19 | } 20 | 21 | [SetUp] 22 | public void Context() 23 | { 24 | Evaluator = new DirectGenomeEvaluator("--b"); 25 | Parameters = new Dictionary 26 | { 27 | {"a", 2.0}, 28 | {"b", 3.0} 29 | }; 30 | Because(); 31 | } 32 | 33 | void Because() 34 | { 35 | Result = Evaluator.Evaluate(Parameters); 36 | } 37 | } 38 | 39 | [TestFixture] 40 | public class DirectGenomeEvaluator_Tests4 41 | { 42 | DirectGenomeEvaluator Evaluator; 43 | Dictionary Parameters; 44 | double Result; 45 | 46 | [Test] 47 | public void It_should_return_the_right_answer() 48 | { 49 | Assert.That(Result, Is.EqualTo(15)); 50 | } 51 | 52 | [SetUp] 53 | public void Context() 54 | { 55 | Evaluator = new DirectGenomeEvaluator("+*b*aba*ab"); 56 | Parameters = new Dictionary 57 | { 58 | {"a", 2.0}, 59 | {"b", 3.0} 60 | }; 61 | Because(); 62 | } 63 | 64 | void Because() 65 | { 66 | Result = Evaluator.Evaluate(Parameters); 67 | } 68 | } 69 | 70 | [TestFixture] 71 | public class DirectGenomeEvaluator_Tests3 72 | { 73 | DirectGenomeEvaluator Evaluator; 74 | Dictionary Parameters; 75 | double Result; 76 | 77 | [Test] 78 | public void It_should_return_the_right_answer() 79 | { 80 | Assert.That(Result, Is.EqualTo(15)); 81 | } 82 | 83 | [SetUp] 84 | public void Context() 85 | { 86 | Evaluator = new DirectGenomeEvaluator("+*b*aba"); 87 | Parameters = new Dictionary 88 | { 89 | {"a", 2.0}, 90 | {"b", 3.0} 91 | }; 92 | Because(); 93 | } 94 | 95 | void Because() 96 | { 97 | Result = Evaluator.Evaluate(Parameters); 98 | } 99 | } 100 | 101 | [TestFixture] 102 | public class DirectGenomeEvaluator_Tests2 103 | { 104 | DirectGenomeEvaluator Evaluator; 105 | Dictionary Parameters; 106 | double Result; 107 | 108 | [Test] 109 | public void It_should_return_the_right_answer() 110 | { 111 | Assert.That(Result, Is.EqualTo(Math.Sqrt(2.0))); 112 | } 113 | 114 | [SetUp] 115 | public void Context() 116 | { 117 | Evaluator = new DirectGenomeEvaluator("r+**aabb"); 118 | Parameters = new Dictionary 119 | { 120 | {"a", 1.0}, 121 | {"b", 1.0} 122 | }; 123 | Because(); 124 | } 125 | 126 | void Because() 127 | { 128 | Result = Evaluator.Evaluate(Parameters); 129 | } 130 | } 131 | 132 | [TestFixture] 133 | public class DirectGenomeEvaluator_Tests 134 | { 135 | DirectGenomeEvaluator Evaluator; 136 | Dictionary Parameters; 137 | double Result; 138 | 139 | [Test] 140 | public void It_should_return_the_right_answer() 141 | { 142 | Assert.That(Result, Is.EqualTo(5)); 143 | } 144 | 145 | [SetUp] 146 | public void Context() 147 | { 148 | Evaluator = new DirectGenomeEvaluator("r+**aabb"); 149 | Parameters = new Dictionary 150 | { 151 | {"a", 3.0}, 152 | {"b", 4.0} 153 | }; 154 | Because(); 155 | } 156 | 157 | void Because() 158 | { 159 | Result = Evaluator.Evaluate(Parameters); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /Tests/When_evaluating_a_genome.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using EvolvingPythagoreansTheorem.GenomeEvaluation; 3 | using NUnit.Framework; 4 | 5 | namespace Tests 6 | { 7 | [TestFixture] 8 | public class When_evaluating_an_expression_that_square_roots_a_negative_value 9 | { 10 | string AGenome; 11 | IEvaluatable Ast; 12 | GenomeConverter Converter; 13 | double Result; 14 | 15 | [Test] 16 | public void Should_compute_positive_infinity() 17 | { 18 | Assert.That(Result, Is.EqualTo(double.NaN)); 19 | } 20 | 21 | [SetUp] 22 | public void Context() 23 | { 24 | AGenome = "rx"; 25 | Converter = new GenomeConverter(); 26 | Ast = Converter.Convert(AGenome); 27 | 28 | Because(); 29 | } 30 | 31 | void Because() 32 | { 33 | Result = Ast.Evaluate(new Dictionary { { "x", -3.0 }, { "y", 0 } }); 34 | } 35 | } 36 | 37 | [TestFixture] 38 | public class When_evaluating_an_expression_that_divides_by_zero 39 | { 40 | string AGenome; 41 | IEvaluatable Ast; 42 | GenomeConverter Converter; 43 | double Result; 44 | 45 | [Test] 46 | public void Should_compute_positive_infinity() 47 | { 48 | Assert.That(Result, Is.EqualTo(double.PositiveInfinity)); 49 | } 50 | 51 | [SetUp] 52 | public void Context() 53 | { 54 | AGenome = "/xy"; 55 | Converter = new GenomeConverter(); 56 | Ast = Converter.Convert(AGenome); 57 | 58 | Because(); 59 | } 60 | 61 | void Because() 62 | { 63 | Result = Ast.Evaluate(new Dictionary { { "x", 3.0 }, { "y", 0 } }); 64 | } 65 | } 66 | 67 | [TestFixture] 68 | public class When_evaluating_a_corrupt_expression_of_all_operands 69 | { 70 | string AGenome; 71 | IEvaluatable Ast; 72 | GenomeConverter Converter; 73 | double Result; 74 | 75 | [Test] 76 | public void Should_compute_zero() 77 | { 78 | Assert.That(Result, Is.EqualTo(3)); 79 | } 80 | 81 | [SetUp] 82 | public void Context() 83 | { 84 | AGenome = "xxyxyxyxyx"; 85 | Converter = new GenomeConverter(); 86 | Ast = Converter.Convert(AGenome); 87 | 88 | Because(); 89 | } 90 | 91 | void Because() 92 | { 93 | Result = Ast.Evaluate(new Dictionary { { "x", 3.0 }, { "y", 4.0 } }); 94 | } 95 | } 96 | 97 | [TestFixture] 98 | public class When_evaluating_a_corrupt_expression_of_all_operators 99 | { 100 | string AGenome; 101 | IEvaluatable Ast; 102 | GenomeConverter Converter; 103 | double Result; 104 | 105 | [Test] 106 | public void Should_compute_zero() 107 | { 108 | Assert.That(Result, Is.EqualTo(0)); 109 | } 110 | 111 | [SetUp] 112 | public void Context() 113 | { 114 | AGenome = "++++++++"; 115 | Converter = new GenomeConverter(); 116 | Ast = Converter.Convert(AGenome); 117 | 118 | Because(); 119 | } 120 | 121 | void Because() 122 | { 123 | Result = Ast.Evaluate(new Dictionary { { "x", 3.0 }, { "y", 4.0 } }); 124 | } 125 | } 126 | 127 | [TestFixture] 128 | public class When_evaluating_a_pythagorean_formula 129 | { 130 | string AGenome; 131 | IEvaluatable Ast; 132 | GenomeConverter Converter; 133 | double Result; 134 | 135 | [Test] 136 | public void Should_compute_correct_result() 137 | { 138 | Assert.That(Result, Is.EqualTo(5)); 139 | } 140 | 141 | [SetUp] 142 | public void Context() 143 | { 144 | AGenome = "r+**xxyy"; 145 | Converter = new GenomeConverter(); 146 | Ast = Converter.Convert(AGenome); 147 | 148 | Because(); 149 | } 150 | 151 | void Because() 152 | { 153 | Result = Ast.Evaluate(new Dictionary { { "x", 3.0 }, { "y", 4.0 } }); 154 | } 155 | } 156 | 157 | [TestFixture] 158 | public class When_evaluating_a_sqrt_x_genome 159 | { 160 | string AGenome; 161 | IEvaluatable Ast; 162 | GenomeConverter Converter; 163 | double Result; 164 | 165 | [Test] 166 | public void Should_compute_correct_result() 167 | { 168 | Assert.That(Result, Is.EqualTo(9)); 169 | } 170 | 171 | [SetUp] 172 | public void Context() 173 | { 174 | AGenome = "rx"; 175 | Converter = new GenomeConverter(); 176 | Ast = Converter.Convert(AGenome); 177 | 178 | Because(); 179 | } 180 | 181 | void Because() 182 | { 183 | Result = Ast.Evaluate(new Dictionary { { "x", 81.0 } }); 184 | } 185 | } 186 | 187 | [TestFixture] 188 | public class When_evaluating_a_divide_x_y_genome 189 | { 190 | string AGenome; 191 | IEvaluatable Ast; 192 | GenomeConverter Converter; 193 | double Result; 194 | 195 | [Test] 196 | public void Should_compute_correct_result() 197 | { 198 | Assert.That(Result, Is.EqualTo(.5)); 199 | } 200 | 201 | [SetUp] 202 | public void Context() 203 | { 204 | AGenome = "/xy"; 205 | Converter = new GenomeConverter(); 206 | Ast = Converter.Convert(AGenome); 207 | 208 | Because(); 209 | } 210 | 211 | void Because() 212 | { 213 | Result = Ast.Evaluate(new Dictionary { { "x", 2.0 }, { "y", 4.0 } }); 214 | } 215 | } 216 | 217 | [TestFixture] 218 | public class When_evaluating_a_multiply_x_y_genome 219 | { 220 | string AGenome; 221 | IEvaluatable Ast; 222 | GenomeConverter Converter; 223 | double Result; 224 | 225 | [Test] 226 | public void Should_compute_correct_result() 227 | { 228 | Assert.That(Result, Is.EqualTo(6.0)); 229 | } 230 | 231 | [SetUp] 232 | public void Context() 233 | { 234 | AGenome = "*xy"; 235 | Converter = new GenomeConverter(); 236 | Ast = Converter.Convert(AGenome); 237 | 238 | Because(); 239 | } 240 | 241 | void Because() 242 | { 243 | Result = Ast.Evaluate(new Dictionary { { "x", 2.0 }, { "y", 3.0 } }); 244 | } 245 | } 246 | 247 | [TestFixture] 248 | public class When_evaluating_a_minus_x_y_genome 249 | { 250 | string AGenome; 251 | IEvaluatable Ast; 252 | GenomeConverter Converter; 253 | double Result; 254 | 255 | [Test] 256 | public void Should_compute_correct_result() 257 | { 258 | Assert.That(Result, Is.EqualTo(-1.0)); 259 | } 260 | 261 | [SetUp] 262 | public void Context() 263 | { 264 | AGenome = "-xy"; 265 | Converter = new GenomeConverter(); 266 | Ast = Converter.Convert(AGenome); 267 | 268 | Because(); 269 | } 270 | 271 | void Because() 272 | { 273 | Result = Ast.Evaluate(new Dictionary { { "x", 2.0 }, { "y", 3.0 } }); 274 | } 275 | } 276 | 277 | [TestFixture] 278 | public class When_evaluating_a_plus_x_y_genome 279 | { 280 | string AGenome; 281 | IEvaluatable Ast; 282 | GenomeConverter Converter; 283 | double Result; 284 | 285 | [Test] 286 | public void Should_compute_correct_result() 287 | { 288 | Assert.That(Result, Is.EqualTo(5.0)); 289 | } 290 | 291 | [SetUp] 292 | public void Context() 293 | { 294 | AGenome = "+xy"; 295 | Converter = new GenomeConverter(); 296 | Ast = Converter.Convert(AGenome); 297 | 298 | Because(); 299 | } 300 | 301 | void Because() 302 | { 303 | Result = Ast.Evaluate(new Dictionary { { "x", 2.0 }, { "y", 3.0 } }); 304 | } 305 | } 306 | } 307 | --------------------------------------------------------------------------------