Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабораторная работа №9 / a
.cpp#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <cmath>
#include<iostream>
#include "math.h"
#define min(a,b) (((a)>(b))?(b):(a))
#define max(a,b) (((a)<(b))?(b):(a))
double error=-9999;
unsigned int vusov=0;
#define adr unsigned long
#define right(p) (((adr )p!=NULL))
// структура для вектора
class vect {
public:
unsigned short n; //длина вектора
double * x;
vect() {n=0; x=0;} //конструктор по умолчанию
vect(unsigned short dlin) {n=dlin;if(n!=0) x=new double [n];else x=0;} //создание вектора длины n без инициализации
vect (vect &a) //конструктор копирования
{
n=a.n;
if(n)
{
x=new double [n];
memcpy(x,a.x,n*sizeof(double));
}
else x=0;
}
vect operator = (vect &a)
{
n=a.n;
if(n) x=new double [n]; else x=0;
if(n) memcpy(x,a.x,n*sizeof(double));
return *this;
}
vect mult(double c) //метод класса, для умножения вектора на число
{
vect itog(n) ;
for(int i=0;i<n;i++)
{
itog.x[i]=x[i]*c;
}
return itog;
}
vect sum(vect a) //метод класса, для подсчета суммы векторов
{
if(a.n!=n)
{
printf("Error in sum");
return vect(0);
}
vect itog(n) ;
for(int i=0;i<n;i++)
{
itog.x[i]=x[i]+a.x[i];
}
return itog;
}
vect razn(vect a) //метод класса, для подсчета разности векторов
{
if(a.n!=n)
{
printf("Dif vectors with diff. dimensions");
return vect(0);
}
vect itog(n) ;
for(int i=0;i<n;i++)
{
itog.x[i]=x[i]-a.x[i];
}
return itog;
}
double pr_ch(vect b)// метод для перемножения векторов
{
if(n!=b.n)
{
printf("Dif vectors with diff. dimensions");
return 0;
}
double itog=0;
for(int i=0;i<n;i++)
{
itog=itog+x[i]*b.x[i];
}
return itog;
}
double norm()//подсчет нормы вектора
{
double res=0;
for(int i=0; i<n;i++)
res+=x[i]*x[i];
res=sqrt(res);
return res;
}
};
class matr
{
public:
unsigned short n;
double * x;
matr(unsigned short dlin=0) {n=dlin; if(n) x=new double[n*n];else x=0;}
matr (matr &a) // метод для копирования матриц
{
n=a.n;
if(n) x=new double [n*n]; else x=0;
if(n) memcpy(x,a.x,n*n*sizeof(double));
}
matr operator = (matr &a)// метод для копирования матриц
{
n=a.n;
if(n) x=new double [n*n]; else x=0;
if(n) memcpy(x,a.x,n*n*sizeof(double));
return *this;
}
double & e(unsigned short i,unsigned short j )// метод для определения элемента матрицы
{
if(i>n || j>n )
{printf("Error in e"); return error; }
return x[i*n+j];
}
~matr() {if(right(x)) delete [] x;n=0;x=0;}
matr multm(matr &a, matr &res)// метод для перемножения матриц
{
if(a.n!=n){printf("Error - Mult matrix - different dimensions"); return matr(0);}
memset(res.x,0,n*n*sizeof(double));
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
for(int k=0; k<n; k++)
res.e(i,j)+=e(i,k)*a.e(k,j);
}
}
return res;
}
matr sum(matr a, matr b)// метод для сложения матриц
{
if(a.n!=b.n)
{
printf("Error - Sum matrix - different dimensions");
return matr(0);
}
matr itog(n);
for(int i=0;i<n*n;i++)
{
itog.x[i]=a.x[i]+b.x[i];
printf("i=%d x[i]=%f",i,x[i]);
}
return itog;
}
matr mult(double c)// метод для перемножения матрицы на число
{
int ind=0;
matr itog(n);
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
itog.x[ind]=x[ind]*c;
ind++;
}
}
return itog;
}
vect mult(vect &a)// метод для перемножения матрицы на столбец
{
if(a.n!=n){printf("Error in mult matrix"); return vect(0);}
vect res(n);
memset(res.x,0,sizeof(double)*n);
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
res.x[i]+=e(i,j)*a.x[j];
}
}
return res;
}
matr pr_m(vect a,vect b)// метод для перемножения векторов
{
if(a.n!=b.n)
{
printf("Dif vectors with diff. dimensions");
return matr(0);
}
matr itog(a.n);
int ind=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
itog.x[ind]=a.x[i]*b.x[j];
ind++;
}
}
return itog;
}
matr Gauss()//метод Гаусса для нахождения обратной матрицы
{
int i,j;
matr E(n);
memset(E.x,0,n*n*sizeof(double));
for(i=0;i<n;i++)
E.e(i,i)=1;
for(i=0;i<n;i++)
{
if(e(i,i)==0)
{
int find_not_0 = 0;
for(int j=0; j<n && !find_not_0; j++)
if(j!=i && e(j,i))
{
double *temp=new double[n];
memcpy(temp,x+i*n,n*sizeof(double));
memcpy(x+i*n,x+j*n,n*sizeof(double));
memcpy(x+j*n,temp,n*sizeof(double));
delete [] temp;
find_not_0=1;
}
if(!find_not_0){printf("Det is 0"); return matr(0);
}
}
double d=e(i,i);
for(j=0;j<n;j++)
{
e(i,j)=e(i,j)/d;
E.e(i,j)=E.e(i,j)/d;
}
for(j=0;j<n;j++)
if(j!=i)
{
double d2=e(j,i)/e(i,i);
for(int k=0; k<n;k++)
{
e(j,k)-=e(i,k)*d2;
E.e(j,k)-=E.e(i,k)*d2;
}
}
}
return E;
}
};
int z=0;//выбор функции
int dlin;//число переменных
double y(vect &v)//заданные функции
{
vusov++;
if(z==1)return 8*v.x[0]*v.x[0]+4*v.x[0]*v.x[1]+5*v.x[1]*v.x[1];
if(z==2)return (1.5-v.x[0]*(1-v.x[1]))*(1.5-v.x[0]*(1-v.x[1]))+(2.25-v.x[0]*(1-v.x[1]*v.x[1]))*(2.25-v.x[0]*(1-v.x[1]*v.x[1]))+(2.625-v.x[0]*(1-v.x[1]*v.x[1]*v.x[1]))*(2.625-v.x[0]*(1-v.x[1]*v.x[1]*v.x[1]));
}
//функция для прехода в новую точку вдоль линии
double next(double a, vect &x0, vect &p)
{
return y(x0.sum(p.mult(a)));//y(x+p*a)
}
//функция для расчёта производной
double dy(double a, vect &x0, vect & p)
{
double e=0.000000001;
return (next(a+e/2,x0,p)-next(a-e/2,x0,p))/e;
}
//функция для расчёта градиента
inline vect grad(vect & point)
{
double e=0.000000001;
vect res(point.n);
vect temp(point.n);
for(int i=0; i<point.n;i++)
{
memcpy(temp.x,point.x,point.n*sizeof(double));
temp.x[i]+=e;
res.x[i]=(y(temp)-y(point))/e;
}
return res;
}
//функция для расчёта Гессиана
matr Gessian(vect & point)
{
double e=0.00001;
matr Gess(point.n);
for(int i=0;i<point.n;i++ )
{
vect point_e(point);
point_e.x[i]+=e;
vect res0= (grad(point_e).razn(grad(point))).mult(1/e);
memcpy(Gess.x+i*Gess.n,res0.x,Gess.n*sizeof(double));
}
return Gess;
}
// метод Свенна 4
void Swann4(double a0,vect &x0, vect & p, double &x1, double &x2)
{
double x=0,y1,y2;
if(dy(a0,x0,p)>0) a0=-a0;
y1=dy(a0,x0,p);
do
{
a0*=2;
//x=x+a0;
//y1=next(x,x0,p);
y2=dy(a0,x0,p);
}while(y1*y2>0);
x1=min(a0,a0/2);
x2=max(a0,a0/2);
/*x1=min(x,x-a0/2);
x2=max(x,x-a0/2);*/
printf("\n x1= %f",x1);
printf("\n x2= %f",x2);
}
/*
vect Davidon(vect &x0, vect & p, double *al)
{
vect res(x0.n);
double e=0.000001;
double a,b,c;
Swann4(0.001, x0, p,a,b);
do
{
c=(a+b)/2;
if(c*a>0)
a=c;
else
b=c;
}while(fabs(dy(c,x0,p))>e);
res=x0.sum(p.mult(c));
return res;
}
*/
// метод Дэвидона
vect Davidon(vect &x0, vect & p, double *al)
{
vect res(x0.n);
double e=0.00001;
double a,b;
Swann4(0.000001, x0, p,a,b);
double x1=0,x12=0, z=0, w=0,delta=0;
do{
z =dy(a,x0,p)+dy(b,x0,p)+3*(next(a,x0,p)-next(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);
*al=x1;
res=x0.sum(p.mult(x1));
return res;
}
//шаг метода Коши
vect step(vect &x0)
{
double al;
vect p=grad(x0);
p=p.mult(-1);
vect x=Davidon(x0,p, &al);
return x;
}
//проверка положительной определенности Гессиана
void prov(matr &x1)
{
matr d(x1.n),t(x1.n),sv(x1.n),x(x1.n),tt(x1.n),mu(x1.n),mu1(x1.n),musv(x1.n),tsv(x1.n);
vect l(x1.n-1),vx(x1.n-1),vx1(x1.n);
int n=x1.n,i,j,k,otr=0,par=1,im,jm;
double m=0,e=0.000001;
double al,tg=1,sn,cs,fi;
x=x1;
//делаем матрицу sv еденичной
memset(sv.x,0,n*n*sizeof(double));
for(i=0;i<n;i++)
sv.e(i,i)=1;
//находим матрицу d, такую, что sv*d*tsv=x1,
//причём матрица d диагональная и состоит
//из собственных чисел Гесссиана
do
{
m=0;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if( (m<= fabs(x.e(i,j)) ) && (i!=j) )
{
m=fabs(x.e(i,j));
im=i;
jm=j;
}
}
}
tg=-(2*x.e(im,jm)/(x.e(im,im)-x.e(jm,jm)));
fi=0.5*atan(tg);
sn=sin(fi);
cs=cos(fi);
memset(t.x,0,n*n*sizeof(double));
for(i=0;i<n;i++)
t.e(i,i)=1;
t.e(im,im)=cs;
t.e(jm,jm)=cs;
t.e(im,jm)=sn;
t.e(jm,im)=-sn;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
tt.e(i,j)=t.e(j,i);
}
sv.multm(t,musv);
sv=musv;
tt.multm(x,mu);
mu.multm(t,mu1);
x=mu1;
}while(m>e);
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
tsv.e(i,j)=sv.e(j,i);
}
tsv.multm(x1,mu);
mu.multm(sv,mu1);
d=x;
//проверяем собственные числа на положительность,
//если они отриц. переопределяем
for(i=0;i<n;i++)
if(d.e(i,i)<0)
d.e(i,i)=-d.e(i,i);
//переопределяем Гессиан как sv*d*tsv
sv.multm(d,mu);
mu.multm(tsv,mu1);
x1=mu1;
}
void MakKorm(vect &x0)
{
int i,j, iter=0,k=1;
double e=0.0001,al,kop,znam,b;
vect x2(x0.n),x1(x0.n),d(x0.n),p[10],xn(x0.n);
x1=x0;
x2=x1;
do
{
for(i=0;i<x0.n;i++)
{
if(iter==0)
{
for(j=0;j<x0.n;j++)
{
if(i==j)
p[i].x[j]=1;
else
p[i].x[j]=0;
}
}
else
{
if(i==(x0.n-1))
p[i]=d;
else
p[i]=p[i+1];
}
x2=Davidon(x2,p[i], &al);
}
d=x2.razn(x1);
xn=Davidon(x2,d, &al);
kop=grad(xn).norm();
iter++;
}while(kop>e);
printf("\n\n\nITER=%d, ",iter);
x0=x2;
}
//метод Гринстида
void Greenstid(vect &x0)
{
vect x1,x2,p,agrad;
matr gess,gesso;
int ch=0,i;
double al,kop,e=0.0001;
x1=x0;
do
{
ch++;
printf("\n iter=%d ",ch);
printf("\n Point ");
for(i=0;i<x1.n;i++)
printf("%f, ",x1.x[i]);
agrad=(grad(x1)).mult(-1);//находим антиградиент
printf("\n Agrad ");
for(i=0;i<agrad.n;i++)
printf("%f, ",agrad.x[i]);
gess=Gessian(x1);//находим гессиан
printf("\n Gessian\n");
for(i=0;i<gess.n*gess.n;i++)
{
printf("%f, ",gess.x[i]);
if((i+1)%(gess.n)==0)
printf("\n");
}
getch();
prov(gess);//проверяем гессиан
/*printf("\n Gessian after proverka\n");
for(i=0;i<gess.n*gess.n;i++)
{
printf("%f, ",gess.x[i]);
if((i+1)%(gess.n)==0)
printf("\n");
}
getch();*/
gesso=gess.Gauss();//находим обратный гессиан
printf("\n Obratnui Gessian \n");
for(i=0;i<gesso.n*gesso.n;i++)
{
printf("%f, ",gesso.x[i]);
if((i+1)%(gesso.n)==0)
printf("\n");
}
getch();
p=gesso.mult(agrad);//находим pk= -(H k)-1*grad y k
printf("\n P ");
for(i=0;i<p.n;i++)
printf("%f, ",p.x[i]);
x2=Davidon(x1,p, &al);//переходим в новую точку
printf("\n New point ");
for(i=0;i<x2.n;i++)
printf("%f, ",x2.x[i]);
getch();
kop=(x2.razn(x1)).norm();
x1=x2;
}while(kop>e);
x0=x2;
getch();
}
void main(void)
{
vect x1;
do
{
system("cls");
printf("\nFunction minimum search \n\n\n\n");
printf("\nMenu:\n\n\n");
printf(" 1. 8x1^2 + 4x1x2 + 5x2^2 Min: (0,0)\n\n");
printf(" 2.[1.5 - x1(1 - x2)]^2 + [2.25 - x1(1 - x2^2)]^2 + [2.625 - x1(1 - x2^3)]^2 Min : (3,0.5)\n\n");
printf(" 3.Exit\n\n");
printf("Please select punkt menu(from 1 to 3): ");
scanf( "%d",&z );
if(z<0||z>3)
{
printf("\n Please from 1 to 3 ");
getch();
}
switch(z)
{
case 1:{
dlin=2;
vusov=0;
vect x0(dlin);
x0.x[0]=10;
x0.x[1]=10;
MakKorm(x0);
printf("Min:");
for(int i=0;i<x0.n;i++)
printf("%f, ",x0.x[i]);
getch();
getch();
break;
}
case 2:{dlin=2;
vusov=0;
vect x0(dlin);
x0.x[0]=0;
x0.x[1]=0;
MakKorm(x0);
printf("Min:");
for(int i=0;i<x0.n;i++)
printf("%f, ",x0.x[i]);
getch();
getch();
break;
}
}
}while(z!=3);
}