/// <summary> /// Create a directed graph based on the provided connections (between node IDs) and a predefined set of node IDs. /// Clearly the set of nodeIDs could be discovered by iterating over the connections. This overload exists to allow /// for additional fixed node IDs to be allocated regardless of whether they are connected to or not, this is primarily /// to allow for the allocation of NeatGenome input and output nodes, which are defined with fixed IDs but aren't /// necessarily connected to. /// </summary> public static WeightedDirectedGraph <T> Create( IList <WeightedDirectedConnection <T> > connectionList, int inputCount, int outputCount) { // Debug assert that the connections are sorted. Debug.Assert(SortUtils.IsSortedAscending(connectionList, WeightedDirectedConnectionComparer <T> .Default)); // Determine the full set of hidden node IDs. int inputOutputCount = inputCount + outputCount; var hiddenNodeIdArr = GetHiddenNodeIdArray(connectionList, inputOutputCount); // Compile a mapping from current nodeIDs to new IDs (i.e. removing gaps in the ID space). INodeIdMap nodeIdMap = DirectedGraphUtils.CompileNodeIdMap_InputOutputCount_HiddenNodeIdArr( inputOutputCount, hiddenNodeIdArr); // 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(connectionList, nodeIdMap, out ConnectionIdArrays connIdArrays, out T[] weightArr); // Construct and return a new WeightedDirectedGraph. int totalNodeCount = inputOutputCount + hiddenNodeIdArr.Length; return(new WeightedDirectedGraph <T>(connIdArrays, inputCount, outputCount, totalNodeCount, weightArr)); }
private static DirectedGraphViewModel CreateGraphViewModel() { // Simple acyclic graph. var connList = new LightweightList <WeightedDirectedConnection <float> > { new WeightedDirectedConnection <float>(0, 4, 1f), new WeightedDirectedConnection <float>(4, 5, 2f), new WeightedDirectedConnection <float>(5, 2, 3f), new WeightedDirectedConnection <float>(1, 2, 4f), new WeightedDirectedConnection <float>(2, 2, 5f), new WeightedDirectedConnection <float>(2, 3, 5f), new WeightedDirectedConnection <float>(2, 4, 5f), new WeightedDirectedConnection <float>(2, 5, 5f) }; var connSpan = connList.AsSpan(); connSpan.Sort(WeightedDirectedConnectionComparer <float> .Default); // Create graph. var digraph = WeightedDirectedGraphBuilder <float> .Create(connSpan, 2, 2); // Create graph view model, and return. INodeIdMap nodeIdByIdx = CreateNodeIdByIdx(digraph.TotalNodeCount); DirectedGraphViewModel graphViewModel = new(digraph, digraph.WeightArray, nodeIdByIdx); return(graphViewModel); }
public void TestIsConnectionCyclic3() { var cyclicTest = new CyclicConnectionTest(); var connArr = new DirectedConnection[8]; connArr[0] = new DirectedConnection(0, 10); connArr[1] = new DirectedConnection(0, 20); connArr[2] = new DirectedConnection(0, 30); connArr[3] = new DirectedConnection(10, 40); connArr[4] = new DirectedConnection(40, 20); connArr[5] = new DirectedConnection(20, 50); connArr[6] = new DirectedConnection(30, 60); connArr[7] = new DirectedConnection(30, 20); Array.Sort(connArr); INodeIdMap nodeIdxByIdMap = DirectedGraphUtils.CompileNodeIdMap_InputOutputCount_HiddenNodeIdArr( 0, new int[] { 0, 10, 20, 30, 40, 50, 60 }); // True tests (cycle). Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(20, 10))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(20, 40))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(50, 20))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(50, 0))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(50, 40))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(60, 0))); // False tests (no cycle). Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(30, 50))); Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(10, 30))); Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(60, 10))); Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(60, 20))); Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(60, 40))); Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(30, 40))); }
/// <summary> /// Tests if the proposed new connection newConn would form a cycle if added to the existing directed /// acyclic graph described by connArr. /// </summary> /// <param name="connArr">A set of connections that describe a directed acyclic graph.</param> /// <param name="newConn">A proposed new connection to add to the graph.</param> public bool IsConnectionCyclic( DirectedConnection[] connArr, INodeIdMap nodeIdxByIdMap, int totalNodeCount, DirectedConnection newConn) { #if DEBUG // Check for attempts to re-enter this method. if (1 == Interlocked.CompareExchange(ref _reentranceFlag, 1, 0)) { throw new InvalidOperationException("Attempt to re-enter non reentrant method."); } #endif EnsureNodeCapacity(totalNodeCount); _nodeIdxByIdMap = nodeIdxByIdMap; try { return(IsConnectionCyclicInner(connArr, newConn)); } finally { // Ensure cleanup occurs before we return so that we can guarantee the class instance is ready for // re-use on the next call. Cleanup(); } }
/// <summary> /// Create a directed graph based on the provided connections (between node IDs) and a predefined set of input/output /// node IDs defined as being in a contiguous sequence starting at ID zero. /// </summary> /// <param name="connections">The connections that define the structure and weights of the weighted directed graph.</param> /// <param name="inputCount">Input node count.</param> /// <param name="outputCount">Output node count.</param> /// <returns>A new instance of <see cref="DirectedGraph"/>.</returns> /// <remarks> /// <paramref name="connections"/> is required to be sorted by sourceId, TargetId. /// </remarks> public static DirectedGraph Create( Span <DirectedConnection> connections, int inputCount, int outputCount) { // Debug assert that the connections are sorted. Debug.Assert(SortUtils.IsSortedAscending <DirectedConnection>(connections)); // Determine the full set of hidden node IDs. int inputOutputCount = inputCount + outputCount; var hiddenNodeIdArr = GetHiddenNodeIdArray(connections, inputOutputCount); // Compile a mapping from current nodeIDs to new IDs (i.e. removing gaps in the ID space). INodeIdMap nodeIdMap = DirectedGraphBuilderUtils.CompileNodeIdMap( inputOutputCount, hiddenNodeIdArr); // 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. ConnectionIds connIds = CopyAndMapIds(connections, nodeIdMap); // Construct and return a new DirectedGraph. int totalNodeCount = inputOutputCount + hiddenNodeIdArr.Length; return(new DirectedGraph(inputCount, outputCount, totalNodeCount, connIds)); }
public void TestIsConnectionCyclic1() { var cyclicTest = new CyclicConnectionTest(); var connArr = new DirectedConnection[3]; connArr[0] = new DirectedConnection(0, 1); connArr[1] = new DirectedConnection(1, 2); connArr[2] = new DirectedConnection(2, 3); INodeIdMap nodeIdxByIdMap = DirectedGraphUtils.CompileNodeIdMap_InputOutputCount_HiddenNodeIdArr( 0, new int[] { 0, 1, 2, 3 }); // True tests (cycle). Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(0, 0))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(1, 1))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(2, 2))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(3, 3))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(1, 0))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(2, 0))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(3, 0))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(2, 1))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(3, 1))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(3, 2))); // False tests (no cycle). Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(0, 2))); Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(0, 3))); Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(1, 3))); Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 4, new DirectedConnection(2, 3))); }
public void TestIsConnectionCyclic2() { var cyclicTest = new CyclicConnectionTest(); var connArr = new DirectedConnection[8]; connArr[0] = new DirectedConnection(0, 1); connArr[1] = new DirectedConnection(0, 2); connArr[2] = new DirectedConnection(0, 3); connArr[3] = new DirectedConnection(1, 4); connArr[4] = new DirectedConnection(4, 2); connArr[5] = new DirectedConnection(2, 5); connArr[6] = new DirectedConnection(3, 6); connArr[7] = new DirectedConnection(3, 2); Array.Sort(connArr); INodeIdMap nodeIdxByIdMap = DirectedGraphUtils.CompileNodeIdMap_InputOutputCount_HiddenNodeIdArr( 0, new int[] { 0, 1, 2, 3, 4, 5, 6 }); // True tests (cycle). Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(2, 1))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(2, 4))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(5, 2))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(5, 0))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(5, 4))); Assert.IsTrue(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(6, 0))); // False tests (no cycle). Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(3, 5))); Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(1, 3))); Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(6, 1))); Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(6, 2))); Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(6, 4))); Assert.IsFalse(cyclicTest.IsConnectionCyclic(connArr, nodeIdxByIdMap, 7, new DirectedConnection(3, 4))); }
public void CreateInverse(int fixedNodeCount) { var nodeIdxById = new Dictionary <int, int> { { 100, fixedNodeCount }, { 50, fixedNodeCount + 1 }, { 200, fixedNodeCount + 2 }, { 70, fixedNodeCount + 3 }, { 300, fixedNodeCount + 4 }, { 30, fixedNodeCount + 5 } }; var nodeIdMap = new DictionaryNodeIdMap(fixedNodeCount, nodeIdxById); INodeIdMap inverseMap = nodeIdMap.CreateInverseMap(); Assert.Equal(nodeIdMap.Count, inverseMap.Count); Assert.Equal(0, inverseMap.Map(0)); Assert.Equal(fixedNodeCount - 1, inverseMap.Map(fixedNodeCount - 1)); Assert.Equal(100, inverseMap.Map(fixedNodeCount)); Assert.Equal(50, inverseMap.Map(fixedNodeCount + 1)); Assert.Equal(200, inverseMap.Map(fixedNodeCount + 2)); Assert.Equal(70, inverseMap.Map(fixedNodeCount + 3)); Assert.Equal(300, inverseMap.Map(fixedNodeCount + 4)); Assert.Equal(30, inverseMap.Map(fixedNodeCount + 5)); }
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, 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)); }
private void Cleanup() { _traversalStack.Clear(); _visitedNodes.Reset(false); _nodeIdxByIdMap = null; #if DEBUG // Reset reentrancy test flag. Interlocked.Exchange(ref _reentranceFlag, 0); #endif }
/// <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 void AssertNodeCounts( MetaNeatGenome <T> metaNeatGenome, int[] hiddenNodeIdArr, INodeIdMap nodeIndexByIdMap, DirectedGraph digraph) { int totalNodeCount = metaNeatGenome.InputNodeCount + metaNeatGenome.OutputNodeCount + hiddenNodeIdArr.Length; Debug.Assert(digraph.InputCount == metaNeatGenome.InputNodeCount); Debug.Assert(digraph.OutputCount == metaNeatGenome.OutputNodeCount); Debug.Assert(digraph.TotalNodeCount == totalNodeCount); Debug.Assert(nodeIndexByIdMap.Count == totalNodeCount); }
private static bool ValidateNodeCounts( MetaNeatGenome <T> metaNeatGenome, int[] hiddenNodeIdArr, INodeIdMap nodeIndexByIdMap, DirectedGraph digraph) { int totalNodeCount = metaNeatGenome.InputNodeCount + metaNeatGenome.OutputNodeCount + hiddenNodeIdArr.Length; return(digraph.InputCount == metaNeatGenome.InputNodeCount && digraph.OutputCount == metaNeatGenome.OutputNodeCount && digraph.TotalNodeCount == totalNodeCount && nodeIndexByIdMap.Count == totalNodeCount); }
private static ConnectionIds CopyAndMapIds( Span <DirectedConnection> connSpan, INodeIdMap nodeIdMap) { int count = connSpan.Length; var connIds = new ConnectionIds(count); var srcIds = connIds.GetSourceIdSpan(); var tgtIds = connIds.GetTargetIdSpan(); for (int i = 0; i < count; i++) { srcIds[i] = nodeIdMap.Map(connSpan[i].SourceId); tgtIds[i] = nodeIdMap.Map(connSpan[i].TargetId); } return(connIds); }
private static ConnectionIdArrays CopyAndMapIds( IList <DirectedConnection> connectionList, INodeIdMap nodeIdMap) { int count = connectionList.Count; int [] srcIdArr = new int[count]; int [] tgtIdArr = new int[count]; for (int i = 0; i < connectionList.Count; i++) { srcIdArr[i] = nodeIdMap.Map(connectionList[i].SourceId); tgtIdArr[i] = nodeIdMap.Map(connectionList[i].TargetId); } return(new ConnectionIdArrays(srcIdArr, tgtIdArr)); }
private static void CopyAndMapIds( DirectedConnection[] connArr, INodeIdMap nodeIdMap, out ConnectionIds connIds) { int count = connArr.Length; connIds = new ConnectionIds(count); var srcIds = connIds.GetSourceIdSpan(); var tgtIds = connIds.GetTargetIdSpan(); for (int i = 0; i < count; i++) { srcIds[i] = nodeIdMap.Map(connArr[i].SourceId); tgtIds[i] = nodeIdMap.Map(connArr[i].TargetId); } }
private static void CopyAndMapIds( DirectedConnection[] connArr, INodeIdMap nodeIdMap, out ConnectionIdArrays connIdArrays) { int count = connArr.Length; int[] srcIdArr = new int[count]; int[] tgtIdArr = new int[count]; for (int i = 0; i < count; i++) { srcIdArr[i] = nodeIdMap.Map(connArr[i].SourceId); tgtIdArr[i] = nodeIdMap.Map(connArr[i].TargetId); } connIdArrays = new ConnectionIdArrays(srcIdArr, tgtIdArr); }
/// <summary> /// Construct with the provided digraph, weights, and node IDs. /// The node positions array is allocated, but must be updated with actual positions outside of this constructor. /// </summary> /// <param name="digraph">Directed graph.</param> /// <param name="weightArr">Graph connection/vertex weights.</param> /// <param name="nodeIdByIdx">Provides a ID/label for each node.</param> public DirectedGraphViewModel( DirectedGraph digraph, float[] weightArr, INodeIdMap nodeIdByIdx) { if (weightArr.Length != digraph.ConnectionIds.Length) { throw new ArgumentException("Weight and connection ID arrays must have same length.", nameof(weightArr)); } if (nodeIdByIdx.Count != digraph.TotalNodeCount) { throw new ArgumentException("Node counts must match.", nameof(nodeIdByIdx)); } this.DirectedGraph = digraph; this.WeightArr = weightArr; this.NodeIdByIdx = nodeIdByIdx; this.NodePosByIdx = new Point[digraph.TotalNodeCount]; }
/// <summary> /// Construct with the provided digraph, weights, and node IDs. /// The node positions array is allocated, but must be updated with actual positions outside of this constructor. /// </summary> /// <param name="digraph">Directed graph.</param> /// <param name="weightArr">Graph connection/vertex weights.</param> /// <param name="nodeIdByIdx">Provides a ID/label for each node.</param> public DirectedGraphViewModel( DirectedGraph digraph, float[] weightArr, INodeIdMap nodeIdByIdx) { if (weightArr.Length != digraph.ConnectionIdArrays.Length) { throw new ArgumentException(nameof(weightArr)); } if (nodeIdByIdx.Count != digraph.TotalNodeCount) { throw new ArgumentException(nameof(nodeIdByIdx)); } this.DirectedGraph = digraph; this.WeightArr = weightArr; this.NodeIdByIdx = nodeIdByIdx; this.NodePosByIdx = new Point[digraph.TotalNodeCount]; }
/// <summary> /// Split each IWeightedDirectedConnection in a list into an array of DirectedConnections(s), and an array of weights. /// Map the node IDs to indexes as we go. /// </summary> private static void CopyAndMapIds( IList <WeightedDirectedConnection <T> > connectionList, INodeIdMap nodeIdMap, out ConnectionIdArrays connIdArrays, out T[] weightArr) { int count = connectionList.Count; int[] srcIdArr = new int[count]; int[] tgtIdArr = new int[count]; weightArr = new T[count]; for (int i = 0; i < count; i++) { srcIdArr[i] = nodeIdMap.Map(connectionList[i].SourceId); tgtIdArr[i] = nodeIdMap.Map(connectionList[i].TargetId); weightArr[i] = connectionList[i].Weight; } connIdArrays = new ConnectionIdArrays(srcIdArr, tgtIdArr); }
/// <summary> /// Split each IWeightedDirectedConnection in a list into an array of DirectedConnections(s), and an array of weights. /// Map the node IDs to indexes as we go. /// </summary> private static void CopyAndMapIds( Span <WeightedDirectedConnection <T> > connSpan, INodeIdMap nodeIdMap, out ConnectionIds connIds, out T[] weightArr) { int count = connSpan.Length; connIds = new ConnectionIds(count); var srcIds = connIds.GetSourceIdSpan(); var tgtIds = connIds.GetTargetIdSpan(); weightArr = new T[count]; for (int i = 0; i < count; i++) { srcIds[i] = nodeIdMap.Map(connSpan[i].SourceId); tgtIds[i] = nodeIdMap.Map(connSpan[i].TargetId); weightArr[i] = connSpan[i].Weight; } }
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); }