К оглавлению

Минимизация функции n переменных

С.И.Хашин


dfunc.h - заголовочный файл
dfunc.cpp - реализация.

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


    ...

К оглавлению


free counters