Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа №3.docx
Скачиваний:
0
Добавлен:
25.06.2025
Размер:
243.73 Кб
Скачать

Расчетные таблицы при Градиентный метод с постоянным шагом

ɛ

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- Метод наискорейшего спуска

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