Лабораторная работа №21
.docМинистерство образования РФ
Санкт-Петербургский государственный электротехнический
университет имени В.И. Ульянова (Ленина) "ЛЭТИ"
Лабораторная работа по дисциплине
«Методы оптимизации » №2
на тему: «Методы полиномиальной интерполяции для поиска минимума целевых функций».
Выполнил: Воронин А.В.
Погодина К.
Группа: 2373
Преподаватель:
Санкт-Петербург
2004 г
Целью работы является:
1) сравнение двух методов одномерной минимизации - прямого и интерполяционного;
2) разработка программы, реализующей прямой метод на этапе установления границ начального интервала и метод полиномиальной интерполяции для локализации искомого минимума.
Описание методов оптимизации.
Алгоритм Фибоначчи-2
Начальный этап
(1) Задать константу , начальный интервал [a1, b1], длину конечного интервала Ln и определить число n так, чтобы выполнялось условие Fn > (b1 - a1)/Ln.
(2) Выбрать одну пробную точку . Положить
k = 1.
Основной этап
Шаг 1. Проверить критерий окончания поиска: если k=n, то остановиться и положить x*=x2.
Шаг 2. Сократить текущий интервал локализации рассмотрением 4-х ситуаций, аналогично методу золотого сечения-2.
Алгоритм ДСК
Данный метод относится к классу прямых методов, опирающихся на идею построения аппроксимирующего полинома второго порядка на основании информации о значениях функции в n+1 точке – узлах интерполяции.
Начальный этап
-
Выбрать произвольную точку x1Rn
-
Задаться величиной шага h=0.001
-
Определить погрешность
-
Положить счётчик числа итераций равным 1, а также b=x1
Основной этап
Шаг 1. Вычислить fi в 3-х точках: a, b и с – центральной (b) и двух соседних: a=b-h, c=b+h. Затем, по формуле
(1)
или
(2)
найти аппроксимирующий минимум d
Шаг 2. Проверить критерий близости 2-х точек b и d
и
Если оба условия выполняются – фиксируем аппроксимирующий минимум
и останавливаемся. Если оба критерия не выполняются, полагаем b=d и возвращаемся на шаг 1.
Текст программы:
#include<conio.h>
#include<math.h>
#include<iostream.h>
double f(double x)
{
return (2*x*x+3*exp(-x));
}
long fib(long n)
{
long i,f1=1,f2=1,f;
if((n==1)||(n==2)) return 1;
for(i=3;i<=n;i++)
{
f=f2;
f2=f1+f;
f1=f;
}
return f2;
}
long number(long fn)
{
long fd,f0=1,f1=1,k=2;
while(f1<fn)
{
fd=f1;
f1=f1+f0;
f0=fd;
k++;
}
return k;
}
void swann(double x0,double* a,double* b)
{
double h1,x1;
h1=0.0001*fabs(x0);
x1=x0+h1;
if(f(x0)<f(x1))
{
h1=-h1;
x1=x0+h1;
}
do
{
h1=2*h1;
x1=x1+h1;
}
while(f(x1-h1)>f(x1));
*a=x1-1.5*h1;
*b=x1;
}
double F1(double* a,double* b)
{
double Ln=0.000001,L1,e,x1,x2;
long n,Fn;
int k;
L1=fabs(*b-*a);
Fn=(int)(L1/Ln+0.5);
n=number(Fn);
e=L1/fib(n+1);
x1=*a+fib(n-2)/Fn*L1;
x2=*a+fib(n-1)/Fn*L1;
k=1;
while(k<5)
{
if (f(x1)<f(x2))
{
*b=x2;
x2=x1;
x1=*a+fib(n-k-2)/Fn*L1;
L1=fabs(*b-*a);
}
else
{
*a=x1;
x1=x2;
x2=*a+fib(n-k-1)/Fn*L1;
L1=fabs(*b-*a);
}
k++;
}
x2=x1+e;
if (f(x1)<f(x2)) return (*a+x2)/2;
else return (x1+*b)/2;
}
double DSK(double x0)
{
double e1,e2,h1,x1,x,a,b,c,d;
e1=0.0001;
e2=e1;
if(x0!=0) h1=0.01*fabs(x0);
else h1=0.01;
do
{
x1=x0+h1;
if(f(x0)<f(x1))
{
h1=-h1;
x1=x0+h1;
}
do
{
h1=2*h1;
x1=x1+h1;
}
while(f(x1-h1)>f(x1));
x=(x1+x1-h1)/2;
if(f(x)<f(x1-h1))
{
a=x1-h1;
b=x;
c=x1;
}
else
{
a=x1-1.5*h1;
b=x1-h1;
c=x;
}
d=b+1/2*((b-a)*(f(a)-f(c)))/(f(a)-2*f(b)+f(c));
if((fabs((d-b)/b)<=e1)&&(fabs((f(d)-f(b))/f(b))<=e2))
return (b+d)/2;
if(f(b)<f(d)) x0=b;
else x0=d;
h1=h1/2;
}
while(1);
}
void main()
{
double x0,a,b,n,min;
cout<<"Введите начальную точку";
cin>>x0;
swann(x0,&a,&b);
if(a>b)
{
n=a;
a=b;
b=n;
}
cout<<"Интервал, полученный методом Свенна: ["<<a<<";"<<b<<"]"<<'\n';
x0=F1(&a,&b);
min=DSK(x0);
cout<<"Искомая точка "<<min;
getch();