public ChordChainGeneticFunction(
            DiscreteNeuralNetworkByChord dnn,
            NGramGraphMarkovChain <Chord> chord,
            INGramWeightAssigner <Chord> assigner,
            ChordRandomFunctionType type = ChordRandomFunctionType.NoRandomSelection,
            ChordCrossFunctionType cross = ChordCrossFunctionType.DiscreteChoice)
        {
            dnn.NullCheck();
            chord.NullCheck();
            assigner.NullCheck();

            this.NeuralNetwork      = dnn;
            this.NGramGraph         = chord;
            this.RandomFunctionType = type;
            this.CrossFunctionType  = cross;
            this.ChordDepth         = this.NeuralNetwork.InputsCount * 2;
            this.NGramDepth         = 10;
            this.MutateCoefficient  = 0.05D;
            this.Assigner           = assigner;

            this.random = new Random();

            switch (type)
            {
            case ChordRandomFunctionType.AllowRandomSelection:
                this.RandomSelectionCoefficient = .05D;
                return;
            }
        }
        public double Fitness(NGram <Chord>[] t)
        {
            var training = t.SelectMany(x => x.SelectMany(y => DiscreteNeuralNetworkByChord.ConvertChordIntoTrainingInput(y))).ToList();

            if (training.Count < this.NeuralNetwork.InputsCount)
            {
                training.AddRange(Enumerable.Repeat(-2D, this.NeuralNetwork.InputsCount - training.Count));
                return(this.NeuralNetwork.Compute(training.ToArray()));
            }

            var data  = this.Partition(training);
            var query = data.Where(x => x.Length == this.NeuralNetwork.InputsCount).ToList();
            var error = query.Select(x => this.NeuralNetwork.Compute(x)).Sum();

            if (data.Count != query.Count)
            {
                int   count   = data.Last().Length;
                float percent = (float)count / (float)query.Count * (float)this.NeuralNetwork.InputsCount;
                error *= percent;
            }
            return(error);
        }
        private void trainingButton_Click(object sender, EventArgs e)
        {
            PianoNoteRetriever retriever = new PianoNoteRetriever();
            var midiEvents = new InstrumentMidiEventProducer(this.files.Select(x => new Sequence(x)));
            var midi = midiEvents.GetOrderedMessages(GeneralMidiInstrument.AcousticGrandPiano);
            Chord.AllowForComplexSimplification = this.checkBox.Checked;
            var accords = Chord.RetrieveChords(midi, retriever);

            DiscreteDataRetriever data = new DiscreteDataRetriever(accords.ToList());
            DiscreteNeuralNetworkByChord.OkayWeight = (double)this.okayWeight.Value;
            DiscreteNeuralNetworkByChord.HiddenLayerSize = (int)hiddelLayerSize.Value;

            if (this.okayFiles != null)
            {
                var midiEvents1 = new InstrumentMidiEventProducer(this.okayFiles.Select(x => new Sequence(x)));
                var midi1 = midiEvents1.GetOrderedMessages(GeneralMidiInstrument.AcousticGrandPiano);
                Chord.AllowForComplexSimplification = this.checkBox.Checked;
                var accords1 = Chord.RetrieveChords(midi1, retriever);
                DiscreteDataRetriever data1 = new DiscreteDataRetriever(accords1.ToList());

                this.nnByChord = new DiscreteNeuralNetworkByChord(data.Good, data1.Good, data.Bad.Union(data1.Bad).Take(data.Bad.Count).ToList(),
                    new AForge.Neuro.BipolarSigmoidFunction());
            }
            else
            {
                this.nnByChord = new DiscreteNeuralNetworkByChord(data.Good, data.Okay, data.Bad, new AForge.Neuro.SigmoidFunction());
            }

            foreach (var item in this.Controls.OfType<Control>())
            {
                item.Enabled = false;
            }
            threadTrain = new Thread(Start);
            threadTrain.Start();
        }