public static Point2D FindMinimum(Func <double, double, double> f, Point2D b1, Point2D h, double eps0)
        {
            Point2D b2, xk, x;
            bool    flag;
            double  z = 0.1;
            double  f1, f2;

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

            do
            {
                do
                {
                    xk = b1;
                    //Исследуюший поиск
                    b2 = search(f, xk, h);
                    Logger.Write("1. xk = b1 = {0}", xk);
                    Logger.Write("2. Выполняем исследующий поиск вокруг точки xk: b2 = {0}", b2);


                    do
                    {
                        //Шаг по образцу
                        xk = new Point2D(b1.X + 2 * (b2.X - b1.X), b1.Y + 2 * (b2.Y - b1.Y));
                        Logger.Write("3. Выполняем шаг по образцу xk = b1 + 2(b2-b1) = {0}", xk);

                        //Исследующий поиск
                        x = search(f, xk, h);
                        Logger.Write("4. Выполняем исследующий поиск вокруг точки xk: x = {0}", x);
                        b1 = b2;
                        Logger.Write("5. b1 = b2 = {0}", b1);

                        f1 = f(x.X, x.Y);
                        f2 = f(b1.X, b1.Y);

                        Logger.Write("6. f(x) = {0};  f(b1) = {1}", f1, f2);
                        if (f1 < f2)
                        {
                            b2 = x;
                            Logger.WriteContinue("   f(x) < f(b1) => переход на шаг 3");
                        }
                    } while (f1 < f2);

                    flag = f(x.X, x.Y) > f(b1.X, b1.Y);
                    if (flag)
                    {
                        Logger.Write("f(x) > f(b1) => переход на шаг 1");
                    }
                } while (flag);

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

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

                Logger.Write("9. Уменьшаем шаг: h = {0} * h = {1}", z, h);
            } while (true);

            Logger.Write("||h|| = {0} <= eps => поиск завершен");
            Logger.WriteContinue("Минимум найден: b1 = {0}", b1);

            return(b1);
        }
Ejemplo 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);
        }