public static float averageWeightDifference(Genome g1, Genome g2) { float g1TotalWeights = 0.0f; float g2TotalWeights = 0.0f; float matchingGeneCounter = 0.0f; foreach (KeyValuePair <int, ConnectionGene> c in g1.getConnections()) { if (g2.getConnections().ContainsKey(c.Key)) { matchingGeneCounter++; g1TotalWeights += c.Value.getWeight(); } } foreach (KeyValuePair <int, ConnectionGene> c in g2.getConnections()) { if (g1.getConnections().ContainsKey(c.Key)) { g2TotalWeights += c.Value.getWeight(); } } // Debug.Log("g1TotalWeights" + g1TotalWeights + "g2TotalWeights" + g1TotalWeights + "matchingGeneCounter" + matchingGeneCounter); //Console.WriteLine("g1TotalWeights " + g1TotalWeights + " g2TotalWeights " + g1TotalWeights + " matchingGeneCounter " + matchingGeneCounter); if (matchingGeneCounter == 0) { return(0f); } return((Math.Abs(g1TotalWeights - g2TotalWeights)) / matchingGeneCounter); }
public static int excessCount(Genome g1, Genome g2) { int count = 0; int g1HighestInnovation = g1.getConnections().Keys.Max(); int g2HighestInnovation = g2.getConnections().Keys.Max(); // if g1 has lower innovation, count excess genes on g2 if (g1HighestInnovation < g2HighestInnovation) { foreach (KeyValuePair <int, ConnectionGene> c in g2.getConnections()) { if (c.Key > g1HighestInnovation) { count++; } } } else if (g1HighestInnovation > g2HighestInnovation) { foreach (KeyValuePair <int, ConnectionGene> c in g1.getConnections()) { if (c.Key > g2HighestInnovation) { count++; } } } return(count); }
public static int disjointCount(Genome g1, Genome g2) { int count = 0; int g1HighestInnovation = g1.getConnections().Keys.Max(); int g2HighestInnovation = g2.getConnections().Keys.Max(); if (g1HighestInnovation <= g2HighestInnovation) { foreach (KeyValuePair <int, ConnectionGene> c in g1.getConnections()) { if (!g2.getConnections().ContainsKey(c.Key)) { count++; } } foreach (KeyValuePair <int, ConnectionGene> c in g2.getConnections()) { if (!g1.getConnections().ContainsKey(c.Key) && c.Key < g1HighestInnovation) { count++; } } } else if (g1HighestInnovation > g2HighestInnovation) { foreach (KeyValuePair <int, ConnectionGene> c in g2.getConnections()) { if (!g1.getConnections().ContainsKey(c.Key)) { count++; } } foreach (KeyValuePair <int, ConnectionGene> c in g1.getConnections()) { if (!g2.getConnections().ContainsKey(c.Key) && c.Key < g2HighestInnovation) { count++; } } } return(count); }
// matching genes are inherited randomly, disjoint and excess (unmatching genes) genes are inherited from the more fit parent // parent1 is the more fit parent public static Genome crossover(Random random, Genome parent1, Genome parent2) { Genome offspring = new Genome(); /** * NodeGene Crossover */ // add NodeGenes from parent1 (fittest parent) to the offspring foreach (KeyValuePair <int, NodeGene> n in parent1.getNodes()) { NodeGene oNode = new NodeGene(n.Value); offspring.addNodeGene(oNode); } /** * ConnectionGene Crossover */ foreach (KeyValuePair <int, ConnectionGene> p1Gene in parent1.getConnections()) { // when parent connection genes match one must be inherited by the offspring randomly if (parent2.getConnections().ContainsKey(p1Gene.Key)) { if (random.Next(100) <= 50) { // takes a copy of parent2 gene offspring.addConnectionGene(new ConnectionGene(parent2.getConnections()[p1Gene.Key])); } else { //takes a copy of parent1 gene offspring.addConnectionGene(new ConnectionGene(p1Gene.Value)); } } else // if they don't match (disjoint or excess), copy from more fit parent { offspring.addConnectionGene(new ConnectionGene(p1Gene.Value)); } } return(offspring); }
public static bool compatibilityDistance(Genome g1, Genome g2) { int normalize = 1; int g1GeneCount = g1.getConnections().Count; int g2GeneCount = g2.getConnections().Count; // if either genome has more than 20 genes, change normalize if (g1GeneCount >= GENE_THRESHOLD || g2GeneCount >= GENE_THRESHOLD) { //normalise is set to the length of the largest genome normalize = Math.Max(g1GeneCount, g2GeneCount); } float cDistance = ((excessCount(g1, g2) * Utility.COEFFICIENT1) / normalize) + ((disjointCount(g1, g2) * Utility.COEFFICIENT2) / normalize) + (averageWeightDifference(g1, g2) * Utility.COEFFICIENT3); return(cDistance <= Utility.COMPATIBILITY_THRESHOLD); }
public static void Main(string[] args) { Random random = new Random(); Genome initialGenome = new Genome(); int node0 = initialGenome.getNodes().Count; initialGenome.addNodeGene(new NodeGene(NodeGene.NodeType.INPUT, node0)); int node1 = initialGenome.getNodes().Count; initialGenome.addNodeGene(new NodeGene(NodeGene.NodeType.INPUT, node1)); int node2 = initialGenome.getNodes().Count; initialGenome.addNodeGene(new NodeGene(NodeGene.NodeType.OUTPUT, node2)); InnovationUtility.incrementGlobalInnovation(); initialGenome.addConnectionGene(new ConnectionGene(node0, node2, Genome.getRandomFloatBetweenPoints(random, -1.0, 1.0), true, InnovationUtility.getGlobalInnovation())); InnovationUtility.incrementGlobalInnovation(); initialGenome.addConnectionGene(new ConnectionGene(node1, node2, Genome.getRandomFloatBetweenPoints(random, -1.0, 1.0), true, InnovationUtility.getGlobalInnovation())); Genome initialGenome1 = new Genome(); node0 = initialGenome1.getNodes().Count; initialGenome1.addNodeGene(new NodeGene(NodeGene.NodeType.INPUT, node0)); node1 = initialGenome1.getNodes().Count; initialGenome1.addNodeGene(new NodeGene(NodeGene.NodeType.INPUT, node1)); node2 = initialGenome1.getNodes().Count; initialGenome1.addNodeGene(new NodeGene(NodeGene.NodeType.OUTPUT, node2)); initialGenome1.addConnectionGene(new ConnectionGene(node0, node2, Genome.getRandomFloatBetweenPoints(random, -1.0, 1.0), true, 1)); initialGenome1.addConnectionGene(new ConnectionGene(node1, node2, Genome.getRandomFloatBetweenPoints(random, -1.0, 1.0), true, 2)); Genome initialGenome2 = new Genome(); node0 = initialGenome2.getNodes().Count; initialGenome2.addNodeGene(new NodeGene(NodeGene.NodeType.INPUT, node0)); node1 = initialGenome2.getNodes().Count; initialGenome2.addNodeGene(new NodeGene(NodeGene.NodeType.INPUT, node1)); node2 = initialGenome2.getNodes().Count; initialGenome2.addNodeGene(new NodeGene(NodeGene.NodeType.OUTPUT, node2)); initialGenome2.addConnectionGene(new ConnectionGene(node0, node2, Genome.getRandomFloatBetweenPoints(random, -1.0, 1.0), true, 1)); initialGenome2.addConnectionGene(new ConnectionGene(node1, node2, Genome.getRandomFloatBetweenPoints(random, -1.0, 1.0), true, 2)); Genome initialGenome3 = new Genome(); node0 = initialGenome3.getNodes().Count; initialGenome3.addNodeGene(new NodeGene(NodeGene.NodeType.INPUT, node0)); node1 = initialGenome3.getNodes().Count; initialGenome3.addNodeGene(new NodeGene(NodeGene.NodeType.INPUT, node1)); node2 = initialGenome3.getNodes().Count; initialGenome3.addNodeGene(new NodeGene(NodeGene.NodeType.OUTPUT, node2)); initialGenome3.addConnectionGene(new ConnectionGene(node0, node2, Genome.getRandomFloatBetweenPoints(random, -1.0, 1.0), true, 1)); initialGenome3.addConnectionGene(new ConnectionGene(node1, node2, Genome.getRandomFloatBetweenPoints(random, -1.0, 1.0), true, 2)); // //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // Genome initialGenome2 = new Genome(); // node1 = initialGenome2.getNodes().Count; // initialGenome2.addNodeGene(new NodeGene(NodeGene.NodeType.INPUT, node1)); // node2 = initialGenome2.getNodes().Count; // initialGenome2.addNodeGene(new NodeGene(NodeGene.NodeType.INPUT, node2)); // node3 = initialGenome2.getNodes().Count; // initialGenome2.addNodeGene(new NodeGene(NodeGene.NodeType.OUTPUT, node3)); // InnovationUtility.incrementGlobalInnovation(); // initialGenome2.addConnectionGene(new ConnectionGene(node1, node3, Genome.getRandomFloatBetweenPoints(random, -1.0, 1.0), true, 1)); // InnovationUtility.incrementGlobalInnovation(); // initialGenome2.addConnectionGene(new ConnectionGene(node2, node3, Genome.getRandomFloatBetweenPoints(random, -1.0, 1.0), true, 2)); //------------------------------------------------------------------- initialGenome.addNodeMutation(random); initialGenome3.addNodeMutation(random); Console.Write("initialGenome: "); foreach (KeyValuePair <int, ConnectionGene> c in initialGenome.getConnections()) { Console.Write("[" + c.Key + "]"); } Console.Write("\n" + "initialGenome1: "); foreach (KeyValuePair <int, ConnectionGene> c in initialGenome1.getConnections()) { Console.Write("[" + c.Key + "]"); } Console.Write("\n"); Console.WriteLine("disjoint: " + Speciation.disjointCount(initialGenome, initialGenome1)); Console.WriteLine("excess: " + Speciation.excessCount(initialGenome, initialGenome1)); Console.Write("\n"); GeneratePopulation population = new GeneratePopulation(4); population.addGenomeToPopulation(new Genome(initialGenome)); population.addGenomeToPopulation(new Genome(initialGenome1)); population.addGenomeToPopulation(new Genome(initialGenome2)); population.addGenomeToPopulation(new Genome(initialGenome3)); for (int i = 0; i < 60; i++) { population.sortGenomesIntoSpecies(random); population.addAdjustedFitness(); population.fillNextGeneration(random); Console.WriteLine("\n Generation: " + i); // foreach(Species s in population.getSpeciesList()) { // Console.WriteLine("New Species "); // foreach(Genome g in s.getGenomesList()) { // Console.WriteLine("Genome fitness: " + g.getFitness()); // } // } } //-------------------------------------------------------------------------------- // Console.WriteLine("Parent1"); // foreach(KeyValuePair<int, NodeGene> n in initialGenome.getNodes()) { // Console.WriteLine("ID: " + n.Value.getNodeNumber() + " Layer: " + n.Value.getNodeType()); // } // Console.Write("\n"); // foreach(KeyValuePair<int, ConnectionGene> c in initialGenome.getConnections()) { // Console.WriteLine("In: " + c.Value.getIn() + " Out: " + c.Value.getOut() + " Innov: " + c.Value.getInnovationNumber() + " Enabled: " + c.Value.getEnabled() + " Weight: " + c.Value.getWeight()); // } // Console.Write("\n"); // Console.WriteLine("Parent2"); // foreach(KeyValuePair<int, NodeGene> n in initialGenome2.getNodes()) { // Console.WriteLine("ID: " + n.Value.getNodeNumber() + " Layer: " + n.Value.getNodeType()); // } // Console.Write("\n"); // foreach(KeyValuePair<int, ConnectionGene> c in initialGenome2.getConnections()) { // Console.WriteLine("In: " + c.Value.getIn() + " Out: " + c.Value.getOut() + " Innov: " + c.Value.getInnovationNumber() + " Enabled: " + c.Value.getEnabled() + " Weight: " + c.Value.getWeight()); // } // Console.Write("\n"); // Genome child = Evolution.crossover(random, initialGenome, initialGenome2); // Console.WriteLine("Child"); // foreach(KeyValuePair<int, NodeGene> n in child.getNodes()) { // Console.WriteLine("ID: " + n.Value.getNodeNumber() + " Layer: " + n.Value.getNodeType()); // } // Console.Write("\n"); // foreach(KeyValuePair<int, ConnectionGene> c in child.getConnections()) { // Console.WriteLine("In: " + c.Value.getIn() + " Out: " + c.Value.getOut() + " Innov: " + c.Value.getInnovationNumber() + " Enabled: " + c.Value.getEnabled() + " Weight: " + c.Value.getWeight()); // } //------------------------------------------------------------------------------------------------------------------------------------------------------------ // Console.WriteLine(Speciation.compatibilityDistance(initialGenome, initialGenome2)); //------------------------------------------------------------------------------------------------------------------------------------------------------------ // GeneratePopulation population = new GeneratePopulation(4); // population.addGenomeToPopulation(new Genome(initialGenome)); // population.addGenomeToPopulation(new Genome(initialGenome1)); // population.addGenomeToPopulation(new Genome(initialGenome2)); // population.addGenomeToPopulation(new Genome(initialGenome3)); // GeneratePopulation population = new GeneratePopulation(50); // for(int i = 0; i < population.getPopulationSize(); i++) { // population.addGenomeToPopulation(new Genome(initialGenome)); // } // print connection genes // Console.WriteLine("CONNECTION GENES: "); // foreach(ConnectionGene gene in initialGenome.connections) { // Console.WriteLine("IN: " + gene.getIn() + " OUT: " + gene.getOut() + " WEIGHT: " + gene.getWeight() + " ENABLED: " + gene.getEnabled() + " INNO: " + gene.getInnovationNumber()); // } // Console.WriteLine("\n"); // for(int i = 1; i < 20; i++) { // bestGen = population.GenerateNextGeneration(random); // Console.Write(" Generation: " + i); // // Console.Write(", Species Count: " + population.getSpeciesList().Count); // Console.Write(", Highest Fitness: " + population.getHighestScore() + "\n"); // } }
public void Check_Connection_Weights() { Assert.AreEqual(-0.9f, genome.getConnections()[genome.getInnovationNumbers()[0]].getWeight()); }
public void Length_After_Connection_Mutation() { genome.addConnectionMutation(random); Assert.AreEqual(6, genome.getConnections().Count); }