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

class vector  
{

private:
	int num, fun, d;
	double x[5], p[5], step, l;

public:
	vector();
	void InputDot(int n, int fun1, int def);
	void PassInfo();
	double Function(double k);
	double Differential(int n, double k);
	void Gradient(int n);
	double CreateStep();
	void OutResult();

};

vector::vector() // "Пустой" вектор
{ 
	for (int i=0; i<5; i++)
	{
		x[i]=0;
		p[i]=0;
	}
	step=0; // Шаг
	l=0; // Длина
	fun=0; // Функция для работы еще не выбрана
}

void vector::InputDot(int n, int fun1, int def) // Задаем начальную точку
{
	cout<<"Enter coordinates of an index point\n";
	for (int i=0; i<n; i++)
	{
		cout<<"x["<<i<<"] :";
		cin>>x[i];
	}
	num=n;// Запоминаем с каким количеством переменных работаем
	fun=fun1; // Фиксируем номер выбранной функции
	d=def; // Выбранный тип дифференцирования
}

void vector::PassInfo() //Новая координата вектора, образованная путем смещения
{
	for (int i=0; i<num; i++) // Уже знаем кол-во переменных
	{
		x[i]=x[i]+step*p[i]; // Уже знаем значение step
	}
}

double vector::Function(double k) // Меню выбора тестовой функции
{
	switch(fun)
	{
	case 1:
		return (x[0]+k*p[0])*(x[0]+k*p[0])+2*(x[1]+k*p[1])*(x[1]+k*p[1])-2*(x[0]+k*p[0])*(x[1]+k*p[1])+(x[1]+k*p[1]);
		break;
	case 2:
		return (x[0]+k*p[0]-1)*(x[0]+k*p[0]-1)+(x[1]+k*p[1]-3)*(x[1]+k*p[1]-3)+4*(x[2]+k*p[2]+5)*(x[2]+k*p[2]+5);
		break;
	case 3:
		return 100*((x[1]+k*p[1])-(x[0]+k*p[0])*(x[0]+k*p[0]))*((x[1]+k*p[1])-(x[0]+k*p[0])*(x[0]+k*p[0]))+(1-(x[0]+k*p[0]))*(1-(x[0]+k*p[0]));
		break;
	default:
		return 0;
	}
}

double vector::Differential(int n, double k) //Частные производные функции
{
	double x1, h=0.0000001, d1, d2; // Потребуется для численного дифференцирования
	if(d==1) // Аналитический тип дифференцирования
	{
		switch(fun) // в зависимости от номера функции
		{
		case 1:
			switch(n)  // в зависимости от переменной, по которой дифференцируют
			{
			case 0:
				return 2*((x[0]+k*p[0])-(x[1]+k*p[1]));
			case 1:
				return 4*(x[1]+k*p[1])-2*(x[0]+k*p[0])+1;
			default:
				return 0;
			}
		case 2:
			switch(n)  // в зависимости от переменной, по которой дифференцируют
			{
			case 0:
				return 2*(x[0]+k*p[0]-1);
			case 1:
				return 2*(x[1]+k*p[1]-3);
			case 2:
				return 8*(x[2]+k*p[2]+5);
			default:
				return 0;
			}
		case 3:
			switch(n)  // в зависимости от переменной, по которой дифференцируют
			{
			case 0:
				return -400*((x[1]+k*p[1])-(x[0]+k*p[0])*(x[0]+k*p[0]))-2*(1-(x[0]+k*p[0]));
			case 1:
				return 200*((x[1]+k*p[1])-(x[0]+k*p[0])*(x[0]+k*p[0]));
			default:
				return 0;
			}
		default:
			return 0;
		}
	}
	else  // Численное дифференцирование
	{
		x1=x[n]; // Переменную, по которой дифференцируем, обзываем x1
		x[n]=x[n]-h;
		d1=Function(0);
		x[n]=x[n]+2*h;						
		d2=Function(0);
		x[n]=x1;
		return (d1+d2)/2*h;
	}
}

void vector::Gradient(int n)  //Градиент - вектор из частных производных
{
	for(int i=0; i<num; i++)
	{
		if(i==n)
			p[i]=Differential(i,0);
		else
			p[i]=0;
	}
}

double vector::CreateStep() // Получим step - результат одномерной минимизации
{
	double h1,x_1,x_2,a,b,n,e;
	int k=0;
	h1=0.01;
	x_1=h1;
	if(Function(0)<Function(x_1)) //  Метод Свенна
	{
		h1=-h1;
		x_1=h1;
	}
	do
	{
		h1=2*h1;
		x_1=x_1+h1;
	}
	while(Function(x_1-h1)>Function(x_1));
	a=x_1-1.5*h1; // Получили отрезок
	b=x_1;
	if(a>b) // Для удобства переименовали границы
    {
      n=a;
      a=b;
      b=n;
    }
	e=0.001;
	x_1=a+0.618*fabs(b-a); // Локализуем минимум методом Золотого Сечения 2
	do
	{
		x_2=a+b-x_1;
		if((x_1<x_2)&&(Function(x_1)<Function(x_2)))
			b=x_2;
		if((x_1<x_2)&&(Function(x_1)>=Function(x_2)))
		{
			a=x_1;
			x_1=x_2;
		}
		if((x_1>x_2)&&(Function(x_1)<Function(x_2)))
			a=x_2;
		if((x_1>x_2)&&(Function(x_1)>=Function(x_2)))
		{
			b=x_1;
			x_1=x_2;
		}
		k++;
	}
	while((fabs(b-a)>e)&&(k<200));
	step=(a+b)/2; // Найденый минимум
	return step;
}

void vector::OutResult() // Вывод результата на экран
{
	cout<<"The following coordinates of a point of a minimum are received:\n";
	for(int i=0;i<num;i++)
	{
		cout<<x[i]<<" ";
	}
	cout<<'\n';
}

void main()
{
	vector X;
	double e, s;
	int k=0, M, i, number, flag=1, fun1, def;

	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>>fun1;

	switch(fun1)
	{
	case 1:
		number=2;
		break;
	case 2:
		number=3;
		break;
	case 3:
		number=2;
		break;
	default:
		number=0;
		break;
	}

	cout<<"Enter accuracy for criterion of the ending of search: e=";
	cin>>e;
	cout<<"Set restrictions on amount of iterations: M=";
	cin>>M;
	cout<<"Enter type of differentiation:\n";
	cout<<"1   -   Analytical\n";
	cout<<"2   -   Numerical\n";
	cin>>def;
	X.InputDot(number, fun1, def);

	do
	{
		for(i=0; i<number; i++)
		{
			X.Gradient(i);
			s=X.CreateStep();
			X.PassInfo();
		}
		k++;
	}
	while((fabs(X.Function(0)-X.Function(-s))>=e)&&(k<M)); //Главным образом, здесь е влияет на результат
	cout<<"Quantity of the executed steps: "<<k<<'\n';
	X.OutResult();
}
Соседние файлы в папке Лабораторная работа №5