/// <summary>
        /// Минимизация функции
        /// </summary>
        /// <param name="f">Функция</param>
        /// <param name="x">Начальное приближение</param>
        /// <param name="gradient_calc">Функция вычисление градиента</param>
        /// <param name="eps">Точность</param>
        /// <param name="steps_count">Возвращаемое значение: число шагов, за которое был найден ответ</param>
        /// <returns></returns>
        override public Vector <double> FindMinimum(Func <Vector <double>, double> f, Vector <double> x, AbstractGradientCalc gradient_calc, double eps, out int steps_count)
        {
            ///!!!!!!!!!
            double interval_h = 0.0001;                                                 //Шаг для поиска интервала
            double min_eps    = 0.0001;                                                 //Точность для поиска минимума

            steps_count = 0;                                                            //Число шагов
            string format = Utils.GetFormat(eps);
            double norm;

            //Создаем единичную квазиньютновскую матрицу
            Matrix <double> H = Matrix <double> .Build.DenseIdentity(x.Count, x.Count);

            //Matrix<double> H_prev = null;

            Vector <double> p = Vector <double> .Build.Dense(x.Count);

            Vector <double> grad      = null;
            Vector <double> grad_prev = Vector <double> .Build.Dense(x.Count);

            Vector <double> x_prev = Vector <double> .Build.Dense(x.Count);

            Logger.Write("===> Минимизация методом переменной метрики <==");
            Logger.WriteContinue(" |Начальная точка x0: {0}", x.Vector2String(format));
            Logger.WriteContinue(" |Точность eps: {0} ", eps.ToString(format));

            Logger.Write("Шаг 1: k=0");

            //Вычисление градиента
            grad = gradient_calc.CalcGradient(f, x);

            while ((norm = calc_norm(grad)) > eps)
            {
                Logger.Write("Шаг 2: Вычисление градиента");
                Logger.WriteContinue("grad = {0}", grad.Vector2String(format));

                Logger.Write("Шаг 3: Проверка критерия останова:");
                Logger.WriteContinue("Норма norm = {0}", norm.ToString(format));
                Logger.WriteContinue("norm > eps : {0} > {1}", norm.ToString(format), eps.ToString(format));

                if (steps_count > 0)
                {
                    //Вспомогательные матрицы (Матрицы столбцы)
                    var s_v = (x - x_prev);
                    var s   = s_v.ToColumnMatrix();
                    Logger.Write("Шаг 5: s:{0}T", s_v.Vector2String(format));

                    var y_v = (grad - grad_prev);
                    var y   = y_v.ToColumnMatrix();
                    Logger.Write("Шаг 6: y:{0}T", y_v.Vector2String(format));

                    //Эти же транспонированные
                    var y_t = y.Transpose();
                    var s_t = s.Transpose();

                    //Пересчет квазиньютоновской матрицы
                    H = H - (H * y * y_t * H) / (y_t * H * y)[0, 0] + (s * s_t) / (y_t * s)[0, 0];
                    Logger.Write("Шаг 7: Пересчет матрицы H:\n{0}", H);
                }


                //Вычисление направления поиска
                p = -H * grad;
                Logger.Write("Шаг 8: Направление поиска p = {0}", p.Vector2String(format));

                //Определяем шаг поиска методом одномерной оптимизации
                Func <double, double> f_ = y => f(x + y * p);
                var interval             = IntervalFinder.Find(0, interval_h, f_);
                var a = GoldenRatioMethod.FindMinimum(interval, f_, min_eps);

                Logger.Write("Шаг 9: Определение длины шага");
                Logger.WriteContinue("ak = {0}", a);

                x.CopyTo(x_prev);
                x = x + a * p;

                Logger.Write("Шаг 10: x = {0}", x.Vector2String(format));

                //Вычисление градиента
                grad.CopyTo(grad_prev);
                grad = gradient_calc.CalcGradient(f, x);

                steps_count++;
                Logger.Write("Шаг 11: k = k +1 = {0}", steps_count);
                Logger.Write("----------------------");
            }

            Logger.Write("Шаг 3: Проверка критерия останова:");
            Logger.WriteContinue("Норма norm = {0}", norm.ToString(format));
            Logger.WriteContinue("norm > eps : {0} > {1}", norm.ToString(format), eps.ToString(format));

            Logger.Write("Шаг 12: x* = x = {0}", x.Vector2String(format));
            Logger.WriteContinue("Поиск закончен");
            Logger.WriteContinue("Число итераций: {0}", steps_count);

            return(x);
        }
        /// <summary>
        /// Минимизация функции
        /// </summary>
        /// <param name="f">Функция</param>
        /// <param name="x">Начальное приближение</param>
        /// <param name="gradient_calc">Функция вычисление градиента</param>
        /// <param name="eps">Точность</param>
        /// <param name="steps_count">Возвращаемое значение: число шагов, за которое был найден ответ</param>
        /// <returns></returns>
        override public Vector <double> FindMinimum(Func <Vector <double>, double> f, Vector <double> x, AbstractGradientCalc gradient_calc, double eps, out int steps_count)
        {
            Vector <double> grad = null;

            ///!!!!!!!!!
            double interval_h = 0.000001;                                       //Шаг для поиска интервала
            double min_eps    = 0.000001;                                       //Точность для поиска минимума
            string format     = Utils.GetFormat(eps / 100);                     //Форматная строка для вывода чисел с нужным числом знаков

            steps_count = 0;
            double norm = 0;

            Logger.Write("===> Минимизация оптимальным градиентным методом <==");
            Logger.WriteContinue(" |Начальная точка x0: {0}", x.Vector2String(format));
            Logger.WriteContinue(" |Точность eps: {0} ", eps.ToString(format));


            Logger.Write("Шаг 1: k = {0}", steps_count);

            //Вычисление градиента
            grad = gradient_calc.CalcGradient(f, x);

            while ((norm = calc_norm(grad)) > eps)
            {
                Debug.WriteLine("Grad: {0} f**k", "kek");

                Logger.Write("Шаг 2: Вычисление градиента");
                Logger.WriteContinue("grad = {0}", grad.Vector2String(format));

                Logger.Write("Шаг 3: Проверка критерия останова:");
                Logger.WriteContinue("Норма norm = {0}", norm.ToString(format));
                Logger.WriteContinue("norm > eps : {0} > {1}", norm.ToString(format), eps.ToString(format));

                //Вычисление длины шага
                //ak = arg min f(x-a*gradf(x));
                Func <double, double> f_ = y => f(x - y * grad);
                var interval             = IntervalFinder.Find(0, interval_h, f_);
                var a = GoldenRatioMethod.FindMinimum(interval, f_, min_eps);

                Logger.Write("Шаг 4: Определение длины шага");
                Logger.WriteContinue("ak = {0}", a.ToString(format));

                //Шаг
                x = x - a * grad;
                //Debug.WriteLine("x: {0}", x.Vector2String("N3"));
                Logger.Write("Шаг 5: Xk+1 = Xk + a*grad = {0}", x.Vector2String(format));
                grad = gradient_calc.CalcGradient(f, x);

                steps_count++;
                Logger.Write("Шаг 6: k = k +1 = {0}", steps_count);
                Logger.Write("----------------------");
            }

            Logger.Write("Шаг 3: Проверка критерия останова:");
            Logger.WriteContinue("Норма norm = {0}", norm.ToString(format));
            Logger.WriteContinue("norm > eps : {0} > {1}", norm.ToString(format), eps.ToString(format));

            Logger.Write("Шаг 8: x* = x = {0}", x.Vector2String(format));
            Logger.WriteContinue("Поиск закончен");
            Logger.WriteContinue("Число итераций: {0}", steps_count);

            return(x);
        }
Exemple #3
0
 /// <summary>
 /// Минимизация функции
 /// </summary>
 /// <param name="f">Функция</param>
 /// <param name="x">Начальное приближение</param>
 /// <param name="gradient_calc">Функция вычисление градиента</param>
 /// <param name="eps">Точность</param>
 /// <param name="steps_count">Возвращаемое значение: число шагов, за которое был найден ответ</param>
 /// <returns></returns>
 abstract public Vector <double> FindMinimum(Func <Vector <double>, double> f, Vector <double> x, AbstractGradientCalc gradient_calc, double eps, out int steps_count);
        /// <summary>
        /// Минимизация функции
        /// </summary>
        /// <param name="f">Функция</param>
        /// <param name="x">Начальное приближение</param>
        /// <param name="gradient_calc">Функция вычисление градиента</param>
        /// <param name="eps">Точность</param>
        /// <param name="steps_count">Возвращаемое значение: число шагов, за которое был найден ответ</param>
        /// <returns></returns>
        public Vector <double> FindMinimum(Func <Vector <double>, double> f, Vector <double> x, AbstractGradientCalc gradient_calc, double eps, out int steps_count, Func <Vector <double>, double>[] borders)
        {
            ///!!!!!!!!!
            double interval_h = eps;                                            //Шаг для поиска интервала
            double min_eps    = eps;                                            //Точность для поиска минимума

            steps_count = 0;                                                    //Число шагов
            string format = Utils.GetFormat(eps);
            double norm;

            //Создаем единичную квазиньютновскую матрицу
            Matrix <double> H = Matrix <double> .Build.DenseIdentity(x.Count, x.Count);

            //Matrix<double> H_prev = null;

            Vector <double> p = Vector <double> .Build.Dense(x.Count);

            Vector <double> grad      = null;
            Vector <double> grad_prev = Vector <double> .Build.Dense(x.Count);

            Vector <double> x_prev = Vector <double> .Build.Dense(x.Count);

            //Вычисление градиента
            grad = gradient_calc.CalcGradient(f, x);

            while (((norm = Utils.CalcNorm(grad)) > eps) && (steps_count < 3000))
            {
                if (steps_count > 0)
                {
                    //Вспомогательные матрицы (Матрицы столбцы)
                    var s_v = (x - x_prev);
                    var s   = s_v.ToColumnMatrix();

                    var y_v = (grad - grad_prev);
                    var y   = y_v.ToColumnMatrix();

                    //Эти же транспонированные
                    var y_t = y.Transpose();
                    var s_t = s.Transpose();

                    //Пересчет квазиньютоновской матрицы
                    H = H - (H * y * y_t * H) / (y_t * H * y)[0, 0] + (s * s_t) / (y_t * s)[0, 0];
                }


                //Вычисление направления поиска
                p = -H * grad;
                //Определяем шаг поиска методом одномерной оптимизации
                Func <double, double> f_ = y => f(x + y * p);
                var interval             = IntervalFinder.Find(0, interval_h, f_);
                var a = GoldenRatioMethod.FindMinimum(interval, f_, min_eps);

                x.CopyTo(x_prev);
                x = x + a * p;

                //WTF
                //if (!Utils.CheckInD0(x, borders)) return x;

                //Вычисление градиента
                grad.CopyTo(grad_prev);
                grad = gradient_calc.CalcGradient(f, x);

                steps_count++;
            }

            return(x);
        }