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

// Подключаем класс для работы с матрицами
#include "matrix.cpp"

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

		switch(fun)
	{
	case 1:
			return x[1]*x[1]+2*x[2]*x[2]-2*x[1]*x[2]+x[2];
         //	return 100*pow(x[2]-x[1]*x[1],2)+pow(1-x[1],2); // 19)
			break;
	case 2:
			return x[1]*x[1]-2*x[2]*x[2]+3*x[3]*x[3]-4*x[1]*x[2]+5*x[2]*x[3]-6*x[1]*x[3];	
		 //	return pow(x[1]-1,2)+pow(x[2]-3,2)+4*pow(x[3]+5,2); // 20)
			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;
} 

// Вычисление матрицы Гессе
TMatrix<double> ddf(TMatrix<double> &x,int fun)
{
	double eps=0.0001;
	int ln=x.getSizeRow();
	TMatrix<double> res(ln,ln);
	TMatrix<double> ei(ln,1), ej(ln,1);
	int m=ln, n=ln;

	for (int i=1; i<=m;i++)
	{
		for(int j=1; j<=n; j++)
		{
			ei=Ord(ln,i);
			ej=Ord(ln,j);
			res(i,j)=(f(x+ei*eps+ej*eps,fun)-f(x+ei*eps,fun)-f(x+ej*eps,fun)+f(x,fun))/(eps*eps);
		}
	}
	return res;
}

// Критерий окончания поиска
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> gauss(TMatrix<double> mat)
{
	TMatrix<double> count(mat.getSizeRow(),1);
	TMatrix<double> i; i.setSingle(mat.getSizeRow());
	double tmp; //делитель
	int r=1;//проход по строрке
	for (int z=1; z <= mat.getSizeRow(); z++) 
	{
		for (int k=1; k <= mat.getSizeRow(); k++) 
		{//проход по столбцам
			tmp=mat(k,z);
			for (int j=1; j <=mat.getSizeRow(); j++) 
			{//проход по строкам
				mat(k,j)=mat(k,j)/tmp;
				i(k,j)=i(k,j)/tmp;
			}
		}

		for (int j=1; j <=mat.getSizeRow(); j++) 
		{
			for (int l=1; l<=mat.getSizeRow(); l++)
			{
				if (l != z)
				{
					mat(l,j)=(-1)*mat(z,j)+mat(l,j);
					i(l,j)=(-1)*i(z,j)+i(l,j);
				}
			}

		}

	}
	for (int k=1; k <= mat.getSizeRow(); k++)
	{
		if (mat(k,k) != 1)
		{
			for (int j=1; j <= mat.getSizeRow(); j++)
			{
				i(k,j)=i(k,j)/mat(k,k);
			}
		}
	}
	return i;// Возвращаем обратную матрицу
}

// Обобщенный метод Ньютона
TMatrix<double> Nuton(TMatrix<double> x,double eps,int &max_step,int fun)
{
	// Переменные
	double e=eps;
	TMatrix<double> xNew,p,dy,H;
	int iter=0;
	double alfa;
	// Установка размера матриц и векторов
    xNew.setSize(x.getSizeRow(),x.getSizeCol());
	H.setSize(x.getSizeRow(),x.getSizeRow());
	dy.setSize(x.getSizeRow(),x.getSizeCol());
	p.setSize(x.getSizeRow(),x.getSizeCol());
	xNew=x;

	alfa=1;
	// Сам метод
	do
	{
	dy=Grad(xNew,fun);
	H=ddf(xNew,fun);
	p=gauss(H)*dy*(-1);
	xNew=x-alfa*p;
	iter++;
	}
	while((norma(p)>=e)&&(iter<max_step));
	// Для квадратичной функции метод должен возвращать минимум за 1 итерацию
	max_step=iter;
	return xNew;
}

// Основная программа
void main()
{
	double norm;
	int fun, iter, n, i;
	TMatrix<double> xs, Min, Min1;
	

	cout<<"1) x^2+2*y^2-2*x*y+y"<<endl;
	cout<<"2) x^2-2*y^2+3*z^2-4*x*y+5*y*z-6*x*z"<<endl;
	cout<<"Enter number of the chosen function for testing:"<<endl;
	cin>>fun;

	switch(fun)
	{
	case 1:
			n=2;
			xs.setSize(n,1);
			break;

	case 2:
			n=3;
			xs.setSize(n,1);
			break;

    default:cout<<"Such variant of a choice is not possible!"<<endl;
			break;
	}

	for(i=1; i<=n; i++)
	{
		xs[i]=1; 
	}

	cout<<"Enter restriction on a maximum quantity of iterations:"<<endl;
	cin>>iter;

	Min=Grad(xs,fun);
	cout<<"\nGradient:"<<endl;
	Min.writeArray();

	Min1=ddf(xs,fun);
	cout<<"\nGesse:"<<endl;
	Min1.writeArray();

	norm=norma(xs);
	cout<<"\nNorma:"<<endl;
	cout<<norm;

	Min=Nuton(xs,0.000000001,iter,fun);
	cout<<"\n\nHave received a minimum:"<<endl;
	Min.writeArray();// Вывод полученного минимума
	cout<<"\nQuantity of iterations: "<<iter<<endl; // Сколько итераций было действительно выполнено
}
Соседние файлы в папке Лабораторная работа №6