Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
5
Добавлен:
01.05.2014
Размер:
11.88 Кб
Скачать
#include <iostream.h>
#include <conio.h>
#include <math.h>
/******************************  Klass Vector  ********************************/
class Vector
{
	public:
		Vector(int Size);
		Vector(const Vector& v);
		~Vector();
		int size() const;
		double& Vector::operator[](int N);
		double Vector::operator[](int N) const;
		void Summa(const Vector& a, const Vector& b);
		void Razn(const Vector& a, const Vector& b);
		Vector Scal(Vector x, double d);
      double Umn(const Vector& a, const Vector& b);
		Vector& operator=(const Vector& a);
		void Write() const;
		Vector Grad(const Vector& x);
/*******************  Ispolsuemie algoritmi iz Lab4 ***************************/
		void Swenn4(const Vector& x, Vector& p, double& ala, double& alb, int& iter);
		double ZS2(Vector& x, Vector& p, double& ala, double& alb, double& E, int& iter);
		double Davidon(Vector& x, Vector& p, double& ala, double& alb, double& E, int& iter);
		Vector Evec(int n, int Num);
		double Norma(Vector x);
      Vector GZ_3(Vector& x, double E, int maxiter, int& iter, int& bool, int method);//!!!
/***********************  Operacii nad vectorami ******************************/
		Vector operator+(const Vector& a)
		{
			Vector s(nSize);
			s.Summa(*this, a);
			return s;
		}
		Vector operator-(const Vector& a)
		{
			Vector s(nSize);
			s.Razn(*this, a);
			return s;
		}

      /*Vector Minus(const Vector& a)
      {
      Vector s(nSize);
			s.Razn(*this, a);
			return s;
      }*/

		double operator*(const Vector& a)
		{
			double w;
			Vector s(nSize);
			w = s.Umn(*this, a);
			return w;
		}

      /*double Umnoj(const Vector& a)
      {
         double w;
         Vector s(nSize);
         w=s.Umn(*this, a);
         return w;
		}*/

		void operator*=(double d)
		{
			for (int i = 0; i < nSize; i++)
			Coord[i] *= d;
		}

      /*void ZvRavno(double d)
      {
         for (int i =0; i<nSize; i++)
         Coord[i]*=d;
      }*/

	private:
		double* Coord;
		int nSize;
};

Vector::Vector(int Size)
{
	nSize = Size;
	Coord = new double[Size];
}
Vector::Vector(const Vector& v)
{
	nSize = v.size();
	Coord = new double[nSize];
	for (int i = 0; i < nSize; i++)
		Coord[i] = v[i];
}
Vector::~Vector()
{
	delete[] Coord;
}
int Vector::size() const
{
	return nSize;
}
double& Vector::operator[](int N)
{
	return *&Coord[N];
}
double Vector::operator[](int N) const
{
	return Coord[N];
}
Vector Vector::Scal(Vector x, double d)
{
   int i = x.size();
   Vector W(i);
   for(int j=0; j<i; j++)
     W[j] = x[j]*d;
   return W;
}
void Vector::Summa(const Vector& a, const Vector& b)
{
	int s = a.size();
	int i;
	if ((s = b.size()) != 0 )
	{
	 for (i = 0; i < s; i++)
		{
			Coord[i] = a[i] + b[i];
		}
	}
	else
	{
		cout<<"ERROR!"<<endl;
	}
}
void Vector::Razn(const Vector& a,  const Vector& b)
{
	int s = a.size();
	int i;
	if ((s = b.size()) != 0 )
	{
		for (i = 0; i < s; i++)
		{
			Coord[i] = a[i] - b[i];
		}
	}
	else
	{
		cout<<"ERROR!"<<endl;
	}
}
double Vector::Umn(const Vector& a, const Vector& b)
{
	int s = a.size();
	//int i;
	double Um=0;
	if ((s = b.size()) != 0 )
	{
	 for (int i = 0; i < s; i++)
		{
		  Coord[i] = a[i] * b[i];
		  Um = Um + Coord[i];
		}
	}
	return Um;
}
Vector& Vector::operator =(const Vector& a)
{
	for (int i = 0; i < nSize; i++)
	{
	 Coord[i] = a.Coord[i];
	}
	return *this;
}
void Vector::Write() const
{
	cout<<"This is vector:"<<endl;
	for (int i = 0; i < nSize; i++)
	{
		cout<<Coord[i]<<endl;
	};
}
/**************************  Testovie funkcii *********************************/
double F (Vector t)
{
  double result = 0;
  if (t.size() == 2)
    result = pow(t[1]-t[0]*t[0], 2) + pow(1-t[0], 2);
  if (t.size() == 3)
    result = (t[0]-1)*(t[0]-1) + (t[1]-3)*(t[1]-3) + 4*(t[2]+5)*(t[2]+5);
    //result = 3*(t[0]-4)*(t[0]-4) + 5*(t[1]+3)*(t[1]+3) + 7*(2*t[2]+1)*(2*t[2]+1);
  if (t.size() == 4)
    //result = t[0]-10*t[2]+5*(t[2]-t[3])*(t[2]-t[3])+pow(t[1]-2*t[2], 4)+10*pow(t[0]-t[3], 4);
    result = 100*pow(t[1]-t[0]*t[0], 2) + (1-t[0])*(1-t[0]) + 90*pow(t[3]-t[2]*t[2], 2) + pow(1-t[2], 3) + 10.1*(t[1]-1)*(t[1]-1) + (t[3]-1)*(t[3]-1) + (t[1]-1)*(t[3]-1);
  return result;
}
/*********************  4astnaya proizvodnaya po Xi ***************************/
double ChP(Vector x, int i)
{
	int t = x.size();
	double w = -1000;                   //!!!
	double h = 0.000001;
	Vector q(t);
	if (t >= i)
	  w = ( F(x + q.Scal(q.Evec(t, i), h)) - F(x - q.Scal(q.Evec(t, i), h)) )/(2*h);
	return w;
}
/****************************  Gradient ***************************************/
Vector Vector::Grad(const Vector& x)
{
  int i = x.size();
  Vector w(i);
  for (int j = 1; j<=i; j++)
  {
    w[j-1] = ChP(x, j);
  }
  return w;
}
/***************  1-aya testovaya funkciya-Metod Swenna 4 *********************/
void Vector::Swenn4(const Vector& x, Vector& p, double& ala, double& alb, int& iter)
{
  int r = x.size(),// Vektor skol'ki peremennih?
      iter=0; // Koli4estvo iteraciy
  Vector G(r); // Opredelenie
  G = G.Grad(x); // Vi4islenie gradienta v na4al'noy to4ke
  if ((G * p) > 0) // Proverka napravlenia ubivania functsii...
   {
     p*=-1;
     //t=-1;
     //p=p.Scal(p, t);
   }
  double f1, f2, al = 0.000001;
  Vector x1(r);
  Vector Pro(r);
  x1 = x;
  f1 = G * p; // Proizvodnaya v na4al'noy to4ke po napravleniyu "p"
  do // Dvigaemsya v napravlenii ubivaniya funkcii
  {
    al = al*2; // Udvaivaem shag
    Pro = Pro.Scal(p, al); // Ispol'suem peremennuyu "Pro" dlya hraneniya "al*p"
    x1 = x1 + Pro; // Xk+1 = Xk + ALPHAk * Pk
    G = G.Grad(x1); // Vi4islenie gradienta v novoy to4ke
    f2 = G * p; // Proizvodnaya v novoy to4ke po napravleniyu "p"
    iter++;
  }
  while (f1*f2 > 0); // Proverka KOP
  ala=al/2; // Fiksiruem na4al'niy interval 4erez shagi
  alb=al;
}
/************  2-aya testovaya funkciya-Metod Zolotogo Se4eniya 1  ************/
double Vector::ZS2(Vector& x, Vector& p, double& ala, double& alb, double& E, int& iter)
{
  int r = x.size(),// Vektor skol'ki peremennih?
      iter=0; // Koli4estvo iteraciy
  double al1, al2, f1, f2;
  Vector G(r);
  Vector x1(r);
  Vector x2(r);
  al1=ala+0.61803398875*fabs(alb-ala);
  do
     {
     al2=ala+alb-al1;
     x1=x+G.Scal(p,al1);
     f1=F(x1);
     x2=x+G.Scal(p,al2);
     f2=F(x2);
     if ((al1<al2)&&(f1<f2))
        alb=al2;
     if ((al1<al2)&&(f1>=f2))
        {
        ala=al1;
        al1=al2;
        }
     if ((al1>al2)&&(f1<f2))
        ala=al2;
     if ((al1>al2)&&(f1>=f2))
        {
        alb=al1;
        al1=al2;
        }
     iter++;
     }
  while (iter<5);
}
/***************    *********************/
Vector Vector::Evec(int n, int Num)       // - koordinatniy ort
{                                         // dlinoy 'n'
  Vector W(n);                            // i 1-tsey na 'Num'
  int i=0;
  while (i<n)
  {
    W[i] = 0;
    i++;
  }
  W[Num-1] = 1;
    return W;
}
/***************    *********************/
double Vector::Norma(Vector x)
{
  int i = x.size();
  double d=0;
  for (int j = 0; j < i; j++)
    d = d + x[j]*x[j];
  return sqrt(d);
}
/***************    *********************/
double Vector::Davidon(Vector& x, Vector& p, double& ala, double& alb, double& E, int& iter)
{
  double a, b, bb, c, d, dd, help1, help2, Q, S;
  int r = x.size();
  Vector xa(r);
  Vector xb(r);
  Vector xc(r);
  Vector xd(r);

  a = al1;
  b = (al1+al2)/2;
  c = al2;
  xa = x + xa.Scal(p, a);
  xb = x + xb.Scal(p, b);
  xc = x + xc.Scal(p, c);

  help1 = ( F(xa)*(b*b-c*c) + F(xb)*(c*c-a*a) + F(xc)*(a*a-b*b) );
  help2 = (F(xa)*(b-c) + F(xb)*(c-a) + F(xc)*(a-b));
  if (help2 == 0)
    help2 = 0.0000001;
  d = 0.5*help1/help2;
  xd = x + xd.Scal(p, d);

  while ((fabs((d-b)/b) >= E)  ||  (fabs(F(xd)-F(xb))/F(xb) >= E  ))
  {
    if (b<d)
    {
      if (F(xb)<F(xd))
      {
	c = d;
	b = (a+c)/2;
      }
      else
      {
	a = b;
	b = (a + c)/2;
      }
    }
    if (b>d)
    {
      if (F(xb)>F(xd))
      {
	c = b;
	b = (a + c)/2;
      }
      else
      {
	a = d;
	b = (a + c)/2;
      }
    }
    xa = x + xa.Scal(p, a);
    xb = x + xb.Scal(p, b);
    xc = x + xc.Scal(p, c);
    help1 = (F(xa)-F(xb))*(b-c)*(c-a);
    help2 = (F(xa)*(b-c) + F(xb)*(c-a) + F(xc)*(a-b));
    if (help2 == 0)
      break;               //            Delenie na nol'
    d = (a+b)/2 + 0.5*(help1/help2);
    xd = x + xd.Scal(p, d);
    bb = b;
    dd = d;
  }
  b = bb;
  d = dd;
  return (b + d)/2;
}
/***************    *********************/
Vector Vector::GZ_3(Vector& x, double E, int maxiter, int& iter, int& bool, int method)
{
  int r = x.size();
  Vector p(r);    //napravlenie
  Vector G(r);    //vspomogatel'naya
  Vector t(r);    //dubliruet 'x'
  double w, al, a, b, k;
  int y=0;
  t = x;
  bool = 0;
  while (   (  Norma(G.Grad(t)) >= E  ) && (  y < maxiter  )   )
  {
	  k = Norma(G.Grad(t));
	  for (int i = 1; i<=r; i++)
	  {
	    w = ChP(t, i);
	    p = p.Scal(Evec(r,i), w);
	    G.Swenn(t, p, a, b);
	    if (method == 1)
	      al = G.ZS1(t, p, a, b, E); //alpha i-oe
	    if (method == 2)
	      al = G.Pauell(t, p, a, b, E); //alpha i-oe
	    t = t + G.Scal(p, al);
	  }
	  y++;
  }
  if (Norma(G.Grad(t)) < E)
    bool = 1;
  iter = y;
  return t;
}
/***********************************************/
void main()
{
  clrscr();

  double E;
  int it=0, maxit, tochnost;
  int choice, razmer, method, itogoiter=0;
  char otvet, dalshe;

  cout<<"Dannaia programma ispol'zuet metod GAUSSA-ZEIDELIA"<<endl;
  cout<<"dlia nahojdenia minimuma funktsii."<<endl;
  cout<<"Predusmotren vibor metoda promejutochnih raschetov (ZS-1, Pauell)"<<endl;
  cout<<endl;
  cout<<"Viberite functsiu:"<<endl;
  cout<<"1. f(x1,x2) = (x2-x1x1)(x2-x1x1) + (1-x1)(1-x1);"<<endl;
  cout<<"2. f(x1,x2,x3) = (x1-1)(x1-1) + (x2-3)(x2-3) + 4(x3+5)(x3+5)"<<endl;
  //cout<<"3. f(x1,x2,x3,x4) = x1 - 10x2 + 5(x3-x4) + (x2-2x3)^4 + 10(x1-x4)^4"<<endl;
  cout<<"3. f(x1,x2,x3,x4) = 100(x2-x1x1)^2 + (1-x1)^2 + 90(x4-x3x3)^2 + (1-x3)^3 + "<<endl;
  cout<<"                        + 10.1(x2-1)^2 + (x4-1)^2 + 19.8(x2-1)(x4-1)"<<endl;

  cin>>choice;
  razmer = choice + 1;

  Vector x(razmer);
  for (int i = 0; i < razmer; i++)
    x[i] = 0;

  cout<<"Po umolchaniu nachalnaia tochka imeet koordinati x[i]=0.5. Izmenit'? (y/n)"<<endl;
  otvet = getch();
  if (otvet == 'y')
      for (int i = 0; i < razmer; i++)
	{
	  cout<<"Zadaite "<<i+1<<" koordinatu:   ";
	  cin>>x[i];
	}

  Vector Q3(razmer);
  int pomoshnik = 0;
  do
  {
  cout<<endl;
  cout<<"Viberite metod rascheta:"<<endl;
  cout<<"1. Metod Zolotogo Sechenia (1);"<<endl;
  cout<<"2. Metod Pauella"<<endl;
  cin>>method;

  cout<<"Vvedite max kol-vo iteratsii: ";
  cin>> maxit;
  cout<<"Vvedite pogreshnost' (E = 0.00001 - 0.0000000001) : ";
  cin>>E;
  cout<<endl;
  if (pomoshnik > 0)
  {
    x = Q3;
    cout<<"Izmenit' nachal'nuiu tochku? (y/n)"<<endl;
    otvet = getch();
    if (otvet == 'y')
      for (int i = 0; i < razmer; i++)
	{
	  cout<<"Zadaite "<<i+1<<" koordinatu:   ";
	  cin>>x[i];
	}
  };

  Q3 = Q3.GZ_3(x, E, maxit, it, tochnost, method);

  cout<<"kolichestvo iteratsii v dannom shage:  "<<it;
  itogoiter = itogoiter + it;
  cout<<",  vsego: "<<itogoiter<<endl;

  if (tochnost == 1)
    {
      cout<<"tochnost' DOSTIGNUTA... "<<endl;
    }
  else
    {
      cout<<"tochnost' NE dostignuta... "<<endl;
    }
      Q3.Write();
      cout<<"Prodoljit' rascheti? (y/n)"<<endl;
      dalshe = getch();

     pomoshnik++;
  }
  while (dalshe != 'n');
}
Соседние файлы в папке LABA5