private static void AssertConnections( ConnectionGenes <T> connGenes, DirectedGraph digraph, INodeIdMap nodeIndexByIdMap, int[]?connectionIndexMap) { // Connection counts. Debug.Assert(connGenes._connArr.Length == digraph.ConnectionIdArrays.Length); // Connection order. Debug.Assert(SortUtils.IsSortedAscending(connGenes._connArr)); Debug.Assert(IsSortedAscending(digraph.ConnectionIdArrays)); // Connection node ID mappings. DirectedConnection[] connArr = connGenes._connArr; int[] srcIdArr = digraph.ConnectionIdArrays._sourceIdArr; int[] tgtIdArr = digraph.ConnectionIdArrays._targetIdArr; for (int i = 0; i < connGenes._connArr.Length; i++) { // Determine the index of the equivalent connection in the digraph. int genomeConnIdx = (connectionIndexMap is null) ? i : connectionIndexMap[i]; Debug.Assert(nodeIndexByIdMap.Map(connArr[genomeConnIdx].SourceId) == srcIdArr[i]); Debug.Assert(nodeIndexByIdMap.Map(connArr[genomeConnIdx].TargetId) == tgtIdArr[i]); } }
public static DirectedGraph CreateDirectedGraph <T>( MetaNeatGenome <T> metaNeatGenome, ConnectionGenes <T> connGenes, INodeIdMap nodeIndexByIdMap) where T : struct { // Extract/copy the neat genome connectivity graph into an array of DirectedConnection. // Notes. // The array contents will be manipulated, so copying this avoids modification of the genome's // connection gene list. // The IDs are substituted for node indexes here. CopyAndMapIds( connGenes._connArr, nodeIndexByIdMap, out ConnectionIdArrays connIdArrays); // Construct a new DirectedGraph. var digraph = new DirectedGraph( connIdArrays, metaNeatGenome.InputNodeCount, metaNeatGenome.OutputNodeCount, nodeIndexByIdMap.Count); return(digraph); }
public static void AssertIsValid( MetaNeatGenome <T> metaNeatGenome, int id, int birthGeneration, ConnectionGenes <T> connGenes, int[] hiddenNodeIdArr, INodeIdMap nodeIndexByIdMap, DirectedGraph digraph, int[] connectionIndexMap) { // Mandatory ref tests. Debug.Assert(null != metaNeatGenome); Debug.Assert(null != connGenes); Debug.Assert(null != hiddenNodeIdArr); Debug.Assert(null != nodeIndexByIdMap); Debug.Assert(null != digraph); // Acyclic graph checks. if (metaNeatGenome.IsAcyclic) { AssertAcyclicGraph(metaNeatGenome, digraph, connectionIndexMap); } // Node counts. AssertNodeCounts(metaNeatGenome, hiddenNodeIdArr, nodeIndexByIdMap, digraph); // Hidden node IDs. Debug.Assert(ConnectionGenesUtils.ValidateHiddenNodeIds(hiddenNodeIdArr, connGenes._connArr, metaNeatGenome.InputOutputNodeCount)); // Connections. AssertConnections(connGenes, digraph, nodeIndexByIdMap, connectionIndexMap); }
/// <summary> /// Constructs with the provided ID, birth generation and gene arrays. /// </summary> internal NeatGenome( MetaNeatGenome <T> metaNeatGenome, int id, int birthGeneration, ConnectionGenes <T> connGenes, int[] hiddenNodeIdArr, INodeIdMap nodeIndexByIdMap, DirectedGraph digraph, int[] connectionIndexMap) { #if DEBUG NeatGenomeAssertions <T> .AssertIsValid( metaNeatGenome, id, birthGeneration, connGenes, hiddenNodeIdArr, nodeIndexByIdMap, digraph, connectionIndexMap); #endif this.MetaNeatGenome = metaNeatGenome; this.Id = id; this.BirthGeneration = birthGeneration; this.ConnectionGenes = connGenes; this.HiddenNodeIdArray = hiddenNodeIdArr; this.NodeIndexByIdMap = nodeIndexByIdMap; this.DirectedGraph = digraph; this.ConnectionIndexMap = connectionIndexMap; }
/// <summary> /// Create a NeatGenome with the given meta data and connection genes. /// </summary> /// <param name="id">Genome ID.</param> /// <param name="birthGeneration">Birth generation.</param> /// <param name="connGenes">Connection genes.</param> /// <returns>A new NeatGenome instance.</returns> public NeatGenome <T> Create( int id, int birthGeneration, ConnectionGenes <T> connGenes) { // Determine the set of node IDs, and create a mapping from node IDs to node indexes. int[] hiddenNodeIdArr = ConnectionGenesUtils.CreateHiddenNodeIdArray(connGenes._connArr, _metaNeatGenome.InputOutputNodeCount, _workingIdSet); return(Create(id, birthGeneration, connGenes, hiddenNodeIdArr)); }
/// <summary> /// Create a NeatGenome with the given meta data, connection genes and supplementary data. /// </summary> /// <param name="id">Genome ID.</param> /// <param name="birthGeneration">Birth generation.</param> /// <param name="connGenes">Connection genes.</param> /// <param name="hiddenNodeIdArr">An array of the hidden node IDs in the genome, in ascending order.</param> /// <param name="digraph">A DirectedGraph that mirrors the structure described by the connection genes.</param> /// <param name="acyclicInfoCache">Cached info related to acyclic digraphs only.</param> /// <returns>A new NeatGenome instance.</returns> public NeatGenome <T> Create( int id, int birthGeneration, ConnectionGenes <T> connGenes, int[] hiddenNodeIdArr, INodeIdMap nodeIndexByIdMap, DirectedGraph digraph, int[] connectionIndexMap) { return(new NeatGenome <T>(_metaNeatGenome, id, birthGeneration, connGenes, hiddenNodeIdArr, nodeIndexByIdMap, digraph, connectionIndexMap)); }
/// <summary> /// Create a NeatGenome with the given meta data, connection genes and supplementary data. /// </summary> /// <param name="id">Genome ID.</param> /// <param name="birthGeneration">Birth generation.</param> /// <param name="connGenes">Connection genes.</param> /// <param name="hiddenNodeIdArr">An array of the hidden node IDs in the genome, in ascending order.</param> /// <returns>A new NeatGenome instance.</returns> public NeatGenome <T> Create( int id, int birthGeneration, ConnectionGenes <T> connGenes, int[] hiddenNodeIdArr) { int inputCount = _metaNeatGenome.InputNodeCount; int outputCount = _metaNeatGenome.OutputNodeCount; int inputOutputCount = _metaNeatGenome.InputOutputNodeCount; // Create a mapping from node IDs to node indexes. Dictionary <int, int> nodeIdxById = BuildNodeIndexById(hiddenNodeIdArr); // Create a DictionaryNodeIdMap. DictionaryNodeIdMap nodeIndexByIdMap = new DictionaryNodeIdMap(inputCount, nodeIdxById); // Create a digraph from the genome. DirectedGraph digraph = NeatGenomeBuilderUtils.CreateDirectedGraph( _metaNeatGenome, connGenes, nodeIndexByIdMap); // Calc the depth of each node in the digraph. GraphDepthInfo depthInfo = _graphDepthAnalysis.CalculateNodeDepths(digraph); // Create a weighted acyclic digraph. // Note. This also outputs connectionIndexMap. For each connection in the acyclic graph this gives // the index of the same connection in the genome; this is because connections are re-ordered based // on node depth in the acyclic graph. AcyclicDirectedGraph acyclicDigraph = AcyclicDirectedGraphBuilderUtils.CreateAcyclicDirectedGraph( digraph, depthInfo, out int[] newIdByOldId, out int[] connectionIndexMap, ref _timesortWorkArr, ref _timesortWorkVArr); // TODO: Write unit tests to cover this! // Update nodeIdxById with the new depth based node index allocations. // Notes. // The current nodeIndexByIdMap maps node IDs (also know as innovation IDs in NEAT) to a compact // ID space in which any gaps have been removed, i.e. a compacted set of IDs that can be used as indexes, // i.e. if there are N nodes in total then the highest node ID will be N-1. // // Here we map the new compact IDs to an alternative ID space that is also compact, but ensures that nodeIDs // reflect the depth of a node in the acyclic graph. UpdateNodeIndexById(nodeIdxById, hiddenNodeIdArr, newIdByOldId); // Create the neat genome. return(new NeatGenome <T>( _metaNeatGenome, id, birthGeneration, connGenes, hiddenNodeIdArr, nodeIndexByIdMap, acyclicDigraph, connectionIndexMap)); }
/// <summary> /// Create a NeatGenome with the given meta data, connection genes and supplementary data. /// </summary> /// <param name="id">Genome ID.</param> /// <param name="birthGeneration">Birth generation.</param> /// <param name="connGenes">Connection genes.</param> /// <param name="hiddenNodeIdArr">An array of the hidden node IDs in the genome, in ascending order.</param> /// <returns>A new NeatGenome instance.</returns> public NeatGenome <T> Create( int id, int birthGeneration, ConnectionGenes <T> connGenes, int[] hiddenNodeIdArr, INodeIdMap nodeIndexByIdMap) { // Note. Not required for acyclic graphs. // In acyclic graphs nodeIndexByIdMap is so closely related/tied to digraph and connectionIndexMap that // these three objects exist as a logical unit, i.e. we get all three or none at all. throw new NotImplementedException(); }
/// <summary> /// Create a NeatGenome with the given meta data, connection genes and supplementary data. /// </summary> /// <param name="id">Genome ID.</param> /// <param name="birthGeneration">Birth generation.</param> /// <param name="connGenes">Connection genes.</param> /// <param name="hiddenNodeIdArr">An array of the hidden node IDs in the genome, in ascending order.</param> /// <returns>A new NeatGenome instance.</returns> public NeatGenome <T> Create( int id, int birthGeneration, ConnectionGenes <T> connGenes, int[] hiddenNodeIdArr) { // Create a mapping from node IDs to node indexes. INodeIdMap nodeIndexByIdMap = DirectedGraphUtils.CompileNodeIdMap_InputOutputCount_HiddenNodeIdArr( _metaNeatGenome.InputOutputNodeCount, hiddenNodeIdArr); return(Create(id, birthGeneration, connGenes, hiddenNodeIdArr, nodeIndexByIdMap)); }
/// <summary> /// Create a NeatGenome with the given meta data, connection genes and supplementary data. /// </summary> /// <param name="id">Genome ID.</param> /// <param name="birthGeneration">Birth generation.</param> /// <param name="connGenes">Connection genes.</param> /// <param name="hiddenNodeIdArr">An array of the hidden node IDs in the genome, in ascending order.</param> /// <returns>A new NeatGenome instance.</returns> public NeatGenome <T> Create( int id, int birthGeneration, ConnectionGenes <T> connGenes, int[] hiddenNodeIdArr, INodeIdMap nodeIndexByIdMap) { // Create a digraph from the genome. DirectedGraph digraph = NeatGenomeBuilderUtils.CreateDirectedGraph( _metaNeatGenome, connGenes, nodeIndexByIdMap); return(new NeatGenome <T>(_metaNeatGenome, id, birthGeneration, connGenes, hiddenNodeIdArr, nodeIndexByIdMap, digraph, null)); }
/// <summary> /// Create a NeatGenome with the given meta data, connection genes and supplementary data. /// </summary> /// <param name="id">Genome ID.</param> /// <param name="birthGeneration">Birth generation.</param> /// <param name="connGenes">Connection genes.</param> /// <param name="hiddenNodeIdArr">An array of the hidden node IDs in the genome, in ascending order.</param> /// <param name="digraph">A DirectedGraph that mirrors the structure described by the connection genes.</param> /// <param name="connectionIndexMap">Mapping from genome connection indexes (in NeatGenome.ConnectionGenes) to reordered connections, based on depth based /// node index allocations.</param> /// <returns>A new NeatGenome instance.</returns> public NeatGenome <T> Create( int id, int birthGeneration, ConnectionGenes <T> connGenes, int[] hiddenNodeIdArr, INodeIdMap nodeIndexByIdMap, DirectedGraph digraph, int[] connectionIndexMap) { // This should always be null when evolving cyclic genomes/graphs. Debug.Assert(null == connectionIndexMap); return(new NeatGenome <T>(_metaNeatGenome, id, birthGeneration, connGenes, hiddenNodeIdArr, nodeIndexByIdMap, digraph, null)); }
private static bool ValidateConnections( ConnectionGenes <T> connGenes, DirectedGraph digraph, INodeIdMap nodeIndexByIdMap, int[] connectionIndexMap) { // Connection counts. if (connGenes._connArr.Length != digraph.ConnectionIdArrays.Length) { return(false); } // Connection order. if (!SortUtils.IsSortedAscending(connGenes._connArr) || !IsSortedAscending(digraph.ConnectionIdArrays)) { return(false); } // Connection node ID mappings. DirectedConnection[] connArr = connGenes._connArr; int[] srcIdArr = digraph.ConnectionIdArrays._sourceIdArr; int[] tgtIdArr = digraph.ConnectionIdArrays._targetIdArr; for (int i = 0; i < connGenes._connArr.Length; i++) { DirectedConnection connGene = connArr[i]; // Determine the index of he equivalent connection in the digraph. int genomeConnIdx = (null == connectionIndexMap) ? i : connectionIndexMap[i]; if (nodeIndexByIdMap.Map(connArr[genomeConnIdx].SourceId) != srcIdArr[i] || nodeIndexByIdMap.Map(connArr[genomeConnIdx].TargetId) != tgtIdArr[i]) { return(false); } } return(true); }
public static void AssertIsValid( MetaNeatGenome <T> metaNeatGenome, int id, int birthGeneration, ConnectionGenes <T> connGenes, int[] hiddenNodeIdArr, INodeIdMap nodeIndexByIdMap, DirectedGraph digraph, int[]?connectionIndexMap) { // Check for mandatory object references. Debug.Assert(metaNeatGenome is object); Debug.Assert(connGenes is object); Debug.Assert(hiddenNodeIdArr is object); Debug.Assert(nodeIndexByIdMap is object); Debug.Assert(digraph is object); // Basic check on ID and birth generation. Debug.Assert(id >= 0); Debug.Assert(birthGeneration >= 0); // Acyclic graph checks. if (metaNeatGenome.IsAcyclic) { AssertAcyclicGraph(metaNeatGenome, digraph, connectionIndexMap); } // Node counts. AssertNodeCounts(metaNeatGenome, hiddenNodeIdArr, nodeIndexByIdMap, digraph); // Hidden node IDs. Debug.Assert(ConnectionGenesUtils.ValidateHiddenNodeIds(hiddenNodeIdArr, connGenes._connArr, metaNeatGenome.InputOutputNodeCount)); // Connections. AssertConnections(connGenes, digraph, nodeIndexByIdMap, connectionIndexMap); }
public static bool IsValid( MetaNeatGenome <T> metaNeatGenome, int id, int birthGeneration, ConnectionGenes <T> connGenes, int[] hiddenNodeIdArr, INodeIdMap nodeIndexByIdMap, DirectedGraph digraph, int[] connectionIndexMap) { // Mandatory ref tests. if (null == metaNeatGenome || null == connGenes || null == hiddenNodeIdArr || null == nodeIndexByIdMap || null == digraph) { return(false); } // Acyclic/cyclic specific checks. if (metaNeatGenome.IsAcyclic) { if (digraph.GetType() != typeof(AcyclicDirectedGraph) || null == connectionIndexMap) { return(false); } } else { if (digraph.GetType() != typeof(DirectedGraph)) { return(false); } } // DepthInfo relates to acyclic graphs only, and is mandatory for acyclic graphs. // TODO: Enable once NeatGenomeAcyclicBuilder is finished. //if(metaNeatGenome.IsAcyclic) //{ // if(!IsValid_Acyclic(metaNeatGenome, depthInfo)) { // return false; // } //} // Node counts. if (!ValidateNodeCounts(metaNeatGenome, hiddenNodeIdArr, nodeIndexByIdMap, digraph)) { return(false); } // Hidden node IDs. if (!ConnectionGenesUtils.ValidateHiddenNodeIds(hiddenNodeIdArr, connGenes._connArr, metaNeatGenome.InputOutputNodeCount)) { return(false); } // Connections. if (!ValidateConnections(connGenes, digraph, nodeIndexByIdMap, connectionIndexMap)) { return(false); } // All tests passed. return(true); }