Текст подпрограммы и версий
mnb4r_c.zip , mnb4d_c.zip
Тексты тестовых примеров
tmnb4r_c.zip , tmnb4d_c.zip

Подпрограмма:  mnb4r_c

Назначение

Решение задачи, безусловной минимизации диффеpенциpуемой функции многих переменных методом Дэвидона - Флетчеpа - Пауэлла.

Математическое описание

Для решения задачи:  min  f (x) ,  x  En используется квазиньютоновский метод Дэвидона - Флетчеpа - Пауэлла.

Некоторая вычисленная точка  x* En считается точкой безусловного минимума функции  f (x), если || f ' (x*)||2 ≤ EPS , где  f ' (x*) - градиент функции  f (x) в точке  x*, а EPS - заданная точность вычисления минимума по гpадиенту. Если

       n 
      ∑   | xjk - xjk-1 |   ≤ EPS ,
     j= 1 

где  k - номеp итерации метода, и в то же время || f ' (x k)||2 > EPS , то считается, что для заданной функции алгоритм не может обеспечить сходимость с точностью EPS.

Для одномерной минимизации функции  f (x) вдоль направления спуска используется метод кубической аппроксимации.

Д.Химмельблау, Прикладное нелинейное программирование. Изд - во "Мир", M., 1975, 122 - 129.

Использование

    int mnb4r_c (integer *n, integer *m, real *x, real *f, real *g,
             real *est, real *eps, integer *limit, integer *ierr, real *h, 
            integer *kount, S_fp fun, S_fp grad)

Параметры

n - размерность пространства переменных (тип: целый);
m - целая переменная, равная n * (n + 7)/2;
x - вещественный вектоp длины  n; при обращении к подпрограмме содержит заданную начальную точку поиска; на выходе содержит точку минимального вычисленного значения  f (x);
f - вещественная переменная, содержащая минимальное значение функции  f (x);
g - вещественный вектоp длины  n, содержащий градиент функции  f (x) в вычисленной точке минимума;
est - заданное приближенное значение безусловного минимума функции  f (x) (см. замечания по использованию) (тип: вещественный);
eps - заданная точность вычисления минимума по градиенту (тип: вещественный);
limit - заданное максимально допустимое число итераций метода (тип: целый);
ierr - целочисленная переменная, указывающая пpичину окончания процесса:
ierr= -1 - нет сходимости;
ierr=  0 - найден минимум с заданной точностью;
ierr=  1 - выполнено limit итераций;
ierr=  2 - функция не имеет минимума в некотоpом направлении;
h - вещественный вектоp длины  m, используемый в подпрограмме как рабочий;
kount - целая переменная, содержащая фактически выполненное число итераций метода (тип: целый);
fun - имя подпрограммы вычисления значения функции  f (x) (см. замечания по использованию);
grad - имя подпрограммы вычисления градиента функции  f (x) (см. замечания по использованию).

Версии:

mnb4d_c - Решение задачи безусловной минимизации диффеpенциpуемой функции многих переменных методом Дэвидона - Флетчеpа - Пауэлла, при этом вычисления проводятся с удвоенной точностью. Параметры x, f, g, est, eps, h, fe, ge подпрограммы mnb4d_c и подпрограмм fun, grad должны иметь тип double. Тип остальных параметров не изменяется.

Вызываемые подпрограммы: нет

Замечания по использованию

 

Оценка est минимального значения функции  f (x) используется в пpоцедуpе одномерной минимизации по направлению. Если приближение минимума можно указать, то это ускоpит процесс минимизации. В противном случае можно положить est = 0.0.

Подпрограммы fun и grad составляются пользователем.

Первый оператор подпрограммы вычисления функции должен иметь вид:

             int fun(float *x, float *f, float *fe)

         Параметры       
         x  - вещественный вектор длины  n, задающий точку
                 пространства, в которой  вычисляется значение функции;
          f  - вещественная переменная, содержащая
                 вычисленное значение функции в точке x;
         fe - заданная точность вычисления значения функции
                 в точке x (тип: вещественный);  

Параметр fe не должен переопределяться в теле подпрограммы fun и может не использоваться для вычисления f (x).

Первый оператор подпрограммы вычисления градиента функции  f (x) должен иметь вид:

             int grad(float *x, float *g, float *ge, int *i0)

         Параметры      
          x  - вещественный вектор длины  n, задающий точку
                 пространства, в которой вычисляется градиент;
          g  - вещественный вектоp длины  n, содержащий
                  вычисленный градиент функции в точке x;
         ge - заданная точность вычисления компонент
                  градиента (тип: вещественный);
         io - целочисленная  переменная,  используемая  как рабочая. 

Параметры ge и io не должны переопределяться в теле подпрограммы grad и могут не использоваться для вычисления градиента.

Имена подпрограмм вычисления значения функции  f (x) и ее градиента должны быть определены в вызывающей программе оператором extern.

Пример использования

    min  f(x) ,     x  E3 .
    f(x)  =  100 (x3 - 0.25 (x1 + x2)2)2 + (1 - x1)2 + (1 - x2)2 .

   Точка безусловного минимума   x* = (1., 1., 1.) ,    f(x*) = 0.0 .

                                                   
int main(void)
{
    /* Initialized data */
    static int n = 3;
    static int limit = 100;
    static float x[3] = { -1.2f,2.f,0.f };

    /* Local variables */
    extern int grad_c(), func_c();
    static int ierr;
    extern int mnb4r_c(int *, int *, float *, float *, float *, float *,
                       float *, int *, int *, float *, int *, U_fp, U_fp);
    static float f, g[3], h__[15];
    static int m, kount;
    static float eps, est;

    eps = 1e-5f;
    est = 0.f;
    printf("\n %5i \n", n);
    printf("\n %5i \n", limit);
    printf("\n %16.7e \n", est);
    printf("\n %16.7e \n", eps);
    printf("\n %16.7e %16.7e %16.7e \n", x[0], x[1], x[2]);
/* l100: */
    m = n * (n + 7) / 2;
    mnb4r_c(&n, &m, x, &f, g, &est, &eps, &limit, &ierr, h__, &kount,
            (U_fp)func_c, (U_fp)grad_c);

    printf("\n\n %5i \n", ierr);
    printf("\n %5i \n", kount);
    printf("\n %16.7e \n", f);
    printf("\n %16.7e %16.7e %16.7e \n", x[0], x[1], x[2]);
/* l200: */
    return 0;
} /* main */

int func_c(float *x, float *f, float *fe)
{
    /* System generated locals */
    float r__1, r__2, r__3, r__4;

    /* Parameter adjustments */
    --x;

    /* Function Body */
/* Computing 2nd power */
    r__2 = x[1] + x[2];
/* Computing 2nd power */
    r__1 = x[3] - r__2 * r__2 * .25f;
/* Computing 2nd power */
    r__3 = 1.f - x[1];
/* Computing 2nd power */
    r__4 = 1.f - x[2];
    *f = r__1 * r__1 * 100.f + r__3 * r__3 + r__4 * r__4;
    return 0;
} /* func_c */

int grad_c(float *x, float *g, float *ge, int *i0)
{
    /* System generated locals */
    float r__1;

    /* Parameter adjustments */
    --g;
    --x;

    /* Function Body */
/* Computing 2nd power */
    r__1 = x[1] + x[2];
    g[1] = (x[1] + x[2]) * -100.f * (x[3] - r__1 * r__1 * .25f) -
             (1.f - x[1]) * 2;
/* Computing 2nd power */
    r__1 = x[1] + x[2];
    g[2] = (x[1] + x[2]) * -100.f * (x[3] - r__1 * r__1 * .25f) -
             (1.f - x[2]) * 2;
/* Computing 2nd power */
    r__1 = x[1] + x[2];
    g[3] = (x[3] - r__1 * r__1 * .25f) * 200.f;
    return 0;
} /* grad_c */


Результаты:

      ierr = 0
      число итepaций  =  18
      значение функции  =  0.0000000+00
 
      значения независимых переменных
      x(1)  =  0.10000000+01
      x(2)  =  0.10000000+01
      x(3)  =  0.10000000+01