Pulp 在 options/types 不能相同的地方添加新约束?
Pulp add new constraint where options/types cannot be the same?
下面的代码允许我根据允许的预算 (max_cost) 和选择 (max_to_pick) 优化利润。如何在无法选择同一个城市的情况下添加新约束。
from pulp import *
# PROBLEM DATA:
costs = [15, 25, 35, 40, 45, 55]
profits = [1.7, 2, 2.4, 3.2, 5.6, 6.2]
# city = ["NYC","SF","LA","SF","NYC","LA"] NEW CONSTRAINTS
max_cost = 200
max_to_pick = 4
# DECLARE PROBLEM OBJECT:
prob = LpProblem("Mixed Problem", LpMaximize)
# VARIABLES
n = len(costs)
N = range(n)
x = LpVariable.dicts('x', N, cat="Binary")
# OBJECTIVE
prob += lpSum([profits[i]*x[i] for i in N])
# CONSTRAINTS
prob += lpSum([x[i] for i in N]) <= max_to_pick # Limit number to include
prob += lpSum([x[i]*costs[i] for i in N]) <= max_cost # Limit max. cost
# SOLVE & PRINT RESULTS
prob.solve()
print(LpStatus[prob.status])
print('Profit = ' + str(value(prob.objective)))
print('Cost = ' + str(sum([x[i].varValue*costs[i] for i in N])))
for v in prob.variables ():
print (v.name, "=", v.varValue)
非常感谢!
假设您要限制选择,使列表 city
中的城市最多包含一次,然后按如下方式添加约束即可。它设置了一个约束,使得分配给每个城市的 x
个决策变量的总和最多为 1。
可能有更 pythonic 的方法来创建列表索引。您可以按如下方式在一行中创建所有这些,但我发现它更难遵循:
list_of_lists_of_indices = [[i for i in N if city[i] == c] for c in set(city)]
from pulp import *
# PROBLEM DATA:
costs = [15, 25, 35, 40, 45, 55]
profits = [1.7, 2, 2.4, 3.2, 5.6, 6.2]
city = ["NYC","SF","LA","SF","NYC","LA"] # NEW CONSTRAINTS
max_cost = 200
max_to_pick = 4
# DECLARE PROBLEM OBJECT:
prob = LpProblem("Mixed Problem", LpMaximize)
# VARIABLES
n = len(costs)
N = range(n)
x = LpVariable.dicts('x', N, cat="Binary")
# OBJECTIVE
prob += lpSum([profits[i]*x[i] for i in N])
# CONSTRAINTS
prob += lpSum([x[i] for i in N]) <= max_to_pick # Limit number to include
prob += lpSum([x[i]*costs[i] for i in N]) <= max_cost # Limit max. cost
# NEW CONSTRAINT
for c in set(city):
index_list = [i for i in N if city[i] == c]
prob += lpSum([x[i] for i in index_list]) <= 1
# SOLVE & PRINT RESULTS
prob.solve()
print(LpStatus[prob.status])
print('Profit = ' + str(value(prob.objective)))
print('Cost = ' + str(sum([x[i].varValue*costs[i] for i in N])))
for v in prob.variables ():
print (v.name, "=", v.varValue)
您可能会发现下面的代码更容易理解,因为它不依赖于索引和索引列表。
此方法的关键在于您可以将对象用作字典键。
因此变量字典(此处为 x)由 Facility 对象 LPVariable 的键值对组成。
from pulp import *
class Facility():
def __init__(self, cost, profit, city):
self.cost = cost
self.profit = profit
self.city = city
def __str__(self):
return f"Facility(city={self.city}, profit={self.profit}, cost={self.cost})"
# PROBLEM DATA:
max_cost = 200
max_to_pick = 4
costs = [15, 25, 35, 40, 45, 55]
profits = [1.7, 2, 2.4, 3.2, 5.6, 6.2]
cities = ["NYC","SF","LA","SF","NYC","LA"]
facilities = [Facility(cost, profit, city) for cost, profit, city in
zip(costs, profits, cities)]
# DECLARE PROBLEM OBJECT:
prob = LpProblem("Mixed Problem", LpMaximize)
# VARIABLES
x = LpVariable.dicts('facility', facilities, cat="Binary")
# OBJECTIVE
prob += lpSum([facility.profit * x[facility] for facility in facilities])
# CONSTRAINTS
# number of facilities
prob += lpSum(x.values()) <= max_to_pick # Limit number to include
# maximum cost
prob += lpSum([facility.cost * x[facility] for facility in facilities]) <= max_cost
# no city more than once
# loop through unique city names
# add a constraint that the sum of matching facilities <= 1
unique_cities = set([facility.city for facility in facilities])
for city in unique_cities:
prob += lpSum([x[facility] for facility in facilities if facility.city == city]) <= 1
# solve the problem
prob.solve()
# identify the chosen facilities
# object_variable_d swaps keys and values
# so you can find the Facility object from the LpVariable
# all of the LpVariables are unique, so this should work
object_variable_d = {v: k for k, v in x.items()}
chosen_facilities = [object_variable_d[var]
for var in prob.variables()
if var.value() == 1]
# print out results
print(LpStatus[prob.status])
print(f'Profit = {value(prob.objective)}')
print(f'Cost = {sum([facility.cost for facility in chosen_facilities])}')
for facility in chosen_facilities:
print(facility)
下面的代码允许我根据允许的预算 (max_cost) 和选择 (max_to_pick) 优化利润。如何在无法选择同一个城市的情况下添加新约束。
from pulp import *
# PROBLEM DATA:
costs = [15, 25, 35, 40, 45, 55]
profits = [1.7, 2, 2.4, 3.2, 5.6, 6.2]
# city = ["NYC","SF","LA","SF","NYC","LA"] NEW CONSTRAINTS
max_cost = 200
max_to_pick = 4
# DECLARE PROBLEM OBJECT:
prob = LpProblem("Mixed Problem", LpMaximize)
# VARIABLES
n = len(costs)
N = range(n)
x = LpVariable.dicts('x', N, cat="Binary")
# OBJECTIVE
prob += lpSum([profits[i]*x[i] for i in N])
# CONSTRAINTS
prob += lpSum([x[i] for i in N]) <= max_to_pick # Limit number to include
prob += lpSum([x[i]*costs[i] for i in N]) <= max_cost # Limit max. cost
# SOLVE & PRINT RESULTS
prob.solve()
print(LpStatus[prob.status])
print('Profit = ' + str(value(prob.objective)))
print('Cost = ' + str(sum([x[i].varValue*costs[i] for i in N])))
for v in prob.variables ():
print (v.name, "=", v.varValue)
非常感谢!
假设您要限制选择,使列表 city
中的城市最多包含一次,然后按如下方式添加约束即可。它设置了一个约束,使得分配给每个城市的 x
个决策变量的总和最多为 1。
可能有更 pythonic 的方法来创建列表索引。您可以按如下方式在一行中创建所有这些,但我发现它更难遵循:
list_of_lists_of_indices = [[i for i in N if city[i] == c] for c in set(city)]
from pulp import *
# PROBLEM DATA:
costs = [15, 25, 35, 40, 45, 55]
profits = [1.7, 2, 2.4, 3.2, 5.6, 6.2]
city = ["NYC","SF","LA","SF","NYC","LA"] # NEW CONSTRAINTS
max_cost = 200
max_to_pick = 4
# DECLARE PROBLEM OBJECT:
prob = LpProblem("Mixed Problem", LpMaximize)
# VARIABLES
n = len(costs)
N = range(n)
x = LpVariable.dicts('x', N, cat="Binary")
# OBJECTIVE
prob += lpSum([profits[i]*x[i] for i in N])
# CONSTRAINTS
prob += lpSum([x[i] for i in N]) <= max_to_pick # Limit number to include
prob += lpSum([x[i]*costs[i] for i in N]) <= max_cost # Limit max. cost
# NEW CONSTRAINT
for c in set(city):
index_list = [i for i in N if city[i] == c]
prob += lpSum([x[i] for i in index_list]) <= 1
# SOLVE & PRINT RESULTS
prob.solve()
print(LpStatus[prob.status])
print('Profit = ' + str(value(prob.objective)))
print('Cost = ' + str(sum([x[i].varValue*costs[i] for i in N])))
for v in prob.variables ():
print (v.name, "=", v.varValue)
您可能会发现下面的代码更容易理解,因为它不依赖于索引和索引列表。
此方法的关键在于您可以将对象用作字典键。
因此变量字典(此处为 x)由 Facility 对象 LPVariable 的键值对组成。
from pulp import *
class Facility():
def __init__(self, cost, profit, city):
self.cost = cost
self.profit = profit
self.city = city
def __str__(self):
return f"Facility(city={self.city}, profit={self.profit}, cost={self.cost})"
# PROBLEM DATA:
max_cost = 200
max_to_pick = 4
costs = [15, 25, 35, 40, 45, 55]
profits = [1.7, 2, 2.4, 3.2, 5.6, 6.2]
cities = ["NYC","SF","LA","SF","NYC","LA"]
facilities = [Facility(cost, profit, city) for cost, profit, city in
zip(costs, profits, cities)]
# DECLARE PROBLEM OBJECT:
prob = LpProblem("Mixed Problem", LpMaximize)
# VARIABLES
x = LpVariable.dicts('facility', facilities, cat="Binary")
# OBJECTIVE
prob += lpSum([facility.profit * x[facility] for facility in facilities])
# CONSTRAINTS
# number of facilities
prob += lpSum(x.values()) <= max_to_pick # Limit number to include
# maximum cost
prob += lpSum([facility.cost * x[facility] for facility in facilities]) <= max_cost
# no city more than once
# loop through unique city names
# add a constraint that the sum of matching facilities <= 1
unique_cities = set([facility.city for facility in facilities])
for city in unique_cities:
prob += lpSum([x[facility] for facility in facilities if facility.city == city]) <= 1
# solve the problem
prob.solve()
# identify the chosen facilities
# object_variable_d swaps keys and values
# so you can find the Facility object from the LpVariable
# all of the LpVariables are unique, so this should work
object_variable_d = {v: k for k, v in x.items()}
chosen_facilities = [object_variable_d[var]
for var in prob.variables()
if var.value() == 1]
# print out results
print(LpStatus[prob.status])
print(f'Profit = {value(prob.objective)}')
print(f'Cost = {sum([facility.cost for facility in chosen_facilities])}')
for facility in chosen_facilities:
print(facility)