应用最优化方法及MATLAB实现——第4章代码实现

一、概述

之前对这本书的第三章进行了代码实现,这篇博客是对这本书第4章相关代码进行实现,部分内容安装书中代码无法实现相应功能,MATLAB会报错,对其进行一定程度的更改后,可以正常运行,与书中所给示例运行结果相一致。

二、具体实现

(一)使用函数

1.概述

因为书中几个条件使用的示例函数均相同,在此将其单独罗列出来,复制即可。

2.函数实现

f_test1和其导数g_test1。

Matlab 复制代码
function y = f_test1(x)
%F_TEST1 此处显示有关此函数的摘要
%   此处显示详细说明

y = -3 * x * sin(0.75 * x) + exp(-2 * x);

end
Matlab 复制代码
function y = g_test1(x)
%G_TEST1 此处显示有关此函数的摘要
%   此处显示详细说明

y = -2 / exp(2 * x) - 3 * sin(x * 0.75) - (3 * 0.75 * x * cos(0.75 * x));

end

f_test2和其导数g_test2。

Matlab 复制代码
function y = f_test2(x)
%F_TEST2 此处显示有关此函数的摘要
%   此处显示详细说明

x1 = x(1);
x2 = x(2);
y = x1 ^ 2 + x2 ^ 2 - 1;

end
Matlab 复制代码
function y = g_test2(x)
%G_TEST2 此处显示有关此函数的摘要
%   此处显示详细说明

x1 = x(1);
x2 = x(2);
y = 2 * x1 + 2 * x2;

end

f_test3和其导数g_test3。

Matlab 复制代码
function y = f_test3(x)
%F_TEST3 此处显示有关此函数的摘要
%   此处显示详细说明

y = sin(3 * x) / x;

end
Matlab 复制代码
function y = g_test3(x)
%G_TEST3 此处显示有关此函数的摘要
%   此处显示详细说明

y = (3 * cos(3 * x)) / x - sin(3 * x) / ( x ^ 2);

end

(二)Armijo_search条件

1.main.m文件

这个文件是此条件的主运行文件,放开相应注释即可运行每个示例。

Matlab 复制代码
% 这个文件主要为Armijo_search文件的主程序

% 清空
close;
clear;
clc;

% 第一个示例
% x_current = -2;
% d_current = 1;
% rho = 0.1;
% [alpha_acceptable, x_next, f_next, k] = Armijo_search(@f_test1, @g_test1, x_current, d_current, rho);

% 第二个示例
% x_current = [2;2];
% d_current = [-1;-1];
% rho = 0.1;
% [alpha_acceptable, x_next, f_next, k] = Armijo_search(@f_test2, @g_test2, x_current, d_current, rho);

% 第三个示例
x_current = 5;
d_current = 1;
rho = 0.5;
[alpha_acceptable, x_next, f_next, k] = Armijo_search(@f_test3, @g_test3, x_current, d_current, rho);

2.Armijo_search.m文件

此函数跟书中函数一样,没有太大改动。

Matlab 复制代码
function [alpha_acceptable, x_next, f_next, k] = Armijo_search(f_test, g_test, x_current, d_current, rho)
% f_test, 目标函数
% g_test, 目标函数对决策变量x的导数
% x_current, x在向量空间中的当前点
% d_current, f_test在x_current的下降搜索方向
% rho, 可接受系数

k_max = 1000;
k = 0;
f_current = f_test(x_current);
g_current = g_test(x_current);
f_alpha_lower_k = f_current;
g_alpha_lower_k = g_current;
df_alpha_lower_k = (d_current') * g_alpha_lower_k; % 这里这个值是一直保持不变的
f_alpha_lower_0 = f_alpha_lower_k;
df_alpha_lower_0 = df_alpha_lower_k;

alpha_lower_k = 0;
alpha_upper_k = 1e8;
alpha_k = alpha_upper_k;

% 
for k = 1:k_max
    x_alpha_k = x_current + alpha_k * d_current;
    f_alpha_k = f_test(x_alpha_k);
    Armijo_condition = f_alpha_k - f_alpha_lower_0 - rho * alpha_k * df_alpha_lower_0;
    if (Armijo_condition <= 0)
        alpha_acceptable = alpha_k;
        x_next = x_alpha_k;
        f_next = f_alpha_k;
        break;
    else
        if (alpha_k < alpha_upper_k)
           alpha_upper_k = alpha_k;
        end
        alpha_k = alpha_lower_k + (1/2) * ((alpha_k ^ 2) * df_alpha_lower_k) / (f_alpha_lower_k - f_alpha_k + alpha_k * df_alpha_lower_k);
        % x_alpha_k = x_current + alpha_k * d_current;
        % g_alpha_lower_k = g_test(x_alpha_k);
        % df_alpha_lower_k = (d_current') * g_alpha_lower_k;
    end
end

if(k == k_max)
    disp('Armijo inexact line search algorithm failed');
    alpha_acceptable = NaN;
    x_next = NaN;
    f_next = NaN;
end

end

(三)Goldstein_search条件

1.main.m文件

这个文件是此条件的主运行文件,放开相应注释即可运行每个示例。

Matlab 复制代码
% 这个文件主要为Goldstein_search文件的主程序

% 清空
close;
clear;
clc;

% 第一个示例
% x_current = -2;
% d_current = 1;
% rho = 0.1;
% [alpha_acceptable, x_next, f_next, k] = Goldstein_search(@f_test1, @g_test1, x_current, d_current, rho);

% 第二个示例
x_current = [2;2];
d_current = [-1;-1];
rho = 0.1;
[alpha_acceptable, x_next, f_next, k] = Goldstein_search(@f_test2, @g_test2, x_current, d_current, rho);

% 第三个示例
% x_current = 5;
% d_current = 1;
% rho = 0.1;
% [alpha_acceptable, x_next, f_next, k] = Goldstein_search(@f_test3, @g_test3, x_current, d_current, rho);

2.Goldstein_search.m文件

此文件有些改动。

Matlab 复制代码
function [alpha_acceptable, x_next, f_next, k] = Goldstein_search(f_test, g_test, x_current, d_current, rho)
% f_test, 目标函数
% g_test, 目标函数对决策变量x的导数
% x_current, x在向量空间中的当前点
% d_current, f_test在x_current的下降搜索方向
% rho, 可接受系数

k_max = 1000;
k = 0;
f_current = f_test(x_current);
g_current = g_test(x_current);
f_alpha_lower_k = f_current;
g_alpha_lower_k = g_current;
df_alpha_lower_k = (d_current') * g_alpha_lower_k; 
f_alpha_lower_0 = f_alpha_lower_k;
df_alpha_lower_0 = df_alpha_lower_k;

tolerance = 1e-15;
if (abs(df_alpha_lower_k) > tolerance)
    alpha_initial = - 2 * f_alpha_lower_k ./ df_alpha_lower_k;
else
    alpha_initial = 1;
end
alpha_lower_k = 0;
alpha_upper_k = 1e8;
alpha_k = alpha_initial; % 这个值是从初始值开始

for k = 1:k_max
    x_alpha_k = x_current + alpha_k .* d_current;
    f_alpha_k = f_test(x_alpha_k);
    g_alpha_k = g_test(x_alpha_k);
    df_alpha_k = (d_current') * g_alpha_k;
    Goldstein_condition1 = f_alpha_k - f_alpha_lower_0 - rho * alpha_k * (df_alpha_lower_0');
    Goldstein_condition2 = f_alpha_lower_0 + (1 - rho) * alpha_k * (df_alpha_lower_0') - f_alpha_k;

    if(Goldstein_condition1 <= 0)
        if(Goldstein_condition2 <= 0)
            alpha_acceptable = alpha_k;
            x_next = x_alpha_k;
            f_next = f_alpha_k;
            break;
        else
            delta_alpha_k = (alpha_k - alpha_lower_k) * df_alpha_k / (df_alpha_lower_k - df_alpha_k);
            if(delta_alpha_k <= 0)
                alpha_k_temp = 2 * alpha_k;
            else
                alpha_k_temp = alpha_k + delta_alpha_k;
            end
            alpha_lower_k = alpha_k;
            f_alpha_lower_k = f_alpha_k;
            df_alpha_lower_k = df_alpha_k;
            alpha_k = alpha_k_temp;
        end
    else
        if (alpha_k < alpha_upper_k)
            alpha_upper_k = alpha_k;
        end
        alpha_k_temp = alpha_lower_k + (1/2) * (((alpha_k - alpha_lower_k) ^ 2) * df_alpha_lower_k) / (f_alpha_lower_k - f_alpha_k + (alpha_k - alpha_lower_k) * df_alpha_lower_k);
        alpha_k = alpha_k_temp;
    end

    if(alpha_upper_k - alpha_lower_k < tolerance)
        alpha_acceptable = alpha_k;
        x_next = x_alpha_k;
        f_next = f_alpha_k;
        break;
    end
end
if((Goldstein_condition1 > 0)||(Goldstein_condition2 > 0))
    disp('Goldstein inexact line search algorithm failed');
    alpha_acceptable = NaN;
    x_next = NaN;
    f_next = NaN;
end
end

3.注意

(1)第1方面

这个文件改动的主要原因是因为,在运行第二个示例中,无法安装成功运行,会出现数据维度不一样的报错。因为第二个示例所给的数据不再是单一变量,而是双变量。

如图所示,如图中红线划出部分。这个部分在单一变量中不会出错,但是在多变量中,因为向量没有除法,所以会报错。

将其改成如图所示,即可消除报错。

(2)第二方面

除此之外,还有一部分,如图中红线圈出,由于这两个向量维度相同,都是2*1,所以无法直接相乘。

将其更改为如图所示的部分,更改的思路是因为最后需要的是标量,需要将后面的维度为2*1的,进行转置即可。

(四)Wolfe_search条件

1.main.m文件

这个文件是此条件的主运行文件,放开相应注释即可运行每个示例。

Matlab 复制代码
% 这个文件主要为Wolfe_search文件的主程序

% 清空
close;
clear;
clc;

% 第一个示例
% x_current = -2;
% d_current = 1;
% rho = 0.1;
% sigma = 0.11;
% [alpha_acceptable, x_next, f_next, k] = Wolfe_search(@f_test1, @g_test1, x_current, d_current, rho, sigma);

% 第二个示例
x_current = [2;2];
d_current = [-1;-1];
rho = 0.1;
sigma = 0.11;
[alpha_acceptable, x_next, f_next, k] = Wolfe_search(@f_test2, @g_test2, x_current, d_current, rho, sigma);

% 第三个示例
% x_current = 5;
% d_current = 1;
% rho = 0.5;
% sigma = 0.11;
% [alpha_acceptable, x_next, f_next, k] = Wolfe_search(@f_test3, @g_test3, x_current, d_current, rho, sigma);

2.Wolfe_search.m文件

此文件的部分地方同样也经过更改,部分更改的思路与前面有一些相似之处。

Matlab 复制代码
function [alpha_acceptable, x_next, f_next, k] = Wolfe_search(f_test, g_test, x_current, d_current, rho, sigma)
% f_test, 目标函数
% g_test, 目标函数对决策变量x的导数
% x_current, x在向量空间中的当前点
% d_current, f_test在x_current的下降搜索方向
% rho, 可接受系数
% sigma, 可接受点处的切线斜率大于初始点处切线斜率的倍数,0<rho<sigma<1

k_max = 1000;
k = 0;
f_current = f_test(x_current);
g_current = g_test(x_current);
f_alpha_lower_k = f_current;
g_alpha_lower_k = g_current;
df_alpha_lower_k = (d_current') * g_alpha_lower_k; 
f_alpha_lower_0 = f_alpha_lower_k;
df_alpha_lower_0 = df_alpha_lower_k;

tolerance = 1e-15;
if (abs(df_alpha_lower_k) > tolerance)
    alpha_initial = - 2 * f_alpha_lower_k ./ df_alpha_lower_k;
else
    alpha_initial = 1;
end
alpha_lower_k = 0;
alpha_upper_k = 1e8;
alpha_k = alpha_initial; % 这个值是从初始值开始

for k = 1:k_max
    x_alpha_k = x_current + alpha_k .* d_current;
    f_alpha_k = f_test(x_alpha_k);
    g_alpha_k = g_test(x_alpha_k);
    df_alpha_k = (d_current') * g_alpha_k;
    Wolfe_condition1 = f_alpha_k - f_alpha_lower_0 - rho * alpha_k * (df_alpha_lower_0');
    Wolfe_condition2 = sum(sigma * df_alpha_lower_0 - df_alpha_k);

    if(Wolfe_condition1 <= 0)
        if(Wolfe_condition2 <= 0)
            alpha_acceptable = alpha_k;
            x_next = x_alpha_k;
            f_next = f_alpha_k;
            break;
        else
            delta_alpha_k = (alpha_k - alpha_lower_k) .* df_alpha_k ./ (df_alpha_lower_k - df_alpha_k);
            if(delta_alpha_k <= 0)
                alpha_k_temp = 2 * alpha_k;
            else
                alpha_k_temp = alpha_k + delta_alpha_k;
            end
            alpha_lower_k = alpha_k;
            f_alpha_lower_k = f_alpha_k;
            df_alpha_lower_k = df_alpha_k;
            alpha_k = alpha_k_temp;
        end
    else
        if (alpha_k < alpha_upper_k)
            alpha_upper_k = alpha_k;
        end
        alpha_k_temp = alpha_lower_k + (1/2) * (((alpha_k - alpha_lower_k) ^ 2) * df_alpha_lower_k) / (f_alpha_lower_k - f_alpha_k + (alpha_k - alpha_lower_k) * df_alpha_lower_k);
        alpha_k = alpha_k_temp;
    end

    if(alpha_upper_k - alpha_lower_k < tolerance)
        alpha_acceptable = alpha_k;
        x_next = x_alpha_k;
        f_next = f_alpha_k;
        break;
    end
end
if((Wolfe_condition1 > 0)||(Wolfe_condition2 > 0))
    disp('Wolfe inexact line search algorithm failed');
    alpha_acceptable = NaN;
    x_next = NaN;
    f_next = NaN;
end
end

3.注意

(1)第1方面

与Goldstein条件相同的原因,需要将其修改为下面这样,如图所示。

(2)第2方面

与Goldstein条件相同的原因,需要将其修改为下面这样,如图所示。原因还是因为维度问题。

(3)第3方面

如书中源代码所示,红线划出部分。这个Wolfe_condition2计算结果是2*1维的向量,不是一个标量,虽然在下面判断Wolfe_condition2是否≤0时候没有影响。

但其会影响到这个部分,最后的部分的判断会报错,如图所示。

根据对书中内容的分析,此处应该是个标量,而不应该是个向量,如图所示。

使用sum将其每项相加即可。

(五)Strong_Wolfe_search条件

1.main.m文件

这个文件是此条件的主运行文件,放开相应注释即可运行每个示例。

Matlab 复制代码
% 这个文件主要为Strong_Wolfe_search文件的主程序

% 清空
close;
clear;
clc;

% 第一个示例
x_current = -2;
d_current = 1;
rho = 0.1;
sigma = 0.11;
[alpha_acceptable, x_next, f_next, k] = Strong_Wolfe_search(@f_test1, @g_test1, x_current, d_current, rho, sigma);

% 第二个示例
% x_current = [2;2];
% d_current = [-1;-1];
% rho = 0.1;
% sigma = 0.11;
% [alpha_acceptable, x_next, f_next, k] = Strong_Wolfe_search(@f_test2, @g_test2, x_current, d_current, rho, sigma);

% 第三个示例
% x_current = 5;
% d_current = 1;
% rho = 0.1;
% sigma = 0.11;
% [alpha_acceptable, x_next, f_next, k] = Strong_Wolfe_search(@f_test3, @g_test3, x_current, d_current, rho, sigma);

2.Strong_Wolfe_search.m文件

此文件经过部分更改。

Matlab 复制代码
function [alpha_acceptable, x_next, f_next, k] = Strong_Wolfe_search(f_test, g_test, x_current, d_current, rho, sigma)
% f_test, 目标函数
% g_test, 目标函数对决策变量x的导数
% x_current, x在向量空间中的当前点
% d_current, f_test在x_current的下降搜索方向
% rho, 可接受系数
% sigma, 可接受点处的切线斜率大于初始点处切线斜率的倍数,0<rho<sigma<1

k_max = 1000;
k = 0;
f_current = f_test(x_current);
g_current = g_test(x_current);
f_alpha_lower_k = f_current;
g_alpha_lower_k = g_current;
df_alpha_lower_k = (d_current') * g_alpha_lower_k; 
f_alpha_lower_0 = f_alpha_lower_k;
df_alpha_lower_0 = df_alpha_lower_k;

tolerance = 1e-15;
if (abs(df_alpha_lower_k) > tolerance)
    alpha_initial = - 2 * f_alpha_lower_k ./ df_alpha_lower_k;
else
    alpha_initial = 1;
end
alpha_lower_k = 0;
alpha_upper_k = 1e8;
alpha_k = alpha_initial; % 这个值是从初始值开始

for k = 1:k_max
    x_alpha_k = x_current + alpha_k .* d_current;
    f_alpha_k = f_test(x_alpha_k);
    g_alpha_k = g_test(x_alpha_k);
    df_alpha_k = (d_current') * g_alpha_k;
    Strong_Wolfe_condition1 = f_alpha_k - f_alpha_lower_0 - rho * alpha_k * (df_alpha_lower_0');
    Strong_Wolfe_condition2 = sum(sigma * df_alpha_lower_0 + abs(df_alpha_k));
    % Strong_Wolfe_condition2 = sum(abs(df_alpha_k) - abs(sigma * df_alpha_lower_0));

    if(Strong_Wolfe_condition1 <= 0)
        if(Strong_Wolfe_condition2 <= 0)
            alpha_acceptable = alpha_k;
            x_next = x_alpha_k;
            f_next = f_alpha_k;
            break;
        else
            delta_alpha_k = (alpha_k - alpha_lower_k) .* df_alpha_k ./ (df_alpha_lower_k - df_alpha_k);
            if(delta_alpha_k <= 0)
                alpha_k_temp = 2 * alpha_k;
            else
                alpha_k_temp = alpha_k + delta_alpha_k;
            end
            alpha_lower_k = alpha_k;
            f_alpha_lower_k = f_alpha_k;
            df_alpha_lower_k = df_alpha_k;
            alpha_k = alpha_k_temp;
        end
    else
        if (alpha_k < alpha_upper_k)
            alpha_upper_k = alpha_k;
        end
        alpha_k_temp = alpha_lower_k + (1/2) * (((alpha_k - alpha_lower_k) ^ 2) * df_alpha_lower_k) / (f_alpha_lower_k - f_alpha_k + (alpha_k - alpha_lower_k) * df_alpha_lower_k);
        alpha_k = alpha_k_temp;
    end

    if(alpha_upper_k - alpha_lower_k < tolerance)
        alpha_acceptable = alpha_k;
        x_next = x_alpha_k;
        f_next = f_alpha_k;
        break;
    end
end
if((Strong_Wolfe_condition1 > 0)||(Strong_Wolfe_condition2 > 0))
    disp('Wolfe inexact line search algorithm failed');
    alpha_acceptable = NaN;
    x_next = NaN;
    f_next = NaN;
end
end

3.注意

(1)第1方面

跟前面类似,如图所示。

(2)第2方面

跟前面类似,如图所示,这里将两个问题合并。

(3)第3方面

如图所示,第二个判断条件,可以换成注释掉的那种,根据书中的条件,第二种写法更加符合书中的条件,如图所示。

相关推荐
进阶的架构师9 分钟前
互联网Java工程师面试题及答案整理(2024年最新版)
java·开发语言
易辰君11 分钟前
python爬虫 - 深入requests模块
开发语言·爬虫·python
木子020418 分钟前
java高并发场景RabbitMQ的使用
java·开发语言
无夜_19 分钟前
Prototype(原型模式)
开发语言·c++
看到请催我学习19 分钟前
内存缓存和硬盘缓存
开发语言·前端·javascript·vue.js·缓存·ecmascript
笃励1 小时前
Java面试题二
java·开发语言·python
jyan_敬言1 小时前
【Linux】Linux命令与操作详解(一)文件管理(文件命令)、用户与用户组管理(创建、删除用户/组)
linux·运维·服务器·c语言·开发语言·汇编·c++
FL16238631291 小时前
[C#]C# winform部署yolov11-pose姿态估计onnx模型
开发语言·yolo·c#
笑非不退2 小时前
C++ 异步编程 并发编程技术
开发语言·c++
爱写代码的刚子2 小时前
C++知识总结
java·开发语言·c++