使用 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
我一直在研究和学习一般的优化,尤其是 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