Esempio n. 1
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>
        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);
        }
Esempio n. 2
0
        /// <summary>
        /// Осуществляет оптимизацию многомерной функции методом Гаусса-Зейделя
        /// </summary>
        /// <param name="f">Минимизируемая функция</param>
        /// <param name="x0">начальной точки посика</param>
        /// <param name="interval">интервалы поиска</param>
        /// <param name="h">Векор положительных приращений координат</param>
        /// <param name="eps0">Точность</param>
        /// <returns></returns>
        public static Point2D FindMinimum(Func <double, double, double> f, Point2D x0, Point2D h, double eps0)
        {
            /*Стоило бы сделать поддержку функций многих переменных (N>2), но тут трудности в преобразовании
             * Func<double[], double> -> Func<double, double>*/

            double finder_h  = 0.05;                    //Шаг поиска отрезка минимума
            double z         = 0.1;                     //Уменьшение шага поиска
            double equal_eps = eps0;                    //Совпадение

            Point2D x = new Point2D(0, 0);
            Func <double, double> f_fixed;
            Interval interval;
            double   ak;

            Logger.Write("===> Минимизация методом Гаусса-Зейделя <==");
            Logger.WriteContinue(" |Начальная точка x0: {0}", x0);
            Logger.WriteContinue(" |Шаг h: {0} ", h);
            Logger.WriteContinue(" |Точность eps: {0} ", eps0);


            string format = OptimizationUtils.GetFormat(eps0 / 10);

            do
            {
                do
                {
                    x0.X = x.X;
                    x0.Y = x.Y;

                    Logger.Write("Минимазация по каждой координате");
                    //Поочередная минимизация по каждой координате
                    //X
                    Logger.WriteContinue("X:");
                    f_fixed  = a => f(x0.X + a * h.X, x0.Y);
                    interval = IntervalFinder.Find(x0.X, finder_h, f_fixed);
                    ak       = GoldenRatioMethod.FindMinimum(interval, f_fixed, eps0 / 5);
                    x.X      = x0.X + ak * h.X;
                    Logger.WriteContinue("  3. ak = {0:" + format + "}", ak);
                    Logger.WriteContinue("  4. x[k+1].X=x[k].X + ak*h.X = {0:" + format + "} + {1:" + format + "} * {2:" + format + "} = {3:" + format + "}", x0.X, ak, h.X, x.X);

                    //Y
                    Logger.WriteContinue("Y");
                    f_fixed  = a => f(x.X, x0.Y + a * h.Y);
                    interval = IntervalFinder.Find(x0.Y, finder_h, f_fixed);
                    ak       = GoldenRatioMethod.FindMinimum(interval, f_fixed, eps0 / 5);
                    x.Y      = x0.Y + ak * h.Y;
                    Logger.WriteContinue("  3. ak = {0:" + format + "}", ak);
                    Logger.WriteContinue("  4. x[k+1].Y=x[k].Y + ak*h.Y = {0:" + format + "} + {1:" + format + "} * {2:" + format + "} = {3:" + format + "}", x0.Y, ak, h.Y, x.Y);
                }while (!check_equal(x0, x, equal_eps));
                Logger.Write("x[k+1]==x[k]");
                var h0 = h;

                if (OptimizationUtils.EuclidNorm(h) <= eps0)
                {
                    break;
                }

                //Уменьшаем шаг
                h.X = z * h.X;
                h.Y = z * h.Y;

                Logger.WriteContinue("9. Уменьшаем шаг: h = {0:" + format + "} * {1:" + format + "} = {2:" + format + "}", z, h0, h);
                Logger.WriteContinue("Переход на шаг 3");
            } while (true);

            Logger.Write("||h|| = {0:" + format + "} < eps", OptimizationUtils.EuclidNorm(h));
            Logger.Write("Минимум найден: {0:" + format + "}", x);

            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);
        }
Esempio n. 4
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>
        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);
        }