예제 #1
0
        /// <summary>
        /// Минимизирует функцию методом барьерных функций
        /// </summary>
        /// <param name="f">Минимизируемая функция</param>
        /// <param name="borders">Массиф функци ограничений</param>
        /// <param name="barrier_func">Функция барьера</param>
        /// <param name="x0">Начальная точка</param>
        /// <param name="r0">Начальное значение штрафа</param>
        /// <param name="z">Коэффициент уменьшения штрафа</param>
        /// <param name="eps">Точность</param>
        /// <returns></returns>
        public static Vector <double> FindMinimum(Func <Vector <double>, double> f, Func <Vector <double>, double>[] borders, Func <double, double> barrier_func, Vector <double> x0, double r0, double z, double eps)
        {
            /*
             *      ВОПРОСЫ
             *      1) Какой выбрать шаг
             *      2) Действительно ли F не зависит от rk
             *      3) Какую давать точность
             *      4) Проверка??!!
             */

            int             k;                  //Номер шага
            double          rk;                 //Штарф
            double          B;                  //WTF
            Vector <double> min_x;              //Миниум ф-ии F

            var gradient_method = new DFPMethod();
            var gradient_calc   = new CentralGradientCalc(0.0001);                      //!!! (1)
            int steps;

            //1.
            k  = 0;
            rk = r0;

            do
            {
                //2.
                //Это sum(phi_i(f_i(x)));
                Func <Vector <double>, double> sum_f = x =>
                {
                    double sum = 0;
                    foreach (var b in borders)
                    {
                        sum += barrier_func(b(x));
                    }
                    return(sum);
                };

                //Это вспомогательная функция F(x,rk)
                //Func<Vector<double>, double, double> F = (x, rk) => f(x) + rk * sum_f(x);
                //Преобразуем вспомогательную функцию вида F(x,rk) к F'(x'), где x' = (x, rk)=(x1,...,xn,rk)
                //Func<Vector<double>, double> F_ = v => F(decrease_dimension(v), v[v.Count - 1]);

                //!!! (2)
                Func <Vector <double>, double> F = x => f(x) + rk * sum_f(x);

                //3.
                //!!! (3)
                //Минимизируем
                //!!! (4)
                min_x = gradient_method.FindMinimum(F, x0, gradient_calc, eps / 10, out steps, borders);
                bool is_in = Utils.CheckInD0(min_x, borders);

                //4.
                //Вычисляем какую-то хрень
                B = rk * sum_f(min_x);

                if (Math.Abs(B) >= eps)
                {
                    rk = z * rk;
                    x0 = min_x;
                    k++;
                }
            } while (Math.Abs(B) >= eps);

            return(min_x);
        }
예제 #2
0
        private void btnCalc_Click(object sender, EventArgs e)
        {
            txtLog.Text = "";


            Vector <double> x0;
            double          eps = 0, h = 0.1;
            Vector <double> res;
            int             steps;

            //Парсинг параметров
            try
            {
                var strings = txtX.Text.Split(';');
                x0 = Vector <double> .Build.Dense(strings.Length);

                for (int i = 0; i < strings.Length; i++)
                {
                    x0[i] = Double.Parse(strings[i]);
                }

                eps = double.Parse(txtEps.Text);
                h   = double.Parse(txtH.Text);
            }
            catch (FormatException exp)
            {
                MessageBox.Show("Неверный ввод - не число");
                return;
            }

            //Определяем функцию
            Func <Vector <double>, double> f;

            if (rbTest.Checked)
            {
                f = test;
                if (x0.Count != 2)
                {
                    MessageBox.Show("Неверное число координат в начальной точке");
                    return;
                }
            }
            else
            {
                f = task213;
                if (x0.Count != 4)
                {
                    MessageBox.Show("Неверное число координат в начальной точке");
                    return;
                }
            }

            //Определение разностной схемы
            AbstractGradientCalc calc;

            if (rbCenter.Checked)
            {
                calc = new CentralGradientCalc(h);
            }
            else
            {
                calc = new RightGradientCalc(h);
            }

            //Вычисление
            if (rbGZ.Checked)
            {
                res = (new OptimalGradientMethod()).FindMinimum(f, x0, new CentralGradientCalc(0.01), 0.01, out steps);
            }
            else
            {
                res = (new DFPMethod()).FindMinimum(f, x0, new CentralGradientCalc(0.01), 0.01, out steps);
            }

            txtOut.Text  = res.Vector2String(Utils.GetFormat(eps));
            txtIter.Text = steps.ToString();
        }