// please before call this fuction set 2 properties and then call generate method
        public MyTimeSeriForBestHybrid <T> generateForBestHybrid(int numberOfForecastTests)
        {
            MyTimeSeriForBestHybrid <T> tmp = new MyTimeSeriForBestHybrid <T>();
            int leng = TimeSeri.Length - numberOfForecastTests;
            int l    = 0;

            for (; l < leng / 2; l++)
            {
                tmp.part1.Add(TimeSeri[l]);
            }
            for (; l < leng; l++)
            {
                tmp.part2.Add(TimeSeri[l]);
            }
            for (; l < TimeSeri.Length; l++)
            {
                tmp.testCases.Add(TimeSeri[l]);
            }
            return(tmp);
        }
        void Start()
        {
            var Et = new List <double>();
            var Zt = new List <double>();
            var Lt = new List <double>();

            timeSeriGenerator = new TimeSeriGenerator <double>();
            arimaLogger       = new StreamWriter("Best_Hybrid_ArimaGALog.txt");
            int numInp = 0;

            this.Dispatcher.Invoke(new Action(() => numInp = Int32.Parse(NumberOfInpTextBox.Text)));
            timeSeriGenerator.load(numInp);
            Dispatcher.Invoke(new Action(() => ActivityProgressBar.IsIndeterminate = true));
            Dispatcher.Invoke(new Action(() => numberOfTests         = Int32.Parse(OptimumTestTextBox.Text)));
            Dispatcher.Invoke(new Action(() => numberOfForecastTests = Int32.Parse(ForecastTestTextBox.Text)));

            MyTimeSeriForBestHybrid <double> myTimeSeriForBestHybrid =
                timeSeriGenerator.generateForBestHybrid(numberOfForecastTests);


            //maxGAIteretionInArima = 1000;
            //var train = new double[timeSeriGenerator.TimeSeri.Length - 5];
            //var test = new double[5];
            //for (int i = 0; i < train.Length; i++)
            //{
            //    train[i] = timeSeriGenerator.TimeSeri[i];
            //}
            //for (int i = train.Length, j = 0; i < timeSeriGenerator.TimeSeri.Length; i++, j++)
            //{
            //    test[j] = timeSeriGenerator.TimeSeri[i];
            //}

            //ArimaGA aga=new ArimaGA();
            //aga.StartArima(train);

            //NumericalVariable timeSeriii = new NumericalVariable("timeSeriii", train);
            //arimaModel = new ArimaModel(timeSeriii, aga.bestP, aga.bestD, aga.bestQ);
            //arimaModel.Compute();

            //var fv2 = arimaModel.Forecast(numberOfForecastTests);
            //double ea2 = MyErrorParameters.ERROR_Percent(fv2.ToArray(), test);)



            for (int i = 0; i < myTimeSeriForBestHybrid.part2.Count; i++)
            {
                StartArima(myTimeSeriForBestHybrid.part1.ToArray());

                //// converting to double[]
                //double[] db = new double[myTimeSeriForBestHybrid.part1.Count];
                //for (int j = 0; j < db.Length; j++)
                //{
                //    db[j] = myTimeSeriForBestHybrid.part1.ToArray()[j];
                //}

                NumericalVariable timeSerii = new NumericalVariable("timeSerii", myTimeSeriForBestHybrid.part1.ToArray());
                arimaModel = new ArimaModel(timeSerii, myBestP, myBestD, myBestQ);
                arimaModel.Compute();

                var   res = arimaModel.Forecast(1);
                float lt  = (float)res[0];
                Lt.Add(lt);
                double target = myTimeSeriForBestHybrid.part2[i];
                double e      = lt - target;
                Et.Add(e);

                myTimeSeriForBestHybrid.part1.Add(target);
                double mu = myTimeSeriForBestHybrid.part1.Average();

                if (myBestD == 0)
                {
                    Zt.Add(myTimeSeriForBestHybrid.part1[myTimeSeriForBestHybrid.part1.Count - 1] - mu);
                }
                else if (myBestD == 1)
                {
                    Zt.Add(myTimeSeriForBestHybrid.part1[myTimeSeriForBestHybrid.part1.Count - 1] -
                           myTimeSeriForBestHybrid.part1[myTimeSeriForBestHybrid.part1.Count - 2] - mu);
                }
                else
                {
                    Zt.Add(myTimeSeriForBestHybrid.part1[myTimeSeriForBestHybrid.part1.Count - 1] -
                           2 * myTimeSeriForBestHybrid.part1[myTimeSeriForBestHybrid.part1.Count - 2] +
                           myTimeSeriForBestHybrid.part1[myTimeSeriForBestHybrid.part1.Count - 3] - mu);
                }
            }

            ArimaModel EtArimaModel = new ArimaGA().GetBestModel(Et.ToArray());
            ArimaModel ZtArimaModel = new ArimaGA().GetBestModel(Zt.ToArray());
            int        a            = 0;

            SVM svm = new SVM();


            //TimeSeriGenerator<double> gen = new TimeSeriGenerator<double>();
            //gen.NumberOfInputVariables = Int32.Parse(NumberOfInpTextBox.Text);
            //gen.TimeSeri = Et.ToArray();
            //var EtTimeSeries = gen.generate();

            //gen = new TimeSeriGenerator<double>();
            //gen.NumberOfInputVariables = Int32.Parse(NumberOfInpTextBox.Text);
            //gen.TimeSeri = Zt.ToArray();
            //var ZtTimeSeries = gen.generate();
            //// biaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa


            Pair <int> bestAB = CreateComplexHybridModel(Et.ToArray(), Lt.ToArray(), Zt.ToArray());
            double     minErr = SVMComplexModelForBestModel(bestAB.First, bestAB.Second, Et.ToArray(), Lt.ToArray(),
                                                            Zt.ToArray());

            MessageBox.Show(bestAB.First + " , " + bestAB.Second + "\nMinError In Training Is =>  " + minErr, "Now Best M & N Found", MessageBoxButton.OK,
                            MessageBoxImage.Asterisk);


            // --------------------------------- now our complex hybrid model is created -----------------------------------------------------------------

            double mse          = 0;
            double errorPercent = 0;
            double sumTargets   = 0;

            if (myTimeSeriForBestHybrid.part1.Count != timeSeriGenerator.TimeSeri.Length - numberOfForecastTests)
            {
                MessageBox.Show("Input For Arima Model Is Not Completed", "ERROR", MessageBoxButton.OK, MessageBoxImage.Error);
            }


            // << CHECK HERE >>  (FOR CHECKING PURPOSE ONLY , COMMENT HERE LATER)

            var    forecastedVector = arimaModel.Forecast(numberOfForecastTests);
            double eoa = MyErrorParameters.ERROR_Percent(forecastedVector.ToArray(), myTimeSeriForBestHybrid.testCases.ToArray());

            MessageBox.Show("Error Of Arima Is =>  " + eoa, "Arima Error", MessageBoxButton.OK,
                            MessageBoxImage.Information);

            //maxGAIteretionInArima = 1000;
            //StartArima(myTimeSeriForBestHybrid.part1.ToArray());
            //double[] dbb = new double[myTimeSeriForBestHybrid.part1.Count];
            //for (int j = 0; j < dbb.Length; j++)
            //{
            //    dbb[j] = myTimeSeriForBestHybrid.part1.ToArray()[j];
            //}
            //NumericalVariable timeSeriTest = new NumericalVariable("timeSerii", dbb);
            //arimaModel = new ArimaModel(timeSeriTest, myBestP, myBestD, myBestQ);
            //arimaModel.Compute();

            StreamWriter  hybridWriter = new StreamWriter(OUTPUT_FILE_NAME);
            List <double> results      = new List <double>();

            //double errorOfArima = MyErrorParameters.ERROR_Percent(forcastedVector.ToArray(), myTimeSeriForBestHybrid.testCases.ToArray());
            //MessageBox.Show("Error Of Arima Is =>  " + errorOfArima, "Arima Error", MessageBoxButton.OK,
            //                MessageBoxImage.Information);


            // ---------------------------------------------------------------
            int numOfInp = bestAB.First + bestAB.Second + 1;
            int rows     = Et.Count - Math.Max(bestAB.First, bestAB.Second);

            float[,] inps = new float[rows, numOfInp];
            double[] targs = new double[rows];
            int      y     = bestAB.First;
            int      z     = bestAB.Second;
            int      ll    = 0;

            for (int o = 0; o < rows; o++)
            {
                if (y > z)
                {
                    for (int j = 0; j < y; j++)
                    {
                        inps[o, j] = (float)Et[ll + j];
                    }
                    inps[o, y] = (float)Lt[ll + y];
                    for (int j = 0; j < z; j++)
                    {
                        inps[o, y + j + 1] = (float)Zt[ll + y - z + j];
                    }
                    targs[o] = timeSeriGenerator.TimeSeri[ll + y];
                }
                else
                {
                    for (int j = 0; j < y; j++)
                    {
                        inps[o, j] = (float)Et[ll + z - y + j];
                    }
                    inps[o, y] = (float)Lt[ll + z];
                    for (int j = 0; j < z; j++)
                    {
                        inps[o, j + y + 1] = (float)Zt[ll + j];
                    }
                    targs[o] = timeSeriGenerator.TimeSeri[ll + z];
                }
                ll++;
            }

            float[,] trainInputs = new float[rows - numberOfTests, numOfInp];
            float[] trainTargets = new float[rows - numberOfTests];
            float[,] testInputs = new float[numberOfTests, numOfInp];
            float[] testTargets = new float[numberOfTests];
            int     t           = 0;

            for (; t < rows - numberOfTests; t++)
            {
                for (int j = 0; j < numOfInp; j++)
                {
                    trainInputs[t, j] = inps[t, j];
                }
                trainTargets[t] = (float)targs[t];
            }
            for (int o = 0; t < rows; o++, t++)
            {
                for (int j = 0; j < numOfInp; j++)
                {
                    testInputs[o, j] = inps[t, j];
                }
                testTargets[o] = (float)targs[t];
            }

            svmModelHybrid = new SVM();

            SVM_KERNEL_TYPE bestKernelType = SVM_KERNEL_TYPE.RBF;
            double          bestEps        = 0.001;
            SVMParams       p;
            Matrix <float>  trainData    = new Matrix <float>(trainInputs);
            Matrix <float>  trainClasses = new Matrix <float>(trainTargets);

            p            = new SVMParams();
            p.KernelType = bestKernelType;
            p.SVMType    = Emgu.CV.ML.MlEnum.SVM_TYPE.EPS_SVR; // for regression
            p.C          = 1;
            p.TermCrit   = new MCvTermCriteria(100, bestEps);
            p.Gamma      = 1;
            p.Degree     = 1;
            p.P          = 1;
            p.Nu         = 0.1;

            bool _trained = svmModelHybrid.TrainAuto(trainData, trainClasses, null, null, p.MCvSVMParams, 10);

            // ---------------------------------------------------------------


            for (int i = 0; i < numberOfForecastTests; i++)
            {
                float[,] inpTest = new float[bestAB.First + bestAB.Second + 1, 1];
                int l = 0;
                for (int j = 0; j < bestAB.First; j++, l++)
                {
                    inpTest[l, 0] = (float)Et[Et.Count - bestAB.First + j];
                }
                inpTest[l++, 0] = (float)forecastedVector[i];
                for (int j = 0; j < bestAB.Second; j++, l++)
                {
                    inpTest[l, 0] = (float)Zt[Zt.Count - bestAB.Second + j];
                }


                // injaaaaaaaaaaaaaaaaaaaa



                float result = svmModelHybrid.Predict(new Matrix <float>(inpTest));
                results.Add(result);
                hybridWriter.WriteLine(result);
                double target = myTimeSeriForBestHybrid.testCases[i];


                // preparing for next use in this for loop
                double resi = target - (float)forecastedVector[i];    // float resi = target - result;   << CHECK HERE IMPORTANT >>
                Et.Add(resi);

                myTimeSeriForBestHybrid.part1.Add(target);
                double mu = myTimeSeriForBestHybrid.part1.Average();
                if (myBestD == 0)
                {
                    Zt.Add(myTimeSeriForBestHybrid.part1[myTimeSeriForBestHybrid.part1.Count - 1] - mu);
                }
                else if (myBestD == 1)
                {
                    Zt.Add(myTimeSeriForBestHybrid.part1[myTimeSeriForBestHybrid.part1.Count - 1] -
                           myTimeSeriForBestHybrid.part1[myTimeSeriForBestHybrid.part1.Count - 2] - mu);
                }
                else //else if (bestD == 2)    << CHECK HERE >>
                {
                    Zt.Add(myTimeSeriForBestHybrid.part1[myTimeSeriForBestHybrid.part1.Count - 1] -
                           2 * myTimeSeriForBestHybrid.part1[myTimeSeriForBestHybrid.part1.Count - 2] +
                           myTimeSeriForBestHybrid.part1[myTimeSeriForBestHybrid.part1.Count - 3] - mu);
                }
            }

            double _mse          = MyErrorParameters.MSE(results.ToArray(), myTimeSeriForBestHybrid.testCases.ToArray());
            double _errorPercent = MyErrorParameters.ERROR_Percent(results.ToArray(), myTimeSeriForBestHybrid.testCases.ToArray());

            hybridWriter.WriteLine("\n\n\nMSE & ERROR% are =>\n\n{0} {1}", _mse, _errorPercent);

            hybridWriter.Flush();
            hybridWriter.Close();

            MessageBox.Show(
                String.Format(
                    "Complex Hybrid Model Created File {0} For Output Successfully Now , Please Check It Out .",
                    OUTPUT_FILE_NAME), "Hybrid SVM Arima Done", MessageBoxButton.OK,
                MessageBoxImage.Information);
        }