gpt4 book ai didi

python - 循环遍历字典键的元素而不是枚举所有元素

转载 作者:行者123 更新时间:2023-12-01 09:03:19 25 4
gpt4 key购买 nike

我正在使用 python 字典来定义数学模式的一些变量和参数。

数据框如下所示:

    Service Bill Weight Zone    Resi    UPS FedEx   USPS    DHL
1DEA 1 2 N 33.02 9999 9999 9999
2DAM 2 2 N 33.02 9999 9999 9999

我已经定义了一些输入和变量,如下所示:

cost = {}
for carrier in carriers:
for row in df.to_dict('records'):
key = (row['Service'], row['Bill Weight'],
row['Zone'],row['Resi'], carrier)
cost[key] = row[carrier]

services = df['Service'].unique().tolist()
weights = df['Bill Weight'].unique().tolist()
zones = df['Zone'].unique().tolist()
addresses = df['Resi'].unique().tolist()

我唯一有效的分配和成本组合应该是:

 ['1DEA',1,2,'N','UPS']
['1DEA',1,2,'N','FedEx']
['1DEA',1,2,'N','USPS']
['1DEA',1,2,'N','DHL']
['2DAM',2,2,'N','UPS']
['2DAM',2,2,'N','FedEx']
['2DAM',2,2,'N','USPS']
['2DAM',2,2,'N','DHL']

下面是 gurobi python 的内容,但我实际上只关心通过 python 构建循环而不是 gurobi 语法:

方法A:

assign = {}
for carrier in carriers:
for row in df.to_dict('records'):
key = (row['Service'], row['Bill Weight'],
row['Zone'],row['Resi'], carrier)
cost[key] = row[carrier]
obj = quicksum(cost[key]*assign[key] \
for key in assign)

现在,这可以很好地确保变量和参数仅从字典键生成,而不是服务、权重、区域和地址的所有可能组合。但当我有如下特定约束时,它就不起作用:

  m.addConstrs((assign['1DEA', w, z, r, 'UPS']+assign['1DEA', w, z, r, 'USPS']+assign['1DEA', w, z, r, 'USPS 1C']==1\
for i in clients for s in services for w in weights for z in zones for r in addresses),"C02")

方法 2:

  assign = m.addVars(services, weights, zones, addresses, carriers, name = "Assign", vtype=GRB.BINARY)
obj = quicksum(cost[s, w, z, r, l]*assign[ s, w, z, r, l] \
for s in services for w in weights for z in zones for r in addresses for l in carriers)

这样我可以轻松地编写所有约束,但它会创建服务、权重、区域、地址、运营商的所有组合,这使我的模型错误。例如 ['2DAM',1,2,'N','UPS'] 不是有效的组合。

有没有办法将服务、权重、区域、地址、运营商的循环限制为仅在成本字典键中定义的组合?

最佳答案

由于您已经将数据存储在 pandas 数据框中,因此您可以使用其功能来创建变量和约束。创建包含决策变量的列,然后使用“groupby”和 grb.quicksum 定义约束。

首先,更多Python风格的列名称

df.columns = ['service', 'bill_weight', 'zone', 'resi', 'UPS', 'FedEx', 'USPS', 'DHL']

然后,将数据框 reshape 为方便的形式。

df1 = (df.set_index(['service', 'bill_weight', 'zone', 'resi']).
rename_axis('carrier', axis=1).stack().to_frame('cost'))

新的数据框每个变量将有一行。

                                          cost
service bill_weight zone resi carrier
1DEA 1 2 N UPS 33.02
FedEx 9999.00
USPS 9999.00
DHL 9999.00
2DAM 2 2 N UPS 33.02
FedEx 9999.00
USPS 9999.00
DHL 9999.00

您可以创建变量(并将它们添加到目标中。

df1['assign'] = [m.addVar(name=".".join(map(str, row.Index), 
obj=row.cost, vtype='B')
for row in df1.itertuples()]
m.update()

现在框架将包含决策变量。

                                          cost                         assign
service bill_weight zone resi carrier
1DEA 1 2 N UPS 33.02 <gurobi.Var 1DEA.1.2.N.UPS>
FedEx 9999.00 <gurobi.Var 1DEA.1.2.N.FedEx>
USPS 9999.00 <gurobi.Var 1DEA.1.2.N.USPS>
DHL 9999.00 <gurobi.Var 1DEA.1.2.N.DHL>
2DAM 2 2 N UPS 33.02 <gurobi.Var 2DAM.2.2.N.UPS>
FedEx 9999.00 <gurobi.Var 2DAM.2.2.N.FedEx>
USPS 9999.00 <gurobi.Var 2DAM.2.2.N.USPS>
DHL 9999.00 <gurobi.Var 2DAM.2.2.N.DHL>

最后,您可以使用 pandas groupby 添加类似于问题中的约束

lhs = (df1.groupby(level=['service', 'bill_weight', 
'zone', 'resi']).assign.apply(grb.quicksum)
single_carrier_constrs = [m.addConstr(l == 1 for l in lhs]

关于python - 循环遍历字典键的元素而不是枚举所有元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52285586/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com