【问题标题】:Pulp Optimization with Pandas and NumPy (CLSP - Lot Sizing)使用 Pandas 和 NumPy 优化纸浆(CLSP - 批量大小)
【发布时间】:2017-08-05 14:13:53
【问题描述】:

对于我的硕士论文,我将针对批量大小问题 (CLSP) 实施启发式方法。作为开始(以及启发式的基准),我想为一个小示例实现最佳解决方案,以便了解 Python 及其功能。

这样做,我发现了几个优化问题,但其中肯定比 CLSP 更基本。我觉得我主要是在变量的多个索引以及 Pandas 和 PuLP 的组合中挣扎。

顺便说一句:请不要介意#german cmets。它们仅用于我的文档。

这是我目前所拥有的:

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))

我觉得这不会太错误。不过,我不确定以下部分。我不确定是否可以将索引(对于 PRODUCTS 中的 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 行,我的目标函数:

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 还很陌生,所以我很感谢你在这里与我相处。

干杯, 弗雷德里克

【问题讨论】:

    标签: python pandas numpy linear-programming pulp


    【解决方案1】:

    感谢您提供代码和良好的解释。问题是您用来存储 LpVariables 的字典 qygamma(k, t) 元组上被索引,因此您需要将它们称为 gamma[(k, t)] 而不是 @987654326 @。

    当你遇到这个限制时,你会遇到另一个问题

    clsp += y[(k, t-1)]  + q[(k, t)] - y[(k, t)]  == d.loc[k][t]  , "Lagerbilanzgleichung"
    

    因为当 t 等于 1 时,t-1 不会在 y 中。

    【讨论】:

    • 感谢@thomaskeefe!目标函数现在似乎起作用了。你在另一个问题上是对的。我想我需要添加一个虚拟周期 0 。尽管如此,所有约束(基本上是目标函数之后的所有命令)似乎都会导致各种错误。例如,即使我输入 y[(k,t)] 而不是 y[(k,t-1)] 它仍然返回错误。
    • 您的约束还会遇到另一个问题:您在 for 循环中创建约束,但 for 循环的每次迭代都试图创建具有重复名称的约束。 PuLP 不允许这样做,因此您要么必须不包含约束名称,要么确保每次循环迭代的约束名称都不同。
    • 除了for循环还有其他方法吗?然后我会很容易地删除约束名称。这没那么重要。感谢您的提示。
    • 顺便说一句。我添加了一个变量y[(1,0)]=0,以便覆盖t-1 的情况。尽管如此,我仍然在这里遇到错误.. Traceback (most recent call last): File "/Users/frederic/Dropbox/2_Universita\u0308t Duisburg-Essen/0_Master Thesis/Implementierung/CLSP/clsp_v2.py", line 76, in &lt;module&gt; clsp += y[(k,t-1)] + q[k][t] - y[(k,t)] == d.loc[k][t] , "Lagerbilanzgleichung" KeyError: 1
    • 这是你的 q 字典。要在 for 循环中创建唯一的约束名称,您可以查看字符串格式。它看起来像"Lagerbilanzgleichung_{}_{}".format(k, t)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多