Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Различные алгоритмы минимизации, реализованные в С++ / all / KURS
.CPP#include <conio.h>
#include <stdio.h>
#include <iostream.h>
#include <math.h>
#include <stdlib.h>
//---------------------------------------
// Вспомогательные функции
//---------------------------------------
void SWAP (double &,double&);
double funct(double, double *, double *); //вычисляет значение функции
double fproizv(double, double *, double *); //вычисляет значение производной
double fd1(double, double); //значение частной производной по x1
double fd2(double, double); //значение частной производной по x2
void newgrad(double *,double &, double &); //находим новое направление
double Alpha(double *,double *); //поиск альфа(удлинения вектора)
double Fib(double); //находит число фибона
double norma(double,double); //считает норму
double betta1 (double *p1, double *p2); //считаем значение бетта1 (метод дениела)
double betta2 (double *p1, double *p2); //считаем значение бетта2 (метод дениела)
//---------------------------------------
// Методы оптимизации
//---------------------------------------
void SWENN(); //Метод Свенна
void ZS_1(double, double); //Метод золотого сечения 1
void ZS_2(double, double); //Метод золотого сечения 2
void DETOH(double, double); //Метод Детохомии
void PAUELL(double, double); //Метод Пуэлл
void BOLCANO(double, double); //Метод Больцано
void KOSHI(double, double); //Метод Коши
void FLETCHER_RIVES(double, double); //Метод Флетчера-Ривса
void PARALLEL(double, double); //Метод Параллельных Касательных
void FIBONACHI1(double, double); //Метод Фибоначчи 1
void FIBONACHI2(double, double); //Метод Фибоначчи 2
void GAUSS_ZEIDEL(double, double); //Метод Гайса-Зейделя
void CPS(double, double); //Метод Цикличесского покординатного спуска
void DANIEL(double, double); //Метод Даниела
//-------------------------------------
//Глобальные переменные
//-------------------------------------
double funct(double ,double*, double*); //значение функции
double napr[2]; //начальное направление
double nach[2]; //начальные точки
double eps; //задаем точность
double h; //размер шага
double a; //точка для поиска минимума
double b; //точка для поиска минимума
double L,L1; //точка размеров L
double lam; //точка точек Лямда
double mu; //точка Мю
double an; //для запоминание точки а
double bn; //для запоминание точки b
double X; //Точка минимума
double X1[2];
double alpha;
//---------------------------------------
// Метод Свенна
//---------------------------------------
void SWENN() //свенн
{
a=nach[0];
h=0.01*a; //стартовый размер шага
b=a+h;
if (funct(b,nach,napr) > funct(a,nach,napr)) //если значение в X2> чем
{h=-h; //в X1 тогда изменяем
}; //направление поиска
do {
a=b;
h=2*h; //удваиваем размер шага
b=a+h; //находим след-ую точку
} //пока не найдем изменение
while (funct(b,nach,napr)<funct(a,nach,napr));//поведения функции
a=a-h; //точки найденные по свенну
//b=b;
SWAP(a,b);
};
//---------------------------------------
// Функция перемены местами переменных
//---------------------------------------
void SWAP(double &a,double &b){
if (b<a) { //если б>a то меняем
double temp; //местами
temp=b;
b=a;
a=temp;
};
};
//-----------------------------------------
// Процедура возвращающая значение функции
//-----------------------------------------
double funct(double x,double *nach,double *napr)
{
double x1=nach[0]+x*napr[0]; //X1
double x2=nach[1]+x*napr[1]; //X2
return (x1*x1 + 3*x2*x2 + 2*x1*x2);
//return pow((x1*x1 + x2 - 11),2) + pow((x1 + x2*x2 - 7),2);
//return 100*pow(x2 - x1*x1,2) + pow((1 - x1),2);
return (x1*x1 + 3*x2*x2 + 2*x1*x2);
//функция x1^2+3*x2^2+2*x1*x2
};
//---------------------------------------
// Функция которая ищет Альфу(лаб.р.# 3)
//---------------------------------------
double Alpha(double *x,double *p) //альфа
{
double centr; //вспомогательня точка
double zbeta; //вспомогательня точка
//Выполняется алгоритм свенна
a=x[0];
h=0.01*a; //стартовый размер шага
b=a+h;
if (funct(b,nach,napr) > funct(a,nach,napr)) //если значение в X2> чем
{h=-h; //в X1 тогда изменяем
}; //направление поиска
do {
a=b;
h=2*h; //удваиваем размер шага
b=a+h; //находим след-ую точку
} //пока не найдем изменение
while (funct(b,nach,napr)<funct(a,nach,napr));//поведения функции
a=a-h; //точки найденные по свенну
//b=b;
SWAP(a,b);
//продолжается поиск методом детохомии на основе данных Свенна
zbeta = 0.1*eps;
do
{
centr = (b-a)/2 + a;
lam = centr - zbeta/2;
mu = centr + zbeta/2;
if (funct(a,nach,napr)<funct(b,nach,napr))
{
b=mu;
a=a;
}
else
{
a=lam;
b=b;
}
}
while ((fabs(b-a))>eps);
return (b+a)/2; //возвращаем Альфу.
};
//---------------------------------------
// Функция нахождения нормы
//---------------------------------------
double norma(double x1,double x2)
{
return sqrt(x1*x1+x2*x2); //возвращаем корень из суммы квадратов
};
//---------------------------------------
// Функция нахождения производной
//---------------------------------------
double fproizv(double x,double *nach,double *napr) //считаемпроизводную
{
double g1, g2,z1,z2,h1,h2;
double zz[2];
double zzz[2];
z1=nach[0]+x*napr[0];
z2=nach[1]+x*napr[1];
if ((0.001*z1)>0.0000001)
h1=0.001*z1;
else
h1=0.0000001;
if ((0.001*z2)>0.0000001)
h2=0.001*z2;
else
h2=0.0000001;
zz[0]=z1+h1;
zz[1]=z2;
zzz[0]=z1-h1;
zzz[1]=z2;
g1=((funct(0,zz,napr)-funct(0,zzz,napr))/(2*h1)); //формулой центральной
zz[0]=z1;
zz[1]=z2+h2;
zzz[0]=z1;
zzz[1]=z2-h2;
g2=((funct(0,zz,napr)-funct(0,zzz,napr))/(2*h2)); //формулой центральной
return g1*napr[0]+g2*napr[1];
};
//---------------------------------------
//Нахождение частной производной 1
//---------------------------------------
double fd1(double x1,double x2){
return 2*x1+2*x2;
};
//---------------------------------------
//Нахождение частной производной 2
//---------------------------------------
double fd2(double x1,double x2){
return 6*x2+2*x1;
};
//---------------------------------------
//Вычисляем новое направление
//---------------------------------------
void newgrad(double *x,double &napr1,double &napr2) //ищем новое направление
{
double h1,h2;
double zz[2];
double zzz[2];
if ((0.001*x[0])>0.0000001)
h1=0.001*x[0];
else
h1=0.0000001;
if ((0.001*x[1])>0.0000001)
h2=0.001*x[1];
else
h2=0.0000001;
zz[0]=x[0]+h1;
zz[1]=x[1];
zzz[0]=x[0]-h1;
zzz[1]=x[1];
napr1=((funct(0,zz,napr)-funct(0,zzz,napr))/(2*h1)); //формулой центральной
zz[0]=x[0];
zz[1]=x[1]+h2;
zzz[0]=x[0];
zzz[1]=x[1]-h2;
napr2=((funct(0,zz,napr)-funct(0,zzz,napr))/(2*h2)); //формулой центральной
};
//--------------------------------------
// Поиск числа Фибоначчи
//--------------------------------------
double Fib(double x) // номер числа
{
double s, // итоговое число
tmp; // временная переменная
if(x>=1) // проверяем условие существования числа
{
s=1; // сумма = 1
tmp=0; // обнуляем временныю переменную
for(double k=0; k<x; k++)
{
s=s+tmp; // нахождения числа Фибоначчи
tmp = s-tmp; // осуществляем поиск
}
return s; // возвращаем результат
}
else
return 1; // если индекс меньше 1, возвращаем 1
};
//--------------------------------------
// Нахождение бетта 1
//--------------------------------------
double betta1 (double *p1, double *p2)
{
double g[2],b[2];
g[0]=p2[0]-p1[0];
g[1]=p2[1]-p1[1];
b[0]=p2[0]*g[0]+p2[1]*g[1];
b[1]=p1[0]*g[0]+p1[1]*g[1];
return (b[0]/b[1]);
}
//--------------------------------------
// Нахождение бетта 2
//--------------------------------------
double betta2 (double *p1, double *p2)
{
double g[2],b[2];
g[0]=p2[0]-p1[0];
g[1]=p2[1]-p1[1];
b[0]=p2[0]*g[0]+p2[1]*g[1];
b[1]=p1[0]*p1[0]+p1[1]*p1[1];
return (b[0]/b[1]);
}
//-------------------------------------
//ЗОЛОТОЕ СЕЧЕНИЕ 1
//-------------------------------------
void ZS_1(double z1, double z2)
{ nach[0]=z1; //задем точки
nach[1]=z2;
napr[0]=1; //направление
napr[1]=2;
eps=0.001;
SWENN();
L=(fabs(b-a)); //находим Ln
lam=a+0.382*L; //получаем точки
mu=a+0.618*L; //Лямда и Мю
//
do {
L1=(fabs(b-a));
if ((funct(lam,nach,napr)<funct(mu,nach,napr))) { //находим точку где значение минимально
b=mu; //сужаем интервал ближе к найденному минимуму
mu=lam; //находим новые Лямду,L и Мю
L=(fabs(b-a));
lam=a+0.382*L;
} else {
a=lam; //сужаем интервал ближе к найденному минимуму
lam=mu; //находим новые Лямду,L и Мю
L=(fabs(b-a));
mu=a+0.618*L;
};
}
while (L1>eps); //ппока интервал поиска > погрешности
double X=((a+b)/2); //апроксимирующий минимум
cout <<"ZS_1"<<" ";
cout <<nach[0]+X*napr[0]<<" "; //вывод апроксимирующего минимума
cout <<nach[1]+X*napr[1]<<endl<<endl; //вывод апроксимирующего минимума
};
//-------------------------------------
//ЗОЛОТОЕ СЕЧЕНИЕ 2
//-------------------------------------
void ZS_2(double z1, double z2)
{ nach[0]=z1;
nach[1]=z2;
napr[0]=1;
napr[1]=2;
eps=0.001;
SWENN(); //оптимизируем
do
{
L=(fabs(b-a)); //устанавливаем модуль
lam=a+0.618*L;
mu=a+b-lam;
if ((funct(lam,nach,napr)<funct(mu,nach,napr))&&(lam<mu))
{
b=mu;
}
if ((funct(lam,nach,napr)>=funct(mu,nach,napr))&&(lam<mu))
{
a=lam;
}
if ((funct(lam,nach,napr)<funct(mu,nach,napr))&&(lam>mu))
{
a=mu;
mu=lam;
}
if ((funct(lam,nach,napr)>=funct(mu,nach,napr))&&(lam>mu))
{
b=lam;
lam=mu;
}
}while ((fabs(b-a))>eps); //КОП
X=(a+b)/2;
cout <<"ZS_2"<<" ";
cout <<nach[0]+X*napr[0]<<" "; //выводим минимум
cout <<nach[1]+X*napr[1]<<endl<<endl;
};
//----------------------
//Метод Детохомии
//----------------------
void DETOH(double z1, double z2)
{
double centr; //центральная точка
double beta; //отступ
int M=0; //ограничиваем число операций
nach[0]=z1;
nach[1]=z2;
napr[0]=1;
napr[1]=2;
eps=0.0001;
SWENN(); //опетимизируем
beta = 0.1*eps; //считаемотступ
do
{ M++;
centr = (b-a)/2 + a; //точку внутри отрезка
lam = centr - beta/2;
mu = centr + beta/2;
if (funct(a,nach,napr)<funct(b,nach,napr)) //выполняем поиск
{
b=mu;
a=a;
}
else
{
a=lam;
b=b;
}
}
while ((fabs(b-a))>eps &&(M<200)); //КОП
X=(b+a)/2; //минимум найден
cout <<"DETOH"<<" ";
cout <<nach[0]+X*napr[0]<<" "; //выводим
cout <<nach[1]+X*napr[1]<<endl<<endl;
};
//-------------------------
//Метод Пауэла
//-------------------------
void PAUELL(double z1, double z2)
{
double c;
double eps1; //погрешность 1
double eps2; //погрешность 2
double d; //вспомогат точка
int M=0;
nach[0]=z1;
nach[1]=z2;
napr[0]=1;
napr[1]=2;
eps1=0.001;
eps2=0.001;
SWENN();
bool First=true;
do
{ M++;
c=b;
b=(a+c)/2;
if (First) // если первая итерация.
{
d=((funct(a,nach,napr)*(b*b-c*c)+
funct(b,nach,napr)*(c*c-a*a)+
funct(c,nach,napr)*(a*a-b*b))/
(2*(funct(a,nach,napr)*(b-c)+
funct(b,nach,napr)*(c-a)+
funct(c,nach,napr)*(a-b)
)));
}
else //иначе
{
d=0.5*(a+b)+0.5*((funct(a,nach,napr)-funct(b,nach,napr))*(b-c)*(c-a))
/(funct(a,nach,napr)*(b-c)+funct(b,nach,napr)*(c-a)+funct(c,nach,napr)*(a-b));
};
if ((funct(b,nach,napr)<funct(d,nach,napr))&&(b<d))
{
a=a;
c=d;
b=b;
};
if ((funct(b,nach,napr)<funct(d,nach,napr))&&(b>d))
{
a=d;
c=c;
b=b;
};
if ((funct(b,nach,napr)>funct(d,nach,napr))&&(b<d))
{
a=b;
c=c;
b=d;
};
if ((funct(b,nach,napr)>funct(d,nach,napr))&&(b>d))
{
a=a;
c=b;
b=d;
};
First=false;
}
while ((((fabs(d)-fabs(b))/fabs(b))>=eps1) && //КОП
(((fabs(funct(d,nach,napr))-fabs(funct(b,nach,napr))))
/fabs(funct(b,nach,napr)))>=eps2 && (M<200));
X=(b+d)/2;
cout <<"PAUELL"<<" ";
cout <<nach[0]+X*napr[0]<<" ";
cout <<nach[1]+X*napr[1]<<endl<<endl;
};
//-------------------------------------
//Метод Больцано
//-------------------------------------
void BOLCANO(double z1, double z2)
{
double x;
double x1;
double x2;
double z;
double w;
double y;
int M=0;
nach[0]=z1;
nach[1]=z2;
napr[0]=1;
napr[1]=2;
eps=0.001;
SWENN();
x=a;
h=0.001;
eps=0.1;
if (fproizv(x,nach,napr)>=0) //устанавливаем направление поиска
{
h=-h;
}
int i=0;
do
{i++;
if (i<5)
{
h=h*2;
} else
{
h=0.002;
};
x=x+h;
}
while((fproizv(x,nach,napr)*fproizv(x+h,nach,napr))>=0); //где меняет знак
x1=x; //x1 =X(m-1)
x2=x+h; //Xm
if (x1>x2)
{
a=x2;
b=x1;
}
else
{
a=x1;
b=x2;
};
do //находим лучшую из точек
{
z=(fproizv(a,nach,napr)+fproizv(b,nach,napr)+3*(funct(a,nach,napr)-funct(b,nach,napr)))/b;
w=sqrt(z*z-fproizv(a,nach,napr)*fproizv(b,nach,napr));
y=(z+w-fproizv(a,nach,napr))/(fproizv(b,nach,napr)-fproizv(a,nach,napr)+2*w);
if (y<0)
{
x=a;
};
if (y>1)
{
x=b;
};
if ((y>=0)&&(y<=1))
{
x=a+y*(b-a);
};
M++; //счетчик шагов
if (fproizv(x,nach,napr)>0) //сужаем интервал
{
a=a;
b=x;
}
else
{
a=x;
b=b;
};
} while ((fabs(fproizv(x,nach,napr)))>eps && (M<200));
X=(a+b)/2;
cout <<"BOCANO"<<" ";
cout <<nach[0]+X*napr[0]<<" "; //выводим минимум
cout <<nach[1]+X*napr[1]<<endl<<endl;
};
//---------------------------------------
//Метод Коши
//---------------------------------------
void KOSHI(double z1, double z2) //метод Коши
{
int M=0;
nach[0]=z1;
nach[1]=z2;
napr[0]=1;
napr[1]=1;
eps=0.001;
newgrad(nach,napr[0],napr[1]);
napr[0]=-napr[0];
napr[1]=-napr[1];
do
{
napr[0]=napr[0]/norma(napr[0],napr[1]);
napr[1]=napr[1]/norma(napr[0],napr[1]);
alpha=Alpha(nach,napr); //ищем Альфу
nach[0]=nach[0]+alpha*napr[0];//смещаемся
nach[1]=nach[1]+alpha*napr[1];
newgrad(nach,napr[0],napr[1]); //новое направление
napr[0]=-napr[0];
napr[1]=-napr[1];
M++; //счетчик итерации
}
while ((norma(napr[0],napr[1])>eps) && (M<200)); //КОП
cout <<"KOSHI"<<" ";
cout <<nach[0]<<" "; //вывод минимума
cout <<nach[1]<<endl<<endl;
};
//----------------------------------
// Метод Фибоначи-1
//----------------------------------
void FIBONACHI1(double z1,double z2)
{
double n,k=0;
nach[0]=z1; //нач точки
nach[1]=z2;
napr[0]=1;
napr[1]=2; //нач направление
eps=0.001;
double L=0.01*eps; // задаем длину конечного интервала
n=0; // порядковый номер числа Фибоначчи
SWENN();
while(Fib(n)<(b-a)/L) // определяем этот номер в
n++; // соответствии с алгоритмом
lam=a+(Fib(n-2)*(b-a))/(Fib(n)); // первая начальная точка
mu=a+(Fib(n-1)*(b-a))/(Fib(n)); // вторая начальная точка
while(k<n-1) // сокращаем ТИЛ в соответствии с методом
{
if(funct(lam,nach,napr)<funct(mu,nach,napr))
{
b=mu;
mu=lam;
lam=a+(Fib(n-k-2)*(b-a))/Fib(n-k);
}
else
{
a=lam;
lam=mu;
mu=a+(Fib(n-k-1)*(b-a))/Fib(n-k);
}
k++; // увеличиваем счётчик итераций
}
if(funct(lam,nach,napr)<=funct(mu,nach,napr)) // рассматриваем 2 возможные ситуации,
X=(a+mu)/2; // вычисляем результирующее значение и
else // изменяем значение коэффициента
X=(lam+b)/2; // удлинения вектора
cout <<"FIBONACHHI1"<<" ";
cout <<nach[0]+X*napr[0]<<" "; //выводим на экран
cout <<nach[1]+X*napr[1]<<endl<<endl;
};
//--------------------------------------------------------------------
// Метод Фибоначи-2
//--------------------------------------------------------------------
void FIBONACHI2(double z1,double z2)
{
double n=0; // порядковый номер числа Фибоначчи
double k=0;
nach[0]=z1;
nach[1]=z2;
napr[0]=1;
napr[1]=2;
eps=0.001;
double Ln = 0.01*eps; // задаём длину конечного интервала
double x1, x2; // задаём необходимые переменные
SWENN();
while(Fib(n)<(b-a)/Ln) // определяем этот номер в
n++; // соответствии с алгоритмом
x1=a+Fib(n-1)*(b-a)/Fib(n)+pow((-1),n)*eps/Fib(n); // первая начальная точка
while(k<n) // сокращаем ТИЛ в соответствии с методом
{
x2 = a+b-x1; // вторая точка
if(funct(x1,nach,napr)<funct(x2,nach,napr)) // Сокращаем текущий интервал
{ // локализации рассмотрением
if(x1<x2) // 4-х ситуаций, аналогично
b=x2; // методу золотого сечения-2
else
a=x2;
}
else
{
if(x1<x2)
a=x1;
else
b=x1;
x1=x2;
};
k++; // увеличиваем счётчик итераций
};
X=x2; // изменяем значение коэффициента удлинения вектора
cout <<"FIBONACHI2"<<" ";
cout <<nach[0]+X*napr[0]<<" ";
cout <<nach[1]+X*napr[1]<<endl<<endl;
};
//---------------------------------------
// Метод параллельных касательных
//---------------------------------------
void PARALLEL(double z1, double z2)
{
double x[2]; // начальная точка
double x0[2]={0}; // начальная точка
double x2[2]={0}; // начальная точка
double d[2]={0}; //удлинение вектора
int M=0;
x[0]=z1;
x[1]=z2;
nach[0]=1;
nach[1]=1;
napr[0]=1;
napr[1]=2;
eps=0.001;
x0[0]=x[0]; // начальная точка
x0[1]=x[1]; // начальная точка
// переопределяем массив значений х
// при пошаговом поиске и задаём
// значение начальной точки
do
{
alpha=Alpha(x,napr);
newgrad(x,napr[0],napr[1]);
napr[0]=-napr[0];
napr[1]=-napr[1];
napr[0]=napr[0]/norma(napr[0],napr[1]);
napr[1]=napr[1]/norma(napr[0],napr[1]);
x[0] = x[0]+alpha*napr[0]; // спускаемся в точку х2
x[1] = x[1]+alpha*napr[1]; // спускаемся в точку х2
x2[0] = x[0]; // сохраняем точку х2
x2[1] = x[1]; // сохраняем точку х2
newgrad(x,napr[0],napr[1]); // устанавливаем антградиентное направление
napr[0]=-napr[0];
napr[1]=-napr[1];
napr[0]=napr[0]/norma(napr[0],napr[1]);
napr[1]=napr[1]/norma(napr[0],napr[1]);
alpha=Alpha(x,napr); // находим коэффициент удлинения вектора
x[0] = x[0]+alpha*napr[0]; // спускаемся в точку х3
x[1] = x[1]+alpha*napr[1]; // спускаемся в точку х3
d[0] = x[0]-x0[0]; // определяем ускоряющее направление
d[1] = x[1]-x0[1]; // определяем ускоряющее направление
alpha=Alpha(x,napr); // находим коэффициент удлинения вектора
x[0] = x[0]+alpha*d[0]; // спускаемся в точку х4
x[1] = x[1]+alpha*d[1]; // спускаемся в точку х4
x0[0] = x2[0]; // если КОП не выполняется, то х2 - новая начальная точка
x0[1] = x2[1];
M++; // если КОП не выполняется, то х2 - новая начальная точка
}
while ((norma(d[0],d[1])>eps) && (norma(napr[0],napr[0])>eps) && (M<200)); //КОП
cout <<"Parallel"<<" ";
cout <<x[0]<<" ";
cout <<x[1]<<endl<<endl; //вывод минимума
};
//----------------------------------------
// Метод Гаусса-Зейделя
//----------------------------------------
void GAUSS_ZEIDEL(double z1,double z2){
double X1[2]; // предыдущее значение
double xn[2]; // предыдущее значение
double d[2]; // ускоряющее направление
nach[0]=z1;
nach[1]=z2;
napr[0]=1;
napr[1]=2;
int M=0;
eps=0.001;
X1[0] = nach[0]; // сохраняем точку
X1[1] = nach[1];
do
{
alpha=0;
newgrad(nach,napr[0],napr[1]);
napr[0]=-napr[0];
napr[1]=-napr[1];
napr[0]=napr[0]/norma(napr[0],napr[1]);
napr[1]=napr[1]/norma(napr[0],napr[1]);
napr[0] = napr[0]*1;
napr[1] = napr[1]*0;
alpha=Alpha(X1,napr);
xn[0]=X1[0]+alpha*napr[0];
xn[1]=X1[1]+alpha*napr[1];
alpha=0;
newgrad(X1,napr[0],napr[1]);
napr[0]=-napr[0];
napr[1]=-napr[1];
napr[0]=napr[0]/norma(napr[0],napr[1]);
napr[1]=napr[1]/norma(napr[0],napr[1]);
napr[0] = napr[0]*0;
napr[1] = napr[1]*1;
alpha=Alpha(xn,napr);
xn[0]=xn[0]+alpha*napr[0];
xn[1]=xn[1]+alpha*napr[1];
alpha=0;
d[0]=xn[0]-X1[0];
d[1]=xn[1]-X1[1];
alpha=Alpha(xn,d);
X1[0]=xn[0]+alpha*d[0];
X1[1]=xn[1]+alpha*d[1];
M++; // увеличиваем счётчик итераций
}
while(norma(d[0],d[1])>eps && norma(napr[0],napr[1])>eps && (M<200)); // комбинированный КОП
cout<<"Gauss Zeidel"<<" ";
cout<<X1[0]<<" "; // возвращаем найденный минимум
cout<<X1[1]<<endl<<endl; // возвращаем найденный минимум
};
//----------------------------------------
// Метод Флетчера-Ривса
//----------------------------------------
void FLETCHER_RIVES(double z1, double z2)
{
double g[2]; //направление
nach[0]=z1;
nach[1]=z2;
napr[0]=1;
napr[1]=2;
eps=0.001;
int M=0; //счетчик итераций
double beta; // число, меняющее длину р
// переопределяем массив значений х
// при пошаговом поиске и задаём
// значение начальной точки
newgrad(nach,napr[0],napr[1]);
// сокращаем ТИЛ в соответствии с методом
napr[0] = -napr[0];
napr[1] = -napr[1];
while(norma(napr[0],napr[1])>eps &&(M<200))
{
M++; // увеличиваем счётчик итераций
if(M==1)
{ // проверяем номер итерации
newgrad(nach,napr[0],napr[1]);
napr[0] = -napr[0];
napr[1] = -napr[1];
}//устанавливаем антиградиентное напрвление
else
{ // вычисляем в соответствии с формулой
newgrad(nach,napr[0],napr[1]); //устанавливаем
napr[0] = -napr[0]; //антиградиентное напрвление
napr[1] = -napr[1];
beta = (pow(norma(napr[0],napr[1]),2)/(pow(norma(g[0],g[1]),2))); //бета
napr[0] = napr[0]+napr[0]*beta; // новое направление поиска
napr[1] = napr[1]+napr[1]*beta; // новое направление поиска
}
g[0]=-napr[0];
g[1]=-napr[1];
// сохраняем текущий градиент
// находим коэффициент удлинения вектора
alpha=Alpha(nach,napr);
nach[0] = nach[0] + napr[0]*alpha; // спускаемся в новую точку
nach[1] = nach[1] + napr[1]*alpha; // спускаемся в новую точку
M++;
};
cout <<"Fletcher Rives"<<" ";
cout <<nach[0]<<" "; //вывод минимума
cout <<nach[1]<<endl<<endl;
};
//-------------------------------------------
// Метод Цикличесского покоординатного спуска
//-------------------------------------------
void CPS (double z1, double z2)
{
double p[2];
p[0]=1; p[1]=0;
double M=0;
X1[0]=z1;
X1[1]=z2;
napr[0]=1;
napr[1]=2;
newgrad(X1,napr[0],napr[1]);
//napr[0]=-napr[0];
//napr[1]=-napr[1];
napr[0]=X1[0];
napr[1]=X1[1];
do
{
alpha=Alpha(nach,napr);
nach[0]=nach[0]+alpha*p[0];
nach[1]=nach[1]+alpha*p[1];
alpha=0;
double temp;
temp=p[0];
p[0]=p[1];
p[1]=temp;
alpha=Alpha(nach,napr);
nach[0]=nach[0]+alpha*p[0];
nach[1]=nach[1]+alpha*p[1];
newgrad(nach,napr[0],napr[1]);
napr[0]=-napr[0];
napr[1]=-napr[1];
temp=p[0];
p[0]=p[1];
p[1]=temp;
M++;
}
while ((norma(X1[0]-nach[0],X1[1]-nach[1])>0.001)&&(M<200));
cout<<"CPS"<<" ";
cout<<nach[0]<<" ";
cout<<nach[1]<<endl;
};
//-----------------------------------------
//Метод Даниелла
//-----------------------------------------
void DANIEL(double z1, double z2)
{
double p[2];
napr[0]=1;
napr[1]=2;
nach[0]=z1;
nach[1]=z2;
p[0]=0;
p[1]=0;
div_t q;
int M=0;
newgrad(nach,napr[0],napr[1]);
p[0]=napr[0];
p[1]=napr[1];
while((norma(p[0],p[1])>0.001)&&(M<200))
{
p[0]=p[0]/norma(p[0],p[1]);
p[1]=p[1]/norma(p[0],p[1]);
alpha=Alpha(nach,p);
nach[0]=nach[0]+alpha*p[0];
nach[1]=nach[1]+alpha*p[1];
napr[0]=p[0];
napr[1]=p[1];
newgrad(nach,p[0],p[1]);
q=div(M,2);
if (q.rem)
{
p[0]=p[0]+betta1(napr,p)*napr[0];
p[1]=p[1]+betta2(napr,p)*napr[1];
}
M++;
}
cout<<"Daniel"<<" ";
cout<<nach[0]<<" ";
cout<<nach[1]<<endl;
};
//----------------------------------
//Главная процедура
//----------------------------------
void main()
{
/* ZS_1(1,1);
ZS_2(1,1);
DETOH(1,1);
PAUELL(1,1);
BOLCANO(1,1);
KOSHI(3,2);*/
// FLETCHER_RIVES(3,2);
/*PARALLEL(3,2);
FIBONACHI1(1,1);
FIBONACHI2(1,1);
GAUSS_ZEIDEL(3,2);
CPS(3,2); */
double Points[2];
int meth;
Cout<< "Enter Method Type "<<endl;
/* Cout<< "1. ZS_1: "<<endl;
Cout<< "2. ZS_2: "<<endl;
Cout<< "3. Fibonachi_1: "<<endl;
Cout<< "4. Fibonachi_2: "<<endl;
Cout<< "5. DETOH: "<<endl;
Cout<< "6. Bolcano: "<<endl;
Cout<< "7. PAUELL: "<<endl;
cin >> meth;
Cout<< "Start point 1";cin>>Points[0];cout<<endl;
Cout<< "Start point 2";cin>>Points[1];cout<<endl;
// DANIEL(Points[0],Points[1],math);
getch(); //ожидание нажатия любой клавиши
*/};
Соседние файлы в папке all