Скачиваний:
24
Добавлен:
01.05.2014
Размер:
121.86 Кб
Скачать

Министерство образования рф

Санкт-Петербургский государственный электротехнический

университет «ЛЭТИ»

Кафедра САПР

Отчет по лабораторной работе № 7

по учебной дисциплине «методы оптимизации»

на тему «Исследование методов переменной метрики»

Вариант 1

Выполнили:

Смирнов С.А.

Маркосов А.С.

Баранов А.А.

Группа: 5372

Факультет: КТИ

Проверил:

(должность, Ф.И.О.)

Санкт-Петербург

2007

Оглавление:

Задание…………………………………………………………………………….3

Описание методов оптимизации…………………………………………………3

Спецификация программы……………………………………………………….4

Листинг программы ……………………………………………………………...5

Результаты тестирования и Выводы…………………….……………………….7

Ответы на контрольные вопросы………………………………………………...8

Задание:

Цель работы – изучение методов переменной метрики и разработка программы, удовлетворяющей требованиям лабораторной работы 5. При разработке программы предусмотреть возможность выбора любого из одномерных методов, реализованных в лабораторных работах 1, 2 и 3.

Методы оптимизации:

М1 – метод Дэвидона–Флетчера–Пауэлла;

Функция y(x)

Начальная точка (x1)t

Значение минимума (x*)t

8x12 + 4x1x2 + 5x22

(10; 10)

(0; 0)

(x2 – x12)2 + 100(1 – x12)2

(1.5; 2)

(1; 2)

(1; 1)

Описание методов оптимизации:

Метод Давидона-Флетчера-Пауэлла:

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

  • Выбрать ε - погрешность локализации минимума;

  • Выбрать точку х1 на отрезке [a1;b1], полученном методом Свенна;

  • Положить k = 1 – счетчик итераций;

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

Шаг 1:

  • Сконструировать квазиньютоновское направление поиска, которое вычисляется так: pk = -Akgrad(yk), где Ak: а) = Е (единичной матрице, в данной работе рамера 2х2), если k = {1,n+1,2(n+1),..}; б) = Ak-1 + (Δxk-1)( Δxk-1)t/(( Δxk-1)tγk-1) –

- (Sk-1)(Sk-1)t/((Sk-1)t γk-1), где: Δxk-1 = xk – xk-1; γk-1 = grad(yk) – grad(yk-1);

Sk-1= Ak-1 γk-1.

Шаг 2:

  • Найти αk, доставляющий минимум при движении вдоль найденного направления pk (т.е. решается задача поиска по направлению - л/р №3, метод Фибоначчи2-Пауэлла).

Шаг 3:

  • Перейти в новую точку: xk+1 = xk + αk pk;

  • k = k + 1;

Шаг 4:

  • Проверка КОП: Если ||grad(yk)|| ≤ ε , то остановиться – минимум найден (x* = xk).

  • Если КОП не выполняется, то перейти на Шаг 1;

Спецификация программы: Текст программы:

laba7Int.h

//----------------------------------------------------------

//----------------------------------------------------------

class INTERVAL

{

double d_left;

double d_right;

friend INTERVAL Swann1();

friend INTERVAL Fibonacci2(INTERVAL);

friend double Pauell(INTERVAL);

friend double OneDimensionalDescent(VECTOR,VECTOR);

public:

INTERVAL() {} //Конструкторы и деструктор класса

INTERVAL(double d1,double d2)

{

d_left=d1;

d_right=d2;

}

~INTERVAL() {}

};

//----------------------------------------------------------

//----------------------------------------------------------

laba7M.h

#include <iostream.h>

#include "laba7V.h"

//----------------------------------------------------------

//----------------------------------------------------------

//class for matrix operations(in addition to vector class)

const int N=2; //Size of matrix

class MATRIX

{

double m[2][2];

friend VECTOR KvaziNewtonDirectConst(VECTOR,VECTOR);

friend VECTOR SearchMin(VECTOR);

public: //Конструкторы и деструктор класса

MATRIX()

{

int j;

for(int i=0;i<N;i++)

for(j=0;j<N;j++)

m[i][j]=0;

}

MATRIX(double m00,double m01,double m10,double m11)

{

m[0][0]=m00;

m[0][1]=m01;

m[1][0]=m10;

m[1][1]=m11;

}

~MATRIX() {}

void MatrPrint()

{

for(int i=0;i<N;i++)

{

cout<<endl<<"| ";

for(int j=0;j<N;j++)

cout<<m[i][j];

cout<<"|";

}

}

void MatrInit(MATRIX M)

{

m[0][0]=M.m[0][0];

m[0][1]=M.m[0][1];

m[1][0]=M.m[1][0];

m[1][1]=M.m[1][1];

}

};

//----------------------------------------------------------

//----------------------------------------------------------

laba7V.h

#include <stdio.h>

#include <math.h>

//----------------------------------------------------------

//----------------------------------------------------------

//class containing vector operations

class VECTOR

{

double x1;

double x2;

friend VECTOR DisplToPoint(double);

friend double Func(double);

friend double OneDimensionalDescent(VECTOR,VECTOR);

friend VECTOR KvaziNewtonDirectConst(VECTOR,VECTOR);

friend VECTOR SearchMin(VECTOR);

public:

VECTOR() {} //Конструкторы и деструктор класса

VECTOR(double k1,double k2)

{

x1=k1;

x2=k2;

}

~VECTOR() {}

void Grad(VECTOR Xk) //Ф-ция для вычисления градиента

{

x1=16*Xk.x1+4*Xk.x2;

x2=4*Xk.x1+10*Xk.x2;

}

double Norm() // Ф-ция для вычисления нормы вектора

{

return(sqrt(x1*x1+x2*x2));

}

void VectAdd(VECTOR Xk,double displ,VECTOR Pk) // Ф-ция для вычисления

{ // координат точки xk+1

x1=Xk.x1+displ*Pk.x1;

x2=Xk.x2+displ*Pk.x2;

}

void VectPrint() //Ф-ция для вывода на экран вектора

{

printf("[%.20f;%.20f]",x1,x2);

}

void VectInit(VECTOR Xk)

{

x1=Xk.x1;

x2=Xk.x2;

}

void VectSub(VECTOR a,VECTOR b)

{

x1=a.x1-b.x1;

x2=a.x2-b.x2;

}

};

//----------------------------------------------------------

//----------------------------------------------------------

laba7.cpp

#include <math.h>

#include <conio.h>

#include <iostream.h>

#include <stdio.h>

#include "laba7M.h"

#include "laba7Int.h"

//----------------------------------------------------------

//----------------------------------------------------------

//global variables & class objects

VECTOR X0;

VECTOR Point;

int K=1; //счетчик итераций

MATRIX PrA(1,0,0,1);

VECTOR PrX(10,10);

//----------------------------------------------------------

//----------------------------------------------------------

//functions

VECTOR DisplToPoint(double d_point)

{

VECTOR v_point;

v_point.x1=X0.x1+d_point*Point.x1;

v_point.x2=X0.x2+d_point*Point.x2;

return(v_point);

}

//----------------------------------------------------------

//----------------------------------------------------------

double Func(double d_point) //8x12 + 4x1x2 + 5x22

{

VECTOR x;

x=DisplToPoint(d_point);

return(8*x.x1*x.x1+4*x.x1*x.x2+5*x.x2*x.x2);

}

//----------------------------------------------------------

//----------------------------------------------------------

//swenn method

INTERVAL Swann1()

{

double d_step=0.01; //начальный шаг

if(Func(d_step)>Func(0))

d_step=-d_step;

double d_point=0;

do

{

d_point+=d_step;

d_step*=2;

}while(Func(d_point)>Func(d_point+d_step));

INTERVAL int1; //объект для сохранения начального интервала локализации

//минимума

if((d_point+d_step)<(d_point-d_step/2))

{

int1.d_left=d_point+d_step; //a

int1.d_right=d_point-d_step/2; //b

}

else

{

int1.d_left=d_point-d_step/2; //a

int1.d_right=d_point+d_step; //b

}

return(int1);

}

//----------------------------------------------------------

//----------------------------------------------------------

//----------------------------------------------------------

//----------------------------------------------------------

//fib2 method

INTERVAL Fibonacci2(INTERVAL int1)

{

double Ln=0.0001;

double L1=fabs(int1.d_right-int1.d_left);

double Fn=L1/Ln;

double n=log(Fn*2.236)/log(1.618)-1;

double Fnm1=pow(1.618,(int)n)/2.236;

double Fnp1=Fn+Fnm1;

double E=L1/Fnp1; //погрешность локализации минимума

int count=1; //счетчик итераций

double L2=Fnm1/Fn*L1+pow(-1,(int)n)*E/Fn;

double displX1=int1.d_left+L2;

double displX2;

INTERVAL intk(int1.d_left,int1.d_right); //инициализация дополнительного объекта для

// хранения рабочего интервала

while((count!=(int)n)&&(count!=6))

{

if(fabs(intk.d_right-intk.d_left)<=E) //Проверка КОП данного метода

{

intk.d_left=intk.d_right=(intk.d_left+intk.d_right)/2;

return(intk);

}

displX2=intk.d_left+intk.d_right-displX1;

if(displX1<displX2) //Сокращение ТИЛ

if(Func(displX1)<Func(displX2)) //1

intk.d_right=displX2;

else //2

{

intk.d_left=displX1;

displX1=displX2;

}

else

if(Func(displX1)<Func(displX2)) //3

intk.d_left=displX2;

else //4

{

intk.d_right=displX1;

displX1=displX2;

}

count++;

}

return(intk);

}

//----------------------------------------------------------

//----------------------------------------------------------

//----------------------------------------------------------

//----------------------------------------------------------

//pauell method

double Pauell(INTERVAL int1)

{

int k=1; //счетчик итераций

double E=0.000001; //погрешность локализации минимума

double displA,displB,displC; //абсолютные смещения симметричных точек А, В и С

displA=int1.d_left;

displC=int1.d_right;

displB=(displA+displC)/2;

double displD,Fa,Fb,Fc,Fd,displX; //Смещение апроксимирующего минимума и значекния

while(1) //целевой ф-ции в точках А, В, С и D

{

Fa=Func(displA);

Fb=Func(displB);

Fc=Func(displC);

if(k==1)

{

displD=0.5*(Fa*(displB*displB-displC*displC)+Fb*(displC*displC-displA*displA)+Fc*(displA*displA-displB*displB));

displD/=(Fa*(displB-displC)+Fb*(displC-displA)+Fc*(displA-displB));

}

else

displD=(displA+displB)/2+1/2*(Fa-Fb)*(displB-displC)*(displC-displA)/(Fa*(displB-displC)+Fb*(displC-displA)+Fc*(displA-displB));

Fd=Func(displD);

if((fabs((displD-displB)/displB)<=E)&&(fabs((Fd-Fb)/Fb)<=E)) //проверка КОП

{

displX=(displB+displD)/2;

break;

}

if(displB<displD) //Сокращение ТИЛ

if(Fb<Fd) //1

displC=displD;

else //2

{

displA=displB;

displB=displD;

}

else

if(Fb<Fd) //3

displA=displD;

else //4

{

displC=displB;

displB=displD;

}

k++;

}

return displX;

}

//----------------------------------------------------------

//----------------------------------------------------------

//----------------------------------------------------------

//----------------------------------------------------------

double OneDimensionalDescent(VECTOR Xk,VECTOR Pk)

{

X0.x1=Xk.x1;

X0.x2=Xk.x2;

Point.x1=Pk.x1;

Point.x2=Pk.x2;

INTERVAL intI=Swann1();

INTERVAL int2=Fibonacci2(intI);

double d_point; //смещение минимума целевой ф-ции от Xk по направлению Pk

if(int2.d_left==int2.d_right)

d_point=int2.d_left;

else

d_point=Pauell(int2);

return(d_point);

}

//----------------------------------------------------------

//----------------------------------------------------------

//----------------------------------------------------------

//----------------------------------------------------------

VECTOR KvaziNewtonDirectConst(VECTOR Xk,VECTOR Xkm1)

{ //km1 - означает индекс k-1, в остальном обозначения эквивалентны приведенным в схеме

//метода

VECTOR dXkm1,GRADk,GRADkm1,GAMMAkm1,Skm1,Pk;

GRADk.Grad(Xk);

if((K%2)==0)

{

dXkm1.VectSub(Xk,Xkm1);

GRADkm1.Grad(Xkm1);

GAMMAkm1.VectSub(GRADk,GRADkm1);

Skm1.x1=PrA.m[0][0]*GAMMAkm1.x1+PrA.m[0][1]*GAMMAkm1.x2;

Skm1.x2=PrA.m[1][0]*GAMMAkm1.x1+PrA.m[1][1]*GAMMAkm1.x2;

double zn2,zn1=dXkm1.x1*GAMMAkm1.x1+dXkm1.x2*GAMMAkm1.x2;

MATRIX Ak,mat1,mat2;

mat1.m[0][0]=(dXkm1.x1*dXkm1.x1)/zn1;

mat1.m[0][1]=(dXkm1.x1*dXkm1.x2)/zn1;

mat1.m[1][0]=(dXkm1.x1*dXkm1.x2)/zn1;

mat1.m[1][1]=(dXkm1.x2*dXkm1.x2)/zn1;

zn2=Skm1.x1*GAMMAkm1.x1+Skm1.x2*GAMMAkm1.x2;

mat2.m[0][0]=(Skm1.x1*Skm1.x1)/zn2;

mat2.m[0][1]=(Skm1.x1*Skm1.x2)/zn2;

mat2.m[1][0]=(Skm1.x1*Skm1.x2)/zn2;

mat2.m[1][1]=(Skm1.x2*Skm1.x2)/zn2;

for(int j,i=0;i<N;i++)

for(j=0;j<N;j++)

Ak.m[i][j]=PrA.m[i][j]+mat1.m[i][j]-mat2.m[i][j];

Pk.x1=-(Ak.m[0][0]*GRADk.x1+Ak.m[0][1]*GRADk.x2);

Pk.x2=-(Ak.m[1][0]*GRADk.x1+Ak.m[1][1]*GRADk.x2);

PrA.MatrInit(Ak);

}

else

{

Pk.x1=-GRADk.x1;

Pk.x2=-GRADk.x2;

}

return(Pk);

}

//----------------------------------------------------------

//----------------------------------------------------------

//----------------------------------------------------------

//----------------------------------------------------------

VECTOR SearchMin(VECTOR Xk)

{

VECTOR Pk=KvaziNewtonDirectConst(Xk,PrX);

double d_point=OneDimensionalDescent(Xk,Pk);

VECTOR Xkp1;

Xkp1.VectAdd(Xk,d_point,Pk);

PrX.VectInit(Xk);

return(Xkp1);

}

//----------------------------------------------------------

//----------------------------------------------------------

//----------------------------------------------------------

//----------------------------------------------------------

//main function

int main(void)

{

double E=0.000001; //погрешность локализации минимума

VECTOR vectorPointer,vectorPointer1,vP(10,10);

cout<<"Lab7 Davidona-Fletchera-Pauella method";

do

{

vectorPointer1=SearchMin(vP);

K++;

vectorPointer.Grad(vectorPointer1);

cout<<endl<<endl<<"Iteration: "<<(K-1);

cout<<endl<<"Point : "<<(K-1);

vP.VectPrint();

cout<<endl<<"Point : "<<K;

vectorPointer1.VectPrint();

cout<<endl<<"Gradient: ";

vectorPointer.VectPrint();

printf("\nNorm of gradient: %.20f\n",vectorPointer.Norm());

getch();

if(vectorPointer.Norm()<=E)

{

cout<<endl<<endl<<"Minimum: ";

vectorPointer1.VectPrint();

cout<<endl<<endl;

break;

}

vP.VectInit(vectorPointer1);

}while(1);

getch();

return 0;

}

//----------------------------------------------------------

//----------------------------------------------------------

Соседние файлы в папке Всё стасовское новое