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

Цель работы

Изучение методов переменной метрики и разработка программы, удовлетворяющей требованиям лабораторной работы 5.

В программе использовать метод Пирсона-3.

Тестовые функции:

1) (x1x2x3 – 1)2 + 5[x3(x1 + x2) – 2]2 + 2(x1 + x2 + x3 – 3)2 , начальная точка (x1)t = (-1; -1; -1), истинный минимум (x*)t = (1; 1; 1);

2) 0.1(12 + x12 + (1 + x22)/x12 + (x12x22 + 100)/(x14x24)) , начальная точка (x1)t = (0.5; 0.5),

истинный минимум (x*)t = (1.743; 2.036);

Краткое описание метода оптимизации

Суть методов переменной метрики заключается в введении некоторой матрицы Ак , корректирующей направление поиска. (Рк = Акyк) Создается серия квазиньютоновских направлений pk (k=1,…,n), где n число переменных, минимизируемой функции. Доказано, что если функция квадратичная n-порядка, то минимум из любой точки Х1 отыскивается не более чем за n итераций. Для произвольных функций из-за накопления погрешности при вычислении градиента у матрицы А перестает выполняться условие положительной определенности, что вызывает искажение аппроксимации и вынуждает периодически через n шагов прибегать к процедуре рестарта.

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

Установить значение счетчика к=1;

Задать точность вычислений е=10-4 – 10-7

Задать начальную точку Х;

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

Шаг 1: Построить квазиньютоновское направление:

Для метода Пирсона-3:

Шаг 2: Найти αk, по направлению pk, как результат одномерной минимизации.

Шаг 3: Положить к=к+1 и перейти в новую точку xk+1= xk+ αk * pk

Шаг 4: Проверить критерий окончания поиска ||||<e;

Если выполняется, то минимум найден Хмин= Хк , иначе перейти на шаг 1.

Выводы

В результате проведения работы была создана программа, способная находить минимум функции с помощью метода Пирсона-3, а также были получены навыки объектно-ориентированного программирования на языке С++.

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

1. Выполнить 2 шага аналитического решения задачи Вашего варианта задания.

2. Сравнить методы переменной метрики.

Все методы переменной метрики отличаются только способом нахождения матрицы А.. Метод БФШ менее остальных нуждается в обновлении направлений.А для метода ДФП точность важна и по этому у необходимо вычислять как можно точнее, например сочетать методы Больцана и Давидона или методы золотого сечения и ДСК.

3. Какие алгоритмы линейного поиска рекомендуют для применения в программах, реализующих квазиньютоновские методы?

Рекомендуется сочетать успешно «стартующие» и хорошо «финиширующие» методы, например, методы Больцана и Давидона или методы золотого сечения и ДСК.

4. Как выбирается начальная матрица A1 в методе ДФП? Что такое процедура рестарта, зачем она нужна?

Матрица A1 – любая симметричная матрица >0, удобно выбирать матрицу Е. В дальнейшем матрицы А определяются с учетом предыдущих матриц до n-го шага. На n шагу необходимо проводить пересчет поискового направления и приравнивать матрицу А матрице Е. Это необходимо из-за накопления погрешности при вычислении у из-за чего перестает выполняться условие положительности матрицы А. В случае, если минимизируется квадратичная функция, процедура рестарта не нужна, так как минимум будет найден менее чем за n шагов.

Текст программы

#include "stdafx.h"

int c;

class Pirson

{

private: double eps;

double Xo[3];

double p[3];

double A[3][3];

double ag[3];

public: double Function (double);

void Init(double,double,double);

double DifFunction (double);

void AntiGradient ();

double Swenn4 (int);//TIL

double Bolcano (void);//min in direction

double Alpha (double, double);

void Pirson3 (void);

void Output();};

int main(int argc, char* argv[])

{

Pirson Obj;

c=1;

cout<<"\t\t\t Laboratory work #7"<<"\n"<<endl;

cout<<"\t\t\t Pearson's method #3"<<"\n"<<endl;

cout<<"Function1:0.1(12+x1^2+(1+x2^2)/x1^2+(x1^2*x2^2+100)/(x1^4*x2^4))"<<endl;

Obj.Init(0.5,0.5,0);Obj.Pirson3();Obj.Output();

cout<<"True minimum:(1.743;2.036)"<<endl;

c=2;

cout<<"\nFunction2:(x1x2x3 -1)^2+5[x3(x1+x2)-2]^2+2(x1+x2+x3-3)^2"<<endl;

Obj.Init(-1,-1,-1);Obj.Pirson3();Obj.Output();

cout<<"True minimum:(1;1;1)"<<endl;

cin.get();

return 0;

}

double Pirson::Function(double a)

{

double res;

double x[3]={Xo[0] + a*p[0], Xo[1] + a*p[1], Xo[2] + a*p[2]};

if(c==1)

res=0.1*(12+x[0]*x[0]+(1+x[1]*x[1])/(x[0]*x[0])+(x[0]*x[0]*x[1]*x[1]+100)/(x[0]*x[0]*x[0]*x[0]*x[1]*x[1]*x[1]*x[1]));

else

res=(x[0]*x[1]*x[2]-1)*(x[0]*x[1]*x[2]-1)+5*(x[2]*(x[0]+x[1])-2)*(x[2]*(x[0]+x[1])-2)+2*(x[0]+x[1]+x[2]-3)*(x[0]+x[1]+x[2]-3);

return(res);

}

void Pirson::Init(double x1, double x2, double x3)

{

eps = 0.00000001; Xo[0]=x1;Xo[1]=x2;Xo[2]=x3;

}

double Pirson::DifFunction(double x)

{

double res;

res = (Function(x+eps) - Function(x))/eps;

return(res);

}

double Pirson::Swenn4(int i)

{

double a = 0.0001,m,n,x=0;

if (DifFunction(x) > 0)

{

p[0]= -p[0];p[1]= -p[1];

}

do

{

a = 2*a;x += a;

}

while(DifFunction(x-a)*DifFunction(x)>0);

m = x-a; n = x;

if (i == 1)

return(m);

else

return(n);

}

double Pirson::Bolcano()

{

double x, K = 1, L, A, B;

A = Swenn4(1);

B = Swenn4(2);L = B - A;x = (A + B)/2;

while((fabs(DifFunction(x)) > eps) || (L > eps))

{

if (DifFunction(x) < 0)

A = x;

else

B = x;

L = B - A;x = (A + B)/2;K++;

}

return(x);

}

void Pirson::AntiGradient()

{

if(c==1)

{

p[0] = -(0.2/(Xo[0]*Xo[0]*Xo[0]*Xo[1]*Xo[1])-(0.4*(Xo[0]*Xo[0]*Xo[1]*Xo[1]+100))/(Xo[0]*Xo[0]*Xo[0]*Xo[0]*Xo[0]*Xo[1]*Xo[1]*Xo[1]*Xo[1])+0.2*Xo[0]-0.2*(1+Xo[1]*Xo[1])/(Xo[0]*Xo[0]*Xo[0]));

p[1] = -(0.2/(Xo[0]*Xo[0]*Xo[1]*Xo[1]*Xo[1])-(0.4*(Xo[0]*Xo[0]*Xo[1]*Xo[1]+100))/(Xo[0]*Xo[0]*Xo[0]*Xo[0]*Xo[1]*Xo[1]*Xo[1]*Xo[1]*Xo[1])+0.2*Xo[1]/(Xo[0]*Xo[0]));

}

else

{

p[0] = -(2*(Xo[0]*Xo[1]*Xo[2]-1)*Xo[1]*Xo[2]+10*(Xo[0]*Xo[2]+Xo[1]*Xo[2]-2)*Xo[2]+4*Xo[0]+4*Xo[1]+4*Xo[2]-12);

p[1] = -(2*(Xo[0]*Xo[1]*Xo[2]-1)*Xo[0]*Xo[2]+10*(Xo[0]*Xo[2]+Xo[1]*Xo[2]-2)*Xo[2]+4*Xo[0]+4*Xo[1]+4*Xo[2]-12);

p[2] = -(2*(Xo[0]*Xo[1]*Xo[2]-1)*Xo[0]*Xo[1]+10*(Xo[0]*Xo[2]+Xo[1]*Xo[2]-2)*(Xo[0]+Xo[1])+4*Xo[0]+4*Xo[1]+4*Xo[2]-12);

}

}

double Pirson::Alpha(double x,double y)

{

double res;

res = sqrt(x*x + y*y);

return(res);

}

void Pirson::Pirson3()

{

int i,j;

int k = 1;

double Min,gamma[3],s[3],x[3],xs[3];

for(i=0;i<3;i++)

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

{

if(i==j)

{

A[i][j]= -1;

}

else

{

A[i][j]=0;

}

}

for(i=0;i<3;i++)

x[i]=Xo[i];

do

{

AntiGradient();

for(i=0;i<3;i++)

ag[i] = p[i];

for(i=0;i<3;i++)

gamma[i]=gamma[i] - ag[i];

if(k==1||k==3||k==5)

{

for(i=0;i<2;i++)

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

if(i==j)

{

A[i][j] = 1;

}

else

{

A[i][j] = 0;

}

}

else

{

for(i=0;i<2;i++)

s[i]=A[i][0]*gamma[0]+A[i][1]*gamma[1];

for(i=0;i<3;i++)

xs[i]=x[i] - s[i];

for(i=0;i<2;i++)

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

A[i][j]=A[i][j]+xs[i]*s[j]/(s[0]*gamma[0]+s[1]*gamma[1]);

for(i=0;i<2;i++)

p[i] = A[i][0]*ag[0]+A[i][1]*ag[1];

}

for(i=0;i<3;i++)

gamma[i]=ag[i];

for(i=0;i<2;i++)

x[i]=Xo[i];

Min=Bolcano();

Xo[0] += Min*p[0]; Xo[1] += Min*p[1]; Xo[2] += Min*p[2];

for(i=0;i<2;i++)

x[i]=Xo[i] - x[i];

k++;

}

while (Alpha (x[0], x[1]) > eps && Alpha (ag[0],ag[1]) > eps);

}

void Pirson::Output()

{

if(c==1)

cout<<"Min=("<<Xo[0]<<","<<Xo[1]<<")"<<endl;

else

cout<<"Min=("<<Xo[0]<<","<<Xo[1]<<","<<Xo[2]<<")"<<endl;

}

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

Входные данные: начальная точка, погрешность,исходная функция.

Выходные данные: значение минимума.

Спецификация функций программы.

double Function(double) –возвращает значение функции.

double DifFunction(double) – вычисление значения производной в точке.

double Swenn(int) – нахождение ТИЛ.

double Boltsano() – нахождение минимума в заданном напрвлении.

void AntiGradient() – вычисление антиградиента.

double Alpha(double, double) – вычисление нормы вектора.

void Pirson3() – реализация метода Пирсон-3.

void Init(double,double,double) – инициализация.

void Output() – вывод минимума.

Результат выполнения программы.

Схема алгоритма Пирсон-3