Лабораторная работа №32 / Отчёт
.docОтчёт по лабораторной работе №3
Исследование методов линейного поиска
Цель работы – разработка программы, реализующей комбинированную процедуру минимизации функции многих переменных в заданном направлении методами золотого сечения-2 – Дэвидона;
Описание методов.
-
Суть метода ЗС-2 заключается в том, что на каждом шаге (кроме последнего) текущий интервал локализации делится на отрезки, в том же отношении, что и 2 последовательных числа Фибоначчи. Как и в методе золотого-сечения действуют правила симметрии и одного вычисления. На начальном этапе задаётся начальный интервал [a1, b1] (методом Свенна)
-
Предварительная часть:
-
а) определение исследуемого промежутка [a, b] методом Свенна-4. Выбор точности – ε;
2) Основная часть:
а) Вычисление 2- х симметричных точек m и l сокращение текущего интервала локализации рассмотрением четырёх случаев в зависимости от отношения значений функции и точках m и l.
б) проверка критерия окончания поиска (L<= ε). В случае, если критерий достигнут минимум функции = (a+b)/2, иначе – повторение шага а).
-
Метод Дэвидона
1) Предварительная часть
а) Задание начального шага, макс погрешности, начальной точки х1
б) Нахождение вектора р, шага α.
в) Нахождение начального интервала методом Свенна 4.
2) Основной этап
а) Найти аппроксимирующий шаг по формуле.
б) Критерий окончания поиска: y’<ε, если не выполнен, то возвращаемся к пункту 1 в).
Спецификация
Функция |
Переменная |
Смысл |
|
X0 |
Начальная точка |
|
p |
Направление поиска |
y |
|
Значение заданной функции |
Vector v |
переменные |
|
f |
|
Значение заданной функции по линии |
|
double a |
переменные |
df |
|
Производная заданной функции по линии |
|
double a |
переменные |
dyp |
|
Производная заданной функции |
|
Vector х |
переменные |
Swann 4 |
|
метод Свенна4 |
x |
точки в которую делается шаг |
|
a0 |
Шаг |
|
ZS2 |
|
Метод ЗС-2 |
a b |
Границы промежутка |
|
l,m |
Точки на помежутке |
|
к |
Счётчик |
|
|
e |
погрешность |
z |
|
Формула для метода Дэвидона |
w |
|
Формула для метода Дэвидона |
Davidon |
|
метод Дэвидона |
a b |
Границы промежутка |
|
e,ex |
погрешность |
|
r |
Шаг |
Текст программы.
#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
#define t 0.61803398874989484820458683436564
#include <math.h>
class CVector
{
public:
double x;
double y;
CVector operator+(CVector y_){return CVector(x+y_.x,y+y_.y);}
CVector operator-(CVector y_){return CVector(x-y_.x,y-y_.y);}
CVector operator*(double c ){return CVector(x*c,y*c);}
CVector operator-() {return CVector(-x,-y);}
double operator*(CVector y_){return x*y_.x+y*y_.y;}
operator double() {return sqrt(x*x+y*y);}//norm when converting to double
CVector(double x_,double y_) {x=x_;y=y_;}
};
//Начальные условия
CVector x0(1,1);
CVector p(2,3);
//Вычисление зеданной тестовой функции.
double y(CVector v)
{
return v.x*v.x+3*v.y*v.y+2*v.x*v.y;
}
//по линии
double f(double a)
{
return y(x0+p*a);
}
//произв по линии
double df(double a)
{ double e=0.00001
return (f(a+e)-f(a))/(e*(double)p);
}
double dyp(CVector x)
{
double e=0.00001
return (y(x+p*e)-y(x))/(e*(double)p);
}
//-----------------------
CVector Swann4(double &a0)
{
CVector x=x0;
double dy1=dyp(x);
if(dy1>0) p=-p;
do
{
x=x+p*a0;
a0*=2;
}while(dy1*dyp(x)< 0);
return x;
}
// Метод ЗС-2
double ZS2(double &a ,double &b, double e)
{
double l=a+t*(b-a);
int k=0; m=a+b-l;
do
{
m=a+b-l;
if(m<l && f(m)<f(l)) {b=l;l=m;}
if(l<m && f(l)<f(m)) {b=m;}
if(m<l && f(m)>f(l)) {a=m;}
if(l<m && f(l)>f(m)) {a=l;l=m;}
k++;
}while(k<100 && fabs(b-a)>e);
return (a+b)/2;
}
inline double z(double a, double b)
{return df(a)+df(a+b)+3*(f(a)-f(a+b))/b;}
inline double w(double a, double b)
{return sqrt(z(a,b)*z(a,b)-df(a)*df(a+b));}
// Метод Дэвидона
double Davidon(double a,double b ,double ex=0.000001)
{
b-=a;
double r;
do
{
r=b*(z(a,b)-df(a)-w(a,b))/(df(a+b)-df(a)+2*w(a,b));
if(df(r+a)>0) a=r;
else
{
a+=r;
b-=r;
}
}
while(r>ex );
return a+r;
}
int _tmain(int argc, _TCHAR* argv[])
{
double a0=0.1;
CVector x=Swann4(a0);
double b=(x-x0).x/p.x;
double a=b-a0/2;
if(a>b){double temp=a; a=b; b=temp;}
double res=ZS2(a,b,0.0001);
printf("res vector: [%f,%f]\n",(x0+p*res).x,(x0+p*res).y);
res=Davidon(a,b,0.000001);
printf("res vector: [%f,%f]",(x0+p*res).x,(x0+p*res).y);
getch();
return 0;
}
Пошаговое выполнение метода ЗС-2
1 l=0.452786 m=0.452786 a=0.300000 b=0.547214
2 l=0.394427 m=0.394427 a=0.300000 b=0.452786
3 l=0.358359 m=0.358359 a=0.300000 b=0.394427
4 l=0.358359 m=0.336068 a=0.336068 b=0.394427
5 l=0.372136 m=0.372136 a=0.358359 b=0.394427
6 l=0.372136 m=0.380650 a=0.358359 b=0.380650
7 l=0.372136 m=0.366874 a=0.366874 b=0.380650
8 l=0.372136 m=0.375388 a=0.366874 b=0.375388
9 l=0.372136 m=0.370126 a=0.370126 b=0.375388
10 l=0.372136 m=0.373378 a=0.370126 b=0.373378
11 l=0.372136 m=0.371368 a=0.371368 b=0.373378
12 l=0.372136 m=0.372610 a=0.371368 b=0.372610
13 l=0.372136 m=0.371843 a=0.371843 b=0.372610
14 l=0.372136 m=0.372317 a=0.371843 b=0.372317
15 l=0.372136 m=0.372024 a=0.372024 b=0.372317
16 l=0.372136 m=0.372205 a=0.372024 b=0.372205
17 l=0.372093 m=0.372093 a=0.372024 b=0.372136
18 l=0.372093 m=0.372067 a=0.372067 b=0.372136
Пошаговое выполнение метода Дэвидона.
1
2
3
1 r=-0.000038 a=0.372029 b=0.000107
2 r=0.000017 a=0.372045 b=0.000091
3 r=0.000009 a=0.372054 b=0.000082
Выводы:
В результате проведения лабораторной работы была изучена минимизация функции многих переменных в заданном направлении методами золотого сечения-2 и Дэвидона;
Результат совпал с ожидаемым (указанным в задании и полученным построением). Из представленного пошагового выполнения программы видно, что метод Дэвидона обходится значительно меньшим количеством итераций.