public PullWeightsLearning( ActivationNetwork network )
        {
            this.network = network;

            // create error and deltas arrays
            neuronErrors = new double[network.Layers.Length][];
            weightsUpdates = new double[network.Layers.Length][][];
            thresholdsUpdates = new double[network.Layers.Length][];

            // initialize errors and deltas arrays for each layer
            for ( int i = 0; i < network.Layers.Length; i++ )
            {
                Layer layer = network.Layers[i];

                neuronErrors[i] = new double[layer.Neurons.Length];
                weightsUpdates[i] = new double[layer.Neurons.Length][];
                thresholdsUpdates[i] = new double[layer.Neurons.Length];

                // for each neuron
                for ( int j = 0; j < weightsUpdates[i].Length; j++ )
                {
                    weightsUpdates[i][j] = new double[layer.InputsCount];
                }
            }
        }
        /// <summary>
        ///   Constructs a new Gaussian Weight initialization.
        /// </summary>
        /// 
        /// <param name="network">The activation network whose weights will be initialized.</param>
        /// <param name="stdDev">The standard deviation to be used. Common values lie in the 0.001-
        /// 0.1 range. Default is 0.1.</param>
        /// 
        public GaussianWeights(ActivationNetwork network, double stdDev = 0.1)
        {
            this.network = network;

            this.random = new GaussianGenerator(0f, (float)stdDev, Accord.Math.Tools.Random.Next());

            this.UpdateThresholds = false;
        }
        /// <summary>
        ///   Constructs a new Nguyen-Widrow Weight initialization.
        /// </summary>
        /// 
        /// <param name="network">The activation network whose weights will be initialized.</param>
        /// 
        public NguyenWidrow(ActivationNetwork network)
        {
            this.network = network;

            int hiddenNodes = network.Layers[0].Neurons.Length;
            int inputNodes = network.Layers[0].InputsCount;

            randRange = new Range(-0.5f, 0.5f);
            beta = 0.7 * Math.Pow(hiddenNodes, 1.0 / inputNodes);
        }
        /// <summary>
        ///   Initializes a new instance of the <see cref="ParallelResilientBackpropagationLearning"/> class.
        /// </summary>
        /// 
        /// <param name="network">Network to teach.</param>
        /// 
        public ParallelResilientBackpropagationLearning(ActivationNetwork network)
        {
            this.network = network;

            networkOutputs = new ThreadLocal<double[][]>(() => new double[network.Layers.Length][]);

            networkErrors = new ThreadLocal<double[][]>(() =>
            {
                var e = new double[network.Layers.Length][];
                for (int i = 0; i < e.Length; i++)
                    e[i] = new double[network.Layers[i].Neurons.Length];
                return e;
            });

            weightsDerivatives = new double[network.Layers.Length][][];
            thresholdsDerivatives = new double[network.Layers.Length][];

            weightsPreviousDerivatives = new double[network.Layers.Length][][];
            thresholdsPreviousDerivatives = new double[network.Layers.Length][];

            weightsUpdates = new double[network.Layers.Length][][];
            thresholdsUpdates = new double[network.Layers.Length][];

            // Initialize layer derivatives and updates
            for (int i = 0; i < network.Layers.Length; i++)
            {
                Layer layer = network.Layers[i];

                weightsDerivatives[i] = new double[layer.Neurons.Length][];
                weightsPreviousDerivatives[i] = new double[layer.Neurons.Length][];
                weightsUpdates[i] = new double[layer.Neurons.Length][];

                // for each neuron
                for (int j = 0; j < layer.Neurons.Length; j++)
                {
                    weightsDerivatives[i][j] = new double[layer.InputsCount];
                    weightsPreviousDerivatives[i][j] = new double[layer.InputsCount];
                    weightsUpdates[i][j] = new double[layer.InputsCount];
                }

                thresholdsDerivatives[i] = new double[layer.Neurons.Length];
                thresholdsPreviousDerivatives[i] = new double[layer.Neurons.Length];
                thresholdsUpdates[i] = new double[layer.Neurons.Length];
            }

            // Initialize steps
            Reset(initialStep);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="EvolutionaryFitness"/> class.
        /// </summary>
        /// 
        /// <param name="network">Neural network for which fitness will be calculated.</param>
        /// <param name="input">Input data samples for neural network.</param>
        /// <param name="output">Output data sampels for neural network (desired output).</param>
        /// 
        /// <exception cref="ArgumentException">Length of inputs and outputs arrays must be equal and greater than 0.</exception>
        /// <exception cref="ArgumentException">Length of each input vector must be equal to neural network's inputs count.</exception>
        /// 
        public EvolutionaryFitness( ActivationNetwork network, double[][] input, double[][] output )
        {
            if ( ( input.Length == 0 ) || ( input.Length != output.Length ) )
            {
                throw new ArgumentException( "Length of inputs and outputs arrays must be equal and greater than 0." );
            }

            if ( network.InputsCount != input[0].Length )
            {
                throw new ArgumentException( "Length of each input vector must be equal to neural network's inputs count." );
            }

            this.network = network;
            this.input = input;
            this.output = output;
        }
        //создание сети для обучения и учителя по топологии
        private void createLearn(int[] topology)
        {
            if (this.alphaBox.Text != "")
                activationFunc = new BipolarSigmoidFunction(Double.Parse(this.alphaBox.Text));
            else
                activationFunc = new BipolarSigmoidFunction();

            network = new ActivationNetwork(activationFunc,
            colCountData - 1, topology);
            //ActivationLayer layer = network.Layers[0] as ActivationLayer;

            NguyenWidrow initializer = new NguyenWidrow(network);
            initializer.Randomize();
            // create teacher
            /*GeneticLearning genetic = new GeneticLearning(network, chromosomes);
            teacher = genetic;*/
        }
        // Create and initialize genetic population
        private int CalculateNetworkSize( ActivationNetwork activationNetwork )
        {
            // caclculate total amount of weight in neural network
            int networkSize = 0;

            for ( int i = 0; i < network.Layers.Length; i++ )
            {
                Layer layer = network.Layers[i];

                for ( int j = 0; j < layer.Neurons.Length; j++ )
                {
                    // sum all weights and threshold
                    networkSize += layer.Neurons[j].Weights.Length + 1;
                }
            }

            return networkSize;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="EvolutionaryLearning"/> class.
        /// </summary>
        /// 
        /// <param name="activationNetwork">Activation network to be trained.</param>
        /// <param name="populationSize">Size of genetic population.</param>
        /// 
        /// <remarks><para>This version of constructor is used to create genetic population
        /// for searching optimal neural network's weight using default set of parameters, which are:
        /// <list type="bullet">
        /// <item>Selection method - elite;</item>
        /// <item>Crossover rate - 0.75;</item>
        /// <item>Mutation rate - 0.25;</item>
        /// <item>Rate of injection of random chromosomes during selection - 0.20;</item>
        /// <item>Random numbers generator for initializing new chromosome -
        /// <c>UniformGenerator( new Range( -1, 1 ) )</c>;</item>
        /// <item>Random numbers generator used during mutation for genes' multiplication -
        /// <c>ExponentialGenerator( 1 )</c>;</item>
        /// <item>Random numbers generator used during mutation for adding random value to genes -
        /// <c>UniformGenerator( new Range( -0.5f, 0.5f ) )</c>.</item>
        /// </list></para>
        /// 
        /// <para>In order to have full control over the above default parameters, it is possible to
        /// used extended version of constructor, which allows to specify all of the parameters.</para>
        /// </remarks>
        ///
        public GeneticLearning(ActivationNetwork activationNetwork, int populationSize)
        {
            // Check of assumptions during debugging only
            Debug.Assert( activationNetwork != null );
            Debug.Assert( populationSize > 0 );

            // networks's parameters
            this.network = activationNetwork;
            this.numberOfNetworksWeights = CalculateNetworkSize( activationNetwork );

            // population parameters
            this.populationSize = populationSize;
            this.chromosomeGenerator = new UniformGenerator( new Range( -1, 1 ) );
            this.mutationMultiplierGenerator = new ExponentialGenerator( 1 );
            this.mutationAdditionGenerator = new UniformGenerator( new Range( -0.5f, 0.5f ) );
            this.selectionMethod = new EliteSelection( );
            this.crossOverRate = 0.75;
            this.mutationRate = 0.25;
            this.randomSelectionRate = 0.2;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="EvolutionaryLearning"/> class.
        /// </summary>
        /// 
        /// <param name="activationNetwork">Activation network to be trained.</param>
        /// <param name="populationSize">Size of genetic population.</param>
        /// <param name="chromosomeGenerator">Random numbers generator used for initialization of genetic
        /// population representing neural network's weights and thresholds (see <see cref="DoubleArrayChromosome.chromosomeGenerator"/>).</param>
        /// <param name="mutationMultiplierGenerator">Random numbers generator used to generate random
        /// factors for multiplication of network's weights and thresholds during genetic mutation
        /// (ses <see cref="DoubleArrayChromosome.mutationMultiplierGenerator"/>.)</param>
        /// <param name="mutationAdditionGenerator">Random numbers generator used to generate random
        /// values added to neural network's weights and thresholds during genetic mutation
        /// (see <see cref="DoubleArrayChromosome.mutationAdditionGenerator"/>).</param>
        /// <param name="selectionMethod">Method of selection best chromosomes in genetic population.</param>
        /// <param name="crossOverRate">Crossover rate in genetic population (see
        /// <see cref="Population.CrossoverRate"/>).</param>
        /// <param name="mutationRate">Mutation rate in genetic population (see
        /// <see cref="Population.MutationRate"/>).</param>
        /// <param name="randomSelectionRate">Rate of injection of random chromosomes during selection
        /// in genetic population (see <see cref="Population.RandomSelectionPortion"/>).</param>
        /// 
        public GeneticLearning( ActivationNetwork activationNetwork, int populationSize,
            IRandomNumberGenerator chromosomeGenerator,
            IRandomNumberGenerator mutationMultiplierGenerator,
            IRandomNumberGenerator mutationAdditionGenerator,
            ISelectionMethod selectionMethod,
            double crossOverRate, double mutationRate, double randomSelectionRate )
        {
            // Check of assumptions during debugging only
            Debug.Assert( activationNetwork != null );
            Debug.Assert( populationSize > 0 );
            Debug.Assert( chromosomeGenerator != null );
            Debug.Assert( mutationMultiplierGenerator != null );
            Debug.Assert( mutationAdditionGenerator != null );
            Debug.Assert( selectionMethod != null );
            Debug.Assert( crossOverRate >= 0.0 && crossOverRate <= 1.0 );
            Debug.Assert( mutationRate >= 0.0 && crossOverRate <= 1.0 );
            Debug.Assert( randomSelectionRate >= 0.0 && randomSelectionRate <= 1.0 );

            // networks's parameters
            this.network = activationNetwork;
            this.numberOfNetworksWeights = CalculateNetworkSize( activationNetwork );

            // population parameters
            this.populationSize = populationSize;
            this.chromosomeGenerator = chromosomeGenerator;
            this.mutationMultiplierGenerator = mutationMultiplierGenerator;
            this.mutationAdditionGenerator = mutationAdditionGenerator;
            this.selectionMethod = selectionMethod;
            this.crossOverRate = crossOverRate;
            this.mutationRate = mutationRate;
            this.randomSelectionRate = randomSelectionRate;
        }