Скачиваний:
15
Добавлен:
01.05.2014
Размер:
25.29 Кб
Скачать
#include <conio.h>
#include <stdio.h>
#include <iostream.h>
#include <math.h>
#include <stdlib.h>


//---------------------------------------
// Вспомогательные функции
//---------------------------------------

void SWAP (double &,double&);
double funct(double, double *, double *);	//вычисляет значение функции
double fproizv(double, double *, double *);	//вычисляет значение производной
double fd1(double, double);					//значение частной производной по x1
double fd2(double, double);					//значение частной производной по x2
void newgrad(double *,double &, double &);	//находим новое направление
double Alpha(double *,double *);			//поиск альфа(удлинения вектора)
double Fib(double);							//находит число фибона
double norma(double,double);				//считает норму
double betta1 (double *p1, double *p2);		//считаем значение бетта1 (метод дениела)
double betta2 (double *p1, double *p2);		//считаем значение бетта2 (метод дениела)

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

void SWENN();								//Метод Свенна
void ZS_1(double, double);					//Метод золотого сечения 1
void ZS_2(double, double);					//Метод золотого сечения 2
void DETOH(double, double);					//Метод Детохомии
void PAUELL(double, double);				//Метод Пуэлл
void BOLCANO(double, double);				//Метод Больцано
void KOSHI(double, double);					//Метод Коши
void FLETCHER_RIVES(double, double);		//Метод Флетчера-Ривса
void PARALLEL(double, double);				//Метод Параллельных Касательных
void FIBONACHI1(double, double);			//Метод Фибоначчи 1
void FIBONACHI2(double, double);			//Метод Фибоначчи 2
void GAUSS_ZEIDEL(double, double);			//Метод Гайса-Зейделя
void CPS(double, double);					//Метод Цикличесского покординатного спуска
void DANIEL(double, double);				//Метод Даниела





//-------------------------------------
//Глобальные переменные
//-------------------------------------

	double funct(double ,double*, double*); //значение функции
	
	double napr[2];		//начальное направление
	double nach[2];		//начальные точки
	double eps;			//задаем точность
	double h;			//размер шага
    double a;			//точка для поиска минимума
    double b;			//точка для поиска минимума
	double L,L1;		//точка размеров L
	double lam;			//точка точек Лямда
	double mu;			//точка Мю
	double an;			//для запоминание точки а
	double bn;			//для запоминание точки b
	double X;			//Точка минимума
	double X1[2];
	double alpha;



//---------------------------------------
// Метод Свенна
//---------------------------------------
void SWENN()	//свенн
{
	a=nach[0];
	h=0.01*a; //стартовый размер шага
	b=a+h; 

	if (funct(b,nach,napr) > funct(a,nach,napr)) //если значение в X2> чем 
		{h=-h;					//в X1 тогда изменяем
	};								//направление поиска

	do {
		a=b;
		h=2*h;				//удваиваем размер шага
		b=a+h;			//находим след-ую точку
	}								//пока не найдем изменение
	while (funct(b,nach,napr)<funct(a,nach,napr));//поведения функции
	a=a-h;		//точки найденные по свенну
				//b=b;
	SWAP(a,b);
	};



//---------------------------------------
// Функция перемены местами переменных
//---------------------------------------

void SWAP(double &a,double &b){
	if (b<a) {			//если б>a то меняем
		double temp;	//местами
		temp=b;
		b=a;
		a=temp;
	};
};

//-----------------------------------------
// Процедура возвращающая значение функции
//-----------------------------------------


double funct(double x,double *nach,double *napr)
{
	double x1=nach[0]+x*napr[0];	//X1
	double x2=nach[1]+x*napr[1];	//X2
	return (x1*x1 + 3*x2*x2 + 2*x1*x2);
	//return pow((x1*x1 + x2 - 11),2) + pow((x1 + x2*x2 - 7),2);
	//return 100*pow(x2 - x1*x1,2) + pow((1 - x1),2);
	return (x1*x1 + 3*x2*x2 + 2*x1*x2);
	//функция x1^2+3*x2^2+2*x1*x2
};

//---------------------------------------
// Функция которая ищет Альфу(лаб.р.# 3)
//---------------------------------------


double Alpha(double *x,double *p)		//альфа
{
	double centr;	//вспомогательня точка
	double zbeta;	//вспомогательня точка
//Выполняется алгоритм свенна	
	a=x[0];
	h=0.01*a; //стартовый размер шага
	b=a+h; 

	if (funct(b,nach,napr) > funct(a,nach,napr)) //если значение в X2> чем 
		{h=-h;					//в X1 тогда изменяем
	};								//направление поиска

	do {
		a=b;
		h=2*h;				//удваиваем размер шага
		b=a+h;			//находим след-ую точку
	}								//пока не найдем изменение
	while (funct(b,nach,napr)<funct(a,nach,napr));//поведения функции
	a=a-h;		//точки найденные по свенну
				//b=b;
	SWAP(a,b);
//продолжается поиск методом детохомии на основе данных Свенна	
	
	zbeta = 0.1*eps;
	do
		{
			centr = (b-a)/2 + a;
			lam = centr - zbeta/2;
			mu = centr + zbeta/2;
			if (funct(a,nach,napr)<funct(b,nach,napr))
			{
				b=mu;
				a=a;
			}
			else 
			{
				a=lam;
				b=b;
			}
		}
	while ((fabs(b-a))>eps);
	return (b+a)/2; //возвращаем Альфу.
};

//---------------------------------------
// Функция нахождения нормы
//---------------------------------------

double norma(double x1,double x2)
{
   return sqrt(x1*x1+x2*x2);					//возвращаем корень из суммы квадратов
};

//---------------------------------------
// Функция нахождения производной
//---------------------------------------

double fproizv(double x,double *nach,double *napr)	//считаемпроизводную
{
	double g1, g2,z1,z2,h1,h2;
	double zz[2];
	double zzz[2];
	
	z1=nach[0]+x*napr[0];
	z2=nach[1]+x*napr[1];
	if ((0.001*z1)>0.0000001)
		h1=0.001*z1;
	else
		h1=0.0000001;
	if ((0.001*z2)>0.0000001)
		h2=0.001*z2;
	else
		h2=0.0000001;
	
	zz[0]=z1+h1;
	zz[1]=z2;
	zzz[0]=z1-h1;
	zzz[1]=z2;
	g1=((funct(0,zz,napr)-funct(0,zzz,napr))/(2*h1)); //формулой центральной		
	zz[0]=z1;
	zz[1]=z2+h2;
	zzz[0]=z1;
	zzz[1]=z2-h2;
	g2=((funct(0,zz,napr)-funct(0,zzz,napr))/(2*h2)); //формулой центральной
	return g1*napr[0]+g2*napr[1];
};
	
	

//---------------------------------------
//Нахождение частной производной 1
//---------------------------------------

double fd1(double x1,double x2){ 
return 2*x1+2*x2;
};

//---------------------------------------
//Нахождение частной производной 2
//---------------------------------------

double fd2(double x1,double x2){ 
return 6*x2+2*x1;
};


//---------------------------------------
//Вычисляем новое направление
//---------------------------------------

void newgrad(double *x,double &napr1,double &napr2)		//ищем новое направление
{
	double h1,h2;
	double zz[2];
	double zzz[2];
	
	if ((0.001*x[0])>0.0000001)
		h1=0.001*x[0];
	else
		h1=0.0000001;
	if ((0.001*x[1])>0.0000001)
		h2=0.001*x[1];
	else
		h2=0.0000001;
	
	zz[0]=x[0]+h1;
	zz[1]=x[1];
	zzz[0]=x[0]-h1;
	zzz[1]=x[1];
	napr1=((funct(0,zz,napr)-funct(0,zzz,napr))/(2*h1)); //формулой центральной		
	zz[0]=x[0];
	zz[1]=x[1]+h2;
	zzz[0]=x[0];
	zzz[1]=x[1]-h2;
	napr2=((funct(0,zz,napr)-funct(0,zzz,napr))/(2*h2)); //формулой центральной
	
};

//--------------------------------------
// Поиск числа Фибоначчи
//--------------------------------------
double Fib(double x)			// номер числа
{
   double s,		// итоговое число
		tmp;				// временная переменная

   if(x>=1)				// проверяем условие существования числа
   {
      s=1;				// сумма = 1
      tmp=0;			// обнуляем временныю переменную
      
		for(double k=0; k<x; k++)
      {						
			s=s+tmp;			// нахождения числа Фибоначчи
			tmp = s-tmp;	// осуществляем поиск
      }
      return s;		// возвращаем результат
   }
   else
      return 1;		// если индекс меньше 1, возвращаем 1
};

//--------------------------------------
// Нахождение бетта 1
//--------------------------------------

double betta1 (double *p1, double *p2)
{
	double g[2],b[2];
		g[0]=p2[0]-p1[0];
		g[1]=p2[1]-p1[1];
		b[0]=p2[0]*g[0]+p2[1]*g[1];
		b[1]=p1[0]*g[0]+p1[1]*g[1];
	return (b[0]/b[1]);
}

//--------------------------------------
// Нахождение бетта 2
//--------------------------------------

double betta2 (double *p1, double *p2)
{
	double g[2],b[2];
	g[0]=p2[0]-p1[0];
	g[1]=p2[1]-p1[1];
	b[0]=p2[0]*g[0]+p2[1]*g[1];
	b[1]=p1[0]*p1[0]+p1[1]*p1[1];
	return (b[0]/b[1]);
}


//-------------------------------------
//ЗОЛОТОЕ СЕЧЕНИЕ 1
//-------------------------------------


void ZS_1(double z1, double z2) 
{	nach[0]=z1;		//задем точки
	nach[1]=z2;
	napr[0]=1;		//направление
	napr[1]=2;
	eps=0.001;
	SWENN();
	L=(fabs(b-a));		//находим Ln
	lam=a+0.382*L;	//получаем точки
	mu=a+0.618*L;	//Лямда и Мю
	//
	do {
		L1=(fabs(b-a));
		if ((funct(lam,nach,napr)<funct(mu,nach,napr))) { //находим точку где значение минимально
			
			b=mu;			//сужаем интервал ближе к найденному минимуму
			mu=lam;			//находим новые Лямду,L и Мю
			L=(fabs(b-a));
			lam=a+0.382*L;
		} else {
		    a=lam;			//сужаем интервал ближе к найденному минимуму
   			lam=mu;			//находим новые Лямду,L и Мю
			L=(fabs(b-a));
			mu=a+0.618*L;
		};
	}
	while (L1>eps); //ппока интервал поиска > погрешности
	double X=((a+b)/2);	//апроксимирующий минимум
	cout <<"ZS_1"<<"   ";
	cout <<nach[0]+X*napr[0]<<"   ";		//вывод апроксимирующего минимума
	cout <<nach[1]+X*napr[1]<<endl<<endl;		//вывод апроксимирующего минимума

};
	  

//-------------------------------------
//ЗОЛОТОЕ СЕЧЕНИЕ 2
//-------------------------------------



void ZS_2(double z1, double z2) 
{	nach[0]=z1;
	nach[1]=z2;
	napr[0]=1;
	napr[1]=2;
	eps=0.001;
	SWENN();		//оптимизируем
	do
	{
		L=(fabs(b-a));		//устанавливаем модуль
		lam=a+0.618*L;		
		mu=a+b-lam;

		if ((funct(lam,nach,napr)<funct(mu,nach,napr))&&(lam<mu))
			{
			b=mu;
			}
		if ((funct(lam,nach,napr)>=funct(mu,nach,napr))&&(lam<mu))
			{
			a=lam;
			}

		if ((funct(lam,nach,napr)<funct(mu,nach,napr))&&(lam>mu))
			{
			a=mu;
			mu=lam;
			}

		if ((funct(lam,nach,napr)>=funct(mu,nach,napr))&&(lam>mu))
			{
			b=lam;
			lam=mu;
			}


	}while ((fabs(b-a))>eps);	//КОП

	X=(a+b)/2;
	cout <<"ZS_2"<<"   ";
	cout <<nach[0]+X*napr[0]<<"   ";		//выводим минимум
	cout <<nach[1]+X*napr[1]<<endl<<endl;
};


//----------------------
//Метод Детохомии
//----------------------

void DETOH(double z1, double z2) 
{	
	double centr;		//центральная точка
	double beta;		//отступ
    
	int M=0;		//ограничиваем число операций
	nach[0]=z1;
	nach[1]=z2;
	napr[0]=1;
	napr[1]=2;
	eps=0.0001;
	SWENN();	//опетимизируем
	beta = 0.1*eps;	//считаемотступ
	do
		{	M++;
			centr = (b-a)/2 + a;		//точку внутри отрезка
			lam = centr - beta/2;
			mu = centr + beta/2;
			if (funct(a,nach,napr)<funct(b,nach,napr))	//выполняем поиск
			{
				b=mu;
				a=a;
			}
			else 
			{
				a=lam;
				b=b;
			}
		}
		
	while ((fabs(b-a))>eps &&(M<200));		//КОП

	X=(b+a)/2;	//минимум найден
	cout <<"DETOH"<<"   ";
	cout <<nach[0]+X*napr[0]<<"   ";		//выводим
	cout <<nach[1]+X*napr[1]<<endl<<endl;

};



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

void PAUELL(double z1, double z2) 
{
	double c;
	double eps1;		//погрешность 1
	double eps2;		//погрешность 2
	double d;			//вспомогат точка
	int M=0;
	nach[0]=z1;
	nach[1]=z2;
	napr[0]=1;
	napr[1]=2;
	eps1=0.001;
	eps2=0.001;
	SWENN();

	bool First=true;
  	do 
	{	M++;
		c=b;
		b=(a+c)/2;
		if (First)		// если первая итерация.
		{
			d=((funct(a,nach,napr)*(b*b-c*c)+
			funct(b,nach,napr)*(c*c-a*a)+
  			funct(c,nach,napr)*(a*a-b*b))/
			(2*(funct(a,nach,napr)*(b-c)+
			funct(b,nach,napr)*(c-a)+
			funct(c,nach,napr)*(a-b)
			)));
		}
		else //иначе
		{
		  	 d=0.5*(a+b)+0.5*((funct(a,nach,napr)-funct(b,nach,napr))*(b-c)*(c-a))
			 /(funct(a,nach,napr)*(b-c)+funct(b,nach,napr)*(c-a)+funct(c,nach,napr)*(a-b));
		};
			
		if ((funct(b,nach,napr)<funct(d,nach,napr))&&(b<d))
		{
			  a=a;
			  c=d;
			  b=b;
		};
		if ((funct(b,nach,napr)<funct(d,nach,napr))&&(b>d))
		{
			  a=d;
			  c=c;
			  b=b;
		};
		if ((funct(b,nach,napr)>funct(d,nach,napr))&&(b<d))
		{
			  a=b;
			  c=c;
			  b=d;
		};
		if ((funct(b,nach,napr)>funct(d,nach,napr))&&(b>d))
		{
			  a=a;
			  c=b;
			  b=d;
		};
		First=false;
		}
		while ((((fabs(d)-fabs(b))/fabs(b))>=eps1) &&		//КОП
		(((fabs(funct(d,nach,napr))-fabs(funct(b,nach,napr))))
		/fabs(funct(b,nach,napr)))>=eps2 && (M<200));
		
		X=(b+d)/2;
		cout <<"PAUELL"<<"   ";
		cout <<nach[0]+X*napr[0]<<"   ";
		cout <<nach[1]+X*napr[1]<<endl<<endl;
};

//-------------------------------------
//Метод Больцано
//-------------------------------------

void BOLCANO(double z1, double z2) 
{		
	double x;
	double x1;
	double x2;
	double z;
	double w;
	double y;

	int M=0;
	nach[0]=z1;
	nach[1]=z2;
	napr[0]=1;
	napr[1]=2;
	eps=0.001;
	SWENN();
	x=a;
	h=0.001;
	eps=0.1;

	if (fproizv(x,nach,napr)>=0)		//устанавливаем направление поиска
		{
		h=-h;
		}
	int i=0;
	do 
		{i++;
		if (i<5) 
		{
			h=h*2;
		} else
		{
			h=0.002;
		};
		x=x+h;
		}
	while((fproizv(x,nach,napr)*fproizv(x+h,nach,napr))>=0);	//где меняет знак
	x1=x;  //x1 =X(m-1)
	x2=x+h;  //Xm

	if (x1>x2) 
		{
		a=x2;
		b=x1;
		}
	else 
		{
		a=x1;
		b=x2;
		};
	do //находим лучшую из точек
		{
		z=(fproizv(a,nach,napr)+fproizv(b,nach,napr)+3*(funct(a,nach,napr)-funct(b,nach,napr)))/b;
		w=sqrt(z*z-fproizv(a,nach,napr)*fproizv(b,nach,napr));
		y=(z+w-fproizv(a,nach,napr))/(fproizv(b,nach,napr)-fproizv(a,nach,napr)+2*w);
		if (y<0) 
			{
			x=a;
			};
		if (y>1) 
			{
			x=b;
			};
		if ((y>=0)&&(y<=1))
			{
			x=a+y*(b-a);
			};
			M++; //счетчик шагов
		if (fproizv(x,nach,napr)>0)			//сужаем интервал
			{
			a=a;
			b=x;
			}
		else
			{
			a=x;
			b=b;
			};
	} while ((fabs(fproizv(x,nach,napr)))>eps && (M<200));
	X=(a+b)/2;
		cout <<"BOCANO"<<"   ";
	cout <<nach[0]+X*napr[0]<<"   ";		//выводим минимум
	cout <<nach[1]+X*napr[1]<<endl<<endl;
};


//---------------------------------------
//Метод Коши
//---------------------------------------


void KOSHI(double z1, double z2) //метод Коши
{
	int M=0;
	nach[0]=z1;
	nach[1]=z2;
	napr[0]=1;
	napr[1]=1;
	
	eps=0.001;
	
	newgrad(nach,napr[0],napr[1]);
	napr[0]=-napr[0];
	napr[1]=-napr[1];
	do
	{
		napr[0]=napr[0]/norma(napr[0],napr[1]);
		napr[1]=napr[1]/norma(napr[0],napr[1]);
		alpha=Alpha(nach,napr);	//ищем Альфу
		nach[0]=nach[0]+alpha*napr[0];//смещаемся
		nach[1]=nach[1]+alpha*napr[1];
		newgrad(nach,napr[0],napr[1]);		//новое направление
		napr[0]=-napr[0];
		napr[1]=-napr[1];

		M++;		//счетчик итерации
		
	}
	while ((norma(napr[0],napr[1])>eps) && (M<200)); //КОП

	

	cout <<"KOSHI"<<"   ";
	cout <<nach[0]<<"   ";		//вывод минимума
	cout <<nach[1]<<endl<<endl;

};


//----------------------------------
// Метод Фибоначи-1
//----------------------------------
void FIBONACHI1(double z1,double z2)
{	

	double n,k=0;

	nach[0]=z1;		//нач точки
	nach[1]=z2;		
	napr[0]=1;
	napr[1]=2;		//нач направление
	eps=0.001;
	
	double L=0.01*eps;			// задаем длину конечного интервала
    n=0;					// порядковый номер числа Фибоначчи
	SWENN();
    while(Fib(n)<(b-a)/L)	// определяем этот номер в  
		n++;						// соответствии с алгоритмом

    lam=a+(Fib(n-2)*(b-a))/(Fib(n));	// первая начальная точка
    mu=a+(Fib(n-1)*(b-a))/(Fib(n));	// вторая начальная точка

    while(k<n-1)				// сокращаем ТИЛ в соответствии с методом
    {
		if(funct(lam,nach,napr)<funct(mu,nach,napr))
		{
			b=mu;
			mu=lam;
			lam=a+(Fib(n-k-2)*(b-a))/Fib(n-k);
		}
		else
		{
			a=lam;
			lam=mu;
			mu=a+(Fib(n-k-1)*(b-a))/Fib(n-k);
		}
		 k++;						// увеличиваем счётчик итераций
	}

	if(funct(lam,nach,napr)<=funct(mu,nach,napr))	// рассматриваем 2 возможные ситуации,
		X=(a+mu)/2;			// вычисляем результирующее значение и
	else							// изменяем значение коэффициента
		X=(lam+b)/2;			// удлинения вектора

	cout <<"FIBONACHHI1"<<"   ";
	cout <<nach[0]+X*napr[0]<<"   ";		//выводим на экран
	cout <<nach[1]+X*napr[1]<<endl<<endl;
};


//--------------------------------------------------------------------
// Метод Фибоначи-2
//--------------------------------------------------------------------
void FIBONACHI2(double z1,double z2)
{	
	double n=0;			// порядковый номер числа Фибоначчи
	double k=0;
	nach[0]=z1;
	nach[1]=z2;
	napr[0]=1;
	napr[1]=2;
	eps=0.001;
   
	double Ln = 0.01*eps;		// задаём длину конечного интервала
	double x1, x2;			// задаём необходимые переменные
	SWENN();    
	while(Fib(n)<(b-a)/Ln)	// определяем этот номер в 
    n++;						// соответствии с алгоритмом

	x1=a+Fib(n-1)*(b-a)/Fib(n)+pow((-1),n)*eps/Fib(n);	// первая начальная точка

	while(k<n)							// сокращаем ТИЛ в соответствии с методом
    {
		x2 = a+b-x1;					// вторая точка
        if(funct(x1,nach,napr)<funct(x2,nach,napr))		// Сокращаем текущий интервал
		{									// локализации рассмотрением
			if(x1<x2)					// 4-х ситуаций, аналогично
				b=x2;						// методу золотого сечения-2
			else
				a=x2;
		}
		else
		{
			if(x1<x2)
				a=x1;
			else
				b=x1;
			x1=x2;
		};
		k++;					// увеличиваем счётчик итераций
    };
    X=x2;				// изменяем значение коэффициента удлинения вектора
	cout <<"FIBONACHI2"<<"   ";
	cout <<nach[0]+X*napr[0]<<"   ";
	cout <<nach[1]+X*napr[1]<<endl<<endl;


};


//---------------------------------------
// Метод параллельных касательных
//---------------------------------------
	

void PARALLEL(double z1, double z2)
{
	double x[2];			// начальная точка
	double x0[2]={0};			// начальная точка
	double x2[2]={0};			// начальная точка
	double d[2]={0};			//удлинение вектора
	

	int M=0;
	x[0]=z1;
	x[1]=z2;
	nach[0]=1;
	nach[1]=1;
	napr[0]=1;
	napr[1]=2;
	eps=0.001;
	x0[0]=x[0];				// начальная точка
	x0[1]=x[1];				// начальная точка
	

	// переопределяем массив значений х
	// при пошаговом поиске и задаём
	// значение начальной точки
	do
	{
		alpha=Alpha(x,napr);
		newgrad(x,napr[0],napr[1]);
		
		napr[0]=-napr[0];
		napr[1]=-napr[1];
		
		napr[0]=napr[0]/norma(napr[0],napr[1]);
		napr[1]=napr[1]/norma(napr[0],napr[1]);
		x[0] = x[0]+alpha*napr[0];					// спускаемся в точку х2
		x[1] = x[1]+alpha*napr[1];					// спускаемся в точку х2
		x2[0] = x[0];								// сохраняем точку х2
		x2[1] = x[1];								// сохраняем точку х2
		newgrad(x,napr[0],napr[1]);					// устанавливаем антградиентное направление
		
		napr[0]=-napr[0];
		napr[1]=-napr[1];
		
		napr[0]=napr[0]/norma(napr[0],napr[1]);
		napr[1]=napr[1]/norma(napr[0],napr[1]);
		alpha=Alpha(x,napr);						// находим коэффициент удлинения вектора
		x[0] = x[0]+alpha*napr[0];					// спускаемся в точку х3
		x[1] = x[1]+alpha*napr[1];					// спускаемся в точку х3
		d[0] = x[0]-x0[0];							// определяем ускоряющее направление
		d[1] = x[1]-x0[1];							// определяем ускоряющее направление
		alpha=Alpha(x,napr);						// находим коэффициент удлинения вектора
		x[0] = x[0]+alpha*d[0];						// спускаемся в точку х4
		x[1] = x[1]+alpha*d[1];						// спускаемся в точку х4
		x0[0] = x2[0];								// если КОП не выполняется, то х2 - новая начальная точка
		x0[1] = x2[1];		
		M++;											// если КОП не выполняется, то х2 - новая начальная точка
	}
	while ((norma(d[0],d[1])>eps) && (norma(napr[0],napr[0])>eps) && (M<200)); //КОП

	cout <<"Parallel"<<"   ";
	cout <<x[0]<<"   ";
	cout <<x[1]<<endl<<endl;		//вывод минимума
};




//----------------------------------------
// Метод Гаусса-Зейделя
//----------------------------------------

void GAUSS_ZEIDEL(double z1,double z2){
	double X1[2];			//	предыдущее значение
	double xn[2];			//	предыдущее значение
	double d[2];		// ускоряющее направление
	nach[0]=z1;
	nach[1]=z2;
	napr[0]=1;
	napr[1]=2;
	int M=0;
	eps=0.001;
	X1[0] = nach[0];			// сохраняем точку
	X1[1] = nach[1];
	
	do
	{
		alpha=0;
		newgrad(nach,napr[0],napr[1]);
		napr[0]=-napr[0];
		napr[1]=-napr[1];
		napr[0]=napr[0]/norma(napr[0],napr[1]);
		napr[1]=napr[1]/norma(napr[0],napr[1]);
		napr[0] = napr[0]*1;
		napr[1] = napr[1]*0;
		alpha=Alpha(X1,napr);
		xn[0]=X1[0]+alpha*napr[0];
		xn[1]=X1[1]+alpha*napr[1];
		alpha=0;
		newgrad(X1,napr[0],napr[1]);
		napr[0]=-napr[0];
		napr[1]=-napr[1];
		napr[0]=napr[0]/norma(napr[0],napr[1]);
		napr[1]=napr[1]/norma(napr[0],napr[1]);
		napr[0] = napr[0]*0;
		napr[1] = napr[1]*1;
		alpha=Alpha(xn,napr);
		xn[0]=xn[0]+alpha*napr[0];
		xn[1]=xn[1]+alpha*napr[1];
		alpha=0;
		d[0]=xn[0]-X1[0];
		d[1]=xn[1]-X1[1];
		alpha=Alpha(xn,d);
		X1[0]=xn[0]+alpha*d[0];
		X1[1]=xn[1]+alpha*d[1];
		M++;								// увеличиваем счётчик итераций
	}
	while(norma(d[0],d[1])>eps && norma(napr[0],napr[1])>eps && (M<200));	// комбинированный КОП
	cout<<"Gauss Zeidel"<<"   ";
	cout<<X1[0]<<"   ";			// возвращаем найденный минимум
	cout<<X1[1]<<endl<<endl;			// возвращаем найденный минимум

};



//----------------------------------------
// Метод Флетчера-Ривса
//----------------------------------------


void FLETCHER_RIVES(double z1, double z2)
{

	double g[2];		//направление
	nach[0]=z1;
	nach[1]=z2;
	napr[0]=1;
	napr[1]=2;
	eps=0.001;
	int M=0; //счетчик итераций
	double beta;		// число, меняющее длину р
	// переопределяем массив значений х
	// при пошаговом поиске и задаём
	// значение начальной точки
	
	newgrad(nach,napr[0],napr[1]);
	// сокращаем ТИЛ в соответствии с методом
			napr[0] = -napr[0];		
			napr[1] = -napr[1];		
	while(norma(napr[0],napr[1])>eps &&(M<200))
	{
		M++;								// увеличиваем счётчик итераций
		if(M==1)
		{									// проверяем номер итерации
			newgrad(nach,napr[0],napr[1]);
			napr[0] = -napr[0];		
			napr[1] = -napr[1];		
		
		}//устанавливаем антиградиентное напрвление
		else
			{								// вычисляем в соответствии с формулой
			newgrad(nach,napr[0],napr[1]);	//устанавливаем 
			napr[0] = -napr[0];				//антиградиентное напрвление
			napr[1] = -napr[1];
			beta = (pow(norma(napr[0],napr[1]),2)/(pow(norma(g[0],g[1]),2)));	//бета
			napr[0] = napr[0]+napr[0]*beta;		// новое направление поиска
			napr[1] = napr[1]+napr[1]*beta;		// новое направление поиска
		}
		g[0]=-napr[0];
		g[1]=-napr[1];
											// сохраняем текущий градиент
											// находим коэффициент удлинения вектора
		alpha=Alpha(nach,napr);
		nach[0] = nach[0] + napr[0]*alpha;	// спускаемся в новую точку
		nach[1] = nach[1] + napr[1]*alpha;	// спускаемся в новую точку
		M++;
		
	};
	cout <<"Fletcher Rives"<<"   ";
	cout <<nach[0]<<"   ";					//вывод минимума
	cout <<nach[1]<<endl<<endl;
   
};

//-------------------------------------------
// Метод Цикличесского покоординатного спуска
//-------------------------------------------

void CPS (double z1, double z2)		
{
	double p[2];
	p[0]=1; p[1]=0;
	double M=0;
	X1[0]=z1;
	X1[1]=z2;
	napr[0]=1;
	napr[1]=2;
	newgrad(X1,napr[0],napr[1]);
	//napr[0]=-napr[0];
	//napr[1]=-napr[1];
	napr[0]=X1[0];
	napr[1]=X1[1];
	do
	{
		alpha=Alpha(nach,napr);
		nach[0]=nach[0]+alpha*p[0];
		nach[1]=nach[1]+alpha*p[1];
		alpha=0;
		double temp;
		temp=p[0];
		p[0]=p[1];
		p[1]=temp;
		alpha=Alpha(nach,napr);
		nach[0]=nach[0]+alpha*p[0];
		nach[1]=nach[1]+alpha*p[1];
		newgrad(nach,napr[0],napr[1]);
		napr[0]=-napr[0];
		napr[1]=-napr[1];
		temp=p[0];
		p[0]=p[1];
		p[1]=temp;
		M++;
	}
	while ((norma(X1[0]-nach[0],X1[1]-nach[1])>0.001)&&(M<200));
	cout<<"CPS"<<"   ";
	cout<<nach[0]<<"   ";
	cout<<nach[1]<<endl;
};
//-----------------------------------------
//Метод Даниелла
//-----------------------------------------



void DANIEL(double z1, double z2)
{
	double p[2];
	napr[0]=1;
	napr[1]=2;
	nach[0]=z1;
	nach[1]=z2;
	p[0]=0;
	p[1]=0;
	div_t q;
	int M=0;
	newgrad(nach,napr[0],napr[1]);
	p[0]=napr[0];
	p[1]=napr[1];
	
	while((norma(p[0],p[1])>0.001)&&(M<200))
	{
		p[0]=p[0]/norma(p[0],p[1]);
		p[1]=p[1]/norma(p[0],p[1]);
		alpha=Alpha(nach,p);
			
		nach[0]=nach[0]+alpha*p[0];
		nach[1]=nach[1]+alpha*p[1];
		napr[0]=p[0];
		napr[1]=p[1];
		newgrad(nach,p[0],p[1]);
		q=div(M,2);
		if (q.rem)
		{
			p[0]=p[0]+betta1(napr,p)*napr[0];
			p[1]=p[1]+betta2(napr,p)*napr[1];
		}
		M++;
	}

					
	cout<<"Daniel"<<"   ";
	cout<<nach[0]<<"   ";
	cout<<nach[1]<<endl;
};

//----------------------------------
//Главная процедура
//----------------------------------

void main()
{

/*	ZS_1(1,1);
	ZS_2(1,1);
	DETOH(1,1);
	PAUELL(1,1);
	BOLCANO(1,1);
	KOSHI(3,2);*/
//	FLETCHER_RIVES(3,2);
	/*PARALLEL(3,2);
	FIBONACHI1(1,1);
	FIBONACHI2(1,1);
	GAUSS_ZEIDEL(3,2);
	CPS(3,2);   */

	double Points[2];
	int meth;
	Cout<< "Enter Method Type "<<endl;
/*	Cout<< "1. ZS_1: "<<endl;
	Cout<< "2. ZS_2: "<<endl;
	Cout<< "3. Fibonachi_1: "<<endl;
	Cout<< "4. Fibonachi_2: "<<endl;
	Cout<< "5. DETOH: "<<endl;
	Cout<< "6. Bolcano: "<<endl;
	Cout<< "7. PAUELL: "<<endl;
	cin >> meth;
	Cout<< "Start point 1";cin>>Points[0];cout<<endl;
	Cout<< "Start point 2";cin>>Points[1];cout<<endl;
//	DANIEL(Points[0],Points[1],math);
	getch();	//ожидание нажатия любой клавиши
*/};
Соседние файлы в папке all