Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Оптимизация в САПР / Курсовик_Мальгин_1.doc
Скачиваний:
42
Добавлен:
01.05.2014
Размер:
713.22 Кб
Скачать

Результаты тестирования программы

Результат тестирования методов для одномерной функции

Результат тестирования методов для двухмерной функции

Результат тестирования методов для трёхмерной функции

Результат тестирования методов для четырёхмерной функции

Результат тестирования метода комплексов Бокса

1.

2.

Результат тестирования парсера

Инструкция для пользователя

Ввод функции производится двумя способами: выбором из списка имеющейся функции либо ввод функции в ручную. При вводе в ручную можно использовать любые математические функции типа sin,cos,exp,ctg…

Исходные данные

Простой ввод пгорешности вычислений, ввод начальной точки через запятую или точку с запятой, максимальное число итераций, и выбор одномерного метода из списка.

Выбор метода многомерной минимизации производится также как и выбор функции, и выбор метода одномерного тоесть с помощью списка.

Кнопки программы выполняют следующие функции. Кнопка расчёт обрабатывает начальные условия и вызывает методы для подсчёта. В свою очередь кнопка Очистка результата выполнят ту функцию которую несёт ее название, ну и выход является выходом.

Заключение

В ходе выполнения курсовой работы был разработан пакет диалоговых программ, позволяющих автоматизировано находить оптимальные решения различных функций. Курсовая работа содержит различные методы одномерной и многомерной оптимизации, а кроме того позволяет проводить оптимизации целевых функций с большим числом переменных, осуществлять численное дифференцирование минимизируемых функций, выполнять решение в автоматическом режиме и в поитерационном режиме с выдачей всей информации, необходимой для контроля соответствия работы программы по заданному методу, задавать с клавиатуры критерий останова (норма градиента и число итераций) и продолжать решение после внесения дополнительных уточнений в текущую точку и критерий остановки, вводить с клавиатуры минимизируемые функции многих переменных, содержащих скобки, степени и основные математические функции (Eps, Ln, Sin, Cos и т.д.). Кроме этого программа имеет дружественный пользователю интерфейс и содержит необходимые заставки и сообщения, характеризующие программу, используемый метод, характер выводимой информации, допущенную ошибку при вводе данных и т.д., блокирует ошибочные действия при вводе данных и обеспечивает простоту исправления ошибки. В демонстрационном режиме имеется возможность выбора из нескольких тестовых функций.

В итоге, мы получили полноценно приложение, содержащее различные методы оптимизации, которое позволяет легко и эффективно решать задачи поиска минимума функций.

Приложение – листинг программы

// Метод Свенна

int CMETODI::Swann(CMatrix &x,CMatrix &p)

{

double h = 0.1; // шаг

double la = 0; // значение функции

int k = 0; // счётчик числа итераций

if(dfp(x,p)>0) // если необходимо,

h=-h; // меням направление поиска

while(dfp(x+la*p,p)*dfp(x+(la+h)*p,p)>0) // сокращаем ТИЛ до начала

{ // возрастания функции

la += h; // изменяем значения функции

h = 2*h; // удваиваем шаг

k++; // увеличиваем счётчик числа итераций

}

if(h<0) // проверяем направление поиска

{ // и в соответствии с ним

b = la; // присваиваем новые значения

a = la+h; // локализированного минимума

}

else

{

a = la;

b = la+h;

}

return k; // возвращаем число итераций

}

// Метод Больцано

int CMETODI::Bolcano(

CMatrix &x, // начальная точка

CMatrix &p, // направление поиска

double &e, // погрешность поиска

int &max_step) // максимальное количество итераций

{

int k=0; // устанавливаем счётчик числа итераций

// сокращаем ТИЛ до соответствующего условия

while((fabs(dfp(x+((a+b)/2)*p,p)))>e && fabs(b-a)>e && k<max_step)

{

k++; // увеличиваем счётчик итераций

if(dfp(x+((a+b)/2)*p,p)>0) // локализуем минимум

b=(a+b)/2; // в соответствии с

else // методом

a=(a+b)/2;

}

alpha = (a+b)/2; // изменяем значение коэффициента удлинения вектора

return k; // возвращаем количесво итераций

}

// Метод золотого сечения - 1

int CMETODI::ZS_1(

CMatrix &x, // начальная точка

CMatrix &p, // направление поиска

double &e, // погрешность поиска

int &max_step) // максимальное количество итераций

{

int k=0; // задаём счётчик числа итераций

double l = a+0.382*fabs(b-a); // выбираем первую точку

double m = a+0.618*fabs(b-a); // выбираем вторую точку

// сокращаем ТИЛ до соответствующего условия

while((fabs(dfp(x+((a+b)/2)*p,p)))>e && fabs(a-b)>e && k<max_step)

{

if(f(x+l*p)<f(x+m*p))

{

b = m;

m = l;

l = a+0.382*fabs(b-a);

}

else

{

a = l;

l = m;

m = a+0.618*fabs(b-a);

}

k++; // увеличиваем счётчик итераций

}

alpha = (a+b)/2; // изменяем значение коэффициента удлинения вектора

return k; // возвращаем количество итераций

}

// Метод золотого сечения - 2

int CMETODI::ZS_2(

CMatrix &x, // начальная точка

CMatrix &p, // направление поиска

double &e, // погрешность поиска

int &max_step) // максимальное количество итераций

{

int k=0; // задаём счётчик числа итераций

double x1 = a + 0.618*fabs(b-a); //выбираем первую точку

double x2 = a + b - x1; //выбираем вторую точку

// сокращаем ТИЛ до соответствующего условия

while((fabs(dfp(x+((a+b)/2)*p,p)))>e && fabs(a-b)>e && k<max_step)

{

if(f(x+x1*p) > f(x+x2*p))

{

if(x1 > x2)

b = x1;

else

a = x1;

x1 = a + 0.618*fabs(b-a);

}

else

{

if(x1 > x2)

a = x2;

else

b = x2;

x2 = a + b - x1;

}

k++; // увеличиваем счётчик итераций

}

alpha=(a+b)/2; // изменяем значение коэффициента удлинения вектора

return k; // возвращаем количество итераций

}

// Метод Пауэлла

int CMETODI::Pauell_Odn(

CMatrix &x, // начальная точка

CMatrix &p, // направление поиска

double &e, // погрешность поиска

int &max_step) // максимальное количество итераций

{

int k=0; // задаём счётчик числа итераций

double c=b,d; // задаём необходимые переменные

b=(a+c)/2; // определяем начальное значение b

// определяем начальное значение d

d=0.5*(f(x+a*p)*(b*b-c*c)+f(x+b*p)*(c*c-a*a)+f(x+c*p)*(a*a-b*b))/

(f(x+a*p)*(b-c)+f(x+b*p)*(c-a)+f(x+c*p)*(a-b));

// сокращаем ТИЛ до соответствующего условия

while((fabs((d-b)/fabs(b))>e) && (fabs((f(x+d*p)-f(x+b*p))/f(x+b*p))>e) && k<max_step)

{

if(f(x+b*p)>f(x+d*p))

{

if(b>d) // выбираем "лучшую" точку -

c=b; // которой соответствует наименьшее

else // значение функции, и, обозначив её как b

a=b; // рассматриваем 4 ситуации

b=d;

}

else

{

if(b>d)

c=d;

else

a=d;

}

// определяем значение d

d = 0.5*((f(x+a*p)-f(x+b*p))*(b-c)*(c-a))/

(f(x+a*p)*(b-c)+f(x+b*p)*(c-a)+f(x+c*p)*(a-b))+0.5*(a+b);

k++; // увеличиваем счётчик итераций

}

alpha=(b+d)/2; // изменяем значение коэффициента удлинения вектора

return k; // возвращаем количество итераций

}

// Метод Давидона

int CMETODI::Davidon(

CMatrix &x, // начальная точка

CMatrix &p, // направление поиска

double &e, // погрешность поиска

int &max_step) // максимальное количество итераций

{

int k=0; // задаём счётчик числа итераций

double z,w,r; // задаём необходимые переменные

if (a>b)

{

r=b;

b=a;

a=r;

}

// находим переменные в соответстви с методом

z=dfp(x+a*p,p)+dfp(x+b*p,p)+3*(f(x+a*p)-f(x+b*p))/(b-a);

w=sqrt(z*z-dfp(x+a*p,p)*dfp(x+b*p,p));

r=a+(b-a)*(z-dfp(x+a*p,p)+w)/(dfp(x+b*p,p)-dfp(x+a*p,p)+2*w);

// сокращаем ТИЛ до соответствующего условия

while((fabs(dfp(x+((a+b)/2)*p,p)))>e && fabs(a-b)>e && k<max_step && dfp(x+r*p,p)>e)

{

k++; // увеличиваем счётчик итераций

if(dfp(x+r*p,p)<0) // рассматриваем 2 ситуации

a=r;

else

b=r;

// находим переменные в соответстви с методом

z=dfp(x+a*p,p)+dfp(x+b*p,p)+3*(f(x+a*p)-f(x+b*p))/(b-a);

w=sqrt(z*z-dfp(x+a*p,p)*dfp(x+b*p,p));

r=a+(b-a)*(z-dfp(x+a*p,p)+w)/(dfp(x+b*p,p)-dfp(x+a*p,p)+2*w);

}

alpha=r/*(a+b)/2*/; // изменяем значение коэффициента удлинения вектора

return k; // возвращаем количество итераций

}

// Метод Фибоначчи-1

int CMETODI::Fibonachchi_1(

CMatrix &x, // начальная точка

CMatrix &p, // направление поиска

double &e, // погрешность поиска

int &max_step) // максимальное количество итераций

{

int k=0; // задаём счётчик числа итераций

double Ln=0.01*e; // задаём длину конечного интервала

double n=0; // порядковый номер числа Фибоначчи

while(Fib(n)<(b-a)/Ln) // определяем этот номер в

n++; // соответствии с алгоритмом

double l, m; // задаём необходимые переменные

l=a+(Fib(n-2)*(b-a))/(Fib(n)); // первая начальная точка

m=a+(Fib(n-1)*(b-a))/(Fib(n)); // вторая начальная точка

while(k<n-1) // сокращаем ТИЛ в соответствии с методом

{

if(f(x+l*p)<f(x+m*p))

{

b=m;

m=l;

l=a+(Fib(n-k-2)*(b-a))/Fib(n-k);

}

else

{

a=l;

l=m;

m=a+(Fib(n-k-1)*(b-a))/Fib(n-k);

}

k++; // увеличиваем счётчик итераций

}

if(f(x+l*p)<=f(x+m*p)) // рассматриваем 2 возможные ситуации,

alpha=(a+m)/2; // вычисляем результирующее значение и

else // изменяем значение коэффициента

alpha=(l+b)/2; // удлинения вектора

return k; // возвращаем количество итераций

}

// Метод Фибоначчи-2

int CMETODI::Fibonachchi_2(

CMatrix &x, // начальная точка

CMatrix &p, // направление поиска

double &e, // погрешность поиска

int &max_step) // максимальное количество итераций

{

int k=0; // задаём счётчик числа итераций

double Ln = 0.01*e; // задаём длину конечного интервала

double x1 ,x2; // задаём необходимые переменные

double n=0; // порядковый номер числа Фибоначчи

while(Fib(n)<(b-a)/Ln) // определяем этот номер в

n++; // соответствии с алгоритмом

x1=a+Fib(n-1)*(b-a)/Fib(n)+pow((-1),n)*e/Fib(n); // первая начальная точка

while(k<n) // сокращаем ТИЛ в соответствии с методом

{

x2 = a+b-x1; // вторая точка

if(f(x+x1*p)<f(x+x2*p)) // Сокращаем текущий интервал

{ // локализации рассмотрением

if(x1<x2) // 4-х ситуаций, аналогично

b=x2; // методу золотого сечения-2

else

a=x2;

}

else

{

if(x1<x2)

a=x1;

else

b=x1;

x1=x2;

}

k++; // увеличиваем счётчик итераций

}

alpha=x2; // изменяем значение коэффициента удлинения вектора

return k; // возвращаем количество итераций

}

// Метод экстраполяции-интерполяции

int CMETODI::ExIn(

CMatrix &x, // начальная точка

CMatrix &p, // направление поиска

double &e, // погрешность поиска

int &max_step) // максимальное количество итераций

{

int k=0; // задаём счётчик числа итераций

double c=0,d=norma(x); // задаём необходимые переменные

double h=0.001; // шаг

// сокращаем ТИЛ в соответствии с методом

while((fabs((d-b)/b)>e) && (fabs((f(x+d*p)-f(x+b*p))/f(x+b*p))>e) && k<max_step)

{

b=d;

a=b-h;

c=b+h;

d=0.5*(f(x+a*p)*(b*b-c*c)+f(x+b*p)*(c*c-a*a)+

f(x+c*p)*(a*a-b*b))/(f(x+a*p)*(b-c)+f(x+b*p)*(c-a)+f(x+c*p)*(a-b));

k++; // увеличиваем счётчик итераций

}

alpha=(b+d)/2; // изменяем значение коэффициента удлинения вектора

return k; // возвращаем количество итераций

}

// Методы многомерной оптимизации

// Метод параллельных касательных

CMatrix CMETODI::ParallelKasat(

CMatrix x, // начальная точка

double e, // погрешность поиска

int* max_step, // максимальное количество итераций

int i1Min) // метод одномерного поиска

{

int k=0; // задаём счётчик числа итераций

CMatrix x2, // промежуточная точка

x0=x, // начальная точка

d, // ускоряющее направление

p; // направление поиска

// переопределяем массив значений х

// при пошаговом поиске и задаём

// значение начальной точки

MASSIV.setSize(x.getSizeRow(),x.getSizeCol());

MASSIV.setCol(1,x);

do

{

p = -df(x); // устанавливаем антградиентное направление

x = x+alpha*p; // спускаемся в точку х2

x2 = x; // сохраняем точку х2

p = -df(x); // устанавливаем антградиентное направление

FindAlpha(x,p,e,i1Min); // находим коэффициент удлинения вектора

x = x+alpha*p; // спускаемся в точку х3

d = x-x0; // определяем ускоряющее направление

FindAlpha(x,p,e,i1Min); // находим коэффициент удлинения вектора

x = x+alpha*d; // спускаемся в точку х4

x0 = x2; // если КОП не выполняется, то х2 - новая начальная точка

k++; // увеличиваем счётчик итераций

MASSIV.insertCol(x); // добавляем новое значение х в массив

}

while(norma(d)>e && norma(df(x))>e && k<*max_step);

*max_step=k; // возвращаем количество итераций

return x; // возвращаем найденный минимум

}

// Метод Коши

CMatrix CMETODI::Koshi(

CMatrix x, // начальная точка

double e, // погрешность поиска

int* max_step, // максимальное количество итераций

int i1Min) // метод одномерного поиска

{

int k=0; // задаём счётчик числа итераций

CMatrix p(x); // направление поиска

// переопределяем массив значений х

// при пошаговом поиске и задаём

// значение начальной точки

MASSIV.setSize(x.getSizeRow(),x.getSizeCol());

MASSIV.setCol(1,x);

do

{

p = -df(x); // устанавливаем антградиентное направление

FindAlpha(x,p,e,i1Min); // находим коэффициент удлинения вектора

x = x+p*alpha; // спускаемся в следующую точку х

k++; // увеличиваем счётчик итераций

MASSIV.insertCol(x); // добавляем новое значение х в массив

}

while(norma(p)>e && fabs(f(x+alpha*p)-f(x))>e && k<*max_step); // комбинированный КОП

*max_step=k; // возвращаем количество итераций

return x; // возвращаем найденный минимум

}

// Метод циклического покоординатного спуска

CMatrix CMETODI::CPS(

CMatrix x, // начальная точка

double e, // погрешность поиска

int* max_step, // максимальное количество итераций

int i1Min) // метод одномерного поиска

{

int k=0; // задаём счётчик числа итераций

CMatrix x_prev(x), // предыдущее значение

d(x), // ускоряющее направление

p(x); // направление поиска

// переопределяем массив значений х

// при пошаговом поиске и задаём

// значение начальной точки

MASSIV.setSize(x.getSizeRow(),x.getSizeCol());

MASSIV.setCol(1,x);

do

{

x_prev = x; // сохраняем точку

for(int i=1; i<=x.getSizeRow(); i++)

{ // выполняем серию одномерных

p[i] = 1; // поисков вдоль координатных осей

FindAlpha(x,p,e,i1Min); // находим коэффициент удлинения вектора

x = x + p*alpha; // спускаемся в следующую точку х

p[i] = 0;

}

d = x - x_prev; // определяем ускоряющее направление

k++; // увеличиваем счётчик итераций

MASSIV.insertCol(x); // добавляем новое значение х в массив

}

while(norma(d)>e && norma(df(x))>e && k<*max_step); // комбинированный КОП

*max_step=k; // возвращаем количество итераций

return x; // возвращаем найденный минимум

}

// Метод Гаусса-Зейделя

CMatrix CMETODI::GaussZeydel(

CMatrix x, // начальная точка

double e, // погрешность поиска

int* max_step, // максимальное количество итераций

int i1Min) // метод одномерного поиска

{

int k=0; // задаём счётчик числа итераций

CMatrix x_prev(x), // предыдущее значение

d(x), // ускоряющее направление

p(x); // направление поиска

// переопределяем массив значений х

// при пошаговом поиске и задаём

// значение начальной точки

MASSIV.setSize(x.getSizeRow(),x.getSizeCol());

MASSIV.setCol(1,x);

do

{

x_prev = x; // сохраняем точку

for(int i=1; i<=x.getSizeRow(); i++)

{ // выполняем серию одномерных

p[i] = df(x)[i]; // поисков вдоль производной

FindAlpha(x,p,e,i1Min); // находим коэффициент удлинения вектора

x = x + p*alpha; // спускаемся в следующую точку х

p[i] = 0;

}

d = x - x_prev; // определяем ускоряющее направление

k++; // увеличиваем счётчик итераций

MASSIV.insertCol(x); // добавляем новое значение х в массив

}

while(norma(d)>e && norma(df(x))>e && k<*max_step); // комбинированный КОП

*max_step=k; // возвращаем количество итераций

return x; // возвращаем найденный минимум

}

// Метод Хука-Дживса

CMatrix CMETODI::HookJeeves(

CMatrix x, // начальная точка

double e, // погрешность поиска

int* max_step) // максимальное количество итераций

{

CMatrix h(x), // шаг поиска в виде матрицы

b(x), // базовая точка

c, q; // вспомогательные матрицы

// переопределяем массив значений х

// при пошаговом поиске и задаём

// значение начальной точки

MASSIV.setSize(x.getSizeRow(),x.getSizeCol());

MASSIV.setCol(1,x);

for(int i=1; i<=h.getSizeRow(); i++)

h[i]=1; // задаём начальный шаг

int n=x.getSizeRow(), // количество строк

is_sample=0, // флаг для следующенго поиска

k=0; // задаём счётчик числа итераций

while(norma(h)>e && k<*max_step) // проверяем стандартный КОП

{

// выполняем исследующий поиск

int not_found=1; // флаг на окончание поиска

for(int i=1; i<=n; i++)

{

double f_x=f(x); // находим значение производной

c=x; // сохраняем точку

c[i]+=h[i]; // шаг в положительном направлении i-ой коорд.

if(f(c)<=f_x) // если нашли подходящую точку

{

x=c; // сохраняем точку

not_found=0; // устанавливаем флаг в 0

}

else // если не нашли подходящую точку

{

c[i]-=2*h[i]; // шаг в отрицательном направлении i-ой корд.

if(f(c)<f_x)

{

x=c; // сохраняем точку

not_found=0; // устанавливаем флаг в 0

}

}

//k++;

}

if(is_sample) // проверяем необходимость

{ // следующего исследующего поиска

if(not_found || !(f(x)<f(q)))

{

// возвращаемся к базовой точке

x=q;

b=q;

is_sample=0;

continue;

}

else

{

// запоминаем новую базовую точку

b=q;

}

}

else

{

if(not_found)

{

// если исследующий поиск закончился неудачей - уменьшаем шаг

h/=10; // (здесь beta = 10)

continue;

}

}

// выполняем ускоряющий поиск

q=x;

x=x*2-b;

is_sample=1;

k++; // увеличиваем счётчик итераций

MASSIV.insertCol(x); // добавляем новое значение х в массив

}

MASSIV.insertCol(x); // добавляем новое значение х в массив

k++; // увеличиваем счётчик итераций

*max_step=k; // возвращаем количество итераций

return x; // возвращаем найденный минимум

}

// Обобщённый метод Ньютона

CMatrix CMETODI::Newton_Ob(

CMatrix x, // начальная точка

double e, // погрешность поиска

int* max_step, // максимальное количество итераций

int i1Min) // метод одномерного поиска

{

int k=0; // задаём счётчик числа итераций

// переопределяем массив значений х

// при пошаговом поиске и задаём

// значение начальной точки

MASSIV.setSize(x.getSizeRow(),x.getSizeCol());

MASSIV.setCol(1,x);

if(norma(df(x))<e) // дополнительный КОП:

{ // если х0 - точка

*max_step=0; // минимума, то завершить

return x; // поиск

}

CMatrix x0(x), // предыдущая точка

x1, // текущая точка

p; // направление поиска

for(k=0; k<*max_step; k++) // выполняем поиск в

{ // соответствии с методом

if(norma(df(x0))<e) // проверка на окончание поиска 

break;

p=(-inverseGJ(hesse(x0))*df(x0)); // выбираем ньютоновское направление поиска

FindAlpha(x,p,e,i1Min); // находим коэффициент удлинения вектора

x1=x0+p*alpha; // спускаемся в новую точку

// проверка на окончание поиска

if(norma(x1-x0)/norma(x0)<e && norma(x0)<e && norma(x1)<e)

break;

// дополнительный КОП

if (norma(df(x1))>norma(df(x0)))

{

*max_step=k;

return x0;

}

x0=x1; // сохрарняем предыдущую точку

MASSIV.insertCol(x0); // добавляем новое значение х в массив

}

*max_step=k; // возвращаем количество итераций

return x1; // возвращаем найденный минимум

}

// Метод Зангвила

CMatrix CMETODI::Sangvil(

CMatrix x, // начальная точка

double e, // погрешность поиска

int* max_step) // максимальное количество итераций

{

int k=0; // задаём счётчик числа итераций

// переопределяем массив значений х

// при пошаговом поиске и задаём

// значение начальной точки

MASSIV.setSize(x.getSizeRow(),x.getSizeCol());

MASSIV.setCol(1,x);

if(norma(df(x))<e) // дополнительный КОП:

{ // если х0 - точка

*max_step=0; // минимума, то завершить

return x; // поиск

}

CMatrix x0(x), // предыдущая точка

x1, // текущая точка

i; // единичная матрица

i.setSingle(x0.getSizeRow()); // переопределение размера

double lambda=1000; // необходимый коэффициент

for(k=0; k<*max_step; k++) // выполняем поиск в

{ // соответствии с методом

if(norma(df(x0))<e) // проверка на окончание поиска

break;

for(;;) // бесконечный цикл

{

x1=x0-inverseGJ(hesse(x0)+lambda*i)*df(x0); // новая точка

if(f(x1)<f(x0)) // рассматриваем

{ // 2 ситуации

lambda*=0.5;

break;

}

else

lambda*=2;

}

x0=x1; // сохрарняем предыдущую точку

MASSIV.insertCol(x0); // добавляем новое значение х в массив

}

*max_step=k; // возвращаем количество итераций

return x1; // возвращаем найденный минимум

}

// Метод Флетчера-Ривса

CMatrix CMETODI::FletcherReeves(

CMatrix x, // начальная точка

double e, // погрешность поиска

int* max_step, // максимальное количество итераций

int i1Min) // метод одномерного поиска

{

int k=0; // задаём счётчик числа итераций

// переопределяем массив значений х

// при пошаговом поиске и задаём

// значение начальной точки

MASSIV.setSize(x.getSizeRow(),x.getSizeCol());

MASSIV.setCol(1,x);

CMatrix p(x), // направление поиска

g(x); // градиент функции

double beta; // число, меняющее длину р

// сокращаем ТИЛ в соответствии с методом

while(norma(df(x))>e && k<*max_step)

{

k++; // увеличиваем счётчик итераций

if(k%(x.getSizeRow())==1) // проверяем номер итерации

p = -df(x); // устанавливаем антиградиентное напрвление

else

{ // вычисляем в соответствии с формулой

beta = (pow(norma(df(x)),2))/(pow(norma(g),2));

p = -df(x) + p*beta; // новое направление поиска

}

g=df(x); // сохраняем текущий градиент

FindAlpha(x,p,e,i1Min); // находим коэффициент удлинения вектора

x = x + p*alpha; // спускаемся в новую точку

MASSIV.insertCol(x); // добавляем новое значение х в массив

}

*max_step=k; // возвращаем количество итераций

return x; // возвращаем найденный минимум

}

// Метод Пауэлла - 1

CMatrix CMETODI::Pauell_1(

CMatrix x, // начальная точка

double e, // погрешность поиска

int* max_step, // максимальное количество итераций

int i1Min) // метод одномерного поиска

{

int k=0; // задаём счётчик числа итераций

// переопределяем массив значений х

// при пошаговом поиске и задаём

// значение начальной точки

MASSIV.setSize(x.getSizeRow(),x.getSizeCol());

MASSIV.setCol(1,x);

CMatrix x1(x), // начальная точка

p(x), // направление поиска

d(x), // ускоряющее направление

PI; // система сопряжённых направлений

// устанавливаем начальное значение системы

PI.setSize(x.getSizeRow(),x.getSizeRow()+1);

p.setNull(); // делаем направление поиска нулевым

// строим начальную поисковую систему,

// которая состоит из координатных ортов

for(int i=1; i<=x.getSizeRow(); i++)

{

p[i] = 1;

PI.setCol(i,p);

p[i] = 0;

}

// сокращаем ТИЛ в соответствии с методом

while(norma(df(x))>e && k<*max_step)

{

x1=x; // сохраняем начальную точку

// выполняем поиск вдоль системы направлений

for(i=1; i<=x.getSizeRow(); i++)

{

p=PI.getCol(i); // получаем направление

FindAlpha(x,p,e,i1Min); // находим коэффициент удлинения вектора

x = x + alpha*p; // спускаемся в новую точку

}

d=x-x1; // получаем новое направление

FindAlpha(x,d,e,i1Min); // находим коэффициент удлинения вектора

x = x + alpha*d; // спускаемся в новую точку

PI.setCol(x.getSizeRow()+1,d); // устанавливаем последним

// новое направление

if(x.getSizeRow()!=1)

for(i=1; i<=x.getSizeCol()+1; i++) // создаём новую систему

PI.setCol(i,PI.getCol(i+1)); // в соответствии с методом

k++; // увеличиваем счётчик итераций

MASSIV.insertCol(x); // добавляем новое значение х в массив

}

*max_step=k; // возвращаем количество итераций

return x; // возвращаем найденный минимум

}

// Метод Пауэлла - 2

CMatrix CMETODI::Pauell_2(

CMatrix x, // начальная точка

double e, // погрешность поиска

int* max_step, // максимальное количество итераций

int i1Min) // метод одномерного поиска

{

int k=0; // задаём счётчик числа итераций

// переопределяем массив значений х

// при пошаговом поиске и задаём

// значение начальной точки

MASSIV.setSize(x.getSizeRow(),x.getSizeCol());

MASSIV.setCol(1,x);

CMatrix x1(x), // начальная точка

p(x), // направление поиска

d(x), // ускоряющее направление

PI; // система сопряжённых направлений

// устанавливаем начальное значение системы

PI.setSize(x.getSizeRow(),x.getSizeRow()+1);

p.setNull(); // делаем направление поиска нулевым

// строим начальную поисковую систему,

// которая состоит из координатных ортов

for(int i=1; i<=x.getSizeRow(); i++)

{

p[i] = 1;

PI.setCol(i,p);

p[i] = 0;

}

// сокращаем ТИЛ в соответствии с методом

while(norma(df(x))>e && f(x1)>=f(x) && k<*max_step)

{

x1=x; // сохраняем начальную точку

// выполняем поиск вдоль системы направлений

for(i=1; i<=x.getSizeRow(); i++)

{

p=PI.getCol(i); // получаем направление

FindAlpha(x,p,e,i1Min); // находим коэффициент удлинения вектора

x = x + alpha*p; // спускаемся в новую точку

}

d=x-x1; // получаем новое направление

FindAlpha(x,d,e,i1Min); // находим коэффициент удлинения вектора

x = x + alpha*d; // спускаемся в новую точку

PI.setCol(1,d);

PI.setCol(x.getSizeRow()+1,d); // устанавливаем последним

// новое направление

if(x.getSizeRow()!=1)

for(i=2; i<x.getSizeCol()+1; i++) // создаём новую систему

PI.setCol(i,PI.getCol(i+1)); // в соответствии с методом

k++; // увеличиваем счётчик итераций

MASSIV.insertCol(x); // добавляем новое значение х в массив

}

*max_step=k; // возвращаем количество итераций

return x; // возвращаем найденный минимум

}

CMatrix CMETODI::ComplexBox(CMatrix x,int num)

{

CMatrix complex[2*5+1];

int complexSize=2*x.getSizeRow(); // размер комплекса >(n+1), принимаем его = 2n

int ii=0;

for(ii=1; ii<complexSize; ii++)

complex[ii]=x.setSingle(5);

complex[0]=x;

CMatrix Xi=x, Xc=x, Xh=x, Xr=x, X0=x;

double alpha=1.3, sigma=0, sum=0, sum2=0, Eps=0.0001;

CMatrix Ai;

CMatrix Bi;

int nmax_dot=0;

srand((unsigned)time(NULL));

int k=0, kk=0, kkk=0;

int i=0;

Xc=x;

for(i=1; i<complexSize; i++)

{

for(int j=0; j<=x.getSizeRow(); j++)

Xi[j]=Ai[j] + ((double)rand()/(double)(RAND_MAX)) * (Bi[j]-Ai[j]);

kkk=0;

while(!(isComplies_g(Xi, num)&&(isComplies_a_b(Xi, Ai, Bi, num)))) // 6

{

Xi=0.5*(Xi+Xc);

if(kkk++>1000)

{ break; }

}

complex[i]=Xi; // 5

Xc=(1/(double)i)*((i-1)*Xc+Xi);

}

for(ii=0; ii<complexSize; ii++)

sortComplexByFuncVal(complex, complexSize, num);

do // вторая блок-схема

{

for(ii=0; ii<complexSize; ii++)

nmax_dot=complexSize-1;

X0=centerOfGravity(&complex[0], complexSize, x, nmax_dot);

Xh=complex[nmax_dot]; // Xh=Xk

Xr=(alpha+1)*X0 - alpha*Xh;

kk=0;

do

{

if(isComplies_g(Xr, num)&&(isComplies_a_b(Xr, Ai, Bi, num))) // 16

{

if(f(Xr) > f(Xh))

{

Xr=0.5*(Xr+X0);

continue;

}

else

{

break; // ->21

}

}

if(!isComplies_a_b(Xr, Ai, Bi, num))

{

for(ii=0; ii<Xr.getSizeCol(); ii++) // 17

{

if(Xr[ii]<Ai[ii])

Xr[ii] = Ai[ii] + 1e-6;

}

for(ii=0; ii<=Xr.getSizeRow(); ii++)

{

if(Xr[ii]>Bi[ii])

Xr[ii] = Bi[ii] - 1e-6;

} }

if(!isComplies_g(Xr, num)) // 18

{

Xr=0.5*(Xr+X0);

}

if(kk++>1000) break;

} while(!((isComplies_g(Xr, num))&&(isComplies_a_b(x, Ai, Bi, num))));

complex[nmax_dot]=Xr; // 22

sortComplexByFuncVal(complex, complexSize, num);

sum=0; sum2=0; sigma=0;

for(ii=0; ii<complexSize; ii++)

{ sum+=f(complex[ii]); }

sum/=double(complexSize);

for(ii=0; ii<complexSize; ii++)

sigma += pow(f(complex[ii]) - sum, 2)/complexSize;

if(k++>1000) break;

if((sigma < Eps) && (findMaxDistance(&complex[0], complexSize-1)<Eps)) break; }

while(1);

x+=complex[0];

return x;

}