Python определить имя переменной и условие на основе входных данных Excel - PullRequest
2 голосов
/ 14 июля 2020

Я работаю над проблемой LP в python.

Варианты выделения:

Type          Qty_Available   Cost  For_Protein    For_Carb
Protein_Can         50         10      TRUE          FALSE
Soup                15          8      FALSE         TRUE
EnergyDrink         10         15      TRUE          TRUE
            

Dataframe

StudentID   Age ProteinDef  CarbDef
A01         16      TRUE     TRUE
A02         17      FALSE    TRUE
A03         16      FALSE    FALSE
A04         18      TRUE     TRUE
A05         16      FALSE   TRUE
B01         18      FALSE   FALSE
B02         18      TRUE    TRUE
B03         20      FALSE   TRUE
B04         19      FALSE   FALSE
B05         19      TRUE    FALSE

Мой код работает нормально. Проблема, с которой я сталкиваюсь, заключается в том, что выбор распределения меняется каждый месяц в зависимости от наличия и предоставляется в формате Excel. Но мой код жестко запрограммирован (показан ниже)

Protein_Can = pulp.LpVariable.dicts("Protein_Can", df.StudentID, pulp.LpBinary)
Soup= pulp.LpVariable.dictsSoupdf.StudentID, pulp.LpBinary)
EnergyDrink= pulp.LpVariable.dicts("EnergyDrink", df.StudentID, pulp.LpBinary)


cost[id] = Protein_Can[id] * Protein_Can_Cost + Soup[id] * Soup_Cost + EnergyDrink[id] * EnergyDrink_Cost 

for id in df.StudentID:
    if df.loc[id]['ProteinDef'] == TRUE:
        prob +=  Soup[id] <= 0
    if df.loc[id]['CarbDef'] == TRUE:
        prob +=  Protein_Can[id] <= 0

Возможен ли подход, при котором я могу убедиться, что переменная определяется автоматически на основе ввода Excel? Не жестко закодированный способ? Можно ли сделать такой код динамическим c?

1 Ответ

1 голос
/ 14 июля 2020

Да!

Вам нужно лучше использовать наборы. Если у вас есть текст по линейному программированию или вы просматриваете несколько руководств, вы сможете найти множество примеров. Вы не должны жестко закодировать данные в формулировку, как вы есть. Можно либо читать данные из файла, либо разрабатывать их отдельно перед вашей математической моделью, но не в формулировке ограничений и т.п.

В приведенном выше примере есть 2 основных набора, каждый из которых имеет два подмножества . (ниже в псевдокоде)

основные наборы

Foods (или «варианты выделения»):

Foods = {protein_can, soup, etc...}

Вы можете использовать эти имена строк в качестве членов набора или просто используйте индекс и отслеживайте имена в индексированном списке отдельно от задачи

Студенты:

Students = {A01, A02, ... }

Подмножества

Каждый из вышеперечисленных наборов имеет 2 подмножества , связь с protein и carbs. Так, например, для Foods:

Foods_P = {Protein_can, energy_drink}  
Foods_C = ...

Их должно быть очень легко настроить при чтении данных, и их использование сделает вашу программу более чистой и быстрой.

Использование наборов. ..

После этого вам потребуются только 2 переменные для работы с продуктами:

avail[food]
cost[food]

, где food является членом набора Foods

Ваша модель выглядит как модель назначения, в которой вы назначаете определенное количество определенной пищи определенному учащемуся, поэтому у вас должна быть некоторая переменная решения с двойным индексом:

x[f, s]  # an integer/real number representing the assignment of x quantity of food f to student s

Подобные конструкции ограничения и стоимость должны встать на свои места ...

Чтение из Excel.

У вас есть пара вариантов здесь ...

  1. Используйте pandas для чтения информации, что, вероятно, является излишним и необязательным
  2. Используйте прямой интерфейс Excel, например openpyxl, что опять же является излишним.
  3. После настройки файла Excel, сохранять каждую вкладку как отдельный файл .csv (стандарт для данных ), а затем пусть python прочитает csv, что очень просто. (Используйте функцию «сохранить как» в Excel и выберите .csv ... игнорируйте предупреждения Билла Гейтса)

Вы должны создать два CSV-файла, один для еды, другой для студентов. Тогда они могут быть прочитаны как таковые:

# script to import csv files

file_name = 'food.csv'

qty_dict = {}
cost_dict = {}
foods = set()
food_p = set()
food_c = set()

with open(file_name, 'r') as fin:
    fin.readline()  # read the header and discard it
    # process the rest
    for line in fin:
        data = line.strip().split(',')
        key = data[0]           # the type name
        qty = int(data[1])      # int conversion of qty
        cost = int(data[2])     # int conversion of cost
        qty_dict[key] = qty
        cost_dict[key] = cost

        # test the booleans, construct the sets
        if data[3].lower() == 'true':
            food_p.add(key)
        if data[4].lower() == 'true':
            food_c.add(key)

print (cost_dict)
print (food_p)


# do same for students...

# make pulp model

# you probably have a decision variable X[f,s] which is probably something like:

X = pulp.LpVariable.dicts("assign", [(f, s) for f in foods for s in students], cat='Binary')

У меня не установлено pulp, поэтому последняя строка точна, но не проверена.

У вас должна быть возможность установить уточните свои ограничения и цель с помощью словарей и наборов, которые были созданы во время чтения.

Снимок еды в Excel:

введите описание изображения здесь

...