English version Spanish version Italian version

Lektion 5: Ein Produktionsplanungsproblem mit mehreren Produktionsstandorten

Bei der Modellformulierung von Problemen größerer Firmen trifft man häufig auf die Situation, dass nicht ein einzelner Standort, sondern gleich ein Verbund mehrerer Standorte abgebildet werden muss. Daher wird in dieser Lektion ein Produktionsplanungsproblem mit mehreren Standorten formuliert. Daher wird in dieser Lektion das Modell aus der vorherigen Lektion aufgegriffen und um einen Standort-Index erweitert, dessen Elemente alle verfügbaren Standorte sind, an denen die Produkte produziert werden können. Hierzu werden wieder schrittweise alle Vektoren um diesen Index erweitert.


Neue Konzepte in dieser Lektion

Produktionstandorte und andere Standortindizes

Standortindizes sind sehr nützlich in Produktionsplanungsmodellen. Sie können Produktionsstandorte, Warenhäuser oder z.b. Verteilzentren repräsentieren.

Die Standorte, die durch die Elemente der Standortindexmenge benannt werden, sind meist durch Transportwege verknpüft. Daher werden derartige Modelle auch häufig Transport- oder Distributionsmodelle genannt; sie werden in einer späteren Lektion behandelt.

Externe Datendateien

Bei kleineren, überschaubaren Modellen ist es möglich und auch häufig sinnvoll, die Daten gleich in der Modelldatei zu definieren. Sobald man aber mehrdimensionale Vektoren mitführt, wird dies sehr mühsam und es ist sinnvoller, die Daten in externen Dateien zu halten. Dies verbessert zum einen die Lesbarkeit der Daten, macht aber auch die Pflege der Daten in dafür geeigneteren Strukturen einfacher.

Das in dieser Lektion zu erstellende Modell enthält Variablenvektoren, die von den drei Indizes product, month, und plant abhängen, aber auch zwei-dimensionale Datenvektoren, wie z.b. den Demand-Vektor, dessen Daten nun aus einer externen Datei bezogen werden sollen. Hierzu kann das Befehlswort DATAFILE in Verbindung mit dem Namen der Datendatei wie im folgenden Beispiel verwendet werden:

     demand[product, month]   :=  DATAFILE("Demand.dat");
    

Problembeschreibung: Ein Produktionsplanungsproblem mit mehreren Produktionsstandorten

In dieser Lektion soll ein neues Produktionsplanungsmodell entwickelt werden, das als weiteren Index einen Index für die Produktionsstandorte enthält.

Hierzu sollen vier verschiedene Standorte p1, p2, p3 und p4 berücksichtigt werden, von denen jeder jedes Produkt herstellen kann. Zu diesem Zeitpunkt sei die Feinstruktur der Standorte, d.h. die Existenz individueller Anlagen, noch nicht weiter betrachtet; dies erfolgt erst in Lektion 7. In dieser Lektion wird zunächst die Indexmenge plants erzeugt, die die vier verschiedenen Standorte enthält; anschliessend wird der neue Index zu den entsprechenden Vektoren hinzugefügt.

Die Verkaufspreise je Produkt $120.00, $100.00 und $150.00 sollen, wie auch die Verkaufsnachfragen, gegenüber de vorherigen Lektion unverändert bleiben.

Allerdings soll jeder Standort verschiedene Produktionskosten haben; diese sind in der nachfolgenden Tabelle gezeigt:

Production Cost A1 A2 A3
plant 1 $73.30 $52.90 $65.40
plant 2 $79.00 $52.00 $66.80
plant 3 $75.80 $52.10 $50.90
plant 4 $82.70 $63.30 $53.80

Wie die nachfolgende Tabelle zeigt, sind nun auch die Produktionsraten für jedes standortabhängig:

Production Rate A1 A2 A3
plant 1 500 450 450
plant 2 550 450 300
plant 3 450 350 300
plant 4 550 400 350

Formulierung des Problems in MPL

Nachstehend ist das vollständige Modell für das Problem Planning5 aufgelistet. Gegenüber der Formulierung in Lektion 4 sind einige Erweiterungen erkennbar; sie sind im Fettdruck hervorgehoben und leicht zu verfolgen.

     TITLE
        Production_Planning5;

     INDEX
        product := (A1, A2, A3);
        month   := (Jan, Feb, Mar, Apr);
        plant   := (p1, p2, p3, p4);

     DATA
        Price[product]            :=  (120.00, 100.00, 115.00);
        Demand[product, month]    :=  DATAFILE("Demand.dat");
        ProdCost[plant, product]  :=  DATAFILE("ProdCost.dat");
        ProdRate[plant, product]  :=  DATAFILE("ProdRate.dat");

        ProdDaysAvail[month]      :=  (23, 20, 23, 22);
        InvtCost[product]         :=  (3.50, 4.00, 3.00);
        InvtCapacity              :=  800;

     VARIABLES
        Produce[plant, product, month]  -> Prod;
        Inventory[product, month]       -> Invt;
        Sales[product, month]           -> Sale;

     MACROS
        TotalRevenue   := SUM(product, month: Price * Sales);
        TotalProdCost  := SUM(plant, product, month: ProdCost * Produce);
        TotalInvtCost  := SUM(product, month: InvtCost * Inventory);
        TotalCost      := TotalProdCost + TotalInvtCost;

     MODEL

        MAX  Profit  =  TotalRevenue - TotalCost;

     SUBJECT TO
        ProdCapacity[plant, month] -> PCap:
           SUM(product: Produce / ProdRate)  <=  ProdDaysAvail;

        InvtBal[product, month] -> IBal:
           SUM(plant: Produce) + Inventory[month-1]  =  Sales + Inventory;

        MaxInventory[month] -> MaxI:
           SUM(product: Inventory)   <=  InvtCapacity;

     BOUNDS
        Sales   <=  Demand;

     END
    

Schrittweise Eingabe der neuen Elemente in MPL

Schritt 1: Start von MPL und Erzeugung einer neuen Modelldatei

  1. Start der MPL Applikation.

  2. Wähle File | Open und öffne die Modelldatei Planning4.mpl aus der vorherigen Lektion.

  3. Wähle File | Save As zum Speichern der neuen Modelldatei Planning5.mpl.

Schritt 2: Ändern des Titels des Modells

Der Titel des Modells soll geändert werden um klarzustellen, dass nun mit der Modelldatei Planning5 gearbeitet wird.

     TITLE
        Production_Planning5;
    

Schritt 3: Hinzufügen des Indexs 'plant' zum Modell

In diesem Beispiel sind vier Standorte zu berücksichtigen. Der neu zu erstellende Index soll plant heissen und die vier Element p1, p2, p3 und p4 haben. Zunächst soll die Definition für den Index plant, wie sie in Fettdruck hervorgehoben ist, zum INDEX-Abschnitt hinzugefügt werden:

     INDEX
        product :=  (A1, A2, A3);
        month   :=  (Jan, Feb, Mar, Apr);
        plant   :=  (p1, p2, p3, p4);
    

Schritt 4: Modifikation des 'Demand' Datenvektors zum Zugriff auf eine externe Datendatei

In dieser Lektion sollen die Werte für den zweidimensionalen Datenvektor 'Demand' von einer externen Datei bezogen werden. Dies verbessert die Lesbarkeit des Modells, aber auch die Pflege der Daten.

Um den Demand Datenvektor mit einer exteren Datei zu verknüpfen, wird im DATA-Abschnitt der Cut-Befehl aus dem Edit-Menu verwendet, um die Werteliste aus der Definition des DemandVektors zu entfernen und anschliessend durch das Schlüsselwort DATAFILE und den Dateinamen Demand.dat wie folgt zu ersetzen:

     DATA
        Price[product]          :=  (120.00, 100.00, 115.00);
        Demand[product, month]  :=  DATAFILE("Demand.dat");
    

Schritt 5: Erzeugung der Datendatei 'Demand.dat'

Als nächstes ist nun die Datei Demand.dat zu erzeugen. Dazu wird ein neues Editorfenster durch Wahl von New im File-Menu geöffnet. Wurde im vorherigen Schritt 4 der Edit | Cut-Befehl verwendet, um die Daten zu entfernen, so sind können diese dem Clipboard wieder mit dem Edit | Paste-Befehl entnommen werden. Andernfalls können die Daten der Problembeschreibung in Lektion 3 entnommen und hier wieder neu eingegeben werden:

     !  Demand.dat  -  Demand per month for each product
     !
     !  Demand[product,month]:
     !
     !          Jan    Feb    Mar    Apr
     !        ----------------------------
               4300,  4200,  6400,  5300,
               4500,  5400,  6500,  7200,
               5400,  6700,  7800,  8200
     

Die mit einem Ausrufezeichen beginnenden Zeilen sind lediglich Kommentarzeilen zur Erhöhung der Lesbarkeit. Die Zahlenwerte selbst können durch Kommas, Leerzeichen oder beides getrennt werden. Nach Eingabe aller Daten soll die Datei unter dem Namen Demand.dat in das Tutorial-Vereichnis gespeichert werden.

Schritt 6: Aktualisierung der 'ProdCost' und 'ProdRate' Datenvektoren durch Einbeziehung des 'plant'-Indexes

Zwei der im Modell enthaltenen Datenvektoren, ProdCost und ProdRate, müssen um den plant-Index erweitert werden. Der ProdCost-Datenvektor ist nun sowohl vom plant- als auch vom product-Index abhängig und wird von einer externen Datendatei mit Werten gefüllt. Der ProdRate wird nun ebenfalls mit einer externen Datendatei verknpüft. Dazu wird im Modelleditor der plant zur Deklaration der ProdCost und ProdRate-Datenvektoren hinzugefügt und mit den Dateien ProdCost.dat und ProdRate.dat wie folgt verknpüft:

Die mit einem Ausrufezeichen beginnenden Zeilen sind lediglich Kommentarzeilen zur Erhöhung der Lesbarkeit. Die Zahlenwerte selbst können durch Kommas, Leerzeichen oder beides getrennt werden. Nach Eingabe aller Daten soll die Datei unter dem Namen Demand.dat in das Tutorial-Vereichnis gespeichert werden.

        ProdCost[plant, product]  :=  DATAFILE("ProdCost.dat");
        ProdRate[plant, product]  :=  DATAFILE("ProdRate.dat");
        ProdDaysAvail[month]      :=  (23, 20, 23, 22);
        InvtCost[product]         :=  (3.50, 4.00 3.00);
        InvtCapacity              :=  800;
    

Schritt 7: Erzeugung der Dateien für die 'ProdCost' und 'ProdRate'-Datenvektoren

Mit File | New im Menu wird ein neues Fenster zur Eingabe der Daten erzeugt. Hier werden nun die Produktionskosten aus der Problembeschreibung übernommen:

     !
     !  ProdCost.dat  -  Cost per item produced
     !
     !  ProdCost[plant, product]:
     !
     !           A1      A2      A3
     !        -----------------------
               73.30,  52.90,  65.40,
               79.00,  52.00,  66.80,
               75.80,  52.10,  50.90,
               82.70,  63.30,  53.80
    

Wiederum sind zur Erhöhung der Lesbarkeit mit einem Ausrufezeichen markierte Kommentarzeilen eingefügt. Nach Eingabe aller Daten wird die Datei unter der Bezeichnung ProdCost.dat gespeichert.

Für die Produktionsraten soll nun die ProdRate.dat erzeugt und mit den Werten aus der Tabelle der Problembeschreibung gefüllt werden.

     !
     !  ProdRate.dat  -  Items produced per day
     !
     !  ProdRate[plant, product]:
     !
     !          A1    A2    A3
     !        ------------------
               500,  450,  450,
               550,  450,  300,
               450,  350,  300,
               550,  400,  350
   

Schritt 8: Aktualisierung der 'Produktions'-Variablen und Einbeziehung des 'plant' Indexes

Um die Entscheidungen zu verfolgen, wieviel von jedem Produkt an jedem Standort produziert wird, muss der plant-Index zur Definition der Vektorvariablen Produce wie folgt hinzugefügt werden:

     VARIABLES
        Produce[plant, product, month] -> Prod;
        Inventory[product, month]      -> Invt;
        Sales[product, month]          -> Sale;
    

Schritt 9: Hinzufügung des 'plant'-Indexes zur Summation 'TotalProdCost'

Da die Produce-Variable nun den neuen plant-Index enthält, muss die Berechnung der gesamten Produktionskosten im MACROS-Abschnitt ebenfalls angepasst und um den plant-Index erweitert werden:

     MACROS
        TotalRevenue   := SUM(product, month: Price * Sales);
        TotalProdCost  := SUM(plant, product, month: ProdCost * Produce) ;
        TotalInvtCost  := SUM(product, month: InvtCost * Inventory);
        TotalCost      := TotalProdCost + TotalInvtCost;
    

Die Zielfunktion selbst braucht nicht geändert zu werden, da dieselben Makros wie in der vorherigen Lektion verwendet werden.

Schritt 10: Hinzufügung des 'plant'-Indexes zur 'ProdCapacity'-Bedingung

Die Änderungen, die die Produktionskapazitätsbedingung betreffen sind sehr einfach vorzunehmen. Es braucht lediglich der plant-Index zur Deklaration der Nebenbedingung hinzugefügt zu werden; alles übrige bleibt unverändert.

     SUBJECT TO
        ProdCapacity[plant, month] -> PCap:
           SUM(product: Produce / ProdRate)   <=  ProdDaysAvail;
    

Schritt 11: Hinzufügung der 'Produktions'-Variablen unter Einbeziehung des 'plant'-Indexes zur Lagerbilanzgleichung

Da alle Produkte an jedem der vier Standorte produziert werden können, muss nun in der Lagerblanzgleichung eine Summierung der Produktionsvariablen über alle Standorte erfolgen.

     InvtBal[product, month] -> IBal:
        SUM(plant: Produce) + Inventory[month-1]  =  Sales + Inventory;
    

Nach dieser Ersetzung sind nun alle Korrekturen beendet und die Modelldatei kann durch Wahl von Save im File-Menu gespeichert werden.


Lösung des Problems und Analyse der Lösung

Durch die zusäztzlichen Indizes ist die Anzahl der Variablen enorm angewachsen. Bei großen, umfangreichen Modellen mit vielen Variablen ist es nicht unbedingt sinnvoll, alle Variablen auszuweisen. Wir wollen daher nur die Variablen in der Lösungsdatei betrachten, deren Lösungswert von Null verschieden ist. MPL bietet im Options-Menu eine Reihe von Optionsdialogfenster, mit denen das standardmässige Verhalten beeinflusst werden kann. Eine dieser Dialogfenster heisst Solution File Options und bietet die Möglichkeit, die Ausgabe und die Details für den Ausdruck in die Lösungsdatei zu beeinflussen. Um zu bewirken, dass nur Variablen in die Lösungsdatei aufgenommen werden, deren Werte von Null verschieden sind, ist wie folgt vorzugehen:

  1. Aus dem Options-Menu wird Solution File ausgewählt, um das nachfolgend gezeigte Options Dialogfenster zu öffnen:

  2. Das Options-Dialogfenster für die Lösungsdatei

  3. Aktivieren der Nonzero Values Only-Feldes On durch Anklicken.

  4. Das Dialogfenster wird durch Drücken der OK-Taste geschlossen.

Nach Änderung der Nonzero Values Only-Option, soll das durch 'Planning5.mpl' kodierte Problem nun gelöst werden. Hierzu wird im Run-Menu die Option Solve CPLEX gewählt. Sofern alle Daten richtig eingegeben und alle Modifikationen korrekt durchgeführt wurden, meldet sich MPL mit der Meldung Optimal Solution Found zurück. Bei Identifizierung eines Syntaxfehlers ist die Eingabe des Modells nocheinmal zu überprüfen.

Da das Modell größer und größer wird, ist es eher praktikabel, nur bestimmte Teile der Lösung anzuschauen. Hier bietet sich es sich an, in einem Fenster die hierarchische Baumstruktur des Modells zu nutzen und nur die Teile der Lösung anzuschauen, die wirklich interessant sind.

MPL unterstützt die Visualisierung aller definierten Objekte eines Modells in einem hierarchischem Baum im sogenannten Modell-Definitions-Fenster. Jeder Zweig dieses Baumes entspricht einem Abschnitt des Modells. Allgemein scheint es ratsam, während der Arbeit mit MPL das Modell-Definitions-Fenster ständig geöffnet zu lassen. MPL aktualisiert dann ständig den Inhalt dieser Fenster. Um nun die Modelldefinitionen für das Planning5-Modells zu zeigen, wird Model Definitions aus dem View-Menu gewählt.

Das Modell-Definitions-Fenster für das Planning5-Modell

Aus dem Baum kann nun jedes beliebige Modellobjekt mit seinem zugehörigen einer genaueren Betrachtung unterzogen werden. Um zu Beispiel die Werte der Produktions-Variablen zu inspizieren, wird das Produce-Objekt im Baum gewählt und mit der View-Taste bestätigt. Dies erzeugt ein Fenster, dass die von Null verschiedenen Produktions-Variablen anzeigt.

     VARIABLE Produce[plant,product,month] :

       plant  product  month           Activity     Reduced Cost
      -----------------------------------------------------------
       p1     A1       Jan           4300.0000           0.0000
       p1     A1       Feb           4200.0000           0.0000
       p1     A1       Mar           6400.0000           0.0000
       p1     A1       Apr           5300.0000           0.0000
       p2     A2       Jan           4500.0000           0.0000
       p2     A2       Feb           5400.0000           0.0000
       p2     A2       Mar           6500.0000           0.0000
       p2     A2       Apr           7200.0000           0.0000
       p3     A3       Jan           5400.0000           0.0000
       p3     A3       Feb           6000.0000           0.0000
       p3     A3       Mar           6900.0000           0.0000
       p3     A3       Apr           6600.0000           0.0000
       p4     A3       Feb            700.0000           0.0000
       p4     A3       Mar            900.0000           0.0000
       p4     A3       Apr           1600.0000           0.0000
       -----------------------------------------------------------
      

Bei der Betrachtung der Produktions-Variable fällt auf, dass nun genug Produktionskapazität zur Verfügung steht, um alle Nachfragen zu befriedigen. Interessant ist auch zu sehen, wie der Solver entscheidet, welcher Standort für welches Produkt 'zuständig' ist. Zum Beispiel wird am p1 das Produkt A1, am Standort p2 das Produkt A2 und schliesslich an den Standorten p3 und p4 das Produkt A3 produziert.

Verwendet man das Modell-Definitions-Fenster nun, um die ProdCapacity-Bedingung genauer anzuschauen, so erhält man die folgenden Werte:

     CONSTRAINT ProdCapacity[plant,month] :

       plant  month              Slack     Shadow Price
      --------------------------------------------------
       p1     Jan             14.4000           0.0000
       p1     Feb             11.6000           0.0000
       p1     Mar             10.2000           0.0000
       p1     Apr             11.4000           0.0000
       p2     Feb              8.0000           0.0000
       p2     Mar              8.5556           0.0000
       p2     Apr              6.0000           0.0000
       p3     Jan              5.0000           0.0000
       p4     Jan             23.0000           0.0000
       p4     Feb             18.0000           0.0000
       p4     Mar             20.4286           0.0000
       p4     Apr             17.4286           0.0000
      --------------------------------------------------
     

Hier fällt auf, dass für alle Standorte und Monate die Werte der Schlupfvariablen anzeigen, dass noch erheblich mehr produziert werden kann; da bereits alle Nachfragen erfüllt sind, geschieht dies nicht. Zur Interpretation der Schlupfvariablen ist noch zu bemerken, dass diese, da die Produktionskapazitätsbeschränkung in Tagung spezifiziert sind, die Anzahl der freien Tage der einzelnen Standorte angeben.


Back To Top | Maximal Home Page | Overview | Previous Page | Next Page