private void AddGeneFromOther(Gene curr1, Gene curr2, Dictionary <int, Node> dict, Random rnd, SortedList <int, Gene> genes) { var gene = curr2.ShallowCopy(); AddNodesToDictIfNotIn(dict, gene); // Layers are not OK gene.Type = (curr2.CrossoverChildDisabled(rnd, curr1)) ? GeneType.Enabled : GeneType.Disabled; genes.Add(gene.Innovation, gene); // Correct Layers from more fit parent A.K.A. this genome gene.In.Layer = curr1.In.Layer; gene.Out.Layer = curr1.Out.Layer; }
/// <summary> /// Add nodes to random connection gene in genome /// </summary> private void AddNode(Random rnd, ref int innovation, ref int number, List <Gene> allGenes) { int index = rnd.Next(0, Genes.Count); var pair = Genes.ElementAt(index); Gene gene = pair.Value; gene.Type = GeneType.Disabled; Node node = null; Gene firstGene = null; Gene latterGene = null; bool exists = FindExistingNode(gene, ref node, ref firstGene, ref latterGene, allGenes, ref innovation, ref number); if (!exists) { node = new Node(NodeType.Hidden, gene.In.Layer + 1, ++number); firstGene = new Gene(gene.In, node, 1f, GeneType.Enabled, ++innovation); latterGene = new Gene(node, gene.Out, gene.Weight, GeneType.Enabled, ++innovation); } // Check if the latter gene connection cannot be from the same layer to the same layer if (gene.Out.Layer == node.Layer) { IncrementLayer(node); } if (!Genes.ContainsKey(firstGene.Innovation)) // should always go to if branch { Genes.Add(firstGene.Innovation, firstGene); firstGene.In.OutgoingConnections.Add(firstGene); if (!exists) { var g = firstGene.ShallowCopy(); g.Type = GeneType.AddNode; allGenes.Add(g); // still points to nodes in this genome } } else { ; } if (!Genes.ContainsKey(latterGene.Innovation)) // should always go to if branch { Genes.Add(latterGene.Innovation, latterGene); latterGene.In.OutgoingConnections.Add(latterGene); if (!exists) { var g = latterGene.ShallowCopy(); g.Type = GeneType.AddNode; allGenes.Add(g); // still points to nodes in this genome } } else { ; } if (!Nodes.Contains(node)) // should always go to if branch { Nodes.Add(node); } else { for (int i = 0; i < Nodes.Count; i++) { if (node.Number == Nodes[i].Number) { if (ReferenceEquals(node, Nodes[i])) { ; } else { ; } } } } }
/// <summary> /// Fitness of this is greater than or equal to fitness of other /// </summary> /// <returns>child of this and other</returns> internal Genome Crossover(Genome other, Random rnd, bool sameFitness, int disableChance = 75) { var enumThis = Genes.GetEnumerator(); var enumOther = other.Genes.GetEnumerator(); var dict = new Dictionary <int, Node>(); SortedList <int, Gene> genes = new SortedList <int, Gene>(Genes.Count); Gene curr1 = enumThis.MoveNext() ? enumThis.Current.Value : new Gene(null, null, 0f, GeneType.Enabled, -1); Gene curr2 = enumOther.MoveNext() ? enumOther.Current.Value : new Gene(null, null, 0f, GeneType.Enabled, -1); while (true) { if (curr1.Innovation == curr2.Innovation) { if (curr1.Innovation == -1) { break; } if (rnd.Next(0, 100) > 50) { AddGeneFromThis(curr1, curr2, dict, rnd, genes); } else { AddGeneFromOther(curr1, curr2, dict, rnd, genes); } curr1 = enumThis.MoveNext() ? enumThis.Current.Value : new Gene(null, null, 0f, GeneType.Enabled, -1); curr2 = enumOther.MoveNext() ? enumOther.Current.Value : new Gene(null, null, 0f, GeneType.Enabled, -1); } else if (curr1.Innovation < curr2.Innovation) { if (curr1.Innovation == -1) { if (sameFitness) { AddGeneFromThis(curr2, curr1, dict, rnd, genes); } curr2 = enumOther.MoveNext() ? enumOther.Current.Value : new Gene(null, null, 0f, GeneType.Enabled, -1); } else { AddGeneFromThis(curr1, curr2, dict, rnd, genes); curr1 = enumThis.MoveNext() ? enumThis.Current.Value : new Gene(null, null, 0f, GeneType.Enabled, -1); } } else { if (curr2.Innovation == -1) { AddGeneFromThis(curr1, curr2, dict, rnd, genes); curr1 = enumThis.MoveNext() ? enumThis.Current.Value : new Gene(null, null, 0f, GeneType.Enabled, -1); } else { if (sameFitness) { AddGeneFromThis(curr2, curr1, dict, rnd, genes); } // THE OTHER GENE HAS LOWER FITNESS SO WHY ADD IT'S GENE ??? - case onlu with same fitness of genomes curr2 = enumOther.MoveNext() ? enumOther.Current.Value : new Gene(null, null, 0f, GeneType.Enabled, -1); } } } var nodes = new List <Node>(Nodes.Count); // Copy Nodes from Genes from Other Genome foreach (var item in dict) { nodes.Add(item.Value); } Node node; for (int i = 0; i < Nodes.Count; i++) { if (dict.TryGetValue(Nodes[i].Number, out node)) { ; } else { nodes.Add(Nodes[i].ShallowCopy()); } } nodes.Sort(new NodeNumberComparer()); var child = new Genome(nodes, genes, null); // CORRECT LAYER MESS if (sameFitness) { bool notdone = false; do { notdone = false; foreach (var item in genes) { var g = item.Value; while (g.In.Layer >= g.Out.Layer) { g.Out.Layer++; notdone = true; } } }while (notdone); } return(child); }