【问题标题】:Returning output of linprog in Matlab as a sparse vector在 Matlab 中将 linprog 的输出作为稀疏向量返回
【发布时间】:2018-04-09 15:08:06
【问题描述】:

我在 Matlab 中使用 mu=linprog(f,A,b, Aeq, beq),将 A,b, Aeq, beq 作为稀疏矩阵传递,因为它们很大,例如,A 具有维度 2000 x 2000

Matlab 没有给我任何内存错误,但运行线性编程需要很长时间(正如预期的那样,考虑到大尺寸)。

我注意到的一件事是,尽管我将 A,b, Aeq, beq 作为稀疏传递,但输出 mu 以非稀疏形式返回。将mu 作为稀疏向量返回是否有助于节省一些时间(和内存)?为什么linprog 不这样做?我如何修改linprog 来强制这样做?


这是我的具体示例(您可以通过约束看到mu 的每个元素是01mu 是稀疏的)

n_m=10;
n_w=15;
C=n_m*n_w+n_m+n_w;

%Inequalities A*mu<=b
b=sparse(C,1);
i=1:1:C;
v1=-ones(1,C);
A=sparse(i,i,v1,C,C);


%Equalities Aeq*mu=beq

row1=kron(1:1:n_m, ones(1,n_w+1)); 
temp=zeros(n_w+1, n_m);
for i=1:n_m
    temp(:,i)=(i:n_m:n_m*n_w+i).'; 
end
column1=temp(:).'; 
v1=ones(1,n_m*n_w+n_m);
Aeqmen=sparse(row1, column1, v1, n_m, C); 


row2=kron(1:1:n_w, ones(1,n_m+1)); 
temp=zeros(n_m+1,n_w);
for j=1:n_w
    temp(:,j)=[(j-1)*n_m+1:j*n_m n_m*n_w+n_m+j].';
end
column2=temp(:).'; 
v2=ones(1,n_m*n_w+n_w);
Aeqwomen=sparse(row2, column2, v2, n_w, C); 

Aeq=[Aeqmen; Aeqwomen]; 
beq=ones(n_m+n_w,1); 

%Objective function
f=-(randn(n_m*n_w+n_m+n_w,1));  %Cx1

%LP
mu= linprog(f,A,b, Aeq, beq); %Cx1

编辑 感谢下面的一些 cmets/answers,我发现,对于我的具体示例intlinproglinprog 快得多。这可以通过运行这个例子来看到:

clear
N=100:100:500;
mu1=cell(size(N,2),1);
mu2=cell(size(N,2),1);
rng default

for n=1:size(N,2)
n_m=N(n);
n_w=N(n);
C=n_m*n_w+n_m+n_w;

%Inequalities A*mu<=b
b=zeros(C,1);
i=1:1:C;
v1=-ones(1,C);
A=sparse(i,i,v1,C,C);


%Equalities Aeq*mu=beq
row1=kron(1:1:n_m, ones(1,n_w+1)); 
temp=zeros(n_w+1, n_m);
for i=1:n_m
    temp(:,i)=(i:n_m:n_m*n_w+i).'; 
end
column1=temp(:).'; 
v1=ones(1,n_m*n_w+n_m);
Aeqmen=sparse(row1, column1, v1, n_m, C); 

row2=kron(1:1:n_w, ones(1,n_m+1)); 
temp=zeros(n_m+1,n_w);
for j=1:n_w
    temp(:,j)=[(j-1)*n_m+1:j*n_m n_m*n_w+n_m+j].';
end
column2=temp(:).'; 
v2=ones(1,n_m*n_w+n_w);
Aeqwomen=sparse(row2, column2, v2, n_w, C); 

Aeq=[Aeqmen; Aeqwomen]; 
beq=ones(n_m+n_w,1); 

%Objective function
f=-(randn(n_m*n_w+n_m+n_w,1));  %Cx1

%Intcon
intcon=1:1:C; 

tic
mu1{n}= linprog(f,A,b, Aeq, beq); %Cx1
toc
tic
mu2{n}= intlinprog(f,intcon,A,b, Aeq, beq); %Cx1
toc
end

【问题讨论】:

  • 稀疏矩阵可以节省大量空间(和时间)。稀疏向量没有那么多。我不会打扰。
  • 谢谢,但是对于大的C(在我的例子中Cmu 的维度),Matlab 甚至不允许存储mu,除非它是稀疏的。
  • 我不明白。如果A = 2000 x 2000(顺便说一句,它很小——现在我们解决了数百万行和列的问题),那么 mu 是一个长度为 2000 的向量。一点也不大..
  • linprog 不是一个好的 LP 求解器。我认为稀疏不是问题。 linprog 的实现是。如果你环顾四周,你会发现类似的(也许更好的)免费求解器。例如,检查 CLP 或 GLPK。如果您有学术隶属关系,请务必使用 Gurobi 或 CPLEX,它们可免费用于学术用途。他们应该有一个 MATLAB 接口。更好的做法是同时避免使用 MATLAB,但这是另一回事。
  • 我认为我从未见过 MIP 比 LP 快(而且我这样做了很长时间)。

标签: matlab linear-programming


【解决方案1】:

具有稀疏矩阵的方程组(Ax=b 或变体)的结果不需要(在绝大多数情况下也不需要)稀疏。

例如

  • 有限元方法(系统矩阵是稀疏的,但 基础物理结果一般不会)
  • 大多数类型的断层扫描

【讨论】:

  • 谢谢。就我而言,输出是稀疏的。我添加了一个例子。谢谢你。有什么简单的方法可以修改linprog 函数以获得稀疏输出?
  • @user3285148 仍然不能确保它是,这取决于数值结果。它恰好是稀疏的
  • @user3285148 出于某种原因哼了一声。
【解决方案2】:

虽然在线性规划公式中,等式和不等式约束通常是稀疏的,但这并不一定意味着得到的解是稀疏的(事实上,除非约束特别需要,否则它通常不适用于 LP )。

如果整数约束将大量输出强制为零(例如,如果您有很多决策变量被限制为

函数linprog是Matlab提供的优化包中的一个函数,所以直接修改不太可能(这可能不是一个好主意)。

您可能想要检查您的结果以找出有多少输出正好为零 - 这将告诉您是否有稀疏解决方案甚至可以解决此问题:

% Total number of entries that are nonzero
nnz(D)
% Density of the matrix relative to total number of elements
nnz(D)/prod(size(D))

【讨论】:

  • nnz(D) 更好,然后您只需检查大小。一般来说,更好的方法是计算稀疏度:nnz(D)/prod(size(D))
  • 哇 - 使用 Matlab 20 年,从未遇到过 nnz。将更新答案以包括在内。
  • 感谢您的见解:(1)我认为我的LP可以重写为MIP(约束确保mu的每个元素都是01);我知道 intlinprog 在 Matlab 中,但似乎 bbeq 不能作为稀疏传递; (2) 在我的 LP 中,输出 mu 受约束稀疏(它最多可以有固定数量的依赖于 n_mn_w
  • 使用 MIP 代替 LP 来节省内存根本没有意义。我错过了什么吗?
  • 我并不提倡使用 MIP 作为一种节省内存的方法,只是说明 LP 和 MIP 之间的差异,并指出 LP 通常不会导致决策变量稀疏。
猜你喜欢
  • 2012-01-03
  • 1970-01-01
  • 2017-05-10
  • 1970-01-01
  • 2017-03-26
  • 2017-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多