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

#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))

#define Eps 0.001

class Vector
{
	public:
		double x1;
		double x2;
		Vector (double a, double b) {x1 = a; x2 = b;}
		Vector (void) {};
};

double mod (double x)
{
	return (x > 0) ? x : -x;
}

// Заданная функция
double F (Vector X) 
{ 
	//return 8 * X.x1 * X.x1 + 4 * X.x1 * X.x2 + 5 * X.x2 * X.x2; 
	return (X.x2-X.x1)*(X.x2-X.x1) + (1-X.x1)*(1-X.x1);
}


// Градиент в точке Х
Vector Grad (Vector X)
{
	//Vector g (16*X.x1 + 4*X.x2, 4*X.x1 + 10*X.x2);
	Vector g (4*X.x1-2*X.x2-2, 2*X.x2-2*X.x1);
	return g;
}

// Производная в точке Х по направлению Р
double dF_dA (Vector X, Vector p, double Alpha)
{
	Vector t (X.x1 + Alpha * p.x1, X.x2 + Alpha * p.x2);
	Vector g = Grad(t);
	return g.x1*p.x1 + g.x2*p.x2;
}

// Значение одномерной функции от Alpha по направлению р из точки х
double F_A (Vector x, Vector p, double Alpha)
{
	Vector Z (x.x1 + Alpha*p.x1, x.x2 + Alpha*p.x2);
	return F(Z);
}

// Метод Свенна-4
void Swann4 (double *a, double *b, Vector x, Vector p)
{
	double Alpha = 0.001;// * mod(F(x));
	printf ("F:Swann4: Alpha = %f\n", Alpha);
	if (dF_dA (x, p, Alpha) > 0) {p.x1 = -p.x1; p.x2 = -p.x2;}
	while (dF_dA (x, p, Alpha) * dF_dA (x, p, 2*Alpha) > 0) 
	{
		//printf ("F:Swann4: dF_dA = %f, %f; alpha = %f\n", dF_dA (x, p, Alpha), dF_dA (x, p, 2*Alpha), Alpha);
		Alpha *= 2;
		//getch ();
	}
	*a = min(Alpha/2, 2*Alpha);
	*b = max(Alpha/2, 2*Alpha);
}


double Davidon (double a, double b, Vector x, Vector p)
{
	double z = 0;

	while ((b-a) > Eps)
	{
		z = (a + b) / 2;
		if (dF_dA(x, p, z) > 0) b = z;
		else a = z;
	}

    return z;
}

double Davidon1 (double a, double b, Vector x, Vector p)
{
	double z, w, g, min;
	bool done = false;

	// f'(a) = dF_dA (x, p, a)
	// f'(b) = dF_dA (x, p, b)
	// f (a) = F (x, p, a)
	// f (b) = F (x, p, b)
	
	while (!done)
	{
		z = dF_dA (x, p, a) + dF_dA (x, p, b) + 3 * ((F_A (x, p, a) - F_A (x, p, b))/b);
		w = sqrt (z*z - dF_dA (x, p, a) * dF_dA (x, p, b));
		g = (z - dF_dA (x, p, a) + w) / (dF_dA (x, p, b) - dF_dA (x, p, a) + 2*w);
		min = a + g * (b - a);

		done = (mod(dF_dA (x, p, min)) < Eps) || (min == a) || (min == b);

		if (!done)
		{
			if (dF_dA (x, p, min) > 0) b = min;
			else a = min;
		}
	}

	return min;
}

// Овражный метод
Vector OvragMetod (Vector X1)
{
	// Начальный этап
	double Eps1 = 0.001;			// Приближение
	double Eps2 = 0.001;			// Точность
	double a, b;					// Для метода Свенна
	Vector X1m (X1.x1 + Eps1, X1.x2);
	Vector X1r (X1.x1, X1.x2);
	Vector d, X3 (X1.x1, X1.x2);
	Vector stop;
	double Alpha;

	// Основной этап
	printf ("X1r = (%f, %f)\n", X1r.x1, X1r.x2);
	printf ("X1m = (%f, %f)\n", X1m.x1, X1m.x2);

	do
	{
		X1r.x1 = X3.x1; X1r.x2 = X3.x2;
		X1m.x1 = X3.x1 + Eps1; X1m.x2 = X3.x2;
		Vector grad = Grad(X1r);
		printf ("grad = (%f, %f)\n", grad.x1, grad.x2);
		grad.x1 *= -1; grad.x2 *= -1;
		printf ("new grad = (%f, %f)\n", grad.x1, grad.x2);
		Vector Direction (grad.x1, grad.x2);				// Направление антиградиента
		printf ("Direct = (%f, %f)\n", Direction.x1, Direction.x2);

		Swann4 (&a, &b, X1r, Direction);
		printf ("Swann4 = (%f, %f)\n", a, b);
		Alpha = Davidon(a, b, X1r, Direction);
		printf ("Davidon = %f\n", Alpha);
		Vector X2r (X1r.x1 + Alpha*Direction.x1, X1r.x2 + Alpha*Direction.x2);
		printf ("X2r = (%f, %f)\n", X2r.x1, X2r.x2);
		Vector X2m (X1m.x1 + Alpha*Direction.x1, X1m.x2 + Alpha*Direction.x2);
		printf ("X2m = (%f, %f)\n", X2m.x1, X2m.x2);

		d.x1 = X2r.x1 - X2m.x1; d.x2 = X2r.x2 - X2m.x2;		// Направление ускорения
		printf ("d = (%f, %f)\n", d.x1, d.x2);
		Swann4 (&a, &b, X2r, d);
		printf ("Swann4_2 = (%f, %f)\n", a, b);
		Alpha = Davidon (a, b, X2r, d);
		printf ("Alpha = %f\n", Alpha);
		X3.x1 = X2r.x1 + Alpha*d.x1; X3.x2 = X2r.x2 + Alpha*d.x2;
		printf ("X3 = (%f, %f)\n", X3.x1, X3.x2);

		stop = Grad(X3);
		printf ("sqrt = %f\n\n\n", sqrt(stop.x1*stop.x1 + stop.x2*stop.x2));
		
		//getch ();
	}
	while (sqrt(stop.x1*stop.x1 + stop.x2*stop.x2) > Eps2);

	return X3;
}


void main (void)
{
	Vector	StartPoint (10, 10);
	Vector	min = OvragMetod (StartPoint);
	printf ("Minimum: (%f, %f)\n", min.x1, min.x2);

	getch();
}
Соседние файлы в папке MO_Lab4