/// <summary> /// Returns true if there is at least one connectivity cycle within the provided INetworkDefinition. /// </summary> public bool IsNetworkCyclicInternal(INetworkDefinition networkDef) { // Clear any existing state (allow reuse of this class). _ancestorNodeSet.Clear(); _visitedNodeSet.Clear(); // Get and store connectivity data for the network. _networkConnectivityData = networkDef.GetConnectivityData(); // Loop over all nodes. Take each one in turn as a traversal root node. foreach(INetworkNode node in networkDef.NodeList) { // Determine if the node has already been visited. if(_visitedNodeSet.Contains(node.Id)) { // Already traversed; Skip. continue; } // Traverse into the node. if(TraverseNode(node.Id)) { // Cycle detected. return true; } } // No cycles detected. return false; }
/// <summary> /// Creates a CyclicNetwork from an INetworkDefinition. /// </summary> public static CyclicNetwork CreateCyclicNetwork(INetworkDefinition networkDef, NetworkActivationScheme activationScheme) { List <Neuron> neuronList; List <Connection> connectionList; InternalDecode(networkDef, out neuronList, out connectionList); // Construct neural net. if (activationScheme.RelaxingActivation) { return(new RelaxingCyclicNetwork(neuronList, connectionList, networkDef.InputNodeCount, networkDef.OutputNodeCount, activationScheme.MaxTimesteps, activationScheme.SignalDeltaThreshold)); } return(new CyclicNetwork(neuronList, connectionList, networkDef.InputNodeCount, networkDef.OutputNodeCount, activationScheme.TimestepsPerActivation)); }
/// <summary> /// Writes an INetworkDefinition to XML. /// </summary> /// <param name="xw">XmlWriter to write XML to.</param> /// <param name="networkDef">Network definition to write as XML.</param> /// <param name="nodeFnIds">Indicates if node activation function IDs should be emitted. They are required /// for HyperNEAT genomes but not for NEAT.</param> public static void Write(XmlWriter xw, INetworkDefinition networkDef, bool nodeFnIds) { xw.WriteStartElement(__ElemNetwork); // Emit nodes. xw.WriteStartElement(__ElemNodes); foreach (INetworkNode node in networkDef.NodeList) { xw.WriteStartElement(__ElemNode); xw.WriteAttributeString(__AttrType, GetNodeTypeString(node.NodeType)); xw.WriteAttributeString(__AttrId, node.Id.ToString(NumberFormatInfo.InvariantInfo)); if (nodeFnIds) { xw.WriteAttributeString(__AttrActivationFunctionId, node.ActivationFnId.ToString(NumberFormatInfo.InvariantInfo)); } xw.WriteEndElement(); } xw.WriteEndElement(); // Emit connections. xw.WriteStartElement(__ElemConnections); foreach (INetworkConnection con in networkDef.ConnectionList) { xw.WriteStartElement(__ElemConnection); xw.WriteAttributeString(__AttrSourceId, con.SourceNodeId.ToString(NumberFormatInfo.InvariantInfo)); xw.WriteAttributeString(__AttrTargetId, con.TargetNodeId.ToString(NumberFormatInfo.InvariantInfo)); xw.WriteAttributeString(__AttrWeight, con.Weight.ToString("R", NumberFormatInfo.InvariantInfo)); xw.WriteEndElement(); } xw.WriteEndElement(); // </Network> xw.WriteEndElement(); }
/// <summary> /// Returns true if there is at least one connectivity cycle within the provided INetworkDefinition. /// </summary> public bool IsNetworkCyclicInternal(INetworkDefinition networkDef) { // Clear any existing state (allow reuse of this class). _ancestorNodeSet.Clear(); _visitedNodeSet.Clear(); // Get and store connectivity data for the network. _networkConnectivityData = networkDef.GetConnectivityData(); // Loop over all nodes. Take each one in turn as a traversal root node. foreach (INetworkNode node in networkDef.NodeList) { // Determine if the node has already been visited. if (_visitedNodeSet.Contains(node.Id)) { // Already traversed; Skip. continue; } // Traverse into the node. if (TraverseNode(node.Id)) { // Cycle detected. return(true); } } // No cycles detected. return(false); }
/// <summary> /// Creates a CyclicNetwork from an INetworkDefinition. /// </summary> public static FastCyclicNetwork CreateFastCyclicNetwork(INetworkDefinition networkDef, NetworkActivationScheme activationScheme) { FastConnection[] fastConnectionArray; IActivationFunction[] activationFnArray; double[][] neuronAuxArgsArray; InternalDecode(networkDef, activationScheme.RelaxingActivation ? activationScheme.MaxTimesteps : activationScheme.TimestepsPerActivation, out fastConnectionArray, out activationFnArray, out neuronAuxArgsArray); // Construct neural net. if(activationScheme.RelaxingActivation) { return new FastRelaxingCyclicNetwork(fastConnectionArray, activationFnArray, neuronAuxArgsArray, networkDef.NodeList.Count, networkDef.InputNodeCount, networkDef.OutputNodeCount, activationScheme.MaxTimesteps, activationScheme.SignalDeltaThreshold); } return new FastCyclicNetwork(fastConnectionArray, activationFnArray, neuronAuxArgsArray, networkDef.NodeList.Count, networkDef.InputNodeCount, networkDef.OutputNodeCount, activationScheme.TimestepsPerActivation); }
/// <summary> /// Creates a CyclicNetwork from an INetworkDefinition. /// </summary> public static FastCyclicNetwork CreateFastCyclicNetwork(INetworkDefinition networkDef, NetworkActivationScheme activationScheme, bool boundedOutput) { FastConnection[] fastConnectionArray; IActivationFunction[] activationFnArray; double[][] neuronAuxArgsArray; InternalDecode(networkDef, activationScheme.RelaxingActivation ? activationScheme.MaxTimesteps : activationScheme.TimestepsPerActivation, out fastConnectionArray, out activationFnArray, out neuronAuxArgsArray); // Construct neural net. if (activationScheme.RelaxingActivation) { return(new FastRelaxingCyclicNetwork(fastConnectionArray, activationFnArray, neuronAuxArgsArray, networkDef.NodeList.Count, networkDef.InputNodeCount, networkDef.OutputNodeCount, activationScheme.MaxTimesteps, activationScheme.SignalDeltaThreshold, boundedOutput)); } return(new FastCyclicNetwork(fastConnectionArray, activationFnArray, neuronAuxArgsArray, networkDef.NodeList.Count, networkDef.InputNodeCount, networkDef.OutputNodeCount, activationScheme.TimestepsPerActivation, boundedOutput)); }
static void HandleNewBestNetwork(INetworkDefinition networkDefinition) { graphViewportPainter.IOGraph = graphFactory.CreateGraph(networkDefinition); form.Invoke((MethodInvoker) delegate { graphControl.RefreshImage(); }); }
public BitcoinNetworkProtocolMessageSerializer(ILogger <BitcoinNetworkProtocolMessageSerializer> logger, INetworkDefinition chainDefinition, INetworkMessageSerializerManager networkMessageSerializerManager) { _logger = logger; _chainDefinition = chainDefinition; _networkMessageSerializerManager = networkMessageSerializerManager; _deserializationContext = new DeserializationContext(chainDefinition.MagicBytes); _peerContext = null !; //initialized by SetPeerContext }
public static XmlDocument Save(INetworkDefinition networkDef, bool nodeFnIds) { XmlDocument doc = new XmlDocument(); using (XmlWriter xw = doc.CreateNavigator().AppendChild()) { Write(xw, networkDef, nodeFnIds); } return(doc); }
public NetworkMessageDecoder(ILogger <NetworkMessageDecoder> logger, INetworkDefinition chainDefinition, INetworkMessageSerializerManager networkMessageSerializerManager, ConnectionContextData contextData) { this.logger = logger; this.chainDefinition = chainDefinition; this.networkMessageSerializerManager = networkMessageSerializerManager; this.ContextData = contextData; }
private static void InternalDecode(INetworkDefinition networkDef, out List <Neuron> neuronList, out List <Connection> connectionList) { // Build a list of neurons. INodeList nodeDefList = networkDef.NodeList; int nodeCount = nodeDefList.Count; neuronList = new List <Neuron>(nodeCount); // A dictionary of neurons keyed on their innovation ID. var neuronDictionary = new Dictionary <uint, Neuron>(nodeCount); // Loop neuron genes. IActivationFunctionLibrary activationFnLib = networkDef.ActivationFnLibrary; for (int i = 0; i < nodeCount; i++) { // Create a Neuron, add it to the neuron list and add an entry into neuronDictionary - // required for next loop. INetworkNode nodeDef = nodeDefList[i]; // Note that we explicitly translate between the two NeuronType enums even though // they define the same types and could therefore be cast from one to the other. // We do this to keep genome and phenome classes completely separated and also to // prevent bugs - e.g. if one of the enums is changed then TranslateNeuronType() will // need to be modified to prevent exceptions at runtime. Otherwise a silent bug may // be introduced. Neuron neuron = new Neuron(nodeDef.Id, nodeDef.NodeType, activationFnLib.GetFunction(nodeDef.ActivationFnId), nodeDef.AuxState); neuronList.Add(neuron); neuronDictionary.Add(nodeDef.Id, neuron); } // Build a list of connections. IConnectionList connectionDefList = networkDef.ConnectionList; int connectionCount = connectionDefList.Count; connectionList = new List <Connection>(connectionCount); // Loop connection genes. for (int i = 0; i < connectionCount; i++) { INetworkConnection connDef = connectionDefList[i]; connectionList.Add( new Connection(neuronDictionary[connDef.SourceNodeId], neuronDictionary[connDef.TargetNodeId], connDef.Weight)); } }
private static void InternalDecode(INetworkDefinition networkDef, int timestepsPerActivation, out FastConnection[] fastConnectionArray, out IActivationFunction[] activationFnArray, out double[][] neuronAuxArgsArray) { // Creates an array of FastConnection(s) that represent the // connectivity of the network. fastConnectionArray = CreateFastConnectionArray(networkDef); // TODO: Test/optimize heuristic - this is just back of envelope maths. // A rough heuristic to decide if we should sort fastConnectionArray // by source neuron index. The principle here is that each activation // loop will be about 2x faster (unconfirmed) if we sort fastConnectionArray, // but sorting takes about n*log2(n) operations. Therefore the // decision to sort depends on length of fastConnectionArray and // _timestepsPerActivation. Another factor here is that small // networks will fit into CPU caches and therefore will not appear // to speed up - however the unsorted data will 'scramble' CPU caches // more than they otherwise would have and thus may slow down other // threads (so we just keep it simple). double len = fastConnectionArray.Length; double timesteps = timestepsPerActivation; if ((len > 2) && (((len * Math.Log(len, 2)) + ((timesteps * len) / 2.0)) < (timesteps * len))) { // Sort fastConnectionArray by source neuron index. Array.Sort(fastConnectionArray, delegate(FastConnection x, FastConnection y) { // Use simple/fast diff method. return(x._srcNeuronIdx - y._srcNeuronIdx); }); } // Construct an array of neuron activation functions. Skip bias and // input neurons as these don't have an activation function // (because they aren't activated). INodeList nodeList = networkDef.NodeList; int nodeCount = nodeList.Count; IActivationFunctionLibrary activationFnLibrary = networkDef.ActivationFnLibrary; activationFnArray = new IActivationFunction[nodeCount]; neuronAuxArgsArray = new double[nodeCount][]; for (int i = 0; i < nodeCount; i++) { activationFnArray[i] = activationFnLibrary.GetFunction(nodeList[i].ActivationFnId); neuronAuxArgsArray[i] = nodeList[i].AuxState; } }
private static void InternalDecode(INetworkDefinition networkDef, out List<Neuron> neuronList, out List<Connection> connectionList) { // Build a list of neurons. INodeList nodeDefList = networkDef.NodeList; int nodeCount = nodeDefList.Count; neuronList = new List<Neuron>(nodeCount); // A dictionary of neurons keyed on their innovation ID. Dictionary<uint,Neuron> neuronDictionary = new Dictionary<uint,Neuron>(nodeCount); // Loop neuron genes. IActivationFunctionLibrary activationFnLib = networkDef.ActivationFnLibrary; for(int i=0; i<nodeCount; i++) { // Create a Neuron, add it to the neuron list and add an entry into neuronDictionary - // required for next loop. INetworkNode nodeDef = nodeDefList[i]; // Note that we explicitly translate between the two NeuronType enums even though // they define the same types and could therefore be cast from one to the other. // We do this to keep genome and phenome classes completely separated and also to // prevent bugs - e.g. if one of the enums is changed then TranslateNeuronType() will // need to be modified to prevent exceptions at runtime. Otherwise a silent bug may // be introduced. Neuron neuron = new Neuron(nodeDef.Id, nodeDef.NodeType, activationFnLib.GetFunction(nodeDef.ActivationFnId), nodeDef.AuxState); neuronList.Add(neuron); neuronDictionary.Add(nodeDef.Id, neuron); } // Build a list of connections. IConnectionList connectionDefList = networkDef.ConnectionList; int connectionCount = connectionDefList.Count; connectionList = new List<Connection>(connectionCount); // Loop connection genes. for(int i=0; i<connectionCount; i++) { INetworkConnection connDef = connectionDefList[i]; connectionList.Add( new Connection(neuronDictionary[connDef.SourceNodeId], neuronDictionary[connDef.TargetNodeId], connDef.Weight)); } }
public PeerConnectionFactory(ILoggerFactory loggerFactory, IEventBus eventBus, IPeerContextFactory peerContextFactory, INetworkDefinition chainDefinition, INetworkMessageProcessorFactory networkMessageProcessorFactory, INetworkMessageSerializerManager networkMessageSerializerManager) { this.loggerFactory = loggerFactory; this.eventBus = eventBus; this.peerContextFactory = peerContextFactory; this.chainDefinition = chainDefinition; this.networkMessageProcessorFactory = networkMessageProcessorFactory; this.networkMessageSerializerManager = networkMessageSerializerManager; this.logger = loggerFactory.CreateLogger <PeerConnectionFactory>(); }
/// <summary> /// Calculate node depths in an acyclic network. /// </summary> public NetworkDepthInfo CalculateNodeDepths(INetworkDefinition networkDef) { // Clear any existing state (allow reuse of this class). _nodeDepthById.Clear(); // Get and store connectivity data for the network. _networkConnectivityData = networkDef.GetConnectivityData(); // Loop over all input (and bias) nodes; Perform a depth first traversal of each in turn. // Set of nodes visited in the current traversal (reset before each individual depth first traversal). HashSet <uint> visitedNodeSet = new HashSet <uint>(); int inputAndBiasCount = networkDef.InputNodeCount + 1; for (int i = 0; i < inputAndBiasCount; i++) { visitedNodeSet.Clear(); TraverseNode(_networkConnectivityData.GetNodeDataByIndex(i), visitedNodeSet, 0); } // Extract node depths from _nodeDepthById into an array of depths (node depth by node index). // Note. Any node not in the dictionary is in an isolated sub-network and will be assigned to // layer 0 by default. INodeList nodeList = networkDef.NodeList; int nodeCount = nodeList.Count; int[] nodeDepthArr = new int[nodeCount]; int maxDepth = 0; // Loop over nodes and set the node depth. Skip over input and bias nodes, they are defined as // being in layer zero. for (int i = inputAndBiasCount; i < nodeCount; i++) { // Lookup the node's depth. If not found depth remains set to zero. int depth; if (_nodeDepthById.TryGetValue(nodeList[i].Id, out depth)) { nodeDepthArr[i] = depth; // Also determine maximum depth, that is, total depth of the network. if (depth > maxDepth) { maxDepth = depth; } } } // Return depth analysis info. return(new NetworkDepthInfo(maxDepth + 1, nodeDepthArr)); }
/// <summary> /// Decodes a CPPN NeatGenome to a concrete network instance via a HyperNEAT substrate. /// </summary> public IBlackBox Decode(NeatGenome genome) { // Decode the CPPN. IBlackBox cppn = _decodeCppnMethod(genome); // Generate a network definition from the CPPN and Substrate. INetworkDefinition substrateNetworkDef = _substrate.CreateNetworkDefinition(cppn, _lengthCppnInput); // Check for null network. This can happen if, e.g. querying the substrate did not result in any connections. if (null == substrateNetworkDef) { return(null); } // Create a network from the substrate network definition, and return it. return(_createSubstrateNetworkMethod(substrateNetworkDef)); }
/// <summary> /// Calculate node depths in an acyclic network. /// </summary> public NetworkDepthInfo CalculateNodeDepths(INetworkDefinition networkDef) { // Clear any existing state (allow reuse of this class). _nodeDepthById.Clear(); // Get and store connectivity data for the network. _networkConnectivityData = networkDef.GetConnectivityData(); // Loop over all input (and bias) nodes; Perform a depth first traversal of each in turn. // Set of nodes visited in the current traversal (reset before each individual depth first traversal). HashSet<uint> visitedNodeSet = new HashSet<uint>(); int inputAndBiasCount = networkDef.InputNodeCount + 1; for(int i=0; i<inputAndBiasCount; i++) { visitedNodeSet.Clear(); TraverseNode(_networkConnectivityData.GetNodeDataByIndex(i), visitedNodeSet, 0); } // Extract node depths from _nodeDepthById into an array of depths (node depth by node index). // Note. Any node not in the dictionary is in an isolated sub-network and will be assigned to // layer 0 by default. INodeList nodeList = networkDef.NodeList; int nodeCount = nodeList.Count; int[] nodeDepthArr = new int[nodeCount]; int maxDepth = 0; // Loop over nodes and set the node depth. Skip over input and bias nodes, they are defined as // being in layer zero. for(int i=inputAndBiasCount; i<nodeCount; i++) { // Lookup the node's depth. If not found depth remains set to zero. int depth; if(_nodeDepthById.TryGetValue(nodeList[i].Id, out depth)) { nodeDepthArr[i] = depth; // Also determine maximum depth, that is, total depth of the network. if(depth > maxDepth) { maxDepth = depth; } } } // Return depth analysis info. return new NetworkDepthInfo(maxDepth+1, nodeDepthArr); }
/// <summary> /// Writes a single INetworkDefinition to XML within a containing 'Root' element and the activation /// function library that the genome is associated with. /// </summary> /// <param name="xw">XmlWriter to write XML to.</param> /// <param name="networkDef">Network definition to write as XML.</param> /// <param name="nodeFnIds">Indicates if node activation function IDs should be emitted. They are required /// for HyperNEAT genomes but not for NEAT.</param> public static void WriteComplete(XmlWriter xw, INetworkDefinition networkDef, bool nodeFnIds) { // <Root> xw.WriteStartElement(__ElemRoot); // Write activation function library. Write(xw, networkDef.ActivationFnLibrary); // <Networks> xw.WriteStartElement(__ElemNetworks); // Write single network. Write(xw, networkDef, nodeFnIds); // </Networks> xw.WriteEndElement(); // </Root> xw.WriteEndElement(); }
private static void InternalDecode(INetworkDefinition networkDef, int timestepsPerActivation, out FastConnection[] fastConnectionArray, out IActivationFunction[] activationFnArray, out double[][] neuronAuxArgsArray) { // Create an array of FastConnection(s) that represent the connectivity of the network. fastConnectionArray = CreateFastConnectionArray(networkDef); // TODO: Test/optimize heuristic - this is just back of envelope maths. // A rough heuristic to decide if we should sort fastConnectionArray by source neuron index. // The principle here is that each activation loop will be about 2x faster (unconfirmed) if we sort // fastConnectionArray, but sorting takes about n*log2(n) operations. Therefore the decision to sort // depends on length of fastConnectionArray and _timestepsPerActivation. // Another factor here is that small networks will fit into CPU caches and therefore will not appear // to speed up - however the unsorted data will 'scramble' CPU caches more than they otherwise would // have and thus may slow down other threads (so we just keep it simple). double len = fastConnectionArray.Length; double timesteps = timestepsPerActivation; if((len > 2) && (((len * Math.Log(len,2)) + ((timesteps * len)/2.0)) < (timesteps * len))) { // Sort fastConnectionArray by source neuron index. Array.Sort(fastConnectionArray, delegate(FastConnection x, FastConnection y) { // Use simple/fast diff method. return x._srcNeuronIdx - y._srcNeuronIdx; }); } // Construct an array of neuron activation functions. Skip bias and input neurons as // these don't have an activation function (because they aren't activated). INodeList nodeList = networkDef.NodeList; int nodeCount = nodeList.Count; IActivationFunctionLibrary activationFnLibrary = networkDef.ActivationFnLibrary; activationFnArray = new IActivationFunction[nodeCount]; neuronAuxArgsArray = new double[nodeCount][]; for(int i=0; i<nodeCount; i++) { activationFnArray[i] = activationFnLibrary.GetFunction(nodeList[i].ActivationFnId); neuronAuxArgsArray[i] = nodeList[i].AuxState; } }
/// <summary> /// Creates a CyclicNetwork from an INetworkDefinition. /// </summary> public static CyclicNetwork CreateCyclicNetwork(INetworkDefinition networkDef, NetworkActivationScheme activationScheme) { List<Neuron> neuronList; List<Connection> connectionList; InternalDecode(networkDef, out neuronList, out connectionList); // Construct neural net. if(activationScheme.RelaxingActivation) { return new RelaxingCyclicNetwork(neuronList, connectionList, networkDef.InputNodeCount, networkDef.OutputNodeCount, activationScheme.MaxTimesteps, activationScheme.SignalDeltaThreshold); } return new CyclicNetwork(neuronList, connectionList, networkDef.InputNodeCount, networkDef.OutputNodeCount, activationScheme.TimestepsPerActivation); }
public static void Write(XmlWriter xw, INetworkDefinition networkDef, bool nodeFnIds) { xw.WriteStartElement(__ElemNetwork); xw.WriteStartElement(__ElemNodes); foreach (var node in networkDef.NodeList) { xw.WriteStartElement(__ElemNode); xw.WriteAttributeString(__AttrType, NetworkXmlIO.GetNodeTypeString(node.NodeType)); xw.WriteAttributeString(__AttrId, node.Id.ToString(NumberFormatInfo.InvariantInfo)); if (nodeFnIds) { // Write activation fn ID. xw.WriteAttributeString(__AttrActivationFunctionId, node.ActivationFnId.ToString(NumberFormatInfo.InvariantInfo)); // Write aux state as comma separated list of real values. XmlIoUtils.WriteAttributeString(xw, __AttrAuxState, node.AuxState); } xw.WriteEndElement(); } xw.WriteEndElement(); // Emit connections. xw.WriteStartElement(__ElemConnections); foreach (INetworkConnection connection in networkDef.ConnectionList) { xw.WriteStartElement(__ElemConnection); xw.WriteAttributeString(__AttrSourceId, connection.SourceNodeId.ToString(NumberFormatInfo.InvariantInfo)); xw.WriteAttributeString(__AttrTargetId, connection.TargetNodeId.ToString(NumberFormatInfo.InvariantInfo)); xw.WriteAttributeString(__AttrWeight, connection.Weight.ToString("R", NumberFormatInfo.InvariantInfo)); xw.WriteEndElement(); } xw.WriteEndElement(); // </Network> xw.WriteEndElement(); }
/// <summary> /// Create an IOGraph that represents the structure described by the provided INetworkDefinition. /// </summary> public IOGraph CreateGraph(INetworkDefinition networkDef) { // Perform depth analysis of network. NetworkDepthInfo depthInfo; if (networkDef.IsAcyclic) { AcyclicNetworkDepthAnalysis depthAnalysis = new AcyclicNetworkDepthAnalysis(); depthInfo = depthAnalysis.CalculateNodeDepths(networkDef); } else { CyclicNetworkDepthAnalysis depthAnalysis = new CyclicNetworkDepthAnalysis(); depthInfo = depthAnalysis.CalculateNodeDepths(networkDef); } // Create an IOGraph, allocating storage for the node lists. INodeList nodeList = networkDef.NodeList; int nodeCount = nodeList.Count; int inputCount = networkDef.InputNodeCount + 1; // + to count bias as an input layer node. int outputCount = networkDef.OutputNodeCount; int hiddenCount = nodeCount - (inputCount + outputCount); IOGraph ioGraph = new IOGraph(inputCount, outputCount, hiddenCount, 0f, depthInfo._networkDepth); // We also build a dictionary of nodes keyed by innovation ID. This is used later // to assign connections to nodes. Dictionary <uint, GraphNode> nodeDict = new Dictionary <uint, GraphNode>(nodeCount); // Loop input nodes. int idx = 0; for (int i = 0; i < inputCount; i++, idx++) { // Create node, assign it a tag and add it to the node dictionary and the // input node list of the IOGraph. uint innovationId = nodeList[idx].Id; GraphNode node = new GraphNode(innovationId.ToString()); node.AuxData = CreateGraphNodeAuxData(nodeList[idx]); node.Depth = depthInfo._nodeDepthArr[idx]; nodeDict.Add(innovationId, node); ioGraph.InputNodeList.Add(node); } // Loop output nodes. for (int i = 0; i < outputCount; i++, idx++) { // Create node, assign it a tag and add it to the node dictionary and the // output node list of the IOGraph. uint innovationId = nodeList[idx].Id; GraphNode node = new GraphNode(innovationId.ToString()); node.AuxData = CreateGraphNodeAuxData(nodeList[idx]); node.Depth = depthInfo._nodeDepthArr[idx]; nodeDict.Add(innovationId, node); ioGraph.OutputNodeList.Add(node); } // Loop hidden nodes. for (; idx < nodeCount; idx++) { // Create node, assign it a tag and add it to the node dictionary and the // hidden node list of the IOGraph. uint innovationId = nodeList[idx].Id; GraphNode node = new GraphNode(innovationId.ToString()); node.AuxData = CreateGraphNodeAuxData(nodeList[idx]); node.Depth = depthInfo._nodeDepthArr[idx]; nodeDict.Add(innovationId, node); ioGraph.HiddenNodeList.Add(node); } // Loop connections. Build GraphConnection objects and connect them to their source // and target nodes. double maxAbsWeight = 0.1; // Start at a non-zero value to prevent possibility of a divide by zero occuring. IConnectionList connectionList = networkDef.ConnectionList; int connCount = connectionList.Count; for (int i = 0; i < connCount; i++) { // Create connection object and assign its source and target nodes. INetworkConnection connection = connectionList[i]; GraphNode sourceNode = nodeDict[connection.SourceNodeId]; GraphNode targetNode = nodeDict[connection.TargetNodeId]; GraphConnection conn = new GraphConnection(sourceNode, targetNode, (float)connection.Weight); // Add the connection to the connection lists on the source and target nodes. sourceNode.OutConnectionList.Add(conn); targetNode.InConnectionList.Add(conn); // Track weight range oevr all connections. double absWeight = Math.Abs(connection.Weight); if (absWeight > maxAbsWeight) { maxAbsWeight = absWeight; } } ioGraph.ConnectionWeightRange = (float)maxAbsWeight; return(ioGraph); }
private void SaveNetworkDefinitionToFile(INetworkDefinition champ, string fileName) { NeatGenomeXmlIO.Save(champ, true).Save(fileName); }
/// <summary> /// Returns true if there is at least one connectivity cycle within the provided INetworkDefinition. /// </summary> public static bool IsNetworkCyclic(INetworkDefinition networkDef) { return(new CyclicNetworkTest().IsNetworkCyclicInternal(networkDef)); }
/// <summary> /// Creates a AcyclicNetwork from an INetworkDefinition. /// </summary> public static FastAcyclicNetwork CreateFastAcyclicNetwork(INetworkDefinition networkDef) { Debug.Assert(!CyclicNetworkTest.IsNetworkCyclic(networkDef), "Attempt to decode a cyclic network into a FastAcyclicNetwork."); // Determine the depth of each node in the network. // Node depths are used to separate the nodes into depth based layers, these layers can then be // used to determine the order in which signals are propagated through the network. AcyclicNetworkDepthAnalysis depthAnalysis = new AcyclicNetworkDepthAnalysis(); NetworkDepthInfo netDepthInfo = depthAnalysis.CalculateNodeDepths(networkDef); // Construct an array of NodeInfo, ordered by node depth. // Create/populate NodeInfo array. int[] nodeDepthArr = netDepthInfo._nodeDepthArr; INodeList nodeList = networkDef.NodeList; int nodeCount = nodeList.Count; NodeInfo[] nodeInfoByDepth = new NodeInfo[nodeCount]; for (int i = 0; i < nodeCount; i++) { nodeInfoByDepth[i]._nodeId = nodeList[i].Id; nodeInfoByDepth[i]._definitionIdx = i; nodeInfoByDepth[i]._nodeDepth = nodeDepthArr[i]; } // Sort NodeInfo array. // We use an IComparer here because an anonymous method is not accepted on the method overload that accepts // a sort range, which we use to avoid sorting the input and bias nodes. Sort() performs an unstable sort therefore // we must restrict the range of the sort to ensure the input and bias node indexes are unchanged. Restricting the // sort to the required range is also more efficient (less items to sort). int inputAndBiasCount = networkDef.InputNodeCount + 1; Array.Sort(nodeInfoByDepth, inputAndBiasCount, nodeCount - inputAndBiasCount, NodeDepthComparer.__NodeDepthComparer); // Array of live node indexes indexed by their index in the original network definition. This allows us to // locate the position of input and output nodes in their new positions in the live network data structures. int[] newIdxByDefinitionIdx = new int[nodeCount]; // Dictionary of live node indexes keyed by node ID. This allows us to convert the network definition connection // endpoints from node IDs to indexes into the live/runtime network data structures. Dictionary <uint, int> newIdxById = new Dictionary <uint, int>(nodeCount); // Populate both the lookup array and dictionary. for (int i = 0; i < nodeCount; i++) { NodeInfo nodeInfo = nodeInfoByDepth[i]; newIdxByDefinitionIdx[nodeInfo._definitionIdx] = i; newIdxById.Add(nodeInfo._nodeId, i); } // Make a copy of the sub-range of newIdxByDefinitionIdx that represents the output nodes. int outputCount = networkDef.OutputNodeCount; int[] outputNeuronIdxArr = new int[outputCount]; // Note. 'inputAndBiasCount' holds the index of the first output node. Array.Copy(newIdxByDefinitionIdx, inputAndBiasCount, outputNeuronIdxArr, 0, outputCount); // Construct arrays with additional 'per node' data/refs (activation functions, activation fn auxiliary data). IActivationFunctionLibrary activationFnLibrary = networkDef.ActivationFnLibrary; IActivationFunction[] nodeActivationFnArr = new IActivationFunction[nodeCount]; double[][] nodeAuxArgsArray = new double[nodeCount][]; for (int i = 0; i < nodeCount; i++) { int definitionIdx = nodeInfoByDepth[i]._definitionIdx; nodeActivationFnArr[i] = activationFnLibrary.GetFunction(nodeList[definitionIdx].ActivationFnId); nodeAuxArgsArray[i] = nodeList[definitionIdx].AuxState; } //=== Create array of FastConnection(s). // Loop the connections and lookup the node IDs for each connection's end points using newIdxById. IConnectionList connectionList = networkDef.ConnectionList; int connectionCount = connectionList.Count; FastConnection[] fastConnectionArray = new FastConnection[connectionCount]; for (int i = 0; i < connectionCount; i++) { INetworkConnection conn = connectionList[i]; fastConnectionArray[i]._srcNeuronIdx = newIdxById[conn.SourceNodeId]; fastConnectionArray[i]._tgtNeuronIdx = newIdxById[conn.TargetNodeId]; fastConnectionArray[i]._weight = conn.Weight; } // Sort fastConnectionArray by source node index. This allows us to activate the connections in the // order they are present within the network (by depth). We also secondary sort by target index to // improve CPU cache coherency of the data (in order accesses that are as close to each other as possible). Array.Sort(fastConnectionArray, delegate(FastConnection x, FastConnection y) { if (x._srcNeuronIdx < y._srcNeuronIdx) { return(-1); } if (x._srcNeuronIdx > y._srcNeuronIdx) { return(1); } // Secondary sort on target index. if (x._tgtNeuronIdx < y._tgtNeuronIdx) { return(-1); } if (x._tgtNeuronIdx > y._tgtNeuronIdx) { return(1); } // Connections are equal (this should not actually happen). return(0); }); // Create an array of LayerInfo(s). Each LayerInfo contains the index + 1 of both the last node and last // connection in that layer. // The array is in order of depth, from layer zero (bias and inputs nodes) to the last layer // (usually output nodes, but not necessarily if there is a dead end pathway with a high number of hops). // Note. There is guaranteed to be at least one connection with a source at a given depth level, this is // because for there to be a layer N there must necessarily be a connection from a node in layer N-1 // to a node in layer N. int netDepth = netDepthInfo._networkDepth; LayerInfo[] layerInfoArr = new LayerInfo[netDepth]; // Scanning over nodes can start at inputAndBiasCount instead of zero, // because we know that all nodes prior to that index are at depth zero. int nodeIdx = inputAndBiasCount; int connIdx = 0; for (int currDepth = 0; currDepth < netDepth; currDepth++) { // Scan for last node at the current depth. for (; nodeIdx < nodeCount && nodeInfoByDepth[nodeIdx]._nodeDepth == currDepth; nodeIdx++) { ; } // Scan for last connection at the current depth. for (; connIdx < fastConnectionArray.Length && nodeInfoByDepth[fastConnectionArray[connIdx]._srcNeuronIdx]._nodeDepth == currDepth; connIdx++) { ; } // Store node and connection end indexes for the layer. layerInfoArr[currDepth]._endNodeIdx = nodeIdx; layerInfoArr[currDepth]._endConnectionIdx = connIdx; } return(new FastAcyclicNetwork(nodeActivationFnArr, nodeAuxArgsArray, fastConnectionArray, layerInfoArr, outputNeuronIdxArr, nodeCount, networkDef.InputNodeCount, networkDef.OutputNodeCount)); }
/// <summary> /// Create an IOGraph that represents the structure described by the provided INetworkDefinition. /// </summary> public IOGraph CreateGraph(INetworkDefinition networkDef) { // Perform depth analysis of network. NetworkDepthInfo depthInfo; if(networkDef.IsAcyclic) { AcyclicNetworkDepthAnalysis depthAnalysis = new AcyclicNetworkDepthAnalysis(); depthInfo = depthAnalysis.CalculateNodeDepths(networkDef); } else { CyclicNetworkDepthAnalysis depthAnalysis = new CyclicNetworkDepthAnalysis(); depthInfo = depthAnalysis.CalculateNodeDepths(networkDef); } // Create an IOGraph, allocating storage for the node lists. INodeList nodeList = networkDef.NodeList; int nodeCount = nodeList.Count; int inputCount = networkDef.InputNodeCount + 1; // + to count bias as an input layer node. int outputCount = networkDef.OutputNodeCount; int hiddenCount = nodeCount - (inputCount + outputCount); IOGraph ioGraph = new IOGraph(inputCount, outputCount, hiddenCount, 0f, depthInfo._networkDepth); // We also build a dictionary of nodes keyed by innovation ID. This is used later // to assign connections to nodes. Dictionary<uint, GraphNode> nodeDict = new Dictionary<uint,GraphNode>(nodeCount); // Loop input nodes. int idx = 0; for(int i=0; i<inputCount; i++, idx++) { // Create node, assign it a tag and add it to the node dictionary and the // input node list of the IOGraph. uint innovationId = nodeList[idx].Id; GraphNode node = new GraphNode(innovationId.ToString()); node.AuxData = CreateGraphNodeAuxData(nodeList[idx]); node.Depth = depthInfo._nodeDepthArr[idx]; nodeDict.Add(innovationId, node); ioGraph.InputNodeList.Add(node); } // Loop output nodes. for(int i=0; i<outputCount; i++, idx++) { // Create node, assign it a tag and add it to the node dictionary and the // output node list of the IOGraph. uint innovationId = nodeList[idx].Id; GraphNode node = new GraphNode(innovationId.ToString()); node.AuxData = CreateGraphNodeAuxData(nodeList[idx]); node.Depth = depthInfo._nodeDepthArr[idx]; nodeDict.Add(innovationId, node); ioGraph.OutputNodeList.Add(node); } // Loop hidden nodes. for(; idx<nodeCount; idx++) { // Create node, assign it a tag and add it to the node dictionary and the // hidden node list of the IOGraph. uint innovationId = nodeList[idx].Id; GraphNode node = new GraphNode(innovationId.ToString()); node.AuxData = CreateGraphNodeAuxData(nodeList[idx]); node.Depth = depthInfo._nodeDepthArr[idx]; nodeDict.Add(innovationId, node); ioGraph.HiddenNodeList.Add(node); } // Loop connections. Build GraphConnection objects and connect them to their source // and target nodes. double maxAbsWeight = 0.1; // Start at a non-zero value to prevent possibility of a divide by zero occurring. IConnectionList connectionList = networkDef.ConnectionList; int connCount = connectionList.Count; for(int i=0; i<connCount; i++) { // Create connection object and assign its source and target nodes. INetworkConnection connection = connectionList[i]; GraphNode sourceNode = nodeDict[connection.SourceNodeId]; GraphNode targetNode = nodeDict[connection.TargetNodeId]; GraphConnection conn = new GraphConnection(sourceNode, targetNode, (float)connection.Weight); // Add the connection to the connection lists on the source and target nodes. sourceNode.OutConnectionList.Add(conn); targetNode.InConnectionList.Add(conn); // Track weight range over all connections. double absWeight = Math.Abs(connection.Weight); if(absWeight > maxAbsWeight) { maxAbsWeight = absWeight; } } ioGraph.ConnectionWeightRange = (float)maxAbsWeight; return ioGraph; }
private FastAcyclicNetwork CreateSubstrateNetwork_AcyclicNetwork(INetworkDefinition networkDef) { return(FastAcyclicNetworkFactory.CreateFastAcyclicNetwork(networkDef)); }
/// <summary> /// Create an array of FastConnection(s) representing the connectivity of the provided INetworkDefinition. /// </summary> private static FastConnection[] CreateFastConnectionArray(INetworkDefinition networkDef) { // We vary the decode logic depending on the size of the genome. The most CPU intensive aspect of // decoding is the conversion of the neuron IDs at connection endpoints into neuron indexes. For small // genomes we simply use the BinarySearch() method on NeuronGeneList for each lookup; Each lookup is // an operation with O(log n) time complexity. Thus for C connections and N neurons the number of operations // to perform all lookups is approximately = 2*C*Log(N) // // For larger genomes we invest time in building a Dictionary that maps neuron IDs to their indexes, this on the // basis that the time invested will be more than recovered in time saved performing lookups; The time complexity // of a dictionary lookup is near constant O(1). Thus number of operations is approximately = O(2*C*1) + the time // required to build the dictionary which is approximately O(N). // // Therefore the choice of lookup type is based on which of these two expressions gives the lowest value. // // Binary search. LookupOps = 2 * C * Log2(N) * x // Dictionary Search. LookupOps = (N * y) + (2 * C * z) // // Where x, y and z are constants that adjust for the relative speeds of the lookup and dictionary building operations. // Note that the actual time required to perform these separate algorithms is actually a far more complex problem, and // for modern CPUs exact times cannot be calculated because of large memory caches and superscalar architecture that // makes execution times in a real environment effectively non-deterministic. Thus these calculations are a rough // guide/heuristic that estimate which algorithm will perform best. The constants can be found experimentally but will // tend to vary depending on factors such as CPU and memory architecture, .Net framework version and what other tasks the // CPU is currently doing which may affect our utilisation of memory caches. // TODO: Experimentally determine reasonably good values for constants x,y and z in some common real world runtime platform. IConnectionList connectionList = networkDef.ConnectionList; INodeList nodeList = networkDef.NodeList; int connectionCount = connectionList.Count; int nodeCount = nodeList.Count; FastConnection[] fastConnectionArray = new FastConnection[connectionCount]; if((2.0 * connectionCount * Math.Log(nodeCount, 2.0)) < ((2.0 * connectionCount) + nodeCount)) { // Binary search requires items to be sorted. Debug.Assert(nodeList.IsSorted()); // Loop the connections and lookup the neuron IDs for each connection's end points using a binary search // on nGeneList. This is probably the quickest approach for small numbers of lookups. for(int i=0; i<connectionCount; i++) { INetworkConnection conn = connectionList[i]; fastConnectionArray[i]._srcNeuronIdx = nodeList.BinarySearch(conn.SourceNodeId); fastConnectionArray[i]._tgtNeuronIdx = nodeList.BinarySearch(conn.TargetNodeId); fastConnectionArray[i]._weight = conn.Weight; // Check that the correct neuron indexes were found. Debug.Assert( nodeList[fastConnectionArray[i]._srcNeuronIdx].Id == conn.SourceNodeId && nodeList[fastConnectionArray[i]._tgtNeuronIdx].Id == conn.TargetNodeId); } } else { // Build dictionary of neuron indexes keyed on neuron innovation ID. Dictionary<uint,int> neuronIndexDictionary = new Dictionary<uint,int>(nodeCount); for(int i=0; i<nodeCount; i++) { // ENHANCEMENT: Check if neuron innovation ID requires further manipulation to make a good hash code. neuronIndexDictionary.Add(nodeList[i].Id, i); } // Loop the connections and lookup the neuron IDs for each connection's end points using neuronIndexDictionary. // This is probably the quickest approach for large numbers of lookups. for(int i=0; i<connectionCount; i++) { INetworkConnection conn = connectionList[i]; fastConnectionArray[i]._srcNeuronIdx = neuronIndexDictionary[conn.SourceNodeId]; fastConnectionArray[i]._tgtNeuronIdx = neuronIndexDictionary[conn.TargetNodeId]; fastConnectionArray[i]._weight = conn.Weight; // Check that the correct neuron indexes were found. Debug.Assert( nodeList[fastConnectionArray[i]._srcNeuronIdx].Id == conn.SourceNodeId && nodeList[fastConnectionArray[i]._tgtNeuronIdx].Id == conn.TargetNodeId); } } return fastConnectionArray; }
private FastCyclicNetwork CreateSubstrateNetwork_FastCyclicNetwork(INetworkDefinition networkDef) { return(FastCyclicNetworkFactory.CreateFastCyclicNetwork(networkDef, _activationSchemeSubstrate)); }
/// <summary> /// Writes an INetworkDefinition to XML. /// </summary> /// <param name="xw">XmlWriter to write XML to.</param> /// <param name="networkDef">Network definition to write as XML.</param> /// <param name="nodeFnIds">Indicates if node activation function IDs should be emitted. They are required /// for HyperNEAT genomes but not for NEAT.</param> public static void Write(XmlWriter xw, INetworkDefinition networkDef, bool nodeFnIds) { xw.WriteStartElement(__ElemNetwork); // Emit nodes. xw.WriteStartElement(__ElemNodes); foreach(INetworkNode node in networkDef.NodeList) { xw.WriteStartElement(__ElemNode); xw.WriteAttributeString(__AttrType, GetNodeTypeString(node.NodeType)); xw.WriteAttributeString(__AttrId, node.Id.ToString(NumberFormatInfo.InvariantInfo)); if(nodeFnIds) { xw.WriteAttributeString(__AttrActivationFunctionId, node.ActivationFnId.ToString(NumberFormatInfo.InvariantInfo)); } xw.WriteEndElement(); } xw.WriteEndElement(); // Emit connections. xw.WriteStartElement(__ElemConnections); foreach(INetworkConnection con in networkDef.ConnectionList) { xw.WriteStartElement(__ElemConnection); xw.WriteAttributeString(__AttrSourceId, con.SourceNodeId.ToString(NumberFormatInfo.InvariantInfo)); xw.WriteAttributeString(__AttrTargetId, con.TargetNodeId.ToString(NumberFormatInfo.InvariantInfo)); xw.WriteAttributeString(__AttrWeight, con.Weight.ToString("R", NumberFormatInfo.InvariantInfo)); xw.WriteEndElement(); } xw.WriteEndElement(); // </Network> xw.WriteEndElement(); }
/// <summary> /// Returns true if there is at least one connectivity cycle within the provided INetworkDefinition. /// </summary> public static bool IsNetworkCyclic(INetworkDefinition networkDef) { return new CyclicNetworkTest().IsNetworkCyclicInternal(networkDef); }
private CyclicNetwork CreateSubstrateNetwork_CyclicNetwork(INetworkDefinition networkDef) { return(CyclicNetworkFactory.CreateCyclicNetwork(networkDef, _activationSchemeCppn)); }
/// <summary> /// Create an array of FastConnection(s) representing the connectivity of the provided INetworkDefinition. /// </summary> private static FastConnection[] CreateFastConnectionArray(INetworkDefinition networkDef) { // We vary the decode logic depending on the size of the genome. The most CPU intensive aspect of // decoding is the conversion of the neuron IDs at connection endpoints into neuron indexes. For small // genomes we simply use the BinarySearch() method on NeuronGeneList for each lookup; Each lookup is // an operation with O(log n) time complexity. Thus for C connections and N neurons the number of operations // to perform all lookups is approximately = 2*C*Log(N) // // For larger genomes we invest time in building a Dictionary that maps neuron IDs to their indexes, this on the // basis that the time invested will be more than recovered in time saved performing lookups; The time complexity // of a dictionary lookup is near constant O(1). Thus number of operations is approximately = O(2*C*1) + the time // required to build the dictionary which is approximately O(N). // // Therefore the choice of lookup type is based on which of these two expressions gives the lowest value. // // Binary search. LookupOps = 2 * C * Log2(N) * x // Dictionary Search. LookupOps = (N * y) + (2 * C * z) // // Where x, y and z are constants that adjust for the relative speeds of the lookup and dictionary building operations. // Note that the actual time required to perform these separate algorithms is actually a far more complex problem, and // for modern CPUs exact times cannot be calculated because of large memory caches and superscalar architecture that // makes execution times in a real environment effectively non-deterministic. Thus these calculations are a rough // guide/heuristic that estimate which algorithm will perform best. The constants can be found experimentally but will // tend to vary depending on factors such as CPU and memory architecture, .Net framework version and what other tasks the // CPU is currently doing which may affect our utilisation of memory caches. // TODO: Experimentally determine reasonably good values for constants x,y and z in some common real world runtime platform. IConnectionList connectionList = networkDef.ConnectionList; INodeList nodeList = networkDef.NodeList; int connectionCount = connectionList.Count; int nodeCount = nodeList.Count; FastConnection[] fastConnectionArray = new FastConnection[connectionCount]; if ((2.0 * connectionCount * Math.Log(nodeCount, 2.0)) < ((2.0 * connectionCount) + nodeCount)) { // Binary search requires items to be sorted. Debug.Assert(nodeList.IsSorted()); // Loop the connections and lookup the neuron IDs for each connection's end points using a binary search // on nGeneList. This is probably the quickest approach for small numbers of lookups. for (int i = 0; i < connectionCount; i++) { INetworkConnection conn = connectionList[i]; fastConnectionArray[i]._srcNeuronIdx = nodeList.BinarySearch(conn.SourceNodeId); fastConnectionArray[i]._tgtNeuronIdx = nodeList.BinarySearch(conn.TargetNodeId); fastConnectionArray[i]._weight = conn.Weight; // Check that the correct neuron indexes were found. Debug.Assert( nodeList[fastConnectionArray[i]._srcNeuronIdx].Id == conn.SourceNodeId && nodeList[fastConnectionArray[i]._tgtNeuronIdx].Id == conn.TargetNodeId); } } else { // Build dictionary of neuron indexes keyed on neuron innovation ID. Dictionary <uint, int> neuronIndexDictionary = new Dictionary <uint, int>(nodeCount); for (int i = 0; i < nodeCount; i++) { // ENHANCEMENT: Check if neuron innovation ID requires further manipulation to make a good hash code. neuronIndexDictionary.Add(nodeList[i].Id, i); } // Loop the connections and lookup the neuron IDs for each connection's end points using neuronIndexDictionary. // This is probably the quickest approach for large numbers of lookups. for (int i = 0; i < connectionCount; i++) { INetworkConnection conn = connectionList[i]; fastConnectionArray[i]._srcNeuronIdx = neuronIndexDictionary[conn.SourceNodeId]; fastConnectionArray[i]._tgtNeuronIdx = neuronIndexDictionary[conn.TargetNodeId]; fastConnectionArray[i]._weight = conn.Weight; // Check that the correct neuron indexes were found. Debug.Assert( nodeList[fastConnectionArray[i]._srcNeuronIdx].Id == conn.SourceNodeId && nodeList[fastConnectionArray[i]._tgtNeuronIdx].Id == conn.TargetNodeId); } } return(fastConnectionArray); }