/// <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));
        }
Example #2
0
        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);
        }
Example #3
0
        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));
    }
Example #6
0
        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)));
        }
Example #7
0
        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)));
        }
Example #8
0
        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));
        }
Example #9
0
        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]);
            }
        }
Example #10
0
        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);
        }
Example #11
0
        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);
        }
Example #12
0
        /// <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));
        }
Example #19
0
        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);
    }
Example #22
0
        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));
        }
Example #23
0
    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);
        }
    }
Example #24
0
        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];
        }
Example #27
0
        /// <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);
        }
Example #28
0
    /// <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);
        }
Example #30
0
        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);
        }