# -*- coding: utf-8 -*- """ Warehouse Location Problem vereinfacht """ from gurobipy import Model, GRB, quicksum """ Parameter """ # Fixkosten der Eröffnung der Standorte i f = [5, 6] # Kapazitäten der Standorte i a = [8, 9] # Nachfrage der Kunden j b = [5, 3, 7] # Kosten für die Lieferung einer Einheit von Standort i zu Kunde j c = [[9, 6, 7], [7, 3, 6]] """ Enumerierte Formulierung Alle Variablen und Nebenbedingungen werden explict aufgeschrieben, Parameter werden direkt aus gelesen """ model_enumerated = Model("WLP Vorlesung allgemein") ## Variablen ################################################################## # Transportmenge von Standort i zu Kunde j # lb=0 heißte untere grenze = 0, also nur positive Transportmengen # (Variablengrenzwerte werden schon bei der Definition berücksichtigt) x11 = model_enumerated.addVar(lb=0,vtype=GRB.CONTINUOUS, name="x_1_1") x12 = model_enumerated.addVar(lb=0,vtype=GRB.CONTINUOUS, name="x_1_2") x13 = model_enumerated.addVar(lb=0,vtype=GRB.CONTINUOUS, name="x_1_3") x21 = model_enumerated.addVar(lb=0,vtype=GRB.CONTINUOUS, name="x_2_1") x22 = model_enumerated.addVar(lb=0,vtype=GRB.CONTINUOUS, name="x_2_2") x23 = model_enumerated.addVar(lb=0,vtype=GRB.CONTINUOUS, name="x_2_3") # Eröffnung Standort i y1 = model_enumerated.addVar(vtype=GRB.BINARY, name="y1") y2 = model_enumerated.addVar(vtype=GRB.BINARY, name="y2") model_enumerated.update() # Variablen werden System bekannt gemacht ## Nebenbedingungen ########################################################## # Kapatzitätsbegrenzung der Standorte i # Zum Nachschlagen in der Liste müssen wir i-1 rechnen, da python in einer Liste von 0 anfägt zu zählen model_enumerated.addConstr(x11 + x12 + x13 <= y1 * a[0]) # Standort 1 model_enumerated.addConstr(x21 + x22 + x23 <= y2 * a[1]) # Standort 2 # Erfüllung der Nachfrage für Kunde j # Zum Nachschlagen in der Liste müssen wir j-1 rechnen, da python in einer Liste von 0 anfägt zu zählen model_enumerated.addConstr(x11 + x21 == b[0]) # Kunde 1 model_enumerated.addConstr(x12 + x22 == b[1]) # Kunde 2 model_enumerated.addConstr(x13 + x23 == b[2]) # Kunde 3 ## Zielfunktion ############################################################## # Kosten i,j müssen auch wieder an die 0-Zählweise angepasst werden model_enumerated.setObjective( c[0][0] * x11 + c[0][1] * x12 + c[0][2] * x13 + c[1][0] * x21 + c[1][1] * x22 + c[1][2] * x23 + y1 * f[0] + y2 * f[1], GRB.MINIMIZE) ############################################################################### model_enumerated.optimize() model_enumerated.write("enummerated.lp") """ Allgemeine Formulierung Wir machen uns schreiben Formeln in der allgemein gültigen Form und nutzen dabei Hilfsfunktion von Python und Gurobi. Es ist generell die bevorzugte Form MILP in allgemeiner Form aufzuschreiben, da es viel kürzer und übersichtlicher ist. Dementsprechend ist es von Vorteil, das auch direkt im Code auszudrücken. """ model_general = Model("WLP Vorlesung allgemein") m = 2 # Mögliche Standorte i n = 3 # Kunden j # 'range' erlaubt erstellt eine Abfolge 0,1 bzw 0,1,2. In den Folgenden Formel # benutzen wir es in etwa wie die Menge M M = range(m) N = range(n) ## Variablen ################################################################## # Transportmenge von Standort i zu Kunde j # Beachte: x ist jetzt ein Vektor von 6 Variablen (m x n) x = model_general.addVars(M, N, lb=0, vtype=GRB.CONTINUOUS, name="x") # Eröffnung Standort i # Beachte: y ist jetzt ein Vektor von 2 Variablen (m) y = model_general.addVars(M, vtype=GRB.BINARY, name="y") model_general.update() # Variablen werden System bekannt gemacht ## Nebenbedingungen ########################################################## # Kapatzitätsbegrenzung der Standorte i model_general.addConstrs(quicksum(x[i, j] for j in N) <= y[i] * a[i] for i in M) """ Was passiert hier? Erst einmal schreiben wir das i in M am Ende der Formel in eine Schleife um, dann erhalten wir die folgende Nebenbedingung (addConstr ohne 's' es ist nur eine Nebenbedingung pro Schleifendurchlauf) for i in M: model_general.addConstr(quicksum(x[i, j] for j in N) <= y[i] * a[i]) Zum Beispiel für i = 0 (Standort 1) hatten wir oben im Model diese Formel model_enumerated.addConstr(x11 + x12 + x13 <= y1 * a[0]) # Standort 1 Quicksum for j in N sorgt jetzt dafür das die folgended Gleichung eingefügt wird model_general.addConstr(x[0, 0] + x[0, 1] + x[0, 2] <= y[0] * a[0]) """ # Erfüllung der Nachfrage für Kunden j model_general.addConstrs(quicksum(x[i, j] for i in M) == b[j] for j in N) ## Zielfunktion ############################################################## model_general.setObjective(quicksum(c[i][j] * x[i, j] for i in M for j in N) + quicksum(y[i] * f[i] for i in M), GRB.MINIMIZE) # Definition Ende ############################################################# model_general.optimize() model_general.write("general.lp") """ Ausgabe Lösung """ print(" ") # Die Formulierungen sind gleichwertig print("Optimale Loesung gibt Gesamtkosten von: %s" % model_enumerated.objVal) print("Optimale Loesung gibt Gesamtkosten von: %s" % model_general.objVal) model_general.getVars() print(" ") for i in M: # Das x Attribut einer Variable ist der Wert in der aktuellen Lösung if (y[i].x == 1): print("Eroeffne Standort %s" % i) print(" ") print("Transportmenge von Standort i zu Kunde j:") print(" ") for i in M: # Das x Attribut einer Variable ist der Wert in der aktuellen Lösung if (y[i].x == 1): print(" ") for j in N: if (x[i, j].x > 0): print("Von Standort %s Kunde %s: %s" % (i, j, x[i, j].x))