Скачиваний:
11
Добавлен:
03.06.2014
Размер:
108.55 Кб
Скачать

ФЕДЕРАЛЬНОЕ АГЕНСТВО ПО ОБРАЗОВАНИЮ.

Государственное образовательное учреждение высшего профессионального образования.

«Санкт-Петербургский государственный электротехнический университет «ЛЭТИ» имени В.И. Ульянова (Ленина)»

(СПБГЭТУ)

Кафедра ВТ

Отчет

по п/р №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;

Конец

Да

Нет

Нет

Да

Нет

Да

Метод Пауэлла

Метод Пауэлла является одним из самых популярных методов. Эффективен как и рассмотренный ранее алгоритм квадратичной интерполяции – экстраполяции, если начальная точка x1d(x*).

Начальный этап

  1. Выбрать ε1, ε2, h.

  2. Взять 3 точки a, b, c на равных на равных интервалах. Предполагается, что сработал метод Свенна и получен интервал [a, b].

a=a;

c=b;

b=(a+c)/2;

Основной этап

  1. Найти аппроксимирующий минимум на 1-й итерации по формуле:

на последующих итерациях по формуле:

  1. Проверить критерии близости двух точек:

;

Если он выполняется, принять и остановиться.

Если не выполняется, то из 2-х точек b и d выбрать «лучшую» - в которой наименьшее значение функции, обозначить её как b, а 2 соседние с ней – a и c. Далее рассмотреть 4 ситуации аналогично ЗС-2.

  1. Положить 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();

}

Соседние файлы в папке р 1-5, 2 вар.; 7 лаб. метод Полака Рибьера + Лекции МО + перевод ГА