Текст подпрограммы и версий
mnr5r_c.zip
Тексты тестовых примеров
tmnr5r_c.zip

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

Назначение

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

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

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

       min  f(x) ,    xQ ,
        x
где     Q = { x:  A1*x = B1 ,   A ≤ x ≤ B } ,
       x, A, B - векторы из  En ,
             B1 - вектор из  Em ,
             A1 - вещественная матрица  m * n . 

Используется модификация метода условного градиета. В процессе счета каждое новое приближение определяется по формуле:

     xk+1  =  xk + αk(yk - xk) , 

где    yk - минимум линейной функции  < f ' (xk), x - xk > при  x  Q;
   f ' (xk) - градиент функции  f точке  xk;
        αk - величина шага по направлению спуска  pk = yk - xk.

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

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

    int mnr5r_c (integer *n, integer *m, real *x, real *xe,
            integer *i0, real *a, real *b, real *b1, integer *la, real *a1, 
            integer *ns, real *t, S_fp func, real *f, real *fe, S_fp grad,
            real *g, real *ge, real *up, real *rm, integer *irm, shortint *irm1,
            integer *ierr)

Параметры

n - размерность пространства переменных (тип: целый);
m - целая переменная, значение которой полагается равным  m + 2, где  m - число стpок в матрице линейных ограничений;
x - вещественный вектоp длины  n; на входе содержит начальное приближение; на выходе содержит компоненты вектоpа  x, отвечающего наименьшему найденному значению  f (x);
xe - вещественный вектоp длины  n заданных значений абсолютной точности по аргументу (см. замечания по использованию);
i0 - целый вектоp длины  n, с помощью которого можно фиксировать на время минимизации компоненты вектоpа  x: если  i0 (j) = 0, то  j - ая компонента вектоpа  x остается равной своему начальному значению, в противном случае следует положить  i0 (j) = 1;
a - вещественный вектоp длины  n, задающий ограничения снизу на переменные;
b - вещественный вектоp длины  n, задающий ограничения свеpху на переменные;
b1 - вещественный вектоp длины  m, задающий правые части системы линейных ограничений;
la - число ненулевых элементов в матрице условий (тип: целый);
a1 - вещественный вектоp длины  la, содержащий ненулевые элементы матрицы условий (см. замечания по использованию);
ns - целый вектоp длины  la, содержащий номера строк ненулевых элементов матрицы условий;
t - вещественный вектоp длины  n, содержащий заданное количество ненулевых элементов в матрице условий по столбцам: число  t (j) pавно количеству ненулевых элементов в  j - ом столбце матрицы;
func - имя подпрограммы вычисления значения функции  f (x) (см. замечания по использованию);
f - вещественная переменная, равная наименьшему найденному значению функции;
fe - заданная абсолютная погрешность вычисления функции (тип: вещественный);
grad - имя подпрограммы, вычисляющей градиент функции  f (x) (см. замечания по использованию);
g - вещественный вектоp длины  n, содержащий компоненты градиента;
ge - вещественный вектоp длины  n, задающий значения абсолютной точности по компонентам градиента;
up - вещественный вектоp длины 4 заданных управляющих параметров:
up(1) - заданное максимально допустимое время счета в секундах;
up(2) - заданная константа управления точностью по  x,  10 > up (2) > 1 (см. замечания по использованию);
up(3) - заданная константа управления точностью функции, 10 > up (3) > 1 (см. замечания по использованию);
up(4) - заданная относительная погрешность невязки  r  (r = a1 * x - b1) (см. замечания по использованию);
rm - вещественный вектоp длины 10 + 8n + m + m * m;
при обращении к подпрограмме:
rm(1) - заданное максимально допустимое число итераций;
  при выходе из подпрограммы:
rm(1) - выполненное число итераций;
rm(2) - выполненное число вычислений функции;
rm(3) - выполненное число вычислений градиента;
  остальные компоненты вектоpа rm используются как рабочие;
irm - целый вектоp длины 2n+5+[n/16], используемый как рабочий;
irm1 - целый вектоp длины 2n , используемый как рабочий;
ierr - целая переменная, указывающая причину окончания счета, при этом:
ierr= 1 - шаг по аргументу стал меньше заданной точности по аргументу;
ierr= 2 - изменение функции стало меньше заданной точности fe;
ierr= 4 - выполнено заданное число итераций;
ierr= 5 - истекло время, заданное для решения задачи.
ierr=65 - множество  Q пусто.
  Если выполнено одновременно несколько критериев окончания счета, то ierr = (ierr1) + (ierr2) * 10 + (ierr3) * 102 и т.д. Например, ierr = 24 означает, что ierr1 = 2,  ierr2 = 4.

Версии: нет

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

  mnk3r_c, ml03r_c.

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

1. 

Вектоp xe - заданный положительный вектоp; точностью по аргументу называется абсолютная величина проекции этого вектоpа на направление сдвига.

2. 

B массиве a1 задаются ненулевые элементы матрицы условий (по столбцам). Каждый элемент a1 содержит очередной ненулевой элемент  ai j. В массиве ns задаются номера строк ненулевых элементов, т.е. если  ai j ≠ 0 и  a1 (k) = ai j , то ns (k) = 1.

3. 

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

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

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

Параметр fe не должен переопределяться в теле подпрограммы func и может не использоваться при вычислении  f (x). Если время вычисления  f (x) зависит от требуемой точности, то следует вычислять  f (x) с точностью не большей, чем fe.

4. 

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

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

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

Константы up (2) и  up (3) используются для ускорения вычислений путем снижения точности вычислений в начале процесса минимизации, а именно, счет начинается при xe0 (i) = xe (i)  (up (2))5 и  fe0 = fe * (up (3))5, постепенно точность повышается и, если не срабатывают другие критерии окончания счета, то конечная точность вычислений совпадает с требуемой.

Kонстанта up (4) используется при решении вспомогательной задачи линейного программирования, а именно, абсолютная невязка считается допустимой, если она меньше  || B1 || * up (4).

6.  Используются служебные подпрограммы: mnr1s_c, mnr1n_c, mnr51_c, mnr52_c, mnr53_c, mnr54_c, mnr55_c, mnr56_c, ml07r_c, mlu43_c.

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

     min  f(x)  =  4x12 + 3x22

                  x1 + 3x2 - x3  =  5
             0.5x1 + 2x2 - x4  =  2

             10-6 ≤ x1 ≤ 5
             10-6 ≤ x2 ≤ 5
             10-6 ≤ x3 ≤ 5
             10-6 ≤ x4 ≤ 5

int main(void)
{
    /* Initialized data */
    static int io[4] = { 1,1,1,1 };
    static float up[4] = { 100.f,3.f,2.f,1e-12f };
    static float a1[6] = { 1.f,.5f,3.f,2.f,-1.f,-1.f };
    static int ns[6] = { 1,2,1,2,1,2 };
    static float x[4] = { 5.f,.1f,1.f,1.f };
    static float ge[4] = { 1e-6f,1e-6f,1e-6f,1e-6f };
    static float xe[4] = { 1e-11f,1e-11f,1e-11f,1e-11f };
    static float a[4] = { 1e-6f,1e-6f,1e-6f,1e-6f };
    static float b[4] = { 5.f,5.f,5.f,5.f };
    static float b1[4] = { 5.f,2.f,0.f,0.f };
    static float t[4] = { 2.f,2.f,1.f,1.f };
    static float fe = 1e-7f;

    /* Local variables */
    extern int grad_c(), func_c();
    static int ierr;
    extern int mnr5r_c(int *, int *, float *, float *, int *, float *,
                       float *, float *, int *, float *, int *, float *,
                       U_fp, float *, float *, U_fp, float *, float *,
                       float *, float *, int *, shortint *, int *);
    static float f, g[4];
    static int m, n, la;
    static float rm[58];
    static int irm[16];
    static shortint irm1[8];

    la = 6;
    m = 4;
    n = 4;
    rm[0] = 20.f;
    mnr5r_c(&n, &m, x, xe, io, a, b, b1, &la, a1, ns, t, (U_fp)func_c, &f,
            &fe, (U_fp)grad_c, g, ge, up, rm, irm, irm1, &ierr);

    printf("\n %5i \n", ierr);
    printf("\n %12.3e %12.3e \n", rm[1], rm[2]);
    printf("\n %12.3e \n", f);
    printf("\n %12.4e %12.4e %12.4e %12.4e \n", x[0], x[1], x[2], x[3]);
    printf("\n %12.3e \n", rm[0]);
    return 0;
} /* main */

int func_c(float *x, float *f, float *fe)
{
    /* Parameter adjustments */
    --x;

    /* Function Body */
    *f = x[1] * 4 * x[1] + x[2] * 3 * x[2];
    return 0;
} /* func_c */

int grad_c(float *x, float *g, float *ge, int *io)
{
    static int i__;

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

    /* Function Body */
    for (i__ = 1; i__ <= 4; ++i__) {
/* l3: */
        g[i__] = 0.f;
    }
    if (io[1] == 0) {
        goto l1;
    }
    g[1] = x[1] * 8;
l1:
    if (io[2] == 0) {
        goto l2;
    }
    g[2] = x[2] * 6;
l2:
    return 0;
} /* grad_c */


Результаты:

      ierr = 2 ;  кoличecтвo итepaций  = 7 ;
      nf (кoличecтвo вычиcлeний фyнкции)  = 8 ;
      ng (кoличecтвo вычиcлeний гpaдиeнтa)  = 22 ;
      f  =  7.692 ;
      x  =  (0.3846,  1.538,  10-6,  1.269) .