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

// Подключаем класс для работы с матрицами
#include "matrix.cpp"
TMatrix<double> Po,Xo;

double f(TMatrix<double> &x,int fun)
{	

		switch(fun)
	{
	case 1: 
	    	return 2*x[1]*x[1]+2*x[1]*x[2]+2*x[2]*x[2]-x[1]+1;
         	break;
	case 2:
			return pow(x[1]-1,2)+pow(x[2]-3,2)+4*pow(x[3]+5,2);
		 	break;
    default:cout<<"Such variant of a choice is not possible!"<<endl;
			break;
	}
}

// Численное вычисление производной любой функции в точке "х" по направлению "р"
double df(TMatrix<double> &x,TMatrix<double> &p, int fun)
{
    double eps=0.0001;
	return (f(x+p*eps,fun)-f(x,fun))/(eps);
}

// Возвращает направление поиска, параллельное оси координат
TMatrix<double> Ord(int size, int i) // size - число переменных функции
									 // i - число обращений к этой функции	
{
	TMatrix<double> res(size,1);
	for(int k=1; k <= size; k++)
	{
		if (k!=i)
		{
			res[k]=0;
		}
		else
		{
			res[k]=1;
		}
	}
	return res;
}

// Возвращает вектор градиента функции в точке "х"
TMatrix<double> Grad(TMatrix<double> &x,int fun)
{
  int i=x.getSizeRow();
  TMatrix<double> res(i,1);
  for (int k = 1;k<=i;k++)
  {
	  res[k]=df(x,Ord(i,k),fun);

  }
  return res;
} 

// Вычисление шага
double Alpfa(double X1, int fun)
{
 double X2, a, b, c, d, h, Min;
 int i=0;
 double e,e2=0.0000001;
 e=e2;
 h = 0.001*X1;
 if (!h)
	h = 0.001;
 X2 = X1 + h;
 if (f(Xo+X1*Po,fun) < f(Xo+X2*Po,fun)) 
	 h = -h;
 do
	{
	 X2 = X1 + h;
	 while(f(Xo+X1*Po,fun) > f(Xo+X2*Po,fun))
		{
		 h = 2*h;
		 X1 = X2;
		 X2 = X1 + h;
		}
	 if (f(Xo+X1*Po,fun) < f(Xo+((X1+X2)/2)*Po,fun))
		{
		 b = X1;
		 c = (X1+X2)/2;
		 a = 2*b - c;
		}
	 else
		{
		 a = X1;
		 b = (X1+X2)/2;
		 c = 2*b - a;
		}
	 d = b + (b-a)*(f(Xo+a*Po,fun)-f(Xo+c*Po,fun))/(f(Xo+a*Po,fun) - 2*f(Xo+b*Po,fun) + f(Xo+c*Po,fun))/2;
	 h = h/2;
	 if (f(Xo+b*Po,fun) < f(Xo+d*Po,fun))
	 {
		 X1 = b;
	 }
	 else
	 {
		X1 = d;
	 }
	 i++;
	}
 while((fabs((d - b)/b) > e) || (fabs((f(Xo+d*Po,fun) - f(Xo+b*Po,fun))/f(Xo+b*Po,fun)) > e2));
 Min = (b+d)/2;
 cout<<"Dsk iteracii: "<<i<<"\n";
 return Min;
}

// Критерий окончания поиска
double norma(TMatrix<double> &x)
{
   double res=0;
   int m=x.getSizeRow(), n=x.getSizeCol();

   for(int i=1; i<=m; i++)
   {
      for(int j=1; j<=n; j++)
      {
	 res+=fabs(x(i,j)*x(i,j));
      }
   }
   return sqrt(res);
}

// Метод Даниела
TMatrix<double> Daniel(TMatrix<double> x,double eps,int &max_step,int fun)
{
	// Переменные
	double epsilon=eps;
	TMatrix<double> p1, p2, g1, g2, x1, x2, x3, gamma, r1, r2,y;
	int k=1;
	double alfa1, alfa2, beta1;

	// Установка размера матриц и векторов
    p1.setSize(x.getSizeRow(),x.getSizeCol());
	p2.setSize(x.getSizeRow(),x.getSizeCol());
	g1.setSize(x.getSizeRow(),x.getSizeCol());
	g2.setSize(x.getSizeRow(),x.getSizeCol());
	x1.setSize(x.getSizeRow(),x.getSizeCol());
	x2.setSize(x.getSizeRow(),x.getSizeCol());
	x3.setSize(x.getSizeRow(),x.getSizeCol());
	
	r1.setSize(0,0);
	r2.setSize(0,0);
	
	Po.setSize(x.getSizeRow(),x.getSizeCol());
	x1=x;

	do
	{
		cout<<"Iteraciya	"<<k<<endl;
		cout<<"x1="<<endl;
		x1.writeArray();
	p1=Grad(x1,fun)*-1;
		cout<<"p1="<<endl;
		p1.writeArray();
	Po=p1;
	Xo=x1;
	alfa1=Alpfa(0,fun);
	x2=x1+p1*alfa1;
		cout<<"x2="<<endl;
		x2.writeArray();
	y.setSize(x.getSizeRow(),x.getSizeCol());
	y=Grad(x2,fun);
	if (norma(y)<epsilon) 
	{
		return x2;
	}
	g1=Grad(x1,fun);
		cout<<"g1="<<endl;
		g1.writeArray();
	g2=Grad(x2,fun);
		cout<<"g2="<<endl;
		g2.writeArray();
	gamma.setSize(x.getSizeRow(),x.getSizeCol());
	gamma=g2-g1;
		cout<<"gamma="<<endl;
		gamma.writeArray();
	r1=g2.getTranspose()*gamma;
	r2=p1.getTranspose()*gamma;
	beta1=(r1[1]/r2[1]);
		cout<<"beta1="<<endl;
		cout<<beta1<<endl;
	p2=g2*-1+p1*beta1;
		cout<<"p2="<<endl;
		p2.writeArray();
	Po=p2;
	Xo=x2;
	alfa2=Alpfa(0,fun);
	x3=x2+p2*alfa2;
		cout<<"x3="<<endl;
		x3.writeArray();
	k++;
	y=Grad(x3,fun);
	x1=x3;
	}
	while((norma(y)>=epsilon)&&(k<=max_step)); // Для п=2 х3 - минимум, т. е. надо задавать k=1
		cout<<"norma(y)="<<norma(y)<<endl;
	max_step=k-1;
	return x3;
}

// Основная программа
void main()
{//1
	double e=0.001;
	int fun, iter, n;
	TMatrix<double> xs, Min;
	char answer;

	do
		{//2
			cout<<"1) 2*x^2+2*y^2+2*x*y-x+1"<<endl;
			cout<<"2) (x-1)^2+(y-3)^2+4*(z+5)^2"<<endl;
			cout<<"Enter number of the chosen function for testing:"<<endl;
			cin>>fun;
			switch(fun)
			{//3
			case 1:
					n=2;
					xs.setSize(n,1);
					xs[1]=0;
					xs[2]=0;
					break;
			case 2:
					n=3;
					xs.setSize(n,1);
					xs[1]=4;
					xs[2]=-1;
					xs[3]=2;
					break;
			default:cout<<"Such variant of a choice is not possible!"<<endl;
					break;
			}//3
			cout<<"Enter restriction on a maximum quantity of iterations:"<<endl;
			cin>>iter;
			Min=Daniel(xs,e,iter,fun);
			cout<<"\n\nHave received a minimum:"<<endl;
			Min.writeArray();// Вывод полученного минимума
			cout<<"\nQuantity of iterations: "<<iter<<endl; 
			cout<<"Will continue?  y (yes) or n (no) ?\n";

			cin>>answer;
			if (answer=='n') break;

		}//2
	while (1);
}//1
Соседние файлы в папке Лабораторная работа №7