/// <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> /// <remarks> /// connectionList is assumed to be sorted by sourceID, TargetID. /// </remarks> public static DirectedGraph Create( IList <DirectedConnection> connectionList, int inputCount, int outputCount) { // Debug assert that the connections are sorted. Debug.Assert(SortUtils.IsSortedAscending(connectionList)); // 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. ConnectionIdArrays connIdArrays = CopyAndMapIds(connectionList, nodeIdMap); // Construct and return a new DirectedGraph. int totalNodeCount = inputOutputCount + hiddenNodeIdArr.Length; return(new DirectedGraph(connIdArrays, inputCount, outputCount, totalNodeCount)); }
// Notes. // Array.Sort() can sort a secondary array, but here we need to sort a third array; the below code // does this but performs a lot of unnecessary memory allocation and copying. As such this logic was // replaced (see current implementation of SharpNeat.Network.ConnectionSorter) with a customised sort // routine that is faster and more efficient w.r.t memory allocations and copying. public static void Sort <S>(ConnectionIdArrays connIdArrays, S[] weightArr) where S : struct { // Init array of indexes. int[] srcIdArr = connIdArrays._sourceIdArr; int[] tgtIdArr = connIdArrays._targetIdArr; int[] idxArr = new int[srcIdArr.Length]; for (int i = 0; i < idxArr.Length; i++) { idxArr[i] = i; } // Sort the array of indexes based on the connections that each index points to. var comparer = new ConnectionComparer(connIdArrays); Array.Sort(idxArr, comparer); int len = srcIdArr.Length; int[] srcIdArr2 = new int[len]; int[] tgtIdArr2 = new int[len]; S[] weightArr2 = new S[len]; for (int i = 0; i < len; i++) { int j = idxArr[i]; srcIdArr2[i] = srcIdArr[j]; tgtIdArr2[i] = tgtIdArr[j]; weightArr2[i] = weightArr[j]; } Array.Copy(srcIdArr2, srcIdArr, len); Array.Copy(tgtIdArr2, tgtIdArr, len); Array.Copy(weightArr2, weightArr, len); }
public static void Sort(ConnectionIdArrays connIdArrays, T[] secondaryArr) { Debug.Assert(connIdArrays._sourceIdArr != null); Debug.Assert(connIdArrays._targetIdArr != null); Debug.Assert(secondaryArr != null); Debug.Assert(connIdArrays._sourceIdArr.Length == connIdArrays._targetIdArr.Length); Debug.Assert(connIdArrays._sourceIdArr.Length == secondaryArr.Length); IntrospectiveSort(connIdArrays._sourceIdArr, connIdArrays._targetIdArr, secondaryArr, 0, connIdArrays._sourceIdArr.Length); }
internal DirectedGraph( ConnectionIdArrays connIdArrays, int inputCount, int outputCount, int totalNodeCount) { _connIdArrays = connIdArrays; _inputCount = inputCount; _outputCount = outputCount; _totalNodeCount = 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); }
public ConnectionComparer(ConnectionIdArrays connIdArrays) { _srcIdArr = connIdArrays._sourceIdArr; _tgtIdArr = connIdArrays._targetIdArr; }