使用 Pandas 和 NumPy 进行纸浆优化(CLSP - 批量调整)
Pulp Optimization with Pandas and NumPy (CLSP - Lot Sizing)
对于我的硕士论文,我将针对批量大小问题 (CLSP) 实施启发式算法。作为开始(和启发式的基准),我想为一个小例子实施最佳解决方案,以便了解 Python 及其功能。
这样做,我发现了几个优化问题,但其中一定比 CLSP 更基本。我觉得我主要是在与变量的多个索引以及 Pandas 和 PuLP.
的组合作斗争
顺便说一句:请不要介意#german 评论。它们仅用于我的文档。
这是我目前拥有的:
import pandas as pd
import numpy as np
import pulp
# Liste für Perioden erstellen
PERIODS = list(range(1,7))
# Liste für Produkte erstellen
PRODUCTS = [1, 2]
# Liste für Ressourcen erstellen
RESSOURCES = [1]
# Minimierungsproblem definieren
clsp = pulp.LpProblem("Capacitated Lot-Sizing Problem", pulp.LpMinimize)
# Variablen deklarieren
# Nichtnegativitätsbedingungen werden durch LB=0 sichergestellt.
q = pulp.LpVariable.dicts("Losgroesse fuer Produkt j in Periode t",
((k,t) for k in PRODUCTS
for t in PERIODS),
0, None, 'Continuous')
y = pulp.LpVariable.dicts("Lagerbestand für Produkt j am Ende der Periode t",
((k,t) for k in PRODUCTS
for t in PERIODS),
0, None, 'Continuous')
gamma = pulp.LpVariable.dicts("binaere Ruestvariable für Produkt j in Periode t",
((k,t) for k in PRODUCTS
for t in PERIODS),
0, 1, 'Binary')
#Daten festlegen (Sollte in Zukunft in extra csv-Datei gespeichert werden)
#Rüstkostensatz pro Produkt
s = {1: 100,
2: 50}
#Lagerhaltungskostensatz pro Produkt
h = {1: 4,
2: 1}
#Produktionskosten pro Produkt & Periode
p = pd.DataFrame (np.array([(2, 2, 2, 2, 2, 2), (3, 3, 3, 3, 3, 3)]), index=PRODUCTS ,columns=PERIODS)
'''1 2 3 4 5 6
1 2 2 2 2 2 2
2 3 3 3 3 3 3'''
#Bedarfsmengen pro Produkt & Periode
d = pd.DataFrame (np.array([(110, 49, 0, 82, 40, 65), (48, 75, 15, 10, 15, 70)]), index=PRODUCTS ,columns=PERIODS)
''' 1 2 3 4 5 6
1 110 49 0 82 40 65
2 48 75 15 10 15 70'''
#Big-M für binäre Rüstvariable
M = 1000
#Stückbearbeitungszeit für Produkt k an Ressource j
tb = pd.DataFrame (np.ones((1,2), dtype=np.int16), index=RESSOURCES ,columns=PRODUCTS)
#Rüstzeit für Produkt k auf Resource j
tr = pd.DataFrame (np.ones((1,2), dtype=np.int16), index=RESSOURCES ,columns=PRODUCTS)
#Kapazität der Ressource j in Periode t
b = pd.DataFrame (np.array([(160, 160, 160, 160, 120, 120)]), index=RESSOURCES ,columns=PERIODS)
# Zielfunktion aufstellen - Summe der Ruest-, Lager- & Produktionskosten:
clsp += pulp.lpSum([s[k] * gamma[k][t] + h[k] * y[k][t] + p.loc[k][t] * q[k][t] for k in PRODUCTS for t in PERIODS]), "Total Costs"
# Restriktionen
for k in PRODUCTS:
for t in PERIODS:
clsp += y[k][t-1] + q[k][t] - y[k][t] == d.loc[k][t] , "Lagerbilanzgleichung"
clsp += q[k][t] - M * gamma[k][t] <= 0 , "Big-M für Ruestvariable"
clsp += pulp.lpSum([tb.loc[j][k] * q[k][t] + tr.loc[j][k] * gamma[k][t] <= b.loc[j][t], "Kapazitaetstrestriktion"] for j in RESSOURCES)
# Lineares Programm (LP) in Textdatei schreiben
clsp.writeLP("CLSP.lp")
# LP lösen
clsp.solve()
# Status der Loesung ausgeben: “Not Solved”, “Infeasible”, “Unbounded”, “Undefined” or “Optimal”
print("Status:", pulp.LpStatus[clsp.status])
# Ergebnisse für einzelne Variablen ausgeben
for v in clsp.variables():
print(v.name, "=", v.varValue, "%")
# Optimale Loesung der Zielfunktion ausgeben
print("Total Costs = ", value(clsp.objective))
我觉得这不会太错..不过,我不确定接下来的部分。我不确定是否可以将索引(对于产品中的 k 等)放在所有约束之前,是否必须分别将它们放在每个约束之后。至少这样我在这里没有收到错误...
for k in PRODUCTS:
for t in PERIODS:
clsp += y[k][t-1] + q[k][t] - y[k][t] == d.loc[k][t] , "Lagerbilanzgleichung"
clsp += q[k][t] - M * gamma[k][t] <= 0 , "Big-M für Ruestvariable"
clsp += pulp.lpSum([tb.loc[j][k] * q[k][t] + tr.loc[j][k] * gamma[k][t] <= b.loc[j][t], "Kapazitaetstrestriktion"] for j in RESSOURCES)
此外,当 运行 该代码时,它给了我以下错误:
Traceback (most recent call last):
File "/Users/frederic/Dropbox/2_Universita\u0308t Duisburg-Essen/0_Master Thesis/Implementierung/CLSP/clsp_v2.py", line 69, in <module>
clsp += pulp.lpSum([s[k] * gamma[k][t] + h[k] * y[k][t] + p.loc[k][t] * q[k][t] for k in PRODUCTS for t in PERIODS]), "Total Costs"
File "/Users/frederic/Dropbox/2_Universita\u0308t Duisburg-Essen/0_Master Thesis/Implementierung/CLSP/clsp_v2.py", line 69, in <listcomp>
clsp += pulp.lpSum([s[k] * gamma[k][t] + h[k] * y[k][t] + p.loc[k][t] * q[k][t] for k in PRODUCTS for t in PERIODS]), "Total Costs"
KeyError: 1
第 69 行我的 objective 函数:
clsp += pulp.lpSum([s[k] * gamma[k][t] + h[k] * y[k][t] + p.loc[k][t] * q[k][t] for k in PRODUCTS for t in PERIODS]), "Total Costs"
我研究了所有在线文档并用谷歌搜索了几个小时,但我还没有找到可行的解决方案,所以任何提示都会有所帮助!
我是 Python 的新手,感谢您的耐心等待。
干杯,
弗雷德里克
感谢您提供代码和很好的解释。问题是您用来存储 LpVariables 的词典 q
、y
和 gamma
在 (k, t)
元组上建立了索引,因此您需要引用它们作为 gamma[(k, t)]
而不是 gamma[k][t]
.
当你达到这个限制时你会遇到另一个问题
clsp += y[(k, t-1)] + q[(k, t)] - y[(k, t)] == d.loc[k][t] , "Lagerbilanzgleichung"
因为当 t
等于 1 时 t-1
不会在 y
中。
对于我的硕士论文,我将针对批量大小问题 (CLSP) 实施启发式算法。作为开始(和启发式的基准),我想为一个小例子实施最佳解决方案,以便了解 Python 及其功能。
这样做,我发现了几个优化问题,但其中一定比 CLSP 更基本。我觉得我主要是在与变量的多个索引以及 Pandas 和 PuLP.
的组合作斗争顺便说一句:请不要介意#german 评论。它们仅用于我的文档。
这是我目前拥有的:
import pandas as pd
import numpy as np
import pulp
# Liste für Perioden erstellen
PERIODS = list(range(1,7))
# Liste für Produkte erstellen
PRODUCTS = [1, 2]
# Liste für Ressourcen erstellen
RESSOURCES = [1]
# Minimierungsproblem definieren
clsp = pulp.LpProblem("Capacitated Lot-Sizing Problem", pulp.LpMinimize)
# Variablen deklarieren
# Nichtnegativitätsbedingungen werden durch LB=0 sichergestellt.
q = pulp.LpVariable.dicts("Losgroesse fuer Produkt j in Periode t",
((k,t) for k in PRODUCTS
for t in PERIODS),
0, None, 'Continuous')
y = pulp.LpVariable.dicts("Lagerbestand für Produkt j am Ende der Periode t",
((k,t) for k in PRODUCTS
for t in PERIODS),
0, None, 'Continuous')
gamma = pulp.LpVariable.dicts("binaere Ruestvariable für Produkt j in Periode t",
((k,t) for k in PRODUCTS
for t in PERIODS),
0, 1, 'Binary')
#Daten festlegen (Sollte in Zukunft in extra csv-Datei gespeichert werden)
#Rüstkostensatz pro Produkt
s = {1: 100,
2: 50}
#Lagerhaltungskostensatz pro Produkt
h = {1: 4,
2: 1}
#Produktionskosten pro Produkt & Periode
p = pd.DataFrame (np.array([(2, 2, 2, 2, 2, 2), (3, 3, 3, 3, 3, 3)]), index=PRODUCTS ,columns=PERIODS)
'''1 2 3 4 5 6
1 2 2 2 2 2 2
2 3 3 3 3 3 3'''
#Bedarfsmengen pro Produkt & Periode
d = pd.DataFrame (np.array([(110, 49, 0, 82, 40, 65), (48, 75, 15, 10, 15, 70)]), index=PRODUCTS ,columns=PERIODS)
''' 1 2 3 4 5 6
1 110 49 0 82 40 65
2 48 75 15 10 15 70'''
#Big-M für binäre Rüstvariable
M = 1000
#Stückbearbeitungszeit für Produkt k an Ressource j
tb = pd.DataFrame (np.ones((1,2), dtype=np.int16), index=RESSOURCES ,columns=PRODUCTS)
#Rüstzeit für Produkt k auf Resource j
tr = pd.DataFrame (np.ones((1,2), dtype=np.int16), index=RESSOURCES ,columns=PRODUCTS)
#Kapazität der Ressource j in Periode t
b = pd.DataFrame (np.array([(160, 160, 160, 160, 120, 120)]), index=RESSOURCES ,columns=PERIODS)
# Zielfunktion aufstellen - Summe der Ruest-, Lager- & Produktionskosten:
clsp += pulp.lpSum([s[k] * gamma[k][t] + h[k] * y[k][t] + p.loc[k][t] * q[k][t] for k in PRODUCTS for t in PERIODS]), "Total Costs"
# Restriktionen
for k in PRODUCTS:
for t in PERIODS:
clsp += y[k][t-1] + q[k][t] - y[k][t] == d.loc[k][t] , "Lagerbilanzgleichung"
clsp += q[k][t] - M * gamma[k][t] <= 0 , "Big-M für Ruestvariable"
clsp += pulp.lpSum([tb.loc[j][k] * q[k][t] + tr.loc[j][k] * gamma[k][t] <= b.loc[j][t], "Kapazitaetstrestriktion"] for j in RESSOURCES)
# Lineares Programm (LP) in Textdatei schreiben
clsp.writeLP("CLSP.lp")
# LP lösen
clsp.solve()
# Status der Loesung ausgeben: “Not Solved”, “Infeasible”, “Unbounded”, “Undefined” or “Optimal”
print("Status:", pulp.LpStatus[clsp.status])
# Ergebnisse für einzelne Variablen ausgeben
for v in clsp.variables():
print(v.name, "=", v.varValue, "%")
# Optimale Loesung der Zielfunktion ausgeben
print("Total Costs = ", value(clsp.objective))
我觉得这不会太错..不过,我不确定接下来的部分。我不确定是否可以将索引(对于产品中的 k 等)放在所有约束之前,是否必须分别将它们放在每个约束之后。至少这样我在这里没有收到错误...
for k in PRODUCTS:
for t in PERIODS:
clsp += y[k][t-1] + q[k][t] - y[k][t] == d.loc[k][t] , "Lagerbilanzgleichung"
clsp += q[k][t] - M * gamma[k][t] <= 0 , "Big-M für Ruestvariable"
clsp += pulp.lpSum([tb.loc[j][k] * q[k][t] + tr.loc[j][k] * gamma[k][t] <= b.loc[j][t], "Kapazitaetstrestriktion"] for j in RESSOURCES)
此外,当 运行 该代码时,它给了我以下错误:
Traceback (most recent call last):
File "/Users/frederic/Dropbox/2_Universita\u0308t Duisburg-Essen/0_Master Thesis/Implementierung/CLSP/clsp_v2.py", line 69, in <module>
clsp += pulp.lpSum([s[k] * gamma[k][t] + h[k] * y[k][t] + p.loc[k][t] * q[k][t] for k in PRODUCTS for t in PERIODS]), "Total Costs"
File "/Users/frederic/Dropbox/2_Universita\u0308t Duisburg-Essen/0_Master Thesis/Implementierung/CLSP/clsp_v2.py", line 69, in <listcomp>
clsp += pulp.lpSum([s[k] * gamma[k][t] + h[k] * y[k][t] + p.loc[k][t] * q[k][t] for k in PRODUCTS for t in PERIODS]), "Total Costs"
KeyError: 1
第 69 行我的 objective 函数:
clsp += pulp.lpSum([s[k] * gamma[k][t] + h[k] * y[k][t] + p.loc[k][t] * q[k][t] for k in PRODUCTS for t in PERIODS]), "Total Costs"
我研究了所有在线文档并用谷歌搜索了几个小时,但我还没有找到可行的解决方案,所以任何提示都会有所帮助!
我是 Python 的新手,感谢您的耐心等待。
干杯, 弗雷德里克
感谢您提供代码和很好的解释。问题是您用来存储 LpVariables 的词典 q
、y
和 gamma
在 (k, t)
元组上建立了索引,因此您需要引用它们作为 gamma[(k, t)]
而不是 gamma[k][t]
.
当你达到这个限制时你会遇到另一个问题
clsp += y[(k, t-1)] + q[(k, t)] - y[(k, t)] == d.loc[k][t] , "Lagerbilanzgleichung"
因为当 t
等于 1 时 t-1
不会在 y
中。