English version Spanish version Italian version

Lektion 6: Einbeziehung von Transport zwischen den Produktionsstandorten

In Lektion wurden zwar schon mehrere Standorte mit eigener Produktion betrachtet, aber Verkauf und Lager wurden kollektiv behandelt. In dieser Lektion soll nun das Modell aus Lektion 5 so erweitert werden, dass jeder Standort seine Produktion und sein Lager selbst verwaltet. Zudem soll es möglich sein, die Produkte zwischen den Standorten bedarfsgerecht zu transportieren, wobei allerdings angenommen wird, dass die Transportzeiten klein im Vergleich zur Länge der Monatszeitscheiben sind und somit zu Null gesetzt werden.En la sesión 5, usted encontró un modelo para una compañía de producción.

Um dieses Ziel zu erreichen, werden zwei weitere sogenannte Alias-Indizes, toplant und fromplant eingeführt werden, die bei einem Transportvorgang den Ursprungs- und Zielstandort angeben. Da jeder Standort nun seine eigene Produktion und Lager verwaltet, müssen ausserdem die Lager- und Verkaufs-Variablen entsprechend angepasst werden, sodass sie vom plant-Index abhängen.


Neue Konzepte in dieser Lektion

Modelos de Transporte

Los Modelos que permiten embarques entre localizaciones son algunas veces llamados Modelos de Distribución o de Transporte. Normalmente, en modelos de transporte, usted tiene orígenes con cierta disponibilidad, destinos con ciertos requerimientos, y usted necesita embarcar los productos desde esos orígenes a esos destinos. En algunos casos, usted tiene modelos de transporte con multiples niveles. Por ejemplo, pueden haber embarques desde las plantas hacia los depósitos, y desde esos depósitos a las tiendas de ventas al por menor.

(Gerichtete) Transportmodelle

Modelle, die Transport zwischen verschiedenen Standorten erlauben, werden manchmal auch Transport- oder Distributions-Modelle genannt. In solchen Modellen werden typischerweise Quellen mit bestimmten Materialverfügbarkeiten und Bestimmungsorte mit bestimmten Nachfragen abgebildet, zwischen denen Produkte transport werden sollen. Hierbei können Transporte mehrstufig verknüpft sein. Beispielsweise soll ein Transport zunächst von einem Produktionsstandort zu einem Depot erfolgen und dann von einem solchen Depot zu einem Verteillager.

Ungerichtete Transportmodelle

Sind in einem Transportmodell keine spezifischen Quellen und Senken spezifiziert, d.h. jeder Standort kann sowohl Ware versenden als auch empfangen, so spricht man auch von ungerichteten Transportmodellen. Hierbei kann es im Extremfall vorkommen, dass von jedem beliebigen Standort ein Transport zu jedem anderen Standort erfolgen kann.

Alias-Indizes

Alias-Indizes finden Verwendung, wenn ein Vektor mehrfach vomselben Index abhängt. Sollen Produkte zwischen Standorten transport werden, so wird ein Variablenvektor benötigt, der diese Transportmengen als Entscheidungsvariablen repräsentiert. Da die Ausgangs- und Bestimmungsorte der Transportvorgänge Elemente derselben Menge, nämlich der Menge aller Standorte sind, werden hier zwei Alias-Indizes benötigt: einer für die Ursprungsorte und einer für die Bestimmungsorte.

Verwendung von Logischer Bedingungen auf Vektoren

Bei der Verwendung mehrdimensionaler Vektorvariablen tritt häufig der Fall auf, dass nicht alle Elemente des Vektors erlaubt oder eine sinnvolle Bedeutung haben. In einem ungerichteten Transportmodell ist es z.B. nicht sinnvoll, einen Transport von einem Standort zu sich selbst zuzulassen. In MPL können solche logische Bedingungen mit der Schlüsselwort WHERE modelliert werden. Damit kann die Erzeugung nicht sinnvoller Elemente und damit ein unötiges Anwachsen der Modellgröße vermieden werden.

Das folgende Beispiel zeigt, wie der Transport eines Standort zu sich selbst vermieden werden kann:

     VARIABLES
        Ship[fromplant,toplant] WHERE (fromplant <> toplant);
    

In diesem Beispiel eliminiert die Bedingung (fromplant <> toplant) alle Vektorelemente, bei denen Ausgangs- und Bestimmungsort identisch sind.

Logische Bedingung treten aber nicht nur in Verbindung mit Vektorvariablen auf und sind auch nicht unbedingt vom Index abhängig. Im Zusammenhang mit Datenvektoren kann z.B. der Transportkostenvektor für nicht erlaubte Transportwege auf den Wert Null gesetzt werden. Damit ist es dann möglich, bei der Definition der Transportvariablen unerlaubte Transportwege dadurch auszuschliessen, indem wie im folgenden Beispiel getestet wird, ob die Transportkosten Null sind:

     VARIABLES
        Ship[fromplant,toplant]
           WHERE (ShipCost[fromplant,toplant] > 0);
    

Transportbilanzgleichungen

Bei Transportmodellen, insbesondere den ungerichteten, ist für jeden Standort sicherzustellen, dass die Summe aus eingehenden Transportmengen, produzierter und aus dem Lager entnommener Menge gerade der Summe aus abgehender Transportmenge, verkaufter Menge und der Menge, die im Lager verbleibt, entspricht. In Kurzform bedeutet dies, dass die Menge der Eingangs- und Ausgangsströme gleich sind. Solche Bilanzgleichungen werden auch Massenerhaltungs- oder Transportbilanzgleichungen genannt. Nachfolgend dafür ein Beispiel:

      PlantBal[plant, product, month]:
         Produce + Inventory[month-1]
       + SUM(fromplant: Ship[fromplant, toplant:=plant])
     =
         Sales + Inventory
       + SUM(toplant: Ship[fromplant:=plant, toplant]);
    

Diese Bilanzgleichung hat natürlich ein ähnliche Form wie die Lagerbilanzgleichung in Lektion 5; sie enthält lediglich die zusätzlichen Terme für die Summen der ein- und ausgehenden Transportmengen.

Die Zuweisung 'toplant:=plant' im ersten Summanden definiert lokal und nur für die Bedingung PlantBal, die Indexmenge toplant als identisch mit der Indexmenge plant. Die Summe ergibt dann die Lieferung aller eingehenden Transportmengen in die betrachtete Anlage. Entsprechend ordnet die Zuweisung 'fromplant:=plant' in der Summe der Indexmenge fromplant die Elemente der Indexmenge plant zu.


Problembeschreibung: Einbeziehung von Transport zwischen den Produktionsstandorten

In dieser Lektion wird, aufbauend auf der Formulierung in Lektion 5, ein neues Modell erzeugt, in dem jeder Standort jetzt als separate Nachfragelokation mit eigenem Lager betrachtet wird.

Da nun jeder Standort nicht nur Produkte produzieren, sondern auch verkaufen kann, wird die Nachfrage, wie in der nachfolgenden Tabelle spezifiziert, als abhängig von Standort, Produkt und Monat aufgefasst:

Diese Daten hängen von den drei Dimensionen Standort, Produkt und Zeit (Monat) ab. Lineare Optimierungsmodelle enthalten häufig Daten und Strukturen, die von bis zu 8 Dimensionen abhängen dürfen. In der nächsten Lektion werden die Nachfragedaten nochmals um eine weitere Dimension, dem Anlagenindex, erweitert und somit zu einem vierdimensionalen Datenvektor.

Die Lagerkapazität ist nun auch für jeden Standort separat zu spezifizieren. Die Daten lauten hier: 800, 400, 500 und 400.

Weiterhin werden nun, da jeder Standort ein eigenes Lager unterhält, auch die Lagerkosten sowohl von Produkt als auch Standort abhängen. Die nachfolgende Tabelle spezifiziert diese:

Schließlich werden noch die mit dem Transport verbundenen Kosten benötigt:

Wie erwartet, enthält die Tabelle keine Transportkosten, in denen Ausgangs- und Bestimmungsort identisch sind. Dieser Fall könnte lediglich sinnvoll sein, wenn von Null verschiedene Transportzeiten betrachtet würden, da sich dann für eine kurze Zeit zusätzliche Lagerkapazität ergeben würde.


Formulierung des Problems in MPL

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

     TITLE
         Production_Planning6;

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


     DATA
         Price[product]                := (120.00, 100.00, 115.00);
         Demand[plant, product, month] := DATAFILE("Demand6.dat");
         ProdCost[plant, product]      := DATAFILE("ProdCost.dat");
         ProdRate[plant, product]      := DATAFILE("ProdRate.dat");
         ProdDaysAvail[month]          := (23, 20, 23, 22);
         InvtCost[plant, product]      := DATAFILE("InvtCost.dat");

         InvtCapacity[plant]           := (800, 400, 500, 400);
         ShipCost[fromplant, toplant]  := DATAFILE ("ShipCost.dat");

     VARIABLES
         Produce[plant, product,month]      -> Prod;
         Inventory[plant, product, month]   -> Invt;
         Sales[plant,product, month]        -> Sale;
         Ship[product, month, fromplant, toplant]
             WHERE (fromplant <> toplant);

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

     MODEL

         MAX Profit= TotalRevenue - TotalCost;

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

         PlantBal[plant, product, month] -> PBal:
               Produce + Inventory[month-1]
             + SUM(fromplant:Ship[fromplant, toplant:=plant])
            =
               Sales + Inventory
             + SUM(toplant: Ship[fromplant:=plant,toplant]);

         MaxInventory[plant, 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 Planning5.mpl aus der vorherigen Lektion.

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

Schritt 2: Ändern des Titels des Modells

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

     TITLE
        Production_Planning6;
    

Schritt 3: Hinzufügung eines Alias-Indexes für Ausgangs- und Bestimmungsstandorte

In dieser Lektion wird das Modell nun um den Transport zwischen den Standorten erweitert. Vektoren, in denen die Elemente einer Indexmenge mehrfach als Indizes auftreten, lassen sich nutzbringend mit sogenannten Alias-Indizes bzw. aktuellen Indizes konstruieren. Derartige Indexmengen sind exakte Kopien von bereits definierten Indenxmengen. In bestimmten Situation greifen sie aber nur das jeweilige, aktuelle Element einer Indexmenge heraus.

Zunächst soll nun eine Vektorvariable erzeugt werden, die beschreibt, wieviel zwischen zwei jeweiligen Standorten transportiert wird. Dazu sind zwei Alias-Indizes zu erzeugen, eine zur Beschreibung der Ausgangsstandorte und eine zur Darstellung der Bestimmungsorte. Am Ende des INDEX-Abschnittes sollen nun die beiden Alias-Indizes fromplant und toplant hinzugefügt werden:

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

Schritt 4: Aktualisierung des 'Demand'-Datenvektors und Erweiterung um den 'plant' Index

Da die Nachfrage jetzt auch vom Standort abhängt, muss der plant Index in den Demand-Datenvektor aufgenommen werden. Im Modelleditor wird der plant-Index nun zum Demand-Datenvektor hinzugefügt und der Dateiname zu Demand6.dat geändert.

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

Da der Demand-Vektor nun von drei Indizes abhängt, muss auch die Datei Demand.dat, die die Nachfragen enthält, aktualisiert werden. Dazu sind die folgenden Daten einzugeben:

     !
     ! Demand6.dat - Demand for each product and each plant
     !
     ! Demand[plant,product,month]:
     !
     !           Jan    Feb    Mar    Apr
     !          ---------------------------
     !plant 1:
                 4300,  4200,  6400,  5300,
                 4500,  5400,  6500,  7200,
                 5400,  6700,  7800,  8200,
     !plant 2:
                 5100,  6200,  5400,  7600,
                 6300,  7100,  5200,  6300,
                 4800,  6500,  5000,  7200,
     !plant 3:
                 4100,  6100,  4700,  5800,
                 5300,  5200,  5700,  4100,
                 4200,  4100,  5200,  6300,
     !plant 4:
                 4300,  4100,  5300,  4500,
                 5300,  6400,  4200,  6200,
                 5600,  5200,  3800,  4100
    

Bei dreidimensionalen Daten ist sorgfältig auf die Reihenfolge der Eingabe zu achten. Die Daten müssen in derselben Ordnung eingegeben werden, in der die Indizes definiert sind. Der Index, der am weitesten rechts (im Beispiel: month) in der Definiton steht, variiert am schnellsten; entsprechend der am weitesten links stehende (im Beispiel: plant) am langsamsten. Daraus resultiert in obiger Tabelle, dass in jeder Zeile alle Informationen für ein bestimmtes Produkt an einem bestimmten Standort stehen.

Schritt 5: Aktualisierung des 'InvtCost'-Datenvektors und der 'InvtCapacity'-Datenkonstante

Wegen der Standortabhängigkeit der Läger wird nun der plant-Index zur Deklaration des InvtCost-Datenvektors und der InvtCapacity-Datenkonstante hinzugefügt. Die Daten, die für den InvtCost-Datenvektor definiert wurden, werden entfernt und durch das Schlüsselwort DATAFILE und den Dateinamen 'InvtCost.dat.' ersetzt. Der Wert 800, der der Datenkonstante zugeordnet wurde, wird durch eine Liste von vier Werten, ein jeder für einen der vier Standorte, ersetzt.

     InvtCost[<b>plant</b>, product] := <b>DATAFILE(&quot;InvtCost.dat&quot;)</b>;
     InvtCapacity<b>[plant]</b>      := <b>(800, 400, 500, 400)</b>;

Danach ist die neue Datei 'InvtCost.dat' zu erzeugen; sie enthält die Lagerkosten, wie sie in der Problembeschreibung spezifiziert wurden:

      !
      ! InvtCost.dat - Inventory cost per item a month
      !
      ! InvtCost[plant,product]:
      !
      !         A1    A2    A3
      !     -----------------------
               8.50,  7.00, 6.50
               9.80,  9.80, 9.80
               7.50,  7.50, 7.50
               9.30,  8.00, 6.50
      

Schritt 6: Hinzufügung der Transportkosten

Zur Definition der Transportkosten wird im Modelleditor der neue Datenvektor ShipCost über die beiden Alias-Indizes fromplant und toplant definiert und über das Schlüsselwort DATAFILE mit der Datei ShipCost.dat verknüpft.

     ShipCost[fromplant, toplant] := DATAFILE("ShipCost.dat");
    

Dazu ist nun natürlich noch die Datei ShipCost.dat mit den entsprechenden Daten zu erzeugen:

     !
     ! ShipCost.dat - Costos de embarque de planta a planta
     !
     ! ShipCost[fromplant, toplant]
     !
                0, 15.00, 21.00, 13.00,
            16.00,     0, 12.00, 12.00,
            14.00, 17.00,     0, 15.00,
            21.00, 13.00, 10.00,     0,
     

Schritt 7: Hinzufügung des Variablenvektors für den Transport

Die Transportmengen sollen durch den Variablenvektor Ship repräsentiert werden. Dieser Variablenvektor hängt von den Alias-Indizes fromplant und toplant sowie von Indizes product und month ab. Seine Definition erfolgt wie folgt im Abschnitt VARIABLES:

     Ship[product, month, fromplant, toplant]
        WHERE (fromplant <> toplant);
    

Da der Transport eines Produktes von einem Ausgangsort zu sich selbst ausgeschlossen werden soll, werden in der Definition mit Hilfe des WHERE-Schlüsselwortes die entsprechenden Vektorelemente ausgeschlossen.

Schritt 8: Hinzufügung der Transportkosten zur Zielfunktion

Im MACROS-Abschnitt wird der zusätzliche Makro TotalShipCost definiert und der existierende Makro TotalCost enstprechend aktualisiert:

      TotalShipCost := SUM(product, month, fromplant, toplant: ShipCost * Ship);
      TotalCost     := TotalProdCost + TotalInvtCost + TotalShipCost;
    

Die Zielfunktion selbst braucht nicht geändert zu werden, da der Makro TotalCost bereits alle Änderungen enthält.

Schritt 9: Erweiterung der Lagerbilanzgleichung zu einer Standortbilanzgleichung durch Berücksichtigung des Transports

Die existierenden Lagerbilanzgleichungen sind nun um die ein- und ausgehenden Transportmengen zu erweitern und werden damit zu Standortbilanzgleichungen. Deshalb wird zunächst der Name InvtBal in PlantBal umgeändert und der Index plant zur Deklaration hinzugefügt. Da nun die Nebenbedingung selbst vom plant-Index abhängt, braucht in der Summe der Produce-Variablen nicht mehr über den plant-Index summiert zu werden.

     PlantBal[plant, product, month] -> PBal:

               Produce + Inventory[month-1]
             + SUM (fromplant:Ship[fromplant, toplant:=plant])
           =
               Sales + Inventory
             + SUM(toplant: Ship[fromplant:=plant, toplant]);
    

Auf der linken Seite dieser Bilanzgleichung sind die Massenströme berücksichtigt, die in den Standort einfliessen, also die eingehenden Transportmengen sowie das, was neu produziert wird. Zu beachten ist, dass das die Summe alle möglichen Ausgangsorte berücksichtigt, die den aktuellen Standort beliefern können. Als Bestimmungsort wird im Argument der Ship-Variable mit Hilfe des Alias-Indexes toplant der aktuelle Standort, d.h. das aktuelle Element der Indexmenge plant gewählt.

Auf der rechten Seite der Bilanzgleichung sind die abfliessenden Materialströme zusammengefasst. Diesmal spielt im Argument der Ship-Variablen der aktuelle Standort die Rolle des aktuellen Indexes.


Lösung des Problems und Analyse der Lösung

Der nächste Schritt besteht darin, das durch 'Planning6.mpl' kodierte Problem zu lösen. 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.

Wie schon in Lektion 5, sollen mit Hilfe des Modelldefinitionsfensters lediglich die hier interessierenden Aspekte der Lösung angezeigt werden. Dazu wird für das Planning6-Modell Model Definitions aus dem View-Menu gewählt.

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

Um 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.0              0.0
        p1     A1       Feb              4200.0              0.0
        p1     A1       Mar              6400.0              0.0
        p1     A1       Apr              5300.0              0.0
        p1     A2       Jan              1080.0              0.0
        p1     A3       Jan              5400.0              0.0
        p1     A3       Feb              5220.0              0.0
        p1     A3       Mar              4590.0              0.0
        p1     A3       Apr              5130.0              0.0
        p2     A1       Jan              5100.0              0.0
        p2     A1       Feb              6200.0              0.0
        p2     A1       Mar              5400.0              0.0
        p2     A1       Apr              7600.0              0.0
        p2     A2       Jan              6177.3              0.0
        p2     A2       Feb              3927.3              0.0
        p2     A2       Mar              5931.8              0.0
        p2     A2       Apr              3681.8              0.0
        p3     A1       Jan              4100.0              0.0
        p3     A1       Feb              6100.0              0.0
        p3     A1       Mar              4700.0              0.0
        p3     A1       Apr              5800.0              0.0
        p3     A3       Jan              4166.7              0.0
        p3     A3       Feb              1933.3              0.0
        p3     A3       Mar              3766.7              0.0
        p3     A3       Apr              2733.3              0.0
        p4     A1       Jan              3850.0              0.0
        p4     A1       Feb              2828.6              0.0
        p4     A1       Mar              5300.0              0.0
        p4     A1       Apr              4500.0              0.0
        p4     A3       Jan              5600.0              0.0
        p4     A3       Feb              5200.0              0.0
        p4     A3       Mar              4677.3              0.0
        p4     A3       Apr              4836.4              0.0
       -----------------------------------------------------------
     

Man bemerkt nun, dass die Produktion zwischen den einzelnen Standorten effizienter verteilt ist. Einige Produkte werden unter Berücksichtigung der Produktions- und Transportkosten sinnvollerweise an bestimmten Standorten produziert. So wird z.B. das Produkt A2 an den Standorten p1 und p2 produziert, nicht aber in p3 und p4, während das Produkt A3 an den Standorten p1, p3 und p4 produziert wird. Produkt A1 wird an allen Standorten produziert.

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

     VARIABLE Ship[product,month,fromplant,toplant] :

        product  month  fromplant  toplant           Activity     Reduced Cost
       ------------------------------------------------------------------------
        A2       Mar    p2         p4                  331.8              0.0
        A3       Mar    p4         p3                  877.3              0.0
        A3       Apr    p4         p3                  736.4              0.0
       ------------------------------------------------------------------------
      

Hier sehen wir den Vorschlag, Produkt A2 vom Standort p2 zum Standort p4 sowie Produkt A3 von p4 nach p3 zu transportieren. Offensichtlich bieten die Standorte p2 und p4 zusätzliche Kapazitäten zu niedrigeren Kosten; diese Kapazitäten werden genutzt, um die Nachfragen der Standorte p4 und p3 zu bedienen.


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