- •2005 Содержание:
- •1) Цель работы и требования задания
- •1.1) Цель работы
- •2) Краткое описание метода оптимизации
- •2.1) Обобщенный метод Ньютона
- •2.2) Метод Давидона:
- •3.1) Метод Давидона:
- •3.2) Обобщенный метод Ньютона:
- •4) Спецификация программы
- •5) Текст программы
- •6) Результаты тестирования программы
- •7) Ответы на контрольные вопросы
- •8) Выводы по работе
5) Текст программы
//Obobshenniy Method Nutona
#include <iostream.h>
#include <math.h>
#include <stdio.h>
#include "point1.h"
Point fabs(const Point&); //fabs: x[]=fabs(x[])
double f(const Point&); //prototype function f(x1,x2)
double dfdp(const Point&,const Point&); //derivative in the direction #2
Point df(const Point&); //derivative of f(x[])
double dfitd(const Point&,const Point&); //derivative in the direction
double min(double,double); //prototype of function min(x,y)
double SegmentLength(const Point&,const Point&); //length of segment x0(x0[0],x0[1]),x1(x1[0],x1[1])
void Svenn4(double,const Point&,const Point&,double,Point&,Point&); //Method Svenn-4
double FindAlpha(const Point&,const Point&,double); //find alpha of Davidon's method
bool KOP(const Point&,double); //KOP for Koshi method
Point ON(double[],double); //Coshi method
const int k=3;
main()
{
cout << "Laboratory work #6\nVariant 1\nObobshennii metod N'utona\n\n";
cout << endl;
double xk[3]={4,-1,-2}; //start point xk
double x_min[3]={1,3,-5}; //really minimum of f(x1,x2)
double eps=0.0001; //accuracy (epsilon)
Point answer(k);
answer=ON(xk,eps);
cout << "Minimum finded ON method:\n";
answer.printPointEx("Coordinates");
answer.Inaccuracy(x_min);
cout << "\nPress any key for exit..." << endl;
getchar();
return 0;
}
/////////////////////////////fabs/////////////////////////////////
Point fabs (const Point &A)
{
Point At=A;
Point result(k);
int i=0;
while (i<k)
{
result[i]=fabs(At[i]);
i++;
}
return result;
}
////////////////////////////f(x1,x2)//////////////////////////////
double f(const Point &p)
{
Point pt=p;
return (pt[0]-1)*(pt[0]-1)+(pt[1]-3)*(pt[1]-3)+4*(pt[2]+5)*(pt[2]+5);
}
///////////////derivative in the direction#2//////////////////////
double dfdp(const Point &x, const Point &p)
{
double alpha=0.000001;
Point x1=x;
Point p1=p;
x1=x1+p1*alpha;
Point x2=x;
x2=x2+p1*(-alpha);
return (f(x1)-f(x2))/(2*alpha);
}
/////////////////////derivative of f(x[])////////////////////////
Point df(const Point &x)
{
Point ans(k);
double alpha=0.000001;
Point x1(k);
Point x2(k);
double tmp_ans = 0;
int i=0;
while (i<k)
{
x1=x;
x2=x;
x1[i]=x1[i]+alpha; //ans.x1=(f(x[0]+alpha,x[1])-f(x[0]-alpha,x[1]))/(2*alpha);
x2[i]=x2[i]-alpha; //ans.x2=(f(x[0],x[1]+alpha)-f(x[0],x[1]-alpha))/(2*alpha);
ans[i]=(f(x1)-f(x2))/(2*alpha);
i++;
}
return ans;
}
///////////////////////derivative in the direction////////////////////////////
double dfitd(const Point &x, const Point &p)
{
Point dy=df(x);
Point pt=p;
double ans=0;
int i=0;
while (i<k)
{
ans=ans+dy[i]*pt[i];
i++;
}
return ans;
}
///////////////////////////function min(x,y)//////////////////////////////////
double min(double x, double y)
{
if (x < y)
return x;
else
return y;
}
/////////////////////////////SegmentLength////////////////////////////////////
double SegmentLength(const Point &x,const Point &y)
{
Point xt=x;
Point yt=y;
double ans=0;
int i=0;
while (i<k)
{
ans=ans+pow(xt[i]-yt[i],2);
i++;
}
if ((yt[0]-xt[0])>0)
return sqrt(ans);
else
return -sqrt(ans);
}
////////////////////////////////////Svenn-4//////////////////////////////////////////////
void Svenn4(double dy1,const Point &pk1,const Point &xk1,double ak,Point &xa,Point &xb)
{
//Svenn-4:
Point xk=xk1;
Point pk=pk1;
Point x_prev=xk;
//Step 1:
if (dy1 > 0)
{
pk = -pk;
};
//Step 2:
while (dfitd(x_prev,pk)*dfitd(xk,pk) > 0)
{
x_prev = xk;
xk = xk + pk*ak;
ak = ak*2;
}
//Step 3:
Point x_a(k);
Point x_b(k);
if (dy1 > 0)
{
x_a = xk;
x_b = x_prev;
}
else
{
x_a = x_prev;
x_b = xk;
};
//cout << "Intervals finded of Svenn-4 method:" << endl;
// x_a.printPoint();
// x_b.printPoint();
//end of Svenn-4;
xa = x_a;
xb = x_b;
}
/////////////////////////Davidon's method//////////////////////////////
double FindAlpha(const Point &pk1,const Point &xk1,double eps)
{
//Davidon method:
//Initial Stage:
Point xk=xk1;
Point pk=pk1;
pk.Norming();
double dy1=dfdp(xk,pk);
double nju=1;
double ak=min(nju,fabs(2*(f(xk)-dy1)/dy1));
//cout << ak <<endl;
Point xa(k);
Point xb(k);
Svenn4(dy1,pk,xk,ak,xb,xa);
//Basic Stage:
//Step I:
double dya=dfdp(xa,pk);
double dyb=dfdp(xb,pk);
double z=dya+dyb+3*(f(xb)-f(xa))/SegmentLength(xb,xa);
double W=sqrt(z*z-dya*dyb);
double al_r=ak*((W-dyb+z)/(2*W-dyb+dya)); //approximation step
double sum_al_r=al_r;
Point r(k); //approximation minimum:
r = xk;
r = r + pk*al_r;
//Step II:
while ((fabs(dfdp(r,pk))>eps) && (fabs(SegmentLength(xa,r))>eps) && (fabs(SegmentLength(r,xb))>eps))
{
if (dfdp(r,pk)>0)
{
xa = r;
ak = al_r;
}
else
{
xb = r;
ak = ak-al_r;
}
dya=dfdp(xa,pk);
dyb=dfdp(xb,pk);
z=dya+dyb+3*(f(xb)-f(xa))/SegmentLength(xb,xa);
W=sqrt(z*z-dya*dyb);
al_r=ak*((W-dyb+z)/(2*W-dyb+dya)); //approximation step
//approximation minimum:
r = xb;
r = r + pk*al_r;
}
return al_r;
}
////////////////////////////KOP////////////////////////////////////////
bool KOP(const Point &x,double epsilon)
{
bool stop=false;
Point temp(k);
temp=df(x);
if (temp.norma()<epsilon)
{
stop=true;
}
return stop;
}
/////////////////////////ON_method///////////////////////////////////
Point ON(double *xk1,double eps)
{
//Initial Stage:
Point xk(k);
xk.setPoint(xk1);
int count=1;
int M=100;
//Basic Stage:
//Step I:
double H1[3][3] = {{0.5, 0,0},{0,0.5,0},{0,0,0.125}}; //obratnaya = Gesse^(-1)
Point dy = df(xk);
Point pk(k);
pk[0]=-(H1[0][0]*dy[0]+H1[0][1]*dy[1]+H1[0][2]*dy[2]);
pk[1]=-(H1[1][0]*dy[0]+H1[1][1]*dy[1]+H1[1][2]*dy[2]);
pk[2]=-(H1[2][0]*dy[0]+H1[2][1]*dy[1]+H1[2][2]*dy[2]);
//pk.printPoint();
//getchar();
//Step II:
double alpha;
cout << "Please input alpha: " << endl;
cin >> alpha;
xk = xk + pk*alpha;
count++;
while ((KOP(xk,eps)==false) && (count < M))
{
dy = df(xk);
pk[0]=-(H1[0][0]*dy[0]+H1[0][1]*dy[1]+H1[0][2]*dy[2]);
pk[1]=-(H1[1][0]*dy[0]+H1[1][1]*dy[1]+H1[1][2]*dy[2]);
pk[2]=-(H1[2][0]*dy[0]+H1[2][1]*dy[1]+H1[2][2]*dy[2]);
alpha = FindAlpha(pk,xk,0.001);
xk = xk + pk*alpha;
xk.printPointEx("TmpCoordinates");
count++;
}
cout << "ON iteration counts: "<< count <<endl;
return xk;
}
/////////////////////////////////////////////////////////////////////