
- •Отчет по лабораторной работе №3
- •Расчетные таблицы при Градиентный метод с постоянным шагом
- •Градиентный метод с дроблением шага
- •Метод наискорейшего спуска
- •Расчетные таблицы при Градиентный метод с постоянным шагом
- •Градиентный метод с дроблением шага
- •Метод наискорейшего спуска
- •Траектория движения точек
Расчетные таблицы при Градиентный метод с постоянным шагом
ɛ |
|
|
|
N |
|
|
l |
|
|
21.5987 |
-21.3315 |
-837.555 |
6406 |
0 |
6406 |
3202 |
0.0499974 |
|
21.6296 |
-21.3633 |
-837.558 |
8708 |
0 |
8708 |
4353 |
0.00499121 |
|
21.6328 |
-21.3665 |
-837.558 |
11008 |
0 |
11008 |
5503 |
0.000499325 |
|
21.6331 |
-21.3668 |
-837.558 |
13308 |
0 |
13308 |
6653 |
5.00103e-005 |
|
21.6332 |
-21.3668 |
-837.558 |
15608 |
0 |
15608 |
7803 |
5.06616e-006 |
Градиентный метод с дроблением шага
ɛ |
|
|
|
N |
|
|
l |
|
|
21.598 |
-21.3317 |
-837.555 |
3282 |
1644 |
1638 |
818 |
0.0497328 |
|
21.6296 |
-21.3633 |
-837.558 |
4454 |
2230 |
2224 |
1111 |
0.00499594 |
|
21.6328 |
-21.3665 |
-837.558 |
5630 |
2818 |
2812 |
1405 |
0.000498007 |
|
21.6331 |
-21.3668 |
-837.558 |
6806 |
3400 |
3400 |
1699 |
4.96999e-005 |
|
- |
- |
- |
- |
- |
- |
- |
- |
Метод наискорейшего спуска
ɛ |
|
|
|
N |
|
|
l |
|
|
21.6101 |
-21.344 |
-837.557 |
12008 |
10672 |
1336 |
667 |
0.0324623 |
|
21.6308 |
-21.3645 |
-837.558 |
16004 |
14224 |
1780 |
889 |
0.00331731 |
|
21.6329 |
-21.3666 |
-837.558 |
20000 |
17776 |
2224 |
1111 |
0.000339053 |
|
21.6331 |
-21.3668 |
-837.558 |
23672 |
21040 |
2632 |
1315 |
4.15319e-005 |
|
21.6332 |
-21.3668 |
-837.558 |
23906 |
21248 |
2658 |
1328 |
2.65256e-006 |
Траектория движения точек
Код программы:
#include <stdafx.h>
#include <iostream>
#include <Windows.h>
#include <algorithm>
#include <math.h>
#include <iomanip>
#include <conio.h>
#include <stdlib.h>
#include <fstream>
using namespace std;
const double const_x1 = 1.0, const_x2 = 1.0;
const double cor_x1 = 21.6331659, cor_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 function_post_shag();
void function_naiskor_spusk();
void function_drobl_shag();
void function_find_lymbda_zolotim(double x1, double x2, double z1, double z2, 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\t0. Выход";
cout << "\n\n\tВвод: ";
cin >> j;
switch (j) {
case 1:
function_post_shag();
cout << endl << endl;
system("pause");
break;
case 2:
function_drobl_shag();
cout << endl << endl;
system("pause");
break;
case 3:
function_naiskor_spusk();
cout << endl << endl;
system("pause");
break;
case 0:
exit(0);
break;
default:
continue;
break;
}
Sleep(100);
cout << endl << endl;
}
cin.get();
cin.clear();
cin.ignore(2018, '\n');
cout << endl << endl;
exit(0);
}
void function_post_shag() { //Градиентный метод с постоянным шагом
cout << "\n\n\tГрадиентный метод с постоянным шагом";
double eps, x1_rasch, x2_rasch, y_rasch, eps_fact;
int N, N_1, l;
double z1, z2, x1, x2, x1L, x2L;
double lymbda = 0.001;
N = 0;
cout << "\nВведите точноеть eps = ";
cin >> eps;
z1 = f_dx1(const_x1, const_x2);
z2 = f_dx2(const_x1, const_x2);
N_1 = 2;
l = 0;
x1 = const_x1;
x2 = const_x2;
do {
x1L = x1 - lymbda * z1;
x2L = x2 - lymbda * z2;
z1 = f_dx1(x1L, x2L);
z2 = f_dx2(x1L, x2L);
N_1 += 2;
x1 = x1L;
x2 = x2L;
l++;
} while (sqrt(pow(z1, 2.0) + pow(z2, 2.0)) > eps);
x1_rasch = x1;
x2_rasch = x2;
y_rasch = f(x1_rasch, x2_rasch);
eps_fact = sqrt(pow((x1_rasch - cor_x1), 2.0) + pow((x2_rasch - cor_x2), 2.0));
N = N_1;
cout << "\neps = " << eps << "\nx1_rasch= " << x1_rasch << "\nx2rasch =" << x2_rasch << "\ny_rasch = " << y_rasch << "\nN = " << N << "\nN_1 = " << N_1 << "\nl = " << l << "\neps_fact = " << eps_fact;
}
void function_drobl_shag() { //Градиентный метод с дроблением шагом
cout << "\n\n\tГрадиентный метод с дроблением шагом";
double eps, x1_rasch, x2_rasch, y_rasch, eps_fact;
int N, N_0, N_1, l;
double z1, z2, x1, x2, x1L, x2L, y, y1;
double lymbda;
cout << "\nВведите точноеть eps = ";
cin >> eps;
lymbda = 1.0;
N = 0;
N_0 = 0;
z1 = f_dx1(const_x1, const_x2);
z2 = f_dx2(const_x1, const_x2);
N_1 = 2;
l = 0;
x1 = const_x1;
x2 = const_x2;
do {
y = f(x1, x2);
N_0++;
do {
y1 = f((x1 - lymbda * z1), (x2 - lymbda * z2));
N_0++;
lymbda /= 2.0;
} while (y <= y1);
lymbda *= 2.0;
x1L = x1 - lymbda * z1;
x2L = x2 - lymbda * z2;
z1 = f_dx1(x1L, x2L);
z2 = f_dx2(x1L, x2L);
x1 = x1L;
x2 = x2L;
N_1 += 2;
l++;
} while (sqrt(pow(z1, 2.0) + pow(z2, 2.0)) > eps);
x1_rasch = x1;
x2_rasch = x2;
y_rasch = f(x1_rasch, x2_rasch);
eps_fact = sqrt(pow((x1_rasch - cor_x1), 2.0) + pow((x2_rasch - cor_x2), 2.0));
N = N_0 + N_1;
cout << "\neps = " << eps << "\nx1_rasch= " << x1_rasch << "\nx2_rasch =" << x2_rasch << "\ny_rasch = " << y_rasch << "\nN = " << N << "\nN_0 = " << N_0 << "\nN_1 = " << N_1 << "\nl = " << l << "\neps_fact = " << eps_fact;
}
void function_naiskor_spusk() { //Метод наискорейшего спуска
cout << "\n\n\tМетод наискорейшего спуска";
double eps, x1_rasch, x2_rasch, y_rasch, eps_fact;
int N, N_0, N_1, l;
double z1, z2, x1, x2, x1L, x2L;
double lymbda;
cout << "\nВведите точноеть eps = ";
cin >> eps;
x1 = const_x1;
x2 = const_x2;
z1 = f_dx1(const_x1, const_x2);
z2 = f_dx2(const_x1, const_x2);
N_0 = 0;
N_1 = 2;
l = 0;
do {
function_find_lymbda_zolotim(x1, x2, z1, z2, lymbda, N_0);
x1L = x1 - lymbda * z1;
x2L = x2 - lymbda * z2;
z1 = f_dx1(x1L, x2L);
z2 = f_dx2(x1L, x2L);
N_1 += 2;
l++;
x1 = x1L;
x2 = x2L;
} while (sqrt(pow(z1, 2.0) + pow(z2, 2.0)) > eps);
x1_rasch = x1;
x2_rasch = x2;
y_rasch = f(x1_rasch, x2_rasch);
N = N_0 + N_1;
eps_fact = sqrt(pow((x1_rasch - cor_x1), 2.0) + pow((x2_rasch - cor_x2), 2.0));
cout << "\neps = " << eps << "\nx1_rasch = " << x1_rasch << "\nx2_rasch =" << x2_rasch << "\ny_rasch = " << y_rasch << "\nN = " << N << "\nN_0 = " << N_0 << "\nN_1 = " << N_1 << "\nl = " << l << "\neps_fact = " << eps_fact;
}
void function_find_lymbda_zolotim(double x1, double x2, double z1, double z2, double& lymbda, int& N_0) {
//find AB
double y_1, y_2, a, b, h = 1;
y_1 = f(x1, x2);
N_0++;
int iter = 1;
while (1) {
y_2 = f((x1 - (iter - h) * z1), (x2 - (iter - h) * z2));
N_0++;
if (y_1 > y_2) {
iter++;
y_1 = y_2;
}
else break;
}
b = iter * h;
if (iter == 1)a = 0;
else a = (iter - 2.0) * h;
//zolotoy
double tau, lymbda_1, lymbda_2, eps;
eps = 0.001;
tau = (1.0 + sqrt(5.0)) / 2.0;
lymbda_1 = b - (b - a) / tau;
lymbda_2 = a + (b - a) / tau;
y_1 = f((x1 + lymbda_1 * z1), (x2 + lymbda_1 * z2));
y_2 = f((x1 + lymbda_2 * z1), (x2 + lymbda_2 * z2));
N_0 += 2;
do {
if (y_1 < y_2) {
b = lymbda_2;
lymbda_2 = lymbda_1;
y_2 = y_1;
lymbda_1 = a + b - lymbda_2;
y_1 = f((x1 - lymbda_1 * z1), (x2 - lymbda_1 * z2));
}
else {
a = lymbda_1;
lymbda_1 = lymbda_2;
y_1 = y_2;
lymbda_2 = a + b - lymbda_1;
y_2 = f((x1 - lymbda_1 * z1), (x2 - lymbda_1 * z2));
}
N_0++;
} while ((b - a) > (2.0 * eps * tau));
if (y_1 < y_2) lymbda = (a + lymbda_2) / 2.0;
else lymbda = (lymbda_2 + b) / 2.0;
}
Блок – схемы:
Рисунок 1- Градиентный метод с постоянным шагом
Рисунок 2- Градиентный метод с дроблением шага
Рисунок 1- Метод наискорейшего спуска
Вывод: в ходе лабораторной работы были сравнены градиентные методы: градиентный метод с постоянным шагом, градиентный метод с дроблением шага и метод наискорейшего спуска. Для заданной целевой функции для заданных условий окончания поиска по критерию минимального числа экспериментов лучшим оказался градиентный метод с дроблением шага.