【问题标题】:Python CPLEX API: Conditional iteration on binary variablesPython CPLEX API:二进制变量的条件迭代
【发布时间】:2020-04-22 10:36:36
【问题描述】:

我正在研究一个图论问题。假设我们想找到一个图 G=(V,E),使得存在一个 V 的分区 X,最多包含 k 个等价类。当 S 是分区 X 的成员时,变量 p_S 的值为 1,否则为零。所以我们有一个约束,对于 V 的所有子集 S,所有变量 p_S 的总和最多为 k。

所以我想要做的是遍历所有值为 1 的 p_S,并根据我从 S 中提取的元素定义更多约束。这些约束将保留等价类的成员共享一些相互属性。

是否可以通过这种方式访问​​ p_S 变量?我该怎么做?

另外,如果我被允许在我的约束中使用二进制变量作为系数,我知道我可以不用迭代我的二进制变量。这可能吗?

提前致谢!

【问题讨论】:

  • 一般来说,你需要线性化它。是的,if I'm allowed to use binary variables as coefficients in my constraints 是这背后的基本概念,但一般来说,您不能两个变量,这意味着您需要线性化这些产品(二进制 * 二进制、二进制 * 整数、二进制* 续)(通过附加变量和约束)。对于这些线性化中的每一个,都需要不同的方法和假设(例如先验界限)!由于这非常依赖于模型(我们不知道),因此无需多说。
  • 感谢您的回复。我不明白线性化的概念,你能提供一个 case binary* binary 的例子吗?它不必与我的模型相关。
  • B/B, B/C
  • @sascha 这些都是很好的例子,谢谢!如果你从你的回复中做出正式的回答,我会接受。
  • 因此线性化二进制变量的乘积涉及制定约束,其中包含右侧的决策变量。我刚刚意识到,在 Python CPLEX API 中,右手边必须是实数。那么我该如何完成这项工作呢?

标签: python iteration graph-theory mathematical-optimization cplex


【解决方案1】:

CPLEX Python API 是基于索引的。要迭代解决方案值设置为 1 的所有二进制变量,我们需要查询变量类型和解决方案值并进行相应的过滤。这是一个简单的例子:

import sys
import cplex


def main(modelfile):
    # Read in a model file.
    c = cplex.Cplex()
    c.read(modelfile)

    # Solve the model and print the solution and status.
    c.solve()
    print("Solution value:", c.solution.get_objective_value())
    print("Solution status: {0} ({1})".format(
        c.solution.get_status_string(),
        c.solution.get_status()))

    # Display all binary variables that have a solution value of 1.
    types = c.variables.get_types()
    nvars = c.variables.get_num()
    binvars = [idx for idx, typ
               in zip(range(nvars), c.variables.get_types())
               if typ == c.variables.type.binary]
    inttol = c.parameters.mip.tolerances.integrality.get()
    binvars_at_one = [idx for idx, val
                      in zip(binvars, c.solution.get_values(binvars))
                      if abs(val - 1.0) <= inttol]
    print("Binary variables with a solution value equal to one:")
    for varname in c.variables.get_names(binvars_at_one):
        print("  ", varname)


if __name__ == "__main__":
    if len(sys.argv) != 2:
        raise ValueError("usage: {0} <model>".format(sys.argv[0]))
    main(sys.argv[1])

有关更多信息,请参阅 Cplex.variablesCplex.solution 的文档。

【讨论】:

  • 感谢您的努力。您的回答让我意识到我提出问题的方式首先没有意义,因为在解决优化问题之前需要有解决方案值,以便有条件地基于它们定义更多约束。所以我会像 sascha 指出的那样坚持线性化。
  • 没问题。但是,求解原始模型、添加更多约束并在循环中再次求解直到达到某个所需状态的情况并不少见。默认情况下,CPLEX 将保留来自先前求解的求解信息,并将其用作后续求解的起始信息。我以为你正在考虑做类似的事情。
  • 这很有趣!我不知道那件事。我想这实际上是我提出的问题的正确答案,所以我会接受这个。
【解决方案2】:

线性化示例:

from docplex.mp.model import Model

mdl = Model(name='binaryproduct')

x = mdl.binary_var(name='x')
y = mdl.binary_var(name='y')

z = mdl.binary_var(name='z')
# z==x*y
mdl.add_constraint(x+y<=1+z, 'ct1')
mdl.add_constraint(z<=x, 'ct2')
mdl.add_constraint(z<=y, 'ct3')
#end of z==x*y

mdl.solve()



for v in mdl.iter_binary_vars():
    print(v," = ",v.solution_value)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多