MATLAB cvx错误汇总,cvx错误解决,cvx知识点总结,cvx编程技巧

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

近期在使用MATLAB cvx进行优化问题求解的过程中遇到了各种各样的问题,bug不断,明明看起来很合理的表达式却一再报错,最终经过一个多月的调试终于将优化问题求解了出来。
在调试期间,用到了很多方法,例如问题和约束条件的转化,非凸转化为近似凸,查阅资料,改变公式写法等等手段,本文记录一下编程过程中遇到的错误、bug,希望能够帮到有相同问题的秃友们。

如果是cvx初学者,想要掌握一般cvx语法和编程方法,可以看这篇文章:
MATLAB中CVX工具箱解决凸优化问题的基本知识——语法、变量声明、目标函数、约束条件、cvx编程错误及解决方法

CVX工具箱中有很多特定的,专有的函数,这些函数不仅能够简化表达式,还能够通过函数替换来解决很多报错问题,例如除法、取倒数、对数㏒函数等都有专门函数替代,下面这篇文章总结了cvx中常用的函数,阅读这篇文章一定会对你产生帮助!
MATLAB cvx工具箱中常用的替换函数汇总,解决表达式报错问题


cvx编程错误及解决方法汇总

错误1—无法从 cvx 转换为 double

报错提示:
无法从 cvx 转换为 double
在这里插入图片描述

错误原因:
如果变量声明是在cvx框架之外(cvx_begin-cvx_end之外),那么cvx运行过程中会产生数据从cvx类型存到double(外面是double的)的过程。必须要将中间变量在cvx表达式里面进行定义。
具体来说,cvx中的variable类型是其特有的数据类型,也就是你的优化变量是cvx类型,如果你想要让你的cvx优化变量和其他已定义好的double数据进行数学运算,就必须提前声明表达式类型的变量来接受这个操作。
解决方法:
例如:a是cvx之外的double类型,b是cvx中的variable变量,如果想要在cvx中实现ab,那么必须定义表达式expression类型的变量来接收ab的值。
错误代码:

 b = rand(3,2);   
 cvx_begin
    variable a;
    variable c;  %c为variable变量
    c = a * b;   %因为c是variable变量,所以进行该操作会出现错误
    minimize f(x)
    subject to
        a <= 10;
cvx_end

将上述代码中的variable c;修改为expression c;即可得到正确代码。

正确代码:

 b = rand(3,2);   
 cvx_begin
    variable a;
    expression c;  %c为variable变量
    c = a * b;   %因为c是variable变量,所以进行该操作会出现错误
    minimize f(x)
    subject to
        a <= 10;
cvx_end

知识点总结:cvx中variable和expression的区别
在CVX软件包中,Variable(变量)和Expression(表达式)是CVX变量声明中最基本的两种类型。

Variable是可以优化的变量,可以看做是一个容器,存储着优化过程中待求解的变量。在声明一个Variable时,需要指定其形状、是否为实数、是否为非负数等属性,这样可以方便地控制变量的取值范围和优化方法的选择。Variable在最优化问题中具有待求解的性质,它在CVX中被定义为待优化的对象。

Expression用来指定变量之间的约束关系,也可以理解为一个可以计算的数学表达式。Expression可以由variable和基本的算术操作、点乘、矩阵乘法、原子函数等运算通过组合得到,可以是定值或是与Variable相关的表达式。

Variable一般是问题中的未知量,需要被求解出来,而Expression通常是已知的、确定的。由于Expression不需要求解,所以CVX对其进行符号相关的运算和简化等,有助于提高数值计算的效率。也就是把Expression作为一个中间变量,最终cvx不会保存Expression的计算结果。

错误2—等号问题

报错提示:
This is often an indication that an equality constraint was written with one equals ‘=’ instead of two ‘==’. The model must be rewritten before cvx can proceed.

错误原因:
cvx中的variable变量不是允许人为赋值的,只有在最后得出结果才会被结果覆盖,使用等号对某一个变量进行赋值是不允许的,cvx会动态优化变量,不允许人为复制。

解决方法:
使用expression声明临时变量,expression变量是可以使用“=”的。

// 声明临时变量
cvx_begin

    variable a;   %优化变量,不可以赋值修改,可以用双等号==来写约束条件
    expression b;  %临时变量,可以用等号=来赋值修改
    minimize(f(x));
    subject to
       a == 0;  %约束条件,a必须等于零
       b = 10;  %给b赋值为10,优化结束后自动清除
 			
cvx_end  

错误3—{real affine} .* {invalid}

报错提示:
Disciplined convex programming error:
Cannot perform the operation: {real affine} .* {invalid}
不能进行下面操作:仿射*无效
在这里插入图片描述
错误原因:
变量中存在无效数据,例如正负无穷+Inf、-Inf,空数据NaN,或者是0。

解决方法:
查看那个变量中的数据是无效的,修改该变量的值,或者调整初始化参数,或者检查哪一步运算出现了无效数据,修改该语句,进而消除无效数据。

错误4—除法问题

报错提示:
点除运算出现错误,出错 ./ (line 29)
在这里插入图片描述
错误原因:
cvx中的除法很容易出现问题,有时候你认为很正常的除法操作,但是cvx中就是会出错,因此cvx中有专有的针对除法操作的函数,inv_pos()。

解决方法:
例如: x ./ y报错
用inv_pos(y)来代替y,上式修改为x * inv_pos(y)

 cvx_begin
    variable a;
    variable b;  %c为variable变量
    minimize (a * inv_pos(b))  %不要用a/b
    subject to
        a <= 10;
cvx_end

知识点总结:cvx中inv_pos函数
在CVX中,inv_pos(x)是一个原子函数,用于求一个正数x的倒数,即1/x。但是,在定义该函数的时候,需要加上一个前缀“inv_pos”来表示参数x必须是正数,否则会产生未定义的结果。

在优化问题中,经常需要对矩阵或向量的逆进行求解。但是,如果涉及到非正定或奇异矩阵,逆运算是无法进行的。因此,为了确保矩阵或向量是正定的,可以使用CVX中的inv_pos函数,它会自动判断变量的正定性并求解其逆。当变量不是正定的时候,inv_pos函数会返回inf(无穷大)或NaN(非数值)。

例如,在求解下面的凸优化问题的时候:

cvx_begin
    variable x
    minimize(inv_pos(x) - 1)
    subject to
        x >= 0.5;
cvx_end

上面这个问题要求求解一个变量x,使得1/x最小,且x要大于等于0.5。在这个例子中,因为我们使用了inv_pos函数,所以x必须是正数,否则会出现一个错误。最后,CVX将求解出一个正数x,使得1/x最小。

错误5—对数log问题

报错提示:
错误使用 cvx/log (line 64)
Disciplined convex programming error:
Illegal operation: log( {convex} ).
在这里插入图片描述
错误原因:
cvx中是不允许出现log函数中出现凸函数的,即log(凸)是非法的,cvx中有专门针对log运算的函数,即rel_entr

解决方法:
使用rel_entr表示log函数
rel_entr(x,y) = xlog(x/y)
当你知道了上述表达式表示的含义后,你可以将你的log表达式进行变形,然后使用多个rel_entr
函数的组合来表示的想要表达的式子。
例如:wlog(1+p/w),借助数学公式log(1/x)=-log(x),可得表达式:
wlog(1+p/w) = -rel_entr(w,w+p),注意负号

%想要计算log(1+1/x)
    a = rel_entr(x+1,x)+rel_entr(x,x+1);

知识点总结:cvx中rel_entr函数
在CVX中,rel_entr(x, y)是一个原子函数,表示 KL 散度的一部分,即 x log(x/y)。其中,x和y具有相同的尺寸和形状,元素之间进行逐项计算。

rel_entr函数的第一个参数 x 可以是任何非负实数或实数向量(或矩阵),而第二个参数 y 也是非负实数或实数向量(或矩阵),并且 y 中不能存在 0 的项。当 x 和 y 相等时,rel_entr(x, y)的值是 0。在CVX问题中,rel_entr(x, y)通常用在求解最大熵问题、信息论问题、对数几率回归等一些特殊问题。

代码示例:

cvx_begin
    variable x(n);
    maximize(sum(rel_entr(x, p)));
    subject to
        sum(x) == 1;
        x >= 0;
cvx_end

其中,x 是一个 n 维列向量,p 也是一个相同尺寸和形状的列向量,CVX会自动将所有元素之间的操作转换成相应的 KL散度公式。在这个例子中,CVX将每个 x(i) 和 p(i) 进行逐项相除,然后计算 KL 散度公式的一部分并相加,从而求解满足约束条件的最大化x的问题。

错误6—无效数据

报错提示:
Disciplined convex programming error:
Illegal operation: {invalid} + {convex}
在这里插入图片描述

错误原因:
无效数据与凸表达式相加,错误原因及处理方法与错误3类似,不再赘述。

错误7—非凸问题

报错提示:
Disciplined convex programming error:
Cannot perform the operation: {positive constant} ./ {real affine}
在这里插入图片描述

错误原因:
正实数除以仿射函数,很明显该表达式是一个非凸的,cvx作为一个凸优化工具箱是无法解决非凸问题的。

解决方法:
将表达式转化为凸表达式,重新转化约束条件或目标函数。不再使用cvx工具箱,使用其他求解优化问题的工具箱,例如Gurobi、CPLEX等。

总结

上面总结了几个cvx编程中常见的错误,能力有限,不一定能准确解决各位遇到的现实问题,cvx编程看起来简单,实际上水很深,希望大家不要放弃,掌握好编程技巧,一起进步,祝各位的论文仿真早日成功!

如果是cvx初学者,想要掌握一般cvx语法和编程方法,可以看这篇文章:
MATLAB中CVX工具箱解决凸优化问题的基本知识——语法、变量声明、目标函数、约束条件、cvx编程错误及解决方法

CVX工具箱中有很多特定的,专有的函数,这些函数不仅能够简化表达式,还能够通过函数替换来解决很多报错问题,例如除法、取倒数、对数㏒函数等都有专门函数替代,下面这篇文章总结了cvx中常用的函数,阅读这篇文章一定会对你产生帮助!
MATLAB cvx工具箱中常用的替换函数汇总,解决表达式报错问题

如果是对MATLAB基础操作,尤其是涉及到矩阵操作、逻辑运算、数组生成等方面不是很熟悉的,可以参考下面这篇文章:
MATLAB基础操作,矩阵乘法、数组矩阵索引、最大最小运算符、零矩阵/随机矩阵/单位矩阵的生成、log函数、Inf和NaN的含义,语句过长用连接符换行、逻辑运算符以及区别

如果程序调试成功需要画结果图,但是对MATLAB画图的基本知识和语法搞不清楚的,可以参考下面这篇文章:
MATLAB绘图必看,画图大全!MATLAB绘图基础操作大全—折线图、散点图、颜色样式、线条粗细汇总

猜你喜欢

转载自blog.csdn.net/qq_45296693/article/details/130860024