使用 ortools 为 python 选择列表的最小值或最大值

Selecting min or max value of a list using ortools for python

我一直在研究和学习一般的优化,尤其是 ortools,我需要帮助来理解它是什么我在使用 ortools 的这个简单问题上做错了。

问题本身很简单(简单到 ortools 应该是矫枉过正),但请记住这只是为了学习基础知识:

如何select整数列表中的最小(和最大)整数?

这是我的代码。

# 1. A simple problem:
# Select the smallest number from a list of integers

from __future__ import print_function
from ortools.sat.python import cp_model

# Define data
cost_data = [
    5, 4, 3, 6, 9, 12, 5, 9, 12, 14
]
num_hours = len(cost_data)
hours = range(num_hours)

# Create model
model = cp_model.CpModel()

# Create variables
cost_vars = [] # Keep variables for costs
pick_vars = [] # Keep variables for picked items (later we add a constraint for only selecting one pick)
for i in hours:
    cost_vars.append(model.NewIntVar(0, 20, ''))
    pick_vars.append(model.NewBoolVar(''))

# Create constraints

# Only one pick
model.Add(sum(pick_vars) == 1)

for i in hours:
    model.Add(cost_vars[i] == cost_data[i]).OnlyEnforceIf(pick_vars[i])

# Set objective function
model.Minimize(sum(cost_vars)) # This works (returns 3)
# model.Maximize(sum(cost_vars)) # This doesnt work (returns 194 as objective value)

# Solve problem

solver = cp_model.CpSolver()
status = solver.Solve(model)

if status == cp_model.INFEASIBLE:
    print("INFEASIBLE")
elif status == cp_model.FEASIBLE:
    print("FEASIBLE")
elif status == cp_model.OPTIMAL:
    print("OPTIMAL")

print("ObjectiveValue()")
print(solver.ObjectiveValue())

这个例子在我使用 Minimize 函数时有效,但如果我用 Maximize 替换 Minimize,它会以某种方式 returns 194 作为 objective 值。

我做错了什么?

现在发生的事情是: 9*20+14 = 194

因为你告诉求解器 cost_var 只有在被选中时才等于你的成本,否则它可以是 0 到 20 之间的任何整数。

编辑: 您想要的逻辑是:

model.Add(cost_vars[i] == cost_data[i]).OnlyEnforceIf(pick_vars[i])
model.Add(cost_vars[i] == 0).OnlyEnforceIf(pick_vars[i].Not())

您还应该看看 AddMaxEquality 和 AddMinEquality