Определите наборы и параметры из CSV-файла, которые будут использоваться в задаче оптимизации максимального количества собранных отходов pyomo

Впервые пользователь Pyomo здесь.

Я пытаюсь построить модель оптимизации, которая максимизирует количество отходов, собираемых в сети переработки отходов, состоящей из клиентов i и центров переработки j. (т. е. максимизировать количество отходов Qij, перетекающих из i в j). Вот математическая модель:

Математическая модель

Я закодировал функцию в блокноте jupyter, которая считывает координаты широты и долготы клиента и центра переработки из двух отдельных файлов csv, используя функцию read_csv. Функция с именем Distance_from вычисляет гаверсинус расстояния между координатами и запускает цикл, который будет анализировать местоположение клиентов один за другим до функции Distance_from. Это генерирует фрейм данных 80x16 RowsxColumns. Вот код этого бита:

#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-файлов для создания наборов и параметров для моей модели Pyomo с помощью AbstractModel(). Я не уверен, что этот метод или ConcreteModel() лучший способ сделать это.

Одно ограничение на задачу оптимизации определяет максимальное расстояние, которое клиент i преодолеет до центра переработки j, причем это максимальное расстояние установлено равным b = 5 км. Мне нужно, чтобы эти данные были прочитаны из CSV-файла или фрейма данных, но я не уверен, что это лучший метод, так как я мог бы также выполнить эту проверку при циклической передаче координат местоположения в функцию Distance_from.

Второе ограничение гарантирует, что общее количество отходов Qij, доставленных в аптеку j, не превысит пропускную способность 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_)


Заранее спасибо!

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
47
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Добро пожаловать на сайт.

Вы готовы начать "ОК". В вашей модели довольно много ошибок.... вы смотрели примеры в pyomoдокументация?

Несколько предложений:

  1. Начните с ConcreteModel и инициализируйте данные вручную. Я думаю, что это проще сделать, особенно. с возможностью python обрабатывать файлы .csv либо вручную (как показано ниже), либо с помощью pandas или csv_reader.

  2. Выбросьте pandas пока. Используйте его из отдельного файла, если необходимо, для Создайте файлов .csv, если вам это удобно, или просто напишите их вручную, или используйте csv_reader, но не смешивайте pandas и pyomo, пока не встанете на ноги. Тот же совет для numpy.

  3. Используйте формат «плоский файл» для ваших данных, а не табличный. Его легче проглотить. Так, например, создайте свою таблицу расстояний в формате csv, которая имеет 3 столбца, как у меня, и ее легче читать в словаре или, если вы идете в AbstractModel, она находится в простом формате.

  4. Используйте фрагмент небольшой ваших данных и pprint() вашей модели, чтобы убедиться, что это имеет смысл и соответствует вашей математической модели.

расстояний.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

Спасибо за ваш ответ. Да, я просматривал документацию Pyomo, но запутался в правильном способе формулировки проблемы при использовании «ConcreteModel» или «AbstractModel». Я попробую ваше предложение, так как оно кажется немного проще.

give the ball to bobby 23.03.2022 15:31

Другие вопросы по теме