如何在MATLAB中求解含双重求和的目标函数极小化问题
解决MATLAB fmincon中目标函数未定义的问题
你遇到的fun_rp是未定义函数或变量错误,核心原因是你定义匿名函数的方式不符合MATLAB的语法规则,而且目标函数的实现逻辑也有两处关键问题:
- MATLAB的匿名函数默认不支持直接写多行
for循环(除非用特殊的单行拼接语法,但可读性极差); - 你的循环代码没有对目标函数值进行累加,也没有返回计算结果,相当于这个函数没有输出。
下面给你两种可行的解决方案,推荐优先用第一种向量化实现(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




