/// <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); }
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(); }