Текст подпрограммы и версий
mna6r_c.zip , mna6d_c.zip
Тексты тестовых примеров
tmna6r_c.zip , tmna6d_c.zip

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

Назначение

Поиск локального минимума функции многих переменных методом Пауэлла.

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

Пусть задана функция  N переменных F (x1, x2, ..., xN) и пусть известны координаты начальной точки X = (x*1, x*2, ..., x*N) поиска локального минимума (N ≤ 50).

Подпрограмма mna6r_c выполняет итерационный процесс, состоящий в проведении последовательных одномерных поисков минимумов, начиная с точки  X, вдоль системы определяемых в самой подпрограмме сопряженных направлений. В качестве начальных направлений поиска выбираются направления координатных осей в пространстве En.

Итерационный процесс продолжаетася до тех пор, пока модуль разности между значениями функции  F в точках приближения к минимуму на двух последних итерациях не станет меньше EPS.

Предполагается, что составляемая пользователем подпрограмма - функция вычисления  F в текущей точке XTEC всегда имеет имя FUNC и оформляется с двумя формальными параметрами:

XTEC - вещественный вектор длины  N, содержащий координаты точки, в которой вычисляется значение функции  F;

N - количество переменных (тип: целый).

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

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

    int mna6r_c (integer *n, real *x, real *y, real *p, real *eps,
            integer *iflag, integer *itmax)

Параметры

n - количество переменных; n ≤ 50 (тип: целый);
x - вещественный вектор длины  n, содержащий на входе координаты начальной точки поиска локального минимума, а на выходе - координаты этого минимума;
y - вещественная переменная, содержащая на выходе значение функции  F в полученной точке минимума;
p - вещественный двумерный массив размеров n на n, используемый в подпрограмме в качестве рабочего;
eps - заданное допустимое отклонение между значениями функции  F на двух последовательных итерациях (тип: вещественный);
iflag - целая переменная, служащая для сообщения о том, удалось ли найти локальный минимум за itmax итераций; при этом:
iflag=0 - когда минимум функции  F не найден; тогда вектор  x содержит приближение к минимуму на последней итерации, а y - значение  F в этой точке;
iflag=1 - когда точка минимум найдена;
itmax - заданное максимальное число итераций (тип: целый).

Версии

mna6d_c - поиск локального минимума функции многих переменных методом Пауэлла в режиме удвоенной точности; при этом параметры x, y, p и eps должны иметь тип double, а подпрограмма - функция FUNC должна быть описана как double.

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

mna1r_c -
mna1d_c  
локализация минимума функции одной переменной в режимах одинарной и удвоенной точности; используются в подпрограммах mna6r_c и mna6d_c соответственно;
mna3r_c -
mna3d_c  
поиск локального минимума функции одной переменной методом Брента (методом обратной параболической интерполяции) в режимах одинарной и удвоенной точности; используются в подпрограммах mna6r_c и mna6d_c соответственно.

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

 

В подпрограммах mna6r_c и mna6d_c имеется внешняя структура с именем mna6rr_ , содержащая элемент целого типа с именем iter. Переменная iter полагается равной количеству итераций, выполненных при поиске минимума функции. Если iflag = 0, то iter = itmax. В этом случае следует либо увеличить itmax, либо увеличить eps.

В качестве рабочих используются подпрограммы mna6r1_c (mna6d1_c) и mna6r2_c (mna6d2_c), в которых имеется внешняя структура с именем mna6rc_ .

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

struct {
    int ntest;
} _BLNK__;

#define _BLNK__1 _BLNK__

struct {
    int iter;
} mna6rr_;

#define mna6rr_1 mna6rr_

int main(void)
{
    /* Local variables */
    extern int mna6r_c(int *, float *, float *, float *, float *, int *,
                       int *);
    static int n, iflag;
    static float y;
    static int itmax;
    static float p1[4] /* was [2][2] */,
                 p2[4] /* was [2][2] */, x1[2], x2[2], eps;

    _BLNK__1.ntest = 1;
    n = 2;
    x1[0] = 8.f;
    x1[1] = 9.f;
    eps = 1e-6f;
    itmax = 500;
    mna6r_c(&n, x1, &y, p1, &eps, &iflag, &itmax);

    printf("\n %16.7e %16.7e \n", x1[0], x1[1]);
    printf("\n %16.7e \n", y);
    printf("\n %5i \n", iflag);
    printf("\n %5i \n", mna6rr_1.iter);
    _BLNK__1.ntest = 2;
    x2[0] = 1.2f;
    x2[1] = 1.f;
    mna6r_c(&n, x2, &y, p2, &eps, &iflag, &itmax);

    printf("\n %16.7e %16.7e \n", x2[0], x2[1]);
    printf("\n %16.7e \n", y);
    printf("\n %5i \n", iflag);
    printf("\n %5i \n", mna6rr_1.iter);
    return 0;
} /* main */

float func_c(float *x, int *n)
{
    /* System generated locals */
    float ret_val, r__1, r__2, r__3;

    /* Parameter adjustments */
    --x;

    /* Function Body */
    if (_BLNK__1.ntest != 1) {
        goto l1;
    }
/* Computing 2nd power */
    r__1 = x[1] - .5f;
/* Computing 2nd power */
    r__2 = x[2] - 6.f;
    ret_val = r__1 * r__1 * 4.f + r__2 * r__2;
    return ret_val;
l1:
/* Computing 2nd power */
    r__2 = x[1];
/* Computing 2nd power */
    r__1 = x[2] - r__2 * r__2;
/* Computing 2nd power */
    r__3 = 1.f - x[1];
    ret_val = r__1 * r__1 * 100.f + r__3 * r__3;
    return ret_val;
} /* func_c */


Результаты: 

      x1(1) = 0.5 ;            x1(2) = 6.0 ;   y = 0.0 
      iflag = 1 ;             mna6rr_1.iter = 3 

      x2(1) = 1.00001 ;     x2(2) = 1.0 ;   y = 0.295415e - 7 
      iflag = 1 ;              mna6rr_1.iter = 2