"KeyError: (0, 'num')" when using List Comprehension to create PuLP LPConstraint

"KeyError: (0, 'num')" when using List Comprehension to create PuLP LPConstraint

我认为我为优化创建的是一个相当简单的问题。我在 csv 文件中有以下数据:

我正在尝试使用 PuLP 包创建“最佳”骑行日,但在创建我的约束之一时不断出现错误。约束简单概括为:每次骑行的时间(#次骑行*骑行时间,加上#次骑行*等待时间),加上两次骑行之间的15分钟,必须等于或小于公园开放时间(减去固定的用餐和洗手间时间)

当我 运行 约束行时,我不断收到 KeyError: (0, 'num') 。 (我可以毫无问题地打印 ride_list.loc[0,'num'] - 解决问题的第一步。)任何提示或想法将不胜感激。

import pandas as pd
import pulp

ride_list = pd.read_csv('RideData.csv')
num_rides = ride_list.shape[0]
rides = list(range(num_rides))
min_times = 0 #minimum # times for each ride
max_times = 2 #maximum # times for each ride
time_between = 0.25 #how long to allow between rides
food_time = 2.5 #how long to allow for meals
hours_open = 12 #how many hours the park is open

# Set default values for testing
for i in rides:
    ride_list.loc[i, 'my_min'] = min_times
    ride_list.loc[i, 'my_max'] = max_times
    ride_list.loc[i, 'my_rating'] = ride_list.loc[i, 'rating']
    ride_list.loc[i, 'num'] = 0

# Initialize model
model = pulp.LpProblem('Maximimize ride enjoyment', pulp.LpMaximize)

# Add calculation to be optimized
model += pulp.lpSum([ride_list.loc[i,'ride'] * ride_list.loc[i,'rating'] * ride_list.loc[i,'num'] for i in rides])

# Add constraint to # times for each ride
x = pulp.LpVariable.dicts("times",[ride_list.loc[i, 'num'] for i in rides], 
                          lowBound = min_times,
                          upBound = max_times,
                          cat = 'Integer')

# Add constraint for total amount of time
total_rides = pulp.lpSum([ride_list[i,'num'] for i in rides])
model += pulp.LpConstraint('total_ride_time',
                          (pulp.lpSum([((ride_list.loc[i,'wait'] * ride_list.loc[i,'num']) + 
                          (ride_list.loc[i,'ride'] * ride_list.loc[i,'num'])) for i in rides]) + 
                          ((total_rides - 1) * time_between)) <= 
                          (hours_open - food_time))

所以您在索引方面遇到的问题是由于您没有在 pulp 中正确构造变量。当您这样做时:

x = pulp.LpVariable.dicts("times",[ride_list.loc[i, 'num'] for i in rides], ...

您正在传递数据框 values 的列表,这是不正确的。该调用应为要创建的变量提供键集,在本例中为 x,逻辑索引只是骑行次数的计数。在你的例子中,你提供了一个包含 3 个零的列表,因为你已经用这些值填充了 df。这会折叠成一个其中有一个零的集合。请参阅下面的示例。此外,在你剩下的努力中,你没有使用你创建的变量......??您正在使用 ride_list.loc[i,'num'] 这只是数据框中的一些固定值, 而不是 问题中的变量。

这里是一个示例,展示了构建变量等的更好方法。请注意打印 x [格式不正确] 和 y 的输出结果。还要注意在名义约束中创建的变量的用法。

import pulp
import pandas as pd

data = { 'wait':        [1, 5, 10],
         'ride_time':   [2, 6, 8],
         'num' :        [0, 0, 0]}

df = pd.DataFrame(data)
print (df)

model = pulp.LpProblem("ride_plan", pulp.LpMaximize)
x = pulp.LpVariable.dicts("rides", [df.loc[i, 'num'] for i in range(len(df))])  # <-- bad
print(x)

y = pulp.LpVariable.dicts("rides", range(len(df)), cat="Integer")
print(y)

# example constraint for notional max wait time of 15 minutes...
model += pulp.LpConstraint(pulp.lpSum(df.loc[i, 'wait'] * y[i] for i in range(len(df)))) <= 15

print(model)

产量:

   wait  ride_time  num
0     1          2    0
1     5          6    0
2    10          8    0

{0: rides_0}    # <--- x
{0: rides_0, 1: rides_1, 2: rides_2}   # <--- y

ride_plan:
MAXIMIZE
None
SUBJECT TO
_C1: rides_0 + 5 rides_1 + 10 rides_2 <= 15

VARIABLES
rides_0 free Integer
rides_1 free Integer
rides_2 free Integer

[Finished in 220ms]