С.И.Хашин
Сначала одна вспомогательная функция.
Пусть даны четыре вектора min, v, max, g одной и той же длины.
Считаем, что min[i] <= v[i] <= max[i].
Найти наибольшее alpha такое, что
min[i] <= v[i] + alpha*g[i] <= max[i]:
double maxAlpha(dvect &v, dvect &min, dvect &max, dvect &g);
Теперь определяем класс MathFunc:
class MathFunc
{
public:
virtual double operator () (dvect &) = 0;
virtual int N() = 0;
int counter; // рекомендуется при каждом вызове функции увеличивать на 1.
...
}
Важнейшие методы:
// минимизация // v - вектор с начальным приближением, в нем же возвращается ответ // min, max - минимальное и максимальное значение каждой координаты // epsX - минимальное смещение аргумента за шаг // epsF - минимальное улучшение минимума за шаг // // минимизация методом градиентов double minGrad(dvect &v, dvect &min, dvect &max, double epsX, double epsF); // минимизация координатным спуском double minCoord(dvect &v, dvect &min, dvect &max, double epsX, double epsF);
Пример использования:
// Описание класса с минимизируемой фунцкцией:
class f02 : public MathFunc {
public:
double operator () (dvect &v) {
if (v.size() != 2) vError("f02: size != 2");
double x = v[0], y = v[1];
return dSquare(2 * x - 3 * y + 2+ x*y - 7*x*x*y)
+ dSquare(5*y*y*x- 3 * x - 1 * y + 1 + x*y)
+ dSquare(1 * x - 1 * y - 1 - 2*x*y);
}
int N() { return 2; }
};
//-------------------------------------------------------------------------
f02 f;
int n = f.N();
dvect mi(n), v(n), ma(n);
mi.set(-3); // наименьшее значение -3 по всем координатам
ma.set(3); // наибольшее значение +3 по всем координатам
double epsX = 0.001, epsY = 1e-6; // погрешности по x и по y
v.set(1); // начальное приближение
f.counter = 0; // обнулим счётчик вызовов функции
double f2 = f.minGrad(v, mi, ma, epsX, epsY);// поиск минимума методом градиентов
int c2 = f.counter; // количество вызовов функции
v.set(1); // начальное приближение
f.counter = 0; // обнулим счётчик вызовов функции
double f3 = f.minCoord(v, mi, ma, epsX, epsY);// поиск минимума координатным методом
int c3 = f.counter; // количество вызовов функции
printf("c2=%4d, min = %10.5f\n", c2, f2);
printf("c3=%4d, min = %10.5f\n", c3, f3);
...