实验二:最速下降法
一、实验目的
通过最速下降法的程序设计,为今后的约束优化方法的学习和编程奠定基础;掌握负梯度方向的定义和最速下降法的迭代公式;通过此次实验,进一步巩固最速下降法的基本原理和思想。

二、实验内容

(1)求解无约束优化问题: ;
(2)终止准则取 ;f(x)=(x1+10*x2)^2+5(x3-x4)^2+(x2-2*x3)^4+10*(x1-x4)^4||f(x^k)||10^(-6)
(3)完成最速下降法(负梯度法)的MATLAB编程、调试;
(4)要求选取多个不同的初始点,并给出迭代次数,最优函数值等相关信息,有能力的同学尝试画出最优值随迭代次数变化的曲线图;
(5)按照模板撰写实验报告,要求规范整洁。


三、算法步骤、代码、及结果
1. 算法步骤
1. steepest_descent 函数
1. 定义目标函数 f 和其梯度 grad_f:
目标函数 f 和梯度 grad_f 是给定的,分别用于计算函数值和梯度。
2. 初始化初始点集合 initial_points:
定义了一组初始点用于梯度下降算法。
3. 设置终止准则和最大迭代次数:
使用 tol 作为梯度范数的阈值,当梯度范数小于 tol 时停止迭代;max_iter 为最大迭代次数。
4. 遍历初始点:
对于每个初始点,调用 gradient_descent 函数进行梯度下降优化,并打印结果。
5. 绘制最优值随迭代次数变化的曲线图:
使用 plot 函数为每个初始点绘制最优值随迭代次数变化的曲线图。
2. gradient_descent 函数
1. 初始化:
将初始点 x0 赋给 x,并初始化一个用于存储每次迭代函数值的数组 f_values。
2. 迭代过程:
对于每次迭代,计算当前点的梯度 grad,并将函数值 f(x) 存储在 f_values 中。
3. 检查终止条件:
如果梯度的范数小于 tol,则停止迭代。
4. 线搜索:
调用 line_search 函数找到最佳的步长 alpha。
5. 更新解:
使用步长 alpha 和梯度 grad 更新解 x。
6. 返回结果:
返回优化后的解 x_opt、最优函数值 f_val、迭代次数 iter 以及函数值数组 f_values。
3. line_search 函数
1. 初始化步长和参数:
设置初始步长 alpha 为 1,以及 c、rho 作为线搜索的参数。
2. 线搜索过程:
在 while 循环中,检查 f(x - alpha * grad) 是否满足Armijo-Goldstein条件(即是否小于 f(x) - c * alpha * (grad' * grad))。
3. 更新步长:
如果不满足Armijo-Goldstein条件,则将步长 alpha 乘以 rho 进行缩减。
4. 返回结果:
当满足Armijo-Goldstein条件时,返回步长 alpha。

2. 代码
function steepest_descent()
% 定义目标函数
f = @(x) (x(1) + 10*x(2))^2 + 5*(x(3) - x(4))^2 + (x(2) - 2*x(3))^4 + 10*(x(1) - x(4))^4;

% 定义目标函数的梯度
grad_f = @(x) [
2*(x(1) + 10*x(2)) + 40*(x(1) - x(4))^3;
20*(x(1) + 10*x(2)) + 4*(x(2) - 2*x(3))^3;
10*(x(3) - x(4)) - 8*(x(2) - 2*x(3))^3;
-10*(x(3) - x(4)) - 40*(x(1) - x(4))^3
];

% 初始点集合
initial_points = [
0, 0, 0, 0;
1, 1, 1, 1;
-1, -1, -1, -1;
2, 2, 2, 2;
-2, -2, -2, -2
];

% 终止准则
tol = 1e-6;

% 最大迭代次数
max_iter = 10000;

% 遍历初始点
for i = 1:size(initial_points, 1)
x0 = initial_points(i, :)';
[x_opt, f_val, iter, f_values] = gradient_descent(f, grad_f, x0, tol, max_iter);
fprintf('初始点: [%f, %f, %f, %f]\n', x0);
fprintf('迭代次数: %d\n', iter);
fprintf('最优函数值: %f\n', f_val);
fprintf('最优点: [%f, %f, %f, %f]\n\n', x_opt);

% 绘制最优值随迭代次数变化的曲线图
figure;
plot(1:iter, f_values, '-o');
title(sprintf('初始点 [%f, %f, %f, %f]', x0));
xlabel('迭代次数');
ylabel('函数值');
grid on;
end
end

function [x_opt, f_val, iter, f_values] = gradient_descent(f, grad_f, x0, tol, max_iter)
x = x0;
f_values = zeros(max_iter, 1);
for iter = 1:max_iter
grad = grad_f(x);
f_values(iter) = f(x);
if norm(grad) < tol
break;
end
alpha = line_search(f, grad_f, x, grad);
x = x - alpha * grad;
end
x_opt = x;
f_val = f(x_opt);
f_values = f_values(1:iter);
end

function alpha = line_search(f, grad_f, x, grad)
alpha = 1;
c = 1e-4;
rho = 0.9;
while f(x - alpha * grad) > f(x) - c * alpha * (grad' * grad)
alpha = rho * alpha;
end
end


3. 结果

四、心得体会在每一步迭代中,选择能使目标函数下降最快的方向作为搜索方向,即负梯度方向
通过本次实验对于最速下降法有了更深的理解,这是寻找最小值,通过每次迭代,使用负梯度方向作为搜索方向进行,让目标函数下降最快.同时在本次实验中学会了在MATLAB中绘制图形,让函数有了更直观的表现形式.

代码量 200行