/// <summary> /// Rebuild structure so we get layer information to make sure there are not circular dependencies. /// </summary> private void RebuildStructure() { // Clear the temporary node storage. TempNodes.Clear(); // Load all nodes for each connection gene. ConnectionGenes.ForEach(LoadNodes); // Find all the node in the connection genes. TempNodes.AddRange(ConnectionGenes.SelectMany(p => new[] { p.InNode, p.OutNode }).Distinct()); // Add all input nodes TempNodes.AddRange(Inputs.Select(p => p.InputNode)); // Add all output nodes. TempNodes.AddRange(Outputs.Select(p => p.OutputNode)); //Set all nodes to the lowest value so they don't keep older values. foreach (Node node in TempNodes) { if (!IsNodeAnOutputNode(node)) { SetLayer(node, uint.MinValue, true); } } foreach (Node node in TempNodes) { if (IsNodeAnOutputNode(node)) { // For each node of type OutputNode set the layer to 0 SetLayer(node, 0); } else if (IsNodeAnInputNode(node)) { // For each node of type InputNode set the layer to minimum value and force to true. SetLayer(node, uint.MaxValue, true); } } }
/// <summary> /// Rebuild structure so we get layer information to make sure there are not circular dependencies. /// </summary> private void RebuildStructure() { // Clear the temporary node storage. _tempNodes.Clear(); // Load all nodes for each connection gene. ConnectionGenes.ForEach(LoadNodes); // Find all the node in the connection genes. _tempNodes.AddRange(ConnectionGenes.SelectMany(p => new[] { p.InNode, p.OutNode }).Distinct()); // Add all input nodes _tempNodes.AddRange(Inputs.Select(p => p.InputNode)); // Add all output nodes. _tempNodes.AddRange(Outputs.Select(p => p.OutputNode)); // For each node of type OutputNode set the layer to 0, otherwise set the layer to the minimum value and force to true. foreach (Node node in _tempNodes) { if (node is OutputNode) { SetLayer(node, 0); } else { SetLayer(node, uint.MinValue, true); } } // For each node of type InputNode set the layer to minimum value and force to true. foreach (InputNode node in _tempNodes.OfType <InputNode>()) { SetLayer(node, uint.MaxValue, true); } void SetLayer(Node node, uint layer, bool force = false) { // Set the layer depending on force and if the current layer is higher than the layer given. node.Layer = force ? layer : (layer > node.Layer ? layer : node.Layer); // If force is true, return early. if (force) { return; } // For each connection gene where the out node identifier is the same as the given node identifier // set the layer to the node's layer plus one. foreach (ConnectionGene connectionGene in ConnectionGenes) { if (connectionGene.OutNodeIdentifier.Equals(node.NodeIdentifier)) { SetLayer(connectionGene.InNode, node.Layer + 1); } } } void LoadNodes(ConnectionGene connectionGene) { // Get or create the In and Out nodes based on the given node identifiers. connectionGene.InNode = GetOrCreateNodeForNodeId(connectionGene.InNodeIdentifier); connectionGene.OutNode = GetOrCreateNodeForNodeId(connectionGene.OutNodeIdentifier); } Node GetOrCreateNodeForNodeId(uint nodeIdentifier) { // Tries to get a node for the given id, if not found returns a default. Node node = GetNodeForId(nodeIdentifier); // If the node is not equal to default return the given node. if (node != default) { return(node); } // Tries to find the node in the hidden nodes list, if not found returns a default. node = _hiddenNodes.FirstOrDefault(n => n.NodeIdentifier == nodeIdentifier); // If the node is not equal to default return the given node. if (node != default) { return(node); } // If no node was found then create a hidden node. node = new HiddenNode(nodeIdentifier); // Add it to the hidden nodes list. _hiddenNodes.Add((HiddenNode)node); // Return the hidden node. return(node); } Node GetNodeForId(uint nodeIdentifier) { // Tries to find the first relation where the input node has the given identifier or return default. OrganismInputNode organismInputNode = Inputs.FirstOrDefault(n => n.InputNode.NodeIdentifier == nodeIdentifier); // if the organism input node is not default return the input node. if (organismInputNode != default) { return(organismInputNode.InputNode); } // Tries to find the first relation where the output node has the given identifier, else return default. return(Outputs.FirstOrDefault(n => n.OutputNode.NodeIdentifier == nodeIdentifier)?.OutputNode); } }