我正在计算约束线性最小二乘问题的解决方案如下:
lb = zeros(7,1);
ub = ones(7,1);
for i = 1:size(b,2)
x(:,i) = lsqlin(C,b(:,i),[],[],[],[],lb,ub);
end
其中C
为m x 7
,b
为m x n
。 n
非常大,导致计算时间缓慢。有没有办法加快这个过程,摆脱慢for
循环。我使用lsqlin
代替pinv
或\
,因为我需要将我的解决方案限制在0-1(lb
和ub
)的边界。< / p>
答案 0 :(得分:2)
for
循环不一定是任何缓慢的原因 - 你没有预先分配,lsqlin
可能在每次迭代时打印出很多东西。但是,您可以通过将C
矩阵转换为稀疏块对角矩阵C2
,使用n
个相同的块(see here)来加快速度。这一次解决了所有n
个问题。如果新的C2
不是稀疏的,那么您可能会使用更多的内存,并且计算可能需要比for
循环更长的时间。
n = size(b,2);
C2 = kron(speye(n),C);
b2 = b(:);
lb2 = repmat(lb,n,1); % or zeros(7*n,1);
ub2 = repmat(ub,n,1); % or ones(7*n,1);
opts = optimoptions(@lsqlin,'Algorithm','interior-point','Display','off');
x = lsqlin(C2,b2,[],[],[],[],lb2,ub2,[],opts);
使用optimoptions
,我specified the algorithm并将'Display'
设置为'off'
,以确保任何输出和警告都不会减慢计算速度。
在我的机器上,这比使用for
循环快6到10倍(具有适当的预分配和设置选项)。此方法假定具有C2
元素的稀疏m*n*7
矩阵可以适合内存。如果没有,基于for
循环的方法将是唯一的选择(除了编写您自己的lsqlin
专用版本或利用问题中的任何其他备用方法)。