Метод Дэвидона.
Этот метод является аналогом метода кубической аппроксимации в задачах поиска минимума функции нескольких переменных по заданному направлению. Идея метода заключается в том, чтобы на ТИЛ найти аппроксимирующий минимум строя полином 3-го порядка.
Начальный этап:
-
Взять ε, х 0 – начальную точку поиска, p – направление поиска.
-
Найти начальный шаг α1 = min{ η,|(y1-y’)/y’1|}, где η=1,2. y1=y(x1), y’1 =y’(x1,p)
-
Получить начальный интервал поиска [a,b] методом Свенна 4.
Основной этап:
-
Найти аппроксимирующий минимум, т.е. точку r по формулам:
r = a+αr *p
αr = α a +γ*( α b - αa )
γ=(z-f’a+W)/(f’b-f’a+2*W)
W=√z2-f’a*f’b
z=f’a+f’b+3*(fa-fb)/(b-a)
-
Проверить КОП если Y’r<=ε, то остановиться.X= a+ αr *p Иначе сократить ТИЛ двумя способами:
Y’r<0 -> [r,b]
Y’r>0 -> [a,r]
Установить k=k+1 и вернуться на шаг 1.
Можно модифицировать алгоритм – ввести смещение точек на α0 .
Спецификация программы.
В программе приведены два метода поиска – это линейный метод поиска, модифицированный для функций нескольких переменных, метод Золотого сечения 2. Также приведен метод Дэвидона – кубической аппроксимации для функций нескольких переменных. В программе присутствуют два вспомогательных алгоритма поиска начального интервала: метод Свенна1 и Свенна4. Присутствуют функции вычисления градиента и функция вычисления производной по направлению в точке. В качестве переменных-векторов используются обьекты класса complex, представляющие собой обьект из двух полей double, т.е. двумерные векторы. Также используются некоторые методы этого класса.
Текст программы.
#include<iostream.h>
#include<math.h>
#include<conio.h>
#include<complex.h>
//++++++++++++++++++++++++++++++++++++++++++++++
complex a,b;
int k=1,k1=1,k2=1,k3=1;
//++++++++++++++++++++++++++++++++++++++++++++++
double f (complex x)
{
return (real(x)*real(x)+3*imag(x)*imag(x)+2*real(x)*imag(x));
}
//++++++++++++++++++++++++++++++++++++++++++++++
complex grad (complex x)
{
return (complex(2*real(x)+2*imag(x),2*real(x)+6*imag(x)));
}
//++++++++++++++++++++++++++++++++++++++++++++++
double dy (complex x,complex p)
{
return (real(grad(x))*real(p)+imag(grad(x))*imag(p));
}
//++++++++++++++++++++++++++++++++++++++++++++++
void Svenn(complex x0,complex p)
{
double h=0.001;
if (f(x0)<f(x0+h*p)) h=-h;
x0=x0+h*p;
while (f(x0)<f(x0-h*p))
{
h=2*h;
x0=x0+h*p;
k++;
}
if (h>0)
{
a=x0-h*p-p*h/2;
b=x0;
}
else
{
a=x0;
b=x0-h*p-p*h/2;
}
}
//++++++++++++++++++++++++++++++++++++++++++++++
complex ZS2(complex x1)
{
double R=0.5*sqrt(5)-0.5,e=0.0001;
complex x0;
x0=complex(real(a)+R*(real(b)-real(a)),imag(a)+R*(imag(b)-imag(a)));
while (abs(b-a)>=e)
{
if ((abs(x0-a)<abs(x1-a))&&(f(x0)<f(x1)))
{
b=x1;
x0=complex(real(a)+R*(real(b)-real(a)),imag(a)+R*(imag(b)-imag(a)));
x1=a+b-x0;
}
else
if ((abs(x0-a)<abs(x1-a))&&(f(x0)>f(x1)))
{
a=x0;
x1=complex(real(a)+R*(real(b)-real(a)),imag(a)+R*(imag(b)-imag(a)));
x0=a+b-x1;
}
else
if ((abs(x0-a)>abs(x1-a))&&(f(x0)<f(x1)))
{
a=x1;
x0=complex(real(a)+R*(real(b)-real(a)),imag(a)+R*(imag(b)-imag(a)));
x1=a+b-x1;
}
else
if ((abs(x0-a)>abs(x1-a))&&(f(x0)>f(x1)))
{
b=x0;
x1=complex(real(a)+R*(real(b)-real(a)),imag(a)+R*(imag(b)-imag(a)));
x0=a+b-x1;
}
k1++;
};
return ((a+b)/2);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void Svenn4(complex x0,complex p)
{
double h=0.001;
if (dy(x0,p)>0) h=-h;
x0=x0+h*p;
while (dy(x0,p)*dy(x0-h*p,p)>=0)
{
h=2*h;
x0=x0+h*p;
k2++;
}
a=x0-h*p;
b=x0;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
complex Davidon(complex x0,complex p)
{
double da=real(a-x0)/real(p),db=real(b-x0)/real(p),z,w,r,e=0.0001;
if (da>db)
{
r=db;
db=da;
da=r;
}
a=x0+da*p;
b=x0+db*p;
z=dy(a,p)+dy(b,p)+3*(f(a)-f(b))/(db-da);
w=sqrt(z*z-dy(a,p)*dy(b,p));
r=da+(db-da)*(z-dy(a,p)+w)/(dy(b,p)-dy(a,p)+2*w);
while (dy(x0+r*p,p)>=e)
{
if (dy(x0+r*p,p)<0)
da=r;
else
db=r;
a=x0+da*p;
b=x0+db*p;
z=dy(a,p)+dy(b,p)+3*(f(a)-f(b))/(db-da);
w=sqrt(z*z-dy(a,p)+dy(b,p) );
r=da+(db-da)*(z-dy(a,p)+w)/(dy(b,p)-dy(a,p)+2*w);
k3++;
}
return (x0+r*p);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void main ()
{
clrscr();
complex x0 = complex(1,1),p = complex(2,3),x;
Svenn(x0,p);
cout <<" Swenn: [ "<< a <<" ; "<<b<<" ] "<<" k= " << k << endl;
x=a+b-x0;
x=ZS2(x);
cout <<" ZS2: X= "<< x <<" k= " << k1 << endl;
Svenn4(x0,p);
cout <<" Swenn4: [ "<< a <<" ; "<<b<<" ] "<<" k= " << k2 << endl;
x=Davidon(x0,p);
cout <<" Davidon: X= "<< x <<" k= " << k3 << endl;
getch();
}