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

//class vector(for math vector operations)
class CVector
{
public:
	CVector(int VectorSize);
	CVector( const CVector & );
	~CVector(void);

int getSize() const;

double & operator[](int subscript);
const double &operator[](int subscript) const;

const CVector & operator=(const CVector &right);
bool operator==( const CVector &right) const;
bool operator!=( const CVector &right) const;

CVector operator*(const double k) const;
double operator*(const CVector &right) const;
CVector operator+(const double &alfaPoint) const;
CVector operator-(const double alfaPoint) const;

CVector operator+(const CVector &right) const;
CVector operator-(const CVector &right) const;
CVector operator-() const;

private:
	double *vectorPointer;
	int size;
};

CVector x0(2),result(2);	//для хранения промежуточных и окончательного результата
CVector p(2),step(2);
int numberOfVariables;
double d_left,d_right;

//class storing all nessesary data for optimisation methods
class CMetOp
{
public:
	CMetOp();
	~CMetOp();

  double func(double t);
	double dfunc(double k);
  void antigradNapr();
  void KOSHI(double e);
  double getNorma(const CVector x);
  double Davidon(double e);
  double formules(double c);
  void Swann4(double t);

private:	//переменные класса
	int numberOfVariables;
  int funcNumber;
  int d;
	double alfaPoint;
public:
	int numberOfFormula;
};

//class vector methods describtion
CVector::CVector(int VectorSize)
{
	size = VectorSize ;
	vectorPointer = new double[size];
	//for( int i = 0; i < size; i++ )
	//	vectorPointer[i]=0;
  vectorPointer[0]=-1.2;
  vectorPointer[1]=1;
}
CVector::CVector(const CVector &init) : size(init.size)
{
	vectorPointer = new double[size];
	for( int i = 0; i < size; i++ )
		vectorPointer[i]=init.vectorPointer[i];
}
CVector::~CVector(void)
{
	delete [] vectorPointer;
}


int CVector::getSize() const
{
	return size;
}

double & CVector::operator[](int subscript)
{
	return vectorPointer[subscript];
}

const double & CVector::operator[](int subscript) const
{
	return vectorPointer[subscript];
}


const CVector & CVector::operator=(const CVector &right)
{
	if(&right!=this)
	{
		if( size!= right.size)
		{
			delete [] vectorPointer;
			size=right.size;
			vectorPointer = new double[size];
		}
		for ( int i = 0; i < size; i++)
			vectorPointer[i] = right.vectorPointer[i];
	}
	return *this;
}

bool CVector::operator==( const CVector &right) const
{
	if( size != right.size )
		return false;
	for (int i = 0; i < size; i++)
		if ( vectorPointer[i] != right.vectorPointer[i])
			return false;
	return true;
}

bool CVector::operator!=( const CVector &right) const
{
	return ! (*this == right );
}

CVector CVector::operator*(const double k) const
{
	CVector result(size);
	for (int i=0; i<size;i++)
		result[i]=k*vectorPointer[i];
	return result;
}

CVector CVector::operator+(const double &alfaPoint) const
{
	CVector result(size);
	for (int i=0; i<size;i++)
		result[i]=vectorPointer[i]+alfaPoint;
	return result;
}

CVector CVector::operator-(const double alfaPoint) const
{
	return *this+(-alfaPoint);
}

CVector CVector::operator+(const CVector &right) const
{
	CVector result(size);
	for (int i=0; i<size;i++)
		result[i]=vectorPointer[i] + right[i];
	return result;
}

double CVector::operator*(const CVector &right) const
{
	double result=0;
	for (int i=0; i<size;i++)
		result+=vectorPointer[i]*right[i];
	return result;
}

CVector CVector::operator-(const CVector &right) const
{
	CVector result(size);
	for (int i=0; i<size;i++)
		result[i]=vectorPointer[i] - right[i];
	return result;
}
CVector CVector::operator-() const
{
	CVector result(size);
	for (int i=0; i<size;i++)
		result[i]=-vectorPointer[i];
	return result;
}

CMetOp :: CMetOp()
{
}

CMetOp :: ~CMetOp()
{
}


double CMetOp :: func(double t)
{
   CVector x2(2);
      for(int k=0;k<2;k++)
          x2[k]=x0[k]+t*p[k];
   return (100*pow((x2[1]-x2[0]*x2[0]),2)+pow((1-x2[0]),2));
}

double CMetOp :: dfunc(double k) //Частные производные функции
{
  switch(funcNumber) // в зависимости от номера функции
		{
		case 1:
			switch(numberOfVariables)  // в зависимости от переменной, по которой дифференцируют
			{
			case 0:
				return 2*((x0[0]+k*p[0])-(x0[1]+k*p[1]));
			case 1:
				return 4*(x0[1]+k*p[1])-2*(x0[0]+k*p[0])+1;
			default:
				return 0;
			}
		case 2:
			switch(numberOfVariables)  // в зависимости от переменной, по которой дифференцируют
			{
			case 0:
				return 2*(x0[0]+k*p[0]-1);
			case 1:
				return 2*(x0[1]+k*p[1]-3);
			case 2:
				return 8*(x0[2]+k*p[2]+5);
			default:
				return 0;
			}
		case 3:
			switch(numberOfVariables)  // в зависимости от переменной, по которой дифференцируют
			{
			case 0:
				return -400*((x0[1]+k*p[1])-(x0[0]+k*p[0])*(x0[0]+k*p[0]))-2*(1-(x0[0]+k*p[0]));
			case 1:
				return 200*((x0[1]+k*p[1])-(x0[0]+k*p[0])*(x0[0]+k*p[0]));
			default:
				return 0;
			}
		default:
			return 0;
		}
}

/**********************Antigradientnoe napravlenie***************************/
void CMetOp :: antigradNapr()
{
   p[0]=400*(x0[1]-x0[0]*x0[0])*x0[0]+2*(1-x0[0]);
   p[1]=-200*(x0[1]-x0[0]*x0[0]);
}

/****************************getNorma*****************************************/
double CMetOp :: getNorma(const CVector x)
{
   return(sqrt(pow((x[0]-x0[0]),2)+pow((x[1]-x0[1]),2)));
}

/***************************Ras4etnie formuli********************************/
double CMetOp :: formules(double c)
{
   double z,w;
   z=dfunc(d_left)+dfunc(d_right)+3*(func(d_left)-func(d_right))/d_right;
   w=sqrt(z*z-dfunc(d_left)*dfunc(d_right));
   c=d_left+((z-dfunc(d_left)+w)/(dfunc(d_right)-dfunc(d_left)+2*w))*(d_right-d_left);
   return c;
}

void CMetOp :: Swann4(double t)
{
   double s=0;
   if(t>fabs((func(0)-dfunc(0))/dfunc(0)))
      t=fabs((func(0)-dfunc(0))/dfunc(0));
   if(dfunc(0)>0)
      for(int k=0;k<2;k++)
         p[k]=-p[k];
   do
      {
      s=s+t;
      t=2*t;
      }
   while((dfunc(0)*dfunc(s))>0);
   d_left=s-t/2;
   d_right=s;
}

/*****************************Metod Devidona*********************************/
double CMetOp :: Davidon(double e)
{
   double c;
   Swann4(1);
   do
      {
      c=formules(c);
	   if(dfunc(c)<0)
         d_left=c;
	   else
         d_right=c;
	   }
   while(fabs(dfunc(c))>e);
   return c;
}



/******************************Metod Koshi***********************************/
void CMetOp :: KOSHI(double e)
{
   double d_alfaPoint;
   CVector x1(2);
   int k;
   int g=0;
   for(k=0;k<2;k++)
      x1[k]=x0[k];
   do
      {
      g++;
      for(k=0;k<2;k++)
         x0[k]=x1[k];
      antigradNapr();
      d_alfaPoint=Davidon(e);
      for(int k=0;k<2;k++)
         x1[k]=x0[k]+d_alfaPoint*p[k];
      }
   while((getNorma(x1)>e)||(fabs(func(0)-func(d_alfaPoint))>e));
   for(k=0;k<2;k++)
      x0[k]=x1[k];
   cout<<"\nKolli4estvo iteraciy: k = "<<g;
}


/******************************Main***********************************/
void main()
{
	CMetOp method;
	int funcNumber;
  double E;

  cout<<"\n---Laboratornaya rabota 5. Issledovanie gradientnih metodov.---";
  cout<<"\n-------------------------Variant 1-----------------------------";
  cout<<"\n------------------------Metod Koshi----------------------------\n";
  do
  {
	cout<<"1   -   x1^2 + 2*x2^2 - 2*x1*x2 + x2 \n";
	cout<<"2   -   (x1-1)^2+(x2-3)^2+4*(x3+5)^2 \n";
	cout<<"3   -   100*(x2-x1^2)^2+(1-x1)^2\n";
	cout<<"Enter number of function: ";
  cin>>funcNumber;
  }
  while(funcNumber>3 && funcNumber<1);
  cout<<"\nVvedite to4nost' poiska: E = ";
  cin>>E;
  cout<<"\nNa4al'naya to4ka poiska: Xo = ( -1.2 ; 1 )";
	switch(funcNumber)
	{
	case 1:
		numberOfVariables=2;
		break;
	case 2:
		numberOfVariables=3;
		break;
	case 3:
		numberOfVariables=2;
		break;
	default:
		numberOfVariables=0;
		break;
	}
  //method.InputPoint(numberOfVariables, funcNumber);
  method.KOSHI(E);
  cout<<"\nRezultat minimizacii: ";
  cout<<"( "<<x0[0]<<" ; "<<x0[1]<<" )";
  getch();
}


Соседние файлы в папке prog