Лабораторная работа №3
Минимизация функции многих переменных методом градиента с дроблением шага.
Выполнил студент группы ПВ-22
Воробьев Роман
Вариант № 3
f(x,y)=x2 + y2 + xy – 3x -6y
1) Найти точное решение задачи, используя необходимые и достаточные условия локального минимума.
2) Выполнить один шаг метода градиента с дроблением шага, начиная с произвольного выбранного начального приближения.
3) Записать ответ: (x; y) — приближенные координаты точки локального минимума; fmin = f(x; y) — приближенное минимальное значение; — точность результата; m — количество выполненных итераций.
4) Выполнить задание Л.Р. №2 методом градиента с дроблением шага.
-
Составить программу вычисления координат точки локального минимума и минимального значения функции двух переменных.
Программа должна использовать логическую функцию, описанную в модуле, с побочным эффектом для нахождения локального минимума функции двух переменных.
Входными данными для этой логической функции являются: минимизируемая функция; ее градиент; начальное приближение к точке локального минимума; точность; ограничение n на число итераций; параметры .
Спецификация подпрограммы met_grad:
-
Заголовок: bool met_grad (double (*f)(double,double), double(**grad)(double,double), point *m0, double E, int n, double a, double b, double g,double *result)
-
Назначение: Функция возвращает значение «истина», если приближенное решение минимизируемой функции f(x) с ее градиентом grad, параметрами a, b, g, и начальным приближением к точке локального минимума m0(х0,у0) получено за число итераций, не превышающее n, с точностью E. Значение координат точки локального минимума записывается в m0(x,y), а значение функции f(x) в этой точке в result. Иначе, функция возвращает значение «ложь».
-
Входные параметры: f, grad, m0, E, n, a, b, g;
-
Выходные параметры: result;
#ifndef GRAD_H_INCLUDED
#define GRAD_H_INCLUDED
typedef struct point
{
double x,y;
};
/*==Метод градинта 1-способ==*/
bool met_grad (double (*f)(double,double), double(**grad)(double,double), point *m0, double E, int n, double a, double b, double g,double *result)
{
int i=0,step=0;
point gra,m1;
double F0,F1,d,T1,T2;
gra.x=grad[0]((*m0).x,(*m0).y);
gra.y=grad[1]((*m0).x,(*m0).y);
F0=f((*m0).x,(*m0).y);
do
{
d=a*pow(g,i);
T1=f((*m0).x-d*gra.x,(*m0).y-d*gra.y);
T2=(-d*b*(pow(gra.x,2)+pow(gra.y,2)));
//printf("i=%i step=%i\nT=%lf <= T2=%lf\n m0.x=%lf m0.y=%lf\n m1.x=%lf m1.y=%lf alp=%lf\n",i,step,T1,T2,(*m0).x,(*m0).y,(*m0).x-a*gra.x,(*m0).y-a*gra.y,a);
if ((T1-F0)<=(T2))
{ a=d;
m1.x=(*m0).x-a*gra.x;
m1.y=(*m0).y-a*gra.y;
F1=f(m1.x,m1.y);
gra.x=grad[0](m1.x,m1.y);
gra.y=grad[1](m1.x,m1.y);
//printf("\F1-F0=%lf (gra.x^2+gra.y^2)^0.5=%lf\n",F1-F0,(sqrt(pow(gra.x,2)+pow(gra.y,2))));
if (((F1-F0)<E)&&(sqrt(pow(gra.x,2)+pow(gra.y,2))<E))
break;
else
{
F0=F1;
(*m0).x=m1.x;
(*m0).y=m1.y;
a=d;
i=0;
step++;
}
}
else
i++;
}
while ((i<n)&&(step<n));
(*m0).x=m1.x;
(*m0).y=m1.y;
*result=f((*m0).x,(*m0).y);
return (step<n)&&(i<n);
}
/*==Ввод данных==*/
bool input_data(point *m0, double *e, int *n,double *alpha,double *beta,double *gamma)
{
printf("Enter initial данные:начальное M approach (х0, у0), accuracy е, a quantity of iterations n\n");
printf("x0=");
scanf("%lf",&(*m0).x);
printf("y0=");
scanf("%lf",&(*m0).y);
printf("E=");
scanf("%lf",e);
printf("n=");
scanf("%i",n);
printf("alpha=");
scanf("%lf",alpha);
printf("beta=");
scanf("%lf",beta);
printf("gamma=");
scanf("%lf",gamma);
if (*alpha<=0 || *beta <0 || *beta >1 || *gamma <0 || *gamma >1)
{
printf("Inadmissible values!!!\n");
return false;
}
else return true;
}
/*==Метод градинта 2-способ==*/
bool min_grad(double (*f)(double,double),double(**grad)(double,double),point *m0, double e,int n, double alpha0, double beta, double gamma, double *rezult)
{
double t,k,d;
int i=0,j=0;
double f1,f2;
bool F=false;
double alpha=alpha0;
point gra,m1;
gra.x=grad[0]((*m0).x,(*m0).y);
gra.y=grad[1]((*m0).x,(*m0).y);
do
{
j=0;
do
{
d=alpha*pow(gamma,j);
m1.x=(*m0).x-d*gra.x;
m1.y=(*m0).y-d*gra.y;
f1=f(m1.x,m1.y)-f((*m0).x,(*m0).y);
t=pow(gra.x,2)+pow(gra.y,2);
f2=-beta*d*t;
j++;
}
while ((f1>f2)&&(j<=n));
if ((f1<=f2)&&(j<=n))
{
alpha=alpha*pow(gamma,(j-1));
d=alpha*pow(gamma,(j-1));
m1.x=(*m0).x-d*gra.x;
m1.y=(*m0).y-d*gra.y;
t=sqrt(pow(m1.x,2)+pow(m1.y,2));
k=fabs(f(m1.x,m1.y)-f((*m0).x,(*m0).y));
}
else
{
printf("Think over the initial data\n");
return false;
}
if(k<e||t<e)
F=true;
(*m0).x=m1.x;
(*m0).y=m1.y;
gra.x=grad[0](m1.x,m1.y);
gra.y=grad[1](m1.x,m1.y);
++i;
}
while(!F&&i<=n);
if (F)
{
*rezult=f((*m0).x,(*m0).y);
return true;
}
else
{
printf("Think over the initial data\n");
return false;
}
}
#endif // GRAD_H_INCLUDED
Текст основной программы:
// Bbl4MaT3.cpp: главный файл проекта.
#include "stdafx.h"
#include <iostream>
#include <math.h>
#include "GRAD.h"
using namespace System;
using namespace std;
/*======================1=========*/
double funct (double x, double y) // 0 3 = -9
{
return (x*x+y*y+x*y-3*x-6*y);
}
double dx (double x,double y)
{
return 2*x+y-3;
}
double dy (double x,double y)
{
return 2*y+x-6;
}
int main(array<System::String ^> ^args)
{
double (*grad[2])(double,double)={dx,dy};
double a,b,g,E,result,x0,y0;
point m0;
int n;
if (input_data(&m0,&E,&n,&a,&b,&g))
{
x0=m0.x; y0=m0.y;
if (min_grad(funct,grad,&m0,E,n,a,b,g,&result))
printf("x=%lf, y=%lf result=%lf\n",m0.x,m0.y,result);
else printf("step>max\n");
m0.x=x0; m0.y=y0;
if (met_grad(funct,grad,&m0,E,n,a,b,g,&result))
printf("\n\nx=%lf, y=%lf result=%lf\n",m0.x,m0.y,result);
else printf("step>max\n");
}
system("pause");
return 0; }