LINGO: Eine kleine Einführung Jun.-Prof.Dr. T. Nieberg Lineare und Ganzzahlige Optimierung, WS 2009/10 LINDO/LINGO ist ein Software-Paket, mit dessen Hilfe (ganzzahlige) lineare Programme schnell und einfach formuliert und gelöst werden können. Das Programm kann beim Hersteller 1 als Studentenversion heruntergeladen werden, diese Version ist in der Anzahl Variablen und Nebenbedingungen limitiert. Anhand des folgenden Beispiels werden wir nun den Formulierungs- und Lösungsprozess mit LINGO darstellen. 1 Ein Beispielproblem Eine Firma produziert ein Produkt, für das in den folgenden 4 Wochen eine Nachfrage von 20, 30, 40 und 35 Einheiten besteht. Pro Woche können maximal 36 Einheiten produziert werden, die Nachfrage kann aber auch durch Produktion vorhergehender Wochen erfüllt werden, d.h. es steht ein Lager zur Verfügung. Im Moment ist der Vorrat dort 10. Die Lagerhaltungskosten betragen 30 EUR für jede Einheit, die beim Übergang in die nächste Woche fällig wird, und jede produzierte, aber nicht direkt verkaufte Einheit wird gelagert. Die Produktionskosten pro Einheit betragen 200, 180, 175 und 190 EUR in Woche 1,2,3 bzw. 4. Ziel ist, die Nachfrage mit minimalen Kosten zu erfüllen. 2 Modellierung mit LINGO Entscheidungsvariablen: prod(i): Einheiten, die in Woche i produziert werden; i = 1, 2, 3, 4 lager(i): Einheiten, die zwischen Woche i und i + 1 im Lager sind; i = 1, 2, 3 In LINGO: SETS: WOCHE/1..4/: prod, lager; ENDSETS 1 www.lindo.com 1
Lineare und Ganzzahlige Optimierung, WS 2009/10 2 Hiermit hat jede Woche (1, 2, 3, 4) die Variablen prod(i) und lager(i). (Die Variable lager(4) ist nicht unbedingt nötig, sie ist aber im nachfolgenden Modell sinnvoll.) Will man den Wochen andere Namen geben, ist dies auch möglich: WOCHE/w19, w20, w21, w22/: prod, lager; Zielfunktion: mit min 4 pcost(i)prod(i) + i=1 3 lcost(i)lager(i) i=1 pcost = (200, 180, 175, 190) und lcost = (30, 30, 30). In LINGO: Wir verändern die Sets in WOCHE/1..4/: prod, lager, pcost, lcost; und fügen die Zielfunktion MIN = @SUM(WOCHE(i): pcost(i)*prod(i) + lcost(i)*lager(i)); sowie die Werte DATA: pcost = 200,180,175,190; lcost = 30,30,30,0; ENDDATA der Beschreibung hinzu. Die letzten 4 Zeilen legen für die Variablen pcost und lcost Werte fest, und diese werden nun als Konstanten, d.h. Koeffizienten, angesehen. (Durch lcost(4)=0 bleibt das Modell korrekt! Alternativ kann auch die Zielfunktion durch MIN = @SUM(WOCHE(i): pcost(i)*prod(i)) + @SUM(WOCHE(i) i #LE# 3: lcost(i)*lager(i)); definiert werden. Nebenbedingungen: prod(i) 36; i = 1, 2, 3, 4 lager(1) =prod(1) nachfrage(1) + 10 lager(i) =prod(i)+lager(i 1) nachfrage(i); i = 2, 3, 4 prod(i) 0; i = 1, 2, 3, 4 lager(i) 0; i = 1, 2, 3, 4 In LINGO: Wir verändern die Sets in WOCHE/1..4/: prod, lager, pcost, lcost, nachfrage; und fügen die Werte nachfrage = 20, 30, 40, 35; in DATA hinzu.
Lineare und Ganzzahlige Optimierung, WS 2009/10 3 Die Nebenbedingungen sind dann: @FOR(WOCHE(i): prod(i) <= 36); lager(1) = prod(1)-nachfrage(1)+10; @FOR(WOCHE(i) i #GE# 2: lager(i) = prod(i) + lager(i-1) - nachfrage(i)); @FOR(WOCHE(i): prod(i) >= 0); @FOR(WOCHE(i): lager(i) >= 0); Bei den letzten beiden Nebenbedingungen kommt eine Besonderheit von LINGO zum Tragen: standardmäßig wird davon ausgegangen, dass alle Variablen nichtnegativ sind (wie man dies umgeht wird später noch behandelt). Die letzten zwei Zeilen sind also streng genommen überflüssig.... die komplette Modellbeschreibung: MODEL: SETS: WOCHE/1..4/: prod, lager, pcost, lcost, nachfrage; ENDSETS MIN = @SUM(WOCHE(i): pcost(i)*prod(i) + lcost(i)*lager(i)); @FOR(WOCHE(i): prod(i) <= 36); lager(1) = prod(1)-nachfrage(1)+10; @FOR(WOCHE(i) i #GE# 2: lager(i) = prod(i) + lager(i-1) - nachfrage(i)); DATA: pcost = 200,180,175,190; lcost = 30,30,30,0; nachfrage = 20, 30, 40, 35; ENDDATA END 3 Generierung des (I)LPs und dessen Lösung LINGO Generate Display model liefert das entsprechende (I)LP-Modell: MODEL: [ 1] MIN= 200 * PROD 1 + 30 * LAGER 1 + 180 * PROD 2 + 30 * LAGER 2 + 175 * PROD 3 + 30 * LAGER 3 + 190 * PROD 4 ; [ 2] PROD 1 <= 36 ; [ 3] PROD 2 <= 36 ; [ 4] PROD 3 <= 36 ; [ 5] PROD 4 <= 36 ; [ 6] - PROD 1 + LAGER 1 = - 10 ; [ 7] - LAGER 1 - PROD 2 + LAGER 2 = - 30 ;
Lineare und Ganzzahlige Optimierung, WS 2009/10 4 [ 8] - LAGER 2 - PROD 3 + LAGER 3 = - 40 ; [ 9] - LAGER 3 - PROD 4 + LAGER 4 = - 35 ; END Nach der Lösungsberechnung (CTRL-U oder LINGO Solve) erscheint ein LINGO Solver Status -Fenster, das Auskunft über den Prozess gibt, und ein solution report, der die Werte der Entscheidungsvariablen, Zielfunktion und weitere nützliche Informationen enthält. Für das Beispiel sieht dieser Report wie folgt aus: Global optimal solution found. Objective value: 21190.00 Total solver iterations: 1 Variable Value Reduced Cost PROD( 1) 10.00000 0.000000 PROD( 2) 34.00000 0.000000 PROD( 3) 36.00000 0.000000 PROD( 4) 35.00000 0.000000 LAGER( 1) 0.000000 50.00000 LAGER( 2) 4.000000 0.000000 LAGER( 3) 0.000000 50.00000 LAGER( 4) 0.000000 190.0000 PCOST( 1) 200.0000 0.000000 PCOST( 2) 180.0000 0.000000 PCOST( 3) 175.0000 0.000000 PCOST( 4) 190.0000 0.000000 LCOST( 1) 30.00000 0.000000 LCOST( 2) 30.00000 0.000000 LCOST( 3) 30.00000 0.000000 LCOST( 4) 0.000000 0.000000 NACHFRAGE( 1) 20.00000 0.000000 NACHFRAGE( 2) 30.00000 0.000000 NACHFRAGE( 3) 40.00000 0.000000 NACHFRAGE( 4) 35.00000 0.000000 Row Slack or Surplus Dual Price 1 21190.00-1.000000 2 26.00000 0.000000 3 2.000000 0.000000 4 0.000000 35.00000 5 1.000000 0.000000 6 0.000000 200.0000
Lineare und Ganzzahlige Optimierung, WS 2009/10 5 7 0.000000 180.0000 8 0.000000 210.0000 9 0.000000 190.0000 Standardmäßig wird von nichtnegativen, rationalen Variablen ausgegangen. Soll im obigen Modell eine Variable als ganzzahlig deklariert werden, so fügt man @FOR(WOCHE(i): @GIN( prod(i))); hinzu (prod(i) sind jetzt nichtnegativ und ganzzahlig). Weitere Möglichkeiten für Variablen: @GIN: ganzzahlig, nichtnegativ ( N) @BIN: binär @FREE: frei (kann sowohl positiv, als auch negativ sein) 4 Weitere Tipps LINGO ist nicht case-sensitive: SUM, SuM, sum oder sum ist das gleiche. Jede Zeile wird mit einem Semikolon (;) beendet, außer SETS, DATA, ENDSETS und ENDDATA. Kommentar beginnen mit Ausrufungszeichen und enden mit Semikolon:! Dies ist ein Kommentar ; Es können auch Matrizen (mehrdimensionale Vektoren ) als Variablen definiert werden: TYP/1..5/; LINK(WOCHE,TYP): prod; definiert eine 2-dimensionalen 4 5 Matrix prod (WOCHE hatte 1..4 als Länge). Sind bei obiger Matrix prod nicht alle Kombinationen von WOCHE und TYP erlaubt, kann man diesen Vektor auch einschränken: LINK(WOCHE,TYP)/1,2 1,3 1,4 2,1 2,4 3,4 4,2 4,4 5,1/: prod prod(1,1) gibt es also nicht, und beim Aufbau des Modells wird dies auch entsprechend berücksichtigt. Um Indizes einzuschränken sind auch logische Operatoren vorhanden: #EQ#: gleich (equal) #NE#: ungleich (not equal) #GE#: größer gleich (greater than or equal) #GT#: größer (greater than) #LE#: kleiner gleich (less than or equal) #LT#: kleiner (less than) #AND#: logisches und #OR#: logisches oder
Lineare und Ganzzahlige Optimierung, WS 2009/10 6 LINGO kennt zwei Dateitypen,.lng und.lg4. Erstgenannte sind reine Textdateien, welche die Modellbeschreibung enthalten, und können mit jedem Editor bearbeitet werden.