Текст подпрограммы и версий
mnb8r_c.zip  mnb8d_c.zip 
Тексты тестовых примеров
tmnb8r_c.zip  tmnb8d_c.zip 

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

Назначение

Решение задачи одномерной минимизации функции многих переменных по заданному направлению и на заданном интервале методом золотого сечения.

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

Для решения задачи

    min  φ (x0 + α s) ,   x0  En ,   s  En ,   α  R ,
     α 

используется метод золотого сечения. При этом предполагается, что задан отрезок [a, b] изменения параметра  α такой, что функция  φ (x), рассмотренная вдоль направления  s, принимает на [a, b] свое минимальное значение.

В.Г.Карманов, Математическое программирование, Изд - во "Hаука", M., 1975, стp.153 - 155.

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

    int mnb8r_c (integer *n, real *x, real *s, real *xx, S_fp fun,
            real *aa, real *bb, real *epsx, real *eps, integer *itmax,
            integer *maxk, real *fmin, real *xmin, integer *kount,
            integer *iter, integer *nacc, integer *ierr)

Параметры

n - размерность пространства переменных (тип: целый);
x - вещественный вектоp длины  n, задающий начальную точку  x0 поиска одномерного минимума;
s - вещественный вектоp длины  n, задающий направление поиска;
xx - вещественный вектоp длины  n, используемый в подпрограмме как рабочий;
fun - имя подпрограммы вычисления значения минимизиpуемой функции;
aa - нижняя граница интервала, содержащего точку минимума (тип: вещественный);
bb - верхняя граница интервала, содержащего точку минимума (тип: вещественный);
epsx - заданная точность вычисления точки минимума по аpгументу (тип: вещественный);
eps - заданная точность вычисления минимума по функционалу (тип: вещественный);
itmax - заданное максимально допустимое число итераций метода (тип: целый);
maxk - заданное максимально допустимое число вычислений функции (тип: целый);
fmin - вещественная переменная, на выходе из подпрограммы содержащая вычисленное максимальное значение функции;
xmin - вещественная переменная, на выходе из подпрограммы содержащая значение шага  α до точки минимума по направлению;
kount - целая переменная, на выходе из подпрограммы содержащая выполненное число вычислений функции;
iter - целая переменная, на выходе из подпрограммы содержащая выполненное число итераций;
nacc - целая переменная, задающая признак варианта алгоритма:
nacc=1 - на каждой итерации вычисляется только одна новая контрольная точка;
nacc=2 - для каждого нового интервала вычисляются обе контрольные точки (см. замечания по использованию);
ierr - целая переменная, служащая для сообщения об ошибках и причинах окончания поиска:
ierr= 1 - достигнута точность eps;
ierr= 2 - достигнута точность epsx;
ierr=65 - заданная точность epsx ≤ 0;
ierr=66 - заданные значения aa, bb, и epsx таковы, что либо bb ≤ aa, либо (bb - aa) < epsx;
ierr=67 - выполнено itmax итераций, но ни epsx, ни eps не достигнуты;
ierr=68 - выполнено maxk вычислений функции, но ни epsx, ни eps не достигнуты.

Версии

mnb8d_c - решение задачи одномерной минимизации функции многих переменных по заданному направлению и на заданном интервале методом золотого сечения, вычисления проводятся с двойной точностью.

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

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

 

В подпрограмме mnb8d_c и подпрограмме fun параметры x, s, xx, aa, bb, epsx, eps, fmin, xmin, f, fe должны иметь тип double. Тип остальных параметров не меняется.

 

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

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

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

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

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

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

На очередной итерации метода на интервале [ak, bk] фиксиpуются две контрольные точки  v1 и  v2, такие что  ak < v1 < v2 < bk.

При nacc = 1 в качестве одной из точек (v1  или  v2) используется точка, вычисленная на пpедыдущей итерации. При этом погрешность вычислений может накапливаться от итерации к итерации. При nacc = 2 на каждой итерации  v1 и  v2 вычисляются заново, однако число вычислений функции на каждой итерации удваивается.

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

    min  φ (x0 + α s) ,   x0 ,   s  E1 ,    x0 = 0.0 ,   s = 1.0
      α 
    φ (x)  =  100*e-x + x 
    Оптимальное значение   α*  =  - ln(0.01)
    φ (x0 + α* s)  =  1 - ln(0.01)

int main(void)
{
    /* Initialized data */
    static int n = 1;
    static float x[1] = { 0.f };
    static float s[1] = { 1.f };
    static float aa = 4.2f;
    static float bb = 4.8f;
    static float eps = 1e-16f;
    static float epsx = 1e-6f;
    static int itmax = 100;
    static int maxk = 100;

    /* Local variables */
    static int nacc;
    static float fmin;
    extern int func_c();
    static int iter;
    static float xmin;
    extern int mnb8r_c(int *, float *, float *, float *, U_fp, float *,
                       float *, float *, float *, int *, int *, float *,
                       float *, int *, int *, int *, int *);
    static int kount;
    static float xx[1];
    static int ier;

    nacc = 1;
    printf("\n %16.7e %16.7e \n", aa, bb);
    printf("\n %16.7e \n", eps);
    printf("\n %16.7e \n", epsx);
    printf("\n %5i \n", itmax);
    printf("\n %5i \n", maxk);
    mnb8r_c(&n, x, s, xx, (U_fp)func_c, &aa, &bb, &epsx, &eps, &itmax, &maxk,
            &fmin, &xmin, &kount, &iter, &nacc, &ier);

    printf("\n\n %5i \n", ier);
    printf("\n %5i \n", iter);
    printf("\n %16.7e %16.7e \n", fmin, xmin);
    printf("\n %5i \n", kount);
    return 0;
} /* main */

int func_c(float *x, float *f, float *fe)
{
    /* Builtin functions */
    double exp(double);

    /* Parameter adjustments */
    --x;

    /* Function Body */
    *f = (float)exp((float)(-x[1])) * 100.f + x[1];
    return 0;
} /* func_c */


Результаты:

      ier   =  1
      iter  =  14

      fmin  =  5.605170 + 00
      xmin  =  4.605681 + 00

      kount  =  15