
Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабораторная работа №42 / Lab_4 / LABA43
.CPP#include <iostream.h>
#include <conio.h>
#include <math.h>
#include <stdio.h>
#define min(a,b) (((a)>(b))?(b):(a))// функция для определения минимума
#define max(a,b) (((a)<(b))?(b):(a))//функция для определения максимума
int i=1;
// структура для вектора
struct vect {
double x; //координата х
double y; //координата у
double z; //координата z
double norm() {return sqrt(x*x+y*y+z*z);} //норма вектора
};
// возвращаем значение функции у от вектора х
double y(vect &x)
{
return 3*(x.x-4)*(x.x-4)+5*(x.y+3)*(x.y+3)+7*(2*x.z+1)*(2*x.z+1);
}
// заданная функция
double y(double x, double y, double z)
{
return 3*(x-4)*(x-4)+5*(y+3)*(y+3)+7*(2*z+1)*(2*z+1);
}
//функция для прехода в новую точку
double f(double a, vect &x0, vect &p)
{
vect x;
x.x=x0.x+p.x*a;
x.y=x0.y+p.y*a;
return y(x);
}
//считаем длину вектора
double Length(vect &x1, vect &x2)
{
return sqrt((x1.x-x2.x)*(x1.x-x2.x)+(x1.y-x2.y)*(x1.y-x2.y)+(x1.z-x2.z)*(x1.z-x2.z));
}
//считаем производную
double dy(double a, vect &x0, vect & p,double e=0.001)
{
return (y( x0.x+p.x*(a+e), x0.y+p.y*(a+e), x0.z+p.z*(a+e) )-y( x0.x+p.x*a, x0.y+p.y*a, x0.z+p.z*a))/(p.norm()*e);
}
inline vect Grad(vect &point,double e=0.000001)
{
vect px; px.x=point.x+e; px.y=point.y; px.z=point.z;
vect py; py.x=point.x; py.y=point.y+e; py.z=point.z;
vect pz; pz.x=point.x; pz.y=point.y; pz.z=point.z+e;
vect res;
res.x=(y(px)-y(point))/e;
res.y=(y(py)-y(point))/e;
res.z=(y(pz)-y(point))/e;
return res;
}
// метод Свенна 4
void Swann4(double a0,vect &x0, vect & p, double &x1, double &x2)
{ double x=0;
vect v;
double dy1=dy(0,x0,p);// берем производную в начальной точке
double a=min(2,fabs(2*(y(x0)-dy1)/dy1));
v = Grad( x0 );
if( v.x > 0 || v.y > 0 || v.z > 0)//меняем направление
{a0=-a0;}
while(dy(a0,x0,p)*dy1>0)// пока производная не поменяла знак
{
a0*=2;// удваиваем шаг
x=x+a0;//запоминаем новую точку
};
//получаем интервал
x1=min(x,x-a0*2);
x2=max(x,x-a0*2);
}
// метод Дэвидона
double Davidon(vect &x0, vect & p)
{ vect res;
double e=0.00001;// погрешность
// устанавливаем интервал [a,b]
double a,b;
Swann4(0.001, x0, p,a,b);
printf("\n a=%f , b = %f", a,b);
double x1=0, z=0, w=0, x12, delta=0;
do{
z =dy(a,x0,p)+dy(b,x0,p)+3*(f(a,x0,p)-f(b,x0,p))/(b-a);
w =sqrt(z*z-dy(a,x0,p)*dy(b,x0,p));
delta =(z-dy(a,x0,p)+w)/(dy(b,x0,p)-dy(a,x0,p)+2*w);
x12=x1;
x1=a+delta*(b-a);
//сокращаем текущий интервал локализации
if(dy(x1,x0,p)>0) {b=x1;}
else {a=x1;}
}while(fabs(dy(x1,x0,p))>e);
return delta;
}
//Циклический покоординатный спуск
void CPS( vect &x1, double e2=0.0001 )
{
vect x2;
vect p;
double a;
int k=0;
printf("\nЦиклический покоординатный спуск:\n");
printf("\nШаг, x1 x2 \n");
do
{ //координаты вспомогательной точки
p.x = 1; //Изменяем значение х
p.y = 0;
p.z = 0;
// p = antiGrad(x1);
a = Davidon(x1,p);
getch();
x2.x = x1.x + a;
p.x = 0; //Изменяем значение у
p.y = 1;
p.z = 0;
a = Davidon(x1,p);
x2.y = x1.y + a;
p.x = 0; //Изменяем значение z
p.y = 0;
p.z = 1;
a = Davidon(x1,p);
x2.z = x1.z + a;
printf("%d [%f %f %f] \t[%f %f %f]\n",i,x1.x,x1.y,x1.z,x2.x,x2.y,x2.z);
if( k=(Length(x1,x2)>e2))
{
x1.x = x2.x;
x1.y = x2.y;
x1.z = x2.z;
}
i++;
}
while(k);
printf("\n\tMinimum: [%f %f %f]", x2.x, x2.y, x2.z );
}
void main()
{
vect x0={2,-2,-2};
clrscr();
CPS(x0);
getch();
}
Соседние файлы в папке Lab_4