|
Текст подпрограммы и версий mnr5r_c.zip |
Тексты тестовых примеров tmnr5r_c.zip |
Решение задачи минимизации дифференцируемой функции многих переменных при наличии линейных ограничений методом условного градиента.
Для решения задачи:
min f(x) , x∈Q ,
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) .