コード例 #1
0
ファイル: Optimizer.cs プロジェクト: ObDivanKenobi/MO1
        public Tuple <Matrix, double> SpeedestDescentMethod(Matrix x0, double epsilon, double a = 1, int steps = 100)
        {
            int n        = function.Variables.Count,
                accuracy = 10;// Regex.Match(epsilon.ToString(), @"(?<=[,])\d+").Value.Count();

            //заполняем градиент
            FunctionParser[] gradFunctional = new FunctionParser[n];
            for (int i = 0; i < n; ++i)
            {
                gradFunctional[i] = function.DifferentiateBy(function.Variables[i]).Optimize();
            }

            //вычисляем градиент в точке x_0
            Matrix x    = (Matrix)x0.Clone(),
                   grad = CountGrad(x, gradFunctional);

            int step = steps;

            //пока ||grad f(x_0)|| >= e
            while (Norm(grad) >= epsilon && step-- > 0)
            {
                string func = function.ToString();
                //заменяем цифры в скобках просто цифрами
                func = Regex.Replace(func, @"[(](\d+)[)]", "$1");
                //заменяем переменные x_i на x_i - x * grad_i, чтобы получить функцию одной переменной x
                for (int i = 0; i < function.Variables.Count; ++i)
                {
                    string replacedVariable = function.Variables[i],
                    //replacement = grad[i] > 0 ? $"{Math.Round(x[i], accuracy)}-{Math.Round(grad[i], accuracy)}a" : $"{Math.Round(x[i], accuracy)}+{Math.Abs(Math.Round(grad[i], accuracy))}a";
                           replacement = grad[i] > 0 ? $"{x[i]:f10}-{grad[i]:f10}a" : $"{x[i]:f10}+{Math.Abs(grad[i]):f10}a";

                    func = Regex.Replace(func, $@"(?<=[(]){replacedVariable}(?=[)])", replacement);
                    func = Regex.Replace(func, replacedVariable, $"({replacement})");
                }

                FunctionParser Ф = new FunctionParser(func);
                Matrix         A = new Matrix(1);
                A[0] = a;
                Optimizer support = new Optimizer(Ф);
                var       min     = support.NewtonsMethod(A, epsilon);

                x    = x - min.Item1[0] * grad;
                grad = CountGrad(x, gradFunctional);
            }

            if (step < 0)
            {
                throw new MethodDivergencyException($"Методу не удалось найти решение за {steps} шагов.");
            }

            return(new Tuple <Matrix, double>(x, f(x.ToVector())));
        }