/// <summary>
        /// Create a Feedforward Network with the given number of layers and neurons filled with the given weights from the genome
        /// </summary>
        /// <param name="inputs">Number of input neurons</param>
        /// <param name="outputNeurons">Number of output neurons</param>
        /// <param name="hiddenLayers">Number of hidden neuron layers</param>
        /// <param name="neuronsPerHiddenLayer">Number of neurons per hidden layer</param>
        public FeedforwardNetwork(int inputs, int outputNeurons, int hiddenLayers, int neuronsPerHiddenLayer, Genome genome)
        {
            InputNeuronCount  = inputs;
            OutputNeuronCount = outputNeurons;
            Genome            = genome;

            var allweights = genome.Chromosome;

            var lastOutputCount = setHiddenLayers(inputs, hiddenLayers, neuronsPerHiddenLayer, allweights);
            var usedWeightCount = _hiddenLayers.Sum(x => x.AllWeights.Count());

            _outputLayer = new NeuronLayer(outputNeurons, lastOutputCount, allweights.Skip(usedWeightCount));
        }
        /// <summary>
        /// Create a Feedforward Network with the given number of layers and neurons filled with the given weights from the genome
        /// </summary>
        /// <param name="inputs">Number of input neurons</param>
        /// <param name="outputNeurons">Number of output neurons</param>
        /// <param name="hiddenLayers">Number of hidden neuron layers</param>
        /// <param name="neuronsPerHiddenLayer">Number of neurons per hidden layer</param>
        public FeedforwardNetwork(int inputs, int outputNeurons, int hiddenLayers, int neuronsPerHiddenLayer, Genome genome)
        {
            InputNeuronCount = inputs;
            OutputNeuronCount = outputNeurons;
            Genome = genome;

            var allweights = genome.Chromosome;

            var lastOutputCount = setHiddenLayers(inputs, hiddenLayers, neuronsPerHiddenLayer, allweights);
            var usedWeightCount = _hiddenLayers.Sum(x => x.AllWeights.Count());

            _outputLayer = new NeuronLayer(outputNeurons, lastOutputCount, allweights.Skip(usedWeightCount));
        }
        /// <summary>
        /// Create a Feedforward Network with the given number of layers and neurons, a random genome will be created
        /// </summary>
        /// <param name="inputs">Number of input neurons</param>
        /// <param name="outputNeurons">Number of output neurons</param>
        /// <param name="hiddenLayers">Number of hidden neuron layers</param>
        /// <param name="neuronsPerHiddenLayer">Number of neurons per hidden layer</param>
        public FeedforwardNetwork(int inputs, int outputNeurons, int hiddenLayers, int neuronsPerHiddenLayer)
        {
            InputNeuronCount = inputs;
            OutputNeuronCount = outputNeurons;
            var lastOutputCount = setHiddenLayers(inputs, hiddenLayers, neuronsPerHiddenLayer);
            _outputLayer = new NeuronLayer(outputNeurons, lastOutputCount);

            var allWeights = new List<double>();
            foreach (var layer in _hiddenLayers)
            {
                allWeights.AddRange(layer.AllWeights);
            }
            allWeights.AddRange(_outputLayer.AllWeights);

            Genome = new Genome(allWeights, 0.0);
        }
        /// <summary>
        /// Create a Feedforward Network with the given number of layers and neurons, a random genome will be created
        /// </summary>
        /// <param name="inputs">Number of input neurons</param>
        /// <param name="outputNeurons">Number of output neurons</param>
        /// <param name="hiddenLayers">Number of hidden neuron layers</param>
        /// <param name="neuronsPerHiddenLayer">Number of neurons per hidden layer</param>
        public FeedforwardNetwork(int inputs, int outputNeurons, int hiddenLayers, int neuronsPerHiddenLayer)
        {
            InputNeuronCount  = inputs;
            OutputNeuronCount = outputNeurons;
            var lastOutputCount = setHiddenLayers(inputs, hiddenLayers, neuronsPerHiddenLayer);

            _outputLayer = new NeuronLayer(outputNeurons, lastOutputCount);

            var allWeights = new List <double>();

            foreach (var layer in _hiddenLayers)
            {
                allWeights.AddRange(layer.AllWeights);
            }
            allWeights.AddRange(_outputLayer.AllWeights);

            Genome = new Genome(allWeights, 0.0);
        }
        private int setHiddenLayers(int inputs, int hiddenLayers, int neuronsPerHiddenLayer)
        {
            _hiddenLayers = new List <NeuronLayer>();
            _stateLayers  = new List <NeuronLayer>();
            var lastOutputCount = inputs;

            for (int layerIndex = 0; layerIndex < hiddenLayers; layerIndex++)
            {
                var stateLayer = new NeuronLayer(neuronsPerHiddenLayer, inputsPerNeuron: 1, randomInputWeights: false);
                _stateLayers.Add(stateLayer);

                var inputForHiddenLayer = lastOutputCount + neuronsPerHiddenLayer;
                var hiddenLayer         = new NeuronLayer(neuronsPerHiddenLayer, inputForHiddenLayer);
                _hiddenLayers.Add(hiddenLayer);

                lastOutputCount = neuronsPerHiddenLayer;
            }
            return(lastOutputCount);
        }
        private int setHiddenLayers(int inputs, int hiddenLayers, int neuronsPerHiddenLayer)
        {
            _hiddenLayers = new List<NeuronLayer>();
            _stateLayers = new List<NeuronLayer>();
            var lastOutputCount = inputs;
            for (int layerIndex = 0; layerIndex < hiddenLayers; layerIndex++)
            {
                var stateLayer = new NeuronLayer(neuronsPerHiddenLayer, inputsPerNeuron: 1, randomInputWeights: false);
                _stateLayers.Add(stateLayer);

                var inputForHiddenLayer = lastOutputCount + neuronsPerHiddenLayer;
                var hiddenLayer = new NeuronLayer(neuronsPerHiddenLayer, inputForHiddenLayer);
                _hiddenLayers.Add(hiddenLayer);

                lastOutputCount = neuronsPerHiddenLayer;
            }
            return lastOutputCount;
        }