// please before call this fuction set 2 properties and then call generate method
        public MyCategorizedTimeSeri <T> generate(int numberOfTests, int numberOfForecastTests)
        {
            MyTimeSeri <T>            tmp = generate();
            MyCategorizedTimeSeri <T> myCategorizedTimeSeri = new MyCategorizedTimeSeri <T>();
            int rows = tmp.inputs.GetLength(0) - numberOfTests - numberOfForecastTests;

            myCategorizedTimeSeri.TimeSeri            = TimeSeri;
            myCategorizedTimeSeri.TrainInputs         = new T[rows, NumberOfInputVariables];
            myCategorizedTimeSeri.TrainTargets        = new T[rows];
            myCategorizedTimeSeri.TestInputs          = new T[numberOfTests, NumberOfInputVariables];
            myCategorizedTimeSeri.TestTargets         = new T[numberOfTests];
            myCategorizedTimeSeri.ForecastTestInputs  = new T[numberOfForecastTests, NumberOfInputVariables];
            myCategorizedTimeSeri.ForecastTestTargets = new T[numberOfForecastTests];
            int l = 0;

            for (; l < rows; l++)
            {
                for (int j = 0; j < NumberOfInputVariables; j++)
                {
                    myCategorizedTimeSeri.TrainInputs[l, j] = tmp.inputs[l, j];
                }
                myCategorizedTimeSeri.TrainTargets[l] = tmp.targets[l];
            }
            for (int i = 0; i < numberOfTests; i++, l++)
            {
                for (int j = 0; j < NumberOfInputVariables; j++)
                {
                    myCategorizedTimeSeri.TestInputs[i, j] = tmp.inputs[l, j];
                }
                myCategorizedTimeSeri.TestTargets[i] = tmp.targets[l];
            }
            for (int i = 0; i < numberOfForecastTests; i++, l++)
            {
                for (int j = 0; j < NumberOfInputVariables; j++)
                {
                    myCategorizedTimeSeri.ForecastTestInputs[i, j] = tmp.inputs[l, j];
                }
                myCategorizedTimeSeri.ForecastTestTargets[i] = tmp.targets[l];
            }
            return(myCategorizedTimeSeri);
        }
        public void Start()
        {
            try
            {
                svmWriter    = new StreamWriter("Complex_Hybrid_SVMOutput.txt");
                arimaLogger  = new StreamWriter("Complex_Hybrid_ArimaGALog.txt");
                hybridWriter = new StreamWriter(OUTPUT_FILE_NAME);

                #region Loading the training data and classes and test data and test classes

                TimeSeriGenerator <float> timeSeriGenerator = new TimeSeriGenerator <float>();
                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)));
                myCategorizedTimeSeri = timeSeriGenerator.generate(numberOfTests, numberOfForecastTests);

                #endregion


                #region creating and training the svm model

                double          minError       = 9999999;
                SVM_KERNEL_TYPE bestKernelType = SVM_KERNEL_TYPE.LINEAR;
                double          bestEps        = 0.1;

                SVMParams      p;
                Matrix <float> trainData    = new Matrix <float>(myCategorizedTimeSeri.TrainInputs);
                Matrix <float> trainClasses = new Matrix <float>(myCategorizedTimeSeri.TrainTargets);
                Matrix <float> testData     = new Matrix <float>(myCategorizedTimeSeri.TestInputs);
                Matrix <float> testClasses  = new Matrix <float>(myCategorizedTimeSeri.TestTargets);

                foreach (SVM_KERNEL_TYPE tp in Enum.GetValues(typeof(SVM_KERNEL_TYPE)))
                {
                    for (double eps = 0.1; eps >= 0.00001; eps *= 0.1)
                    {
                        using (SVM model = new SVM())
                        {
                            p            = new SVMParams();
                            p.KernelType = tp;
                            p.SVMType    = SVM_TYPE.EPS_SVR; // for regression
                            p.C          = 1;
                            p.TermCrit   = new MCvTermCriteria(100, eps);
                            p.Gamma      = 1;
                            p.Degree     = 1;
                            p.P          = 1;
                            p.Nu         = 0.1;

                            bool trained = model.TrainAuto(trainData, trainClasses, null, null, p.MCvSVMParams, 10);

                            double error = getSumError(model, testData, testClasses);
                            if (trained && minError > error)
                            {
                                minError = error;

                                bestEps        = eps;
                                bestKernelType = tp;
                            }
                        }
                    }
                }

                Matrix <float> trainDataWithGATest    = new Matrix <float>(myCategorizedTimeSeri.getTrainWithTestInputs());
                Matrix <float> trainClassesWithGATest = new Matrix <float>(myCategorizedTimeSeri.getTrainWithTestTargets());

                svmModel     = new SVM();
                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 = svmModel.TrainAuto(trainDataWithGATest, trainClassesWithGATest, null, null,
                                                   p.MCvSVMParams, 10);

                List <float> Et = getResidual(trainDataWithGATest, trainClassesWithGATest);
                svmWriter.Flush();
                svmWriter.Close();

                int bestD = StartArima(Et.ToArray());

                List <float> Zt = new List <float>();
                float        mu = Et.Average();
                if (bestD == 0)
                {
                    for (int i = 0; i < Et.Count; i++)
                    {
                        Zt.Add(Et[i] - mu);
                    }
                }
                else if (bestD == 1)
                {
                    Zt.Add(0);
                    for (int i = 1; i < Et.Count; i++)
                    {
                        Zt.Add(Et[i] - Et[i - 1] - mu);
                    }
                }
                else //else if (bestD == 2)    << CHECK HERE >>
                {
                    Zt.Add(0);
                    Zt.Add(0);
                    for (int i = 2; i < Et.Count; i++)
                    {
                        Zt.Add(Et[i] - 2 * Et[i - 1] + Et[i - 2] - mu);
                    }
                }

                Pair <int> bestAB = CreateComplexHybridModel(Et.ToArray(), Zt.ToArray());
                MessageBox.Show(bestAB.First + " , " + bestAB.Second, "INJAAAAAAAAAAAAAAAAA", MessageBoxButton.OK,
                                MessageBoxImage.Asterisk);

                // now our complex hybrid model is created

                double minErr = SVMComplexModelForBestModel(bestAB.First, bestAB.Second, Et.ToArray(), Zt.ToArray());
                MessageBox.Show("MinError In Training =>  " + minErr);

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

                List <float>   results = new List <float>();
                Matrix <float> testIn  = new Matrix <float>(myCategorizedTimeSeri.ForecastTestInputs);
                Queue <float>  EtQueue = new Queue <float>();
                Queue <float>  ZtQueue = new Queue <float>();
                for (int i = 0; i < bestAB.First; i++)
                {
                    EtQueue.Enqueue(Et[Et.Count - bestAB.First + i]);
                }
                for (int i = 0; i < bestAB.Second; i++)
                {
                    ZtQueue.Enqueue(Zt[Zt.Count - bestAB.Second + i]);
                }
                for (int i = 0; i < numberOfForecastTests; i++)
                {
                    float   Lt      = svmModel.Predict(testIn.GetRow(i));
                    float[] inpTest = new float[bestAB.First + bestAB.Second + 1];
                    float[] EQArray = EtQueue.ToArray();
                    float[] ZQArray = ZtQueue.ToArray();
                    int     l       = 0;
                    for (int j = 0; j < bestAB.First; j++, l++)
                    {
                        inpTest[l] = EQArray[j];
                    }
                    inpTest[l++] = Lt;
                    for (int j = 0; j < bestAB.Second; j++, l++)
                    {
                        inpTest[l] = ZQArray[j];
                    }
                    float result = svmModelHybrid.Predict(new Matrix <float>(inpTest));
                    results.Add(result);
                    hybridWriter.WriteLine(result);
                    float target = myCategorizedTimeSeri.TestTargets[i];

                    //mse += Math.Pow(target - result, 2);
                    //errorPercent += Math.Abs(target - result);
                    //sumTargets += Math.Abs(target);

                    // preparing for next use in this for loop
                    float resi = target - Lt;    // float resi = target - result;   << CHECK HERE IMPORTANT >>
                    Et.Add(resi);
                    EtQueue.Dequeue();
                    EtQueue.Enqueue(resi);
                    ZtQueue.Dequeue();
                    mu = Et.Average();
                    if (bestD == 0)
                    {
                        ZtQueue.Enqueue(EQArray[EQArray.Length - 1] - mu);
                    }
                    else if (bestD == 1)
                    {
                        ZtQueue.Enqueue(EQArray[EQArray.Length - 1] - EQArray[EQArray.Length - 2] - mu);
                    }
                    else //else if (bestD == 2)    << CHECK HERE >>
                    {
                        ZtQueue.Enqueue(EQArray[EQArray.Length - 1] - 2 * EQArray[EQArray.Length - 2] +
                                        EQArray[EQArray.Length - 3] - mu);
                    }
                }
                //mse /= numberOfForecastTests;
                //hybridWriter.WriteLine("\n\nMSE =>  " + mse);
                //errorPercent /= sumTargets;
                //hybridWriter.WriteLine("\n\nERROR% =>  " + errorPercent*100);

                double _mse          = MyErrorParameters.MSE(results.ToArray(), myCategorizedTimeSeri.ForecastTestTargets);
                double _errorPercent = MyErrorParameters.ERROR_Percent(results.ToArray(), myCategorizedTimeSeri.ForecastTestTargets);
                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);

                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace, "ERROR", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }