
Расчетные таблицы при Поиск по образцу
ɛ |
|
|
|
N |
l |
|
|
21.6172 |
-21.3516 |
-837.557 |
77 |
18 |
0.0221028 |
|
21.6318 |
-21.3662 |
-837.558 |
97 |
23 |
0.00146876 |
|
21.6337 |
-21.3668 |
-837.558 |
117 |
28 |
0.000501258 |
|
21.6332 |
-21.3669 |
-837.558 |
153 |
37 |
2.57625e-005 |
|
21.6332 |
-21.3668 |
-837.558 |
181 |
44 |
1.45411e-006 |
Симплекс-регулярный
ɛ |
|
|
|
N |
l |
|
|
19.8594 |
-19.5742 |
-831.163 |
104 |
85 |
2.52187 |
|
21.3315 |
-21.0684 |
-837.377 |
198 |
173 |
0.424339 |
|
21.5943 |
-21.3284 |
-837.555 |
289 |
258 |
0.0546825 |
|
21.6332 |
-21.3668 |
-837.558 |
469 |
430 |
1.89652e-005 |
|
21.6332 |
-21.3668 |
-837.558 |
483 |
438 |
2.44035e-005 |
Метод конфигураций
ɛ |
|
|
|
N |
l |
|
|
21.6318 |
-21.3613 |
-837.556 |
187 |
18 |
0.00566442 |
|
21.6318 |
-21.3613 |
-837.556 |
211 |
18 |
0.00566442 |
|
21.633 |
-21.3665 |
-837.558 |
300 |
24 |
0.000401662 |
|
21.6332 |
-21.3668 |
-837.558 |
381 |
30 |
2.90569e-005 |
|
21.6332 |
-21.3668 |
-837.558 |
443 |
34 |
2.60567e-006 |
Циклический покоординатный спуск
ɛ |
|
|
|
N |
l |
|
|
17.3105 |
-17.0645 |
-800.322 |
4217 |
154 |
6.09881 |
|
21.2992 |
-21.0348 |
-837.336 |
15019 |
408 |
0.470946 |
|
21.6318 |
-21.3651 |
-837.558 |
31423 |
746 |
0.00215164 |
|
21.6289 |
-21.3626 |
-837.558 |
43707 |
842 |
0.00604765 |
|
21.6328 |
-21.3665 |
-837.558 |
67638 |
1092 |
0.0004969 |
Траектория движения точек
Поиск по образцу
Симплекс-регулярный
Метод конфигураций
Метод
покоординатного цикличного спуска
Код программы:
#include <stdafx.h>
#include <iostream>
#include <Windows.h>
#include <algorithm>
#include <math.h>
#include <iomanip>
#include <conio.h>
#include <stdlib.h>
using namespace std;
const int iteration = 5;
const double const_x1 = 1.0, const_x2 = 1.0;
const double rasch_x1 = 21.6331659, rasch_x2 = -21.3668342;
double f(double x1, double x2) {
return 100 * pow(x1, 2) + 198 * x1 * x2 + 100 * pow(x2, 2) - 96 * x1 - 10 * x2 + 94;
}
double f_dx1(double x1, double x2) {
double dfx1;
dfx1 = 200 * x1 + 198 * x2 - 96;
return dfx1;
}
double f_dx2(double x1, double x2) {
double dfx2;
dfx2 = 198 * x1 + 200 * x2 - 10;
return dfx2;
}
void obr();
void simplex();
void config();
void pokoord();
void function_find_lymbda_1(double x1, double x2, double eps, double& lymbda, int& N_0);
void function_find_lymbda_2(double x1, double x2, double eps, double& lymbda, int& N_0);
int main() {
SetConsoleOutputCP(1251);
cout << left;
int j;
while (1) {
system("CLS");
cout << "\n\t1. \"Поиск по образцу\"";
cout << "\n\t2. \"Симплекс-регулярный\"";
cout << "\n\t3. \"Метод конфигурации\"";
cout << "\n\t4. \"Циклический покоординатный спуск\"";
cout << "\n\t0. Выход";
cout << "\n\n\tВвод: ";
cin >> j;
cout << "\n\n\n";
switch (j) {
case 1:
obr();
cout << endl << endl;
system("pause");
break;
case 2:
simplex();
cout << endl << endl;
system("pause");
break;
case 3:
config();
cout << endl << endl;
system("pause");
break;
case 4:
pokoord();
cout << endl << endl;
system("pause");
break;
case 0:
exit(0);
break;
default:
continue;
break;
}
cout << endl << endl;
}
cin.get();
cin.clear();
cin.ignore(2018, '\n');
cout << endl << endl;
exit(0);
}
void obr() { //Поиск по образцу
cout << "\n\n\tПоиск по образцу";
double eps, culc_x1, culc_x2, culc_y, eps_fact;
int N, l;
double h, y[5], x1[5], x2[5];
int k;
cout << "\n\tВведите eps ";
cin >> eps;
h = 10.0;
k = 0;
x1[0] = const_x1;
x2[0] = const_x2;
y[0] = f(x1[0], x2[0]);
N = 1;
l = 0;
while (1) {
x1[1] = x1[0] + h;
x1[2] = x1[0] + h;
x1[3] = x1[0] - h;
x1[4] = x1[0] - h;
x2[1] = x2[0] + h;
x2[2] = x2[0] - h;
x2[3] = x2[0] - h;
x2[4] = x2[0] + h;
for (int i = 1; i <= 4; i++) {
y[i] = f(x1[i], x2[i]);
if (i == 1 || y[k] > y[i]) k = i;
}
N += 4;
if (y[k] < y[0]) {
x1[0] = x1[k];
x2[0] = x2[k];
y[0] = y[k];
}
else if ((sqrt(2.0) * h) > eps)h /= 2.0;
else break;
l++;
}
culc_x1 = x1[0];
culc_x2 = x2[0];
culc_y = f(culc_x1, culc_x2);
eps_fact = sqrt(pow((culc_x1 - rasch_x1), 2) + pow((culc_x2 - rasch_x2), 2));
cout << "\neps = " << eps << "\nx_rasch = " << culc_x1 << "\ny_rasch = " << culc_x2 << "\ny_rasch = " << culc_y << "\nN = " << N << "\nl = " << l << "\neps_fact = "<< eps_fact;
}
void simplex() { //Симплекс-регулярный
cout << "\n\n\tСимплекс-регулярный";
double eps, culc_x1, culc_x2, culc_y, eps_fact;
int N, l;
double r, y[3], x1[3], x2[3], c1, c2, u1, u2, y_tmp;
int k_max, k_min;
cout << "\n\tВведите eps ";
cin >> eps;
k_min = 0;
k_max = 0;
x1[0] = const_x1;
x2[0] = const_x2;
r = 15;
l = 0;
x1[1] = x1[0] + r;
x1[2] = x1[0];
x2[1] = x2[0];
x2[2] = x2[0] + r;
y[0] = f(x1[0], x2[0]);
y[1] = f(x1[1], x2[1]);
y[2] = f(x1[2], x2[2]);
N = 3;
while (fabs(r) > eps) {
for (int i = 0; i <= 2; i++) {
if (y[k_min] > y[i]) k_min = i;
if (y[k_max] < y[i]) k_max = i;
}
c1 = 0.5 * (x1[0] + x1[1] + x1[2] - x1[k_max]);
c2 = 0.5 * (x2[0] + x2[1] + x2[2] - x2[k_max]);
u1 = 2.0 * c1 - x1[k_max];
u2 = 2.0 * c2 - x2[k_max];
y_tmp = f(u1, u2);
N++;
if (y_tmp < y[k_max]) {
x1[k_max] = u1;
x2[k_max] = u2;
y[k_max] = y_tmp;
}
else {
for (int i = 0; i <= 2; i++) {
x1[i] = (x1[i] + x1[k_max]) / 2.0;
x2[i] = (x2[i] + x2[k_max]) / 2.0;
y[i] = f(x1[i], x2[i]);
}
N += 2;
r /= 2.0;
}
l++;
}
culc_x1 = x1[k_min];
culc_x2 = x2[k_min];
culc_y = f(x1[k_min], x2[k_min]);
eps_fact = sqrt(pow((culc_x1 - rasch_x1), 2.0) + pow((culc_x2 - rasch_x2), 2.0));
cout << "\neps = " << eps << "\nx_rasch = " << culc_x1 << "\ny_rasch = " << culc_x2 << "\ny_rasch = " << culc_y << "\nN = " << N << "\nl = " << l << "\neps_fact = "<< eps_fact;
}
void config() { //Метод конфигурации
cout << "\n\n\tМетод конфигурации";
double eps, culc_x1, culc_x2, culc_y, eps_fact;
int N, l;
double h, lymbda, x1L, x2L, x1L1, x2L1, x1L2, x2L2, y0, y1, y2, y3;
double y[3][3];
cout << "\n\tВведите eps ";
cin >> eps;
l = 0;
y0 = f(const_x1, const_x2);
N = 1;
x1L = x1L1 = const_x1;
x2L = x2L1 = const_x2;
h = 0.4;
while (1) {
x1L = x1L1;
x2L = x2L1;
y[0][0] = f((x1L - h), (x2L + h));
y[0][1] = f((x1L), (x2L + h));
y[0][2] = f((x1L + h), (x2L + h));
y[1][0] = f((x1L - h), (x2L));
y[1][1] = f((x1L), (x2L));
y[1][2] = f((x1L + h), (x2L));
y[2][0] = f((x1L - h), (x2L - h));
y[2][1] = f((x1L), (x2L - h));
y[2][2] = f((x1L + h), (x2L - h));
N += 8;
y1 = y2 = y[1][1];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (y[i][j] < y2) {
y2 = y[i][j];
if (j == 0)x1L1 = x1L - h;
else if (j == 1)x1L1 = x1L;
else x1L1 = x1L + h;
if (i == 0)x2L1 = x2L + h;
else if (i == 1)x2L1 = x2L;
else x2L1 = x2L - h;
}
if (x1L1 == x1L && x2L1 == x2L)
if (h > eps) h /= 2.0;
else break;
else {
lymbda = 1000.0;
do {
x1L2 = x1L + lymbda * (x1L1 - x1L);
x2L2 = x2L + lymbda * (x2L1 - x2L);
y3 = f(x1L2, x2L2);
N++;
lymbda /= 2.0;
} while (y3 >= y2);
x1L1 = x1L2;
x2L1 = x2L2;
l += 2;
y0 = y3;
}
}
culc_x1 = x1L;
culc_x2 = x2L;
culc_y = f(culc_x1, culc_x2);
eps_fact = sqrt(pow((culc_x1 - rasch_x1), 2.0) + pow((culc_x2 - rasch_x2), 2.0));
cout << "\neps = " << eps << "\nx_rasch = " << culc_x1 << "\ny_rasch = " << culc_x2 << "\ny_rasch = " << culc_y << "\nN = " << N << "\nl = " << l << "\neps_fact = "<< eps_fact;
}
void pokoord() { //Циклический покоординатный спуск
cout << "\n\n\tЦиклический покоординатный спуск";
double eps, culc_x1, culc_x2, culc_y, eps_fact;
int N, l, N_0, N_1;
double x1L, x1L1, x1L2, x2L, x2L1, x2L2, lymbda, d;
cout << "\n\tВведите eps ";
cin >> eps;
N_0 = 0;
N_1 = 0;
l = 0;
x1L = const_x1;
x2L = const_x2;
do {
function_find_lymbda_1(x1L, x2L, eps, lymbda, N_0);
x1L1 = x1L + lymbda;
x2L1 = x2L;
function_find_lymbda_2(x1L1, x2L1, eps, lymbda, N_0);
x1L2 = x1L1;
x2L2 = x2L1 + lymbda;
d = sqrt(pow((x1L2 - x1L), 2.0) + pow((x2L2 - x2L), 2.0));
l += 2;
x1L = x1L2;
x2L = x2L2;
} while (d > eps);
culc_x1 = x1L;
culc_x2 = x2L;
culc_y = f(culc_x1, culc_x2);
N = N_0 + N_1;
eps_fact = sqrt(pow((culc_x1 - rasch_x1), 2.0) + pow((culc_x2 - rasch_x2), 2.0));
cout << "\neps = " << eps << "\nx_rasch = " << culc_x1 << "\ny_rasch = " << culc_x2 << "\ny_rasch = " << culc_y << "\nN = " << N << "\nl = " << l << "\neps_fact = "<< eps_fact;
}
void function_find_lymbda_1(double x1, double x2, double eps, double& lymbda, int& N_0) {
double lymbda_1, lymbda_2, y_2, y_1;
double h = 50.0;
lymbda_1 = 0.0;
y_1 = f(x1, x2);
N_0++;
while (1) {
while (1) {
lymbda_2 = lymbda_1 + h;
y_2 = f((x1 + lymbda_2), x2);
N_0++;
if (y_1 > y_2) {
lymbda_1 = lymbda_2;
y_1 = y_2;
}
else break;
}
if (fabsl(h) <= eps) {
lymbda = lymbda_1;
break;
}
else {
h /= -4.0;
lymbda_1 = lymbda_2;
y_1 = y_2;
}
}
}
void function_find_lymbda_2(double x1, double x2, double eps, double& lymbda, int& N_0) {
double lymbda_1, lymbda_2, y_2, y_1;
double h = 50.0;
lymbda_1 = 0.0;
y_1 = f(x1, x2);
N_0++;
while (1) {
while (1) {
lymbda_2 = lymbda_1 + h;
y_2 = f(x1, (x2 + lymbda_2));
N_0++;
if (y_1 > y_2) {
lymbda_1 = lymbda_2;
y_1 = y_2;
}
else break;
}
if (fabsl(h) <= eps) {
lymbda = lymbda_1;
break;
}
else {
h /= -4.0;
lymbda_1 = lymbda_2;
y_1 = y_2;
}
}
}
Блок
– схемы:
Блок – схема метода поиска по образцу
Блок – схема метода симплекс - регулярного
Блок -схема метода конфигураций
Блок – схема метода циклического покоординатного спуска
Вывод: в ходе лабораторной работы были сравнены градиентные методы: градиентный метод с постоянным шагом, градиентный метод с дроблением шага и метод наискорейшего спуска. Для заданной целевой функции для заданных условий окончания поиска по критерию минимального числа экспериментов лучшим оказался градиентный метод с дроблением шага.