Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
1
Добавлен:
01.05.2014
Размер:
3.29 Кб
Скачать
#include <iostream.h>
#include <conio.h>
#include <math.h>
#include <stdio.h>

#define min(a,b) (((a)>(b))?(b):(a))// функция для определения минимума
#define max(a,b) (((a)<(b))?(b):(a))//функция для определения максимума

int i=1;
// структура для вектора
struct vect { 
			double x; //координата х
			double y; //координата у
			double norm() {return sqrt(x*x+y*y);} //норма вектора
   		 }; 


// возвращаем значение функции у от вектора х
double y(vect &x)
{
	return 8*x.x*x.x+4*x.x*x.y+5*x.y*x.y;
}


// заданная функция
double y(double x, double y)
{
	return 8*x*x+4*x*y+5*y*y;
}

//функция для прехода в новую точку
double f(double a, vect &x0, vect &p)
{
	vect x;
	x.x=x0.x+p.x*a;
	x.y=x0.y+p.y*a;
	return y(x);

}



//считаем длину вектора
double Length(vect &x1, vect &x2)
{
	
	return sqrt((x1.x-x2.x)*(x1.x-x2.x)+(x1.y-x2.y)*(x1.y-x2.y));
}

//считаем производную
double dy(double a, vect &x0, vect & p,double e=0.001)
{
	return (y(x0.x+p.x*(a+e),x0.y+p.y*(a+e))-y(x0.x+p.x*a,x0.y+p.y*a))/(p.norm()*e);
}

//считаем градиент
inline vect Grad(vect & point,double e=0.000001)
{
	vect px; px.x=point.x+e; px.y=point.y;
	vect py; py.x=point.x;py.y=point.y+e;
	vect res;
	res.x=(y(px)-y(point))/e;
	res.y=(y(py)-y(point))/e;
	return res;
}





// метод Свенна 4
void Swann4(double a0,vect &x0, vect & p, double &x1, double &x2)
{	double x=0;
	double dy1=dy(0,x0,p);// берем производную в начальной точке
	double a=min(2,fabs(2*(y(x0)-dy1)/dy1));
	if(dy1>0)//меняем направление
	  {a0=-a0;}
	while(dy(a0,x0,p)*dy1>0)// пока производная не поменяла знак
	{
		a0*=2;// удваиваем шаг
		x=x+a0;//запоминаем новую точку
	};
	//получаем интервал
	x1=min(x,x-a0*2);
	x2=max(x,x-a0*2);
}



// метод Дэвидона
vect Davidon(vect &x0, vect & p)
{	vect res;
	double e=0.001;// погрешность
	// устанавливаем интервал [a,b]
	double a,b;
	Swann4(0.001, x0,  p,a,b);
	double x1=0,x12=0, z=0, w=0,delta=0;
	do{
		z =dy(a,x0,p)+dy(b,x0,p)+3*(f(a,x0,p)-f(b,x0,p))/(b-a);
		w =sqrt(z*z-dy(a,x0,p)*dy(b,x0,p));
		delta =(z-dy(a,x0,p)+w)/(dy(b,x0,p)-dy(a,x0,p)+2*w);
		x12=x1;
        x1=a+delta*(b-a);
		//сокращаем текущий интервал локализации
		if(dy(x1,x0,p)>0) {b=x1;}
		else {a=x1;}	
	}while(fabs(dy(x1,x0,p))>e);
	res.x=x0.x+p.x*x1;
    res.y=x0.y+p.y*x1;
	return res;
}


//шаг метода Коши
vect KoshiStep(vect &x0)
{
	vect p=Grad(x0);//считаем градиент  точке
	//меняем на антиградиент
	p.x=-p.x;
	p.y=-p.y;
	vect x=Davidon(x0,p);//получаем оптимальный шаг
	return x;
}


//овражный метод
void Ovrag(vect &x1,double e=0.01,double e2=0.0001)
{
	vect x2;
	vect d;
	vect x3;
	int k=0;
	printf("\nОВРАЖНЫЙ МЕТОД:\n");
	printf("\nШаг,		  x1				 x1*				x3	\n");

	do
	{   //координаты вспомогательной точки
		x2.x=x1.x+e;
		x2.y=x1.y+e;
		x1=KoshiStep(x1);
		x2=KoshiStep(x2);
		//вычисляем направление ускорения
		d.x=x2.x-x1.x;
		d.y=x2.y-x1.y;
		x3=Davidon(x1,d);
		printf("%d\t [%f   %f]  \t[%f   %f]  \t[%f   %f]\n",i,x1.x,x1.y,x2.x,x2.y,x3.x,x3.y);
		if( k=(Length(x1,x3)>e2))
			x1=x3;
		i++;
	}
	while(k);
	x1=x3;

}


void main()
{
	vect x0={10,10};
	Ovrag(x0);
	printf("\nRESULT : x= [%f,%f] i=%d" ,x0.x,x0.y,i-1);
	getch();


}

Соседние файлы в папке Лабораторная работа №53