Лабораторная работа №6 / 6
.docСодержание
-
Описание метода оптимизации 2
-
Пример реализации метода в Mathcad 3
-
Листинг 4
-
Спецификация 7
-
Результаты тестирования 7
-
Ответы на контрольные вопросы 7
-
Вывод 7
Описание метода оптимизации
В данной программе реализован обобщенный метод Ньютона. Стратегия этого метода состоит в построении последовательности точек Хк, таких что f(Xk+1)<f(Xk).
Хк вычисляется по правилу: Xk+1=Xk-alfa*(-(H(Xk))-1 *Gradf(Xk)), где alfa=1- постоянный шаг.
Для квадратичной функции метод доставляет минимум из любой точки пространства за одну итерацию.
Листинг программы:
#include <conio.h>
#include <iostream.h>
#include <math.h>
// Подключаем класс для работы с матрицами
#include "matrix.cpp"
double f(TMatrix<double> &x,int fun)
{
switch(fun)
{
case 1:
return x[1]*x[1]+2*x[2]*x[2]-2*x[1]*x[2]+x[2];
// return 100*pow(x[2]-x[1]*x[1],2)+pow(1-x[1],2); // 19)
break;
case 2:
return x[1]*x[1]-2*x[2]*x[2]+3*x[3]*x[3]-4*x[1]*x[2]+5*x[2]*x[3]-6*x[1]*x[3];
// return pow(x[1]-1,2)+pow(x[2]-3,2)+4*pow(x[3]+5,2); // 20)
break;
default:cout<<"Such variant of a choice is not possible!"<<endl;
break;
}
}
// Численное вычисление производной любой функции в точке "х" по направлению "р"
double df(TMatrix<double> &x,TMatrix<double> &p, int fun)
{
double eps=0.0001;
return (f(x+p*eps,fun)-f(x,fun))/(eps);
}
// Возвращает направление поиска, параллельное оси координат
TMatrix<double> Ord(int size, int i) // size - число переменных функции
// i - число обращений к этой функции
{
TMatrix<double> res(size,1);
for(int k=1; k <= size; k++)
{
if (k!=i)
{
res[k]=0;
}
else
{
res[k]=1;
}
}
return res;
}
// Возвращает вектор градиента функции в точке "х"
TMatrix<double> Grad(TMatrix<double> &x,int fun)
{
int i=x.getSizeRow();
TMatrix<double> res(i,1);
for (int k = 1;k<=i;k++)
{
res[k]=df(x,Ord(i,k),fun);
}
return res;
}
// Вычисление матрицы Гессе
TMatrix<double> ddf(TMatrix<double> &x,int fun)
{
double eps=0.0001;
int ln=x.getSizeRow();
TMatrix<double> res(ln,ln);
TMatrix<double> ei(ln,1), ej(ln,1);
int m=ln, n=ln;
for (int i=1; i<=m;i++)
{
for(int j=1; j<=n; j++)
{
ei=Ord(ln,i);
ej=Ord(ln,j);
res(i,j)=(f(x+ei*eps+ej*eps,fun)-f(x+ei*eps,fun)-f(x+ej*eps,fun)+f(x,fun))/(eps*eps);
}
}
return res;
}
// Критерий окончания поиска
double norma(TMatrix<double> &x)
{
double res=0;
int m=x.getSizeRow(), n=x.getSizeCol();
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
{
res+=fabs(x(i,j)*x(i,j));
}
}
return sqrt(res);
}
// Нахождение обратной матрицы методом Гаусса
TMatrix<double> gauss(TMatrix<double> mat)
{
TMatrix<double> count(mat.getSizeRow(),1);
TMatrix<double> i; i.setSingle(mat.getSizeRow());
double tmp; //делитель
int r=1;//проход по строрке
for (int z=1; z <= mat.getSizeRow(); z++)
{
for (int k=1; k <= mat.getSizeRow(); k++)
{//проход по столбцам
tmp=mat(k,z);
for (int j=1; j <=mat.getSizeRow(); j++)
{//проход по строкам
mat(k,j)=mat(k,j)/tmp;
i(k,j)=i(k,j)/tmp;
}
}
for (int j=1; j <=mat.getSizeRow(); j++)
{
for (int l=1; l<=mat.getSizeRow(); l++)
{
if (l != z)
{
mat(l,j)=(-1)*mat(z,j)+mat(l,j);
i(l,j)=(-1)*i(z,j)+i(l,j);
}
}
}
}
for (int k=1; k <= mat.getSizeRow(); k++)
{
if (mat(k,k) != 1)
{
for (int j=1; j <= mat.getSizeRow(); j++)
{
i(k,j)=i(k,j)/mat(k,k);
}
}
}
return i;// Возвращаем обратную матрицу
}
// Обобщенный метод Ньютона
TMatrix<double> Nuton(TMatrix<double> x,double eps,int &max_step,int fun)
{
// Переменные
double e=eps;
TMatrix<double> xNew,p,dy,H;
int iter=0;
double alfa;
// Установка размера матриц и векторов
xNew.setSize(x.getSizeRow(),x.getSizeCol());
H.setSize(x.getSizeRow(),x.getSizeRow());
dy.setSize(x.getSizeRow(),x.getSizeCol());
p.setSize(x.getSizeRow(),x.getSizeCol());
xNew=x;
alfa=1;
// Сам метод
do
{
dy=Grad(xNew,fun);
H=ddf(xNew,fun);
p=gauss(H)*dy*(-1);
xNew=x-alfa*p;
iter++;
}
while((norma(p)>=e)&&(iter<max_step));
// Для квадратичной функции метод должен возвращать минимум за 1 итерацию
max_step=iter;
return xNew;
}
// Основная программа
void main()
{
double norm;
int fun, iter, n, i;
TMatrix<double> xs, Min, Min1;
cout<<"1) x^2+2*y^2-2*x*y+y"<<endl;
cout<<"2) x^2-2*y^2+3*z^2-4*x*y+5*y*z-6*x*z"<<endl;
cout<<"Enter number of the chosen function for testing:"<<endl;
cin>>fun;
switch(fun)
{
case 1:
n=2;
xs.setSize(n,1);
break;
case 2:
n=3;
xs.setSize(n,1);
break;
default:cout<<"Such variant of a choice is not possible!"<<endl;
break;
}
for(i=1; i<=n; i++)
{
xs[i]=1;
}
cout<<"Enter restriction on a maximum quantity of iterations:"<<endl;
cin>>iter;
Min=Grad(xs,fun);
cout<<"\nGradient:"<<endl;
Min.writeArray();
Min1=ddf(xs,fun);
cout<<"\nGesse:"<<endl;
Min1.writeArray();
norm=norma(xs);
cout<<"\nNorma:"<<endl;
cout<<norm;
Min=Nuton(xs,0.000000001,iter,fun);
cout<<"\n\nHave received a minimum:"<<endl;
Min.writeArray();// Вывод полученного минимума
cout<<"\nQuantity of iterations: "<<iter<<endl; // Сколько итераций было действительно выполнено
}
Спецификация программы
В программе используется класс Matrix, позволяющий работать с матрицами произвольного размера. Для класса Matrix описан ряд функций-инструментов, которые позволяют решать любые задачи по построению и обработке матриц, необходимых пользователю для работы. Элемент класса Matrix строится на основе двумерного массива, создаваемого динамически.
Результаты тестирования программы
Для функции f(x1,x2) = x1^2+2*x2^2-2*x1*x2+x2:
Значение Е |
10-3 |
10-5 |
10-7 |
10-9 |
Количество итераций |
1 |
1 |
1 |
1 |
Для функции f(x1,x2,x3) = x^2-2*y^2+3*z^2-4*x*y+5*y*z-6*x*z:
Значение Е |
10-3 |
10-5 |
10-7 |
10-9 |
Количество итераций |
1 |
1 |
1 |
1 |
Ответы на контрольные вопросы
1. Что такое ньютоновское направление поиска.
Ньютоновским называется направление, полученное путем перемножения обратной матрицы Гессе на вектор градиента в заданной точке, взятого с противоположным знаком.
2. Каким образом можно проверить положительную определенность Гессиана.
Симметричная матрица Гессе является положительно определенной тогда и только тогда, когда все ее угловые миноры положительны.
3. Какие достоинства есть у метода Ньютона по сравнению с уже известными вам методами.
Метод Ньютона – самый быстрый метод, если выполнено условие сходимости. При правильном выборе начальной точки метод Ньютона сходится за одно итерацию.
4. Есть ли у метода Ньютона какие-либо недостатки, если есть, то как они могут быть устранены.
У метода Ньютона есть три недостатка:
-
Чувствительность к выбору начальной точки;
-
Требование положительной определенности матрицы Гессе;
-
Трудоемкость решения системы Hk∆xk=-grad(yk);
Эти недостатки пытаются устранить модификации метода Ньютона, в частности, метод Ньютона с регулировкой (дроблением) шага, который рассматривается в данной лабораторной работе.
5. Какова геометрическая интерпретация метода Ньютона и его модификаций.
Геометрически метод Ньютона представляет собой процесс последовательного отыскания точек пересечения касательных, проведенных к графику функции, с осью абсцисс, пока не придем в искомую точку x*. Искомая функция при этом аппроксимируется параболой.
Вывод
Метод, действительно, самый быстрый, но результат очень сильно зависит от выбора точки начального приближения. В этом, на мой взгляд, его огромный недостаток, который можно исправить, например, введя регулировку шага.