PuLP: цель Функция: добавление нескольких lpSum в цикле
Я пытаюсь использовать PuLp для решения проблемы смешивания с различными элементами (железо, ртуть). Но вместо максимальной / минимальной прибыли / затрат мне нужно максимально использовать мои ограничения. Так что в Excel у меня было что-то вроде этого (в псевдокоде):
max Sum (for each Element: (Sumproduct([DecisionVariables] * [Values]) / [MaximumAllowedValueForThisElement]))
Я никогда не использовал такую функцию, как эта, но, похоже, она работает в Excel.
Теперь я хочу смоделировать ту же проблему в PuLP. Я думаю, что мне нужно что-то вроде этого:
for Element in ELEMENTS:
prob += lpSum(DecisionVariable[Concentrate]*dic[Element][Concentrate]/ MaxAmount[Element] for Concentrate in CONCENTRATES)
Если ELEMENTS - это список, содержащий все элементы, CONCENTRATES - это список значений от 0 до 100, а dic[Element][Concentrate] хранит значения каждого элемента и всех его концентратов.
Теперь, с помощью кода выше, целевая функция перезаписывается в каждом цикле. Вместо того, чтобы перезаписывать старую целевую функцию, мне нужно что-то вроде append() или тому подобное, чтобы добавить каждый из циклов =lpSums к моей переменной prob?
Я довольно новичок в программировании в целом, и я думаю, что моя проблема больше связана с моим отсутствием навыков программирования на Python, чем с моими (также не имеющими:D) навыками PuLP. Но я не смог найти ничего в документации PuLP, по крайней мере, ничего, к чему я мог бы подключиться.
Изменить: Включил небольшую таблицу, чтобы продемонстрировать проблему:
+------------------------------+-------------------------------------------+----+------------------------------+---------------+----------------------+---------------+---------------+-------------------------------+
| Utilization [%] | Sumproduct[Quantity] = [LHS] | | Constrains[Quantity] = [RHS] | Concentrate | Element 1 [%] | Element 2 [%] | Element 3 [%] | Decision Variables [Quantity] |
+------------------------------+-------------------------------------------+----+------------------------------+---------------+----------------------+---------------+---------------+-------------------------------+
| u1 = z1 / MaxAmount Element1 | z1 = Col Element1 * Col Decison Variables | <= | MaxAmount Element1 | Concentrate 1 | % Element 1 in Con 1 | | | X1 |
| u2 = z2 / MaxAmount Element2 | z2 = Col Element2 * Col Decison Variables | <= | MaxAmount Elemen2 | Concentrate 2 | % Element 1 in Con 2 | | | X2 |
| u3 = z3 / MaxAmount Element3 | z3 = Col Element3 * Col Decison Variables | <= | MaxAmount Elemen3 | Concentrate 3 | % Element 1 in Con 3 | | | X3 |
+------------------------------+-------------------------------------------+----+------------------------------+---------------+----------------------+---------------+---------------+-------------------------------+
В столбцах "Элемент 2" и "Элемент 3" хранится та же информация, что и в столбце "Элемент 1": доля% соответствующего элемента в концентрате 1/2/3.
Задача состоит в том, чтобы максимизировать сумму по всем использованиям (u1+u2+u3). Поэтому я пытаюсь определить, сколько из каждого концентрата мне следует использовать, чтобы использовать как можно больше данных ограничений для каждого элемента. Возвращаясь к своему PuLp-коду, я думаю, что могу добавить эквивалент "u1" в свой PuLp "LpProblem Class", но я не могу понять, как добавить несколько таких LpSums в мой "LpProblem Class" в петля.
1 ответ
Вот одна из версий, с фиктивными данными для наглядности. Посмотрите, поможет ли это вам.
import pulp
from pulp import *
ELEMENTS = ['Iron', 'Mercury', 'Silver']
Max_Per_Elem = {'Iron': 35,
'Mercury': 17,
'Silver': 28
}
# A dictionary of the Iron percent in each of the CONCs
IronPercent = {'CONC_1': 20, 'CONC_2': 10, 'CONC_3': 25}
# A dictionary of the Hg percent in each of the CONCs
MercPercent = {'CONC_1': 15, 'CONC_2': 18, 'CONC_3': 12}
# A dictionary of the Silver percent in each of the CONCs
SilverPercent = {'CONC_1': 30, 'CONC_2': 40, 'CONC_3': 20}
CONCENTRATE_DIC = {'Iron': IronPercent,
'Mercury': MercPercent,
'Silver': SilverPercent
}
# Creates a list of Decision Variables
concs = ['CONC_1', 'CONC_2', 'CONC_3']
Теперь мы готовы позвонить puLP
функции.
conc_vars = LpVariable.dicts("Util", concs, 0, 1.0)
# Create the 'prob' variable to contain the problem data
prob = LpProblem("Elements Concentration Problem", LpMaximize)
# The objective function
prob += lpSum([conc_vars[i] for i in concs]), "Total Utilization is maximized"
for elem in ELEMENTS:
prob += lpSum([CONCENTRATE_DIC[elem][i]/Max_Per_Elem[elem] * conc_vars[i] for i in concs]) <= Max_Per_Elem[elem]/100, elem+"Percent"
Для подтверждения вы можете распечатать prob
чтобы увидеть, как это выглядит:
Elements Concentration Problem:
MAXIMIZE
1*Util_CONC_1 + 1*Util_CONC_2 + 1*Util_CONC_3 + 0
SUBJECT TO
IronPercent: 0.571428571429 Util_CONC_1 + 0.285714285714 Util_CONC_2
+ 0.714285714286 Util_CONC_3 <= 0.35
MercuryPercent: 0.882352941176 Util_CONC_1 + 1.05882352941 Util_CONC_2
+ 0.705882352941 Util_CONC_3 <= 0.17
SilverPercent: 1.07142857143 Util_CONC_1 + 1.42857142857 Util_CONC_2
+ 0.714285714286 Util_CONC_3 <= 0.28
VARIABLES
Util_CONC_1 <= 1 Continuous
Util_CONC_2 <= 1 Continuous
Util_CONC_3 <= 1 Continuous
Как только вы довольны формулировкой, решите проблему.
prob.writeLP("ElemUtiliztionModel.lp")
prob.solve()
print("Status:", LpStatus[prob.status])
for v in prob.variables():
print(v.name, "=", v.varValue)
Получить,
Status: Optimal
Util_CONC_1 = 0.0
Util_CONC_2 = 0.0
Util_CONC_3 = 0.24083333
Надеюсь, что это поможет вам двигаться вперед.