/// <summary> /// Validates that a gene is connected to an input node. /// </summary> /// <param name="gene">The gene being validated.</param> /// <param name="pathsChecked">A list of genes that have been traversed in the recursion.</param> /// <param name="excludeFrozen">Exclude frozen genes from validation (true network).</param> /// <returns>True if the gene is connected to an input node.</returns> private bool ValidateGeneBackward(Gene gene, List <Gene> pathsChecked, bool excludeFrozen) { NodeInformation origin = NodePool.FindById(gene.link.InNode); pathsChecked.Add(gene); if (origin.IsInput()) { return(true); } foreach (var path in Genes.Where(x => x.link.OutNode == gene.link.InNode && !pathsChecked.Contains(x))) { if (excludeFrozen && path.Frozen) { continue; } if (ValidateGeneBackward(path, pathsChecked, excludeFrozen)) { return(true); } } return(false); }
/// <summary> /// Retrieves the node information for all nodes in the genome. /// </summary> /// <returns>A dictionary of node id / node information pairs.</returns> public Dictionary <int, NodeInformation> GetAllNodeInformation(bool excludeFrozen) { List <Gene> genesToUse = Genes; if (excludeFrozen) { genesToUse = genesToUse.Where(x => !x.Frozen).ToList(); } Dictionary <int, NodeInformation> IdSet = new Dictionary <int, NodeInformation>(); foreach (var gene in genesToUse) { if (!IdSet.ContainsKey(gene.link.InNode)) { IdSet.Add(gene.link.InNode, NodePool.FindById(gene.link.InNode)); } if (!IdSet.ContainsKey(gene.link.OutNode)) { IdSet.Add(gene.link.OutNode, NodePool.FindById(gene.link.OutNode)); } } return(IdSet); }
/// <summary> /// Mutates a genome by breaking a connection up into two separate connections. /// </summary> /// <param name="genome">The genome to be modified.</param> /// <param name="innovationsSeen">A list of previously seen innovations.</param> /// <param name="rando">A random number generator.</param> public static void MutateAddNode(Genome genome, InnovationPool innovationsSeen, Random rando) { List <Gene> possibleConnections = new List <Gene>(genome.Genes); possibleConnections.RemoveAll(x => x.Frozen || NodePool.FindById(x.link.InNode).Type == NodeType.BIAS); if (possibleConnections.Count == 0) { return; } //TODO: Note in original algorithm saying uniform distribution is not optimal here. Gene geneToSplit = possibleConnections[rando.Next(possibleConnections.Count)]; geneToSplit.Frozen = true; ActivationStyle style = ActivationFunctions.ChooseActivationStyle(rando); InnovationInformation innovation = new InnovationInformation(geneToSplit.link, style); int firstConId = -1; int secondConId = -1; int registeredInnovationId = innovationsSeen.FindByInnovation(innovation); if (registeredInnovationId == -1) { int newNodeId = NodePool.Add(new NodeInformation(NodeType.HIDDEN, style)); ConnectionInformation firstConnect = new ConnectionInformation(geneToSplit.link.InNode, newNodeId); firstConId = ConnectionPool.Add(firstConnect); ConnectionInformation secondConnect = new ConnectionInformation(newNodeId, geneToSplit.link.OutNode); secondConId = ConnectionPool.Add(secondConnect); innovation.NewNodeDetails.NewNodeId = newNodeId; innovation.NewNodeDetails.FirstConnectionId = firstConId; innovation.NewNodeDetails.SecondConnectionId = secondConId; innovationsSeen.Add(innovation); } else { InnovationInformation registeredInnovation = innovationsSeen.FindById(registeredInnovationId); firstConId = registeredInnovation.NewNodeDetails.FirstConnectionId; secondConId = registeredInnovation.NewNodeDetails.SecondConnectionId; } genome.Genes.Add(new Gene(ConnectionPool.FindById(firstConId), firstConId, 1.0, false)); genome.Genes.Add(new Gene(ConnectionPool.FindById(secondConId), secondConId, geneToSplit.Weight, false)); }
/// <summary> /// Validates that a gene is connected to an output node. /// </summary> /// <param name="gene">The gene being validated.</param> /// <param name="pathsChecked">A list of genes that have been traversed in the recursion.</param> /// <param name="excludeFrozen">Exclude frozen genes from validation (true network).</param> /// <returns>True if the gene is connected to an output node.</returns> private bool ValidateGeneForward(Gene gene, List <Gene> pathsChecked, bool excludeFrozen) { pathsChecked.Add(gene); if (NodePool.FindById(gene.link.OutNode).Type == NodeType.OUTPUT) { return(true); } foreach (var path in Genes.Where(x => x.link.InNode == gene.link.OutNode && !pathsChecked.Contains(x))) { if (excludeFrozen && path.Frozen) { continue; } if (ValidateGeneForward(path, pathsChecked, excludeFrozen)) { return(true); } } return(false); }