从csv文件中定义要在pyomo优化最大数量废物收集问题中使用的集合和参数



Pyomo第一次在这里使用。

我正试图建立一个优化模型,使由客户I和回收中心j组成的废物回收网络中收集的废物数量最大化(即,使从I到j的废物Qij数量最大化(。以下是数学模型:

数学模型

我在jupyter笔记本中编码了一个函数,该函数使用read_csv函数从两个单独的csv文件中读取客户和回收中心的纬度和经度坐标。名为distance_from的函数计算坐标之间的haversine距离,并运行一个循环,该循环将逐个解析客户位置到distance_form函数。这将生成一个80x16行x列的数据帧。这是这个比特的代码:

#create data file of customers i and recycling centres j
df_cent = pd.read_csv("recycling centres.csv",index_col=[0], header=0)
df_cust = pd.read_csv("customers.csv",index_col=[0], header=0)
# concatenating lat and long to create a consolidated location as accepted by haversine function
df_cent['coordinates'] = list(zip(df_cent.Latitude, df_cent.Longitude))
df_cust['coordinates'] = list(zip(df_cust.Latitude, df_cust.Longitude))
# defining a  function to calculate distance between two locations 
# loc1= location of an existing recycling centre
# loc2= location of customer
def distance_from(loc1,loc2): 
dist=hs.haversine(loc1,loc2)
return round(dist,2)
# running a loop which will parse customers location one by one to distance from function 
for _,row in df_cent.iterrows():
df_cust[row.Name]=df_cust['coordinates'].apply(lambda d:
distance_from(row.coordinates,d))

我的问题是我还没有对这个函数进行任何优化。我想使用csv文件中的数据,使用AbstractModel((为我的Pyomo模型创建集合和参数。我不确定这个方法或ConcreteModel((是否是最好的方法。

优化问题的一个约束条件确定了客户i将前往回收中心j的最大距离,该最大距离设置为b=5km。我需要从csv文件或数据帧中读取这些数据,但我不确定这是否是最好的方法,因为在将位置坐标循环到distance_from函数时,我也可以执行此检查。

第二个约束条件确保输送到药房j的废物总量Qij不会超过j的容量,这也是从csv文件中读取的。

二元决策变量Xij=1,如果客户i将废物输送到回收中心j,则Xij=0,否则

这是我试图编写的代码,它将定义要从csv文件中读取的集合,定义目标函数并应用约束。它出现在上面的代码之后。我不确定这个代码离我需要的地方有多远。所有的代码都写在Jupyter Notebook中,但我不认为我可以在这里找到文件,也不认为我能找到csv数据文件。

from pyomo.environ import *
import pandas as pd
import haversine as hs
solver = SolverFactory('glpk') #GNU Linear Programming Kit
model = AbstractModel()
#set of customers
model.I = pd.read_csv("customers.csv", index_col="Number")
#set of recycling centres
model.J = pd.read_csv("recycling centres.csv", index_col="Name")
#waste generation quantity unit=kg/month
model.Q = pd.read_csv("customers.csv", index_col="Waste Generation (kg/month)")
#Capacity at recycling centre j unit=kg/month
model.Cj = pd.read_csv("recycling centres.csv", index_col="Capacity (kg/month)")
#Binary decision Variable X=1 if customer i served by recycling centre j, X=0 otherwise
model.X = Var(model.I, model.J, domain=Binary)
#Maximum distance customer i will travel to recycling facility j unit=km
model.b = 5 
# Objective is to maximise waste collected within network
def waste_(model):
return sum(model.Q[i,j]*model.X[i,j] for i in model.I for j in model.J)
model.waste = Objective(rule=waste_, sense=maximize)
# Distance from i to j constraint
def distance_(model, i, j):
return sum(model.d[i,j]*model.X[i,j] for i in model.I for j in model.J) <= model.b
model.distance = Constraint(rule=distance_)
#Capacity constraint
def capacity_(model, i, j):
return sum(model.d[i,j]*model.X[i,j] for i in model.I for j in model.J) <= model.Cj
model.capacity = Constraint(rule=capacity_)

提前感谢!

欢迎访问本网站。

你去了一个";OK";开始您的模型中有不少错误……您看过pyomo文档中的示例吗?

几个建议:

  1. ConcreteModel开始,手动初始化数据。我认为这更容易做到,尤其是python能够手动处理.csv文件(如下所示(,或者使用panda或csv_reader。

  2. 暂时放弃pandas。如果需要,可以从一个单独的文件中使用它来创建.csv文件(如果您对此感到满意(,或者手动编写它们,或者使用csv_reader,但在站稳脚跟之前不要将pandaspyomo混合在一起。numpy也有同样的建议。

  3. 使用";扁平锉";数据格式,而不是表格格式。它更容易摄入。因此,例如,在csv中创建一个距离表,它有3列,就像我的一样,更容易读入字典,或者,如果你使用AbstractModel,它的格式很简单。

  4. 使用数据的切片和pprint()模型,以确保它有意义并符合您的数学模型。

distances.csv(可以从输出推断出其他数据文件(

Bob,Main St.,2.1
Cindy,Main St.,3.4
Bob,3rd Ave.,4.9
Cindy,3rd Ave.,0.5 

代码

# pyomo model for customers and distances
import pyomo.environ as pyo
customers = []
centers = []
distances = {}
with open('customers.csv', 'r') as src:
for line in src:
customers.append(line.strip())
with open('centers.csv', 'r') as src:
for line in src:
centers.append(line.strip())
with open('distances.csv', 'r') as src:
for line in src:
cust, center, dist = line.strip().split(',')
distances[cust, center] = float(dist)
print(customers)
print(centers)
print(distances)
model = pyo.ConcreteModel()
# SETS
model.customers = pyo.Set(initialize=customers)
model.centers = pyo.Set(initialize=centers)
# PARAMETERS
model.distances = pyo.Param(model.customers, model.centers, initialize=distances)
# check it...
model.pprint()

输出

['Bob', 'Cindy']
['Main St.', '3rd Ave.']
{('Bob', 'Main St.'): 2.1, ('Cindy', 'Main St.'): 3.4, ('Bob', '3rd Ave.'): 4.9, ('Cindy', '3rd Ave.'): 0.5}
3 Set Declarations
centers : Size=1, Index=None, Ordered=Insertion
Key  : Dimen : Domain : Size : Members
None :     1 :    Any :    2 : {'Main St.', '3rd Ave.'}
customers : Size=1, Index=None, Ordered=Insertion
Key  : Dimen : Domain : Size : Members
None :     1 :    Any :    2 : {'Bob', 'Cindy'}
distances_index : Size=1, Index=None, Ordered=True
Key  : Dimen : Domain            : Size : Members
None :     2 : customers*centers :    4 : {('Bob', 'Main St.'), ('Bob', '3rd Ave.'), ('Cindy', 'Main St.'), ('Cindy', '3rd Ave.')}
1 Param Declarations
distances : Size=4, Index=distances_index, Domain=Any, Default=None, Mutable=False
Key                   : Value
('Bob', '3rd Ave.') :   4.9
('Bob', 'Main St.') :   2.1
('Cindy', '3rd Ave.') :   0.5
('Cindy', 'Main St.') :   3.4
4 Declarations: customers centers distances_index distances

最新更新