С.И.Хашин
Сначала одна вспомогательная функция.
Пусть даны четыре вектора 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); ...