添加重复约束时 JuMP 求解器的行为

问题描述

让我们假设为了演示,我有以下不代表任何东西的模型,这只是一个例子:

using GLPK
using JuMP
m = Model(GLPK.Optimizer)
@variable(m,y[i=1:100],Bin)
@objective(m,Min,sum(y))
@constraint(m,[j=5:50],sum([y[i] for i in j:j+10]) >= 5)

现在

julia> num_constraints(m,GenericAffExpr{Float64,VariableRef},MOI.GreaterThan{Float64})
46

哪个好。然后,如下:

julia> @constraint(m,sum([y[i] for i in j:j+10]) >= 5)
[...]
julia> num_constraints(m,MOI.GreaterThan{Float64})
92

这意味着模型现在的约束数量增加了一倍,而所有约束都是重复的。这对我来说是有问题的,因为我有一个真实模型,其中我有更多约束,有时我会添加可能重复或可能不重复的约束。所有这些都在 for 和 while 循环中。所以我想知道是否:

  • 只是约束的数量翻了一番,但模型确切地知道他可以避免处理其中的一半?
  • 他是否仍然记住约束条件,在避免一半的情况下,仍然需要两倍的内存?
  • 如果是,有没有办法在添加之前检查一组约束是否已经存在?

“JuMP 求解器如何处理重复约束?”在某种程度上总结了这一点。

最后,我明白 num_constraints 函数返回所有用户输入的约束。如何获得唯一约束的数量

解决方法

JuMP 不区分唯一约束。它将添加您告诉它添加的每个约束。原因之一是可以在创建约束后对其进行修改。但是,如果您能证明冗余约束是导致显着减速的原因,我只会担心。如果是这样,我建议你重构你的代码,不要添加多余的约束。

回答您的问题:

只是约束的数量翻了一番,但模型确切地知道他可以避免处理其中的一半?

每个求解器的预求解都应删除冗余约束(但这需要时间)。

他是否仍然记住约束条件,并且在避免一半的情况下,仍然需要两倍的内存?

是的。它仍然需要两倍的内存。

如果是,有没有办法在添加之前检查一组约束是否已经存在?

没有检查是否已添加约束的功能。