
ФЕДЕРАЛЬНОЕ
АГЕНСТВО ПО ОБРАЗОВАНИЮ.
Государственное образовательное учреждение высшего профессионального образования.
«Санкт-Петербургский государственный электротехнический университет «ЛЭТИ» имени В.И. Ульянова (Ленина)»
(СПБГЭТУ)

Кафедра ВТ
Отчет
по п/р №3 «Исследование методов линейного поиска»
Выполнил: ст. группы 9307 Джабаров Р.Р.
Проверил: проф. Дмитревич Г.Д.
Санкт-Петербург
2014 г.
Цель работы – Целью работы является разработка программы, реализующей процедуру минимизации функции многих переменных в заданном направлении.
Описание методов оптимизации.
Метод Свенна:
С помощью этого метода получаем начальный интервал локализации минимума.
Начальный этап:
1) задать x0 – произвольная начальная точка.
2) выбрать шаг h равным 0.001 или 0.01*|x0|.
Основной этап:
Шаг 1:
Установить направление убывания целевой функции. Для этого надо взять x2=x1+h. Если f1<f2, то надо поменять направление движения(h=-h и взять x2=x1+h).
Шаг 2:
Вычислять fk в точках xk+1=xk+hk, где hk=2hk-1, k=2,3,…,n-1 до тех пор пока не придём в точку xn такую что fn>fn-1.
Шаг 3:
Установить начальный интервал локализации минимума a1=xn-2 и b1=xn.
Метод Золотого Сечения 1:
Начальный этап:
1) Выбрать погрешность , начальный интервал [a1, b1].
2) Вычислить стартовые точки по формулам: 1 = a1 + 0.618L1, 1 = a1 + 0.382L1.
3) Принять k = 1.
Основной этап:
Шаг 1:
1)Сократит текущий интервал локализации рассмотрением двух ситуаций:
если f1<f2, то ak+1=ak,
bk+1=k,
k+1=k,
и найти k+1=ak+1+0.382Lk+1,
иначе f1>f2, то ak+1=k,
bk+1=bk,
k+1=k,
и найти k+1=ak+1+0.618Lk+1, где Lk+1=| bk+1- ak+1|
2) Положить k=k+1.
Шаг 2:
Проверить критерий окончания поиска:
если L=|a-b| < -остановиться, точнее фиксируем аппроксимирующий минимум x*=(a+b)/2.
Блок-схемы использованных методов.
Метод Свенна
h1=0.1*|x1| x2=x1+h1 Начало f(x1)< f(x2) f(x2)<=
f(x1)
h<0
x1=x2;
x2=x1+h; h=2*h;
Меняем
местами а и b
h=-h; x2=x1+h;
Конец Да Нет Нет Да Нет Да
Метод Пауэлла
Метод Пауэлла является одним из самых популярных методов. Эффективен как и рассмотренный ранее алгоритм квадратичной интерполяции – экстраполяции, если начальная точка x1d(x*).
Начальный этап
-
Выбрать ε1, ε2, h.
-
Взять 3 точки a, b, c на равных на равных интервалах. Предполагается, что сработал метод Свенна и получен интервал [a, b].
a=a;
c=b;
b=(a+c)/2;
Основной этап
-
Найти аппроксимирующий минимум на 1-й итерации по формуле:
на последующих итерациях по формуле:
-
Проверить критерии близости двух точек:
;
Если
он выполняется, принять
и остановиться.
Если не выполняется, то из 2-х точек b и d выбрать «лучшую» - в которой наименьшее значение функции, обозначить её как b, а 2 соседние с ней – a и c. Далее рассмотреть 4 ситуации аналогично ЗС-2.
-
Положить k=k+1 и вернуться на шаг 1.
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <math.h>
using namespace std;
class Vector
{
public:
Vector(int Size);// конструктор, создающий матрицу
Vector(const Vector& v);// конструктор копирования
~Vector(); // деструктор
int size() const; // функция, возвращающая размер матрицы
double& Vector::operator[](int N);// перегрузка оператора [] для работы с массивом, имеющий тип данных ссылка
double Vector::operator[](int N) const;// перегрузка оператора для работы с типом данных double
void Sum(const Vector& a, const Vector& b);//суммирование векторных значении
void Subtraction(const Vector& a, const Vector& b);//разность векторных значении
Vector Scal(Vector x, double d);//Скалярное умножение
double Mult(const Vector& a, const Vector& b);//Умножение векторов
Vector& operator=(const Vector& a);// перегрузка оператора для присваивания вектору значении другого вектора
void print() const;//Вывод значении массива
Vector Grad(const Vector& x);// Градиент
/**Лабораторная №3**/
void Swenn(const Vector& x, Vector& p, double& ala, double& alb);// Метод Свенна для векторных переменных
//double ZS1(Vector& x, Vector p, double al1, double al2);
double ZS1(Vector& x, Vector p, double al1, double al2, double E);// Золотое сечение 1 для векторных переменных
double Powell(Vector& x, Vector p, double al1, double al2, double E);// Метод Пауэлла для векторных переменных
Vector Orta(int n, int Num);// Единичная орта
Vector function(Vector& x, double E, int method);// Метод золотого сечения
Vector operator+(const Vector& a)
{
Vector s(nSize);
s.Sum(*this, a);
return s;
}
Vector operator-(const Vector& a)
{
Vector s(nSize);
s.Subtraction(*this, a);
return s;
}
double operator*(const Vector& a)
{
double w;
Vector s(nSize);
w = s.Mult(*this, a);
return w;
}
void operator*=(double d)
{
for (int i = 0; i < nSize; i++)
Coord[i] *= d;
}
private:
double* Coord;
int nSize;
};
Vector::Vector(int Size)
{
nSize = Size;
Coord = new double[Size];
}
Vector::Vector(const Vector& v)
{
nSize = v.size();
Coord = new double[nSize];
for (int i = 0; i < nSize; i++)
Coord[i] = v[i];
}
Vector::~Vector()
{
delete[] Coord;
}
int Vector::size() const
{
return nSize;
}
double& Vector::operator[](int N)
{
return *&Coord[N];
}
double Vector::operator[](int N) const
{
return Coord[N];
}
Vector Vector::Scal(Vector x, double d)
{
int i = x.size();
Vector W(i);
for(int j=0; j<i; j++)
W[j] = x[j]*d;
return W;
}
void Vector::Sum(const Vector& a, const Vector& b)
{
int s = a.size();
int i;
if ((s = b.size()) != 0 )
{
for (i = 0; i < s; i++)
{
Coord[i] = a[i] + b[i];
}
}
else
{
cout<<"ERROR!"<<endl;
}
}
void Vector::Subtraction(const Vector& a, const Vector& b)
{
int s = a.size();
int i;
if ((s = b.size()) != 0 )
{
for (i = 0; i < s; i++)
{
Coord[i] = a[i] - b[i];
}
}
else
{
cout<<"ERROR!"<<endl;
}
}
double Vector::Mult(const Vector& a, const Vector& b)
{
int s = a.size();
//int i;
double Um=0;
if ((s = b.size()) != 0 )
{
for (int i = 0; i < s; i++)
{
Coord[i] = a[i] * b[i];
Um = Um + Coord[i];
}
}
return Um;
}
Vector& Vector::operator =(const Vector& a)
{
for (int i = 0; i < nSize; i++)
{
Coord[i] = a.Coord[i];
}
return *this;
}
void Vector::print() const
{
cout<<"This is vector:"<<endl;
for (int i = 0; i < nSize; i++)
{
cout<<Coord[i]<<endl;
};
}
double F (Vector t)
{
double result = 0;
result =t[0]*t[0]+3*t[1]*t[1]+2*t[0]*t[1];
return result;
}
double Differ(Vector x, int i)
{
int t = x.size();
double w = 0;
double h = 0.000001;
Vector q(t);
if (t >= i)
w = ( F(x + q.Scal(q.Orta(t, i), h)) - F(x - q.Scal(q.Orta(t, i), h)) )/(2*h);
return w;
}
Vector Vector::Grad(const Vector& x)
{
int i = x.size();
Vector w(i);
for (int j = 1; j<=i; j++)
{
w[j-1] = Differ(x, j);
}
return w;
}
void Vector::Swenn(const Vector& x, Vector& p, double& ala, double& alb)
{
int r = x.size();
Vector G(r);
G = G.Grad(x); // Проверка направления убывания функции
if ((G * p) > 0) //
{ //
p*=-1;
} //
double f1, f2, al = 0.000001;
Vector x1(r);
Vector x2(r);
x1 = x;
f1 = G * p;
do
{
al = al*2;
G = G.Scal(p, al);
x2 = x1 + G;
G = G.Grad(x2);
f2 = G * p;
}
while (f1*f2 > 0);
alb = al;
ala = al/2;
}
double Vector::ZS1(Vector& x, Vector p, double al1, double al2, double E)
{
double l, m, f1, f2;
int j=0;
l = al1 + 0.38196601125*fabs(al1-al2);
m = al1 + 0.61803398875*fabs(al1-al2);
int r = x.size();
Vector G(r);
Vector x1(r);
Vector x2(r);
while ( (fabs(al1-al2) >= E) )
{
j = j + 1;
x1 = x + G.Scal(p, l);
f1 = F(x1);
x2 = x + G.Scal(p, m);
f2 = F(x2);
if (f1 < f2)
{
al2 = m;
m = l;
l = al1 + 0.38196601125*fabs(al1-al2);
}
if (f1 >= f2)
{
al1 = l;
l = m;
m = al1 + 0.61803398875*fabs(al1-al2);
}
}
return (al1+al2)/2;
}
Vector Vector::Orta(int n, int Num) // координатная орта длиной n с 1 на диагонали 1
{ // dlinoy 'n'
Vector W(n); // i 1-tsey na 'Num'
int i=0;
while (i<n)
{
W[i] = 0;
i++;
}
W[Num-1] = 1;
return W;
}
double Vector::Powell(Vector& x, Vector p, double al1, double al2, double E)
{
double a, b, c, d, help1, help2;
int r = x.size();
Vector xa(r);
Vector xb(r);
Vector xc(r);
Vector xd(r);
a = al1;
b = (al1+al2)/2;
c = al2;
xa = x + xa.Scal(p, a);
xb = x + xb.Scal(p, b);
xc = x + xc.Scal(p, c);
help1 = ( F(xa)*(b*b-c*c) + F(xb)*(c*c-a*a) + F(xc)*(a*a-b*b) );
help2 = (F(xa)*(b-c) + F(xb)*(c-a) + F(xc)*(a-b));
if (help2 == 0)
help2 = 0.0000001;
d = 0.5*help1/help2;
xd = x + xd.Scal(p, d);
while ( fabs((d-b)/b) >= E )
{
if( F(xb) > F(xd) )
{
if(b > d)
{
c = b;
}
else
{
a = b;
}
b = d;
}
else
{
if(b > d)
{
a = d;
}
else
{
b = d;
}
}
xa = x + xa.Scal(p, a);
xb = x + xb.Scal(p, b);
xc = x + xc.Scal(p, c);
help1 = (F(xa)-F(xb))*(b-c)*(c-a);
help2 = (F(xa)*(b-c) + F(xb)*(c-a) + F(xc)*(a-b));
if (help2 == 0)
break; // Delenie na nol'
d = (a+b)/2 + 0.5*(help1/help2);
xd = x + xd.Scal(p, d);
}
return (b + d)/2;
}
Vector Vector::function(Vector& x, double E, int method)
{
int r = x.size();
Vector p(r); //napravlenie
Vector G(r); //vspomogatel'naya
Vector t(r); //dubliruet 'x'
double al, a, b, k;
int y=0;
t = x;
p[0]=2; p[1]=3;
G.Swenn(t, p, a, b);
if (method == 1)
al = G.ZS1(t, p, a, b, E); //alpha i-oe
if (method == 2)
al = G.Powell(t, p, a, b, E); //alpha i-oe
t = t + G.Scal(p, al);
return t;
}
void main()
{
double E;
E=0.000001;
int method;
cout<<"Laboratornaya_3"<<endl;
cout<<"f(x1,x2) = x1^2 + 3x2^2 + 2x1*x2;"<<endl;
Vector x(2);
Vector Q3(2);
cout<<"Metod Zolotogo Sechenia-1 and Method Pauella"<<endl;
x[0]=1;
x[1]=1;
Q3 = Q3.function(x, E, 1);
cout<<"Method Zolotogo Sechenia-1 "<<endl;
Q3.print();
Q3 = Q3.function(x, E, 2);
cout<<"Method Pauella "<<endl;
Q3.print();
getch();
}