public OutputData Run()
        {
            int i, j, numOfObservations = observations.numOfObservations;
            double T = area.t.ElementAt(1) - area.t.ElementAt(0), t0=area.t.ElementAt(0);
            double[] moments;
            double[] arobservations;
            double EPSILON = 1e-10;
            Random rnd = new Random();
            OutputData result = new OutputData();
            List<double> positiveMoments = new List<double>();
            List<double> positiveObservations = new List<double>();

            moments = new double[numOfObservations];
            arobservations = new double[numOfObservations];

            //for (i = 0; i < numOfObservations; ++i)//this code should be removed by input from graph/datagrid
            //{
            //    noise = (rnd.NextDouble() - 0.5) * T / compression; // add some noise
            //    moments[i] = T * rnd.NextDouble() - t0;
            //    arobservations[i] = function(moments[i]) + noise;
            //}

            for (i = 0; i < numOfObservations; ++i)//this code should be removed by input from graph/datagrid
            {
                moments[i] = observations.getMoments()[i];
                arobservations[i] = observations.getYArray()[i];
            }

            // delete all initial observations
            for (i = 0; i < numOfObservations; ++i)
                if (moments[i] > EPSILON) // EPSILON threshold for observations
                {
                    positiveMoments.Add(moments[i]);
                    positiveObservations.Add(arobservations[i]);
                }

            numOfObservations = positiveMoments.Count;

            /* PROBLEM 3: u(t), X0 are factors to control.
             * G0_*u0_ + Gu_*u_ = X_
             * G0_ = str(G0(tm0), m = 1, ..., M0); <- numOfObservations
             * Gu_ = str(Gu(tmu), m = 1, ..., Mu); <- numOfObservations
             * X_ - observations;
             * G0(t) = col(G1(t))
             * G1(t') = col(g(t-t')), t = ti, t' < 0
             * Gu(t) = col(G2(t))
             * G2(t') = col(g(t-t')), t = ti, t' > 0
            */

            double[,] Gu_ = new double[numOfObservations, numOfObservations];
            double[,] G0_ = new double[numOfObservations, numOfObservations];
            double[,] P = new double[numOfObservations, numOfObservations];

            for (i = 0; i < numOfObservations; ++i)
            {

                for (j = 0; j < numOfObservations; ++j)
                {
                    Gu_[i, j] = transfer(positiveMoments[i] - positiveMoments[j]);
                    G0_[i, j] = transfer(positiveMoments[i] + positiveMoments[j]); // take imaginary positiveObservations from [-x1, -x0]
                }
            }

            // P = G0_ * (G0_)^T + Gu_ * (Gu_)^T
            double temp = 0;
            int k;

            for (i = 0; i < numOfObservations; ++i)
            {
                for (j = 0; j < numOfObservations; ++j)
                {
                    temp = 0;
                    for (k = 0; k < numOfObservations; ++k)
                        temp += G0_[i, k] * G0_[j, k] + Gu_[i, k] * Gu_[j, k];
                    P[i, j] = temp;
                }
            }

            // find P+
            double[,] invP = new double[numOfObservations, numOfObservations];

            AdditionalFunctions.inverseMatrix(P, invP, numOfObservations);

            result.resize(numOfObservations);
            // u_ = (Gu_)^T * P+ * X_
            // u0_ = (G0_)^T * P+ * X_
            // u[i] = sum(j) (X[j] * sum(k) (G[k, i] * P+[k, j]))

            for (i = 0; i < numOfObservations; ++i)
            {
                result.u[i] = 0;
                result.u0[i] = 0;
                for (j = 0; j < numOfObservations; ++j)
                {
                    temp = 0;
                    for (k = 0; k < numOfObservations; ++k)
                        temp += Gu_[k, i] * invP[k, j];
                    result.u[i] += temp * positiveObservations[j];

                    temp = 0;
                    for (k = 0; k < numOfObservations; ++k)
                        temp += G0_[k, i] * invP[k, j];
                    result.u0[i] += temp * positiveObservations[j];
                }

            }

            // test solution
            for (i = 0; i < numOfObservations; ++i)
            {
                temp = 0;
                for (j = 0; j < numOfObservations; ++j)
                    temp += G0_[i, j] * result.u0[j] + Gu_[i, j] * result.u[j];
                result.x[i] = temp;
                result.t[i] = positiveMoments[i];
                result.func[i] = function(result.t[i]);
            }

            result.isSolved = true;
            return result;
        }
        public OutputData Run()
        {
            int i, j, numOfObservations=observations.numOfObservations;
            double T = area.t.ElementAt(1) - area.t.ElementAt(0), t0=area.t.ElementAt(0);
            double[] moments;
            double[] arobservations;
            Random rnd = new Random();
            OutputData result = new OutputData();

            moments = new double[numOfObservations+1];
            arobservations = new double[numOfObservations+1];

            // initial observation
            moments[0] = t0;
            if (!observations.findObservationAt(t0, out arobservations[0]))
                arobservations[0] = function(moments[0]) + (rnd.NextDouble() - 0.5) * T / 20;

            //moments = (moments.ToList<double>().AddRange(observations.getMoments())).ToArray();
            //arobservations = (arobservations.ToList<double>().AddRange(observations.getYArray())).ToArray();
            for (i = 0; i < numOfObservations; ++i)//this code should be removed by input from graph/datagrid
            {
                moments[i + 1] = observations.getMoments()[i];
                arobservations[i + 1]  = observations.getYArray()[i];
            }

            ++numOfObservations;

            /* PROBLEM 1: u(t) is unknown.
             * G0_*u0_ + Gu_*u_ = X_
             * G0_ = str(G0(tm0), m = 1, ..., M0); <- numOfObservations
             * Gu_ = str(Gu(tmu), m = 1, ..., Mu); <- numOfObservations
             * X_ - observations;
             * G0(t) = col(G1(t))
             * G1(t') = col(g(t-t')), t = ti, t' < 0
             * Gu(t) = col(G2(t))
             * G2(t') = col(g(t-t')), t = ti, t' > 0
            */

            double[,] Gu_ = new double[numOfObservations, numOfObservations - 1];
            double[,] G0_ = new double[numOfObservations, numOfObservations - 1];
            double[,] P = new double[numOfObservations, numOfObservations];

            for (i = 0; i < numOfObservations; ++i)
            {

                for (j = 1; j < numOfObservations; ++j)
                {
                    Gu_[i, j - 1] = transfer(moments[i] - moments[j]);
                    G0_[i, j - 1] = transfer(moments[i] + moments[j]); // take imaginary observations from [-x1, -x0]
                }
            }

            // P = G0_ * (G0_)^T + Gu_ * (Gu_)^T
            double temp = 0;
            int k;

            for (i = 0; i < numOfObservations; ++i)
            {
                for (j = 0; j < numOfObservations; ++j)
                {
                    temp = 0;
                    for (k = 0; k < numOfObservations - 1; ++k)
                        temp += G0_[i, k] * G0_[j, k] + Gu_[i, k] * Gu_[j, k];
                    P[i, j] = temp;
                }
            }

            // find P+
            double[,] invP = new double[numOfObservations, numOfObservations];

            AdditionalFunctions.inverseMatrix(P, invP, numOfObservations);

            result.resize(numOfObservations);
            // u_ = (Gu_)^T * P+ * X_
            // u0_ = (G0_)^T * P+ * X_
            // u[i] = sum(j) (X[j] * sum(k) (G[k, i] * P+[k, j]))

            for (i = 0; i < numOfObservations - 1; ++i)
            {
                result.u[i] = 0;
                result.u0[i] = 0;
                for (j = 0; j < numOfObservations; ++j)
                {
                    temp = 0;
                    for (k = 0; k < numOfObservations; ++k)
                        temp += Gu_[k, i] * invP[k, j];
                    result.u[i] += temp * arobservations[j];

                    temp = 0;
                    for (k = 0; k < numOfObservations; ++k)
                        temp += G0_[k, i] * invP[k, j];
                    result.u0[i] += temp * arobservations[j];
                }

            }

            // test solution
            for (i = 0; i < numOfObservations; ++i)
            {
                temp = 0;
                for (j = 0; j < numOfObservations - 1; ++j)
                    temp += G0_[i, j] * result.u0[j] + Gu_[i, j] * result.u[j];
                result.x[i] = temp;
                result.t[i] = moments[i];
                result.func[i] = function(result.t[i]);
            }

            result.isSolved = true;
            return result;
        }
        private void DisplayToDataGrid(OutputData result)
        {
            List<OutputPoint> points = result.ResultPoints();
              var Points = CollectionViewSource.GetDefaultView(points);

              List<Tuple<double, double>> pairsU = new List<Tuple<double, double>>();
              for (int i = 0; i < result.x.Count; i++)
                pairsU.Add(new Tuple<double, double>(result.t[i], result.u[i]));

              pairsU = pairsU.OrderBy(p => p.Item1).ToList();

              List<double> xAxisU = new List<double>();
              List<double> yAxisU = new List<double>();
              foreach (var pair in pairsU)
              {
                  xAxisU.Add(pair.Item1);
                  yAxisU.Add(pair.Item2);
              }

              List<Tuple<double, double>> pairsX = new List<Tuple<double, double>>();
              for (int i = 0; i < result.x.Count; i++)
                  pairsX.Add(new Tuple<double, double>(result.t[i], result.x[i]));

              pairsX = pairsX.OrderBy(p => p.Item1).ToList();

              List<double> xAxisX = new List<double>();
              List<double> yAxisX = new List<double>();
              foreach (var pair in pairsX)
              {
                  xAxisX.Add(pair.Item1);
                  yAxisX.Add(pair.Item2);
              }

              List<Tuple<double, double>> pairsF = new List<Tuple<double, double>>();
              for (int i = 0; i < result.x.Count; i++)
                  pairsF.Add(new Tuple<double, double>(result.t[i], result.func[i]));

              pairsF = pairsF.OrderBy(p => p.Item1).ToList();

              List<double> xAxisF = new List<double>();
              List<double> yAxisF = new List<double>();
              foreach (var pair in pairsF)
              {
                  xAxisF.Add(pair.Item1);
                  yAxisF.Add(pair.Item2);
              }

              //Filling Data Grid
              DataGridOutputResults.ItemsSource = Points;

              //Drawing plot
              DrawingPlot(outputPlotter, xAxisU, yAxisU, "Керування", Brushes.Black);
              DrawingPlot(outputPlotter, xAxisX, yAxisX, "Стан системи", Brushes.Red);
              DrawingPlot(comparePlotter, xAxisX, yAxisX, "Стан системи", Brushes.Red);
              DrawingPlot(comparePlotter, xAxisF, yAxisF, "Точне значення функції", Brushes.Blue);
        }
 private void DisplayToMessageBox(OutputData result)
 {
     MessageBox.Show(result.ToString());
 }
        public OutputData Analyse()
        {
            OutputData result = new OutputData();

            if (OperatoOrTransferInput == OperatoOrTransferInputEnum.OPERATOR)
                ConvertOperatorToTransfer();

            if (ProblemType == ProblemTypeEnum.CONTROL_PROBLEM)
            {
                if (ObservationType == ObservationTypeEnum.CONTINIOUS)
                {
                    result.isSolved = false;
                }
                else
                {
                    if (ControlType == ControlTypeEnum.CONTINIOUS)
                    {
                        result.isSolved = false;
                    }
                    else
                    {
                        if (Dimension == DimensionEnum._2D)
                        {
                            if (ControlFactorType == ControlFactorTypeEnum.CONTROL)
                            {
                                Contol2dFirst Solver = new Contol2dFirst(this);
                                result = Solver.Run();
                            }
                            else if (ControlFactorType == ControlFactorTypeEnum.INITIAL_PERTRUBATIONS)
                            {
                                Contol2dSecond Solver = new Contol2dSecond(this);
                                result = Solver.Run();
                            }
                            else if (ControlFactorType == ControlFactorTypeEnum.CONTROL_AND_INITIAL_PERTRUBATIONS)
                            {
                                Contol2dThird Solver = new Contol2dThird(this);
                                result = Solver.Run();
                            }
                            else
                            {
                                result.isSolved=false;
                            }
                        }
                        else
                        {
                            result.isSolved = false;
                        }
                    }
                }
            }
            else
            {
                result.isSolved = false;
            }

            return result;
        }