Текст подпрограммы и версий 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) .