MATLAB或CVX中的for循环避免

更新:相应解析器工具已写好,叫Vecpaser

    MATLAB 或 CVX (一种凸优化建模工具)中用 for 循环初始化或者表达变量约束,会导致程序运行时间大大增加。因此可尝试用以下 2 或 3 种操作组合将 for 循环写为矩阵运算(即向量化,vectorize):

命令作用
repmat增加变量(矩阵)的维度
permute置换变量(矩阵)的维度
reshape修改变量(矩阵)的形状

示例

⋆ \star 1. 表达形如 f ( x a b , y c ) ≤ 0 f({x_{ab}},{y_c}) \le 0 f(xab,yc)0 的约束。假设 a ≤ A , b ≤ B , c ≤ C a \le A,b \le B,c \le C aA,bB,cC
    一般 f f f 输出的是一个维度 A × B × C A \times B \times C A×B×C 的变量,那么 x a b x_{ab} xab y c {y_c} yc 都需要在运算前,用 repmat 进行增维。remat( x a b x_{ab} xab, 1, 1, C C C ) 可输出 x a b c x_{abc} xabc, 意思是前两维分别乘上1(不变), 增加一个长度为 C C C 的维度。同理用 remat( y c y_{c} yc, 1, A A A, B B B ) 可输出 y c a b y_{cab} ycab,但两者维度顺序并没有对齐,不能直接运算。所以需要用 permute( y c a b y_{cab} ycab, [2,3,1] ) 使得 y c a b y_{cab} ycab 变成 y a b c y_{abc} yabc 。2,3,1分别代表原来矩阵的第2,第3,第1个维度, [2,3,1] 是排列后的维度顺序。此时两个变量可以直接运算了。例如用 CVX 表达约束

x a b + y c ≤ 3 , ∀ a , b , c . {x_{ab}} + {y_c} \le 3,{\rm{ }}\forall a,b,c. xab+yc3,a,b,c.

共有以下2种表述方法。若不用上述方法,即直接表示为

% 注意x是AxB维矩阵,y是Cx1维矩阵
for a=1:A
	for b=1:B
		for c=1:C
			x(a,b)+y(c) <= 3 ;
		end
	end
end

用上述方法加速,则应表示为

repmat(x,1,1,C) + permute(repmat(y,1,A,B),[2,3,1]) <= 3;

后者优点是避免了三重 for 循环遍历,尤其当 A , B , C A,B,C A,B,C 较大时,极大节省了运行时间缺点是当运算较复杂时,会涉及多层的嵌套,代码可读性下降,不利于后续检查。另外,有极少量约束无法用此方法表达。
    而在实际中,运用类似思维,只要稍微注意输入维度和输出维度,基本上看似复杂的约束全都可以通过一层层这2个命令的嵌套表达。另外,求和是常见的降维操作,需要注意,MATLAB 中只有对矩阵的最后一维求和才会降维,例如 sum( x a b c x_{abc} xabc, 3) 会对 x a b c x_{abc} xabc 的第三维度进行求和,输出一个 A × B A \times B A×B 矩阵,而sum( x a b c x_{abc} xabc, 2) 会对 x a b c x_{abc} xabc 的第二维度求和,输出一个 A × 1 × C A \times 1 \times C A×1×C 矩阵。建议先将需要求和的维度置换到末尾,然后对最后一维求和即可。若经常使用CVX,上述所有过程(包括命令的多层嵌套)可编一个处理字符串的程序自动实现

  1. reshape 的使用。reshape 命令用于调整矩阵的形状,例如将 N × M × P N \times M \times P N×M×P 维矩阵调整为 N × M P N \times MP N×MP 维。有时候会用到。例如想对 N × M × P N \times M \times P N×M×P 矩阵 x n m p x_{nmp} xnmp N N N 个元素做线性变换,而线性变换的矩阵是二维的,所以可用 reshape 先将 x n m p x_{nmp} xnmp 调整为 N × M P N \times MP N×MP 维矩阵,再将线性变换矩阵与其相乘,最后再用 reshape 变形回来。其他说明略。
  2. 一些不可避免的 for 循环可用 C++ 实现再嵌入MATALB。参见其他人写的步骤。

后续

    不知道是否有人编写过一个自动将 LATEX 描述的数学约束或其他式子转化为 MATLAB 中高效矩阵运算的字符串处理程序,希望能看见这样的项目或程序,或类似的方法。有不懂怎么向量化的约束欢迎在下面评论区留言(CVX相关的问题,也可以在CVX论坛寻求帮助。 博主在CVX论坛的用户名是jackfsuia。此篇的英文版在如何向量化大多数CVX约束。)。

* 纪念学生生涯的最后时光 却纵有 太多 、太多 的遗憾。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值