更新:相应解析器工具已写好,叫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
a≤A,b≤B,c≤C。
一般
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+yc≤3,∀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,上述所有过程(包括命令的多层嵌套)可编一个处理字符串的程序自动实现。
- 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 变形回来。其他说明略。
- 一些不可避免的 for 循环可用 C++ 实现再嵌入MATALB。参见其他人写的步骤。
后续
不知道是否有人编写过一个自动将 LATEX 描述的数学约束或其他式子转化为 MATLAB 中高效矩阵运算的字符串处理程序,希望能看见这样的项目或程序,或类似的方法。有不懂怎么向量化的约束欢迎在下面评论区留言(CVX相关的问题,也可以在CVX论坛寻求帮助。 博主在CVX论坛的用户名是jackfsuia。此篇的英文版在如何向量化大多数CVX约束。)。
* 纪念学生生涯的最后时光 却纵有 太多 、太多 的遗憾。