Укрупнённая блок-схема
Да Нет
p=(grad(x1)).mult(-1);
p=((grad(x1)) .mult(-1)).mult(b);
b=grad(x1).pr_ch(grad(x1p)); znam=p.pr_ch(grad(x1p)); b=b/znam; x2=Davidon(x1,p,&al); k++; x1p=x1; x1=x2; if(k>x0.n) k=1; iter++; kop=grad(x1).norm();
Да
Нет
Ответы на вопросы
1) Выполнить 2 шага аналитического решения задачи Вашего варианта задания
2) Являются ли направления p1 = (0; 1)t и p2 = (1; 0)t линейно независимыми? Ортогональными?
Так как a*p1+b*p2≠0 при любых a и b одновременно не равных 0, то вектора p1 и p2 являются линейно независимыми
Так как p1*p2=0, то вектора p1 и p2 являются ортогональными
3) Определить характер матрицы Гессе функции y(x) = (x2 – x1)2 + + (1 – x1)2 в точке минимума x* = (1; 1)t. Используя матрицу Гессе найти направление, сопряженное к p = (1; 0)t
Вывод
В данной работе были изучены методы сопряженных градиентов для поиска минимума целевых функций. В работе был исследован метод Диксона.
Текст программы с комментариями
#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;
}
};
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;
}
// метод Свенна 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;
y2=dy(a0,x0,p);
}while(y1*y2>0);
x1=min(a0,a0/2);
x2=max(a0,a0/2);
}
// метод Дэвидона
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 Dikson(vect &x0)
{
int k=1,i, iter=1;
double e=0.0001,al,kop,znam,b;
vect agrad,p,x1(x0.n),x1p(x0.n),x2(x0.n),dx,gamma,s(x0.n);
x1=x0;
x1p=x0;
do
{
if(k==1)
p=(grad(x1)).mult(-1);
else
p=((grad(x1)).mult(-1)).mult(b);
b=grad(x1).pr_ch(grad(x1p));
znam=p.pr_ch(grad(x1p));
b=b/znam;
x2=Davidon(x1,p, &al);//переходим в новую точку
printf("\n ");
for(i=0;i<x2.n;i++)
printf("%f, ",x2.x[i]);
k++;
x1p=x1;
x1=x2;
if(k>x0.n)
k=1;
iter++;
kop=grad(x1).norm();
}while(kop>e);
printf("\n\n\nITER=%d, ",iter);
x0=x2;
}
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;
Dikson(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;
Dikson(x0);
printf("Min:");
for(int i=0;i<x0.n;i++)
printf("%f, ",x0.x[i]);
getch();
getch();
break;
}
}
}while(z!=3);
}