【问题标题】:Retrieving multiple optimal solutions with Pulp使用 Pulp 检索多个最优解
【发布时间】:2019-03-10 15:39:48
【问题描述】:

我有兴趣使用 Pulp 获得多个最优解决方案(如果存在)。那里的许多文献让我相信编程包不可能做到这一点,但我确实找到了this promising example

这里是代码

"""
The Looping Sudoku Problem Formulation for the PuLP Modeller

Authors: Antony Phillips, Dr Stuart Mitcehll
"""
# Import PuLP modeler functions
from pulp import *

# A list of strings from "1" to "9" is created
Sequence = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]

# The Vals, Rows and Cols sequences all follow this form
Vals = Sequence
Rows = Sequence
Cols = Sequence

# The boxes list is created, with the row and column index of each square in 
# each box
Boxes =[]
for i in range(3):
    for j in range(3):
        Boxes += [[(Rows[3*i+k],Cols[3*j+l]) for k in range(3) for l in range(3)]]

# The prob variable is created to contain the problem data
prob = LpProblem("Sudoku Problem",LpMinimize)

# The problem variables are created
choices = LpVariable.dicts("Choice",(Vals,Rows,Cols),0,1,LpInteger)

# The arbitrary objective function is added
prob += 0, "Arbitrary Objective Function"

# A constraint ensuring that only one value can be in each square is created
for r in Rows:
    for c in Cols:
        prob += lpSum([choices[v][r][c] for v in Vals]) == 1, ""

# The row, column and box constraints are added for each value
for v in Vals:
    for r in Rows:
        prob += lpSum([choices[v][r][c] for c in Cols]) == 1,""

    for c in Cols:
        prob += lpSum([choices[v][r][c] for r in Rows]) == 1,""

    for b in Boxes:
        prob += lpSum([choices[v][r][c] for (r,c) in b]) == 1,""

# The starting numbers are entered as constraints
prob += choices["5"]["1"]["1"] == 1,""
prob += choices["6"]["2"]["1"] == 1,""
prob += choices["8"]["4"]["1"] == 1,""
prob += choices["4"]["5"]["1"] == 1,""
prob += choices["7"]["6"]["1"] == 1,""
prob += choices["3"]["1"]["2"] == 1,""
prob += choices["9"]["3"]["2"] == 1,""
prob += choices["6"]["7"]["2"] == 1,""
prob += choices["8"]["3"]["3"] == 1,""
prob += choices["1"]["2"]["4"] == 1,""
prob += choices["8"]["5"]["4"] == 1,""
prob += choices["4"]["8"]["4"] == 1,""
prob += choices["7"]["1"]["5"] == 1,""
prob += choices["9"]["2"]["5"] == 1,""
prob += choices["6"]["4"]["5"] == 1,""
prob += choices["2"]["6"]["5"] == 1,""
prob += choices["1"]["8"]["5"] == 1,""
prob += choices["8"]["9"]["5"] == 1,""
prob += choices["5"]["2"]["6"] == 1,""
prob += choices["3"]["5"]["6"] == 1,""
prob += choices["9"]["8"]["6"] == 1,""
prob += choices["2"]["7"]["7"] == 1,""
prob += choices["6"]["3"]["8"] == 1,""
prob += choices["8"]["7"]["8"] == 1,""
prob += choices["7"]["9"]["8"] == 1,""
prob += choices["3"]["4"]["9"] == 1,""
prob += choices["1"]["5"]["9"] == 1,""
prob += choices["6"]["6"]["9"] == 1,""
prob += choices["5"]["8"]["9"] == 1,""

# The problem data is written to an .lp file
prob.writeLP("Sudoku.lp")

# A file called sudokuout.txt is created/overwritten for writing to
sudokuout = open('sudokuout.txt','w')

while True:
    prob.solve()
    # The status of the solution is printed to the screen
    print("Status:", LpStatus[prob.status])
    # The solution is printed if it was deemed "optimal" i.e met the constraints
    if LpStatus[prob.status] == "Optimal":
        # The solution is written to the sudokuout.txt file
        for r in Rows:
            if r == "1" or r == "4" or r == "7":
                sudokuout.write("+-------+-------+-------+\n")
            for c in Cols:
                for v in Vals:
                    if value(choices[v][r][c])==1:
                        if c == "1" or c == "4" or c =="7":
                            sudokuout.write("| ")
                        sudokuout.write(v + " ")
                        if c == "9":
                            sudokuout.write("|\n")
        sudokuout.write("+-------+-------+-------+\n\n")
        # The constraint is added that the same solution cannot be returned again
        prob += lpSum([choices[v][r][c] for v in Vals
                                    for r in Rows
                                    for c in Cols
                                    if value(choices[v][r][c])==1]) <= 80
    # If a new optimal solution cannot be found, we end the program
    else:
        break
sudokuout.close()

# The location of the solutions is give to the user
print("Solutions Written to sudokuout.txt")

我最感兴趣的代码在这里

prob += lpSum([choices[v][r][c] for v in Vals
                                    for r in Rows
                                    for c in Cols
                                    if value(choices[v][r][c])==1]) <= 80

我的问题是,对于所有最佳解决方案,我认为带有 1 的所有平方和将是 81。那么为什么不使用&lt;= 81 呢?另外,我不确定为什么在连续迭代求解后添加这个约束会产生不同的最优解,如果它们确实存在的话。谁能解释一下?

【问题讨论】:

  • 你最后是怎么解决的?

标签: python linear-programming pulp


【解决方案1】:

这种迭代只能用于纯二进制整数程序。

该约束将使当前的最优解不可行,因为其变量的总和将达到 81

那么约束&lt;=80 将使该解决方案不可行,并且下一轮循环将不得不寻找另一个解决方案。

【讨论】:

  • 好的。感谢您的回复。我觉得我懂了。那么您是说它找到的第二个解决方案实际上不是最佳的(而是第二个最佳解决方案)?另外,有没有办法为实值解决方案(不是纯二进制整数问题)做这样的把戏?我在类似问题中遇到的是许多目标函数评估为零的最优解决方案。
  • 第二个解可能仍然是最优的(如果有多个最优解),否则它是次优的。我建议您为您的问题添加一些其他“目标”,即对解决方案变量进行排序并将其用作次要目标)
  • 我会接受这个答案,因为我认为它可能是正确的。但我将发布一个关于我的具体问题的新问题,希望它有助于澄清我想要完成的工作。我希望你能看到它,因为我怀疑这里的其他人是否有资格解决这个问题。感谢您迄今为止的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-17
  • 1970-01-01
  • 1970-01-01
  • 2020-10-29
  • 2021-06-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多