/// <summary>
        /// Constructs a new neural network.
        /// </summary>
        /// <returns>
        /// A constructed neural network.
        /// </returns>
        private static ISupervisedLearnerNetwork ConstructNetwork()
        {
            // Create a backpropagation network for supervised learning.
            var network = new BackpropagationNetwork(new RmsCalculator());

            // Use two activation functions.
            // Linear will be used for the input nodes.
            // Sigmoid will be used for all other nodes.
            var linearFunction = new LinearActivationFunction();
            var sigmoidFunction = new HyperbolicTangentFunction();

            // INPUT LAYER:  Create an input layer with two neurons.
            var inputNeuron1 = new BackpropagationNeuron(GetNextRandomWeight(), linearFunction);
            var inputNeuron2 = new BackpropagationNeuron(GetNextRandomWeight(), linearFunction);
            network.AddInputNode(inputNeuron1);
            network.AddInputNode(inputNeuron2);

            // OUTPUT LAYER:  Create an ouput layer with one neuron.
            var outputNeuron = new BackpropagationNeuron(GetNextRandomWeight(), sigmoidFunction);
            network.AddOutputNode(outputNeuron);

            // HIDDEN LAYER:  Create a hidden layer with three neurons.
            // (Note that the hidden layer isn't defined explicitly like the output and input layers.)
            var hiddenNeuron1 = new BackpropagationNeuron(GetNextRandomWeight(), sigmoidFunction);
            var hiddenNeuron2 = new BackpropagationNeuron(GetNextRandomWeight(), sigmoidFunction);
            var hiddenNeuron3 = new BackpropagationNeuron(GetNextRandomWeight(), sigmoidFunction);

            // So far, the network isn't usable, because no nodes are ever connected by default.

            // Manually wire the input layer to the hidden layer.  Notice that we'll connect every
            // input neuron to every output neuron in order to create a proper feedforward network.
            // If we wanted a different structure, we would use a different wiring pattern.
            new BackpropagationConnection(GetNextRandomWeight(), inputNeuron1, hiddenNeuron1);
            new BackpropagationConnection(GetNextRandomWeight(), inputNeuron1, hiddenNeuron2);
            new BackpropagationConnection(GetNextRandomWeight(), inputNeuron1, hiddenNeuron3);
            new BackpropagationConnection(GetNextRandomWeight(), inputNeuron2, hiddenNeuron1);
            new BackpropagationConnection(GetNextRandomWeight(), inputNeuron2, hiddenNeuron2);
            new BackpropagationConnection(GetNextRandomWeight(), inputNeuron2, hiddenNeuron3);

            // Manually wire the hidden layer to the output layer.
            new BackpropagationConnection(GetNextRandomWeight(), hiddenNeuron1, outputNeuron);
            new BackpropagationConnection(GetNextRandomWeight(), hiddenNeuron2, outputNeuron);
            new BackpropagationConnection(GetNextRandomWeight(), hiddenNeuron3, outputNeuron);

            return network;
        }
        /// <summary>
        /// Constructs a new neural network with nested sub-networks.
        /// </summary>
        /// <returns>
        /// A constructed neural network.
        /// </returns>
        private static ISupervisedLearnerNetwork ConstructNestedNetwork()
        {
            // The activation function for the hidden and output layers.
            var sigmoidFunction = new HyperbolicTangentFunction();

            // Create a backpropagation network for supervised learning.
            var nestedNetwork = new BackpropagationNetwork(new RmsCalculator());

            // INPUT LAYER:  2 Sub-networks
            // (Each of these sub-networks are used to "associate" the two pairs of inputs which
            // represent the OR operations that feed into the XOR operation.)
            var subNetwork1 = ConstructSubnetwork();
            var subNetwork2 = ConstructSubnetwork();
            nestedNetwork.AddInputNode(subNetwork1);
            nestedNetwork.AddInputNode(subNetwork2);

            // OUTPUT LAYER:  Create an ouput layer with one neuron.
            var outputNeuron = new BackpropagationNeuron(GetNextRandomWeight(), sigmoidFunction);
            nestedNetwork.AddOutputNode(outputNeuron);

            // HIDDEN LAYER:  Create a hidden layer with three neurons.
            // (Note that the hidden layer isn't defined explicitly like the output and input layers.)
            var hiddenNeuron1 = new BackpropagationNeuron(GetNextRandomWeight(), sigmoidFunction);
            var hiddenNeuron2 = new BackpropagationNeuron(GetNextRandomWeight(), sigmoidFunction);
            var hiddenNeuron3 = new BackpropagationNeuron(GetNextRandomWeight(), sigmoidFunction);

            // Manually wire the network to be a feedforward network just as in Demo #1.
            // Notice that the sub-networks receive connections the same as regular neurons do.
            //
            // Input Layer to Hidden Layer
            new BackpropagationConnection(GetNextRandomWeight(), subNetwork1, hiddenNeuron1);
            new BackpropagationConnection(GetNextRandomWeight(), subNetwork1, hiddenNeuron2);
            new BackpropagationConnection(GetNextRandomWeight(), subNetwork1, hiddenNeuron3);
            new BackpropagationConnection(GetNextRandomWeight(), subNetwork2, hiddenNeuron1);
            new BackpropagationConnection(GetNextRandomWeight(), subNetwork2, hiddenNeuron2);
            new BackpropagationConnection(GetNextRandomWeight(), subNetwork2, hiddenNeuron3);

            // Hidden Layer to Output Layer
            new BackpropagationConnection(GetNextRandomWeight(), hiddenNeuron1, outputNeuron);
            new BackpropagationConnection(GetNextRandomWeight(), hiddenNeuron2, outputNeuron);
            new BackpropagationConnection(GetNextRandomWeight(), hiddenNeuron3, outputNeuron);

            return nestedNetwork;
        }