Скачиваний:
4
Добавлен:
01.05.2014
Размер:
12.39 Кб
Скачать
#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);

 
}
Соседние файлы в папке Лабораторная работа №9
  • #
    01.05.201412.39 Кб4a.cpp
  • #
    01.05.20143.34 Кб4a.dsp
  • #
    01.05.2014527 б4a.dsw
  • #
    01.05.201433.79 Кб4a.ncb
  • #
    01.05.201448.64 Кб4a.opt
  • #
    01.05.20141.49 Кб4a.plg