алгоритм наискорейшего спуска
Код:
//---------------------------------------------------------------------------
#include <conio>
#include <vcl.h>
#include <math.h>
#include <iostream>
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
using namespace std;
cout << "f(x)=(x1-2)^4+(x1-2x2)^2" << endl;
double x11 = 0.5;
double x12 = 1;
cout << "x1=[" << x11 << ";" << x12 << "]" << endl;
double a = 4*pow(x11-2,3)-2*(x11-2*x12);
double b = 4*(x11-2*x12);
double f = pow(x11-2,4)+pow(x11-2*x12,2);
double df = sqrt(pow(a,2) + pow(b,2));
double x21, x22, lym, lym_buf;
bool fnd = false;
double lim = 0.0001;
cout << endl;
while (true) {
lym = 0.1;
lym_buf = lym;
while (lym>lim) {
x21 = x11 - lym*(a/df);
x22 = x12 - lym*(b/df);
double f2 = pow(x21-2,4)+pow(x21-2*x22,2);
cout << lym << " - " << f << " - " << f2 << " df: " << df << endl;
if (f2>=f) lym /= 4;
else {
lym_buf = lym;
lym *= 2;
fnd = true;
f = f2;
}
}
cout << endl;
if (fnd) {
fnd = false;
lym = lym_buf;
x11 = x11 - lym*(a/df);
x12 = x12 - lym*(b/df);
f = pow(x11-2,4)+pow(x11-2*x12,2);
a = 4*pow(x11-2,3)-2*(x11-2*x12);
b = 4*(x11-2*x12);
df = sqrt(pow(a,2) + pow(b,2));
}
else break;
}
cout << endl << "Min:" << x11 << "," << x12 << " - " << pow(x11-2,4)+pow(x11-2*x12,2) << " - lym_buf: " << lym_buf<< endl;
getch();
return 0;
}
//---------------------------------------------------------------------------
#include <conio>
#include <vcl.h>
#include <math.h>
#include <iostream>
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
using namespace std;
cout << "f(x)=(x1-2)^4+(x1-2x2)^2" << endl;
double x11 = 0.5;
double x12 = 1;
cout << "x1=[" << x11 << ";" << x12 << "]" << endl;
double a = 4*pow(x11-2,3)-2*(x11-2*x12);
double b = 4*(x11-2*x12);
double f = pow(x11-2,4)+pow(x11-2*x12,2);
double df = sqrt(pow(a,2) + pow(b,2));
double x21, x22, lym, lym_buf;
bool fnd = false;
double lim = 0.0001;
cout << endl;
while (true) {
lym = 0.1;
lym_buf = lym;
while (lym>lim) {
x21 = x11 - lym*(a/df);
x22 = x12 - lym*(b/df);
double f2 = pow(x21-2,4)+pow(x21-2*x22,2);
cout << lym << " - " << f << " - " << f2 << " df: " << df << endl;
if (f2>=f) lym /= 4;
else {
lym_buf = lym;
lym *= 2;
fnd = true;
f = f2;
}
}
cout << endl;
if (fnd) {
fnd = false;
lym = lym_buf;
x11 = x11 - lym*(a/df);
x12 = x12 - lym*(b/df);
f = pow(x11-2,4)+pow(x11-2*x12,2);
a = 4*pow(x11-2,3)-2*(x11-2*x12);
b = 4*(x11-2*x12);
df = sqrt(pow(a,2) + pow(b,2));
}
else break;
}
cout << endl << "Min:" << x11 << "," << x12 << " - " << pow(x11-2,4)+pow(x11-2*x12,2) << " - lym_buf: " << lym_buf<< endl;
getch();
return 0;
}
//---------------------------------------------------------------------------
Ваша функция как раз такая.
Цитата:
Originally posted by sq_deep
Тут нет ничего странного. У функции может быть несколько локальных экстремумов, вот вы и спускаетесь то к одному, то к другому в зависимости от начальных условий.
Ваша функция как раз такая.
Тут нет ничего странного. У функции может быть несколько локальных экстремумов, вот вы и спускаетесь то к одному, то к другому в зависимости от начальных условий.
Ваша функция как раз такая.
У этой функции ровно один экстремум (глобальный минимум x1 = 2, x2 = 1). Других экстремумов у нее нет (даже локальных).
В реализации метода я не разбирался (лень). Но возможную ошибку нашел сразу же. Если переменные a и b являются частными производными по x1 и x2, то тогда b = -4*(x1-2*x2), а не 4*(x1-2*x2) (Вы забыли минус).