You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何在MATLAB中求解含双重求和的目标函数极小化问题

解决MATLAB fmincon中目标函数未定义的问题

你遇到的fun_rp是未定义函数或变量错误,核心原因是你定义匿名函数的方式不符合MATLAB的语法规则,而且目标函数的实现逻辑也有两处关键问题:

  1. MATLAB的匿名函数默认不支持直接写多行for循环(除非用特殊的单行拼接语法,但可读性极差);
  2. 你的循环代码没有对目标函数值进行累加,也没有返回计算结果,相当于这个函数没有输出。

下面给你两种可行的解决方案,推荐优先用第一种向量化实现(MATLAB对向量/矩阵运算的优化远优于循环):


方案1:向量化实现目标函数(高效推荐)

我们可以把双重求和的目标函数转化为向量/矩阵运算,避免嵌套循环,大幅提升运算效率。先简化目标函数的逻辑:

  • 先计算v = C * w'(协方差矩阵和权重向量的乘积,得到n×1的向量);
  • 再计算k = w .* v(逐元素相乘,得到1×n的向量,每个元素对应w_i*(Cw)_i);
  • 最后通过k - k'生成n×n的差分矩阵,对矩阵所有元素平方后求和,就是目标函数值。

对应的完整代码如下:

% 初始化参数(替换C为你的实际协方差矩阵)
port_size = 4;
C = cov(randn(100, port_size)); % 示例协方差矩阵,替换成你的数据
w0 = [0.25, 0.25, 0.25, 0.25];
Aeq = ones(1, port_size);
beq = 1;
lb = zeros(1, port_size);
ub = ones(1, port_size);

% 定义向量化的目标函数
fun_rp = @(w) sum(sum(( (w .* (C * w')) - (w .* (C * w'))' ).^2 ));

% 调用fmincon求解,添加选项显示迭代过程
options = optimoptions('fmincon', 'Display', 'iter');
[w_opt, f_opt] = fmincon(fun_rp, w0, [], [], Aeq, beq, lb, ub, [], options);

方案2:用单独的函数文件实现循环逻辑

如果你更习惯用循环的方式实现,可以把目标函数写到一个独立的.m文件中,再在主脚本里用匿名函数调用:

第一步:创建rp_objective.m函数文件

function f_val = rp_objective(w, C)
    n = length(w);
    f_val = 0;
    v = C * w'; % 计算C*w的列向量
    
    % 双重循环累加目标函数值
    for i = 1:n
        term_i = w(i) * v(i);
        for j = 1:n
            term_j = w(j) * v(j);
            f_val = f_val + (term_i - term_j)^2;
        end
    end
end

第二步:在主脚本中调用

% 初始化参数
port_size = 4;
C = cov(randn(100, port_size));
w0 = [0.25, 0.25, 0.25, 0.25];
Aeq = ones(1, port_size);
beq = 1;
lb = zeros(1, port_size);
ub = ones(1, port_size);

% 定义匿名函数,传入协方差矩阵C
fun_rp = @(w) rp_objective(w, C);

% 调用fmincon求解
options = optimoptions('fmincon', 'Display', 'iter');
[w_opt, f_opt] = fmincon(fun_rp, w0, [], [], Aeq, beq, lb, ub, [], options);

为什么原来的代码不行?

再看你最初写的代码:

fun_rp = @(w) for i = 1:port_size
    for j = 1: port_size
        (w(1,i)*(C*w(1,i)')-w(1,j)*(C*w(1,j)'))^2;
    end
end

这段代码有两个致命问题:

  • MATLAB匿名函数不支持这种多行for循环的写法,匿名函数需要是一个单行表达式(强行拼接成单行的话可读性极差);
  • 循环里的表达式只计算了单个项,但没有把这些项累加起来,也没有返回结果,相当于这个函数没有输出值,MATLAB无法识别它为有效的目标函数。

内容的提问来源于stack exchange,提问作者Dirty Dan

火山引擎 最新活动