1 Graphen und Netze als Planungsmodelle von: Prof. Dr. rer. nat. habil. Günter Nägler 2 Vorwort Dieses Buch zielt auf die Verbreitung der Kenntnisse über graphische Modelle der Operation Research, die bei Planungsaufgaben genutzt werden. Es geht einerseits um Planungsaufgaben, die in der Nähe der klassischen Transportkostenoptimierung liegen und andererseits um das Gebiet Netzplantechnik. Mathematisch gesehen stehen damit einerseits die Stromoptimierung auf Graphen – Transportmodelle – und andererseits die Spannungsoptimierung auf Graphen – Netzplantechnik – im Blickfeld. Für beide Aufgabenklassen gibt es sehr effiziente und leicht beherrschbare Bearbeitungsalgorithmen. Dem Autor geht es darum, Kenntnisse über von ihm bearbeitete Erweiterungen dieses als klassisch zu bezeichnenden Instrumentariums zu verbreiten – Erweiterungen durch die Möglichkeit, Bogen zu kopppeln, d.h. von ihren Strom- bzw. Spannungskomponenten die Einhaltung vorgegebener Proportionen zu fordern. Diese Möglichkeit gibt dem Modellierer praktischer Aufgaben ein stark erweitertes Instrument in die Hand, für das der Rechenvorteil und die Übersicht über den Rechenverlauf von Optimierungen zwar sinkt, das aber gegenüber Verfahren, die sich auf Matrizen stützen (lineare Optimierung) in der Regel vorteihaft bleibt. Im Kapitel 6, Optimierung des Ressourceneinsatzes in Netzplänen, wird ein Modell betrachtet, das sogar Strom- und Spannungsaufgaben durch Kopplung verbindet, d.h. vom Fluss durch den Bogen eines Netzes wird gefordert, dass er zur Spannung in einem Bogen eines anderen Netzes eine vorgegebene Proportion einhält. Mit diesem Modell wird eine lokale Optimierung klasischer Ressourceneinsatzaufgaben aufgebaut, die zur heuristischen Bearbeitung dieser NP-hard-Probleme genutzt wird. Obwohl die im Buch vorgelegten Problemlösungen relativ alt sind, sind sie nach Meinung des Autors noch wenig bekannt, weshalb diese Publikation Abhilfe schaffen will. Die folgenden Ausführungen decken sich teilweise stark mit Darlegungen des Autors in [Nä/St]. Diese Übernahme dient dem geschlossenen Überblick über die gezeigten Methoden und soll insbesondere die Leichtigkeit demonstrieren, mit der man mit ihnen auch komplexere Aufgaben lösen kann. Im Kapitel 1 wird das benutzte Instrumentarium der Graphentheorie zusammengestellt, wobei, im Gegensatz zur üblichen Darstellung, konsequent der gerichtete Graph und die Basisdarstellung von Strömen und Spannungen über Gerüste und Cogerüste in den Vordergrund gerückt werden. Ferner wird mit Blick auf programmierbare Algorithmen, ein Modell der Bearbeitung im Computer durch Vorgabe geeigneter Objektklassen vorgestellt, dass in den weiteren Kapiteln ausgebaut wird. Es sei an dieser Stelle vermerkt, dass der Autor gleizeitig zwei Programmpakete (Transportprogramm und Netzplanprogramm) offen legt, die dieses Softwareinstrumentarium ausbauen. Alle im folgenden Text vorgestellten Algorithmen und einige weitere sind in einem dieser Programme im Java-Quellcode zu finden. Das Programm „Transportprogramm“ wurde im Rahmen der Diplomarbeit [Sch], gestützt auf Vorlagen aus der Lehre des Autors, erarbeitet. Kapitel 2 beschäftigt sich mit gut bekannten einfachen Netzwerkalgorithmen zur Suche nach kürzesten bzw. längsten Wegen und Minimalgerüsten. Kapitel 3 ist der Minimalkosten-Stromoptimierung also der klassischen Transportkostenoptimierung und der analogen Minimalkosten-Spannungsoptimierung gewidmet und wirft auch einen Blick auf so genannte Tourenprobleme. Die Minimalkosten-Spannungsaufgabe wird genutzt, um die Aufgabe der kostenminimalen Kürzung des kritischen Weges in klassischen Netzplänen zu bearbeiten (Aufgabe von Kelley [1]). Kapitel 4 beschäftigt sich mit der oben genannten Kopplung von Flüssen bei Stromoptimierungsaufgaben. Sie wird über Anwendungsmodelle eingeführt und motiviert und im Anschluss theoretisch und algorithmisch behandelt. Kapitel 5 führt in die Netzplantechnik ein, wobei die klassischen Grundlagen nur knapp behandelt werden, vielmehr ein allgemeineres Modell eingeführt wird, dass nach dem Wissen des Autors heute nur noch wenig genutzt wird (Es wurde um 1965 in der DDR vom Autor und seinem Team entwickelt.), obwohl es für praktische Aufgaben starke Modellierungsmöglichkeiten bietet. Dieses Modell beruht mathematisch auf der Spannungsoptimierung mit Bogenkopplungen – analog zur Stromaufgabe – und es mag durchaus sein, dass die geringe Verbreitung des Wissens über deren Bearbeitung Ursache der geringen Verbreitung des leistungsstarken Modells ist. Der mathematische 3 Hintergrund des Modells, die Spannunggsaufgabe mit Bogenkopplung, wird im Kapitel als Analogon zur Stromaufgabe behandelt und gelöst und zur Bearbeitung der Projekt-Dauer-Kosten-Optimierung genutzt – eine Aufgabe, die einerseits als Verallgemeinerung der im Kapitel 3 behandelten Kürzung des kritischen Weges im klassischen Netzplan anzusehen ist, andererseits die Basisrechnung für das verallgemeinerte Netzplanmodell darstellt. Kapitel 6 schließlich – als Höhepunkt – widmet sich Aufgaben der Ressourceneinsatzoptimierung in dem genannten allgemeinen Netzplanmodell. 4 Inhaltsverzeichnis 1. 1.1 1.2 1.3 1.4 Grundbegriffe der Graphentheorie 6 Definition des Graphen…………………………………………………………………….6 Die Datenstruktur Graph…………………………………………………………………...8 Weitere Grundbegriffe der Graphentheorie..……………………………………………..10 Erreichbarkeit, Zusammenhang, Kreisfreiheit……………………………………………19 2. 2.1 2.2 2.3 Einfache Netzaufgaben 25 Suche nach kürzesten Wegen………………………………………………….………… 25 Suche nach längsten Wegen………………………………………………………………31 Minimalgerüste……………………………………………………………………………35 3. 3.1 3.2 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 Minimalkosten-Strom- und Spannungsoptimierung 36 Einfache Transportkosten-Minimierung…………………………………………………. 36 Ergänzung der theoretischen Grundlagen………………………………………………... 40 Ströme und Spannungen…………………………………………………………………. 40 Lösbarkeit des Minimalkosten-Stromproblems………………………………………….. 42 Grundlagen des Lösungsalgorithmus für das Minimalkosten-Stromproblem…………… 43 Gleichgewichts-Algorithmus zur Lösung des Minimalkosten-Stromproblems………......46 Anwendungsbeispiel Tourenproblem…………………………………………………..... 55 3.2.6 Das Minimalkosten-Stromproblem mit einem freien Parameter………………….57 3.3 3.3.1 3.3.2 Das Minimalkosten-Spannungsproblem………………………………………………..... 64 Grundlagen………………………………………………………………………………..64 Gleichgewichts-Algorithmus zur Lösung des Problems der Kürzung des kritischen Wegs…………………………………………………………………………...66 4. 4.1 4.2 Minimalkosten-Stromproblem mit gekoppelten Flüssen 74 Motivierung und Aufgabenstellung……………………………………………………… 74 Theoretische Grundlagen für die Lösung des Minimalkosten-Stromproblems mit Kopplungen………………………………………………………………………………. 79 4.3 Ein Lösungsalgorithmus für das Minimalkosten-Stromproblem mit Kopplungen (MKSK)…………………………………………………………………………………... 81 4.3.1 Algorithmus zur Bestimmung eines Gerüsts zur Startlösung x = 0 und des zugehörigen Potentials…………………………………………………………………….81 4.3.2 Gleichgewicht für den Out-of-Kilter-Bogen……………………………………………... 83 4.3.3 Softwaretechnische Realisierung des Algorithmus………………………………………. 87 4.3.4 Beispiele für das Minimalkosten-Stromproblem mit Kopplungen………………………. 88 4.3.4.1 Ein Zahlenbeispiel für die zeitabhängige Produktionsmengenplanungen……………….. 88 4.3.3.2 Das Knappsackproblem als Minimalkosten-Stromproblem mit Kopplungen…………… 91 4.4 Das Mehrsorten-Stromproblem…………………………………………………………... 95 5 5.1 Netzplantechnik 98 Einfache Netzplanmodelle………………………………………………………………...98 5.2 Erweitertes Netzplanmodell……………………………………………………...101 5.2.1 Grundlagen……………………………………………………………………….101 5.2.2 Umsetzung des Netzplans in ein Modell des Minimalkosten-Potentialproblems...105 5.3 5.3.1 5.3.2 5.3.3 Ein Lösungsalgorithmus für das Netzplan-Minimalkosten-Potentialproblem (NMKP)....108 Basislösung……………………………………………………………………………….108 Ermittlung einer Startlösung……………………………………………………………...111 Die Prozedur „Gleichgewicht“…………………………………………………………....112 5 5.4 Projekt-Kosten in Abhängigkeit von der Projektdauer………………………………….117 6 6.1 6.1.1 6.1.2 6.2 6.2.1 6.2.2 6.2.3 Planung des Ressourceneinsatzes in Arbeitsabläufen 125 Grundlagen……………………………………………….………………………………125 Verbrauchsressourcen………..…………………………………………………………...125 Erneuerbare Ressourcen………………………………………………………………….125 Kostenminimierung zeitabhängiger Ressourcenströme………………………………….128 Einführung………………………………………………………………………………..128 Kostenminimierung des Ressourceneinsatzes – ein heuristischer Lösungsalgorithmus…135 Rechentechnische Realisierung…………………………………………………………..141 Literatur ………………………………………………………………………………………….145 Sachwortverzeichnis………………………………………………………………………………146 Kapitel 1: Grundbegriffe der Graphentheorie 6 1 Grundbegriffe der Graphentheorie 1.1 Definition des Graphen Unsere Vorstellung von einem Graphen ist die eines gezeichneten Gebildes aus Knoten, die durch Linien oder Pfeile verbunden sind. A B B B A D D C C Bild 1.1: Zwei isomorphe Graphen (Sie veranschaulichen dieselbe Struktur.) Die Knoten modellieren Objekte der Realität, die Verbindungen zwischen den Knoten modellieren strukturelle Beziehungen zwischen den Objekten. Als Modell der Verbindung zwischen zwei Knoten Kn und Kn’ wählen wir das geordnete Knotenpaar [Kn, Kn']. Kn Kn’ Bild 1.2: Ein Pfeil, genannt „Bogen“, veranschaulicht ein geordnetes Knotenpaar. Betrachten wir eine Menge solcher Paare, so müssen diese unterscheidbar, also paarweise verschieden sein. Bei Anwendungen von Graphen z.B. zur Modellierung von Straßennetzen ist es jedoch häufig sinnvoll, mehrere gleiche, parallele Verbindungen zu betrachten. Das erreichen wir, wenn wir statt einer Menge eine geordnete Menge / Tupel / Liste heranziehen. Definition G = [K, B] heißt endlicher g e r i c h t e t e r G r a p h, wenn K eine endliche Liste gleichartiger aber paarweise verschiedener Objekte – so genannter Knoten – ist und B eine Liste geordneter Paare von Elementen aus K – so genannter Bogen. K = [Kn1, Kn2, ... , Knn] heißt K n o t e n l i s t e des Graphen. B = [Bg1, Bg2, ... , Bgm] heißt B o g e n l i s t e des Graphen Ist Bg = [Kn, Kn'] ein Knotenpaar aus B, so nennen wir • Kn den A n f a n g s k n o t e n des Bogens Bg (Kn = AKn(Bg)), • Kn' den E n d k n o t e n des Bogens Bg (Kn' = EKn(Bg)), • Kn, Kn' a d j a z e n t e ( verbundene ) K n o t e n, • Bg E i n g a n g s b o g e n von Kn' und A u s g a n g s b o g e n von Kn und • schließlich Bg i n z i d e n t sowohl mit Kn als auch mit Kn'. m = |B| , n = |K| Sind Bg, Bg‘ ∈ B zwei verschiedene Elemente der Bogenliste, aber es gilt, Bg = [Kn, Kn‘] und Bg‘ = [Kn, Kn‘], so nennen wir Bg und Bg‘ zueinander parallele Bogen. Ein Graph ohne parallele Bogen heißt schlicht. Kapitel 1: Grundbegriffe der Graphentheorie 7 Ein schlichter gerichteter Graph wird auch als Digraph bezeichnet (von dem englischen „directed graph“). Er ist eine Veranschaulichung des wichtigen mathematischen Begriffs der Relation, genauer, einer zweistelligen Relation B in der Menge K, B ⊆ K × K. Parallele Bogen sind zu unterscheiden von Gegenbogen. Gilt Bg = [Kn, Kn'] und Bg' = [Kn', Kn], so heißt Bg Gegenbogen von Bg' und natürlich auch Bg' Gegenbogen von Bg. Ein Paar von Bogen, die zueinander Gegenbogen sind, wollen wir als Kante des Graphen bezeichnen, durch (Kn, Kn') = (Kn', Kn) symbolisieren und durch eine ungerichtete Linienverbindung zwischen den Knoten Kn und Kn' graphisch veranschaulichen. Ist ein Graph vollständig symmetrisch, d.h. existiert zu jedem seiner Bogen auch der Gegenbogen, so heißt er ungerichteter Graph. Der ungerichtete Graph wird im Allgemeinen nur durch Kanten veranschaulicht. Er ist in der hier vertretenen Auffassung ein Spezialfall des gerichteten Graphen. Ein ungerichteter Graph ist in gleicher Weise Verallgemeinerung der symmetrischen Relation wie es der gerichtete hinsichtlich der beliebigen Relation ist. Beispiel Stellen wir uns einen Graphen als Straßennetz vor, so entspricht einem Knoten eine Straßenkreuzung, einem Bogen eine Einbahnstraße mit einer Fahrspur, parallelen Bogen entsprechen Einbahnstraßen mit mehreren Fahrspuren, Kanten entsprechen Straßen mit je einer Fahrspur in jeder Fahrtrichtung, und parallelen Kanten entsprechen Straßen mit mehreren Fahrspuren (gleiche Anzahl) in jeder Fahrtrichtung. Eine Straße mit zwei Fahrspuren in der einen Richtung und drei Fahrspuren in der Gegenrichtung könnte durch zwei parallele Kanten und einen zusätzlichen Bogen in der Gegenrichtung dargestellt werden. Ein Bogen Bg mit AK(Bg) = EK(Bg) wird als Schlinge bezeichnet. Wir werden im Allgemeinen schlingenfreie Graphen betrachten. Die Menge der Eingangsbogen eines Knotens Kn wollen wir durch EBg(Kn) und die Menge der Ausgangsbogen mit ABg(Kn) bezeichnen. EBg(Kn) ∪ ABg(Kn) ist die Menge aller Bogen, die mit dem Knoten Kn inzident sind. Ihre Notation wollen wir durch InzBg(Kn) = (-EBg(Kn)) ∪ ABg(Kn) festlegen. Dabei soll -EBg(Kn) bedeuten, dass alle Bogennummern dieser Menge mit dem Minuszeichen versehen werden, wodurch die Eingangsbogen von den Ausgangsbogen unterschieden werden können. Diese Festlegung wird noch sinnvoller, wenn wir die Abbildungen AK(Bg) und EK(Bg) wie folgt erweitern: Definition AKn(-Bg) = EKn(Bg), EKn(-Bg) = AKn(Bg), Bg ∈ B. Mit dieser Erweiterung führen wir negative Bogenbenennungen ein: Für Bg ∈ B bezeichnet -Bg weiterhin den Bogen Bg, aber das Minuszeichen symbolisiert eine andere Durchlaufrichtung durch den Bogen oder eine Orientierung in Bezug auf andere Bogen einer Bogenmenge. • Die Anfangsknoten der Bogen aus EBg(Kn) wollen wir als linke Nachbarknoten des Knotens Kn bezeichnen. • Entsprechend sind die Endknoten der Bogen aus ABg(Kn) rechte Nachbarknoten des Knotens Kn, • und alle Knoten, die mit Bogen aus InzBg(Kn) inzident und verschieden von Kn sind, also alle direkten Vorgänger und Nachfolger von Kn, mögen Nachbarknoten des Knotens Kn heißen. Mit der getroffenen Vorzeichenfestlegung gilt: Für Bg ∈ InzBg(Kn) ist EK(Bg) ein Nachbarknoten von Kn. 8 Kapitel 1: Grundbegriffe der Graphentheorie 1.2 Die Datenstruktur Graph Die Bearbeitung praktischer Aufgaben in einem Graphen führt sehr schnell in Größenordnungen, die ohne Computer kaum zu bewältigen sind. Wir wollen folglich Algorithmen erarbeiten, die es dem Computer ermöglichen, praktische Aufgaben, wie z.B. die Suche nach kürzesten Wegen, effizient zu bearbeiten. Dabei wollen wir • einen Knoten mit seiner Nummer/Index i in der Liste aller Knoten, der Knotenliste, ansprechen, 1 ≤ i ≤ n. • einen Bogen mit ±k ansprechen, wobei k seine Nummer/Index in der Liste aller Bogen, der Bogenliste, ist, 1 ≤ k ≤ m. maxKnAnz und maxBgAnz mögen die vereinbarten Größen der Listen für Knoten bzw. Bogen bezeichnen, also die maximal mögliche Knoten- bzw. Bogenanzahl angeben. Den Ersatz der Knoten- bzw. Bogenbezeichnung durch den Index in der Knoten- bzw. Bogenliste wollen wir im Folgenden allgemein vornehmen. Grundvoraussetzung für eine effiziente Arbeit mit Graphen im Computer ist 1. für jeden Bogen ein schneller Zugriff auf die durch ihn verbundenen Knoten und 2. für jeden Knoten ein schneller Zugriff auf die mit ihm inzidenten Bogen bzw. auf seine Nachbarn. Da wir erstens kein volles Listeninstrumentarium brauchen und zweitens mit vorzeichenbehafteten Bogennummern arbeiten, werden wir die folgende Datenstruktur Graph (G)auf spezielle Arraylisten abstützen. Mit den oben eingeführten Mengen EBg(i) bzw. ABg(i) bzw. InzBg(i) wollen wie mit Listen arbeiten, wozu die Methoden G.eEBg(i), G.nEBg(k); G.eABg(i), G.nABg(k); G.eInzBg(i), G.nInzBg(k) sowie G.istBg(k) dienen. (e steht für erster …, n für nächster …) Die Methoden G.eEBg(i), G.eABg(i) und G.eInzBg(i) liefern ein erstes Element k der jeweiligen Bogenmenge, und G.nEBg(i, k), G.nABg(i, k) bzw. G.nInzBg(k) liefern ein von k verschiedenes nächstes Element. Wurden alle Elemente der entsprechenden Menge aufgezählt, so mögen die Nächstes-Element-Methoden einen Wert liefern, z.B. den Wert 0, der es der Methode G.istBg(k) gestattet, auf false zu entscheiden. G.istBg(i) ist also weniger als Methode zu verstehen, die entscheidet, ob eine Variable k vom IntegerTyp als Bogenbenennung gültig ist oder nicht, sondern ihre Aufgabe besteht vor allem darin, zu entscheiden, ob ein Schleifendurchlauf durch eine Bogenmenge beendet ist oder nicht. Vorerst geben wir der Datenstruktur Graph den folgenden Inhalt, den wir später weiter ergänzen werden: public class Graph { int maxKnAnz; int maxBgAnz; Knoten[] Knotenliste; Bogen[] Bogenliste; public int n; public int m; public int WrzBg; public Graph(int maxKnAnz, int maxBgAnz) { this.maxKnAnz = maxKnAnz; this.maxBgAnz = maxBgAnz; WrzBg=maxBgAnz+1; Knotenliste = new Knoten[maxKnAnz]; Bogenliste = new Bogen[maxBgAnz]; // - erzeugt einen leeren Graphen } public void insertBg(String von, String nach){ // - fügt einen neuen Bogen in den Graphen ein, der vom // Knoten von (äußere Bez.) zum Knoten // nach (äußere Bez.) führt. } public boolean istKn(int i) { } public boolean istBg(int k) { } public int AKn(int k) {} // Testfunktion für eine Knotennummer // Testfunktion für eine Bogennummer // Anfangsknoten des Bogens k Kapitel 1: Grundbegriffe der Graphentheorie public public public public public public public public public public int int int int int int int void int void public int public void public boolean public void public void public void public int public void public int public void 9 // Endknoten des Bogens k // - ein erster Eingangsbogen des Knotens i // - der nach k nächste Eingangsbogen des Knotens i // - ein erster Eingangsbogen des Knotens i // - der nach k nächste Ausgangsbogen des Knotens i // - ein erster mit Knoten i inzidenter Bogen // - der nach k nächste mit i inzidente Bogen // - setzt Bogen k beim Knoten i als Stützbogen ein // - gibt den Stützbogen des Knoten i an // - initialisiert die Stützbogenangaben: // m+1 beim Knoten start und // 0 sonst StzRchtg(int k) {} // = -1, wenn getStzBg(EKn(k)) = -k // = 1, wenn getStzBg(EKn(k)) = k // = 0, sonst setzWrz(int i) {} // - versetzt die Wurzel des Gerüsts in den Knoten i istWrz(int i) {} // Testfunktion für die Wurzeleigenschaft eines Knotens tauschStzBg(int kAlt, int kNeu) {} // - tauscht einen Gerüstbogen kAlt gegen // einen Bogen kNeu aus cz(kAlt) initMarke(int Wert) {} // - initialisiert eine Knoten-Markierungsfunktion setMarke(int i, int k) {} // - setzt k als Wert der Markierungsfunktion beim Knoten i getMarke(int i) {} // - gibt den Wert der Markierungsfunktion beim Knoten i markCZ(int k) {} // - setzt die Werte der Markierungsfunktion aller mit // AKn(i) über das Gerüst zusammenhängenden Knoten auf EKn(int k) {} eEinBg(int i) {} nEinBg(int i, int k) {} eAusBg(int i) {} nAusBg(int i, int k) {} eInzBg(int i) {} nInzBg(int i, int k) {} setStzBg(int i, int k) {} getStzBg(int i) {} initStzBg(int start) {} // 1, die Werte aller übrigen Knoten auf 2 czKoeff(int k) {} // = -1, wenn -k ∈ des markierten Cozyklus ist // = 1, wenn k ∈ des markierten Cozyklus ist // = 0, sonst setX(int k, double x) {} // - setzt x als Wert der Komponente des Vektors x des // Bogens k G.insertBg(von, nach) dient dazu, einen Bogen, der die Knoten mit den äußeren Bezeichnungen von und nach verbindet, in den Graphen einzufügen. Die Methode sucht die Knotennamen von und nach in der Knotenliste und fügt sie in diese ein, falls sie noch nicht existieren. Mit den Nummern, die in der Knotenliste zu diesem Namen gehören, fügt die Methode den Bogen dann so in die Bogenliste ein, dass alle weiteren Methoden funktionieren. Beispiel Einen Durchlauf durch die Bogenmenge EBg(i), bei dem auf jeden Bogen k ∈ EBg(i) eine Operation bearbeite(k) angewandt wird, müsste wie folgt implementiert werden: k = G.eEBg; while (G.istBg(k)) { bearbeite(k); k = G.nEBg(i, k) } Im angegeben Konstruktor des Graphen treten die Datentypen Knoten und Bogen als Elementtypen der Knoten- bzw. der Bogenliste auf. Der Knoten-Typ ist ein Datensatztyp, der die äußere Bezeichnung des Knotens enthält und dazu zwei Adressen, AusBg, EinBg, der Bogenliste, nämlich die Nummern der ersten Bogen, deren Anfangs- bzw. Endknoten der betrachtete Knoten ist. public class Knoten { public String name=new String(); int EinBg=0, AusBg=0, StzBg=0, Marke=0; double t=0, dt =0; Knoten(String name) { this.name=name; } } Im Bogen-Typ-Datensatz werden dann umgekehrt Anfangs- und Endknoten des Bogens als Adressen der Knotenliste (Typ int) genannt. Neben diesen Adressen enthält er Adressen, nEinBg, nAusBg, mit 10 Kapitel 1: Grundbegriffe der Graphentheorie denen man den Zugriff auf die Eingangsbogen des Endknotens des betrachteten Bogens bzw. zu den Ausgangsbogen seines Anfangsknotens fortsetzen kann. Der Anfang für die Aufzählung dieser Mengen ist durch die Adressen AusBg bzw. EinBg gegeben, die im Knotensatz abgelegt sind. public class Bogen { int AKn = 0, EKn = 0, nEinBg = 0, nAusBg = 0; double x=0; double dx = 0; Bogen(int AKn, int EKn) { this.AKn = AKn; this.EKn = EKn; } } k1 = Knotenliste[i].EinBg i EinBg k2 = Bogenliste[k1].nEinBg k3 = Bogenliste[k2].nEinBg Bild 1.3: Veranschaulichung der Technik des Zugriffs auf Bogen, die zum Knoten i inzident sind, 1.3 Weitere Grundbegriffe der Graphentheorie Definition Eine Folge paarweise verschiedener Bogenbenennungen [k1, k2, ..., kr] heißt K e t t e, wenn für i = 1, 2, ..., r –1 AKn(ki+1) = EKn(ki) gilt. Sind alle ki einer Kette positiv, so wird sie als W e g bezeichnet. Ist jeder Knoten einer Kette mit höchstens zwei ihrer Bogen inzident, so heißt die Kette elementar. Gilt für eine Kette AKn(k1) = EKn(kr), so heißt sie g e s c h l o s s e n oder Z y k l u s. Ein geschlossener Weg wird K r e i s genannt. Die Notation einer Kette beschreibt einen Durchlauf durch die zugehörige Bogenfolge: Beginnend beim Knoten AKn(k1) läuft man zum Knoten EKn(k1), der identisch mit AKn(k2) ist. Von AKn(k2) läuft man zum Knoten EKn(k2) usw. Man durchläuft also die angesprochenen Bogen in ihrer Pfeilrichtung oder gegen diese, je nachdem ob die Bogennummer positiv oder negativ genannt ist. 4 Kn2 Kn5 1 10 7 Kn1 9 8 Kn7 2 11 3 12 Kn4 5 Kn3 Bild 1.4: Ketten, Wege, Kreise 6 Kn6 Kapitel 1: Grundbegriffe der Graphentheorie 11 Beispiel Wir betrachten den im Bild 1.4 gezeigten Graphen: Die Bogenfolgen Kt1 = [1, -7, -12, 11], Kt2 = [3, 5, 8, 9, 11] und Kt3 = [5, 7, 4, -8, -12, 11] bezeichnen Ketten. Kt1 und Kt2 sind elementar; Kt3 ist nicht elementar; Kt2 ist ein Weg. Die Folgen Kt4 = [1, -7, -5, -3], Kt5 = [8, 9, 12], Kt6 = [10, -11, -9] und Kt7 = [8, 10, -11, 12] sind Zyklen; Kt5 ist ein Kreis. Im symmetrischen also ungerichteten Graphen ersetzt man häufig die Bogen einer Kette durch die zugeordneten Kanten und spricht nur von Wegen, d.h., man ersetzt eigentlich alle negativen Bogen einer Kette durch den zugehörigen Gegenbogen. Entsprechend spricht man nicht von Zyklen, sondern nur von Kreisen, und betrachtet den trivialen Kreis [Bogen, Gegenbogen] nicht als solchen. Ein gerichteter Graph heißt z u s a m m e n h ä n g e n d, wenn für jedes Paar i, j seiner Knoten eine Kette Kt = [k1, k2, ..., kr] derart existiert, dass AKn(k1) = i und EKn(kr) = j gilt. Kt heißt i und j verbindende Kette. Ein nicht zusammenhängender Graph besteht aus zusammenhängenden K o m p o n e n t e n. Ein Knoten j heißt von einem Knoten i aus e r r e i c h b a r, wenn von i nach j ein verbindender Weg existiert. Ein gerichteter Graph heißt s t a r k z u s a m m e n h ä n g e n d, wenn jeder seiner Knoten von jedem anderen Knoten aus erreichbar ist. Statt zusammenhängend wird manchmal auch der Begriff schwach zusammenhängend benutzt; dann ersetzt zusammenhängend den Begriff stark zusammenhängend. Jeder zusammenhängende ungerichtete Graph ist stark zusammenhängend. Im ungerichteten Graphen ist also die Unterscheidung zwischen schwachem und starkem Zusammenhang nicht notwendig. Wir geben im Folgenden Algorithmen an, die einen Graphen auf die Eigenschaften Erreichbarkeit und Zusammenhang testen. Wir benötigen dazu den Begriff des Stützgerüstes: Satz Ein B a u m ist ein zyklenfreier, zusammenhängender, endlicher Graph. Im ungerichteten Fall beziehen wir das Attribut zyklenfrei auf Kantenzyklen, sehen also davon ab, dass nach unserer Definition des ungerichteten Graphen streng genommen jede Kante ein Zyklus ist. Falls nichts anderes gesagt wird, meinen wir im Folgenden mit Baum ohne Attribut den gerichteten Baum. Satz Ein Baum mit n Knoten besitzt genau m = n - 1 Bogen. Beweis: Wir konstruieren den Baum neu, indem wir mit einem beliebigen seiner Knoten beginnen und an den aktuellen Baum mittels eines noch nicht hinzugefügten Bogens, der mit einem schon angeschlossenen Knoten inzident ist, einen neuen Knoten anhängen. Jeder hinzugefügte Bogen hängt einen neuen Knoten an, denn sonst schlösse sich ein Zyklus. Andererseits wird jeder Knoten angeschlossen, da der Graph zusammenhängend ist. Folglich ist der Graph durch genau m = n - 1 Bogenaufnahmen komplett. Unter den gerichteten Bäumen haben die Wurzelbäume besondere Bedeutung. 12 Kapitel 1: Grundbegriffe der Graphentheorie Definition Ein W u r z e l b a u m ist ein gerichteter Baum, bei dem jeder Knoten höchstens einen Eingangsbogen besitzt. (|EBg(i)| ≤ 1 ∀ i ∈ K) Ein Knoten, der keinen Eingangsbogen hat, wird W u r z e l des Baums genannt. Satz Ist G = [K, B] ein Wurzelbaum, so gelten folgende Aussagen: a) G besitzt genau eine Wurzel. b) Von der Wurzel aus ist jeder Knoten auf genau einem Weg erreichbar. Zum Beweis des Satzes: Wir betrachten zunächst einen beliebigen Knoten. Besitzt dieser nicht die Wurzeleigenschaft, so gehen wir zurück zum Anfangsknoten seines Eingangsbogens. Da es keinen Zyklus gibt und der Graph endlich ist, kann dieses Zurückgehen nicht beliebig oft wiederholt werden, sondern muss in einem Knoten mit Wurzeleigenschaft enden. Nun nehmen wir an, der Graph G besitze mindestens zwei Knoten mit der Wurzeleigenschaft. Zwischen je zwei dieser Knoten existiert eine verbindende Kette, da G zusammenhängend ist. Wir betrachten einen Fall, bei dem diese Kette keine dritte Wurzel enthält. Die Kette kann kein Weg sein, da an ihrem Anfang und an ihrem Ende eine Wurzel ist, also müsste sie einen Knoten enthalten, der zwei Eingangsbogen besitzt, im Widerspruch zur Wurzelbaumeigenschaft. Da ein Baum zusammenhängend ist, muss zwischen der Wurzel und jedem anderen Knoten eine verbindende Kette existieren. Diese muss ein Weg sein, da sie sonst einen Knoten mit zwei Eingangsbogen besäße. Wegen der Zyklenfreiheit kann es zu zwei Knoten keine zwei verschiedenen Verbindungsketten geben. Man bezeichnet im Wurzelbaum die Anzahl der Bogen des eindeutigen Weges von der Wurzel zu einem Knoten als Höhe des Knotens. Der Wurzel wird die Höhe 0 zugeordnet. Alle Knoten gleicher Höhe h bilden eine h-te Etage des Wurzelbaums. Die Anzahl der Etagen eines Baumes heißt Höhe H des Baums. Der leere Baum hat die Höhe 0. Der Baum, der nur aus einer Wurzel besteht, hat die Höhe 1. Die Anzahl der nach außen inzidenten Bogen eines Knotens eines Wurzelbaums wird als Ordnung des Knotens bezeichnet. Knoten mit der Ordnung 0 heißen Blätter des Baums. Alle Knoten, die weder Wurzel noch Blätter sind, heißen innere Knoten. Das Maximum aller Knotenordnungen heißt Ordnung des Wurzelbaums. Das folgende Bild zeigt einen Wurzelbaum der Ordnung 5 (Die Wurzel hat fünf nach außen inzidente Bogen, deren Endknoten als Söhne der Wurzel bezeichnet werden.), der die Höhe 5 hat (die Etagen 0 bis 4). Definition Ein Wurzelbaum der Ordnung 2 heißt B i n ä r b a u m. Kapitel 1: Grundbegriffe der Graphentheorie 13 Wurzel 0-te Etage Blatt 1. Etage Blatt Blatt Blatt Blatt Blatt Blatt 2. Etage 3. Etage 4. Etage Bild 1.5: Ein Baum der Höhe 5 Wurzelbäume werden schon seit sehr langer Zeit zur Darstellung von Abstammungsbeziehungen benutzt (Stammbäume). Von der Nutzung in patriarchalischen Zeiten kommen die üblichen Bezeichnungen: Ein Knoten wird Vater rechten Nachbarknoten genannt, und umgekehrt nennt man die rechten Nachbarknoten Söhne des Knotens. Hierarchischen Ordnungen wie der Abstammung begegnen wir an vielen Stellen unseres Lebens. Dies ist ein Grund, weshalb man recht häufig auf Wurzelbäume stößt. Ein anderer Grund besteht darin, dass sich Wurzelbäume sehr einfach beschreiben bzw. speichern lassen: Es genügt, zu jedem Knoten den eindeutigen Vorgängerknoten (Vater) zu nennen. Damit können sie vorteilhaft als Notation für Gerüste dienen, die ihrerseits, wie wir bald sehen werden, als Basis für die Beschreibung der Zyklenund Cozyklenstruktur eines Graphen geeignet sind. Wurzelbäume haben die Eigenschaft, dass die Anzahl der Knoten einer Etage sehr schnell, nämlich exponentiell mit der Etagenhöhe, wachsen kann: Beispielsweise kann ein Binärbaum in seiner h-ten Etage bis zu 2h Knoten besitzen, also schon 1024 für h = 10. Der niedrigste Binärbaum mit n Knoten ist der vollständige Binärbaum mit n Knoten, bei dem jede Etage maximal gefüllt ist. Besitzt ein vollständiger Binärbaum H Etagen, so enthalten die vollen Etagen mit den Nummern 0 bis 0 1 H-2 H-2 zusammen 2 + 2 + ... + 2 = 2H-1-1 Knoten, und die (H-1)-te Etage enthält H-1 H-1 1 ≤ n - 2 +1 ≤ 2 Knoten. Daraus folgt, log2(n+1) ≤ H ≤ log2(n) +1, oder Satz Ein Binärbaum mit n Knoten hat mindestens die Höhe H = Aufrundung(log2(n +1)). Mindesten der vollständige Binärbaum realisiert diese Höhe. Im Binärbaum mit n Knoten kann man folglich jede dort gespeicherte Information in maximal H = Aufrundung(log2(n+1)) Schritten wieder finden. Dies ist ein weiterer Grund für die Bedeutung von Bäumen in der Informatik. Da im niedrigstem Binärbaum mit n Knoten, dem vollständigen Binärbaum, alle von der Wurzel ausgehenden Wege die Länge H-1 oder H-2 haben, ist für ihn auch die mittlere Weglänge mit H = O(log2(n)) sicher minimal, so dass für einen beliebigen Binärbaum mittlereWeglänge ≥ log2(n) gilt. 14 Kapitel 1: Grundbegriffe der Graphentheorie Sind im vollständigen Binärbaum der Höhe H von den 2H-2 Knoten der (H-2)-ten Etage b Knoten Blätter und hat der Baum insgesamt B Blätter, so gilt, B = 2 (2H-2 –b)+b [-1], und der Baum hat H-1 H-2 n = 2 -1 +2 (2 –b) [-1] Knoten. Daraus ergibt sich, Satz Ein Binärbaum mit B Blättern hat mindestens n = 2B – 1 Knoten. Hat man die Anwendung von Bäumen für Suchprozesse im Blick, so ist die oben genannte speichergünstige Darstellung, die zu jedem Knoten nur seinen Vater nennt, sehr ungünstig bezüglich der Rechenzeit, denn die Suchprozesse müssen von der Wurzel des Baumes zu den Blättern laufen und brauchen folglich zu jedem Knoten seine Söhne. Damit ergibt sich folgendes Bild für die Darstellung bzw. Speicherung von Bäumen: • Bäume treten in vielen Fällen • entweder direkt als Wurzelbäume auf • oder es sind Gerüste (siehe unten) bzw. zusammenhängende Gerüstkomponenten eines gegebenen Graphen, die als Wurzelbäume beschrieben werden. • Bei einem Wurzelbaum kann jedem Knoten, außer der Wurzel, ein Bogen als dessen Eingangsbogen zugeordnet werden, so dass eine explizit anzugebende Bogenliste entfallen kann. Stattdessen notiert man zu jedem Knoten eines Wurzelbaums den Vater (= AKn(Eingangsbogen)). Allerdings ist diese Notation schlecht geeignet, wenn man auf dem Baum von der Wurzel ausgehende Suchprozesse betreiben will. In diesen Fällen notiert man besser zu jedem Knoten seine Söhne (= EKn(Ausgangsbogen)). • In manchen Fällen sind beide Notationen zweckmäßig. Beschreibt der Wurzelbaum ein Gerüst in einem Graphen mit parallelen Bogen, so ist mit der Angabe des Vaters kein eindeutiger Bezug auf die Bogen des Ausgangsgraphen möglich, so dass in diesem Fall der Eingangsbogen (durch seine vorzeichenbehaftete Nummer in der Bogenliste des Ausgangsgraphen) statt des Vaterknotens genannt wird. Definition Gegeben sei ein Graph G = [K, B]. Gilt für einen Graphen G' = [K', B'] sowohl K' ⊆ K als auch B' ⊆ B (d.h. B' ist Teil der Bogenliste B ), so heißt G' T e i l g r a p h von G. Ein Teilgraph G' = [K, B'] von G heißt s p a n n e n d e r T e i l g r a p h oder G e r ü s t in G, wenn B' eine maximale, zyklenfreie Teilmenge von B ist, wenn er also ein maximaler Baum innerhalb G ist. Ist G' = [K, B'] Gerüst von G, so heißt G" = [K, B\B'] C o g e r ü s t von G. Enthält die Bogenmenge B' eines Teilgraphen genau die Bogen aus B, die zwei Knoten aus K' verbinden, so heißt G' der von K' erzeugte U n t e r g r a p h von G und wird durch Ug(K') symbolisiert. Beispiel Bild 1.6 zeigt ein Gerüst im gegebenen Graphen mit der Bogen-Teilmenge B' = {1, 2, 3, 8, 11, 12}. [K, {4, 5, 6, 7, 9, 10}] ist das zugehörige Cogerüst. Beide Graphen sind auch Teilgraphen von G. Kapitel 1: Grundbegriffe der Graphentheorie 15 4 Kn2 Kn5 1 8 7 Kn1 10 9 Kn7 2 11 12 Kn4 3 Kn6 6 5 Kn3 Bild 1.6: Ein Gerüst des Graphen (fett) K' = {Kn2, Kn4, Kn5, Kn6} und B' = [4, 7, 8, 9, 12] bilden einen Teilgraphen G' = [K', B'] des Graphen im Bild 1.7. Dieser ist Untergraph Ug(K’). 4 Kn5 Kn2 10 1 8 7 Kn1 9 Kn7 2 11 12 3 Kn4 5 Kn6 6 Kn3 Bild 1.7: Ein Untergraph des Graphen Zum besseren Verständnis der Zusammenhänge führen wir zu einer Menge B* von Bogenbennungen einen Bogenvektor v(B*) = (v1, v2, ..., vm) so ein, dass vk = ±1 gilt, wenn ±k ∈ B* ist 0 andernfalls gilt. Da ein Gerüst G‘ = [K, B‘] aus einer maximalen, zyklenfreien Teilmenge der Bogen besteht, schließt jeder Cogerüstbogen k ∈ B\B‘ einen Zyklus. Definition Man bezeichnet die durch Cogerüstbogen erzeugten Zyklen als Basiszyklen z(k) von G zum Cogerüstbogen k. Diese (m-n+ko) Basiszyklen (ko = Anzahl der zusammenhängenden Komponenten) sind unabhängig, weil jeder einen, nämlich den ihn erzeugenden, Bogen enthält, der in keinen anderem Basiszyklus enthalten ist. Die Zyklenvektoren zv(k) zu den Basiszyklen z(k) sind linear unabhängig. Sie spannen den Raum der Ströme oder Zirkulationen des Graphen auf, zu dem alle Zyklen gehören. 16 Kapitel 1: Grundbegriffe der Graphentheorie Beispiel für die Feststellung, dass der Vektor zu jeden beliebigen Zyklus aus den Basisvektoren durch Linearkombination mit den Faktoren ±1 erzeugt werden kann: Im Graphen des Bildes 1.6 gilt: z(4) = [4, -8, -2, 1], z(10) = [10, -11, 12, 8], z(9) = [9, 12, 8], zv(4) = (1, -1, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0), zv(10) = (0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -1, 1), zv(12) = (0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1), Z = [k1, k2, ..., kr] sei ein Zyklus – beschrieben durch die Benennungen ki seiner Bogen: Es gilt: Zv = Σ {z(k) | für die k aus Z, die Cogerüstbogen sind}. Beispiel zv(4) + zv(10) = (1, -1, 0, 1, 0, 0, 0, 0, 0, 1, -1. 1) = Zv zu Z =[4, 10, -11, 12, -2, 1]. Definition Gegeben seien ein Graph G = [K, B] und eine Knotenmenge K' ⊆ K. Ein Bogen, dessen Anfangsknoten nicht in K' liegt, während der Endknoten zu K' gehört, heißt E i n g a n g s b o g e n von K'. Ein Bogen, dessen Anfangsknoten in K' liegt, während der Endknoten nicht zu K' gehört, heißt A u s g a n g s b o g e n von K'. EBg(K') und ABg(K') bezeichnen die Menge der Eingangs- bzw. Ausgangsbogen von K'. CZ(K') = (-EBg(K')) U ABg(K') bezeichnet die Menge aller Eingangs- und Ausgangsbogen von K' und wird C o z y k l u s oder S c h n i t t zur Knotenmenge K' genannt. Ein Cozyklus heißt e l e m e n t a r, wenn sowohl K' als auch K\ K' zusammenhängende Untergraphen erzeugen. 4 Kn2 Kn5 1 10 8 7 Kn1 9 2 11 12 Kn4 3 5 Kn7 Kn6 6 Kn3 Bild 1.8: Ein Cozyklus des Graphen (fett) ABg({i}) = ABg(i), EBg({i}) = EBg(i), CZ({i}) = InzBg(i). Beispiel - Bild 1.8: Für K' = {Kn2, Kn4, Kn5, Kn6} ist CZ(K') = {-1, -2, -5, -6, 10, 11}. Wenn man jede zusammenhängende Komponente des von K' erzeugten Untergraphen Ug(K’) mit einem geschlossenen Linienzug umrahmt, so gehören genau die Bogen von B, die von dieser Rahmenlinie einmal geschnitten werden zum Cozyklus CZ(K') - das begründet die synonyme Bezeichnung „Schnitt“ für Cozyklus. Beispiel – Bild 1.9: CZ({Kn1}) = {1, 2, 3} und CZ({Kn7}) = {-10, -11} sind elementare Cozyklen. Der Cozyklus CZ({Kn1, Kn7}) ist nicht elementar, weil Ug({Kn1, Kn7}) nicht zusammenhängend ist. Es gilt CZ({Kn1, Kn7}) =CZ({Kn1} U (CZ({Kn7})). Kapitel 1: Grundbegriffe der Graphentheorie 17 4 Kn2 Kn5 1 10 Kn1 9 8 7 Kn7 2 11 12 Kn4 3 Kn6 6 5 Kn3 Bild 1.9: Ein nicht elementarer Cozyklus des Graphen Wir betrachten ein Gerüstes G‘ = [K, B‘]: Entfernt man einen Bogen k aus dem Gerüst, so verliert die Komponente (ein Baum) des Gerüstes, die ihn enthielt, ihren Zusammenhang, da es auf Grund der Zyklenfreiheit keine zweite Verbindung zwischen dem Anfangs- und dem Endknoten von k im Gerüst gibt. Der Gerüstbogen k definiert somit eindeutig zwei Knotenmengen, nämlich einmal die Menge K’ aller Knoten, die mit EKn(k) auf dem Rest des Gerüstes zusammenhängen und zum anderen K\K’ (AKn(k) ∈ K\K’). Damit definiert k auch eindeutig einen Cozyklus in G, nämlich den von dieser Knotenmenge erzeugten Cozyklus CZ(K'). Definition Der von einem Gerüstbogen erzeugte Cozyklus heißt Basiscozyklus cz(k) in G zum Gerüstbogen k. Es gilt CZ(K\K') = -CZ(K'), wenn die cz(k) = CZ(K'), also K' die cz(k) erzeugende Knotenmenge ist. Die (n-ko) Basiscozyklen - ko = Anzahl zusammenhängender Komponenten von G - sind unabhängig, weil jeder einen, nämlich den ihn erzeugenden Bogen enthält, der in keinem anderen der Basiscozyklus enthalten ist. Die linear unabhängigen Vektoren zu den Basiscozyklen erzeugen den linearen Vektorraum der Spannungen des Graphen: Ist CZ = {k1, k2, ..., kr} – ein Cozyklus, so gilt: CZ = Σ {cz(k) | für die k ∈ CZ, die GerüstBogen sind}. Beispiel – Bild 1.10: Für den Gerüstbogen 4 gilt cz(4) = CZ({Kn1, Kn2, Kn3, Kn4}) = {4, 6, 8, -12}. Für den Gerüstbogen 10 gilt cz(10) = CZ({Kn1, Kn2, Kn3, Kn4, Kn5}) = {6, 9, 10, -12}. CZ({Kn5}) = {-4, -8, 9, 10} = cz(-4) + cz(10) = {-4, -6, -8, 12} + {6, 9, 10, -12}. 4 Kn2 Kn5 10 1 Kn1 9 8 7 2 11 12 Kn4 3 5 6 Kn3 Bild 1.10: Basiscozyklen, definiert durch ein Gerüst (fett) Kn6 Kn7 18 Kapitel 1: Grundbegriffe der Graphentheorie Im zusammenhängenden Graphen ist ein Gerüst ein Baum. Dieser Baum wird gern als Wurzelbaum notiert: Da in einem Baum jedem seiner Knoten bis auf einen genau ein Bogen zugeordnet werden kann, machen wir den beliebig wählbaren Ausnahmeknoten zur Wurzel des Gerüstes, und nennen den Gerüstbogen, den wir jedem anderen Knoten i zuordnen, Stützbogen des Knotens. Dazu richten wir eine Funktion StzBg(i) über der Knotenmenge so ein, dass sie die Benennung des Stützbogens in folgender Weise liefert: • StzBg(Wurzel) = WrzBg • EKn(StzBg(i)) = i . WrzBg ist ein fiktiver Bogen (sehr große Nummer). Für die Testfunktion istBg(i) soll istBg(WrzBg) = false gelten. Vorteilhaft ist dazu eine über der Bogenmenge erklärte Funktion Stützrichtung, StzRchtg(int k): 1, wenn StzBg(EKn(k)) = k StzRchtg(k) = -1, wenn StzBg(EKn(k)) = -k 0, wenn k kein Stützbogen ist. Die Wurzel eines Stützgerüstes definiert nur seine Notation. Sie kann (mit Hilfe einer einfachen Funktion setzWrz(i)) in einen beliebigen Knoten i gesetzt werden. Dazu müssen in der Notation des Gerüstes nur die Vorzeichen der Stützbogen entlang des Weges von der alten Wurzel zum Knoten i vertauscht werden – siehe Bild 1.11. Wurzel i i =Wurzel Bild 1.11: Veranschaulichung der Verlegung der Wurzel eines Gerüstes in einen vorgegebenen Knoten Man ändert ein Gerüst, indem man einen Cogerüstebogen k durch einen Gerüstbogen seines Basiscozyklus cz(k) ersetzt (vgl. Bild 1.12): public void tauschStzBg(int kAlt, int kNeu) { if (istBg(kNeu)) { setzWrz(EKn(kNeu)); setStzBg(EKn(kNeu), kNeu); int i = EKn(kAlt*StzRchtg(kAlt)); if (kAlt != 0) setStzBg(EKn(kAlt*StzRchtg(kAlt)),WrzBg); } } Kapitel 1: Grundbegriffe der Graphentheorie 19 4 kAlt Kn2 1 Kn5 10 7 Kn1 9 8 2 -11 12 kNeu Kn4 3 Kn7 Kn6 5 6 Kn3 4 Kn2 Kn5 10 1 7 Kn1 9 8 -2 -11 12 Kn4 3 Kn7 Kn6 5 6 Kn3 Bild 1.12: Veranschaulichung der Änderung eines Gerüstes durch Bogentausch Es sei k ein Cogerüstbogen. Wir wollen seinen Basiszyklus durchlaufen: setzWrz(EKn(k)); k = StzBg(AKn(k)); while (istBg(k)) { ... k = StzBg(AKn(k)); } Beispiel – Bild 1.12, z(4) = [4, 1, -2, 12, -11, 10]: StzBg(Kn2) = 1, StzBg(Kn1) = -2, StzBg(Kn4) = 12, StzBg(Kn6) = -11, StzBg(Kn7) = 10, StzBg(Kn5) = WrzBg, istBg(WrzBg) = false. Es sei k ein Gerüstbogen. Wir wollen die Bogen seines Basiscozyklus aufzählen. Eine Prozedur cz(k) macht folgendes: Sie setzt beim EKn(k) bei allen von ihm aus über StützBogen erreichbaren Knoten eine Hilfsgröße Marke(i)=2; bei allen übrigen Knoten Marke(i)=1; czKoeff(l) = Marke[EKn(l)] - Marke[EKn(l)]; liefert dann für alle Bogen des Cozyklus ±1 und für die Bogen, die nicht zum Cozyklus gehören, den Wert Null. Beispiel – Bild 1.13, cz(4) = {4, 6, 8, -12} = CZ({Kn1, Kn2, Kn3, Kn4}): Von Kn1 aus werden die über die Gerüstbogen 10 und 11 erreichbaren Knoten grau (Marke(i)=1) gefärbt, zum Cozyklus gehören alle Bogen, die einen weißen mit einem grauen Knoten verbinden. 4 Kn2 Kn5 10 1 Kn1 9 8 7 2 11 12 Kn4 3 5 6 Kn3 Bild 1.13: Basiscozyklen, definiert durch ein Gerüst (fett) Kn6 Kn7 20 Kapitel 1: Grundbegriffe der Graphentheorie 1.4 Erreichbarkeit, Zusammenhang, Kreisfreiheit Eine häufig anstehende Frage ist die Frage, ob ein Knoten j von einem Knoten i aus erreichbar ist, womit bekanntlich gemeint ist, ob es von i aus einen Weg zum Knoten j gibt. Zur Lösung dieser Frage stehen zwei wichtige Basisalgorithmen zur Verfügung • die so genannte Tiefensuche – englisch depth first search, Abkürzung DFS • die so genannte Breitensuche – englisch breadth first search, Abkürzung BFS Begriffe, die auch für analoge Suchprozesse benutzt werden, bei denen man die Beziehung zu Graphen nicht sofort erkennt. Die Algorithmen lösen die Aufgabe, bestimme für einen Start-Knoten die Menge aller von ihm aus erreichbaren Knoten des Graphen. Zur Unterscheidung zwischen erreichbaren und nicht erreichbaren Knoten braucht man eine Knotenmarkierung. Da meistens nicht nur interessant ist, ob, sondern auch wie ein spezieller Knoten erreicht wird, erzeugt man einen Baum – Erreichbarkeitsbaum – bestehend aus Wegen vom Knoten Start zu allen erreichbaren Knoten. Ein Baum genügt, man muss nicht notwendig alle möglichen Wege anzeigen. Der Baum ist ein Wurzelbaum – Start ist seine Wurzel – und er wird durch die oben eingeführte Bogenfunktion StzBg(i) beschrieben. Damit haben wir gleichzeitig eine sinnvolle Knotenmarkierung: Für Knoten, die von Start aus nicht erreicht werden können, gilt StzBg(i) = 0, während für die übrigen Knoten StzBg(i) den Erreichbarkeitsbaum beschreibt. Tiefensuche • Man markiere den Startknoten und mache ihn zum aktuellen Knoten i. • Man suche vom aktuellen Knoten i aus einen rechten Nachbar j = EKn(k), k ∈ ABg(i), der noch nicht als erreicht markiert ist. Existiert einer, wird er markiert (StzBg(j):=k). • Hat der aktuelle Knoten i keinen Ausgangsbogen mehr, dessen Endknoten noch ohne Markierung ist, so gehe man zu dem Knoten zurück, von dem aus i markiert wurde (i = AKn(StzBg(i))). Die Umsetzung des Algorithmus in eine Prozedur lautet wie folgt: public void DFS(int Start) { int i, j, k; initStzBg(Start); i = Start; k = eAusBg(i); do { while (istBg(k)) { j = EKn(k); if (getStzBg(j) == 0) { setStzBg(j, k); i =j; k = eAusBg(i); } else k = nAusBg(i, k); } if (i != Start) { k =getStzBg(i); i = AKn(k); k = nAusBg(i, k); } } while ((i != Start) || istBg(k)) } Breitensuche • Man gebe den Startknoten in eine Hilfsliste vom Typ Schlange. • solange die Schlange nicht leer ist entnehme man ihr einen Knoten als Standort. • Man untersuche vom Standort aus alle rechten Nachbarn: Diejenigen, die erstmals erreicht werden, werden markiert (StzBg setzen) und in die Schlange aufgenommen. Auch für diesen Algorithmus die Umsetzung in eine Prozedur: public void BFS(int Start) { int i, j, k; IntSchlange S = new IntSchlange(maxKnAnz); S.push(Start); initStzBg(Start); while (!S.istLeer()) { i = S.exTop(); k = eAusBg(i); while (istBg(k)) { j = EKn(k); Kapitel 1: Grundbegriffe der Graphentheorie 21 if (getStzBg(j) == 0) { setStzBg(j, k); S.push(j); } k = nAusBg(i, k); } } } Beide Prozeduren besitzen die Zeitkomplexität O(m), weil bei DFS auf jedem Bogen höchstens einmal im Vorwärtslauf und einmal beim Rückwärtsschritt zugegriffen wird, während bei BFS auf jedem Bogen höchstens einmal zugegriffen wird. 4 Kn2 Kn5 10 1 7 Kn1 9 8 2 11 Kn7 12 Kn4 3 Kn6 5 6 Kn3 4 Kn5 Kn2 10 1 7 Kn1 8 9 Kn7 -2 11 12 Kn4 3 Kn6 5 Kn3 6 Bild 1.14: Veranschaulichung der Tiefensuche und der Breitensuche mit Start = Kn4 Beispiel – Bild 1.14: Tiefensuche: Von Kn4 aus über 7 nach Kn2, weiter über 4 nach Kn5, weiter über 9 nach Kn6, weiter über 11 nach Kn2. Da von Kn7 aus kein Weiter, zurück nach Kn6; da kein Weiter, zurück nach Kn5; da kein Weiter, zurück nach Kn4; da kein Weiter, Ende. Breitensuche: Von Kn4 aus Markierung der Knoten Kn2 über 7 und Kn5 über 8; von Kn2 aus keine neue Markierung; von Kn5 aus über 9 Markierung Kn6, über 10 Markierung Kn7; von Kn6 und Kn7 aus keine neue Markierung; Ende. Beide Prozeduren besitzen die Zeitkomplexität O(m), weil bei DFS auf jedem Bogen höchstens einmal im Vorwärtslauf und einmal beim Rückwärtsschritt zugegriffen wird, während bei BFS auf jedem Bogen höchstens einmal zugegriffen wird. Ersetzt man in einem der Erreichbarkeitsalgorithmen DFS oder BFS die ABg-Funktion durch die InzBg-Funktion, so heißt das, man sucht nach Knoten, die vom Start aus über Ketten statt über Wege „erreicht“ werden können. Folglich markiert man (mit StzBg(i) ≠ 0) alle Knoten, die mit Start zusammenhängen - public void Zusammenhang(int Start). Daraus ist leicht eine public int Graph.AnzZshgKomp() zu entwickeln, die die Anzahl der zusammenhängenden Komponenten eines Graphen ermittelt und allen Knoten, die zur z-ten Komponente gehören Marke(i)=z; zuordnet. Ersetzt man in einem der Erreichbarkeitsalgorithmen public void DFS(int Start) oder BFS die ABgFunktion durch EBg-Funktion, so heißt das, man sucht nach Knoten, die vom Start aus über Wege, die gegen die Bogenrichtung durchlaufen werden, „erreicht“ werden können. Folglich markiert man (mit 22 Kapitel 1: Grundbegriffe der Graphentheorie StzBg(i) ≠ 0) alle Knoten, von denen aus Start erreicht werden kann. Nennen wir eine Prozedur, die das leistet public void DFSrueck(int Start) – DFS(int Start) mit Rückwärtsorientierung – so kann man etwa mit DFS(Start) alle von Start aus erreichbaren Knoten und mit DFSrueck(Start) alle Knoten, von denen aus Start erreicht wird, markieren. Die Knoten, die in beiden Fällen markiert wurden, bilden eine den Knoten Start enthaltende stark zusammenhängende Komponente des Graphen. Definition Einen stark zusammenhängenden Untergraphen nennt man stark zusammenhängende Komponente des Graphen. Daraus ist leicht eine public int Graph.AnzStarkZshgKomp() zu entwickeln, die die Anzahl der stark zusammenhängenden Komponenten eines Graphen ermittelt und allen Knoten, die zur z-ten Komponente gehören Marke(i)=z zuordnet. Beispiel Der Graph, der z.B. im Bild 1.14 gezeigt wird besitzt 3 stark zusammenhängende Komponenten: Den Untergraphen zu der Knotenmenge {Kn2, Kn4, Kn5, Kn6} und die Untergraphen zu den beiden Knotenmengen {Kn1} und {Kn7}, die beide leere Bogenmengen haben. Besitzt der Graph keine stark zusammenhängende Komponente, so ist er kreisfrei. Besitzt der Graph genau eine stark zusammenhängende Komponente, so ist er stark zusammenhängend. Die Prozedur Graph.AnzStarkZshgKomp() kann also sowohl zum Test auf Kreisfreiheit als auch zum Test auf starken Zusammenhang genutzt werden. Die Zeitkomplexität beider Prozeduren kann mit O(AnzKomp·m) angegeben werden, wobei AnzKomp die Anzahl der zusammenhängenden bzw. stark zusammenhängenden Komponenten angibt. Eine andere Anwendung der Erreichbarkeitsalgorithmen ist die Bestimmung einer Maximummenge unabhängiger Kanten oder auch Maximumpaarung in einem ungerichteten Graphen: Wir bezeichnen eine Teilmenge M ⊆ B der Kantenmenge eines ungerichteten Graphen G = [K, B] als Menge unabhängiger Kanten oder auch Paarung falls ihre Elemente paarweise verschieden sind. Wir können eine solche Menge einfach so konstruieren, dass wir, beginnend mit M = Ø, sukzessive Kanten zu M hinzufügen, solange die neue Kante mit keiner der schon dazugehörigen Kanten inzident ist. Einen Knoten des Graphen, der mit keiner Kante von M inzident ist, bezeichnen wir als exponiert bezüglich M und einen Weg, der abwechselnd eine Kante aus M und eine aus (B – M) enthält, als alternierende Kette bezüglich M. Eine bezüglich M alternierende Kette heißt M-vergrößerbar, wenn ihre beiden Endpunkte exponiert sind. Offensichtlich ist eine Paarung nicht optimal, wenn es eine M-vergrößerbare Kette Kt gibt, denn, wenn wir alle Kanten aus Kt, die zu M gehören aus M entfernen und dafür die Kanten aus Kt, nicht zu M gehören zu M hinzunehmen, so ist M wieder Paarung und hat offensichtlich eine Kante mehr als vorher. Kapitel 1: Grundbegriffe der Graphentheorie 23 X5 X4 X8 X1 X2 X3 X7 X6 X5 X4 X8 X1 X2 X3 X7 X6 Bild 1.15: Konstruktion einer Maximumpaarung Bild 1.15 zeigt ein Beispiel: M = {(X1, X2), (X3, X7), (X4, X5)} sei die betrachtete Paarung (ihre Elemente sind fett gezeichnet). Kt = [(X1, X8), (X1, X2), (X2, X4), (X4, X5), (X5, X7), (X3, X7), (X3, X6)] ist eine M-vergrößerbare Kette, die die exponierten Knoten X8 und X6 verbindet. Mit ihr kann man M auf M = {(X1, X8), (X2, X4), (X5, X7), (X3, X6)} erweitern. Auf den Beweis der Notwendigkeit der Existenz einer M–vergrößerbaren Kette für eine Erweiterung einer Paarung wollen wir verzichten. Am Beispiel Bild 1.15 ist offensichtlich, dass die im unteren Bild angegebene Paarung {(X1, X8), (X2, X4), (X5, X7), (X3, X6)} eine Maximumpaarung darstellt. Algorithmus zum Auffinden einer Maximumpaarung im ungerichteten Graphen G = [K, B]: • • Suche eine beliebige Paarung M. Gibt es einen bezüglich M exponierten Knoten Xstart sowie eine von Xstart ausgehende vergrößerbare Kette? o Nein: M ist eine Maxiumpaarung. o Ja: Modifizierte Tiefensuche, ausgehen von Xstart, nach einen von Xstart verschiedenen exponierten Knoten: • Man markiere den Startknoten und mache ihn zum aktuellen Knoten X. • Man suche vom aktuellen Knoten X aus einen Nachbar Y, der noch nicht als erreicht markiert ist. Ist X exponierter Knoten, so ist eine vergrößerbare Kette gefunden. Tausche längs der Kette die Zugehörigkeit ihrer Kanten bezüglich der Paarung und wiederhole den Algorithmus. Andernfalls wird der bezüglich der Paarung gegebener Partner Y* von Y markiert; X := Y*; Wiederholung dieses Schrittes. • Hat der aktuelle Knoten X keine inzidente Kante mehr, deren Endknoten noch ohne Markierung ist, so Abbruch, falls X = Xstart; andernfalls gehe man zu dem Knoten zurück, von dem aus X markiert wurde (X = AKn(StzBg(X))) und wiederhole den vorhergehenden Schritt. 24 Kapitel 1: Grundbegriffe der Graphentheorie Bemerkung: Es ist wichtig, dass beim Vorwärtsgehen nicht der Nachbar Y, sondern dessen Partner Y* bezüglich M markiert wird, denn Y ist nicht eigentlich erreicht, sondern nur Durchgangsstation beim Vorwärtsgehen. Am Beispiel Bild 1.14 oberes Teilbild: X := Xstart := X8; StzBg(X8) := WrzBg; Y := X1; Y* := X2; StzBg(X2) := (X1, X8); X := X2; Y := X3; Y* := X7; StzBg(X7) := (X2, X3); X := X7; Y := X5; Y* := X4; StzBg(X4) := (X5, X7); X := X4; Y := X2; X2 wurde schon erreicht, also rückwärts: StzBg(X4) := (X5, X7); X := X7; X7 hat keinen weiteren Nachbar, also weiter rückwärts: StzBg(X7) := (X2, X3); X := X2; Y := X4; Y* := X5; StzBg(X5) := (X2, X4); X := X5; Y := X7; Y* := X3; StzBg(X3) := (X5, X7); X := X3; Y := X6; X6 ist exponiert, also erfolgreiches Ende der Suche und Erweiterung der Paarung: Alter Partner X3 von ist X7; X := X3; StzBg(X3) = (X5, X7); X3 wird Partner von X6; X6 wird Partner von X3; X := X5; StzBg(X5) = (X2, X4); X7 wird Partner von X5; X5 wird Partner von X7; X := X2; StzBg(X2) = (X1, X6); X2 wird Partner von X4; X4 wird Partner von X2; X := X8; StzBg(X8) = WrzBg, also Ende des Algorithmus. Da es keinen exponierten Knoten mehr gibt, endet das Verfahren, die gegebene Paarung (Bild 1.14 unteres Teilbild) ist eine Maximumpaarung. Kapitel 2: Einfache Netzaufgaben 25 2. Einfache Netzaufgaben 2.1 Suche nach kürzesten Wegen Wir haben im vorigen Kapitel das Erreichbarkeitsproblem behandelt: Die Prozeduren DFS und BFS erzeugen jeweils einen Wurzelbaum innerhalb eines Graphen G = [K, B], der zu jedem Knoten i, der von einem Knoten Start aus in G erreichbar ist, einen Weg enthält, auf dem man i erreichen kann. Im Allgemeinen ist ein Knoten i von einem Knoten Start aus auf mehreren Wegen erreichbar, in manchen Graphen sogar auf sehr vielen. Dieser Tatsache entspricht auch, dass die beiden Algorithmen im Allgemeinen verschiedene Wurzelbäume liefern und dass jeder der Algorithmen für die gleiche mathematische Struktur G verschiedene Ergebnisse liefern kann, wenn man G in verschiedener Weise notiert – z. B. in verschiedenen Bogennummerierungen. In praktischen Fällen – stellen wir uns z.B. den Graphen als Straßennetz vor (lauter Einbahnstraßen!) – wird man häufig nicht nach irgendeinem Weg von Start nach i fragen, sondern nach einem kürzesten. Dies setzt natürlich voraus, dass wir die Länge eines Weges messen können, und dazu benötigen wir eine Bogenlänge/-bewertung: Aufgabe Bestimmung der kürzesten Wege: Gegeben sind • eine Datenstruktur vom Typ eNetz - in Form eines gerichteten Graphen G = [K, B] mit einer über B erklärten reellwertigen Funktion c(k) - sowie • ein Knoten Start ∈ K. Gesucht sind für jeden Knoten, der von Start aus erreichbar ist, ein kürzester elementarer Weg und seine Länge. Die Länge L(W) eines Weges W ist natürlich die Summe der Längen c(k) seiner Bogen. Die Aufgabenstellung verlangt von uns eine Wegangabe. Das werden wir wieder mit StzBg(i) bewerkstelligen, wobei die Funktion gleichzeitig der Markierung dient: Der Knoten i ist genau dann erreichbar, wenn StzBg(i) ≠ 0. Den Anwender werden natürlich auch die Weglängen interessieren, auch wenn in der Problemstellung davon nicht explizit gesprochen wird. Dazu ordnen wir jedem Knoten i ∈ K eine reelle Zahl t(i) zu. Eine über der Knotenmenge eines gerichteten Graphen erklärte Funktion t(i) wird auch als Potential bezeichnet. Da bei vielen Aufgaben in Netzen ein solches Potential benötigt wird, wollen wir unterstellen, dass eine Datenstruktur public class eNetz extends Graph („einfaches“ Netz) mit folgende Methoden zur Verfügung steht: • public double getT(int i) { /** Liefert den Potentialwert des Knotens i. */ …} public void setT(int i, double t) {/** Setzt den Potentialwert des Knotens i auf den Wert t. */ …} • public double c(int k) {/** Liefert für den Bogen k einen Wert, genannt „Bogenlänge“. */ … } c(-k) = -c(k). Für das Problem der kürzesten Wege soll gemäß Aufgabenstellung gelten: 0, für i = Start t(i) = ∞, wenn i von Start aus nicht erreichbar ist Länge eines kürzesten Weges von Start nach i, sonst 26 Kapitel 2: Einfache Netzaufgaben Algorithmus von Dijkstra zur Bestimmung der kürzesten Wege Voraussetzung: c(k) ≥ 0 für alle k ∈ B. Beginnend mit setT(Start, 0); initStzBg(Start); und K’:= {Start}; wiederhole folgenden Prozess bis K’ = K gilt: • Bilde ABg(K’). • Berechne für k ∈ ABg(K'), i = AKn(k), j = EKn(k), die Werte τ(j) = t(i) + c(k). • Bestimme den kleinsten Wert τ(j) sowie die zugehörigen Größen k und j. • Erweitere K’ um den Knoten j: K’:= K’ ∪ { j }; t(j):=τ(j). • Nimm den Bogen k, der das Minimum bestimmte, in das Stützgerüst auf. Kn2 3 c=5 Kn5 7 c=3 c=3 c=5 Kn1 0 c=2 c=5 Kn7 10 c=6 Kn4 5 c=4 c=3 Kn6 12 c=3 c=1 Kn3 4 c = 10 Bild 2.1: Kürzeste Wege nach Dijkstra Beispiel – Bild 2.1: Start = Kn1. Die fett gezeichneten Elemente bilden den Erreichbarkeitsbaum aus kürzesten Wegen. Wir skizzieren den Ablauf des Algorithmus: 1) K’ = {Kn1 }: τ(Kn2) = 3, τ (Kn3) = 4, τ(Kn4) = 6; Min = 3, kMin = [Kn1, Kn2], t(Kn2) = 3 2) K’ = {Kn1, Kn2}: τ(Kn3) = 4, τ(Kn4) = 6, τ(Kn5) = 8; Min = 4, kMin = [Kn1, Kn3], t(Kn3) = 4 3) K’ = {Kn1, Kn2, Kn3}: τ (Kn4) = 6, τ(Kn4) = 5, τ(Kn5) = 8; Min = 5, kMin = [Kn3, Kn4], t(Kn4) = 5 4) K’ = {Kn1, Kn2, Kn3, Kn4}: τ(Kn5) = 8, τ(Kn5) = 7, τ(Kn6) = 14; Min = 7, kMin = [Kn4, Kn5], t(Kn5) = 7 5) K’ = {Kn1, Kn2, Kn3, Kn4, Kn5}: τ(Kn6) =12, τ(Kn6) = 14, τ(Kn7) = 10; Min = 10, kMin = [Kn5, Kn7], t(Kn7) = 10 6) K’ = {Kn1, Kn2, Kn3, Kn4, Kn5, Kn7}: τ(Kn6) =12, τ(Kn6) = 14; Min = 12, kMin = [Kn5, Kn6], t(Kn6) = 12 7) K’ = {Kn1, Kn2, Kn3, Kn4, Kn5, Kn6, Kn7} = K, das Verfahren endet. Beweis der Effektivität des Dijkstra-Algorithmus: Wir betrachten die Aufnahme des Knotens j in die Menge K’. Angenommen es gäbe einen kürzeren Weg von Start nach j als den deklarierten, der über i ∈ K' führt. Dieser müsste über einen Knoten j* ∉ K', j* = EK(k) für ein k ∈ ABg(K’) führen. Da aber für alle j* ∉ K' t(j*) ≥ t(j) gilt, denn t(j) ist das Minimum aller τ(j*) für j* = EK(k), k ∈ ABg(K’), so ist das unmöglich, wenn alle Bogenlängen größer/gleich Null sind. Die Zeitkomplexität des Dijkstra-Algorithmus können wir mit O(n2) abschätzen, denn das Verfahren führt für jeden Knoten eine Minimumbildung über eine durch O(n) abschätzbare Knotenanzahl durch. Kapitel 2: Einfache Netzaufgaben 27 Kn1 0 c=2 c=3 Kn3 2 c = -2 Kn2 3 Bild 2.2: Versagen des Dijkstra-Algorithmus bei c(k) Beispiel Das einfache im Bild 2.2 gezeigte Netz demonstriert, dass der Algorithmus bei negativen Bogenlängen versagen kann. Er würde die im Bild angegebene Lösung erzeugen, weil unterstellt wird, dass bei der Bestimmung von t(Kn3) kein Weg berücksichtigen werden muss, der eine größere Länge als τ(Kn3) = 2 besitzt. Wir geben den Algorithmus als Java-Prozedur an: public boolean kuerzesteWege(int Start) int j, k; PriorHeap Kandidaten; ElementtypIR ID; initT(Infinit); initStzBg(Start); setT(Start, 0.0); Kandidaten = new PriorHeap(m+1); Kandidaten.pushOpt(new ElementtypIR(WrzBg, 0.0)); while (!Kandidaten.istLeer()) { ID = (ElementtypIR) Kandidaten.exOpt(); k = ID.getInt(); if (k == WrzBg) j = Start; else j = EKn(k); if (getStzBg(j) == 0) { setStzBg(j, k); setT(j, ID.getInhalt()); k = eAusBg(j); } while (istBg(k)) { if (getStzBg(EKn(k)) == 0) Kandidaten.pushOpt(new ElementtypIR(k, getT(j) + c(k))); k = nAusBg(j, k); } } boolean negKreis = false; double dY, minY; int i, k1, kS, kMin; for (k=1; k<=m; k++) { dY = getY(k)-c(k); if (StzRchtg(k) == 0 && dY > eps) { setzWrz(AKn(k)); j = EKn(k); kS = getStzBg(j); negKreis = StzRchtg(kS) == -1; if (!negKreis) do { kMin = k; minY = getY(k) - c(k); markCZ(kS); for (k1 = 1; k1 <= m; k1++) if (czKoeff(k1) == -1 && c(k1) - getY(k1) < minY) { minY = c(k1) - getY(k1); kMin = k1; } for (I = 1; I <= n; i++) if (getMarke(i) == 2) setT(i, getT(i) - minY); setStzBg(EKn(kMin), kMin); } while (kMin != k); setzWrz(Start); } } return negKreis; } Die Prozedur stützt sich auf einen Prioritätsheap, in dem als Elemente Paare (k, τ(EKn(k))) gespeichert werden - als ElementtypIR. Ein solcher Speicher sichert, dass bei Entnahme eines 28 Kapitel 2: Einfache Netzaufgaben gespeicherten Elementes immer dasjenige geliefert wird, das den kleinsten Wert, hier von τ(EKn(k)), besitzt. Wird die Menge K‘ um ein j (=EKn(k)) erweitert, so werden für alle k ∈ ABg(j) die Paare (k, τ (EKn(k))) in den Heap gespeichert. Das sind n-mal höchstens O(n) Werte. Der Heap kann O(m) Paare enthalten, aber da Einspeichern und Entnahme nur die Komplexität O(log(Anzahl der im Heap befindliche Elemente)) besitzt, ergibt sich eine Worst-Case-Komplexität von O(n2). Wk W1 W2 Bild 2.3: Ein nicht elementarer Weg W = W1 + Wk + W2 Für den Fall, dass auch negative c(k)-Werte zugelassen sind, betrachten wir einen nicht-elementaren Weg W - siehe Bild 2.3 - bestehend aus einem elementaren Teilweg W1, einem Kreis Wk und einem elementaren Teilweg W2. Den elementaren Weg W1 + W2 wollen wir als elementare Reduktion des nicht-elementaren Weges W = W1 + Wk + W2 bezeichnen. W kann nur dann kürzer sein als seine elementare Reduktion, wenn der Kreis Wk eine negative Länge besitzt. Satz Ein kürzester elementarer Weg von einem Knoten i zu einem Knoten j, der über den Knoten i* führt, besteht genau dann in jedem Fall aus einem kürzesten Weg vom Knoten i zum Knoten i* und einem kürzesten Weg vom Knoten i* zum Knoten j, wenn das Netz keinen Kreis negativer Länge enthält. Es folgt: Ist das Netz kreisfrei, so ergibt in jedem Fall die Addition kürzester Wege einen kürzesten Weg. Umgekehrt, enthält das Netz Kreise negativer Länge, so muss damit gerechnet werden, dass die Addition zweier kürzester Wege einen nicht-elementaren Weg liefert, also nicht den gesuchten elementaren kürzesten Weg. c = -3 c=1 Kn2 4 c=4 c = -3 Kn3 1 c=1 Kn2 3 Kn3 2 c=4 c=2 Kn1 0 c=2 Kn1 0 Bild 2.4: Kürzeste Wege und Kreise negativer Länge Beispiel Zur Demonstration betrachten wir das Bild 2.4: Das Netz enthält den Kreis [[Kn2, Kn3], [Kn3, Kn2]] mit der Länge -2. Wir suchen die kürzesten Wege vom Knoten Kn1: Im linken Bild wird gezeigt, dass zum Knoten Kn3 ein Weg der Länge t(Kn3) = 1 führt. Der darf aber Kapitel 2: Einfache Netzaufgaben 29 nicht durch den kürzesten Weg von Kn3 nach Kn2 fortgesetzt werden zu einem kürzesten Weg nach Kn2, sondern der kürzeste, elementare Weg vom Knoten Kn1 zum Kn2 ist im rechten Bild aufgezeigt. Er hat die Länge t(Kn2) = 3. Der Leser möge einwenden, dass er ohnehin c(k) ≥ 0 für k ≥ 0 unterstellt habe - womit negative Wegbzw. Kreislängen unmöglich sind – und, dass negative Bogenlängen schwer vorstellbar sind. Aber wir haben schon gesehen, dass auch praktische Aufgaben schnell zu abstrakteren Formulierungen führen, und im betrachteten Fall könnten die Bogen-“Längen“ auch Kosten darstellen, und negative Kosten sind als Gewinne sehr real zu interpretieren. Wir werden im weiteren davon ausgehen, dass negative Bogenlängen zugelassen sind aber Kreise negativer Länge auf einen Datenfehler hindeuten, d.h. wir suchen Algorithmen, die Kreise negativer Länge erkennen, verlangen aber nicht, dass sie in diesem Fall das Problem lösen, denn es ist bekannt, dass Algorithmen für den allgemeinen Fall exponentielle Zeitkomplexität haben. Auf der Suche nach einem allgemeingültigeren Algorithmus für das Problem, der die oben genannten Wünsche erfüllt, können wir zunächst feststellen, dass der Dijkstra-Algorithmus in jedem Fall mit höchstens O(n2) Operationen zu Ende kommt, allerdings bei Existenz negativer c(k) eventuell eine falsche Lösung liefert. Die Überprüfung der Lösung auf Gültigkeit erfordert O(m) Testoperationen: Es muss für alle k ∈ 1..m y(k) = t(EKn(k)) – t(AKn(k)) ≤ c(k) gelten. k* k* Bild 2.5: - zum Versagen des Dijkstra-Algorithmus Finden wir einen Bogen k* mit y(k*) > c(k*), so sind zwei Fälle denkbar – vgl. Bild 2.5: a) Es gibt von Start aus zum EKn(k*) einen Weg, der parallel zum gefundenen Weg aus Stz-Bogen über den Nicht-Stz-Bogen k*, verläuft und mit t(AKn(k*))+c(k*) kürzer ist als t(EKn(k*)): t(AKn(k*))+c(k*) < t(EKn(k*) bedeutet, c(k*) < y(k*). b) Der Bogen k* schließt den StzBg-Weg von AKn(k*) nach EKn(k*) – Länge gleich t(AKn(k*)) - t(EKn(k*)) = -y(k*) – zu einem Kreis der Länge -y(k*) + c(k*) < 0. Um die beiden Fälle zu trennen, setzen wir die Wurzel des StzBg-Baumes in den AKn(k*): • Im Fall a) hat das keine Auswirkung auf den Parallelweg aus Stz-Bogen; folglich können wir durch einfachen Ersatz des bisherigen Stz-Bogens des Knotens EKn(k*) durch den Bogen k* die Lösung in Richtung auf das Optimum (y(k) ≤ c(k)) verbessern. Zu beachten ist, dass die t-Werte aller Knoten, die zur erzeugenden Knotenmenge von cz(-k*) (- nach Aufnahme von k* in die StzBg-Menge) geändert werden müssen, und bei diesen Änderungen darf kein Bogen, der „im Gleichgewicht ist“, diesen Zustand verlassen. Die algorithmisch einfachste Lösung besteht in der Wiederholung der Bogenüberprüfung bis entweder alle Bogen im Gleichgewicht sind oder ein Kreis negativer Länge aufgedeckt wird. • Im Fall b) wird der StzBg(EKn(k*)) negativ (StzRchtg(StzBg(EKn(k*))) = -1). Folglich registrieren wir nur die Tatsache, dass ein Kreis negativer Länge existiert, führen aber den Gültigkeitstest weiter, so dass am Ende nur noch für Bogen, die Kreise negativer Länge schließen, die Testgröße c(k) - y(k) = Kreislänge < 0 gilt. Beispiel 1 In dem Netz des vorhergehenden Beispiels – Bild 2.4 – gibt der Algorithmus die Lösung rechts im Bild. Der Test zeigt, dass y([Kn2, Kn3]) = -1 > c([Kn2, Kn3]) = -3 gilt. Die Verlagerung der Wurzel in den Knoten Kn2 würde -[Kn3, Kn2] zum StzBg(Kn3) machen. Folglich schließt der Bogen k* = [Kn2, Kn3] den durch StzBg(Kn3) gegebenen Weg vom Knoten Kn3 zum Knoten Kn2, nämlich den Bogen [Kn3, Kn2], zu einen Kreis der Länge -3 - (-1) = -2. 30 Kapitel 2: Einfache Netzaufgaben Beispiel 2 – vgl. Bild 2.6: Nach dem Dijkstra-Algorithmus gilt für den Bogen k* = [2, 3] y(k*) - c(k*) = 2 > 0. Man muss ihn folglich in das Gerüst der kürzesten Wege aufnehmen - für den Bogen k = [1, 3] – vgl. Bild 2.6.2. 2 4.0 4 5.0 c=1 c=4 1 0.0 c = -3 c=3 c=3 3 3.0-dt c=3 5 6.0-dt Bild 2.6.1: Beispiel 2 für den allgemeinen Kürzeste-Wege-Algorithmus In dem Zustand den Bild 2.6.2 zeigt, ergibt die Wiederholung der Überprüfung dass [3, 4] nicht im Gleichgewicht ist, woraus die dt-Änderung von -1 am Knoten 4 nötig wird, mit Aufnahme k* = [3, 4] in das Gerüst – siehe Bild 2.6.3. 2 4.0 4 5.0 c=1 c=4 1 0.0 c = -3 c = -3 c=3 3 1.0 c=3 5 5.0-dt Bild 2.6.2: Beispiel 2 für den allgemeinen Kürzeste-Wege-Algorithmus 2 4 c=1 4.0 4.0 c=4 c = -3 1 0.0 c=3 c=3 3 1.0 c=3 5 4.0 Bild 2.6.3: Beispiel 2 für den allgemeinen Kürzeste-Wege-Algorithmus - Lösung Kapitel 2: Einfache Netzaufgaben 31 2.2 Suche nach längsten Wegen Aufgabe Bestimmung der längsten Wege: Gegeben sind • eine Datenstruktur vom Typ eNetz in Form eines gerichteten Graphen G = [K, B] und einer über B erklärten reellwertigen Funktion c(k) sowie • ein Knoten Start ∈ K. Gesucht sind zu jedem Knoten, der von Start aus erreichbar ist, ein längster elementarer Weg und seine Länge. Bei dieser vollständig analog zum Problem der kürzesten Wege gestellten Aufgabe sieht man sehr leicht, dass Schwierigkeiten entstehen, wenn es im Netz Kreise positiver Länge gibt. Bei c(k) > 0 für alle Bogen k stört jeder Kreis, obwohl die Aufgabe unter der Einschränkung, die Wege müssen elementar sein, lösbar bleibt. Aber man ahnt, dass das Problem sehr aufwendig wird (exponentiell). In der Tat steht die Aufgabe in den praktischen Anwendungen für kreisfreie Netze oder für Netze, die höchsten Kreise enthalten, deren Länge nicht positiv ist. Wir wollen uns auf Aufgaben beschränken, in denen zwar Kreise positiver Länge enthalten sein können, die aber als Fehler gelten. Folglich können wir analog zum Problem der kürzesten Wege verfahren: • Bilde die toplogische Ordnung unter Nichtbeachtung von Bogen mit c(k) ≤ 0. • Ist diese Ordnung nicht herstellbar, so liegen Kreise positiver Länge vor. Andernfalls wenden wir den folgenden laengsteWege-Algorithmus an. • Anschließend testen wir analog zum Algorithmus für kürzeste Wege k ∈ 1..m auf y(k) = t(EKn(k)) – t(AKn(k)) ≥ c(k). Ist das der Fall, so ist die optimale Lösung gefunden. Ist dagegen k* ein Bogen, für den y(k*) < c(k*) gilt, so testen auf Schließung eines Kreises positiver Länge und, wenn das nicht der Fall ist, korrigieren wir t(EKn(k*)) und wiederholen den Test. Die wichtigste Anwendung ist die Prozessablaufplanung mittels so genannter Netzplantechnik: In dieser Anwendung stellen die Bogen eines gerichteten Graphen - genannt Netzplan - Teilprozesse – genannt Aktivitäten oder Vorgänge – eines Gesamtprozesses dar. Die Knoten repräsentieren als Ereignisse bezeichnete Zeitpunkte im Ablauf, insbesondere Beginnzeitpunkte und Endzeitpunkte von Aktivitäten; Abhängigkeiten der Art (einfachster Fall), Aktivität j kann erst beginnen, wenn Aktivität i beendet ist. (Beispiel: Die Dachkonstruktion kann erst begonnen werden, wenn ihre Stützkonstruktion fertig ist.) Jeder Aktivität hat eine Dauer d(i). Gesucht sind die Anfangs- und Endtermine at(i) bzw. et(i) aller Aktivitäten. Unterstellen wir et(i) = at(i) + d(i), so ist für jeden Knoten at(i), die wesentliche gesuchte Größe und offensichtlich gilt, at(j) ≥ max{et(i) | für alle i = AK(k) mit k ∈ EBg(j)}. Das bedeutet, der früheste mögliche Anfangstermin des Vorgangs j ist gleich der Länge eines längsten Weges vom Startereignis des Gesamtprojektes zum Vorgang j. In einem solchen Netzplan würde ein Kreis mit den Aktivitäten i1 → i2 → ... → ie → i1 bedeuten, dass Aktivität i1 vor i2, i3, ..., ie fertig sein müsste und ie vor i1 – also ein offensichtlicher logischer Widerspruch. Zur Lösung unseres Problems der längsten Wege gibt es einen nach Dantzig benannten Algorithmus, der Kreisfreiheit voraussetzt. Im kreisfreien Graphen kann eine topologischen Ordnung der Knoten hergestellt werden, d.h., eine derartige Knotennummerierung, tOrd(i), dass für jeden Bogen k gilt, tOrd(AK(k)) < tOrd(EK(k)). tOrd(i) = 1 kann nur für eine Quelle i des Graphen gelten, d.h., für einen Knoten i, der keine Eingangsbogen besitzt, für den also |EBg(i)| = 0 gilt. Algorithmus: a) Man nummeriere zunächst die Quellen des Graphen in beliebiger Reihenfolge. 32 Kapitel 2: Einfache Netzaufgaben b) Man entferne die nummerierten Knoten sowie ihre Ausgangsbogen. Ist der Restgraph nicht leer, so wiederhole man Punkt a) unter Fortsetzung der Nummerierung. Die folgende Methode zur Realisierung dieses Algorithmus operiert mit einem Hilfsarray AnzEinBg, das anfangs die Anzahl der Eingangsbogen jedes Knotens enthält: Die Knoten mit AnzEinBg[i] == 0 werden in die resultierende Ordnungsliste aufgenommen. Nun wird die Ordnungsliste sukzessive durchlaufen, und bei jedem Endknoten eines Ausgangsbogens k aus einem ihrer Knoten wird AnzEinBg[Ekn(k)] um 1 reduziert. Wird dabei AnzEinBg[i] == 0 erzielt, so wird der Knoten i an die Ordnungsliste angehängt. public int[] tOrd() { int i, j, k, s, sA, sE, z; boolean Abbr; int[] result = new int[n+1]; int[] AnzEinBg = new int[n+1]; initT(Infinit); z = 0; for (i = 1; i <= n; i++) { AnzEinBg[i] = 0; k = eEinBg(i); while (istBg(k)) {AnzEinBg[i]++; k = nEinBg(i, k); setT(I,0);} if (AnzEinBg[i] == 0) {z++; result[z] = i;} } sA = 1; sE = z; Abbr = (z==0); while (!Abbr) { Abbr = true; for (s = sA; s <= sE; s++) {i = result[s]; k = eAusBg(i); while (istBg(k)) {j = EKn(k); AnzEinBg[j]--; if (AnzEinBg[j] == 0) { z++; result[z] = j; Abbr = false; } k = nAusBg(i, k); } } if (!Abbr) {sA = sE+1; sE = z; } } result[0] = z; return result; } Mit einer topologischen Ordnung im kreisfreien Graphen ist die Berechnung der längsten Wege dann sehr einfach: Man durchläuft die Knoten i in der topologischen Ordnung und gibt jedem das Maximum der Werte getT(AKn(k)) + c(k) für k ∈ EBg(i) als Potential (Weglänge) t(i). Die mögliche Existenz von Kreisen und speziell solchen positiver Länge verkompliziert das Verfahren: In diesem Fall wird nur den Knoten, die mit einer Quelle des Gesamtnetzes zusammenhängen und keinem Kreis angehören, eine Ordnungsnummer erteilt. Damit die Längste-Wege-Rechnung nur auf dem zugehörigen Untergraphen ausgeführt wird, wird in der Prozedur tOrd bei der Aufnahme eines Knoten in die Ordnungsliste ein vorher für alle Knoten auf Infinit gesetzter t-Wert auf 0 korrigiert. Ferner ist zu beachten, dass zwecks Kreisausschluss in tOrd nur Bogen mit c(k) ≥ 0 berücksichtigt werden, was dazu führen kann, dass sie beim regulären Verfahren nicht richtig berücksichtigt werden. Aus diesem Grund enthält die nachfolgende Prozedur laengsteWege() nach dem eigentlichen Algorithmus einen Test jedes Bogens k auf c(k) < t(k) vorgenommen. Wird ein solcher Bogen gefunden, so wird – analog zur Berechnung kürzester Wege – zunächst getestet, ob der Bogen einen Kreis positiver Länge schließt, und bei Verneinung eine Korrektur der t-Werte vorgenommen. Anschließend wird dieser Test vollständig wiederholt. Wir demonstrieren die Algorithmen am Beispiel im Bild 2.7: Die Knoten sind bereits in der topologischen Ordnung nummeriert, die das Netz zulässt, wenn der Bogen [Kn3, Kn2] ignoriert wird. Kapitel 2: Einfache Netzaufgaben 33 c = -3 Kn3 10 c=4 c = 10 c = -3 Kn2 2 c=4 Kn3 10 Kn2 7 c = 10 c=2 Kn1 0 c=2 Kn1 0 Bild 2.7: Längste Wege und Kreise positiver Länge Nun werden den Knoten sukzessive die Werte t(Kn1) = 0; t(Kn2) = 2; t(Kn3) = max{t(Kn1)+10, t(Kn2)+4} = 10 zugewiesen – siehe linkes Teilbild. Die anschließende Durchmusterung der Bogen zeigt, y([Kn3, Kn2]) = -8 < c([Kn3, Kn2]) = -3. Es folgt, t(Kn2) = t(Kn3) – 3 = 7 – siehe rechtes Teilbild. Die wiederholte Durchmusterung der Bogen zeigt, y([Kn2, Kn3]) = 3 < c([Kn2, Kn3]) = 4, aber der Kreistest (setzWrz(Kn2) impliziert StzBg((Kn3) < 0) zeigt, dass der Bogen einen Kreis der Länge 1 schließt. Die Prozedure endet also mit den Informationen des rechten Teilbilds und der Aussage, dass ein Kreis positiver Länge vorliegt. public boolean laengsteWege() { double T,dY; int i,k,kS; boolean posKreis=false, bogenfund=false; int[] tOrd=tOrd(); initT(-Infinit); int N=tOrd[0]; posKreis=N<n(); if (N>0) { i=tOrd[1]; setStzBg(i,WrzBg); setT(i,0); for (int z=2; z<=N; z++) { i=tOrd[z]; setStzBg(i,WrzBg); k=eEinBg(i); while (istBg(k)) { T=getT(AKn(k))+c(k); if (T>getT(i) || (T==getT(i) && getStzBg(i)==WrzBg)) { setT(i,T); setStzBg(i,k); } k=nEinBg(i,k); } } do { k=1; bogenfund=false; while ((k<=m()) && !bogenfund) { dY=c(k)-getY(k); bogenfund=(getT(AKn(k))>-Infinit) && (getT(EKn(k))>-Infinit) && dY>eps; if (bogenfund) { setzWrz(AKn(k)); kS=getStzBg(EKn(k)); posKreis=kS<0; if (!posKreis) { if (kS==WrzBg) { initMarke(1); setMarke(EKn(k),2); } else markCZ(kS); for (i=1; i<=n(); i++) if (getMarke(i)==2) setT(i,getT(i)+dY); setStzBg(EKn(kS),k); } } else k++; }; } while ( !posKreis && (k<=m()) ); setzWrz(tOrd[1]); } return posKreis; } 34 Kapitel 2: Einfache Netzaufgaben Eine sehr schöne Anwendung des Längste-Wege-Problems, außerhalb der Netzplantechnik, ist für das Knappsackproblem bekannt: Knappsackproblem Minimiere die Zielfunktion c1 x1 + c2 x2 + ... + cn xn unten folgenden Bedingungen: • • xj ∈ {0, 1} für j = 1, 2, ..., n g1 x1 + g2 x2 + ... + gn xn ≤ G. Die bekannteste Anwendungssituation dieser Aufgabe ist folgende: Gegeben sind n Gegenstände mit ihren Gewichten gi und ihren Werten cj, j = 1, 2, …, n. Unter ihnen soll eine derartige Auswahl getroffen werden – xj ∈ {0, 1} – dass die Summe der Gewichte eine vorgegeben Schranke G – das Gewicht eines gefüllten Ruck- bzw. Knappsacks – nicht übersteigt und der Gesamtwert der Auswahl maximal ist. Unter der kaum einschränkenden Voraussetzung, dass alle gj ganzzahlige Werte besitzen, bilden wir folgendes Modell: Wir bilden die Aufgabe auf einen Graphen ab – vgl. Bild 2.7. Dieser besitzt • Knoten ij – zunächst für i = j = 0, sodann gehen von jedem Knoten ij höchstens zwei Bogen aus: • Der Bogen [ij, i(j + 1)] mit der Länge c = 0, der für xj = 0 steht und der Bogen [ij, (i + gj)(j + 1)] mit der Länge c = cj, der für xj = 1 steht. Knoten ij mit i > G, entfallen, denn i ist das Gewicht einer möglichen Rucksackfüllung. Wir fügen einen Abschlussknoten mit der Bezeichnung E hinzu und verbinden alle Knoten in mit diesem Knoten. 00 01 g 11 02 g 12 g1+g21 0n g 1n g1+g2n E Bild 2.8: Der Graph zum Knappsackproblem Der längste Weg vom Knoten 00 zum Knoten E in diesem kreisfreien Graphen beschreibt dann die wertvollste Rucksackpackung. Seine Länge ist gleich dem Wert der Packung. Führt dieser längste Weg über den Knoten gn nach E, so hat die wertvollste Rucksackpackung das Gewicht g, und sie besteht aus den Gegenständen j für die die Bogen [ij, (i + gj)(j+ 1)] im Weg enthalten sind. Zur Lösung der Aufgabe empfiehlt sich folgender Algorithmus: In einem Array Packung[i] aus (G + 1) Zahlenpaaren (X, C) speichert man die Knoten ij des Graphen, die zu einem fixierten Gegenstandsindex j gehören, mit Informationen über den längsten Weg vom Knoten 00 zu diesem Knoten: Kapitel 2: Einfache Netzaufgaben 35 • • eine natürliche Zahl X, deren Dualdarstellung den Weg beschreibt (Stelle j besetzt bedeutet Gegenstand j einpacken.) und eine reelle Zahl C, die die Länge Weges, also den Wert der beschriebenen Packung angibt. Anfänglich initialisiert man das Array mit Paaren (0.0, -1) und Packung[0] := (0.0, 0). Für j = 1, 2, …, n sucht man für i = i max, imax-1, …, 0, mit imax der maximale Index im Array Packung[i], die besetzten Stellen Packung[i] = (X, C) mit X ≠ -1: Für ineu := i + gj ; prüft man • ist ineu ≤ G? – andernfalls weiter mit i := i – 1; • ist C + cj > Cneu? für (Xneu, Cneu ) = Packung[ineu] - in diesem Fall: Xneu := X + 2j-1; Cneu := C + cj ; (Der maximale Index im Array Packung[i] hat die Werte i max = 0, g1, g1 + g2, …, G.) Ist die Doppelschleifen (j = 1, 2, …, n und für jedes j i = i max, imax-1, …, 0) abgearbeitet, so ist noch im Array Packung[i] das Maximum der C-Werte zu bestimmen. Beispiel j 1 2 3 4 cj 13 10 8 6 gi 9 7 5 4 Maximales Gesamtgewicht der gesuchten Packung G = 16: 5 5 4 6 2 2 Die nachfolgende Tabelle gibt in ihren Spalten die Endzustände von Packung[i] nach jeder j-Schleife an; sie zeigt also im Prinzip den Graphen des Modells (Abb. 2.7) für das Zahlenbeispiel. Über die reellen Zahlenwerte (C-Werte) der letzten Spalte muss maximiert werden. Es ergibt sich 1 2 3 maxGewinn = 24, erreicht für die Packung 14 = 0 + 2 + 2 + 2 + 0 +0, also für die Gegenstände 2, 3 und 4, die ein Gewicht von 16 hat. Die Tabelle ist zur Lösung aller Aufgaben mit der Vorgabe G ≤ 16 geeignet; also z.B. für G = 9: ergibt sich ein maxGewinn = 14, erreicht für die Packung 12 = 0 + 0 + 22 + 23 + 0 +0, also für die Gegenstände 3 und 4, die ein Gewicht von 9 (= 5 + 4) besitzt, während die beste Packung mit dem Gesamtgewicht 10 nur einen maxGewinn = 13 erreicht – für die Gegenständen 4, 5 und 6. cj gj i/j 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 0 (0, 0) 13 9 1 (0, 0) 10 7 2 (0, 0) 8 5 3 (0, 0) 6 4 4 (0, 0) 5 4 5 (0, 0) 2 2 6 (0, 0) ( 2, 32) (13, 1) ( 8, 4) ( 6, 8) ( 8, 4) ( 6,16) ( 8, 4) (10, 2) (10, 2) (10, 2) (13, 1) (13, 1) (14,12) (10, 2) (11,24) (13,20) (21, 5) (16,10) (18, 6) (19, 9) (21, 5) (23, 3) (24,14) (18, 6) (23, 3) (16, 8) (18, 6) (19, 9) (21, 5) (21,26) (24,14) ( 6, 16) ( 8, 4) ( 8, 48) (10, 2) (11,24) (14,12) (13,56) (16, 8) (18, 6) (19, 9) (21, 5) (21,16) (24,14) 36 Kapitel 2: Einfache Netzaufgaben 2.3 Minimalgerüste Aufgabe In einem eNetz ist unter allen Gerüsten des Graphen dasjenige gesucht, für das die Summe seiner Bogenlängen minimal ist. Das Minimalgerüstproblem ist sehr breit untersucht worden, so dass eine Vielzahl von Algorithmen vorliegt. Viele sind so genannte Greedy-Algorithmen (von engl.: greedy = gierig, gefräßig). Dabei geht es um ein Lösungsprinzip für Aufgaben der diskreten Optimierung, das darin besteht, schrittweise immer das aktuell beste Element zu wählen: Greedy-Prinzip am Beispiel • Bogen := B (Bogenmenge des Graphen); Grst := ∅; • Solange Grst kein vollständiges Gerüst beschreibt, entnehme und entferne aus Bogen den Bogen k mit kleinstem c(k). (Man nutze dazu, den im Abschnitt „Kürzeste Wege eingeführten – Prioritätsheap) • Verletzt die Hinzunahme dieses Bogens zu Grst nicht die Zyklenfreiheit, so wird er in Grst aufgenommen. Greedy-Algorithmen liefern genau dann optimale Lösungen, wenn ein so genanntes Matroid vorliegt, was bedeutet, das über Mengen einer Familie optimiert wird, die folgende Eigenschaften haben: 1. Die leere Menge gehört zur Familie. 2. Jede Untermenge einer Menge, die zur Familie gehört, gehört ebenfalls zur Familie. 3. Alle maximalen Mengen der Familie haben die gleiche Elementanzahl. Die Familie der zyklenfreien Bogenmengen eines Graphen bildet ein solches Matroid. Das Problem des obigen Algorithmus bildet die effiziente Ausführung des Tests auf Zyklenfreiheit. Der folgende Algorithmus umgeht diesen ganz. • • KnMenge := {1}; Bogen := CZ(KnMenge); solange Kandidaten ≠ ∅, wähle man aus dieser Menge den Bogen k mit kleinstem |c(k)| (↑ Prioritätsheap); KnMenge := KnMenge + {EKn(k)}; Kandidaten := CZ(KnMenge); (Beweis durch vollständige Induktion.) Die Worst-Case-Zeitkomplexität kann mit O(m⋅log(m)) abgeschätzt werden (m = Bogenanzahl), wenn man mit einem Prioritätsheap arbeitet. Diese Zeitkomplexität ist optimal. public double Minimalgeruest() { int j, k; PriorHeap Kandidaten; ElementtypIR ID; double result = 0; initT(Infinit); initStzBg(0); Kandidaten = new PriorHeap(m+1); Kandidaten.setMax(true); Kandidaten.pushOpt(new ElementtypIR(WrzBg, 0.0)); while (!Kandidaten.istLeer()) { ID = (ElementtypIR) Kandidaten.exOpt(); k= ID.getInt(); if (k == WrzBg) j = 1; else j = EKn(k); if (getStzBg(j) == 0) { setStzBg(j,k); if (j != 1) result = result+c(k); k=eInzBg(j); while (istBg(k)) { if (getStzBg(EKn(k)) == 0) Kandidaten.pushOpt(new ElementtypIR(k,c(k))); k=nInzBg(j,k); } } } return result; } Kapitel 2: Einfache Netzaufgaben 37 Kn2 3 c=3 c=5 Kn4 5 c=3 Kn6 12 c=4 Kn3 4 c=3 c=5 c=2 Kn1 c=6 Kn5 7 c=5 Kn7 10 c=3 c=1 c = 10 Bild 2.9.1: Ein Beispiel für den Minimalgerüst-Algorithmus Wir demonstrieren den Algorithmus an dem im Bild 2.9 gezeigten Beispiel: KnMenge := {Kn1}, Kandidaten := {[Kn1, Kn2], [Kn1, Kn3], [Kn1, Kn4]}, PH = {3, 4, 6}, min{PH} = 3 für k = [Kn1, Kn2]; KnMenge := {Kn1, Kn2}, Kandidaten := {[Kn1, Kn3], [Kn1, Kn4], -[Kn2, Kn4], [Kn2, Kn5]}, PH = {4, 6, 5, 5}, min{PH} = 4 für k = [Kn1, Kn3]; KnMenge := {Kn1, Kn2, Kn3}, Kandidaten := {[Kn1, Kn4], -[Kn2, Kn4], [Kn2, Kn5], [Kn3, Kn4], [Kn3, Kn6]}, PH = {6, 5, 5, 1, 10}, min{PH} = 1 für k = [Kn3, Kn4]; KnMenge := {Kn1, Kn2, Kn3, Kn4}, Kandidaten := {[Kn2, Kn5], [Kn3, Kn6], [Kn4, Kn5], -[Kn6, Kn4]}, PH = {5, 10, 2, 3}, min{PH} = 2 für k = [Kn4, Kn5]; KnMenge := {Kn1, Kn2, Kn3, Kn4, Kn5}, Kandidaten := {[Kn3, Kn6], [Kn5, Kn6], [Kn5, Kn7], -[Kn6, Kn4]}, PH = {10, 3, 5, 3}, min{PH} = 3 für k = -[Kn6, Kn4] - willkürliche Wahl; KnMenge := {Kn1, Kn2, Kn3, Kn4, Kn5, Kn6}, Kandidaten := {[Kn5, Kn7], [Kn6, Kn7]}, PH = {3, 3}, min{PH} = 3 für k = [Kn5, Kn7] - willkürliche Wahl; KnMenge := {Kn1, Kn2, Kn3, Kn4, Kn5, Kn6, Kn7} = K, Kandidaten = ∅ , Ende des Algorithmus, Gesamtlänge des Gerüstes = 16. Kn2 c=5 Kn5 c=3 c=3 c=5 Kn1 c=6 Kn4 c=2 c=3 c=5 Kn6 Kn7 c=3 c=4 Kn3 c=1 c = 10 Bild 2.9.2: Ein Beispiel für den Minimalgerüst-Algorithmus – Lösung (fett) 38 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 3. Minimalkosten-Strom- und Spannungsoptimierung 3.1 Einfache Transportkosten-Minimierung Wir beginnen mit einer Anwendungsaufgabe Ein Graph G modelliert ein Straßen-, Schienen- oder auch Leitungsnetz in dem ein Transportgut bewegt wird. Einige der Knoten des Netzes sind als Quellen des Transportgutes ausgewiesen - mit Angabe der möglichen Liefermengen. Andere Knoten sind Empfänger des Gutes - mit feststehendem Bedarf. Für jeden Bogen k sind drei reelle Zahlen a(k), b(k), c(k) vorgegeben: • Die als „Transportpreise“ bezeichneten Bogenlängen c(k) geben die Kosten an, die der Transport einer Einheit des betrachteten Transportgutes entlang der durch den Bogen k modellierten Strecke kostet. c(k) = 0 gelte als Standard. • a(k) ist die Mindestmenge des Transportgutes, die auf der Strecke k in einem fixierten Zeitraum transportiert werden muss. In den meisten Fällen gilt a(k) = 0 (Standard!). • b(k) ist die maximale Menge, die in dem fixierten Zeitraum auf der Strecke k transportiert werden kann. Häufig gilt b(k) = ∞ (Standard!). Gesucht ist ein Transportplan x, der bei Einhaltung aller genannten Bedingungen die Gesamtkosten minimiert. Zwecks besserer Modellierung ergänzen wir den Graphen G durch die zwei Knoten Q (Quelle) und S (Senke) sowie die folgenden Bogen: a) Ein Zusatzbogen führt von Q zu jedem Knoten des Originalgraphen, der Quelle des Transportgutes ist. Ein solcher Bogen bekommt als untere Fluss-Schranke a den Wert Null, als oberer Fluss-Schranke b die Lieferkapazität des Lieferanten und als Preis c den Lieferpreis dieser Quelle, falls diese Preise in die Optimierung einbezogen werden sollen, sonst den Wert Null. b) Ein Zusatzbogen führt von jedem Knoten des Originalgraphen, der Empfänger des Transportgutes ist, zu S. Ein solcher Bogen bekommt als untere Fluss-Schranke a den Bedarf des Empfängers, als oberer Fluss-Schranke b den Wert Unendlich und als Preis c den Preis, zu dem der Empfänger bereit ist, die Ware zu übernehmen mit negativem Vorzeichen oder auch den Wert Null (vgl a)). c) Ein Bogen, der so genannte Rückkehrbogen, führt von S nach Q. Er erhält die untere FlussSchranke Null, die obere Fluss-Schranke Unendlich und den Bogenpreis Null. Wir unterstellen zu dem erweiterten Netz G’ einen Vektor x = (x(1), x(2), ..., x(m)), der für jeden Bogen k einen Fluss x(k) enthält, der zwischen den Schranken. a(k) und b(k) liegt. Dieser Vektor x der Bogenflüsse auf dem erweiterten Netz liefert offensichtlich eine zulässige Lösung des formulierten Transportproblems: • Die Flüsse der von Q ausgehenden Bogen geben die tatsächlichen Liefermengen der Lieferanten an, die die Lieferkapazitäten nicht überschreiten. • Die Flüsse der in S einmündenden Bogen geben die bei den Empfängern ankommenden Mengen an. Diese sind kleiner/gleich den Bedarfswerten. • Der Fluss durch den Rückkehrbogen ist gleich der Summe aller bei den Empfängern eingehenden Mengen und außerdem gleich der Summe aller Lieferungen der Quellen. • Die Flüsse des Originalgraphen G beschreiben den Transportplan. Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 39 Aufgabe Minimalkosten-Stromproblem Gegeben ist eine Datenstruktur vom Typ tNetz in Form eines gerichteten Graphen G = [K, B] und den über B erklärten reellwertigen Funktionen a(k), b(k) und c(k). Für a(k) und b(k) gilt a(k) ≤ b(k). Gesucht ist ein über B erklärter Vektor x, der folgende Bedingungen erfüllt: 1) x ist Strom in G. 2) Es gilt a(k) ≤ x(k) ≤ b(k) für k ∈ B. 3) x ist unter allen Vektoren, die die Bedingungen 1) und 2) erfüllen, einer der die Funktion z(x) = ∑{c(k)·x(k) | k = 1, 2, ..., m} minimiert. Für die Bogenparameter mögen folgende Standards gelten: a(k) = 0, b(k) = ∞, c(k) = 0, und im Hinblick auf negative Bogenbenennungen gelten folgende Festlegungen: a(-k) = -b(k), b(-k) = -a(k), x(-k) = -x(k), c(-k) = -c(k). Das Problem kann als eine mathematische Formulierung einer Transportkosten-Minimierung betrachtet werden, wie die obige Darlegung zeigt. Die Aufgabe der Transportkostenoptimierung wird häufig durch ein Matrixschema gemäß Tabelle 3.1 beschrieben. Bei l Lieferanten enthält die erste Spalte die Lieferkapazitäten αi, i = 1, 2, ..., l; bei e Empfängern enthält die erste Zeile die Bedarfszahlen βj, j = 1, 2, ..., e, und schließlich gilt für i = 1, 2, ..., l und j = 1, 2, ..., e, dass das Matrixelement γij den Preis für den Transport einer Einheit des betrachteten Gutes vom i-ten Lieferanten zum j-ten Empfänger darstellt. Diese Schematisierung entsteht aus einer wie oben formulierten Anwendungsaufgabe, indem man von jedem Lieferknoten i zu jedem Empfängerknoten j im Graphen G die Länge γij des kürzesten Wegs berechnet. α1 α2 . . . αl β1 γ11 γ21 . . . γl1 β2 γ12 γ12 . . . γl2 ... ... ... βe γ1e γ1e . . . γle Tabelle 3.1 Diese starke tabellarische Schematisierung schränkt die Allgemeinheit unnötig ein - z.B. dadurch, dass die Größe einer Lieferung nicht beschränkt werden kann. Im Übrigen kann sie ihrerseits auf ein Minimalkosten-Stromproblem abgebildet werden – Knoten für die Lieferanten, Knoten für die Empfänger, Bogen von jedem Lieferanten zu jedem Empfänger und anschließend die Ergänzung durch die Knoten Q und S sowie die mit ihnen verbundenen Bogen. Dabei kann die Einschränkung für die Lieferungen von i nach j auf aij = 0 und bij = ∞, die die Matrizenformulierung implizit enthält, aufgehoben werden vgl. Bild 3.1. 40 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung b = γij b = αi b = βj Liefer1 Empfang1 Liefer2 Empfang2 Q S Lieferl Empfange c = -gross Bild 3.1: Die klassische Transportaufgabe in Netzform Dass das Minimalkosten-Stromproblem als Modell für Transportaufgaben wesentlich leistungsfähiger ist als das klassische Transportschema demonstriert das folgende Beispiel: Grundsätzlich liegt die gleiche Situation vor, wie im obigen Anwendungsbeispiel, allerdings wird die Ware jetzt nicht direkt von den Lieferanten zu den Empfängern transportiert, sondern über eine Reihe von r Zwischenlagern. Die Produzenten liefern an eines der Lager, und die Empfänger decken ihren Bedarf aus den Lagerbeständen. In den Zwischenlagern entstehen natürlich Lagerkosten, und die Lager haben nur eine begrenzte Lagerkapazität. Zur Umformung auf ein Minimalkosten-Stromproblem werden die Knoten, in denen sich Lager befinden, durch Hilfsbogen [Lagereingang, Lagerausgang] ersetzt. Der Knoten Lagereingang bekommt als Eingangsbogen alle Eingangsbogen des Originalknotens und als einzigen Ausgangsbogen den neuen Bogen. Der Knoten Lagerausgang bekommt als einzigen Eingangsbogen den neuen Bogen und als Ausgangsbogen alle Ausgangsbogen des Originalknotens. Die Bogen [Lagereingang, Lagerausgang] erhalten die untere Fluss-Schranke Null, als obere Fluss-Schranke die Kapazität des Lagers und als Bogenpreis die Kosten der Lagerung einer Einheit der Ware in diesem Lager (Lagerpreis). Bild und Tabelle 3.2 skizzieren das so gebildete Netz mit schematischen direkten Transportverbindungen Lieferanten→Lager und Lager → Empfänger. Von Q Lieferi LgEk LgAk Empfngj S Nach Lieferi LgEk LgAk Empfngj S Q a 0 0 0 0 0 0 b αi ∞ Lg.-Kapk ∞ βi ∞ c 0 γik Lg.-Kost.k γ*kj 0 -gross Tabelle 3.2 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 41 b = Lg-Kap., c = Lg-Preis. Liefer 1 LgE1 LgA1 Empfng 1 Liefer 2 LgE2 LgA2 Empfng 2 Q S LgEr Liefe rl LgAr Empfn ge c = -gross Bild 3.2: Ein Modell für Transport über Zwischenlager Anwendungsbeispiel Mehrgütertransport In vielen praktischen Transportaufgaben werden mehrere Güter gleichzeitig betrachtet: Wir unterstellen, dass eine Reihe von Produzenten ein Spektrum von Gütern herstellen. Die verschiedenen Waren werden getrennt transportiert. Jeder der Produzenten hat einerseits eine beschränkte Gesamtlieferfähigkeit und andererseits für jedes der Güter eine obere Kapazitätsschranke - z.B. ist es denkbar, dass er einige Waren des Sortenspektrums überhaupt nicht produziert. In dem einfachen Fall, dass sich die Mengenangaben so dimensionieren lassen, dass die Gesamtlieferung jedes Produzenten durch die Summe der von ihm produzierten Mengen aller Sorten gegeben ist, lässt sich die Aufgabe durch das mit Bild und Tabelle 3.3 skizzierte Netz modellieren. Auch in diesem Fall beschränkt sich die Skizze auf schematische Liefernetze für jede Warensorte. Jedes „Sortennetz“ Sorte k hat für jeden Produzenten i dieser Sorte einen Lieferknoten LieferSik. Alle Lieferknoten des gleichen Produzenten i sind durch eine Konstruktion verbunden, die über einen gemeinsamen Eingangsbogen eines Knotens Lieferi sichert, dass die Summe aller Lieferungen kleiner/gleich der oberen Fluss-Schranke des Bogens [Q, Lieferi] ist. Von Q Lieferi LieferSik EmpfgSjk S Tabelle 3.3 Nach Lieferi LieferSik EmpfgSjk Q Q a 0 0 0 0 0 b Gesamtlieferkapazi Sortenkapazik ∞ Bedarfjk ∞ c 0 0 γijk für Sk 0 -gross 42 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung LieferS11 EmpfgS11 Liefer1 LieferS l1 LieferS12 LieferS l2 EmpfgSe1 EmpfgS12 EmpfgSe2 Q LieferS1s Q EmpfgS1s Lieferl LieferS ls EmpfgSes Bild 3.3: Ein Modell für Mehrgütertransport 3.2 Ergänzung der theoretischen Grundlagen 3.2.1 Ströme und Spannungen Wir haben im Kapitel 1 kurz den Begriff Strom oder Zirkulation x eines Graphen als Linearkombination aus Zyklusvektoren z(k) eingeführt: x = Σ ( α(k)⋅z(k) | für k Cogerüstbogen) Man kann das auch wie folgt formulieren: Definition Ein S t r o m ist ein Bogenvektor x, der durch die Vorgabe seiner Flüsse auf den Bogen eines Cogerüstes eindeutig festgelegt ist. Die Komponente x(k) zum Bogen k eines Stromvektors wird als F l u s s durch den Bogen bezeichnet. Wir wollen jetzt zeigen, dass ein Strom folgende Eigenschaft erfüllt: Kirchhoffscher Knotensatz Für jede Untermenge K’ der Knoten gilt: Die Summe der Flüsse ihrer Eingangsbogen ist gleich der Summe der Flüsse ihrer Ausgangsbogen. Σ ( x(k) | k ∈ CZ(K’) & k < 0) = Σ ( x(k) | k ∈ CZ(K’) & k > 0) oder Σ ( x(k) | k ∈ CZ(K’)) = 0. Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 43 Dazu beweisen wir folgenden: Satz Das Skalarprodukt aus einem beliebigen Zyklusvektor und einem beliebigen Cozyklusvektor ist Null. Beweis: Wir betrachten das folgende Bild 3.4. Es zeigt einen Zyklus Z und einen elementaren Cozyklus CZ(K’). Die Knotenmenge K’, die den Cozyklus erzeugt, ist durch eine Umrisslinie angedeutet. Die vier Z und CZ gemeinsamen Bogen sind fett hervorgehoben. Es ist leicht einzusehen, dass ein Zyklus und ein Cozyklus, wenn sie überhaupt gemeinsame Bogen besitzen, eine gerade Anzahl gemeinsamer Bogen haben: Einem gemeinsamen Bogen k, mit dem der Zyklus in einen Knoten des Untergraphen U(K’) eintritt, folgt beim Durchlauf durch den Zyklus stets ein Bogen k’, mit dem er den Untergraphen wieder verlässt. k und k’ sind Bogenbenennungen aus der Sicht des Zyklus. Sollten die Originalrichtungen der beiden Bogen nicht der im Bild dargestellten Zyklusdurchlaufrichtung entsprechen, so ändert das nichts an der folgenden Argumentation, da sich dann das jeweilige Vorzeichen sowohl im Zyklus als auch im Cozyklus ändert: Die Zykluskomponenten beider Bogen sind Eins. Die Cozykluskomponenten jedoch sind +1 bzw. -1, folglich gilt im Skalarprodukt 1×1 + 1×(-1) = 0. k k’ Bild 3.4: Durchschnitt von Zyklus und Cozyklus Parallel zum Begriff Strom haben wir im Kapitel 1 den Begriff Spannung als Linearkombination aus Cozyklusvektoren eingeführt: y = Σ(β(k)⋅cz(k) | für k Gerüstbogen) Analog zum Strom formulieren wir wie folgt: Satz Eine Spannung ist durch die Vorgabe ihrer Werte auf den Bogen eines Gerüstes eindeutig festgelegt. Gemäß dem Satz, dass jeder Zyklusvektor orthogonal zu jedem Cozyklusvektor ist, erfüllt eine Spannung folgende Eigenschaft: Kirchhoffscher Maschensatz Für jeden Zyklus gilt: Die Summe Spannungskomponente und Richtungsfaktor aller seiner Bogen ist Null. Σ ( y(k) | k ∈ Z & k < 0) = Σ ( y(k) | k ∈ Z & k > 0) oder Σ ( y(k) | k ∈ Z) = 0. der Produkte aus Die charakteristischen Eigenschaften einer Spannung sind deutlicher zu erkennen, wenn man den Begriff des Potentials hinzunimmt, den wir im Kapitel 2 im Zusammenhang mit Wegaufgaben für 44 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung einen Knotenvektor eingeführt haben. Ist t ein Potential, so bezeichnen wir für eine Bogenbenennung k die Potentialdifferenz durch y(k) = t(EKn(k)) - t(AKn(k)). Es gilt folgender Satz: Satz Zu einer Spannung y = (y(1), y(2), ..., y(m)) kann ein Potential t so angegeben werden, dass für jeden Bogen k y(k) die Potentialdifferenz des Bogens ist. Ein solches der Spannung z u g e o r d n e t e P o t e n t i a l ist bis auf p frei wählbare Werte eindeutig bestimmt, wobei p die Anzahl der zusammenhängenden Komponenten des Graphen ist. Umgekehrt erzeugen die Potentialdifferenzen jedes Potentials eine Spannung. Der Beweis dieses Satzes ist sehr einfach: Für die erste Aussage geben wir den Wurzelknoten des Gerüstes, das die Spannung erzeugt, einen beliebigen Potentialwert und bestimmen dann sukzessive die Potentialwerte der Knoten, die noch keinen Potentialwert haben aber mit einem der Knoten, dem bereits ein Potentialwert zugewiesen ist, durch einen Gerüstbogen verbunden sind. In umgekehrter Richtung betrachten wir einen Zyklus als Folge von Bogenbenennungen [k1, k2, …, kr]. Mit der Eigenschaft AKn(ki+1) = EKn(ki) für i = 1, 2, …,r – 1 und EKn(kr) = AKn(k1). Für die Summe der Potentialdifferenzen längs des Zyklus gilt folglich, y(k1) + y(k2) + … + y(kr) = (t(EKn(k1)) - t(AKn(k1))) + (t(EKn(k2)) - t(EKn(k1))) + … + (t(AKn(k1)) - t(EKn(kr-1))) = 0, was zu beweisen war. 3.2.2 Lösbarkeit des Minimalkosten-Stromproblems Betrachten wir die Kirchhoffsche Strombedingung und schätzen die Flüsse der Bogen aus EBg(K’) durch ihre unteren Schranken a(k) und die der Bogen aus ABg(K’) durch ihre oberen Schranken b(k) ab, so muss gelten: ∑{x(k) | k ∈ ABg(K´ )} = ∑{ x(k) | k ∈ EBg(K´ )} ⇒ ∑{a(k) | k ∈ ABg(K´ )} ≤ ∑{ b(k) | k ∈ EBg(K´ )}. ⇒ ∑{b(k) | k ∈ ABg(K´ )} ≥ ∑{ a(k) | k ∈ EBg(K´ )}. Oder auch unter Berücksichtigung der Vorzeichenregeln, die unmittelbar einleuchtende Formulierung: Satz Ein Minimalkosten-Stromproblem ist genau dann lösbar, wenn für jede Knotenmenge K´ gilt, ∑{a(k) | k ∈ InzBg(K´ )} ≤ ∑{ b(k) | k ∈ InzBg(K´ )}. Die Notwendigkeit dieser Existenzbedingung erkennt man aus ∑{a(k) | k ∈ InzBg(K´ )} ≤ ∑{ x(k) | k ∈ InzBg(K´ )} ≤ ∑{ b(k) | k ∈ InzBg(K´ )}. Sie ist auch hinreichend – ohne Beweis. Zur Verdeutlichung der Bedingung ein Blick auf die einfache Transportaufgabe: Die Summe aller Bedarfszahlen muss kleiner oder gleich der Summe der möglichen Liefermengen sein, damit das Problem eine Lösung besitzt. Diese Aussage entsteht, wenn wir die Formel auf die Menge K’ anwenden, die aus allen Lieferanten- und allen Empfängerknoten besteht. Aus der Existenzbedingung ersehen wir, dass eine Lösung, nämliche die triviale Lösung x = 0, immer dann existiert, wenn a = 0 gilt, d.h., wenn alle unteren Flussschranken Null sind. Bei der Formulierung praktischer Aufgaben kann man Existenzfragen folglich auszuweichen, wenn man versucht, untere Schranken zu vermeiden: • So sollte man die einfache Transportaufgabe besser so formulieren, dass die Bedarfszahlen obere Flussschranken sind (b = β und a = 0 auf den Bogen zur Senke S), und eine maximale Bedarfsdeckung dadurch bewirkt wird, dass auf dem Rückkehrbogen als Bogenpreis ein negativer Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 45 • Wert - also ein Gewinn - angesetzt wird, dessen Betrag genügend groß sein muss, nämlich größer als das Maximum der Summen der Bogenpreise längs aller Wege von der Quelle Q zur Senke S – wodurch jeder Weg von Q nach S Gewinn bringt. Die Wirkung, die ein negativer c-Wert des Rückkehrbogens erzielt, erreicht man auch mit negativen c-Werten auf den Bogen zur Senke S. Solche negativen Preise kann man überdies sinnvoll als Preise interpretieren, zu denen die Empfänger einkaufen. Bei diesem Ansatz ist auch einzusehen, dass der Bedarf als obere Schranke angesetzt wird, nämlich als Schranke für die Gültigkeit des Kaufpreises, der sich beim Überschreiten dieser Schranke ändert. Modelliert man in dieser Weise, so erhält man in jedem Fall eine Lösung, die allerdings im Falle zu geringer Gesamtliefermenge bei einigen Empfängern den Bedarf nicht deckt. Es sind natürlich diejenigen, zu denen die Lieferkosten vergleichsweise groß sind. Auch am einzelnen Bogen k kann man Existenzschwierigkeiten umgehen, wenn man a(k) = 0 setzt und in dem zusätzlichen Bereich 0 ≤ x(k) ≤ a_orig (k). den Bogenpreis c_neu(k) = -gross setzt, wobei gross eine positive große Zahl meint. Damit führt man Strafkosten gross·(a_orig(k) - x(k)) ein (denn die konstanten Kosten gross·a_orig (k) kann man vernachlässigen) und stimuliert somit die Einhaltung der Bedingung a_orig(k) ≤ x(k): Ist gross ausreichend groß gewählt, so kann man sicher sein, dass in der existierenden optimalen Lösung a_orig(k) ≤ x(k) gilt – Kostenminimierung – sofern die Bedingung überhaupt einhaltbar ist. 3.2.3 Grundlagen des Lösungsalgorithmus für das Minimalkosten-Stromproblem Das Minimalkosten-Stromproblem ist oben klar als lineare Optimierungsaufgabe formuliert. In der Theorie der linearen Optimierung spielt der Begriff der Basis- oder Eckpunktlösung eine große Rolle, auf den wir uns im Folgenden stützen wollen, denn eine Grunderkenntnis der Theorie der linearen Optimierung besagt: Falls ein Problem überhaupt eine Lösung besitzt, so gibt es auch eine Basislösung, die optimale Lösung ist. Ist die Optimallösung nicht eindeutig, so ist jede konvexe Linearkombination aus optimalen Eckpunktlösungen x1, x2, ... d.h., jeder Vektor λ1 x1+ λ 2 x2+ ... mit 0 ≤ λ 1, λ 2, ... und λ 1 + λ 2 + ... = 1 wieder optimale Lösung. Es ist möglich und günstig, die optimale Lösung unter den optimalen Basislösungen zu suchen. Von einer Ecke des zulässigen Bereiches, der in unserem Fall durch die Forderungen 1) und 2) der obigen Problemdefinition gegeben ist, spricht man, wenn eine zulässige Lösung x eindeutige Lösung eines aus den Restriktionen abgeleiteten Gleichungssystems ist, d.h. wenn man aus den gegebenen Ungleichungen eine Teilmenge so auswählen und als Gleichungen ansetzen kann, dass dieses Gleichungssystem eine eindeutige Lösung besitzt und diese Lösung überdies die übrigen Ungleichungen erfüllt. Das Restriktionssystem 1), 2) besteht aus den Strombedingungen (etwa in Form der Kirchhoffschen Knotenbedingungen), die Gleichungsform haben und den Forderungen 2) nach Einhaltung der Flussschranken. Aus den letzteren müssen wir einen Satz so auswählen und als Gleichungen behandeln, dass diese, zusammen mit den Strombedingungen, eindeutig einen Bogenvektor x festlegen. Dabei hilft uns die Eigenschaft von Strömen: • Wir legen auf den Bogen k eines Cogerüstes x(k) = a(k) oder x(k) = b(k) fest und bilden den zugehörigen Strom. • Falls der so erzeugte Vektor x auch auf den Gerüstbogen seinen Flussschranken genügt, stellt er eine Basislösung des Problems dar. Definition Eine B a s i s l ö s u n g des Minimalkosten-Stromproblems ist ein zulässiger Strom, der für k ∈ B\B’ x(k) = a(k) oder x(k) = b(k) erfüllt. Dabei bezeichnet B’ die Bogenmenge eines Gerüstes im Graphen G = [K, B]. 46 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung Der folgende Satz, der so genannte Dualitätssatz der linearen Optimierung, ist die Basis des Lösungsalgorithmus für das Minimalkosten-Stromproblem. Auf die Wiedergabe eines Beweises wollen wir verzichten. Satz Gegeben sei eine Basislösung x des Minimalkosten-Stromproblems mit dem Gerüst G’ = [K, B’]. Auf G’ definieren wir eine Spannung durch y(k) = c(k) für k∈ B’. x ist genau dann optimale Lösung, wenn folgende Bedingung erfüllt ist: Für k ∈ B\B’ gilt: Falls x(k) = a(k), so ist y(k) ≤ c(k) und, falls x(k) = b(k), so ist y(k) ≥ c(k). Legende: i t(i) c=4 x=0 L1 10 b = 8, c = 10 0 Q E1 13 c=2 x=3 b = 5, c = 12 x=5 b = 6, c = -13 x=4 S 0 c=1 L2 12 a = 1, c = 3 x=1 E2 12 b = 4, c = -13 x=4 c=0 x=8 Bild 3.5: Transportaufgabe mit optimaler Lösung Beispiel Bild und Tabelle 3.5 beschreiben eine einfache Transportaufgabe und deren optimale Lösung. Für die Lieferanten wurden Lieferpreise c(1) und c(2) angesetzt und negative Preise c(7) und c(8) (Gewinne) bei den Empfängern. Im Bild ist ein Gerüst durch fett gezeichnete Bogen markiert (Tabellenzeilen schattiert). Auf den Bogen dieses Gerüstes wird eine Spannung bzw. ein Potential aus deren c-Werten bestimmt. Auf den Cogerüstbogen werden die Werte eines Stroms aus den Schranken bestimmt (x = 0 oder x = b). Dieser Strom ist auch auf den Gerüstbogen zulässig, und Strom und Potential genügen den im Dualitätssatz genannten Bedingungen auf den Cogerüstbogen (Tabellezeilen unschattiert). Folglich liegt eine optimale Lösung vor. k 1 2 3 4 5 6 7 8 9 Von Q Q L1 L1 L2 L2 E1 E2 S Nach L1 L2 E1 E2 E1 E2 S S Q a(k) 0 0 0 0 0 1 0 0 0 x(k) 3 5 0 3 4 1 4 4 8 b(k) 8 5 ∞ ∞ ∞ ∞ 6 4 ∞ y(k) 10 12 3 2 1 0 -13 -12 0 c(k) 10 12 4 2 1 3 -13 -13 0 Tabelle 3.5 Für die Aussage des Dualitätssatzes gibt es eine ökonomische Plausibilitätserklärung, die wir an dem obigen Beispiel erläutern wollen: Zunächst ist festzustellen, dass die Werte t(i) des Potentials die gleiche Dimension besitzen wie die Werte c(k), also in unserem Beispiel Geldeinheiten. Der Potentialwert t(i) lässt sich als Abgabepreis der Ware an ein oder mehrere Transportunternehmen im Knoten i deuten. Wenn z.B. c([Q, Li]) der Herstellungspreis der Ware beim Lieferanten Li ist, so muss der Abgabepreis t(Li) größer/gleich c([Q, Li]) sein. Insbesondere kann t(Li) > c([Q, Li]) gelten, ohne dass Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 47 ein Lieferplan aus dem Gleichgewicht geriete, wenn x([Q, Li]) = b([Q, Li]) gilt, d.h., wenn Li (kurzfristig) nicht in der Lage ist, noch mehr zu liefern. Unterstellen wir, dass der Transport von einem oder mehreren Unternehmen ausgeführt wird. Ist c(k) der Preis, den ein Transportunternehmen für den Transport einer Wareneinheit entlang der Strecke k beanspruchen kann, und nehmen wir an, dass ein Transportunternehmen die Ware im Knoten i = AKn(k) zum Preis t(i) kauft und sie im Knoten j = EKn(k) zum Preis t(j) wieder verkauft, so muss y(k) = c(k) mindestens auf den Strecken gelten, auf denen ein Transportplan a(k) < x(k) < b(k) vorsieht. Gilt für eine Strecke k die Beziehung y(k) > c(k), so erzielt das Transportunternehmen, das eine solche Strecke bedient, einen außerplanmäßigen Gewinn der Größe x(k)⋅(y(k) - c(k)). Es wird also bestrebt sein, auf dieser Strecke viel zu transportieren, d.h., ein Transportplan muss in diesem Fall x(k) = b(k) erzwingen. Im obigen Beispiel tritt y(k) > c(k) nur für k = 8 ein, also für den Bogen, der dem Empfänger E2 zugeordnet ist. Dies bedeutet, dass E2 mehr Gewinn erzielt als vorgesehen (er kauft zum Preis 12 statt zum kalkulierten Preis 13). Unter diesen Bedingungen ordert er natürlich die maximale Menge b(8) = 4. Andererseits ist b(8) die Grenze seines Aufnahmeinteresses. In gleicher Weise ist denkbar, dass für eine Strecke y(k) < c(k) gilt. Ein Transportunternehmen, das eine solche Strecke bedient, macht Verlust in Höhe von x(k)⋅(c(k) - y(k)), sodass ein Transportplan auf einer solchen Strecke die Mindestmenge x(k) = a(k) erzwingen muss (z.B. durch Subventionen). Dieser Fall tritt in unserem Beispiel 3.5 für den Bogen 6 ein (0 < 3). Dort gilt die untere Flussschranke a(6) = 1. Sie kann als technisch oder traditionell bedingte Lieferbeziehung gedeutet werden, und y(6) < c(6) sagt, dass es aus ökonomischer Sicht unsinnig ist, sie einzuhalten. Dieser Transport muss also extra stimuliert werden. Im Übrigen zeigt sich, dass der Bedarf von E1 nicht gedeckt wird, weil 2 Einheiten über den Weg Q → L1→ E1 herangeführt werden müssten, der mit der Länge 14 teurer ist als der Gewinn 13. Durch den Dualitätssatz wird für den Fall der Optimalität zu jedem Bogen k eine Abbildung, y(k) = Char(x(k)), aus der Menge der zulässigen Werte x(k) in die Menge der zulässigen Werte y(k) definiert. Das Bild 3.6 zeigt diese Abbildung als Treppenfunktion im (x(k), y(k))-Koordinatensystem. Sie wird als Charakteristik oder Gleichgewichtsgraph des Bogens k bezeichnet. Im rechten Teil der Abbildung ist die Charakteristik auf den Bereich 0 ≤ x(k) ≤ b(k) erweitert worden, indem bei y(k) = -gross eine Stufe eingefügt wurde. Dies entspricht der oben, im Abschnitt 3.2.2, geführten Diskussion um zulässige Lösungen. y(k) y(k) c(k) c(k) x(k) a(k) x(k) a_orig(k) b(k ) b(k) -gross Bild 3.6: Gleichgewichtsgraph oder Charakteristik eines Bogens k – rechts erweitert Definition Gilt für einen Strom x, eine Spannung y und einen Bogen k y(k) = Char(x(k)), so wollen wir sagen, k liegt auf seiner C h a r a k t e r i s t i k oder auch: k befindet sich in einem seiner Gleichgewichtszustände. Andernfalls sagen wir, der Bogen ist o u t - o f - k i l t e r (außerhalb seines Gleichgewichts). 48 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung Mit diesem Begriff kann der Dualitätssatz auch wie folgt formuliert werden: Dualitätssatz Ein Strom x ist genau dann optimale Lösung des Minimalkosten-Stromproblems, wenn zu ihm eine Spannung y derart existiert, dass sich jeder Bogen des Graphen in einem seiner Gleichgewichtszustände befindet. 3.2.4 Gleichgewichts-Algorithmus zur Lösung des Minimalkosten-Stromproblems 1. Vorbereitung 1.1 Gerüst aufstellen, so dass der Fluss x durch x(k) = a(k) oder x(k) = b(k) für die Cogerüstbogen k bestimmt ist. Im Folgenden – unter der Annahme a(k) = 0 für alle k: x = 0. 1.2 Wir bestimmen über das Gerüst ein zugehöriges Potential so, dass y(k) = c(k) auf jedem Gerüstbogen gilt. Im Folgenden: Dijkstra-Algorithmus der kürzesten Wege mit Start = EKn(Rückkehrbogen), falls ein Rückkehrbogen existiert - in den meisten Transportmodellen. 2. Test, ob es einen Bogen k gibt, der bezüglich seiner Charakteristik out-of-kilter ist. Gibt es einen solchen Bogen kOut – andernfalls ist x eine optimale Lösung - so werden folgende Schritte ausgeführt: Solange ook(kOut) = true: 2.1 Bildung von z(kOut) (= Basiszyklus zum Cogerüstbogen kOut) und dx = Min{b(k) – x(k): k ∈ z(kOut)}; kFlusskrit sei ein Bogen, der das Minimum annimmt; x := x + dx⋅z(kOut)); Ist kFlusskrit ≠ kOut, so 2.2 Bildung von cz(kFlusskrit) (= Basiscozyklus zum Gerüstbogen kFlusskrit); dy = Min{c(k) – y(k): k ∈ cz(kFlusskrit) & (x(k) = a(k)) & ⌐ook(k)}; y := y +dy⋅cz(kFlusskrit)); kSpannkrit sei ein Bogen, der das Minimum annimmt. 2.3 Ist kSpannkrit ≠ kFlusskrit, so wird im Gerüst kFlusskrit durch kSpannkrit ersetzt. kOut kSpannkrit dx dy z(kOut) kFlusskrit Bild 3.7: Schema zum Gleichgewichtsalgorithmus Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 49 Beispiel Bild 3.8 zeigt ein kleines Netz vom Typ tNetz. An den Bogen sind die Zahlen a, b und c angegeben, sofern sie nicht Standartwerte haben. Für Bogen k = [Kn2, Kn3] ist a(k) = 3, was gemäß der oben geführten Diskussion um die Lösbarkeit – vgl. Bild 3.6 – mit c(k) = -100 für b(k) = 3 und c(k) = 3 für b(k) = ∞ umschrieben ist. Die Lösung der Aufgabe beginnt mit dem Dijkstra-Algorithmus der Kürzesten Wege, gestartet vom Knoten Kn1, der die in den Knoten des Bilds 3.8.1 angegebenen Potentialwerte t(i) und das Gerüst (fett gezeichnete Bogen) liefert. x = 0. Die Bogen [Kn2, Kn3] und [Kn4, Kn1] sind out-of-kilter (3 - 5 > -100 bzw. 0 - 7 > -100). Wir wählen kOut = [Kn4, Kn1] für den Start der Rechnung: z(kOut) = [[Kn4, Kn1], [Kn1, Kn3], [Kn3, Kn4]]; maximale Flussvergrößerung in diesem Zyklus dx = 4 bei kFlusskrit = [Kn1, Kn3]; cz(kFlusskrit) = -CZ({Kn3, Kn4}) = [[Kn1, Kn3], [Kn2, Kn3], [Kn2, Kn4], -[Kn4, Kn1]}; maximale Spannungssenkung für kOut in diesem Cozyklus ist dy = 4 bei kSpannkrit = [Kn2, Kn4]; Austausch kFlusskrit gegen kSpannkrit im Gerüst – wir erreichen den im Bild 3.8.2 gezeigten Zustand. Kn2 Legende: i t(i) b = 9, c = 6 x=0 5 Kn4 7+dy b = 8, c = 5 b = 3 / ∞, c = -100 / 3 x=0 x=0 Kn1 0 b = 8, c = 4 x = dx b = 4, c = 3 x = dx ≤ 4! Kn3 3+dy c = -100 x = dx Bild 3.8.1: Demonstration des Lösungsalgorithmus Bild 3.8.2: [Kn4, Kn1] ist weiterhin out-of-kilter (0 - 11 > -100); kOut = [Kn4, Kn1]: z(kOut) = [[Kn4, Kn1], [Kn1, Kn2], [Kn2, Kn4]]; maximale Flussvergrößerung in diesem Zyklus dx = 8 bei kFlusskrit = [Kn1, Kn2]; cz(kFlusskrit) = -CZ({Kn2, Kn3, Kn4}) = {[Kn1, Kn2], [Kn1, Kn3], -[Kn4, Kn1]}; maximale Spannungssenkung für kOut in diesem Cozyklus ist dy = 89 bei kSpannkrit = kOut = [Kn4, Kn1]; Austausch kFlusskrit gegen kSpannkrit im Gerüst – wir erreichen den im Bild 3.8.3 gezeigten Zustand. Kn2 5 b = 8, c = 5 x = dx ≤ 8! Kn1 0 b = 9, c = 6 x = dx Kn4 11+dy b = 3, c = -100 x=0 b = 8, c = 4 x=4 b = 4, c = 3 x=4 Kn3 7+dy c = -100 x = 4 + dx Bild 3.8.2: Demonstration des Lösungsalgorithmus 50 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung Bild 3.8.3: [Kn4, Kn1] ist im Gleichgewicht, aber [Kn2, Kn3] ist weiterhin out-of-kilter (94 - 96 > -100); kOut = [Kn2, Kn3]; z(kOut) = [[Kn2, Kn3], [Kn3, Kn4], -[Kn2, Kn4]]; maximale Flussvergrößerung in diesem Zyklus dx = 3 bei kFlusskrit = kOut = [Kn2, Kn3]. Kn2 94 b = 8, c = 5 x=8 Kn1 0 b = 9, c = 6 x = 8 -dx b = 3, c = -100 x = dx ≤ 3! b = 4, c = 3 x=4 Kn4 100+dy b = 8, c = 4 x = 4 + dx Kn3 96+d y c = -100 x = 12 Bild 3.8.3: Demonstration des Lösungsalgorithmus Jetzt sind alle Bogen im Gleichgewicht, d.h. die optimale Lösung ist gefunden - Bild 3.8.4. Kn2 94 b = 8, c = 5 x=8 Kn1 0 b = 9, c = 6 x=5 Kn4 100 b = ∞, c = 3 x=3 b = 8, c = 4 x=7 b = 4, c = 3 x=4 Kn3 96 c = -100 x = 12 Bild 3.8.4: Demonstration des Lösungsalgorithmus – optimale Lösung Abschließend ein Blick auf den Fall, dass die Originalaufgabe keine zulässige Lösung besitzt: Wir unterstellen, dass die Aufgabe, wie im Abschnitt 3.2.2 dargelegt, so erweitert wurde, dass zulässige Lösungen existieren, und betrachten den Fall, dass die optimale Lösung nicht die Originalaufgabe löst. Wie können wir erkennen, dass es keine zulässige Lösung der Originalaufgabe gibt? Wir betrachten zunächst ein triviales Beispiel – Bild 3.9: Für den Bogen [Kn1, Kn2] wird x ≥ 5 gefordert und im Widerspruch dazu für den anschließenden Bogen x([Kn2, Kn3]) ≤ 3: Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 51 Kn1 0 b = 5 / ∞, c = -1 / 0 x = dx Kn2 -1 b = 3, c = 0 x = dx ≤ 3! Kn3 -1+dy Kn2 -1 b = 3, c = 0 x=3 Kn3 1 c = -1 x = dx Kn1 0 b = 5, c = -1 x=3 c = -1 x=3 Bild 3.9: Eine unlösbare Aufgabe Ausgehend von der Kürzeste-Wege-Berechnung erhalten wir kOut = [Kn3, Kn1] (0 – (-1) > -1). Im Zyklus z(kOut) = [[Kn3, Kn1], [Kn1, Kn2], [Kn2, Kn3]] Stromänderung mit maximalem dx = 3 für kFlusskrit = [Kn2, Kn3]; im Cozyklus -CZ({Kn3}) = {[Kn2, Kn3], -[Kn3, Kn1]} ist ein maximales dy = 2 möglich, wobei kSpannkrit = kOut = [Kn3, Kn1]. Da nun alle Bogen im Gleichgewicht sind, liegt die optimale Lösung vor, die jedoch nicht die Originalforderung a[Kn1, Kn2] = 5 ≤ x([Kn1, Kn2]) = 3 erfüllt. Im Beispiel, wie im allgemeinen Fall, muss die optimale Lösung auf Zulässigkeit überprüft werden: Sie ist genau dann unzulässig, wenn für mindestens einen Bogen k* mit a_orig(k*) > 0 a_orig(k*) < x(k*) gilt. Existiert ein solcher Bogen, so sollten die Ursachen dieser Unzulässigkeit genauer untersucht werden: Es erhebt sich die Frage, ob x(k*) maximal ist. Zu dieser Frage nach dem maximalen Fluss durch einen Bogen k* zunächst ein paar Vorbetrachtungen: Definition CZ sei ein beliebiger Cozyklus. S(k*) = CZ \ {-k*} für k* mit -k* ∈CZ. Kap(S(k*)) = Σ(b(k) | k ∈S(k*)} heißt die K a p a z i t ä t des Schnittes S(k*). Aus Σ( x(k) | k ∈CZ ) = 0 folgt x(k*) = Σ( x(k) | k ∈CZ \ {k*} ≤ Σ( b(k) | k ∈CZ \ {k*} oder x(k*) ≤ Kap(S(k*)). In Worten: Satz von Ford und Fulkerson Der maximale Fluss durch einen Bogen ist höchstens so groß, wie das Minimum der Kapazitäten aller Schnitte zu ihm. Wenn wir einen Strom x und einen Schnitt {-k*, S(k*) haben, so dass für sämtliche Bogenbenennungen von S(k*) x die obere Schranke annimmt (- die untere Schranke für negatives k), so gilt x(k*) = Kap(S(k*)) und damit sind wir sicher, dass a) x(k*) der maximale Fluss durch den Bogen k* ist b) Kap(S(k*)) das Minimum der Kapazitäten aller Schnitte durch k* darstellt. 52 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung Kn2 b=6 Kn4 b=8 a = 3, b = 10 b = 10 Kn1 b=9 Kn3 Bild 3.10.1: Ein Beispiel zum Satz von Ford und Fulkerson Beispiel – Bild 3.10.1: Sc1 = S1([Kn4, Kn1]) = CZ({Kn1}) \ {-[Kn4, Kn1]} = {[Kn1, Kn2], [Kn1, Kn3]}, Kap(Sc1) = 8 + 9 = 17; Sc2 = S2([Kn4, Kn1]) = CZ({Kn1, Kn2}) \ {[Kn4, Kn1]} = {[Kn1, Kn3], [Kn2, Kn3] , [Kn2, Kn4]}, Kap(Sc2) = 9 + 10 + 6 = 25; Sc3 = S3([Kn4, Kn1]) = CZ({Kn1, Kn2, Kn3}) \ {[Kn4, Kn1]} = {[Kn2, Kn4], [Kn3, Kn4] }, Kap(Sc3) = 6 + 10 = 16; Sc4 = S4([Kn4, Kn1]) = CZ({Kn1, Kn3}) \ {[Kn4, Kn1]} = {[Kn1, Kn2], -[Kn2, Kn3] , [Kn3, Kn4] }, Kap(Sc4) = 8 – 3 + 10 = 15. Das Minimum dieser 4 Kapazitäten ist Kap(Sc4) = 15, d.h. max(x(Kn4, Kn1])) = 15. Kn2 90 b = 8, c = 5 x=8 Kn1 0 b = 6, c = 10 x=5 Kn4 100 a = 3, b = 10, c = 1 x=3 b = 10, c = 8 x = 10 b = 9, c = 12 Kn3 x=7 12 c = -100 x = 15 Bild 3.10.2: Ein Beispiel zum Satz von Ford und Fulkerson Im Bild 3.10.2 ist der Strom x, der diesen maximalen Fluss realisiert eingetragen, die Bogen des zugehörigen Schnitts Sc4 sind schwach gezeichnet, und mit den verbleibenden Bogen, die ein Gerüst bilden (fett gezeichnet), wurde zu den hinzugefügten Kostenwerten c(k) ein Potential t erzeugt. Da der Fluss einer optimalen Lösung einer solchen Transportaufgabe, der durch den Rückkehrbogen fließt, sicher maximal ist (bei genügend großem gross), muss umgekehrt, sofern der den maximalen Fluss realisierende Strom eindeutig ist, dieser die optimale Lösung sein. Dies wird im Bild 3.10.2 demonstriert: Der angegebene Strom x und sein zugehöriges Potential t bilden die optimale Lösung der Minimalkosten-Stromaufgabe. Aus diesen Zusammenhängen können wir für die Analyse von Unzulässigkeiten im MinimalkostenStromproblem Folgendes schlussfolgern: Für einen Bogen k*, für den in der optimalen Lösung x(k*) < a_orig(k*) gilt, muss y(k*) ≤ -gross gelten, denn er befindet sich im Gleichgewicht – vgl. Bild 3.6. Falls diese Unzulässigkeit nicht behebbar ist – d.h. falls gross genügend groß gewählt war – besteht sie auch, wenn man gross weiter vergrößert. Wir unterstellen dass k* Gerüstbogen ist und betrachten den Basiscozyklus cz(k*): Wenn es möglich Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 53 ist, gross um ein beliebiges dgross zu vergrößern, so muss für k ∈ cz(k*), k > 0, x(k) = b(k) und für k ∈ cz(k*), k < 0, x(k) = 0 gelten – vgl. Bild 3.6. Mit S(k*) = cz(k*) \ {k*} gilt folglich x(k*) = Kap(S(k*)) d.h., wie oben ausgeführt, x(k*) ist maximal. S(k*) t0 k* t0-gross t -dgross Bild 3.11: Zur Analyse unzulässiger Lösungen Zusammenfassend können wir festhalten: Wird festgestellt, dass in der optimalen Lösung einer Minimalkosten-Stromaufgabe für einen Gerüstbogen k* x(k*) < a_orig(k*) gilt, so sollte der Schnitt zum Basiscozyklus von k*, S(k*) = cz(k*) \ {k*}, eine Kapazität besitzen, die kleiner als a_orig(k*) ist. Ist dies der Fall, so ist die Unlösbarkeit der Originalaufgabe klar aufgezeigt. Andernfalls muss die Stimulierungsgröße gross vergrößert werden. Beispiel 1 Das letzte Netz im Bild 3.9 enthält die optimale Lösung eines unlösbaren Trivialbeispiels. Der Fluss des Gerüstbogens [Kn1, Kn2] erfüllt nicht die an ihn gestellten Bedingungen: a_orig([Kn1, Kn2]) = 5 > x([Kn1, Kn2]) = 3. Zu ihm gehört der Schnitt S([Kn1, Kn2]) = {x([Kn2, Kn3])}, der eine Kapazität Kap(S([Kn1, Kn2])) = 3 besitzt, folglich kann [Kn1, Kn2] keinen größeren Durchfluss als 3 haben. Zwischen den Bedingungen a([Kn1, Kn2]) = 5 und b([Kn1, Kn2]) = 3 besteht ein offensichtlicher Widerspruch. Beispiel 2 Wir betrachten das Beispiel im Bild 3.12: Für den Bogen [Kn2, Kn3] besteht die untere Schranke a([Kn2, Kn3]) = 3, deren Einhaltung durch c([Kn2, Kn3]) = -1 für 0 ≤ x([Kn2, Kn3]) ≤ 3 stimuliert wird. Bild 3.12 zeigt eine optimale Lösung, die x([Kn2, Kn3]) ≥ 3 nicht einhält. Allerdings besitzt der zum Basiscozyklus gehörende Schnitt S([Kn2, Kn3]) = {[Kn1, Kn2], -[Kn2, Kn4]} die Kapazität 8, und eine Veränderung der Stimulierung c([Kn2, Kn3]) = -1 auf weniger als -10 würde das System aus dem Gleichgewicht bringen: c([Kn2, Kn3]) < -10 ⇒ t(Kn2) > 10 ⇒ y([Kn2, Kn4]) < 0, im Widerspruch zu x([Kn2, Kn4]) = b([Kn2, Kn4]). Die Stimulierung wurde also zu schwach gewählt. (Man vgl. auch Beispiel 3.13, insbesondere Bild 3.13.5.) 54 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung Kn2 1 b=8 x=8 Kn1 0 b=6 x=6 b = 3 / 10, c = -1 / 0 x=2 b=9 x=8 Kn4 10 b = 10 x = 10 Kn3 0 c = -10 x = 16 Bild 3.12: Beispiel für einen Stimulierungsfehler Abschließend zu diesen Abschnitt noch folgende Bemerkungen: 1. Der hier vorgestellte Gleichgewichts-Algorithmus ist ein simplexartiger Algorithmus. Er sollte nicht mit dem im Allgemeinen in der Literatur dargelegten „Out-of-kilter-Algorithmus“ verwechselt werden. Der Out-of-kilter-Algorithmus kennt den Begriff der Basislösung nicht. Er arbeitet mit einem zulässigen, manchmal auch mit einem beliebigen, Ausgangsstrom x und einer passenden Spannung; sucht (wie hier) einen Bogen kOut im Out-of-kilter-Zustand und versucht dessen Fluss mit dem Maximalfluss-Algorithmus von Ford und Fulkerson zu maximieren. Der letztgenannte Algorithmus ist eine Tiefensuche, die entweder einen Zyklus liefert über den der existierend Strom so verändert werden kann, dass x(kOut) wächst oder – falls keiner existiert – einen Cozyklus, über den die Spannung bezüglich der Charakteristik von kOut verbessert werden kann. 2. Viele Transportmodelle besitzen einen Rückkehrbogen, auf den durch einen großen Gewinn (c(k) = -gross) ein maximaler Fluss stimuliert wird. Wie im Beispiel 3.10 erwähnt, ist folglich die optimale Lösung einer Minimalkosten-Stromaufgabe durch einen minimalen Schnitt zum Rückkehrbogen bestimmt. Allerdings gibt es im allgemeinen Fall viele solche Schnitte minimaler Kapazität, sodass unter ihnen der billigste ermittelt werden muss. 3. Das Maximalflussproblem ist ein Spezialfall des Minimalkosten-Stromproblems. Wie schon erwähnt, wird es im Allgemeinen mit einem speziellen Algorithmus gelöst und dient mit diesem der Lösung allgemeiner Minimalkosten-Stromprobleme (Out-of-kilter-Algorithmus). Wir halten den hier angegebenen Algorithmus zur Lösung von Minimalkosten-Stromproblemen für besser und empfehlen, ihn auch zur Lösung des Maximalflussproblems einzusetzen, wenn ein solches isoliert auftritt. Zur Demonstration betrachten wir das Beispiel aus Bild 3.10 – vgl. Bilder 3.13: Gestartet wird mit x = 0, t = 0 und einem beliebigen Gerüst, das den Bogen, dessen maximaler Fluss bestimmt werden soll, nicht enthält. Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 55 Kn2 0 b=8 x = dx Kn1 0 b=6 x=0 b = 3 / 10, c = -10 / 0 x = dx b=9 x = -dx ≥ 0! Kn4 0 b = 10 x=0 Kn3 0 - dy c = -1 x=0 Bild 3.13.1: Beispiel für eine Maximalflussberechnung Kn2 0 b=8 x=0 Kn1 0 b=6 x = -dx ≥ 0! Kn4 0 - dy b = 3, c = -10 x = dx ≤ 3! b = 10 x = dx b=9 x=0 Kn3 0-dy c = -1 x=0 Bild 3.13.2: Beispiel für eine Maximalflussberechnung Kn2 0 b=8 x = dx Kn1 0 b=6 x=0 Kn4 -10 + dy b = 3, c = -10 x = dx ≤ 3! b=9 x=0 b = 10 x = dx Kn3 -10 + dy c = -1 x = dx Bild 3.13.3: Beispiel für eine Maximalflussberechnung 56 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung Kn2 0 + dy b=8 x = 3 + dx ≤ 8! Kn1 0 b=6 x = dx b = 3, c = -10 x=3 b=9 x=0 Kn4 0 + dy b = 10 x= 3 Kn3 0 + dy c = -1 x = 3 + dx Bild 3.13.4: Beispiel für eine Maximalflussberechnung Kn2 0 + dy b=8 x=8 Kn1 0 b = 3, c = -10 x=3 b=9 x = 0 + dx b=6 x=5 Kn4 0 + dy b = 10 x = 3 + dx ≤ 10! Kn3 0 c = -1 x = 8 + dx Bild 3.13.5: Beispiel für eine Maximalflussberechnung Kn2 100 b=8 x=8 Kn1 0 b=9 x=7 b=6 x=5 b = 3, c = -10 x=3 Kn4 100 b = 10 x = 10 Kn3 0 c = -1 x = 15 Bild 3.13.5: Beispiel für eine Maximalflussberechnung – optimale Lösung Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 57 3.2.5 Anwendungsbeispiel Tourenproblem Zum Schluss noch ein Blick auf ein Problem, bei dem das Minimalkosten-Stromproblem Hilfsproblem ist. Aufgabe Gegeben ein Netz vom Typ eNetz, in dem einige Knoten (Orte) als Stützstellen einer Tour (Rundreise) benannt sind. Gesucht ist die kürzeste Tour, die ausgehend von einer als Ausgangspunkt fixierten Stützstelle alle anderen Stützstellen genau einmal durchläuft und zur Ausgangsstelle zurückführt – „Rundreise“. Das Rundreiseproblem – auch unter der englischen Bezeichnung Traveling-Salesman-Problem bekannt - ist der klassische Untersuchungsgegenstand für schwierige Probleme (NP-schwierig). Neben vielfältigen theoretischen Ergebnissen liegen zahlreiche Näherungsverfahren vor, die allerdings zum großen Teil auf symmetrische Probleme orientiert sind. Es gibt keinen wirklich befriedigenden exakten Algorithmus, weil theoretisch fast sicher ist, dass der Bearbeitungsaufwand exponentiell mit der Problemgröße wächst – vorausgesetzt, es gilt P = NP, wovon jeder überzeugt ist, was jedoch noch nicht bewiesen ist. Wir werfen im Folgenden einen kurzen Blick auf dieses Problem, weil es als Minimalkosten-Stromproblem mit Zusatzbedingungen modellierbar ist, womit das MinimalkostenStromproblem als Ersatzproblem genutzt werden kann. Das Rundreiseproblem ist außerdem Ausgangspunkt für viele praktische Probleme der Tourenplanung, für deren Behandlung die Modellierung mittels des Minimalkosten-Stromproblems sehr hilfreich sein kann. O1 O1 O2 O3 O2 O3 Bild 3.14: Modellierung von Tourenproblemen Modellierung eines Tourenproblems als Minimalkosten-Stromproblem: Wir ändern das Netz, indem wir die Stützstellen durch Bogen ersetzen, und zwar so, dass alle in den Knoten hineinführenden Bogen Eingangsbogen des Anfangsknotens des Ortsbogens und alle aus dem Ort herausführenden Bogen Ausgangsbogen des Endknotens des Ortsbogens sind – vgl. Bild 3.14. Ein Ortsbogen bekommt die Parameter a = 0, b = 1, c = -gross. Leider wird in den meisten Fällen die optimale Lösung dieser Minimalkosten-Stromaufgabe Kurzzyklen enthalten, d.h. sie wird in mehrere Teiltouren zerfallen. 58 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung Beispiel für ein Tourenproblem –Die Abbildung ist nur eine Skizze. /nach von O1 O2 O3 O4 O5 O1 O2 O3 O4 O5 OE1 ∞ 5 0 8 8 14 ∞ 7 0 0 12 4 ∞ 0 16 0 12 11 ∞ 1 10 0 9 14 ∞ b = 1, c = -100 OA1 c=5 OA2 OE2 c=0 Tabelle 3.6.1 OA3 OE3 c=8 OA4 OE4 c=8 OE5 OA5 Bild 3.15: Skizze des Netzes zur Tabelle Im Bild 3.15 ist zu dem durch die Tabelle beschriebenen Tourenproblem das Netz der zugehörigen Minimalkosten-Stromaufgabe skizziert. Zwecks Übersichtlichkeit wurden nur die Bogen zu O1, also von den Ortsausgängen OAi zum Ortseingang OE1 gezeichnet. Löst man die Aufgabe, so erhält man die optimale Lösung O1 → O4 → O3 → O1 und O2 → O5 → O2, die Kosten = 0 verursacht. Leider handelt es sich nicht um eine Rundreise, sondern um zwei Kurzzyklen. Man kann nun ein so genanntes Branch-and-Bound-Verfahren ansetzen, bei dem man im • im Branch- /Verzweigungsteil den zulässigen Bereiches in zwei Teilbereiche zerlegt: o Teilbereich 1 besteht aus allen Rundreisen, die einen fixierten Bogen [OAi, OEj] enthalten. o Teilbereich 2 besteht aus allen Rundreisen, die den fixierten Bogen [OAi, OEj] nicht enthalten. • im Bound- /Schrankenteil eine untere Schranke für den Wert der Zielfunktion für jeden der Teilbereiche ermittelt. Mit ihrer Hilfe wählt man den Teilbereich, den man als nächsten weiter verzweigt. In der hier betrachteten Anwendung des Branch-and-Bound-Verfahren findet man die Zielfunktionsabschätzung des durch Lösung des Ersatzproblems, nämlich des zugeordneten Minimalkosten-Stromproblems: Eine Rundreise des aktuellen Teilbereichs kostet mindestens so viele wie die optimale Lösung des Ersatzproblems. Falls das Ersatzproblem eine Rundreise liefert, so ist dies auch eine obere Schranke für den Zielfunktionswert des Rundreisproblems, mit der alle Bereiche deren Bound größer/gleich ist, ausgeschlossen werden können. In jedem Fall wählt man zur Fortsetzung einen Bereich mit kleinstem Bound und wiederholt – bis kein zulässiger nicht leerer Teilbereich mehr existiert. Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 59 Im Beispiel Fixierung des Bogens [OA2, OE5]: o Teilbereich 1 enthält [OA2, OE5]; das zugehörige Ersatzproblem zeigt Tabelle 3.6.2. / nach Von O1 O2 O3 O4 O5 O1 O2 O3 O4 O5 ∞ ∞ 0 8 8 14 ∞ 7 0 ∞ 12 ∞ ∞ 0 16 0 ∞ 11 ∞ 1 10 0 9 14 ∞ Tabelle 3.6.2 Wir erhalten die optimale Lösung: O1 → O3 → O1 und O2 → O5 → O4 → O2, die Kosten = 13 verursacht. Da Lösung eindeutig und keine Rundreise ist, können wir auf den Bound = 14 schließen, d.h., in diesem Teilbereich kostet eine Rundreise mindestens 14. o Teilbereich 2 enthält [OA2, OE5] nicht; das zugehörige Ersatzproblem zeigt Tabelle 3.6.3. / nach von O1 O2 O3 O4 O5 O1 O2 O3 O4 O5 ∞ 5 0 8 8 14 ∞ 7 0 0 12 4 ∞ 0 16 0 12 11 ∞ 1 10 ∞ 9 14 ∞ Tabelle 3.6.3 Wir erhalten die optimale Lösung: O1 → O4 → O3 → O5 → O2 → O1, die Kosten = 14 verursacht und eine Rundreise ist. Damit ist klar, dass keine Rundreise weniger als 14 kostet und, da wir eine Rundreise mit diesen Mindestkosten haben, ist diese eine optimale Lösung des Rundreiseproblems. 3.2.5 Das Minimalkosten-Stromproblem mit einem freien Parameter Die mathematische Modellierung eines Problems der Praxis ist meist aufwendig und geschieht selten mit dem Ziel, eine einzelne Berechnung anzustellen, sondern ihr Ziel ist die gedankliche Durchdringung der Praxisproblematik und die Erstellung von Werkzeugen zur Simulation möglicher Varianten zukünftigen Handelns, um Entscheidungshilfen zu bekommen. Betrachten wir die gewöhnliche Transportaufgaben in Bild und Tabelle 3.5. Einer der Beteiligten, also ein Lieferant oder ein Transportunternehmer oder ein Empfänger, möge Kalkulationen anstellen, in die er Verhaltensvarianten seiner Konkurrenten einbeziehen möchte; z.B., was geschieht, wenn ein Konkurrent billiger liefert oder wenn durch Streckensperrung erhöhte Transportkosten entstehen usw. Um solche Überlegungen durch ein Softwarewerkzeug zu unterstützen, ist folgende Aufgabe zu lösen: Parametrisches Minimalkosten-Stromproblem: Gegeben sind ein Graph G = [K, B] und zu jedem seiner Bogen k ϵ B sechs relle Zahlen a(k), da(k), b(k), db(k), c(k), dc(k). Es gelte a(k) ≤ b(k). Gesucht ist für λ ≥ 0 ein m-dimensionaler Vektor x(λ), m = |B|, der folgende Bedingungen erfüllt: 1) x(λ) ist Strom in G. 2) Es gilt a(k) + λ·da(k) ≤ X(k, λ) ≤ b(k) + λ·db(k) für k ϵ B. 60 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 3) x(λ) minimiert die Funktion z(λ, x(λ)) = ∑{(c(k) + λ·cb(k))·X(k, λ) | k = 1, 2, …, m}. Für jeden festen Wert von λ ist die Aufgabe die uns bekannte Minimalkosten-Stromaufgabe. Neu ist nur, dass wir folgende Fragen stellen wollen: 1) Gegeben sei eine optimale Basislösung x(λ0). Gesucht ist der maximale Wert λ1, λ1 ≥ λ0, für den x(λ0) stabil ist. 2) ZOp(λ) = z(λ, x(λ)) sei der optimale Wert der Zielfunktion in Abhängigkeit von λ. Gefragt sind der Definitionsbereich und der Verlauf dieser Optimalwertfunktion. Als Stabilitätsintervall einer optimalen Basislösung x(λ) wollen wir das Intervall [λ0, λ1] bezeichnen in dem das die Lösung definierende Gerüst unverändert bleibt. Beispiel k 1 2 3 4 5 6 Tabelle 3.7 AKn(k) Kn1 Kn1 Kn2 Kn2 Kn3 Kn4 EKn(k) Kn2 Kn3 Kn3 Kn4 Kn4 Kn1 a(k) 1 1 0 0 0 0 da(k) 1 2 0 0 0 0 b(k) 5 10 3 8 - db(k) 1 1 0 1 0 0 c(k) 4 2 0 5 3 -100 dc(k) 1 2 0 0 0 0 Für das durch Tabelle 3.7 beschriebene Zahlenbeispiel geben die Bilder 3.16.1 – 3.16.3 eine Folge stabiler Basislösungen. Bild 3.16.4 zeigt den Graphen der Optimalwertfunktion. Kn2 4+λ x = 3+λ Kn4 100 y = 4+λ x=0 x= 8 Kn1 0 y = 2+2λ Kn3 2+2λ y = -100 Bild 3.16.1: Optimale Lösung für 0 ≤ λ ≤ 2. Für λ > 2 wird [Kn2, Kn3] instabil. Kn2 2+2λ x = 3+λ Kn4 100 x = 5+λ y=0 x= 8 Kn1 0 y = 2+2λ Kn3 2+2λ y = -100 Bild 3.16.2: Optimale Lösung für 2 ≤ λ ≤ 2,5. Für λ > 2,5 wird [Kn1, Kn3] instabil Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 61 Kn2 4+λ x = 3+λ Kn4 100 y = 4+λ y=0 x= 8 Kn1 0 x = 1+2λ y = -100 Kn3 4+λ Bild 3.16.3: Optimale Lösung für 2,5 ≤ λ ≤ 3,5. Für λ > 3,5 wird x([Kn1, Kn3]) unzulässig. ZOp(λ) -100(11+λ) 177 142 127 λ 67 1 2 2,5 3 3,5 Bild 3.16.4: Optimalwertfunktion im Definitionsbereich [0, 3.5]. Wir vereinbaren folgende Hilfsbegriffe: A(λ, k) = a(k) + λ·da(k), X(λ, k) = x(k) + λ·dx(k), Y(λ, k) = y(k) + λ·dy(k), T(λ, i) = t(i) + λ·dt(i), B(λ, k) = b(k) + λ·db(k), C(λ, k) = c(k) + λ·dc(k), dy(k) = dt(EKn(k)) – dt(AKn(k)), und erweitern wieder die Definition der Parameter auf negative Bogenbenennungen: a(-k) = -b(k), b(-k) = -a(k), c(-k) = -c(k), da(-k) = -db(k), db(-k) = -da(k), dc(-k) = -dc(k), x(-k) = -x(k), dx(-k) = -dx(k), sodass auch Folgendes gilt: A(λ, -k) = -B(λ, k), B(λ, -k) = -A(λ, k), X(λ, -k) = -X(λ, k), C(λ, -k) = -C(λ, k), Y(λ, -k) = -Y(λ, k). Betrachtungen zum Definitionsbereich der Optimalwertfunktion In der Aufgabenstellung haben wir formuliert, dass das Problem für λ ≥ 0 gelöst werden soll. Es könnte natürlich der Fall eintreten, dass das Problem für λ = 0 keine Lösung besitzt. Da wir jedoch durch Bereichserweiterung einen leeren Aufgabenbereich vermeiden, gibt es auch keine Probleme von einer Lösung x(0) auszugehen, die nicht die Originalaufgabe löst. 62 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung Für den rechten Rand des Definitionsbereichs der Optimalwertfunktion können wir folgende obere Schranke angeben: Für jedes λ und jeden Bogen k muss die Ungleichung A(λ, k) ≤ B(λ, k) erfüllt sein. Aus ihr folgt: Regel 1 λ wird durch folgende Bedingung global beschränkt: λ ≤ maxλ = min{(b(k) – a(k))/(da(k) – db(k)) | für k ϵ B und da(k) – db(k) > 0. Gibt es keinen Bogen k für den da(k) - db(k) >0 ist, so gilt maxλ = ∞. Im obigen Beispiel ergibt für den Bogen [Kn1, Kn3] maxλ = 9. Berechnung des rechten Randes des Stabilitätsintervalls einer gegebenen Basislösung x(λ0) a) Falls der Bogen k Gerüstbogen ist (StzRchtg(k) ≠ 0) bewirkt Vergrößerung von λ eine Flussänderung. Somit besteht Gefahr, dass er durch Vergrößerung von λ seine Zulässigkeit, A(λ, k) ≤ X(λ, k) ≤ B(λ, k), verliert. Regel 2.1 Falls für einen Gerüstbogen k dx(k) – da(k) < 0 gilt, so muss λ durch die Bedingung λ ≤ (a(k) – x(k))/(dx(k) – da(k)) beschränkt werden. Falls für einen Gerüstbogen k dx(k) – db(k) > 0 gilt, so muss λ durch die Bedingung λ ≤ (b(k) – x(k))/(dx(k) – db(k)) beschränkt werden. b) Falls der Bogen k kein Gerüstbogen ist, StzRchtg(k) = 0, bewirkt Vergrößerung von λ eine Spannungsänderung. Somit besteht Gefahr, dass er durch Vergrößerung von λ seinen Gleichgewichtszustand verlässt: Regel 2.2 Falls für einen Nichtgerüstbogen k X(λ0, k) = A(λ0, k) und dy(k) – dc(k) > 0 oder X(λ0, k) = B(λ0, k) und dy(k) – dc(k) < 0 gilt, so muss λ durch die Bedingung λ ≤ (c(k) – y(k))/(dy(k) – dc(k)) beschränkt werden. Um den rechten Rand des Stabilitätsintervalls der gegebenen Basislösung zu errmitteln, müssen wir somit folgendes tun: Wir durchmustern alle Bögen gemäß den in den beiden Regeln angegebenen Kriterien und ermitteln den Minimalwert λ1 aller relevanten Schranken. Dabei bestimmen wir einen Bogen kParKrit (kritisch gegenüber Parametervergrößerung), dessen Schranke gleich λ1 ist. Gibt es keinen Bogen kParKrit, so ist λ1 = maxλ. Die Lösung x(λ0) ist für λ0 ≤ λ ≤ λ1 stabil. Beispiel Wir betrachten das obige Beispiel, Bild 3.16, näher: Bild 3.16.1 enthält die optimale Basislösung x(0), die über den Nichtgerüstbogen [Kn2, Kn4] auf x(λ) erweitert wird – verbunden mit der Erweiterung der zugehörigen dualen Lösung (Potential) t(0) zu t(λ). Wir durchmustern alle Bogen: [Kn1, Kn2]: Gerüstbogen, dx(1) – da(1) = 0 → irrelevant; dx(1) – db(1) = 0 → irrelevant; [Kn1, Kn3]: Gerüstbogen, dx(2) – da(2) = -2 → λ ≤ ( 1 – 8)/(–2) = 3,5; dx(2) – db(2) = -1 → irrelevant; [Kn2, Kn3]: Nichtgerüstbogen, X(0, 3) = A(0, 3) und dy(3) – dc(3) = 1 → λ ≤ 2; [Kn2, Kn4]: Nichtgerüstbogen, X(0, 4) = B(0, 4) und dy(4) – dc(4) = -1 → λ ≤ 91; [Kn3, Kn4]: Nichtgerüstbogen, X(0, 5) = B(0, 5) und dy(5) – dc(5) = -2 → λ ≤ 47,5; [Kn4, Kn1]: Gerüstbogen, dx(6) – da(6) = 1 → irrelevant. Folglich gilt λ1 = Min{∞, 3.5, 2, 91, 47.5} = 2, kParKrit = 3, d.h. x(λ) ist für 0 ≤ λ ≤ 2 stabil. Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 63 Fortsetzung der Optimalwertfunktion über den rechten Rand des aktuellen Stabilitäsintervalls hinaus Gegeben sei die Basislösung x(λ), die für λ0 ≤ λ ≤ λ1 stabil ist. Sie wird durch X(λ0, k) = A(λ0, k) oder X(λ0, k) = B(λ0, k) auf den Bogen k eines Cogerüsts erzeugt. Die zugehörige duale Lösung T(λ0, i) wird durch Y(λ0, k) = C(λ0, k) auf den Bogen k des zugehörigen Gerüsts erzeugt. kParKrit sei der für λ > λ1 parameterkritische Bogen, d.h. er befindet sich für λ = λ1 in einem Gleigewichtszustand, der einer Ecke seiner Charakteristik entspricht. Es gilt, Y(λ1, kParKrit) =C(λ1, kParKrit) und X(λ1, kParKrit) = A(λ1, kParKrit) oder X(λ1, kParKrit) = B(λ1, kParKrit). Wir haben zwei Fälle zu unterscheiden: 1. kParKrit ist Nichtgerüstbogen (StzRchtg(kParKrit) = 0): λ > λ1 würde dazu führen, dass im Fall X(λ1, kParKrit) = A(λ1, kParKrit) Y(λ, kParKrit) > C(λ, kParKrit) gälte, und im Fall X(λ1, kParKrit) = B(λ1, kParKrit) Y(λ, kParKrit) < C(λ, kParKrit), sodass der Bogen aus dem Gleichgewicht geräte. Der Ausweg besteht darin, den Bogen in das Gerüst aufzunehmen, denn dann gilt Y(λ, kParKrit) = C(λ, kParKrit) auch bei λ-Vergrößerung. Zur Vereinfachung treffen wir die folgende Vorzeichenfestlegung, -kParKrit, für X(λ1, kParKrit) = A(λ1, kParKrit) kNeu = kParKrit, für X(λ1, kParKrit) = B(λ1, kParKrit) die bedeutet, dass im Moment X(λ1, kNeu) = B(λ1, kNeu) gilt. Die Spannung muss natürlich entsprechend transformiert werden: Y(λ, k) := Y(λ, k) - Y(λ, kNeu) + C(λ, kNeu) für die Bogen k ϵ cz(kAlt) - meint, dass y(k) und dy(k) demgemäß transformiert werden. kAlt ist der Bogen, der für kNeu das Gerüst verlässt. Für den zukünftigen Nichtgerüstbogen kAlt müssen wir X(λ, kAlt) = B(λ, kAlt) für λ ≥ λ1 sichern. Dazu ist die Transformation X(λ, k) := X(λ, k) - X(λ, kAlt) + B(λ, kAlt) für k ϵ z(kNeu) nötig. Aus ihr folgt, X(λ1, k) - X(λ1, kAlt) + B(λ1, kAlt) ≥ 0 für k ϵ z(kNeu), sodass wir ihn über die Bestimmung von Min{X(λ1, k) - B(λ1, k) | k ϵ z(kNeu)} finden. kAlt ist ein Bogen, der dieses Minimum annimmt. Wir demonstrieren das Verfahren am obigen Beispiel (Tabelle 3.7, Bild 3.16): Bild 3.16.1 enthält die optimale Basislösung X(0) und die zugehörigen duale Lösung (Potential) T(0). Wir wissen bereits, kParKrit = 2 = -kNeu. z(kNeu) = [-2, 3, 1]. {B(2, k) - X(2, k) | k ϵ z(kNeu)} = {3, ∞, 2} → kAlt = 1; Transformation des Stroms und der Spannung, sowie Austausch Bogen gegen Bogen 3 im Gerüst liefert den im Bild 3.17.2 gezeigten Zustand. 2. kParKrit ist Gerüstbogen (StzRchtg(kParKrit) ≠ 0): -kParKrit, für X(λ1, kParKrit) = A(λ1, kParKrit) kAlt = kParKrit, für X(λ1, kParKrit) = B(λ1, kParKrit) Es gilt X(λ1, kAlt) = B(λ1, kAlt), und λ > λ1 würde dazu führen, dass X(λ, kAlt) > B(λ, kAlt) gälte, sodass der Bogen seine Zulässigkeit verlöre. Der Ausweg besteht darin, den Bogen aus dem Gerüst zu entfernen, denn dann gilt X(λ, kAlt) = B(λ, kAlt) auch für λ > λ1. kAlt muss im Gerüst durch einen anderen Bogen kNeu aus dem Cozyklus cz(kAlt) ersetzt werden. Für dessen Spannung muß im Weiteren Y(λ, kNeu) = C(λ, kNeu) gelten. Diese Spannungsanpassung Y(λ, k) := Y(λ, k) - Y(λ , kNeu) + C(λ, k) muss für k ϵ cz(kAlt) ausgeführt werden, woraus folgt, wir bestimmen Min { C(λ1, k) - Y(λ1, k) | k ϵ cz(kAlt), X(λ1, k) = A(λ1, k) } 64 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung und wählen als kNeu einen Bogen, der dieses Minimum annimmt. Anschließend transformieren wir die Spannung für k ϵ cz(kAlt) sowie den Strom gemäß X(λ, k) := X(λ, k) - X(λ, kAlt) + B(λ, kAlt) für k ϵ z(kNeu)} und tauschen im Gerüst kAlt gegen kNeu. Wir demonstrieren das Verfahren wieder am obigen Beispiel (Tabelle 3.7, Bild 3.16): Bild 3.16.2 enthält die optimale Basislösung X(2) und die zugehörigen duale Lösung (Potential) T(2). Wir durchmustern zunächst alle Bogen, um kParKrit zu finden: [Kn1, Kn2]: Nichtgerüstbogen, X(2, 1) = B(2, 1), dy(1) – dc(1) = 1 → irrelevant; [Kn1, Kn3]: Gerüstbogen, dx(2) – da(2) = -2 → λ ≤ (1 – 6)/(–2) = 2,5; dx(2) – db(2) = -1 → irrelevant; [Kn2, Kn3]: Nichtgerüstbogen, X(2, 3) = A(2,3) und dy(3) – dc(3) = 0 → irrelevant; [Kn2, Kn4]: Gerüstbogen, dx(4) – da(4) = 1; dx(4) – db(4) = 0 → irrelevant; [Kn3, Kn4]: Nichtgerüstbogen, X(2, 5) = B(2,5) und dy(5) – dc(5) = -2 → λ ≤ 46,5; [Kn4, Kn1]: Gerüstbogen, dx(6) – da(6) = 1 → irrelevant. Folglich gilt λ1 = Min{∞, 2.5, ∞, ∞, 46.5, ∞} = 2.5, d.h. x(λ) ist für 2 ≤ λ ≤ 2,5 stabil, kParKrit = 2 = -kAlt, cz(kAlt) = {-1, -2, 4, 5}, Min{0.5, ∞, ∞, ∞} = 0.5 für kNeu = -1. Transformation des Stroms für k ϵ z(-1) = [-1, 2, -3] und der Spannung, sowie Austausch Bogen 2 gegen Bogen 1 im Gerüst liefert den im Bild 3.16.3 gezeigten Zustand. Bestimmung von kParKrit in diesem Zustand: [Kn1, Kn2]: Gerüstbogen, dx(1) - da(1) = -2 → λ ≤ (1 – 10)/(–2) = 4,5; dx(1) - db(1) = 0 → irrelevant; [Kn1, Kn3]: Nichtgerüstbogen, X(2.5, 2) = A(2.5, 2) und dy(2) – dc(2) = 0 → irrelevant; [Kn2, Kn3]: Gerüstbogen, dx(3) - da(3) = -2 → λ ≤ (0 – 7)/(–2) = 3,5; dx(3) - db(3) = -2 → irrelevant; [Kn2, Kn4]: Nichtgerüstbogen, X(2.5, 4) = B(2.5, 4) und dy(4) – dc(4) = -1 → λ ≤ 96; [Kn3, Kn4]: Nichtgerüstbogen, X(2.5, 5) = B(2.5, 5) und dy(5) – dc(5) = -1 → λ ≤ 96; [Kn4, Kn1]: Gerüstbogen, dx(6) – da(6) = 1 → irrelevant. Folglich gilt λ1 = Min{4.5, ∞, 3.5, 96, 96, ∞} = 3.5, d.h. x(λ) ist für 2,5 ≤ λ ≤ 3,5 stabil, kParKrit = 3 = -kNeu, cz(-3) = {-3, -2, 5}, Min{∞, ∞, ∞} = ∞, d.h. eine Änderung der Basis ist nicht möglich. Die Optimalwertfunktion ist nicht fortsetzbar. (λ-Vergrößerung würde zu negativen Fluss durch Bogen 3 führen.) Zusammenfassung: Um die Optimalwertfunktion über den rechten Rand λ1 eines Stabilitätsintervals hinaus fortzusetzen, sind Bogen kAlt und kNeu zu bestimmen, von denen einer gleich ±kParKrit - ist - kParKrit der parameterkritische Bogen. Es sind folgende Transformationen auszuführen: X(λ, k) := X(λ, k) - X(λ, kAlt) + B(λ, kAlt) für k ϵ z(kNeu), Y(λ, k) := Y(λ, k) - Y(λ, kNeu) + C(λ, kNeu) für k ϵ cz(kAlt). Anschließend ist der Bogen kAlt im Gerüst durch kNeu zu ersetzen. Eigenschaften der Optimalwertfunktion ZOp(λ) Aus der Theorie der parametrischen Optimierung (vgl. z.B: [Noz]) ist Folgendes bekannt: 1) Ist der zulässigeBereich des Problems unabhängig vom freien Parameter λ (da(k) = db(k) = 0 für alle k), so ist die Optimalwertfunktion ZOp(λ) konvex und in jedem Stabilitätsintervall linear. 2) Ist die Zielfunktion des Problems unabhängig von λ (dc(k) = 0 für alle k), so ist die ZOp(λ) konkav und in jedem Stabilitätsintervall linear. In unserem allgemeinen Fall gilt: Satz ZOp(λ) ist in jedem Stabilitätsintervall eine lineare oder quadratische (parabolische) Funktion. Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 65 Beweis: ZOp(λ) = z(λ, x(λ)) = ∑{(c(k) + λ·cb(k))·X(k, λ) | k = 1, 2, …, m}. Wählen wir die Vorzeichen der Benennungen der Basisbogen l (StzRchtg(l) = 0) so dass l > 0 gilt, wenn X(l, λ) = X(l, λ), so können wir x(λ) = ∑{(b(l) + λ·db(l))·z(l) | l mit StzRchtg(l) = 0} notieren, also X(l, λ) = x(l) + λ·dx(l)), woraus die Behauptung folgt. Satz Ist die Optimalwertfunktion über den rechten Rand λ1 eines ihrer Stabilitätsintervalle hinaus erklärt, so gibt es für zwei verschiedene optimale Lösungen x(λ1) und x*(λ1) mindestens jedoch zwei verschiedene Basisdarstellungen der Lösung x(λ1). Beweis: Bei der Ermittlung von λ1 haben wir gesehen, dass es ein Wert ist, für den (X(k, λ1), Y(k, λ1)) eine Eckpunktlage der Charakteristik des Bogens k = kParKrit beschreibt. Im Austausch mit einem geigneten Bogen kann somit die Lösung durch X(kParKrit, λ) := B(kParKrit, λ) oder durch Y(kParKrit, λ) := C(kParKrit, λ) determiniert werden. Ändert bei diesem Austausch X(kParKrit, λ1) seinen Wert, so gewinnen wir eine neue Lösung x*(λ1), die den gleichen Wert ZOp(λ1) besitzt, andernfalls nur eine andere Basisdarstellung der Lösung. Beispiel Man betrachte Bild 3.16.1 und Bild 3.16.2: Bild 3.16.1 beschreibt für λ = 2 die optimale Basislösung x(2) = (5, 8, 0, 5, 8, 13) mit Zopt(2) = 127. Bild 3.16.1 beschreibt für λ = 2 die optimale Basislösung x*(2) = (7, 6, 2, 5, 8, 13) mit dem gleichen Zielfunktionswert Zopt(2) = 127. Vergleicht man die Ergebnisse in den Bildern 3.16.2 und Bild 3.16.3, so sieht man, das Bild 3.16.2 für λ = 2,5 die optimale Basislösung x(2) = (7.5, 6, 2, 5.5, 8, 13) mit Zopt(2.5) = 142,5. Bild 3.16.3 beschreibt für λ = 2,5 die gleiche optimale Basislösung aber eben in anderer Weise, so dass die Lösung auch für λ > 2,5 zulässig ist. 66 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 3.3 Das Minimalkosten-Spannungsproblem 3.3.1 Grundlagen Es liegt nahe, ein zum Minimalkosten-Stromproblem analoges Minimalkosten-Spannungsproblem zu betrachten: Minimalkosten-Spannungsproblem Gegeben ist eine Datenstruktur vom Typ tNetz in Form eines gerichteten Graphen G = [K, B] und den über B erklärten reellwertigen Funktionen a(k), b(k) und c(k). Für a(k) und b(k) gilt a(k) ≤ b(k). Gesucht ist ein über B erklärter Vektor y, der folgende Bedingungen erfüllt: 4) y ist Spannung in G. 5) Es gilt a(k) ≤ y(k) ≤ b(k) für k ∈ B. 6) y ist unter allen Vektoren, die die Bedingungen 1) und 2) erfüllen, einer der die Funktion z(y) = ∑{c(k)·y(k) | k = 1, 2, ..., m} minimiert. Für die Bogenparameter mögen auch hier die im Abschnitt 3.1 eingeführten Standards und Festlegungen gelten: a(k) = 0, b(k) = ∞, c(k) = 0; a(-k) = -b(k), b(-k) = -a(k), y(-k) = -y(k), c(-k) = -c(k). Ein Anwendungsfall für dieses Problem ist die kostenoptimale Kürzung des kritischen Weges eines Aktivitätspfeilnetzes der Netzplantechnik. Wir haben das entsprechende Netzplanmodell im Abschnitt 2.2 über längste Wege eingeführt: Die Bogen des Netzplans stellen Teilprozesse – genannt Aktivitäten oder Vorgänge – eines Gesamtprozesses dar. Die Knoten repräsentieren wichtige Zeitpunkte im Ablauf – genannt Ereignisse. Über diese Ereignisse werden Abhängigkeiten zwischen den Aktivitäten realisiert: Kann die Aktivität Aj erst beginnen, wenn die Aktivität Ai beendet ist. (Beispiel: Die Dachkonstruktion kann erst begonnen werden, wenn ihre Stützkonstruktion fertig ist.), so ist das Ereignis „Ende der Aktivität Ai“ identisch mit dem Ereignis „Begin der Aktivität Aj“. Das Netz bekommt genau einen Eingang Start und genau einen Ausgang Ende. Start ist Anfangsknoten aller Bogen der Aktivitäten, die ohne Vorbedingung begonnen werden können. Start ist Anfangsknoten aller Bogen der Aktivitäten, die ohne Vorbedingung begonnen werden können. Setzen wir für das Ereignis Start den Eintrittstermin auf 0, ordnen der Aktivität Ai eine Dauer d(i) zu und unterstellen, dass jede Aktivität ohne Unterbrechung bearbeitet wird (et(i) = at(i) + d(i)), so können wir für jeden Knoten i einen Relativtermin t(i) – relativ zum Start-Ereignis – berechnen, wobei insbesondere der Termin t(Ende) die Dauer des Gesamtprozesses angibt. Da am Ende jede Aktivität ausgeführt sein muss, ist t(Ende) die Länge des längsten Weges vom Start zum Ende. Wir wollen in diesem Abschnitt unterstellen, dass die Dauer d(i) der Aktivität Ai kostenabhängig variiert werden kann: Aufgabe Für jede Aktivität Ai gibt es • eine Normaldauer normD(i), die verkürzt werden kann bis auf • eine Minimaldauer minD(i). • Die Kürzung von normD(i) um eine Zeiteinheit kostet cD(i) Geldeinheiten - Kürzungspreis: Ist d(i), minD(i) ≤ d(i) ≤ normD(i), die gewählte Dauer, so entstehen (Zusatz-)Kosten in Höhe von cD(i)·(normD(i) - d(i)) Geldeinheiten. Gesucht ist ein System d = (d(1), d(2), …, d(n)) so, dass ∑{cD(i)·(normD(i) - d(i)) | i = 1, 2, …, n)} minimal ist. Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 67 Die Lösung der Aufgabe kann mit einem Algorithmus zur kostenoptimalen Kürzung der kritischen Weges nach Kelley erfolgen, der sich unmittelbar aus unserem Algorithmus zur Lösung des Minimalkosten-Stromproblems ableiten lässt. Wir wollen das nachfolgend demonstrieren. Wie beim Minimalkosten-Stromproblems wollen wir eine Eckpunktlösung ermitteln: Definition Eine E c k p u n k t – oder B a s i s l ö s u n g des Minimalkosten-Spannungsproblems ist ein zulässiges Potential t, das für k ∈ B’ t(EKn(k)) - t(AKn(k)) = a(k) oder t(EKn(k)) - t(AKn(k)) = b(k) erfüllt. Dabei bezeichnet B’ die Bogenmenge eines Gerüstes im Graphen G = [K, B]. Im Folgenden bezeichnet y(k) die Potentialdifferenz: y(k) = t(EKn(k)) - t(AKn(k)). Der Dualitätssatz der linearen Optimierung ist auch für diesen Fall die Grundlage des Lösungsalgorithmus: Satz (Dualitätssatz ) Gegeben sei eine Basislösung t des Minimalkosten-Spannungsproblems mit dem Gerüst G’ = [K, B’]. Auf dem Cogerüst zu G’ definieren wir einen Strom durch x(k) = c(k) für k∈ B\B’. t ist genau dann optimale Lösung, wenn folgende Bedingung erfüllt ist: Für k ∈ B’ gilt: Falls y(k) = a(k), so ist x(k) ≤ c(k) und, falls y(k) = b(k), so ist x(k) ≥ c(k). Durch den Dualitätssatz wird für den Fall der Optimalität zu jedem Bogen k eine Abbildung, x(k) = Char(y(k)), aus der Menge der zulässigen Werte y(k) in die Menge der zulässigen Werte x(k) definiert. Man beachte, dass wir hier und im Folgenden zu Gunsten der Beibehaltung der Bezeichnungen x für Strom und y für Spannung y als Abszisse und x als Ordinate sehen. Bild 3.17 zeigt die Abbildung x(k) = Char(y(k)) als Treppenfunktion im gedrehten (y(k), x(k))-Koordinatensystem. Sie wird wieder als Charakteristik oder Gleichgewichtsgraph des Bogens k bezeichnet. Im rechten Teil der Abbildung ist die Charakteristik auf den Bereich 0 ≤ y(k) ≤ b(k) erweitert worden, indem bei x(k) = -gross eine Stufe eingefügt wurde. Dies entspricht der im Abschnitt 3.2.2 geführten Diskussion um zulässige Lösungen. y(k) y(k) b(k) b(k) a_orig(k) a(k) x(k) c(k) x(k) -gross c(k) Bild 3.17: Gleichgewichtsgraph oder Charakteristik eines Bogens k – rechts erweitert Definition Gilt für eine Lösung t des Minimalkosten-Spannungsproblems, einen Strom x und einen Bogen k x(k) = Char(y(k)), so wollen wir sagen, k liegt auf seiner C h a r a k t e r i s t i k oder auch: k befindet sich in einem Gleichgewichtszustand. Andernfalls sagen wir, der Bogen ist o u t - o f - k i l t e r (außerhalb seines Gleichgewichts). 68 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung Mit diesem Begriff kann der Dualitätssatz wieder wie folgt formuliert werden: Dualitätssatz Ein Potential t ist genau dann optimale Lösung des MinimalkostenSpannungsproblems, wenn zu ihm eine Strom x derart existiert, dass jeder Bogen des Graphen auf seiner Charakteristik liegt. 3.3.2 Gleichgewichts-Algorithmus zur Lösung des Problems der Kürzung des kritischen Wegs Wir wollen uns im Weiteren auf den Anwendungsfall der kostenminimalen Kürzung des kritischen Wegs beschränken: Das Netz sei also ein Aktivitätspfeilnetz; jeder seiner Bogen sei eine Aktivität für die eine Charakteristik gilt, wie sie Bild 3.18.1 zeigt. Man beachte, dass auch weiterhin zu Gunsten der Bezeichnung x für Strom und y für Spannung die Umkehrfunktion gezeigt wird. Die Spannung eines Aktivitätsbogens muss mindestens gleich minD(i) sein, sie kann jedoch größer als normD(i) sein. Die Kostenbewertung ist negativ, ∑{cD(i)·(normD(i) - d(i)) | i=1, 2, …, n} = const. + ∑{-cD(i)·d(i) | i=1, 2, …, n}. Wird y(i) = t(EKn(i)) – t(AKn(i)) größer als normD(i), so sind die (Zusatz-)Kosten für Dauerkürzung an der Aktivität gleich Null. Wir fügen dem Netz einen Bogen vom Start-Knoten zum End-Knoten hinzu – den so genannten Netzbogen. Diesem geben wir die im Bild 3.18.2 gezeigte Charakteristik. y(i) etN pEtN normD(i) minD(i) x(i) xN -cD(i) Bild 3.18.1: Charakteristik der Aktivität Bild 3.18.2: Charakteristik des Netzbogens Algorithmus zur kostenoptimalen Kürzung des kritischen Weges nach Kelley: a) Vorbereitungsschritt: Im Abschnitt 2.2 wurde erläutert, dass wir das Netz als kreisfrei voraussetzen können. Folglich können wir problemlos eine Längste-Wege-Berechnung nach Dantzig ausführen, wobei wir für jeden Bogen i als Bogenlänge normD(i) ansetzen. Diese Rechnung liefert uns zur Lösung t ein Gerüst – das der längsten Wege – und sie kann durch den Kostenstrom x = 0 ergänzt werden. Damit haben wir eine zulässige Lösung der Aufgabe, und zwar die, die den längsten kritischen Weg hat, dafür aber die geringsten Kosten = 0. Alle Bogen, einschließlich des Netzbogens, sind im Gleichgewicht. b) Kürzungsschritt: Im Sinne einer parametrischer Optimierung (vgl. Abschnitt 3.2.5) stören wir das Gleichgewicht des Netzes, indem wir die Charakteristik des Netzbogens dadurch ändern, dass wir uns einen geplanten Endtermin, pEtN, für das Netz vorgegeben denken. Dieser gedachte Vorgabe entspricht im Bild 3.18.2 die gestrichelt gezeichnete Horizontale. Wenn wir unterstellen, dass der errechnete Endtermin für das Netz, etN, oberhalb der gedachten Planvorgabe liegt, etN < pEtN, so ist der Netzbogen nicht mehr in einem Gleichgewichtszustand, wenn wir die Vorgabe einhalten wollen. Wir korrigieren daher die gegebene Lösung wie folgt: • Wir maximieren den Fluss durch den Basiszyklus zum Netzbogen, unter den Bedingungen –cD(i) ≤ x(i) für alle Aktivitäten Ai. kFlusskrit sei der Bogen, der das Maximum bestimmt. Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 69 • Wir minimieren die y(kFlusskrit) im Basiscozyklus zu kFlusskrit. kSpannkrit sei der Bogen, der das Minimum bestimmt. • kFlusskrit wird aus dem Gerüst entfernt, kSpannkrit wir in das Gerüst aufgenommen. • Der Prozess wird solange wiederholt bis es keine Beschränkung für den Fluss durch den Netzbogen mehr existiert. Erläuterung: Der aktuelle Basiscozyklus zu kFlusskrit ist der aktuell billigste Schnitt durch das Netz – Schnitt kleinster Kapazität zum Netzbogen, Kapazität = ∑{cD(i) | Ai im Schnitt}. Seine Kapazität ist nach dem Satz von Ford und Fulkerson (vgl. Abschnitt 3.2.4) gleich dem maximalen Fluss durch den Netzbogen, so dass der Fluss x(Netzbogen) den aktuellen Netzkürzungspreis angibt. Wir demonstrieren den Algorithmus an dem folgenden Beispiel – Tabelle 3.8 und Bild 3.19. Aktivität A1 A2 A3 A4 A5 Voraussetzung A1 A1 und A2 A4 normD 8 6 10 5 4 minD 5 4 6 3 2 cD 4 3 6 1 8 Tabelle 3.8 1 8d = 8, cD = 4, x = -4 Start 0 d = 10, cD = 6, x = -4 d = 0, x = 0 Ende 18- d = 6, cD = 3, x = 0 d = 4, cD = 8, x = 0 2 8d = 5, cD = 1, x = 0 3 13- x=4 Bild 3.19.1: Beispiel für die kostenminimale Kürzung des kritischen Wegs Im Bild 3.19.1 ist der Vorbereitungsschritt ausgeführt und es wurde die erste Flussmaximierung längs des Zyklus [[Start, Ende], [-1, Ende], -[Start, 1]] vorgenommen; x([Start, Ende]) = 4, d.h. die Kürzung von t(Ende) = 18 kostet 4 Geldeinheiten pro Zeiteinheit: Um zu kürzen, kann man den Schnitt S([Start, Ende]) = {[Start, 1], [Start, 2]} kürzen. Die Kürzung von [Start, 1] kostet 4 Geldeinheiten pro Zeiteinheit, [Start, 2] hat 2 Zeiteinheiten Puffer, dessen Kürzung keine Kosten verursacht. 70 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 1 6d = 10, cD = 6, x = -4 d = 6, cD = 4, x = -4 Start 0 d = 0, x = 0 Ende 16- d = 6, cD = 3, x = 0 d = 4, cD = 8, x = 0 2 6 d = 5, cD = 1, x = 0 3 11 x=4 Bild 3.19.2: Beispiel für die kostenminimale Kürzung des kritischen Wegs In dem geänderten Netz, Bild 3.19.2, lässt sich x([Start, Ende]) = 4 zunächst nicht erhöhen, denn in seinem Basiszylus liegt -[1, 2]. Die so genannte Scheinaktivität [1, 2] ist nötig, um die Vorbedingungen der Aktivität A3 zu sichern. Man vergleiche zu diesem Thema das folgende Kapitel 5.1. Für eine Scheinaktivität gilt normD = minD = 0 und damit hat sie die gleiche Charakteristik wie der Netzbogen. x([1, 2]) ≤ 0 und damit kFlusskrit = -[1, 2]. Die billigste Kürzung erfolgt im Schnitt Das bedeutet, S([Start, Ende]) = {[Start, 1], -[1, 2], [2, Ende]}. Gekürzt wird auch der Puffer von [3, Ende] = kSpannkrit. 1 5d = 5, cD = 4, x = -4 Start 0 d = 10, cD = 6, x = -4 d = 0, x = 0 Ende 15- d = 6, cD = 3, x = -1 d = 4, cD = 8, x = -1 2 6 d = 5, cD = 1, x = -1 3 11- x=5 Bild 3.19.3: Beispiel für die kostenminimale Kürzung des kritischen Wegs In der neuen Situation - Bild 3.19.3 konnte x([Start, Ende]) längs des Zyklus [[Start, Ende], [Start, 2], [2, 3], [3, Ende]] auf 5 erhöht werden; kFlusskrit = [2, 3], S([Start, Ende]) = {[Start, 1], -[1, 2], [2, 3]}; Kürzungsmöglichkeit gleich 0, bei kSpannkrit = [Start, 1]; A1 hat minD = 5 erreicht. Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 71 1 5 d = 10, cD = 6, x = -6 d = 5, cD = 4, x = -6 Start 0 d = 0, x = 0 Ende 15- d = 6, cD = 3, x = -1 d = 4, cD = 8, x = -1 2 6 d = 4, cD = 1, x = -1 3 10- x=7 Bild 3.19.4: Beispiel für die kostenminimale Kürzung des kritischen Wegs In der Situation Bild 3.19.4 wurde x([Start, Ende]) auf 7 längs des kritischen Wegs [[Start, 1], [1, Ende]] erhöht; kFlusskrit = [1, Ende], S([Start, Ende]) = {[1, Ende], [2, 3]}; Kürzungsmöglichkeit gleich 2, bei kSpannkrit = [2, 3]; A4 erreicht minD(4) = 3. 1 5 d = 5, cD = 4, x = -6 Start 0 d = 8, cD = 6, x = -6 d = 0, x = 0 Ende 13- d = 6, cD = 3, x = -3 d = 4, cD = 8, x = -3 2 6d = 3, cD = 1, x = -3 3 9- x=9 Bild 3.19.5: Beispiel für die kostenminimale Kürzung des kritischen Wegs In der Situation Bild 3.19.5 wurde x([Start, Ende]) auf 9 über den kritischen Weg [[Start, 2], [2, 3], [3, Ende]] erhöht; kFlusskrit = [Start, 2], S([Start, Ende]) = {[1, Ende], [1, 2], [Start, 2]}; Kürzungsmöglichkeit kSpannkrit = [1, 2]. gleich 1, bei 72 Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 1 5 d = 7, cD = 6, x = -6 d = 5, cD = 4, x = -11 Start 0 d = 0, x = -5 Ende 12- d = 5, cD = 3, x = -3 d = 4, cD = 8, x = -8 2 5 d = 3, cD = 1, x = -8 3 8 x = 14 Bild 3.19.6: Beispiel für die kostenminimale Kürzung des kritischen Wegs In der Situation Bild 3.19.6 wurde x([Start, Ende]) auf 14 über den kritischen Weg [[Start, 1], [1, 2], [2, 3], [3, Ende]] erhöht; kFlusskrit = [3, Ende], S([Start, Ende]) = {[1, Ende], [3, Ende]}; Kürzungsmöglichkeit gleich 1, bei kSpannkrit = [1, Ende]; A3 erreicht minD(2) = 6. 1 5 d = 5, cD = 4, x = -6 + λ Start 0 d = 6, cD = 6, x = -6 + λ d = 0, x = 0 Ende 11 d = 5, cD = 3, x = -8 2 5 d = 3, cD = 1, x = -8 d = 3, cD = 8, x = -8 3 x = 14 + λ Bild 3.18.7: Beispiel für die kostenminimale Kürzung des kritischen Wegs In der Situation Bild 3.19.7 kann x([Start, Ende]) über den kritischen Weg [[Start, 1], [1, Ende]] beliebig erhöht werden, λ ≥ 0, d.h., der kritische Weg kann nicht weiter verkürzt werden, 11 ist die minimale Projektdauer. Man kann die Ergebnisse des Kürzungsprozesses in der Projektdauer-Kosten-Funktion zusammenfassen, deren Graph Bild 3.19.8 zeigt. Kapitel 3: Minimalkosten-Strom- und Spannungsoptimierung 73 Kürzungskosten 55 50 45 40 35 30 25 20 15 10 5 Projektdauer 11 12 13 14 15 16 17 18 Bild 3.19.7: Projektdauer-Kosten-Funktion Diese Funktion ist ein nahezu ideales Instrument für Planungen: Mit ihr kann der Projektausführende in Verhandlungen mit seinem Auftraggeber gehen und zu jedem Wunsch bezüglich Ausführungsdauer sofort den Preis nennen – hinter dem ein ausführbarer Ablaufplan steht. Leider sind die realen Verhältnisse selten so ideal: Die Dauer einer Aktivität ist in der Regel von der Menge der zum Einsatz kommenden Ressourcen (Arbeitskräfte, Maschinen usw.) abhängig. Dieselben Arbeitskräfte und Maschinen, die eine fixierte Aktivität ausführen, führen in der Regel aber auch weitere Aktivitäten aus, so dass die Einsatzkosten nicht so einfach auf eine Aktivität umgeschlagen werden können. Folglich stehen die hier vorausgesetzten Dauer-Kosten-Funktionen für jede einzelne Aktivität in der Regel nicht zur Verfügung. Mit den Problemen des Ressourceneinsatzes in Arbeitsabläufen beschäftigt sich Kapitel 5. 74 Kapitel5: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 4. Minimalkosten-Stromproblem mit gekoppelten Flüssen 4.1 Motivierung und Aufgabenstellung Zur Motivierung der folgenden mathematischen Untersuchungen betrachten wir eine Anwendungsaufgabe aus dem Bereich zeitabhängiger Produktionsmengenplanungen: Gegeben sind 1. eine Anzahl gleichartiger Anlagen, die in „Rüstzustände“ Z1, Z2, …, Zm gebracht werden können 2. Vorgaben pit für die Produktion der Anlagen, i = 1, 2, …, m in Zeitabschnitten t = 1, 2, …, T. Bei den Anlagen könnte es sich z.B. um so genannte „numerisch gesteuerte Werkzeugmaschinen“ handeln, die per Programm zu ganz verschiedenen Produktionen fähig sind, die hier als Rüstzustände Zi bezeichnet werden. Zi symbolisiert also ein produziertes Warenprofil und pit sei eine zugehörige Mengenangabe - wie etwa, eine Anlage produziert im Zustand Zi während einer ProduktionsZeiteinheit (Tag, Woche, Monat, …) 100 Werkstücke der Sorte Wi. Eine Vorgabe pit bezieht sich auf den vorgesehenen Absatz der Produktion und somit auf Produktmengen. Im Sinne der Vereinfachung der Modellierung wollen wir die Vorgabe pit durch die Anzahl der Anlagen messen, deren Produktion im Rüstzustand Zi am Ende der t-ten ProduktionsZeiteinheit geliefert werden soll. Zu Beginn des Betrachtungszeitraums mögen vi der insgesamt verfügbaren Anlagen im Rüstzustand Zi, i = 1, 2, …, m, sein. Wir modellieren die Aufgabe als ein Minimalkosten-Stromproblem – vgl. Bild 4.1 – bei dem Anlagen von einem Rüstzustand in einen anderen und von einer Produktions-Zeiteinheit zur nächsten „fließen“: • In dem matrixartigen Schema Bild 4.1 stellen die Zeilen mit den Knoten Ait und Eit bei fixiertem i = 1, 2, …, m die Zustände Zi dar und ein Bogen [Ait, Eit] die Produktions-Zeiteinheit t = 1, 2, …, T; Ait steht für Anfang und Eit für Ende der Produktions-Zeiteinheit t. • x([Q, Ei0]) ≤ vi Anlagen gehen mit dem Rüstzustand Zi in den Produktionskreislauf. An den Knoten Eit kann diese Anzahl korrigiert werden, indem ein Teil dieser Anlagen in einen anderen Rüstzustand umgerüstet wird – Flüsse x([Eit, Aj(t+1)]), j ≠ i – oder indem Anlagen, die sich in einem anderen Rüstzustand befinden, auf Zi umgerüstet werden – Flüsse x([Ejt, Ai(t+1)]), j ≠ i. Umrüsten ist mit Kosten verbunden, die entsprechend als c-Werte zu diesen Bogen gehören. • Die Anlagen, die sich zu Beginn der t-ten Produktions-Zeiteinheit im Rüstzustand Zi befinden, können entweder produzieren – Fluss x([Ait, Eit]Prod) – oder still stehen – Fluss x([Ait, Eit]). Die tiefgestellte Bezeichnung an einer rechten Bogenklammer ist als Zusatz zur Bogenbezeichnung zu verstehen, mit der parallele Bogen unterschieden werden. • Die Produktionsergebnisse können gemäß Plan pit ausgeliefert oder auch gelagert werden. Lagerung verursacht Lagerkosten. Um Auslieferung und Lagerung zu modellieren, erzeugen wir zu dem Hauptnetz eine Reihe von Hilfsnetzen, die mit dem Hauptnetz verbunden werden müssen: • Zu jedem der Bogen x([Ait, Eit]Prod gehört ein zusätzliches Netz, das im Bild 4.1 für x([A12, E12])Prod stellvertretend skizziert ist und folgendes modellieren soll: Es sei x([Q12, S12]Lager) die Menge an produzierter Ware aus dem Rüstzustand Z1, die in der Produktions-Zeiteinheit 1 ( allgemein in einer früheren Produktions-Zeiteinheit) produziert und während der Produktionszeiteinheit 2 gelagert wurde. Unter der Voraussetzung, x([Q12, S12]Prod) = x([A12, E12]Prod) ist x([Q12, S12]Prod) + x([Q12, S12]Lager) die verfügbare Ware des Profils Z1 am Ende der ProduktionsZeiteinheit 2. Diese Menge wird neu aufgeteilt in Ware, die gemäß Plan ausgeliefert werden muss – p12 Einheiten – und solche, die in der nächsten Produktions-Zeiteinheit gelagert wird – x([S12, Q12]Lager). Es muss also gelten, x([Q12, S12]Lager) = x([S11, Q11]Lager), x([Q13, S13]Lager) = x([S12, Q12]Lager) usw. Zu den mit „Lager“ gekennzeichneten Bogen gehören Lagerhaltungskosten (c-Werte), die Sortenund Zeit-abhängig sein können. Zu den nicht weiter gekennzeichneten Bogen [S12, Q12], die die Auslieferung von Waren repräsentieren, gehören die zu erwartenden Gewinne / Preise (negative c-Werte) oder c = -gross, wobei gross eine große Zahl ist, die zur Produktionsstimulierung dient. Die mit Prod gekennzeichneten Bogen könnten die Produktionskosten als c-Werte erhalten, die ebenso wie die Umrüst- und Lagerkosten sowohl Sorten- als auch Zeit-abhängig sein können. Kapitel 4: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 75 Das Netz, das die Aufgabe modelliert, besteht aus m·T+1 zusammenhängende Komponenten. In ihm ist ein Minimalkosten-Stromproblem zu lösen, das allerdings die Zusatzforderungen, Flüsse in Bogen mit dem gleichen Kennzeichen sind gleich, erfüllen muss – im Bild wurden den Kennzeichen Prod und Lager noch Bogenidentifikationen angefügt. A11 E10 E11 A12 Prod11 E12 Prod12 b = v1 Q b = v2 E21 A21 E20 E22 A22 Prod21 Prod22 b = v3 A31 E30 E31 A32 E32 Prod32 Prod31 b=n Prod11 S11 Q11 Lager12 b = p11, c = -gross Prod12 Q12 Lager12 S12 Lager13 b = p12, c = -gross Bild 4.1: Ein Modell der zeitabhängigen Produktionsmengenplanung Wir verallgemeinern den Bedarf an Modellierungsinstrumentarien, den das Beispiel zeigt, zu der folgenden Aufgabenstellung: 76 Kapitel5: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen Minimalkosten-Stromproblem mit Kopplungen Gegeben ist eine Datenstruktur vom Typ tNetz, bestehend aus einem gerichteten Graphen G = [K, B] und über B erklärten Funktionen a(k), b(k), c(k), Partner(k) und f(k). a(k), b(k), c(k) und f(k) sind reell, während Partner(k) ∈ {1, 2, …, m}. Für a(k) und b(k) gilt a(k) ≤ b(k). Gesucht ist ein über B erklärter Vektor x, der folgende Bedingungen erfüllt: 7) x ist Strom in G. 8) Es gilt a(k) ≤ x(k) ≤ b(k) für k ∈ B. 9) x ist unter allen Vektoren, die die Bedingungen 1) und 2) erfüllen, einer, der die Funktion z(x) = ∑{ c(k)·x(k) | k = 1, 2, ..., m} minimiert. 10) Es gilt Partner(Partner(k)) = k und f(k)·x(k) = f(Partner(k))·x(Partner(k)) für k ∈ B. Folgende Festlegungen ergänzen diese Aufgabestellung: • Standard für die Kopplung ist, Partner(k) = k, f(k) = ½. Bogen, für die dieser Standard gilt, nennen wir ungekoppelt. • Partner(-k) = -Partner(k), f(-k) = f(k). In vielen Anwendungen besteht der Wunsch drei und mehr Bögen miteinander zu koppeln. Das ist sehr leicht möglich, indem man den Bogen k = [AKn, EKn] in die aufeinander folgenden Bogen k1 = [AKn, HKn1], …, ke = [HKne, EKn] zerlegt. Auf Grund der Strombedingung gilt, x(k) = x(k1) = x(k2) = …. Man kann nun k1, k2, … verschiedene Partner geben, und es gilt, f(k)·x(k) = f(Partner(k1))·x(Partner(k1)) = f(Partner(k2))·x(Partner(k2)) = …, d.h., alle diese Partner sind mit k gekoppelt. Die Kopplung von Bogen durch die Auflage, dass ihre Flüsse proportional sind, ermöglicht es, einer Minimalkosten-Stromaufgabe beliebige lineare Nebenbedingungen hinzuzufügen: Gegeben seien ein gewöhnliches Minimalkosten-Stromproblem und dazu die folgende Zusatzbedingung: Für die Flüsse der Bogen k1, k2, …, kr besteht die Forderung, a1(k1) ·x(k1) + a2(k2) ·x(k2) + … + ar(kr) ·x(kr) ≤ bN. Um die Forderung zu realisieren fügen wir dem bestehende Netz eine zweite zusammenhängende Komponente hinzu – vgl. Bild 4.2: Diese besitzt die Knoten QN und SN, r parallele Bogen [QN, SN]i für i = 1, 2, …, r sowie den Rückkehrbogen [SN, QN]. 1 2 QN SN r b = bN Bild 4.2: Zusatznetz für eine lineare Ungleichung als Zusatzbedingung Für Bogen ki gilt, Partner(ki) = [QN, SN]i, f(ki) = ai(ki); für Bogen [QN, SN]i gilt, Partner([QN, SN]i) = ki, f([QN, SN]i) = 1. Folglich gilt für den Rückkehrbogen, x[SN, QN] = ∑{x([QN, SN]i) | i = 1, 2, …, r} = ∑{ai(ki) ·x(ki) | i = 1, 2, …, r} und über die Flussschranke b([SN, QN]) = bN realisieren wir die Zusatzforderung. In ähnlicher Weise können wir ein vollständiges lineares Optimierungsproblem auf ein Minimalkosten-Stromproblem mit Kopplungen abbilden: Wir erzeugen ein Hauptnetz, das für jede Variable xj, j = 1, 2, …, r einen Weg aus m Bogen enthält – vgl. Bild 4.3. Jeder dieser Bogen [Knji, Knj(i+1)] wird von dem Fluss xj durchflossen: x([Knji, Knj(i+1)]) = xj. Kapitel 4: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 77 Nun wird für jede Nebenbedingung ai1·x1 + ai2·x2 + … + ain·xn ≤ bi ein Zusatznetz nach dem oben gegeben Schema – Bild 4.2 – angelegt, mit den Knoten QNi, SNi, i = 1, 2, …, m. Kopplung: Partner([Knji, Knj(i+1)]) = [QNi, SNi]j), f([Knji, Knj(i+1)]) = aij, Partner([QNi, SNi]j) = [Knji, Knj(i+1)], f([QNi, SNi]j) = 1. Folglich gilt, aij·x[Knji, Knj(i+1)]) = [QNi, SNi]j) oder aij·xj = x[QNi, SNi]j). Damit folgt aus der Strombedingung ∑{x([QNi, SNi]j) | j = 1, 2, …, n} = x[SNi, QNi] folgt ∑{ aij·xj | j = 1, 2, …, n} = x[SNi, QNi], für i = 1, 2, …, m. Mit dem im Bild 4.3 angegebenen Zielfunktionskoeffizienten ergibt sich die Minimierung der Funktion ∑{cj·xj | j = 1, 2, …, n} unter den Bedingungen ∑{aij·xj | j = 1, 2, …, n} ≤ bi, für i = 1, 2, …, m , xj ≥ für j = 1, 2, …, n. Kn11 Kn12 Kn1(n+1) Kn21 Kn22 Kn2(n+1) c = c1 Q c = c2 Q c = cn Knm1 Knm2 Knm(n+1) n c = -gross Bild 4.3: Hauptnetz für die Modellierung einer linearen Optimierungsaufgabe Natürlich kann es nicht Sinn und Zweck dieser Betrachtungen sein, jede lineare Optimierungsaufgabe als Aufgabe vom Typ Minimalkosten-Stromproblem mit gekoppelten Flüssen bearbeiten zu wollen. Aber die klassische Transportaufgabe ist eine lineare Optimierungsaufgabe, die sich auf Grund ihrer Struktur besonders leicht und elegant lösen lässt. Es geht also darum, auszuloten, wie weit sich diese Leichtigkeit und Eleganz für etwas komplexere Aufgaben retten lässt. Die Möglichkeit der Modellierung jeder linearen Optimierungsaufgabe als Stromproblem mit gekoppelten Flüssen demonstriert die Stärke des Modells und gibt dem Modellierer • zum einen die Sicherheit: Falls er glaubt, eine solche Problemmodellierung sei zweckmäßig, so gelingt sie auch • zum anderen das Wissen, dass die algorithmische Leichtigkeit der Lösung des originalen Minimalkosten-Stromproblems sich sicher nicht beliebig auf allgemeine Probleme mit Kopplung ausdehnen lässt, sondern ihre Grenzen dort findet, wo die Verflechtung der Variablen in allgemeinen linearen Restriktionen zu stark wird. Ein besonderer, leichter Fall – im Sinne der Nähe zum Problem ohne Kopplung - ist die Modellierung von Sammlern und Verteilern: Ein Sammlerknoten – kurz: Sammler – ist ein Knoten, dessen Eingangsflüsse in definierten Proportionen zum Ausgangsfluss stehen. Beispielsweise in einem Modell für den Transport von Frischbeton, in dem auch der Transport der Materialien Sand und Zement mitoptimiert wird, müsste man die Betonmischstation mit einem Eingang für Sand und einem Eingang für Zement versehen und die eingehenden Flüsse in ein Verhältnis setzen, das dem durchschnittlichen Mischverhältnis entspricht – z.B. 1:5: Es soll, bezogen auf Bild 4.4, für vorgegebene Werte s1, s2, …, se-1 gelten: x([E1, SE]) = 1/s1·x([SE, SA]), x([E2, SE]) = 1/s2·x([SE, SA]), …, x([Ee-1, SE]) = 1/se-1·x([SE, SA]). Gesetzmäßig gilt dann x([Ee, SE]) = (1 - 1/s1 – 1/s2 - … - 1/se-1)·x([SE, SA]). Um das zu erreichen muss [SE, SA] durch einen Weg aus Hilfsbogen ersetzt werden, [SE, H1], [H1, H2], …, [He-1, SA], und die Bogen dieses Weges werden wie folgt gekoppelt: Partner([SE, H1]) = [E1, SE], f([SE, H1]) = s1, f([E1, SE]) =1, Partner([H1, H2]) = [E2, SE], f([H1, H2]) = s2, f([E2, SE]) =1, …, Partner([He-2, He-1]) = [Ee-1, SE], f([He-2, He-1]) = se-1, f([Ee-1, SE]) = 1. 78 Kapitel5: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen Analog ist ein Verteilerknoten – kurz: Verteiler – ein Knoten, dessen Ausgangsflüsse in definierten Proportionen zum Eingangsfluss stehen müssen. E1 A1 1:s1 v1:1 1:s2 E2 A2 v2:1 SE SA VA VE Ee Ae Bild 4.4: Modell für einen Sammler und für einen Verteiler Wir demonstrieren die Zusammenhänge an einem einfachen Zahlenbeispiel – vgl. Bild 4.5: Im Knoten Verteiler soll die Hälfte des ankommenden Flusses zum Knoten Kn4 gehen und die andere Hälfte zu gleichen Teilen nach den Knoten Kn2 und Kn3. Im Knoten Sammler soll je ein Drittel des abgehenden Flusses von den Knoten Kn1, Kn2 und Kn3 kommen. Die Kopplungen Partner([Kn1, H]) = [Verteiler, Kn2], f([Kn1, H]) = 4, f([Verteiler, Kn2]) = 1, und Partner([H1, Verteiler]) = [Verteiler, Kn4], f([H, Verteiler]) = 2, f([Verteiler, Kn2]) = 1, bzw. Partner([Kn1, Sammler]) = [Sammler, Kn4], f([Kn1, Sammler]) = 1, f([Sammler, Kn4]) = 3 leisten das, wobei berücksichtigt wurde, dass die Flüsse x([Kn2, Sammler]) und x([Kn3, Sammler]) gleich sind (je ¼x([Verteiler, Kn4])), sodass aus x([Kn1, Sammler]) + x([Kn2, Sammler]) + x([Kn1, Sammler]) = x([Sammler, Kn4]) und 3x([Kn1, Sammler]) = x([Sammler, Kn4]) auch 3x([Kn2, Sammler]) = x([Sammler, Kn4]) und 3x([Kn3, Sammler]) = x([Sammler, Kn4]) folgen. 2:1 Kn1 Verteiler H Kn4 4:1 Kn3 Kn2 Sammler 3:1 Bild 4.5: Beispiel mit einem Verteiler und einem Sammler Kapitel 4: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 79 4.2 Theoretische Grundlagen für die Lösung des Minimalkosten-Stromproblems mit Kopplungen Das Ziel der folgenden Ausführungen ist es, die mathematischen und algorithmischen Erkenntnisse auf das neue Problem so zu übertragen, dass das gewöhnliche Minimalkosten-Stromproblem automatisch als Sonderfall erscheint. Zunächst halten wir fest, dass durch die Kopplung der Flüsse auch deren Schanken gekoppelt sind: f(k)⋅a(k) = f(Partner(k))⋅a(Partner(k)) und f(k)⋅b(k) = f(Partner(k))⋅b(Partner(k)) sind sinnvolle Voraussetzungen an diese Parameter, weil damit aus a(k) ≤ x(k) ≤ b(k) auch a(Partner(k)) ≤ x(Partner(k)) ≤ b(Partner(k)) folgt. Der Begriff der Basislösung, auf den wir den Algorithmus wieder abstützen wollen, überträgt sich wie folgt: Definition Eine B a s i s l ö s u n g des Minimalkosten-Stromproblems mit Kopplungen ist ein zulässiger Strom, der durch Vorgaben x(k) = a(k) oder x(k) = b(k) oder x(k) = f(Partner(k))⋅x(Partner(k)) / f(k) für k ∈ B\B’ eindeutig bestimmt ist, wobei B’ die Bogenmenge eines Gerüstes im Graphen G = [K, B] bezeichnet. B’ darf von jedem Paar gekoppelter Bogen höchstens einen Bogen enthalten. Bei dieser Übertragung ist der letzte Satz wichtig, der sich einfach ergibt, weil zwischen gekoppelten Bogen die Flussgleichung besteht, deren Einhaltung sich auf die Menge der Cogerüstbogen, die Gleichungs-Restriktionen repräsentieren, auswirkt. Der zweite wichtige theoretische Zusammenhang ist der Dualitätssatz. Im Dualitätssatz treten die beiden gekoppelten Bogen gemeinsam auf. Wir bilden dazu folgende Größen: C(k) = f(Partner(k))⋅c(k) + f(k)⋅c(Partner(k)) Y(k) = f(Partner(k))⋅y(k) + f(k)⋅y(Partner(k)). Man beachte, dass neben C(Partner(k)) = C(k) und Y(Partner(k)) = Y(k) für alle Bogen, für ungekoppelte Bogen, d.h. für Partner(k) = k und f(k) = 1/2, C(k) = c(k) und Y(k) = y(k) gelten. Mit den Größen C(k) und Y(k) lautet der Dualitätssatz – ohne Beweis: Dualitätssatz Gegeben sei eine Basislösung x des Minimalkosten-Stromproblems mit Kopplungen zu der das Gerüst G’ = [K, B’] gehört. Auf G’ definieren wir eine Spannung durch Y(k) = C(k) für k∈ B’. x ist genau dann optimale Lösung, wenn folgende Bedingung erfüllt ist: Für k ∈ B\B’ gilt: Falls x(k) = a(k), so ist Y(k) ≤ C(k) und, falls x(k) = b(k), so ist Y(k) ≥ C(k). Die Formulierung des Satzes besticht durch die Analogie zum einfachen Ausgangsproblem. Die Einfachheit täuscht jedoch etwas, was man schon erkennt, wenn man ein zu einem Gerüst „zugehöriges“ Potential – wie wir im Kapitel 3 formuliert haben – bilden will. Wir betrachten dazu das folgende Beispiel Dem Graphen im Bild 4.5 fügen wir die Standardparameter – a(k) = 0, b(k) = ∞, c(k) = 0 – hinzu, mit den Ausnahmen, b([Kn4, Kn1])) = 50, c([Kn4, Kn1])) = -1. Nun wählen wir die Ausgangslösung x = 0 und ein beliebiges Gerüst – vgl. Bild 4.6. Die Bestimmung des zum Gerüst (fette Bogen) zugehörigen Potentials x, auf dessen Bogen also Y(k) = C(k) erfüllt ist, verläuft beispielsweise wie folgt: 80 Kapitel5: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen t(Kn1) = 0; t(Kn4) = 1 wegen t(Kn4) – t(Kn1) = -1; t(Sammler) = 3/2 wegen 3(t(Kn4) – t(Sammler)) + t(Sammler) – t(Kn1) = 0; t(Kn2) = t(Kn3) = 3/2; t(Verteiler) = 3/2 und t(H) = 0 wegen 4t(H) + (3/2 - 3/2) = 0. Es zeigt sich, dass bei diesem Beispiel alle Bogen außer Bogen [H, Verteiler] und [Verteiler, Kn4] in die Potentialberechnung einbezogen sind. Dieses Bogenpaar ist out-of-kilter: Y([H, Verteiler]) = 5, C([H, Verteiler]) = 0, ¬(Y([H, Verteiler]) ≤ C([H, Verteiler])) obwohl x([H, Verteiler]) = 0. 2:1 Kn1 0 H 0 Kn4 1 Verteiler 3/2 4:1 Kn2 3/2 Kn3 3/2 Sammler 3/2 1:3 b = 50, c = -1 Bild 4.6: Beispiel für die Bestimmung eines zugehörigen Potentials Zum Abschluss der theoretischen Betrachtungen ein Blick auf die Frage nach der Lösbarkeit einer konkreten Aufgabe: Ein Minimalkosten-Stromproblem mit Kopplungen ist zunächst ein Minimalkosten-Stromproblem und unterliegt als solches den im Kapitel 2 genannten Lösungsbedingungen. Dort wurde empfohlen in der Lösungspraxis alle Lösbarkeitsprobleme zunächst zu umgehen, indem man an Stelle positiver unterer Fluss-Schranken erweiterte Preisfunktionen benutzt, also die Einhaltung der original gegebenen unteren Schranken nur zu stimulieren statt zu fordern. Wir unterstellen, dass auch die hier betrachtete erweiterte Aufgabenstellung so gehandhabt wird. Da das zusätzliche System aus Kopplungsgleichungen ein homogenes Gleichungssystem ist, besitzt es immer mindestens die triviale Lösung x = 0, und somit enthält der zulässige Bereich jeder konkreten Aufgabe auch im Fall des Minimalkosten-Stromproblems mit Kopplungen die Lösung x = 0. Die Aufgabe ist also zunächst lösbar, und Einschränkungen können an Hand der optimalen Lösung mit Bezug auf Datenfehler diskutiert werden. Satz Ein Minimalkosten-Stromproblem mit Kopplungen ist genau dann lösbar, wenn das zugrunde liegende gewöhnliche Minimalkosten-Stromproblem lösbar ist. Kapitel 4: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 81 4.3 Ein Lösungsalgorithmus für das Minimalkosten-Stromproblem mit Kopplungen (MKSK) Wie schon gesagt, sind wir bestrebt, den im Abschnitt 3.2.4 angegebenen Algorithmus auf die neuen Bedingungen zu übertragen. Wir zitieren deshalb den dort angegeben Algorithmus: 1. Vorbereitung 1.3 Gerüst aufstellen, so dass für die Cogerüstbogen k der Fluss x(k) durch a(k) oder b(k) bestimmt ist. Im Folgenden: x = 0. 1.4 Wir bestimmen über das Gerüst ein zugehöriges Potential so, dass y(k) = c(k) auf jedem Gerüstbogen gilt. Im Folgenden: Dijkstra-Algorithmus der kürzesten Wege mit Start = EKn(Rückkehrbogen), falls ein Rückkehrbogen existiert – in den meisten Transportmodellen. 3. Test, ob es einen Bogen k gibt, der bezüglich seiner Charakteristik out-of-kilter ist. Gibt es einen solchen Bogen kOut – andernfalls ist x eine optimale Lösung – so werden folgende Schritte ausgeführt: Solange ook(kOut) = true: 2.1 Bildung von z(kOut) (= Basiszyklus zum Cogerüstbogen kOut) und dx = Min{b(k) – x(k): k ∈ z(kOut)}; kFlusskrit sei ein Bogen, der das Minimum annimmt; x := x + dx⋅z(kOut)); Ist kFlusskrit ≠ kOut, so 2.2 Bildung von cz(kFlusskrit) (= Basiscozyklus zum Gerüstbogen kFlusskrit); dy = Min{c(k) – y(k): k ∈ cz(kFlusskrit) & (x(k) = a(k)) & ⌐ook(k)}; y := y +dy⋅cz(kFlusskrit)); kSpannkrit sei ein Bogen, der das Minimum annimmt. 3.1 Ist kSpannkrit ≠ kFlusskrit, so wird im Gerüst kFlusskrit durch kSpannkrit ersetzt. Zu 1. Vorbereitung: Im vorherigen Abschnitt haben wir bereits gesehen, dass nicht jedes Gerüst für eine Basislösung des Minimalkosten-Stromproblems mit Kopplungen geeignet ist, sondern in einem geeigneten Gerüst darf von jedem Paar gekoppelter Bogen höchstens ein Bogen vertreten sein. Im Zusammenhang damit muss neben x(k) = a(k) und x(k) = b(k) jetzt auch x(k) = x(Partner(k)) als Bedingungsgleichung eingesetzt werden – für gekoppelte Bogen. Außerdem wird das zugehörige Potential jetzt über die Bedingungen Y(k) = C(k) bestimmt. Wir brauchen also einen Algorithmus zur Bestimmung eines Gerüsts zur Startlösung x = 0 und des zu diesem Gerüst bezüglich der Bedingungen Y(k) = C(k) gehörenden Potentials t. Diese Aufgabe kann sehr gut ein dem Dijkstra-Algorithmus der Bestimmung der kürzesten Wege ähnlicher Algorithmus leisten: 4.3.1 Algorithmus zur Bestimmung eines Gerüsts zur Startlösung x = 0 und des zugehörigen Potentials • • Kn1 sei der Endknoten des Rückkehrbogens, sofern die Aufgabe einen Rückkehrbogen besitzt, andernfalls ein beliebiger Knoten: setT(Kn1, 0) = 0; initStzBg(Kn1) und K’ = {Kn1}; bilde CZ(K’) und ermittle für k ∈ CZ(K'): o falls Partner(k) = k: t(EKn(k)) = t(AKn(k)) + c(k); K’ = K’ + {EKn(k)}; setStzBg(EKn(k), k); wiederhole solange K’ ≠ K; o falls (Partner(k) ≠ k) & (EKn(k) = AKn(Partner(k)) & (StzBg(EKn(Partner(k))) ≠ 0) & (f(k) ≠ f(Partner(k)): t(EKn(k)) = (C(k) + f(Partner(k))·t(AKn(k)) – f(k)·t(EKn(Partner(k)))) / (f(k) - f(Partner(k)); K’ = K’ + {EKn(k)}; setStzBg(EKn(k), k); wiederhole solange K’ ≠ K; falls (Partner(k) ≠ k) & (EKn(k) = EKn(Partner(k)) & (StzBg(AKn(Partner(k))) ≠ 0): t(EKn(k) = (C(k) - f(Partner(k))·t(AKn(k)) + f(k)·t(AKn(Partner(k)))) / (f(k) + f(Partner(k)); K’ = K’ + {EKn(k)}; setStzBg(EKn(k), k); wiederhole solange K’ ≠ K; falls (Partner(k) ≠ k) & (StzBg(AKn(Partner(k))) ≠ 0) & (StzBg(EKn(Partner(k))) ≠ 0): t(EKn(k) = t(AKn(k) + (C(k) - f(k)·y(Partner(k))) / f(Partner(k)); 82 Kapitel5: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen K’ = K’ + {EKn(k)}; setStzBg(EKn(k), k); wiederhole solange K’ ≠ K; Beispiel Wir betrachten das Beispiel aus Bild 4.6: t(Kn1) = 0; K’ = {Kn1}; k = [Kn4, Kn1]; da Partner(k) = k: t(Kn4) = -1; StzBg(Kn4) = [Kn4, Kn1]; K’ = {Kn1}; -[Kn1, Sammler] ∈ CZ(K') & Partner([Kn1, Sammler]) = [Sammler, Kn4] & (EKn([Kn1, Sammler]) = AKn([Sammler, Kn4])) & (StzBg(Kn4) ≠ 0): t(Sammler) = 3/2; StzBg(Sammler) = [Kn1, Sammler]; K’ = {Kn1, Kn4, Sammler}; -[Kn2, Sammler] ∈ CZ(K') & Partner([Kn2, Sammler]) = [Kn2, Sammler]: t(Kn2) = 3/2; StzBg(Kn2) = -[Kn2, Sammler]; K’ = {Kn1, Kn2, Kn4, Sammler}; -[Kn3, Sammler] ∈ CZ(K') & Partner([Kn3, Sammler]) = [Kn3, Sammler]: t(Kn3) = 3/2; StzBg(Kn3) = -[Kn3, Sammler]; K’ = {Kn1, Kn2, Kn3, Kn4, Sammler}; -[Verteiler,Kn3] ∈ CZ(K') & Partner([Verteiler,Kn3]) = [Verteiler,Kn3]: t(Verteiler) = 3/2; StzBg(Verteiler)) = -[ Verteiler), Kn3]; K’ = {Kn1, Kn2, Kn3, Kn4, Sammler, Verteiler}; -[Kn1, H] ∈ CZ(K') & Partner([Kn1, H]) = [Verteiler,Kn2] & (StzBg(Verteiler) ≠ 0) & (StzBg(Kn2) ≠ 0): t(H) = 0; StzBg(H) = -[Kn1, H]; K’ = {H, Kn1, Kn2, Kn3, Kn4, Sammler, Verteiler} = K; Ende des Algorithmus, es wurde das im Bild 4.6 gezeigte Gerüst und das zugehörige Potential gefunden. Es bleibt noch die Frage offen, ob der Algorithmus zum Ende kommt, d.h., ob nicht der Fall eintreten könnte, dass ∀ k ∈ CZ(K') gilt, Partner(k) ≠ k und StzBg(AKn(Partner(k))) = StzBg(EKn(Partner(k))) = 0 2:1 Kn1 0 H Kn4 1 Verteiler 4:1 Kn3 1:3 Kn2 H2 Sammler 1:3 b = 50, c = -1 Bild 4.7: Beispiel für das Versagen des Start-Algorithmus bei Kopplung Als Beispiel betrachten wir wieder die Aufgabe aus Bild 4.5, der wir jetzt aber die überflüssige Kopplung Partner([Kn3, Sammer]) = [Sammler, Kn4] mit f([Kn3, Sammler]) = 3, f([Sammler, Kn4]) = 1 - natürlich über einen Hilfsknoten H2 - hinzugefügt haben. In diesem Beispiel tritt nach t(Kn1) = 0; t(Kn4) = 1; die Situation ein, dass alle Bogen aus Kapitel 4: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 83 CZ({Kn1, Kn4}) = {[Kn1, H], [Kn1, Sammler], -[H2, Kn4], -[Verteiler, Kn4]} Partner haben, deren Spannung jedoch in dieser Situation auch noch nicht bestimmt ist, sodass sie für die Potentialbestimmung nicht brauchbar sind. Man kann diesen Stillstand des Algorithmus überwinden, indem dieser in einer solchen Situation einfach einen Hilfsbogen k* parallel zu irgendeinem k ∈ CZ(K’) einfügt. k* bekommt die Bogenparameter a(k*) = 0, b(k*) = ∞, c(k*) = gross. Damit sollte in der optimalen Lösung x(k*) = 0 gelten, aber der Bogen wird zunächst durch den Algorithmus in das Startgerüst aufgenommen, wodurch die Stillstandssituation aufgelöst wird. Im Beispiel – vgl. Bild 4.7 wählen wir etwa k* = [Kn1, Sammler]2. (Die Bezeichnung ]2 soll wieder eine einfache Markierung für parallele Bogen sein – zweites Exemplar.) Der neue Bogen k* kommt ins Gerüst: K’ = {Kn1, Kn4, Sammler}; t(Sammler) = gross; dadurch ist jetzt [Kn2, Sammler] ∈ CZ(K’) und wird ins Gerüst aufgenommen usw. Es ergibt sich ein ähnliches Gerüst wie das aus Bild 4.6 und die gleiche Fortsetzung: Das Bogenpaar [H, Verteiler] und [Verteiler, Kn4] ist out-of-kilter, kOut = [H, Verteiler], (2(3 - gross – (3 - 2gross)/4) + (1 – (3 – gross)) = 5/2 /≤ 0). 2:1 Kn1 0 Kn4 1 Verteiler 3-gross H (3-2gross)/4 4:1 Kn3 3-gross Kn2 gross 1:3 H2 2/3gross c = gross Sammler gross 1:3 b = 50, c = -1 Bild 4.8: Beispiel für den erweiterten Start-Algorithmus ext. 4.3.2 Gleichgewicht für den Out-of-Kilter-Bogen Kehren wir zum allgemeinen Lösungsalgorithmus für das Minimalkosten-Stromproblem mit Kopplung zurück: Die veränderte Vorbereitung im Punkt 1 liefert zur Basislösung x = 0 ein Gerüst und ein zugehöriges Potential t. Schritt 2 – wie beim gewöhnlichen Minimalkosten-Stromproblem: Test, ob es einen Bogen k gibt, der bezüglich seiner Charakteristik out-of-kilter ist. Gibt es einen solchen Bogen kOut – andernfalls ist x eine optimale Lösung – so werden folgende Schritte 2.1 und 2.2 ausgeführt, solange kOut out-of-kilter ist: Schritt 2.1 – abweichend vom gewöhnlichen Minimalkosten-Stromproblem: Bildung eines Strom-Transformationsvektors dx(kOut) der Basislösung, mit dessen Hilfe die aktuelle Lösung x so transformiert werden kann, dass x := x + p⋅dx weniger stark von einem Gleichgewichtszustand abweicht; Bestimmung des maximalen Wertes von p und des Bogens kFlusskrit, der diesen maximalen Wert bestimmt. 84 Kapitel5: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen Erläuterung: Beim gewöhnlichen Minimalkosten-Stromproblem erzeugt der Cogerüstbogen kOut einen Basiszyklus z(kOut) – wir setzen zur Vereinfachung Zyklus und seine vektorielle Beschreibung gleich – und man kann den Vektor p·z(kOut), für gewisse p einfach zur Lösung x addieren, um wieder eine zulässige Lösung zu erhalten. Es gilt also, dx = z(kOut). Im allgemeinen Fall der Minimalkosten-Stromaufgabe mit Kopplung sind die Verhältnisse etwas komplizierter, weil 1. ein Bogenpaar kOut, Partner(kOut) out-of-kilter sein kann, so dass wir mindestens dx = z(kOut) + (f(kOut)/ f(Partner(kOut)))·z(Partner(kOut)) einsetzen müssen, um x zu transformieren 2. im Zyklus z(kOut) ein Bogen k liegen kann, der einen Partner, Partner(k), besitzt. Wenn x(k) um p·z(kOut, k) geändert wird, muss x(Partner(k)) um (f(k)/f(Partner(k)))·z(kOut, Partner(k))·p geändert werden, folglich muss statt z(kOut) dx = z(kOut) + (f(k)/f(Partner(k)))·z(kOut, Partner(k))·z(Partner(k)) einsetzt werden, um x zu transformieren. Die aufgezeigten Komplikationen sind jedoch nur der Anfang: In jedem Zyklus-Vektor, den man in den Strom-Transformationsvektor dx aufnimmt, können mehrere Bogen liegen, die einen Partner haben, und der Basisvektor jedes dieser Partner muss zwecks Einhaltung der Kopplungsbedingungen im Strom-Transformationsvektor enthalten sein. Definition Strom-Transformationsvektor dx zur Basislösung eines MKSK ist eine Linearkombination aus Basiszyklusvektoren zum aktuellen Cogerüst, die so beschaffen ist, dass • dx(ook) = 1, d.h. Stromänderung um einen noch zu bestimmenden Wert p bei ook • f(k)·dx(k) – f(Partner(k))·dx(Partner(k)) = 0 für Bogen mit Partner(k) ≠ k und dx(k) ≠ 0 gilt. Man kann sich die Verhältnisse auch über einen Hilfsgraphen verdeutlichen: Im Hilfsgraphen wird jeder Basiszyklus zi einer Basislösung x durch einen Knoten repräsentiert. Von einem Knoten zi führt ein Bogen zum Knoten zj, wenn im Zyklus zi ein Gerüstbogen k enthalten ist, dessen Partner (- ein Cogerüstbogen) im Zyklus zj liegt. Wir demonstrieren dies im Bild 4.9 an dem Beispiel aus Bild 4.6: Z2 2 Z3 1/4 dx1 =1 2dx1 – dx2 =0 dx2 – 4dx3 =0 (-dx1 + dx2 +dx4 ) – 3dx4 = 0 dx1 = 1, dx2 = 2, dx3 = ½, dx4 = ½ dx = z1 + 2z2 + ½z3 + 1/3z4 Z1 1/2 -1 Z4 1/3 Bild 4.9: Hilfsgraph zur Bildung eines Strom-Transformationsvektors Es gibt vier Basiszyklen: z1 = [[Verteiler, Kn4], -[Sammler, Kn4], -[Kn3, Sammler], -[Verteiler, Kn3]], z2 = [[H, Verteiler] , [Verteiler, Kn3], [Kn3, Sammler], [Sammler, Kn4], [Kn4, Kn1], [Kn1, H]], z3 = [[Verteiler, Kn2], [Kn2, Sammler], -[Kn3, Sammler], -[Verteiler, Kn3]], z4 = [[Kn1, Sammler], [Sammler, Kn4], [Kn4, Kn1]]. Kapitel 4: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 85 Ein Fluss der Stärke 1 durch z1 impliziert neue Flüsse, nämlich einen Fluss der Stärke 2 durch seinen Partner-Bogen [H, Verteiler] und einen Fluss der Stärke -1/3 durch den Bogen [Kn1, Sammler]. Ein Fluss durch den Bogen [H, Verteiler] fordert einen entsprechenden Fluss durch z2, und der Fluss durch den Bogen [Kn1, Sammler] fordert einen entsprechenden Fluss durch z4. Ein Fluss der Stärke 2 durch z2 impliziert weitere Flüsse, nämlich einen Fluss der Stärke 2/3 durch den Bogen [Kn1, Sammler], d.h. durch z4, und einen Fluss der Stärke 1/2 durch den Bogen [Verteiler, Kn2] , d.h. durch z3. Aus dem Graphen ergibt sich das nebenstehende Gleichungssystem zur Bestimmung der Koeffizienten, mit denen die Zyklenvektoren im Strom-Transformationsvektor auftreten. Führen wir mit diesem Strom-Transformationsvektor eine Strom-Transformation x = x + p⋅dx aus, die bezüglich x(kOut) maximal ist (kOut = [Verteiler, Kn4]), so ist der Bogen [Kn4, Kn1] für diese Transformation flusskritisch: x(kFlusskrit) = 2,5p ≤ 50 oder p ≤ 20, und wir erhalten den im Bild 4.10.1 gezeigten Strom. 2:1 Kn1 0 x = 40 H 0 Verteiler 3/2 x = 40 Kn4 1 x = 20 x = 10 4:1 x = 10 x = 10 Kn3 3/2 x = 30 Kn2 3/2 x = 10 x = 10 Sammler 3/2 1:3 x = b = 50, c = -1 Bild 4.10.1: Maximaler Fluss durch den Bogen [Kn4, Kn1] ext. Falls die Flussverstärkung p⋅dx nicht ausreicht, kOut in einen Gleichgewichtszustand zu überführen, d.h., falls kFlusskrit ≠ kOut, kommen wir zum nächsten Schritt des Lösungsalgorithmus: Schritt 2.2: Bildung eines Spannungs-Transformationsvektor der Basislösung dy(kFlusskrit), mit dessen Hilfe die aktuelle duale Lösung y so transformiert werden kann, dass y = y + q⋅dy(kOut) weniger stark von einem Gleichgewichtszustand abweicht; Bestimmung des maximalen Wertes von q und des Bogens kSpannkrit, der diesen maximalen Wert bestimmt. Erläuterung: Im Fall der gewöhnlichen Minimalkosten-Stromaufgabe wäre dy = cz(kFlusskrit), der Basiscozyklusvektor zum Gerüstbogen kFlusskrit. Wir betrachten das Beispiel im Bild 4.10.1: kFlusskrit = [Kn4, Kn1], cz(kFlusskrit) = cz1 = CZ({Kn2, Kn3, Kn4, Sammler, Verteiler}) – bezogen auf die Knotenmenge. Eine Potentialänderung der Größe -dt1 in den erzeugenden Knoten stört das Gleichgewicht des Bogenpaares [Kn1, Sammler] und [Sammler, Kn4] und impliziert somit eine weitere Potentialänderung -dt2 in den Knoten, die cz([Sammler, Kn4]) = cz2 = CZ({Kn2, Kn3, Sammler, Verteiler}) erzeugen, also dy = dt1·cz(kFlusskrit) + dt2·cz([Kn3, Sammler]) und es muss gelten, dt1 = 1, (-dt1 - dt2) + 3dt2 = 0, dt1 = 1, dt2 = ½. 86 Kapitel5: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen Mit dem Transformationsvektor dy = cz1 + 1/2cz2 können wir das Bogenpaar [H, Verteiler] und [Verteiler, Kn4] in einen Gleichgewichtszustand überführen ohne die bestehenden Gleichgewichtszustände zu stören: y = y + q⋅dy, liefert bei q = 1 das Potential t = 0, mit dem trivialerweise alle Kopplungsbedingungen erfüllt sind - Bild 4.10.2. In dieser Lösung sind alle Bogen bzw. Bogenpaare in einem Gleichgewichtszustand, folglich handelt es sich um die optimale Lösung. Definition Spannungs-Transformationsvektor dy der Basislösung eines NMKP ist eine Linearkombination aus Basiscozyklusvektoren zum aktuellen Gerüst, die so beschaffen ist, dass • dy(ook) = 1, d.h. Spannungsänderung um ein noch zu bestimmenden Wert q bei ook • f(Partner(k)·dy(k) + f(k)·dy(Partner(k)) = 0 für Bogen mit Partner(k) ≠ k, gilt. Im Anschluss an Schritt 2.2 muss noch der Schritt 2.3 ausgeführt werden: Schritt 2.3: Im Gerüst ist kFlusskrit durch kSpannkrit zu ersetzen. Auch dieser Schritt verläuft im Fall der Kopplung nicht ganz so einfach wie im Fall der gewöhnlichen Aufgabe, denn kFlusskrit und kSpannkrit liegen jetzt im Allgemeinen nicht mehr in einem Zyklus- vgl. Bild 4.11. Man kann den Austausch wie folgt vollziehen: • Suche im Basiszyklus z(kSpankrit) nach kFlusskrit oder einen Bogen k mit Partner(k) ≠ 0. • Tausche im Gerüst kFlusskrit gegen k und setze, falls k ≠ kFlusskrit, kSpannkrit := Partner(k). • Wiederhole den Prozess solange k ≠ kFlusskrit. spannKrit k1 k1 k2 k2 flussKrit Bild 4.11: Änderung des Gerüsts nach Änderung der Basislösung - schematisch Schritt 2.3 an unserem Beispiel: Ausgehend von dem Zustand im Bild 4.10.1 durchmustern wir z1 = z(kSpannkrit) = [[Verteiler, Kn4], -[Sammler, Kn4], -[Kn3, Sammler], -[Verteiler, Kn3]], ob er Kapitel 4: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 87 kSpannkrit enthält (hier: kOut = kSpannkrit = [Verteiler, Kn4]). Da dies nicht der Fall ist, tauschen wir die Gerüstzugehörigkeit von kSpannkrit gegen die von [Sammler, Kn4] und setzen kSpannkrit := Partner([Sammler, Kn4]) = [Kn1, Sammler] und wiederholen: Durchmusterung von z(kSpannkrit) = [[Kn1, Sammler], -[Kn3, Sammler], -[Verteiler, Kn3], [Verteiler, Kn4], [Kn4, Kn1]]. Da wir diesmal kFlusskrit = [Kn4, Kn1] finden, endet nach dem Austausch [Kn1, Sammler] im Gerüst gegen kFlusskrit der Prozess, und wir haben im Bild 4.10.2 die optimale Basislösung vorliegen. 2:1 Kn1 0 x = 40 H 0 Verteiler 0 x = 40 Kn4 0 x = 20 x = 10 4:1 x = 10 x = 10 Kn3 0 x = 30 Kn2 0 x = 10 x = 10 Sammler 0 1:3 x = b = 50, c = -1 Bild 4.10.2: Maximaler Fluss durch den Bogen [Kn4, Kn1] – optimalen Lösung ext. 4.3.3 Softwaretechnische Realisierung des Algorithmus Neben der veränderten Erzeugung einer Startlösung: Die in einer Software realisierte algorithmische Erzeugung eines SpannungsTransformationsvektors dy erfolgt mit einem Objekt GlgSystem zur Aufstellung und Lösung des angegebenen Gleichungssystems wie folgt: • Mit dem Konstruktor public GlgSystem(int varNr) wird die Gleichung dy(ook) = 1 angelegt. • Die Methode public void addOrKorrGlchg(int varNr1, int varNr2, double koeff) o sucht, ob es schon eine zu varNr1 gehörende Gleichung gibt o gibt es eine varNr1 zugeordnete Gleichung, so wird deren varNr2 zugeordnetes Glied gesucht und um koeff vergrößert o gibt es noch keine varNr1 zugeordnete Gleichung, so wird das Gleichungssystem um eine neue Gleichung mit den beiden Variablen varNr1 (Koeffizient 1) sowie varNr2 (Koeffizient koeff) ergänzt. • Die Methode public void loeseGlgSystem() berechnet die Lösung des einfachen Gleichungssystems nach dem Gaußschen Algorithmus. Anschließend können mit der Methode public IntDouble getItem(Gleichung r) jeweils varNr und wert abgefragt werden. Nach der Initialisierung von GlgSystem werden in einer Schleife die zu dem wachsenden Gleichungssystem gehörenden varN-ummer-n bestimmt und cz(varNr) erzeugt - varNr ist die Nummern eines kritischen Bogens. Nun wird für alle Bogen (= varNr1) mit Partner geprüft, ob sie kritisch sind und ob ihr partner (= varNr2) zum Cozyklus gehört. Ist beides der Fall, wird 88 Kapitel5: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen GlgSystem.addOrKorrGlchg(varNr1, varNr2, cz(varNr, varNr2)*v(varNr1)) aufgerufen. Bricht der Prozess ab, so wird mit der Lösung koeff = (koeff(varNr1), koeff(varNr2), …, koeff(varNrE)) die Linearkombination dy = koeff(varNr1)* cz(varNr1) + koeff(varNr2)* cz(varNr2) + …+ koeff(varNr1)* cz(varNr) gebildet, mit der eine neue Basislösung erzeugt werden kann. 4.3.4 Beispiele für das Minimalkosten-Stromproblem mit Kopplungen 4.3.4.1 Ein Zahlenbeispiel für die zeitabhängige Produktionsmengenplanungen Im Folgenden soll das motivierende Einführungsbeispiel dieses Kapitels (Abschnitt 4.1) durch ein Zahlenbeispiel ergänzt werden: Q1 0 b = 5, c = -10 E10 0 b=3 A11 0 S1 10 E11 -10 A12 -10 E12 0 c=1 c=1 Q 0 S 0 b=2 c=1 c=1 E20 0 A21 0 E21 -10 A22 -10 E22 0 Q2 10 b = 5, c = -10 S2 0 Bild 4.12.1: Zahlenbeispiel für die zeitabhängige Produktionsmengenplanung - Anfangslösung Wir wählen 5 Anlagen, die während zwei Zeitabschnitten in zwei möglichen Rüstzuständen produzieren sollen. Anfangs befinden sich drei der Anlagen im Rüstzustand 1, die beiden anderen im Kapitel 4: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 89 Rüstzustand 2. Das Umrüsten einer Anlage kostet in jedem Fall 1 Geldeinheit. Der Erlös aus der Produktion einer Anlage während 1 Zeiteinheit beträgt 10 Geldeinheiten, unabhängig von der Zeit und dem Rüstzustand. Es werden am Ende des zweiten Zeitabschnittes die Produktionen von je 5 Anlagen in jeden der beiden Rüstzustände benötigt. Bild 4.12.1 skizziert das vereinfachte Modell bestehend aus dem Hauptnetz und zwei Hilfsnetzen, die über Kopplung die Produktionsauflage realisieren: x([Q1, S1]links) = x([A11, E11]), x([Q1, S1]rechts) = x([A12, E12]) → x([A11, E11]) + x([A12, E12]) ≤ 5; x([Q2, S2]links) = x([A21, E21]), x([Q2, S2]rechts) = x([A22, E22]) → x([A21, E21]) + x([A22, E22]) ≤ 5. In das Bild 4.12.1 ist zur Anfangslösung x = 0 ein Gerüst eingetragen. Es sind genau die Paare ([Q1, S1]rechts, [A12, E12]) und ([Q2, S2]rechts, [A22, E22]) out-of-kilter. Wir wählen gleichgroße Flussverstärkung p über die Zyklen z([Q1, S1]rechts) und z([A12, E12]). Der letztgenannte Zyklus impliziert üben den Bogen [A11, E11] eine gleichgroße Flussverstärkung im Zyklus z([Q1, S1]links). Es ergibt sich kFlusskrit = [S1, Q1] mit p = 2,5. Spannungsänderung um 1 über die Cozyklen cz([S1, Q1]) und cz([A11, E11]) mit kSpannkrit = [A12, E12] (bzw. seinem Partner [Q1, S1]rechts). Im Gerüst muss [S1, Q1] durch [A12, E12] ersetzt werden, verbunden mit dem Ersatz [A11, E11] durch [Q1, S1]links Es ergibt sich der Zustand im Bild 4.12.2. Q1 0 x = 2,5 b = 5, c = -10, x= 5 E10 0 b=3 A11 0 x = 2,5 S1 9 E11 -9 c=1 A12 -9 x = 2,5 E12 0 c=1 Q 0 S 0 b=2 c=1 c=1 E20 0 A21 0 E21 -10 A22 -10 E22 0 Q2 0 x=0 b = 5, c = -10 S2 10 Bild 4.12.2: Zahlenbeispiel für die zeitabhängige Produktionsmengenplanung - 1. Zwischenlösung 90 Kapitel5: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen Das Paar ([Q1, S1]rechts, [A12, E12]) ist weiter out-of-kilter: Gleichgroße Flussverstärkung p über die Zyklen z([Q1, S1]rechts) und z([A12, E12]); der erstgenannte Zyklus impliziert über den Bogen -[Q1, S1]links eine gleichgroße Flusssenkung im Zyklus z([A11, E11]); die Zyklen z([A12, E12]) und z([A11, E11]) implizieren über den Bogen [A21, E21] eine Flussverstärkung im Zyklus z([Q2, S2]links) mit dem Faktor 2; bei p = 1 ergibt sich der Strom im Bild 4.12.3 bei kFlusskrit = [Q, E20]. Spannungsänderung über die Cozyklen cz([Q, E20]) und cz([Q1, S1]links); kSpannkrit = [E10, A21]. Im Gerüst muss [Q, E20] durch [E10, A21] ersetzt werden. Es ergibt sich der Zustand im Bild 4.12.3. Q1 0 x = 3,5 b = 5, c = -10, x= 5 E10 0 b=3 A11 0 x = 1,5 S1 8 E11 -8 c=1 A12 -8 x = 3,5 E12 0 c=1 Q 0 S 0 b = 2, x = 2 c=1 c=1 E20 1 A21 1 E21 -9 A22 -9 x=0 E22 0 Q2 0 x=2 b = 5, c = -10, x=2 S2 10 Bild 4.12.3: Zahlenbeispiel für die zeitabhängige Produktionsmengenplanung - 2. Zwischenlösung Das Paar ([Q1, S1]rechts, [A12, E12]) ist weiter out-of-kilter: Gleichgroße Flussverstärkung p über die Zyklen z([Q1, S1]rechts) und z([A12, E12]); der erstgenannte Zyklus impliziert über den Bogen -[Q1, S1]links eine gleichgroße Flusssenkung im Zyklus z([A11, E11]); die Zyklen z([A12, E12]) und Kapitel 4: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 91 z([A11, E11]) implizieren über den Bogen [A21, E21] eine Flussverstärkung im Zyklus z([Q2, S2]links) mit dem Faktor 2; bei p = 1,5 ergibt sich der Strom im Bild 4.12.4; kFlusskrit = [S2, Q2] (eine von mehreren Möglichkeiten). Spannungsänderung über die Cozyklen cz([S2, Q2]), cz([A21, E21]) und cz([Q1, S1]rechts); kSpannkrit = kOut = [A12, E12]. Im Gerüst muss [Q, E20] durch [E10, A12] ersetzt werden. Es ergibt sich der Zustand im Bild 4.12.4. Q1 0 x=5 b = 5, c = -10, x= 5 E10 0 b=3 A11 0 x=0 Q1 0 E11 0 A12 0 E12 0 c=1 c=1 Q 0 S 0 x=2=b c=1 c=1 E20 1 A21 1 x=5 E21 -1 A22 -1 x=0 E22 0 Q2 0 x=0 b = 5, c = -10, x=5 S2 2 Bild 4.12.4: Zahlenbeispiel für die zeitabhängige Produktionsmengenplanung - 3. Zwischenlösung Jetzt ist nur noch das Paar ([Q2, S2]rechts, [A22, E22]) out-of-kilter: Gleichgroße Flussverstärkung p über die Zyklen z([Q2, S2]rechts) und z([A22, E22]); der erstgenannte Zyklus impliziert über den Bogen -[Q2, S2]links eine gleichgroße Flusssenkung im Zyklus z([A21, E21]); diese Senkung impliziert über den Bogen [A12, E12] eine gleichgroße Flusssenkung im Zyklus z([Q1, S1]rechts) wodurch über [Q1, S1]links auch der Zyklus z([A11, E11]) in die Operation einbezogen wird; bei p = 2,5 ergibt sich schließlich der Strom im Bild 4.12.5; kFlusskrit = [A21, A12]. Spannungsänderung über die Cozyklen cz([E21, A12]) und cz([S2, Q2]rechts ); 92 Kapitel5: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen kSpannkrit = kOut = [A22, E22]. Im Gerüst muss [E21, A12] durch [A22, E22] ersetzt werden. Es ergibt sich der optimale Zustand im Bild 4.12.5. Q1 0 x = 2,5 b = 5, c = -10, x= 5 E10 0 b=3 A11 0 x = 2,5 Q1 0,5 E11 0 A12 0 E12 0 c=1 c=1 Q 0 S 0 b = 2, x = 2 c=1 c=1 E20 1 A21 1 x = 2,5 E21 0,5 A22 0,5 E22 0 x=5 Q2 0 x = 2,5 b = 5, c = -10, x=5 S2 0,5 Bild 4.12.5: Zahlenbeispiel für die zeitabhängige Produktionsmengenplanung – optimale Lösung Auswertung: Wenn man sich mit dem zunächst vielleicht komplex erscheinenden Modell etwas vertraut gemacht hat, erkennt man, dass die optimale Lösung trivial ist: Minimierung des Umrüstaufwandes – das Minimum wird erreicht, wenn man eine halbe Anlage vom Zustand 1 in den Zustand 2 umrüstet. Andererseits gewinnt man einen guten Einblick in die Arbeitsweise des Algorithmus und eben auch in die Problematik der Ganzzahligkeit: Man kann nicht mehr – wie beim einfachen Minimalkosten-Stromproblem – ganzzahlige Lösungen erwarten. Falls die Ganzzahligkeit wichtig ist, muss man mit Methoden der ganzzahligen Optimierung arbeiten, z.B. mit einem Branchand-Bound-Verfahren. Dabei kann man das stetige Problem als Hilfsproblem benutzen. Am hier betrachten Beispiel könnte man nach der eben demonstrierten Lösung versuchen, über eine Fallunterscheidung – Fall 1: x([E10, A21]) = 0, Fall 2: x([E10, A21]) ≥ 1 – Klarheit zu gewinnen. Dies wird auch in der folgenden Anwendung demonstriert. Kapitel 4: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 93 Am Beispiel würde die optimale Lösung des Falls 1 x([E11, A22]) = 1 liefern, also eine Lösung, die ersichtlich für die ganzzahlig Aufgabenstellung optimal ist, was man auch daran erkennen kann, dass sie nur 0,5 Geldeinheiten teurer ist, als das stetige Optimum. 4.3.3.2 Das Knappsackproblem als Minimalkosten-Stromproblem mit Kopplungen Betrachtet wird folgendes Knappsackproblem: Gegenstand-Nr. 1 2 3 4 5 Gewicht Wert Tabelle 4.1 2 23 8 12 4 4 1 13 9 3 Im Abschnitt 2.2 haben wir dieses ganzzahlig lineare Optimierungsproblem in ein Längste-WegeProblem überführt. Hier wollen wir das konkrete Zahlenbeispiel nutzen, um die Überführung einer linearen Optimierungsaufgabe in ein Minimalkosten-Stromproblem mit Kopplungen zu demonstrieren. Als lineares Optimierungsproblem lautet die Aufgabe: Minimiere die Zielfunktion 23x1 + 12x2 + 4x3 + 13x4 + 3x5 unten folgenden Bedingungen: • • xi ∈ {0, 1} für i = 1, 2, 3, 4, 5 2x1 + 8x2 + 4x3 + x4 + 9x5 ≤ 10. Es soll nach dem Branch-and-Bound-Verfahren gelöst werden, wobei das zugehörige stetige lineare Optimierungsproblem (0 ≤ xi ≤ 1 statt xi ∈ {0, 1}) auf ein Minimalkosten-Stromproblem mit Kopplungen abgebildet wird: In der folgenden Abbildung 4.13.1 steht das Netz links oben – Netz 0 – für die Zielfunktion, während das Netz rechts unten – Netz 1 – die Nebenbedingung darstellt. An den Bogen ist eine Nummerierung „i:“ angebracht, die der obigen Variablennummerierung entspricht und die Bogenkopplung definiert: Mit xik = Fluss im Bogen i des Netzes k gilt für Bogen mit gleicher Nummer fi1·xi0 = xi1. Im Netz 0 gilt bi = 1 für alle i, alle anderen nicht explizit angegeben Parameter entsprechen den vereinbarten Standards. Die Anfangslösung ist: t = 0, x = 0, [S0, Q0] und [S1, Q1] bilden das Gerüst. Alle Bogenpaare sind out-of-kilter: [Q0, S0]1, [Q1, S1]1: x10 =1, x11 = 2, ist für das erste Bogenpaar ein Gleichgewichtszustand; [Q0, S0]4, [Q1, S1]4: x40 =1, x41 = 1, ist für das vierte Bogenpaar ein Gleichgewichtszustand; [Q0, S0]2, [Q1, S1]2: x20 =7/8, x21 = 7, ist für das zweite Bogenpaar ein Gleichgewichtszustand, wobei x21 = 7 durch die Schranke b([S1, Q1]) = 10 bestimmt wird, was erfordert, dass [S1, Q1] im Gerüst gegen [Q1, S1]2 ausgetauscht wird. Dabei ergibt sich aus Y([Q1, S1]1) = C([Q1, S1]1) bzw. aus 0 + 8y21 = -12 y21 = -3/2, womit alle Bogenpaare im Gleichgewicht sind (2(-3/2) ≥ -23, 4(-3/2) ≤ -4, 1(-3/2) ≥ -13, 9(-3/2) ≤ -3). Bild 4.13.1 zeigt diese optimale Lösung, die wegen x2 = x20 = 7/8, Gewinn = 46,5, nicht die originale Knappsackaufgabe löst. 94 Kapitel5: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 1: f = 2, c = -23, x = 1 2: f = 8, c = -12, x = 7/8 Q0 0 3: f = 4, c = -4 S0 0 4: f = 1, c = -13, x = 1 5: f = 9, c = -3 1: x = 2 2: x = 7 Q1 3/2 3: x = 0 S1 0 4: x = 1 5: x = 0 b = 10, x = 10 Bild 5.13.1: Das Netzmodell für die Knappsackaufgabe in Tabelle 5.1, erste Lösung Es wird eine Verzweigung („branch“) nach x2 = 0 oder x2 = 0 notwendig, und es folgt eine Wiederholung der Flussoptimierung in den Teilbereichen. a) x2 = 0: x1 = 1, x3 = 1, x4 = 1 und x5 = 1/3, Gewinn = 41, da die Lösung eindeutig ist, ist der Bound < 41 und ganzzahlig, also = 40 – vgl. Bild 4.13.2. b) x2 = 1: x1 = 1/2, x4 = 1, Gewinn = 36,5. Der Teilbereich a) enthält den Gitterpunkt x1 = 1, x3 = 1, x4 = 1, Gewinn = 40, folglich kann der Teilbereich b) ausgeschlossen werden, und der genannte Gitterpunkt ist die optimale Lösung. 1: f = 2, c = -23, x = 1 Q0 0 3: f = 4, c = -4, x = 1 S0 0 4: f = 1, c = -13, x = 1 5: f = 9, c = -3, x = 1/3 1: x = 2 Q1 1/3 3: x = 4 S1 0 4: x = 1 5: x = 3 b = 10, x = 10 Bild 5.13.2: Das Netzmodell für die Knappsackaufgabe in Tabelle 5.1, Lösung für x2 = 0 Kapitel 4: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 95 4.4 Das Mehrsorten-Stromproblem Im Abschnitt 3.1 haben wir bereits ein einfaches Mehrsorten-Stromproblem kennen gelernt: Warenproduzenten erzeugen mehrere Güter, die getrennt an die Empfänger ausgeliefert werden. Die Gesamtproduktionskapazität eines Warenproduzenten wird verglichen mit der Summe der produzierten Mengen der einzelnen Sorten, indem im graphischen Modell – vgl. Bild 3.3 – durch die Bogen [Q, Lieferi] alle von Lieferi produzierten Warensorten fließen und somit in ihrer Summe durch die Gesamtlieferkapazi = b([Q, Lieferi]) beschränkt werden. Von den Knoten Lieferi aus fließen die Güter dann über sortenreine Teilnetze zu den Empfängern EmpfgSjk - Empfängern j der Sorte k. Mit Hilfe der Kopplungsmöglichkeit lässt sich dieses Modell auf lineare Beziehungen zwischen den verschiedenen Warensorten, die ein Produzent liefert, verallgemeinern: Gilt ∑{αk·x([Lieferi, LieferSik]) | k = 1, 2, …,s} ≤ Gesamtlieferkapazi, so lassen wir die Beschränkung der Bogen [Q, Lieferi] fallen und fügen stattdessen für jeden Lieferanten ein Zusatznetz für diese lineare Ungleichung gemäß Bild 4.2 hinzu, dessen Bogen mit den Bogen [Lieferi, LieferSik] gekoppelt sind. Generell bietet die Kopplung vielfältige Möglichkeiten, an sich getrennte Kommunikationsnetze durch „gemeinsame“ Bogen zu verbinden. Die Detailmodellierung wird jedoch mühselig, wenn die Anzahl der Bogen, die von mehreren Sorten durchströmt werden, sehr groß ist. Wir bieten daher im Folgenden ein Modell, bei dem umgekehrt jeder Bogen a priori von allen möglichen Sorten gleichzeitig durchströmt wird und der sortenreine Bogen eine Ausnahme ist – vgl. [DA J. Müller]. Aufgabe Mehrsortentransport Gegeben sei ein Netz N = [K, B, a, b, c] durch • einen gerichteten Graphen G = [K, B] und • Funktionen a(k), b(k), c(k) für k ∈ B. B ist die Vereinigung der paarweise disjunkten Bogenmengen B und Bs für s = 1, 2, …, sAnz; in K sind Teilmengen Qs (Quellen des Sortenstroms der Sorte s) und Ss (Senken des Sortenstroms der Sorte s) für s = 1, 2, …, sAnz definiert. Gesucht sind Vektoren x(s) = (x(1, s), x(2, s), …, x(ms, s)), ms = |Bs| = |B U Bs| und s = 1, 2, …, sAnz, die die folgenden Bedingungen erfüllen: • x(s) ist Strom auf dem Untergraphen Gs = U(Ks) = [Ks, Bs] von G, der alle Bogen der Bogenmenge Bs = B U Bs enthält. • Es gilt a(k) ≤ x(k, s) ≤ b(k) für k ∈ Bs und mit x(k) = ∑{x(k, s) | s = 1, 2, …, sAnz} auch für k ∈ B. • ∑{∑{c(k, s)·x(k, s) | s = 1, 2, …, sAnz} k = 1, 2, …, m} ist minimal unter diesen Bedingungen. Erläuterung: Bs sind die Mengen der sortenreinen Bogen – Sorte s, Sortenanzahl sAnz. B ist die Menge, der Bogen, die von allen Sorten durchströmt werden können. Entsprechend ist der Fluss durch einen Bogen k ∈ B ein Vektor x(k) = (x(k, 1), x(k, 2), …, x(k, sAnz)), während der Fluss durch einen sortenreinen Bogen k ∈ Bs eine Zahl ist, x(k) = x(k, s). Dasselbe gilt für die Preise: Für k ∈ Bs ist c(k) eine Zahl, für k ∈ B ist c(k) = (c(k, 1), c(k, 2), …, c(k, sAnz)) ein Vektor. Die Flussbeschränkungen in den Bogen von k ∈ B betreffen die Summe ∑{x(k, s) | s = 1, 2, …, sAnz} = x(k) aller Sortenflüsse durch den Bogen. Bild 4.11 skizziert (3-dimensional) das Transportmodell auf dessen Bearbeitung die Aufgabe zugeschnitten ist: Der graue elliptische Bereich soll das allen Sorten gemeinsame Netz G = [K, B] darstellen. Zu den Knoten i ∈ Qs führen Bogen [qus, i] ∈ Bs und ebenso Bogen [j, ses] ∈ Bs aus Knoten j ∈ Ss. Ks = {qus, ses}, qus – Quelle des Sortennetzes Gs = [Ks, Bs] und ses Senke des Sortennetzes Gs; qus und ses sind durch einen Rückkehrbogen [ses, qus] verbunden, Ks ist die Knotenmenge des Untergraphen, Gs = U(Ks) = [Ks, Bs], der alle Bogen der Bogenmenge Bs = B U Bs enthält. 96 Kapitel5: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen Q1 Rückkehrbogen m1 der Sorte 1 QsAnz S1 Rückkehrbogen msAnz der Sorte sAnz SsAnz G = [K, B] Bild 4.14: Skizze für ein Mehrsortentransportnetz Beispiel 1 Eine Aufgabe zu Leerfahrtenminimierung – vgl. Bild 4.12: Ein Fuhrunternehmen verfügt über eine Reihe von Fahrzeugen, die zwei Fahrzeugdepots, D1 und D2, zugeordnet sind. Die Fahrtenplanung für den nächsten Tag möge fünf Touren, T1, T2, T3, T4, T5, vorsehen. Die Tour T1 muss mit einem Fahrzeug aus Depot D1 ausgeführt werden, und die Tour T5 mit einem Fahrzeug aus Depot D2. An die Tour T1 kann man die Tour T2 oder auch die Tour T3 anschließen; an die Tour T2 die Touren T3 oder T5; an T3 die Tour T5 und schließlich an T4 die Tour T5. Es ist wegen der Entfernung nicht sinnvoll, die Tour T4 aus Depot D1 zu starten. Gesucht ist ein Tourenplan mit möglichst wenigen Leerfahrten. TA1 DA1 TE1 DE1 TA2 TE2 TA3 TE3 TA4 TE4 DA2 DE2 TA5 TE5 Bild 4.15: Skizze einer Leerfahrtenminimierung Bild 4.15 skizziert das Modell: Die beiden Depots sind jeweils durch die Knoten DA1 und DE1 bzw. DA2 und DE2 sowie durch die Rückkehrbogen [DE1, DA1] und [DE2, DA2] vertreten, die fünf Kapitel 4: Das Minimalkosten-Stromproblem mit gekoppelten Flüssen 97 vorgesehenen Touren durch die Bogen [TAi, TEi], i = 1, 2, 3, 4, 5. Die Bogen [DAi, TAj] stehen für die Ausfahrt eines Fahrzeuges aus Depot Di um die Tour Tj zu starten, entsprechend stehen die Bogen [TEj, DEi] für die Rückkehr eines Fahrzeuges in Depot Di nach Beendigung der Tour Tj. Schließlich repräsentieren die Bogen [Tj, Tk] die unmittelbare Ausführung der Tour Tk nach Beendigung der Tour. 98 Kapitel 5: Netzplantechnik 5 Netzplantechnik 5.1 Einfache Netzplanmodelle Als historisch erstes Netzplanmodell für die Planung zeitlicher Abläufe entstand um 1957 das so genannte Aktivitätspfeilnetz. Es entstand aus einer Notsituation – großer Zeitverzug bei der Entwicklung der Polaris-Raketen. Das eingesetzte Operation-Research-Team definierte Teilaufgaben des Gesamtprojektes als „Aktivitäten“ und bildete jede Aktivität auf einen Bogen / Pfeil eines gerichteten Graphen ab. Dabei wurde die noch heute gültige Festlegung (Definition) getroffen, dass eine Aktivität ein Arbeitsprozess ist, der, sofern die Voraussetzungen für seine Realisierung erfüllt sind, ohne Unterbrechung in einer vorbestimmten Dauer abläuft. Setzt die Aktivität [i, j] – i und j sind Knoten- oder „Ereignis-Nummern im Netzplan – voraus, dass sie erst beginnen kann, wenn gewisse andere Aktivitäten ausgeführt sind, so müssen die Bogen dieser anderen „Vorläufer“-Aktivitäten den Knoten i als Endknoten haben – vgl. Bild 5.1. i Vorläufer-Aktivitäten Aktivität j Bild 5.1: Realisierung zeitlicher Abhängigkeiten in Aktivitäts-Pfeilnetz Der Graph der Aktivitäten – auch Netzplan genannt – wird ergänzt durch einen Eingangsknoten Projekt-„Start“, der Anfangsknoten aller der Aktivitäten ist, die bei Projektbeginn ohne Voraussetzung begonnen werden können, und durch einen Ausgangsknoten Projekt-„Ende“, der Endknoten aller der Aktivitäten ist, die von keiner anderen Aktivität vorausgesetzt werden. Beispiel Aktivität A1 A2 A3 A4 A5 A6 A7 A8 Voraussetzung A1 A1 A1 A2 und A3 A3 und A4 A7 Dauer 2 4 3 2 2 1 4 2 Tabelle 5.1 Beispiel Aus den Angaben in Tabelle 5.1 entsteht der Graph des Bildes 5.2. Er enthält mit den Bogen [2, 3] und [2, 4] zwei Bogen, die keine Aktivitäten darstellen, sondern notwendig sind, um die Ablauflogik des Projektes richtig darzustellen: A6 kann erst ausgeführt werden, wenn A2 und A3 fertig sind, während A7 voraussetzt, dass A3 und A4 fertig sind. A6 und A7 setzten also beide A3 voraus, aber außerdem hat jede der beiden Aktivitäten auch eine andere Voraussetzung. Kapitel5: Netzplantechnik 99 3 A6: d = 1 A2: d = 4 2 A7: d = 4 4 A8: d = 2 5 Ende Start A3: d = 3 A4: d = 2 A1: d = 2 A5: d = 2 1 Bild 5.2.1: Ein Aktivitätspfeilnetz – Beispiel Tabelle 5.1, vgl. Bild 5.2.2 Solche so genannten Schein- oder Dummyaktivitäten sind typisch für Aktivitätspfeilnetze und bilden eine gewisse Problematik bei der Erzeugung solcher Netze: Die Dauer der Aktivitäten kann auch Zufallsgröße sein; dann entsteht das PERT-Modell (Program Evaluation and Review Technique). Die Planung eines Prozesses beginnt in der Regel mit einem „Leistungsverzeichnis“. Dieses enthält Arbeitsumfangsangaben; z.B. bei einem Bauprojekt eine Anzahl von Kubikmeter auszuhebenden Erdreichs oder eine Anzahl von Kubikmeter zu errichtenden Mauerwerks und ähnliche Angaben. Aus diesen „Leistungen“ (nach dem physikalischen Begriffssystem handelt es sich um Arbeiten) werden Aktivitäten abgeleitet, z.B. eine Aktivität „Erdaushub“, und anschließend werden die Abhängigkeiten zwischen den definierten Aktivitäten analysiert. Setzt man auf vereinfachte Zusammenhänge, nämlich dass eine Abhängigkeit bedeutet, Aktivität Aj kann frühestens beginnen, wenn Aktivität Ai fertig ist, so entsteht bei der Abhängigkeitsanalyse eine Tabelle der Art, wie sie Tabelle 5.1 zeigt. Eine solche Tabelle kann problemlos auf ein Aktivitätsknotennetz abgebildet werden: Man ordne jeder Aktivität einen Knoten (Rechtecksymbol) eines gerichteten Graphen zu und jeder Abhängigkeit einen Bogen: Setzt Aj Ai voraus, so verbinde man die Knoten Ai und Ai durch einen Bogen [Ai, Ai]. Man füge dem Netz noch die Ereignisknoten (Kreissymbol) Projekt-„Start“ und Projekt-„Ende“ hinzu, wobei vom Start-Knoten zu jedem Aktivitätsknoten, der keinen Eingang hat ein Bogen geführt wird und in ähnlicher Weise von jedem Aktivitätsknoten, der keinen Ausgang hat, ein Bogen zum Ende-Knoten, und der Netzplan ist fertig. Bild 5.2.2 zeigt das Aktivitätsknotennnetz zum Beispiel Tabelle 5.1. A2 A6 A3 A7 Start A1 A4 A8 A5 Bild 5.2.2: Ein Aktivitätsknotennetz – Beispiel Tabelle 5.1, vgl. Bild 5.1.1 Ende 100 Kapitel 5: Netzplantechnik Die im historischen Prozess vorgebrachten Einwände gegen das Aktivitätsknotennetz betrafen vor allem die Anschaulichkeit: Man verbindet mit einem ablaufenden Prozess, der eine gewisse Dauer besitzt, lieber den Pfeil als den theoretisch punktförmigen Knoten. Der Knoten steht für Zeitpunkte, die in der Ablaufplanung auch Ereignisse genannt werden. Der einfache Zusammenhang zwischen dem analytischen Ergebnis Netzplan-Tabelle und deren graphischen Bild hat aber dazu geführt, dass sich das Aktivitätsknotennetz als Netzplan durchgesetzt hat. Zur Entkräftung des Darstellungseinwandes kann man sagen, wenn man den Knoten als längliches Rechteck darstellt, hat man hinreichenden Bezug zur zeitlichen Ausdehnung, und als Hauptgegenargument gegen das Aktivitätspfeilnetz wirkt die Problematik der Scheinaktivitäten: Wie schon gesagt, sind sie notwendig, um die Ablauflogik richtig darzustellen, aber sie sind in der Regel nicht eindeutig: Den Übergang von dem zuerst vorhandenen Aktivitätsknotennetz – bzw. seinem Äquivalent, der Abhängigkeitstabelle – könnte man so vollziehen, dass man im Aktivitätsknotennetz alle Bogen zu Scheinaktivitäten macht und alle Aktivitätsrechtecke durch Bogen ersetzt – man vergleiche die im Bild 5.3 skizzierte Transformation. A A Bild 5.3: Transformation Aktivitätsknoten in Aktivitätspfeil Anschließend beginnt man überflüssige Scheinaktivitäten zu eliminieren mit dem Ziel, ihre Anzahl zu minimieren. Man kann zeigen, dass diese Optimierung NP-schwierig ist. Es gibt also keinen optimalen Algorithmus, und der Prozess ist nicht trivial; folglich vermeidet man ihn möglichst und bleibt beim Aktivitätsknotennetz, zumal der Rechenprozess, den man auf einem Netzplan ausführen will, die Terminberechnung, im Aktivitätsknotennetz ähnlich einfach auszuführen ist wie im Aktivitätspfeilnetz. In der UML – Unified Modeling Language – einer graphischen Notation im Paradigma der objektorientierten Softwareentwicklung, gibt es auch ein Aktivitätsdiagramm, nämlich für Aktivitäten im Softwareentwicklungsprozess. Dieses Diagramm ist einerseits praktisch das Aktivitätsknotennetz – allerdings verwendet man als Aktivitätssymbol ein Rechteck mit abgerundeten Ecken – aber andererseits werden eindeutige Bedingungen gefordert und durch so genannte „Aufteilungen“ bzw. „Zusammenführungen“ von Abhängigkeitspfeilen erzeugt. Bild 5.2.3 zeigt das Aktivitätsdiagramm für das Beispiel Tabelle 5.1: Im Unterschied zum Aktivitätsknotennetz (Bild 5.2.2) sind jetzt die Balken 1, 2 (Aufteilungen) und 3, 4 (Zusammenführungen) eingefügt. Mit ihrer Hilfe kann man unmittelbar zum Aktivitätspfeilnetz (Bild 5.2.1) transformieren: Die Balken werden zusammen mit den schon vorhandenen Start- und Ende-Ereignis zu Ereignisknoten. Zwischen zwei Ereignisknoten liegt jeweils eindeutig eine Aktivität, und die beiden Bogen [2, 4] sowie [2, 3] im Bild 5.2.3 sind notwendige Scheinaktivitäten – vgl. Bild 5.2.1. 4 A6 A2 2 1 Start A3 3 A7 A1 A8 A4 A5 Bild 5.2.3: Ein Aktivitätsdiagramm nach UML – Beispiel Tabelle 5.1, vgl. Bild 5.2.2 Ende Kapitel5: Netzplantechnik 101 Man sieht, dass das Aktivitätsdiagramm nach UML das nahezu ideale Verbindungsglied zwischen den beiden Netzplanformen ist. Mit Hilfe des Netzplans werden für ein zu planendes Projekt Termine für wichtige Ereignisse berechnet, indem man vom Start-Ereignis aus die längsten Wege berechnet – vgl. Abschnitt 2.2: Im Aktivitätspfeilnetz setzt man für jede Aktivität die Dauer d(A) als Bogenlänge. Scheinaktivitäten haben die Dauer Null. Die Ereignistermine haben dann unmittelbaren Bezug zum frühest-möglichen Anfangstermin at(A) bzw. frühest-möglichen Endtermin et(A) der mit ihnen inzidenten Aktivitäten. Im Aktivitätsknotennetz haben die Bogen die Länge Null und den Knoten werden zwei Termine zugeordnet, der Anfangstermine at(A) der Aktivität und ihr Endtermin et(A) wobei wir et(A) = at(A) + d(A) unterstellen – Ausführung der Aktivität ohne Unterbrechung. Bild 5.2.4 zeigt die Ergebnisse der Rechnung zum Beispiel aus Tabelle 5.1. Die Bogen des Gerüstes der längsten Wege sind fett gezeichnet. Der längste Weg zu einer Aktivität wird auch als der für sie kritische Weg bezeichnet und der längste Weg durch das Netz – vom Start-Ereignis zum Ende-Ereignis – als der kritische Weg des Projektes. Die Bezeichnung „kritisch“ ist als Mahnung an die Projektausführung gedacht, mit dem Sinn, dass jede Verzögerung einer auf dem kritischen Weg liegenden Aktivität den frühest-möglichen Endtermin des Projektes gefährdet. Man kann alle Bogen im Netz umkehren und eine Längste-Wege-Berechnung vom Ende-Ereignis zum Start-Ereignis ausführen. Anschließend subtrahiert man die so erhaltenen Ereignistermine von einem gewünschten Projektendtermin, zum Beispiel von dem vorher berechneten frühest-möglichen Endtermin. Man erhält spätest-mögliche Termine im Bezug auf den gewünschten Projektendtermin Ai at(i) d(i) et(i) A2 0 4 4 A6 5 1 A3 2 3 6 5 A7 5 4 9 A1 0 2 2 A4 2 2 4 A8 9 2 11 Start 0 A5 2 2 4 Ende 11 Bild 5.2.4: Terminberechnung für Beispiel Tabelle 5.1, vgl. Bild 5.2.1 5.2 Erweitertes Netzplanmodell 5.2.1. Grundlagen An den klassischen Modellen der Netzplantechnik ist folgende ernsthafte Kritik vorzunehmen: Am Beginn der Planung ist die Dauer d(i) einer Aktivität meistens keine feste Größe, wie allgemein unterstellt, sondern vielmehr Gegenstand der Planung, also Variable; denn das Leistungsverzeichnis als Ausgangspunkt der Planung enthält, wie schon erwähnt, nur Arbeitsumfangsangaben, z.B. eine Anzahl von Kubikmeter auszuhebenden Erdreichs oder eine Anzahl von Kubikmetern zu errichtenden Mauerwerks und ähnliche Angaben. Aus diesen „Leistungen“ werden die Aktivitäten abgeleitet und wie lange deren Ausführung dauert, hängt insbesondere davon ab, mit welcher Intensität sie ausgeführt werden, d.h., wie viele Maschinen und Arbeitskräfte für ihre Ausführung eingesetzt werden. Der Arbeitskräfte- und Maschineneinsatz hängt jedoch häufig von der Betrachtung aller Aktivitäten ab, die das gleiche Gewerke bzw. die gleiche Maschinenart nutzen: Eine Aktivität 102 Kapitel 5: Netzplantechnik „Erdarbeit“ wird von Baggern ausgeführt. Wir kennen ihren Arbeitsumfang, also die Anzahl Baggerstunden, die zu leisten sind. Stehen ohnehin zwei Bagger zur Verfügung, wird man beide einsetzen, während man zögert, wenn es Mühe macht einen zweiten Bagger zusätzlich zu beschaffen. Im Weiteren wird der Begriff Ressource als Sammelbezeichnung für Gewerke und Maschinenarten benutzt, und wir gehen von folgender Prämisse aus: Die Arbeitskräfte- und Maschineneinsatzplanung und damit auch die Festlegung der Dauer der betroffenen Aktivitäten ist Gegenstand der Ablaufplanung, wobei folgende Regeln gelten: • • • Die Dauer d(i) einer Aktivität Ai kann sicher nicht beliebig variieren. Im Allgemeinen gibt es eine effiziente Einsatzgröße für die ausführende(n) Ressource(n). Die daraus resultierende Dauer wollen wir als Normaldauer, normDi, bezeichnen. Durch erhöhten Einsatz von Ressourcen kann diese Normaldauer verkürzt werden, wobei es für diese Verkürzung ein technologisch sinnvolles Minimum gibt, das wir als Minimaldauer, minDi, bezeichnen wollen. Wir unterstellen, dass im Weiteren gilt: minDi ≤ d(i) ≤ normDi Wie schon angedeutet hängt die Wahl der Aktivitätsdauer mit dem Einsatz der Arbeitskräfte und anderer Ressourcen bei der Ausführung der Aktivität zusammen. Das sehr breite Gebiet der Ressourcen-Einsatzoptimierung verschieben wir auf Kapitel 6 und betrachten zunächst den Fall, dass die Wahl der Aktivitätsdauer durch Kosten stimuliert wird. Das ist dann ein sinnvoller Ansatz, wenn man unterstellt, dass der Ressourceneinsatz nur aus der Sicht der betrachteten Aktivität erfolgt; also sicher dann, wenn es um die Planung einer höheren Leitungsebene geht, in der eine Aktivität etwa die Errichtung eines ganzen Bauwerkes beinhaltet und der Ressourceneinsatz nicht detailliert zu planen ist. • Wir unterstellen für jede Aktivität i einen Preis cD(i), der zu den Kosten cD(i)·(normD(i) - d(i)) führt, mit dem also die Dauerkürzung bewertet wird. Bevor wir uns mit algorithmischen Details dieser Aufgabenstellung beschäftigen können, müssen wir jedoch noch die Vorgaben für den Abstand zwischen zwei Aktivitäten präzisieren: Abstand zwischen zwei Aktivitäten meint eine Zeitvorgabe zwischen den Anfangs- oder / und Endereignissen der beiden Aktivitäten. Diese Vorgabe hängt in vielen Fällen von der Dauer der beiden Aktivitäten ab, die, wie betont, variabel ist, so dass v(i, j)·d(i) + v(i, j)·d(j) + w(i, j) ein sinnvoller Ansatz für das Maß dieser Vorgabe ist. Dabei gelte: • v(i, j), v(i, j) und w(i, j) bezeichnen vorgegebene reelle Zahlen, wobei für v(i, j) und v(i, j) die • • Bereichsvorgabe 0 ≤ v(i, j), v(i, j) ≤ 1 sinnvoll ist, denn diese Zahlen beschreiben Fertigstellungsgrade der Aktivitäten Ai bzw. Aj. at(i) bezeichnet den Anfangstermin der Aktivität Ai et(i) = at(i) + d(i) sei der End- bzw. Fertigstellungstermin der Aktivität Ai Im Netzplan • wird jede Aktivität durch einen Knoten repräsentiert, der als Rechteck dargestellt wird (Aktivitätsknotennetz). • Jede Abstandsvorgabe wird entweder durch einen Bogen [Ai, Aj] vom Knoten Ai zum Knoten Aj oder durch einen Bogen [Aj, Ai] von Aj nach Ai dargestellt, dem ein Tripel [Typ, V, W], mit 0 ≤ V ≤ 100, V ganzzahlig, zugeordnet ist. V steht für 100·v(i, j) oder 100·v(i, j); W für w(i, j). Dabei setzen wir voraus, dass in einer konkreten Abstandsvorgabe, wenn überhaupt, entweder nur 0 < v(i, j) < 1 oder nur 0 < v(i, j) < 1 gilt. Den in der Praxis äußerst seltenen Fall, in dem beides auftritt, kann man durch eine Hilfskonstruktion auf zwei einfachere Abstandsforderungen zurückführen. Damit können wir die Abstandsvorgabe, die mit dem Netzplanbogen [Ai, Aj] verbunden ist, so interpretieren, dass die Aktivität Aj die Aktivität Ai als Vorläufer-Aktivität besitzt, zu der sie einen zeitlichen Abstand einhalten muss, wobei folgende Abstandstypen möglich sind: • • Typ = 0: at(j) - at(i) ≥ V/100·d(i) + W Typ = 1: at(j) - at(i) ≤ V/100·d(i) + W (oder at(i) - at(j) ≥ – V/100·d(i) – W ) Kapitel5: Netzplantechnik 103 • • • • Typ = 2: Typ = 3 Typ = 4: Typ = 5 at(j) - at(i) = V/100·d(i) + W (Typ=0 und Typ=1 gleichzeitig) et(j) - at(i) ≥ V/100·d(i) + W et(j) - at(i) ≤ V/100·d(i) + W (oder at(i) - et(j) ≥ – V/100·d(i) – W ) et(j) - at(i) = V/100·d(i) + W (Typ=3 und Typ=4 gleichzeitig). Das folgende Bild zeigt die Eingabeschablone für eine Aktivität in einer Software, die dieses Netzplan-Modell realisiert. Insbesondere werden Abhängigkeiten durch Nennung von VorläuferAktivitäten eingegeben und zwar so, dass die Schlüsselnummer (Synonym für i) der VorläuferAktivität über eine „Listbox“ eingetragen wird. Dadurch können nur solche Aktivitäten als Vorläufer genannt werden, die schon vorher eingegeben wurden. Die Eingabereihenfolge sollte möglichst eine toplogische Ordnung (vgl. Abschnitt 2.2 – Längste Wege) sein. Bild 5.4: Eingabeschablone aus einer Software für eine Aktivität In einem gezeichneten Netzplan können die Abstandsvorgaben in anschaulicher Weise so dargestellt werden, dass eine Beschriftung des Bogens mit der Zahl W die Abstandsforderung ausreichend beschreibt, wenn dazu bei Typ = 0 oder Typ = 3 – der Unterschied wird durch den Bogenbeginn sichtbar – ein ≥-Zeichen vor die Zahl W gesetzt wird, während bei Typ = 1 oder Typ = 4 ein ≤ vor der Zahl W steht. W = 0 gilt als Standard: Beispiele a) Als Standardtyp des Abstandes bezeichnet man den praktisch häufigsten Fall: A1 muss beendet sein, damit A2 beginnen kann: Typ = 0, V = 100, W = 0, also at(1) + d(1) = et(1) ≤ at(2). Bild 5.5.1: Standardtyp des Abstands A1 A2 b) Abstandsforderung, spätestens wenn A1 fertig ist, muss A2 beginnen: [A1, A2] mit Typ = 1, V = 100, W = 0, also at(2) ≤ at(1) + d(1) = et(1). Bild 5.5.2: Abstands-Typ 1, V = 100, W = 0 A1 ≤0 A2 c) Bild 5.5.3 zeigt einen Netzplan, der aus den beiden Aktivitäten A1 und A2 besteht, beide haben normD = 20 und minD = 10. Der eine Bogen von A1 zu A2 stellt den Standardtyp des Abstandes 104 Kapitel 5: Netzplantechnik dar. Der zweite Bogen ist deutlich vom Anfang von A1 zum Ende von A2 geführt und mit ≤ 30 beschriftet. Er symbolisiert die Abstandsforderung et(2) - at(1) ≤ 30, d.h., beide Aktivitäten sollen nach spätestens 30 Zeiteinheiten fertig sein. A1 10 - 20 A2 10 - 20 Bild 5.5.3: Dauerbeschränkung zweier Aktivitäten ≤ 30 Da der Aktivitätsknoten einem Prozess entspricht, wollen wir den linken Rand seines Rechtecks mit AKn (Anfangsknoten) und den rechten Rand seines Rechtecks mit EKn (Endknoten) bezeichnen. Kehrt man im Bild 5.5.3 den Bogen [AKn(1), EKn(2)] um, so entsteht ein Kreis aus Abstands- und Aktivitätsbögen, dessen Spannungssumme Lg = d(1) + d(2) - 30 nicht positiv sein darf (Kreisbedingung), d(1) + d(2) ≤ 30. In der Tat würde z.B. d(1) = d(2) = 20, Lg = 10, zu einer unmöglichen Situation führen, denn ein Prozess, der 40 Tage dauert, kann nicht nach 30 Tagen beendet werden. Damit veranschaulicht das Beispiel, dass eine Terminrechnung in dem hier betrachteten Netzplanmodell die Festlegung der Aktivitätsdauer mit einbeziehen muss. Abstandskreise, längs denen die Summe der unteren Schranken positiv ist, werden in diesem Modell als Terminkreise bezeichnet. Sie stellen Widersprüche dar. d) Das Bild 5.5.4 zeigt einen Netzplan aus den drei Aktivitäten A1, A2, A3. Die beiden oberen Bögen fordern, dass et(3) ≥ et(2) ≥ et(1) gilt. Die beiden unteren Bögen repräsentieren die Abstandsforderungen at(2) ≥ at(1) + 1 und at(3) ≥ at(2) + 1. Das folgende System aus Anfangs- und Endterminen erfüllt alle Forderungen: at(1) = 0, at(2) = 1 = at(1) + 1, at(3) = 2 = at(2) + 1, A1 et(1) = normD(1) = 10; et(2) = et(1) = 10; et(3) = et(2) = 10. A2 10 3 - 10 ≥1 A3 5 - 10 ≥1 Bild 5.5.4: Ein überraschendes Resultat von Abstandsvorgaben Die im Bild fett gezeichneten Linien beschreiben die kritischen Vorgaben der angegebenen Lösung, nämlich die, bei denen die untere Schranke als gültig festgelegt wurde (im Sinne Basislösung). Dagegen folgen d(2) = et(2) - at(2) = 8 und d(3) = et(3) - at(3) = 9 aus diesen Vorgaben. Das Überraschende an diesem Beispiel ist wohl, dass die kürzeste Gesamtdauer 10 des Netzes sich nicht ergibt, wenn jede Aktivität so schnell wie möglich erledigt wird, sondern bei längerer Dauer von A2 und A3. Die Minimaldauer d(2) = 3 und die Minimaldauer d(3) = 5 würden zur Projektdauer 13 führen mit at(2) = 7. e) Die Bögen in dem Netzplan Bild 5.5.5 repräsentieren folgende Restriktionen: at(2) - at(1) ≥ 1/3d(1) der untere Bogen und at(1) - et(2) ≥ 2/3d(1) oder et(2) ≤ at(1) + 2/3D(1) der rechte Bogen. 67% Bild 5.5.5: Ausführung von A2 im mittleren Drittel von A1 A1 A2 33% Beide Restriktionen zusammen besagen, dass A2 innerhalb des zweiten Drittels der Ausführungszeit von A1 realisiert werden muss. Die Spannungssumme Lg des Zyklus aus den beiden Abstands- und den beiden Aktivitätsbogen (Aktivitätsrechteck als Bogen gesehen) berechnet sich zu Lg = d(1)/3 + d(2) - 2d(1)/3. Aus Lg ≤ 0 (Kreisbedingung) folgt d(2) ≤ d(1)/3, die triviale Bedingung für die Ausführbarkeit der Vorgabe. Kapitel5: Netzplantechnik 105 f) Das Bild 5.5.6 zeigt einen Netzplan des erweiterten Netzplanmodells, in dem folgende Abstandsrestriktionen formuliert sind: at(2) ≥ at(1) + 0,4d(1), at(3) ≥ at(2) + 0,8d(2), at(3) ≥ et(2), at(3) ≤ et(1) + 1, at(4) ≤ at(1) + 0,9d(1) + 10. A1 40% 6 ≤ 10 ≤1 90% 2 -1 A2 12 4 -1 A3 10 6 -1 A4 5 3 -1 80% Bild 5.5.6: Allgemeine Abstandsvorgaben Im Bild 5.5.6 sind zu jeder Aktivität normD und minD angegeben. Die Kürzungspreise zu den normD(i)-Werten betragen alle 1 (cD(i) = 1 für i = 1, 2, 3, 4). Gesucht ist der Ablaufplan (d.h. at(i) und d(i) für i = 1, 2, 3, 4), der die Summe aller Abweichungen von der Normaldauer minimiert. Das willkürlich gewählte Zahlenbeispiel soll demonstrieren, dass praktische Anwendungen dieses allgemeinen Modells durchaus zu numerisch wenig eleganten Rechnungen führen können. 5.2.2 Umsetzung des Netzplans in ein Modell des Minimalkosten-Potentialproblems Mit der Zielstellung, als mathematisches Modell ein Minimalkosten-Potentialproblems zu entwickeln, wandeln wir innerhalb einer Datenstruktur Netzplan, die ein Aktivitätsknotennetz beschreibt, jeden Aktivitätsknoten Ai in einen Aktivitätsbogen [AKn(i), EKn(i)] um und ordnen diesem Bogen k (Die Bogennummer k ist seine Platznummer in einer von 1 bis m indizierten Bogenliste.) folgendes zu: • Funktionen y(k), a(k), b(k) für seine Spannung und deren untere bzw. obere Schranke • sowie eine Bewertungsgröße c(k). Diese sind für den Aktivitätsbogen zur Aktivität Ai so zu initialisieren, dass a(k) = minD(i), b(k) = normD(i), y(k) = d(i) und c(k) = cD(i) gilt. 106 Kapitel 5: Netzplantechnik et(i) ≤ pet(i) | 0, pet(i) < et(i) < set(i) | cT(i) AKn(i) minD(i) minD(i)≤≤d(i) d(i)≤≤normD(j), normD, cD(i) cD(i) EKn(i) at(i) et(i) etN – et(i) ≥ 0 = (V/100)·d(i) at(i) ≥ fat(i) 0 EKnN Hij AKnN (V/100)·d(i) etN at(j) ≥ fat(j) ≥W AKn(j) minD(j) ≤ d(j) ≤ normD(j) | cD(j) at(j) etN – et(j) ≥ 0 EKn(j) et(j) et(j) ≤ pet(j) | 0, pet(j) < et(j) < set(j) | cT(j) Netzbogen: etN ≤ petN | 0, petN < etN < setN | cTN Bild 5.6: Der Netzplan als Modell eines Minimalkosten-Potentialproblems Die Menge der Aktivitätsbogen wird wie folgt zu einem zusammenhängenden Netz ergänzt – vgl. Bild 5.6: • Ein Quellknoten AKnN, repräsentiert den Start des Gesamtablaufs. • Ein Zielknoten EKnN, repräsentiert das Ende des Gesamtablaufs. • Ein Bogen [AKnN, AKn(i)] verbindet AKnN mit den Anfangsknoten der Aktivität Ai bei den Aktivitäten, zu denen kein Abstandsbogen führt oder für die eine Vorgabe – frühestmöglicher Start- / Anfangstermin, fat(i) – bezüglich des Beginns der Aktivität besteht. Es gilt für die untere Bogenschranke a(k), a(k) = 0 bzw. a(k) = fat(i); b(k) = ∞, für einen solchen Bogen k. • Bogen [EKn(i), EKnN] verbinden die Endknoten aller Aktivitäten mit EKnN. Es gilt, a(k) = 0, b(k) = ∞ für einen solchen Bogen k. • Ein Bogen [AKnN, EKnN] genannt Netzbogen repräsentiert Daten für den Gesamtprozess. Das Modell kann sinnvoll ergänzt werden durch • geplante Endtermine pet(i) • Preise cT(i) für deren Überschreitung und • Vorgaben set(i), spätester Endtermin, für den Endtermin einer Aktivitäten Ai. Diese Parameter können wir über Terminbogen [AKnN, EKn(i)] in unser Modell einfließen lassen. Für einen Terminbogen k gilt: a(k) = pe(i), b(k) = set(i), c(k) = cT(i). Der Netzbogen [AKnN, EKnN], bekommt die Nummer 1. Ihm kann, ein geplanter Endtermin, petN, und ein spätester Endtermin, setN, für das Gesamtnetz zugeordnet werden: a(1) = petN, b(1) = setN, c(1) = cTN. Die Transformation eines Abstandsbogens [Ai, Aj] des Netzplans in einen Bogen des mathematischen Modells ist einfach, wenn V = 0 oder V = 100 gilt: Der transformierte Bogen k führt gemäß folgender Übersicht entweder von AKn(i) oder von EKn(i) des Aktivitätsbogens für Ai zu AKn(j) oder EKn(j) des Aktivitätsbogens für Aj oder in umgekehrter Richtung. Es wird ihm die untere Spannungsschranke a(k) = W oder a(k) = -W zugewiesen. Typ = 0, V = 0 → [AKn(i), AKn(j)], a(k) = W Typ = 0, V = 100 → [EKn(i), AKn(j)], a(k) = W Kapitel5: Netzplantechnik 107 Typ = 1, V = 0 Typ = 1, V = 100 Typ = 3, V = 0 Typ = 3, V = 100 Typ = 4, V = 0 Typ = 4, V = 100 → → → → → → [AKn(j), AKn(i)], a(k) = -W [AKn(j), EKn(i)], a(k) = -W [AKn(i), EKn(j)], a(k) = W [EKn(i), EKn(j)], a(k) = W [EKn(j), AKn(i)]. a(k) = -W [EKn(i), EKn(i)] a(k) = -W Alle Abstandsbögen k erhalten die obere Spannungsschranke b(k) = ∞. Komplizierter wird das Modell, wenn 0 < V < 1 gilt: In jedem dieser Fälle denken wir uns den Abstandsbogen, z.B. [AKn(i), AKn(j)], des Netzplans durch zwei aufeinander folgende Bögen im mathematischen Modell ersetzt, z.B. [AKn(i), Hij] und [Hij, AKn(j)] – vgl. Bild 5.6: • [AKn(i), Hij] koppeln wir mit dem Aktivitätsbogen, von dessen Dauer der Abstand abhängt. Wir bezeichnen die gekoppelten Bogen als Partner und definieren die Bogenfunktion Partner(k) zur Bogennummer k. Sind die Bögen k und l, gekoppelt, l = Partner(k), k = Partner(l), so bedeutet dass, wie im Kapitel 4, f(k)·y(k) = f(l)·y(l); beispielsweise im Fall Typ = 0: k = [AKn(i), Hij]; y(k) = f(k)·y([AKn(i), EKn(i)]) = f(k)·d(i) mit f(k) = (V/100). • Der zweite Bogen der Bogenfolge [AKn(i), Hij] und [Hij, AKn(j)] ist ein nicht gekoppelter Bogen, der als untere Abstandsschranke den konstanten Teil W der Abstandsforderung erhält, also z.B. a([Hij, AKn(j)]) = W . Die Bogenzerlegung ist zur Klärung der theoretischen Zusammenhänge bei der Bogenkopplung notwendig. Wir wollen sie jedoch nur nutzen, um die Eigenschaften der originalen Abstandsbogen [Ai, Aj] des Netzplans zu studieren. Im Weiteren wollen wir auch im mathematischen Modell mit ungeteilten Abstandsbogen wie folgt operieren: Typ Bedeutung Realisierung durch Bogen im mathematischen Modell 0: at >= at(j) - at(i) ≥ f(k)·d(i) + W [AKn(i), AKn(j)] 1: at <= mit f(k) = (V/100), a(k) = W, partner = i at(j) - at(i) ≤ f(k)·d(i) + W [AKn(j), AKn(i)] mit f(k) = -(V/100), a(k) = -W, partner = i 3: et >= et(j) - at(i) ≥ f(k)·d(i) + W [AKn(i), EKn(j)] mit f(k) = (V/100), a(k) = W, partner = i 4: et <= et(j) - at(i) ≤ f(k)·d(i) + W [EKn(j), AKn(i)] mit f(k) = -(V/100), a(k) = -W, partner = i Tabelle 5.2 Man beachte zunächst, dass im mathematischen Modell durch eventuelle Umkehrung der Bogenrichtung gesichert wird, dass alle Abstandsbogen untere Spannungsschranken repräsentieren! – vgl. in der Tabelle 5.2 die Typen 1 und 3. Ferner ordnen im Sinne der Einheitlichkeit, wie im Kapitel 4, jedem Abstandsbogen k Werte Partner(k) und f(k) zu (u. z. dem ungeteilten Abstandsbogen), wobei im Regelfall Partner(k) = f(k) = 0 gilt. Der dem Bogen im Sinne der Terminologie aus Kapitel 4 zugeordnete Kopplungsfaktor f(k) hat, wenn 0 < V < 1 gilt, den Wert f(k) = (V/100) bzw. f(k) = -(V/100). Der Partner(k) ist, sofern nicht Null, ein Aktivitätsbogen l = [AKn(i), EKn(i)]. Zur besseren Übersicht nennen wir als Partner nicht den Aktivitätsbogen, sondern einfach die Aktivitätsnummer und verdeutlichen das durch partner(k) = i. Die Menge aller Abstandsbögen k, für die partner(k) = i ≠ 0 gilt, und den Aktivitätsbogen [AKn(i), EKn(i)] bezeichnen wir als Menge miteinander gekoppelter Bogen. Im Unterschied zu Kapitel 4 wollen wir hier mit diesen Mengen arbeiten und nicht (durch Zerlegung des betreffenden Aktivitätsbogens) die Kopplung auf Paare gekoppelter Bogen reduzieren. 108 Kapitel 5: Netzplantechnik 5.3 Ein Lösungsalgorithmus für das Netzplan-Minimalkosten-Potentialproblem (NMKP) 5.3.1 Basislösung Eine Eckpunkt- oder Basislösung des formulierten Netzplan-Minimalkosten-Potentialproblems (NMKP) kann wie folgt charakterisiert werden: Ein Potential t = (t(1), t(2), …, t(n)) bzw. die aus ihm durch y(k) = t(EKn(k)) - t(AKn(k)) erzeugte Spannung y = (y(1), y(2), …, y(m)) bildet eine Eckpunktlösung des NMKP, wenn dazu ein Gerüst der Art existiert, dass y(k) = a(k) oder y(k) = b(k) auf den Gerüstbögen und a(k) ≤ y(k) ≤ b(k) auf den Cogerüstbögen gilt. Die Gerüstbogen werden auch als kritische Bogen (der aktuellen Lösung) bezeichnet: In einem zu realisierenden Zeitplan darf auf kritischen Bogen (wegen y(k) = a(k)) keine Verzögerung eintreten. Betrachten wir einen gekoppelten Abstandsbogen [AKn(i), AKn(j)] in der Zerlegung [AKn(i), Hij] und [Hij, AKn(j)] und seinen Partner-Aktivitätsbogen [AKn(i), EKn(i)]: Wegen y([AKn(i), Hij]) = f(k)·y([Akn(i), EKn(i)] = f(k)·d(i) muss entweder er selbst oder sein Partner [AKn(i), EKn(i)] im Gerüst sein. Bei d(i) ϵ {minD(i), normD(i)} müssen in der Regel beide im Gerüst sein. Falls sich der Abstand aus d(i) bestimmt (at(j) - at(i):= f(k)·d(i) + W), sind [AKn(i), Hij] und [Hij, AKn(i)] im Gerüst. Wir wollen das Gesetz, von einem gekoppelten Bogenpaar [AKn(i), Hij] und [AKn(i), EKn(i)] muss mindestens ein Bogen wegen der Kopplungsgleichung im Gerüst sein, zu der folgenden Forderung verschärfen: Forderung Ein Aktivitätsbogen ist genau dann im Gerüst, wenn d(i) ϵ {minD(i), normD(i)} gilt. Das bedeutet, dass der Fall, der Aktivitätsbogen ist im Gerüst, weil sich die Aktivitätsdauer aus einem Abstand ergibt, durch einen Wechsel, Aktivitätsbogen aus dem Gerüst, Abstandsbogen in das Gerüst, aufgelöst werden muss. Das ist nicht immer problemlos möglich, denn zu jedem Cogerüstbogen gehört bekanntlich ein Basiszyklus aus kritischen Bogen (vgl. Kapitel 1), und die Skizze Bild 5.7 zeigt, dass die beiden Bogen, die ihre Rolle tauschen sollen, nicht im selben Basiszyklus liegen müssen. In einem solchen Fall muss dann vor dem Rollentausch der Abstandsbogen [AKn(i), AKn(j)] in den Abstandsbogen [EKn(i), AKn(j)] transformiert werden. Dazu muss gleichzeitig V:= 100 - V gesetzt werden – vgl. Bild 5.7. Kapitel5: Netzplantechnik 109 Aktivitätsbogen Aktivitätsbogen 100 : (V – 100) 100 : V Abstandsbogen Abstandsbogen Bild 5.7: Transformation eines Abstandsbogens Wir kennen bereits den Dualitätssatz in seiner allgemeinen Form: Eine Lösung ist genau dann optimal, wenn jeder Bogen im Bezug auf seine Charakteristik im Gleichgewicht ist. Mit Blick auf diesen Satz können wir zu einer gegebenen Basislösung t bzw. y einen „zugehörigen Kosten-Strom“ x = (x(1), x(2), …, x(m)) so erzeugen, dass x(k) = c(k) auf allen Cogerüstbogen gilt. Dann sind für dieses y und dieses x alle Cogerüstbogen im Gleichgewicht. Gilt nun für die Gerüstbögen, • falls y(k) = a(k), so ist x(k) ≤ c(k) und, • falls y(k) = b(k), so ist x(k) ≥ c(k), d.h., sind auch sie im Gleichgewicht, so liegt eine optimale Basislösung y vor. Wir betrachten die Charakteristiken der einzelnen Bogenarten, wobei wir (wie im Abschnitt 3.3) die vertikale Achse für die Spannungskomponente y(k) verwenden und die horizontale Achse für den Fluss x(k), obwohl für die Spannungsaufgabe y(k) die unabhängig variierende Größe und x(k) die abhängig variierende Größe ist. Wir können aber die Charakteristik einfach als Menge der Gleichgewichtspunkte des Bogens auffassen, {(x(k), y(k))}. y(k) = at(i) a(k) = fat(i) x(k) Bild 5.8.1: Charakteristik des Bogens k = [AKnN, AKn(i)], c(k) = 0 110 Kapitel 5: Netzplantechnik y(k) = etN - et(i) x(k) Bild 5.8.2: Charakteristik des Bogens k = [EKn(i), EKnN] , c(k) = 0 Die Treppenform der Charakteristik mit mehreren Stufen, wie sie Bild 5.8.3 zeigt, kennen wir bereits aus Abschnitt 3.2.3. Sie bedeutet nur, wie wir wissen, dass die Größen a(k), b(k), c(k) in Abhängigkeit von y(k) ihre Werte ändern, was für die algorithmische Behandlung keine größere Bedeutung hat. y(k) = et(i) b(k) = set(i) a(k) = pet(i) x(k) c(k) = cT(i) Bild 5.8.3: Charakteristik eines Terminbogens k = [AKnN, EKn(i)] Die Bogenkopplung hat die folgende Auswirkung auf die Menge miteinander gekoppelter Bögen: Ihre dualen Kostenflüsse x(k) werden gemeinsam zu einer der Aktivität Ai zuzuordnenden Größe x*(i) zusammengefasst: x*(i) = x([AKn(i), EKn(i)]) + ∑{f(k)·x(k] | für Bogen k mit partner(k) = i} x([AKn(i), EKn(i)]) ist der Durchfluss durch den Aktivitätsbogen. Für (x*(i), y([AKn(i), EKn(i)])) gilt die Aktivitätscharakteristik, die Bild 5.8.4 zeigt. Kapitel5: Netzplantechnik 111 y(k) b(k)=normD(i) a(k)=minD(i) x*(i) c(k) = -cD(i) Bild 5.8.4: Charakteristik des Aktivitätsbogens k = [AKn(i), EKn(i)] bzw. der Aktivität Ai Für jeden Abstandsbogen existiert eine Charakteristik der folgenden Art – Bild 5.8.5 – bei der die Dauer seiner Partneraktivität in die Schranke eingeht: y(k) = at(j) – at(i) a(k) = f(k)·d(i) + W x(k) Bild 5.8.5: Charakteristik des Abstandsbogens k = [AKn(i), AKn(j)] – Typ = 0, c(k) = 0 5.3.2 Ermittlung einer Startlösung Die Lösung der Aufgabe, Gewinnung einer optimalen Basislösung des Systems aus Zeitvorgaben und Kostenfunktionen, die ein konkretes verallgemeinertes Netzplanmodell darstellt, erfolgt prinzipiell mit den Mitteln, die wir von den anderen Aufgaben der Netzoptimierung kennen: Es wird eine erste nicht notwendig zulässige Lösung erzeugt, die die Struktur einer Basislösung besitzt – die Startlösung. Für diese wird ein Bogen gesucht, der nicht im Gleichgewicht („out-of-kilter“) ist, und so in einen seiner Gleichgewichtszustände überführt, dass keiner der Bogen, die sich schon im Gleichgewicht befinden, seine Charakteristik verlässt. Eine optimale Lösung liegt genau dann vor, wenn sich alle Bogen des Netzes in einem Gleichgewichtszustand befinden. Zur Erzeugung der Startlösung wird folgender Prozess ausgeführt: • Vom Knoten mit der Nummer 1, AKnN, aus wird eine Längste-Wege-Berechnung nach dem Dantzig-Algorithmus durchgeführt, für die unterstellt wird, dass die interne Knotennummerierung (von 1 bis n) eine topologische Ordnung des Netzes darstellt. • Für diese Rechnung gelten folgende Festsetzungen für die Bogenlängen lg(k): • lg([AKn(i), EKn(i)]) = d(i) := normD(i) für alle i • lg([AKnN, EKn(i)]) = 0 auf den Terminbögen (bei x(k) = 0; vgl. Bild 5.8.3) • lg(k) = a(k) für alle übrigen Bogen. • Der Terminvektor t dieser Startlösung wird durch den dualen Kostenstromvektor x = 0 ergänzt, was der Festlegung, x(k) = 0 auf allen Cogerüstbogen entspricht. Im Zusammenhang mit der Dateneingabeschablone für Aktivitäten wurde darauf hingewiesen, dass im Regelfall (Es existieren nur Abhängigkeiten der Typen 0 und 3, und das Netz ist kreisfrei.) das Netz so aufgebaut wird, dass die Numerierung der Aktivitäten eine topologische Ordnung ist. Das bedeutet, dass in der durch den Dantzig-Algorithmus gewonnenen Startlösung t 112 Kapitel 5: Netzplantechnik höchsten für Abstandsbogen der Abstandstypen 1 oder 4 (bzw. auch 2 oder 5), die eine negative Bogenlänge lg(k) = a(k) ≤ 0 haben, y(k) ≥ lg(k) nicht erfüllt ist. Für alle Aktivitätsbogen gilt y(k) = normD(i), sie sind kritisch (d.h. im Gerüst). Folglich können nur Terminbogen, [AKnN, EKn(i)] und [AKnN, EKnN], sowie die schon genannten Abstandsbogen der Abstandstypen 1 oder 4 (bzw. auch 2 oder 5) unzulässig sein. Tritt eine Unzulässigkeit auf, so denkt man sich die zugehörige Charakteristik so abgewandelt, dass die Unzulässigkeit in einen Out-of-kilter-Zustand übergeht: Das nachfolgende Beispiel (Bild 5.9) ist das Modellierungsbeispiel aus Bild 5.5.6. An ihm soll die Erzeugung einer zulässigen Anfangslösung für weitere Optimierungen demonstriert werden: Da wir im mathematischen Modell operieren, wurden im Bild 5.9 • die Abstandsvorgabe [A1, A3] mit den Parametern (1, 100, 1) in den Bogen [AKn(3), EKn(1)] mit den Parametern (partner = 0, f = 0, W = -1) • die Abstandsvorgabe [A1, A4] mit den Parametern (1, 90, 10) in den Bogen [AKn(4), AKn(1)] mit den Parametern (partner = 1, f = -0.9, W = -10) • die Abstandsvorgabe [A1, A2] in den Bogen [AKn(1), AKn(2)] mit den Parametern • (partner = 1, f = 0.4, W = 0) die Abstandsvorgabe [A2, A3] in den Bogen (partner = 2, f = 0.8, W = 0) [AKn(2), AKn(3)] mit den Parametern transformiert. Die einfache Längste-Wege-Berechnung erbringt eine unzulässige Lösung: Die Abstände der Bogen [AKn(3), EKn(1)] und [AKn(4), AKn(1)] sind nicht eingehalten: et(1) - at(3) /≥ -1 und at(1) – (at(4) – 0,9·d(1)) /≥ -10. Für die Charakteristik dieser Bogen gilt Bild 5.8.5 (bei f(k) = 0, bzw. f(k) = -0,9). Wir werden sukzessive für beide versuchen durch Flussverkleinerung (x → -∞) und Spannungserhöhung einen Gleichgewichtszustand für sie zu erreichen. Legende: Ai normD(i) at(i) minD(i) -cD(i) et(i) x*(i) W = -1 partner = 1, f = -0.9, W = -10 A1 6 2 -1 0 6 0 f = 0.4 4 -1 A3 10 6 -1 2,4 12,4 0 12 18 0 A2 12 A4 5 3 22 27 -1 0 f = 0.8 Bild 5.9: Beispiel zur Terminoptimierung –Anfangslösung: Unzulässige Startlösung 5.3.3 Die Prozedur „Gleichgewicht“ Das generelle algorithmisches Vorgehen der folgende Optimierungen besteht darin, zu einer StartBasislösung y und den zugehörigen Kostenstrom x einen Bogen zu suchen, der „out-of-kilter“, d.h. nicht im Gleichgewicht ist. Ist ook ein solcher Bogen, so wird er durch Spannungs- und Stromänderungen in einen seiner Gleichgewichtszustände überführt. Die Änderungen sind so beschaffen, dass alle Bögen k, die sich schon in einem Gleichgewichtszustand befinden, im Gleichgewicht bleiben, d.h. der Punkt (x(k), y(k)) eines solchen Bogens wird auf der Bogencharakteristik bewegt. Für diesen Algorithmus benötigt man einen Spannungs- bzw. StromTransformationsvektor der Basislösung eines NMKP – vgl. Abschnitt 4.3: Ist ein Gerüst gegeben, so erzeugt bekanntlich jeder seiner Bogen einen Basiscozyklus. Bei einer gewöhnlichen Kapitel5: Netzplantechnik 113 Potentialaufgabe liefert ein solcher Basiscozyklus einen Vektor, den man einfach zur gegebenen zulässigen Lösung y addieren kann, um wieder eine zulässige Lösung zu erhalten: Vorgesehen sei die Spannungs- / Potentialtransformation y := y - p·dy, ook sei Gerüstbogen. Im Fall einer einfachen Minimalkosten-Potentialaufgabe ohne Kopplung gilt dy = cz(ook), wobei cz(ook) = (cz(ook, 1), cz(ook, 2), …, cz(ook, m)) der zum Gerüstbogen ook gehörende BasiscozyklusVektor ist. Sei akt eine Aktivität, deren Aktivitätsbogen in diesem Cozyklus liegt, so ist im hier betrachteten Modell mit Bogenkopplung zu beachten, dass mit der Änderung der Aktivitätsdauer d(akt) um ein dd(akt) sich die Schranke a(k) aller Abstandsbogen k, die mit akt gekoppelt sind (partner(k) = akt) ändert: a(k) := a(k) + f(k)·dd(akt)). Dies betrifft auch Bogen, die nicht im Cozyklus liegen, sondern kritisch sind. Folglich muss das y(k) eines solchen Bogens, das gleich a(k) ist, ebenfalls um dy(k) = da(k) = f(k)·dd(akt) geändert werden. Da die Spannungsänderung eines kritischen Bogens k über seinen Basiscozyklus cz(k) vollzogen werden muss, ergibt sich dy = cz(ook) + da(k)·cz(k). Dieser neue Transformations-Vektor kann jedoch zu ähnlichen Komplikationen führen. Folglich ist zu definieren: Spannungs-Transformationsvektor dy der Basislösung eines NMKP ist eine Linearkombination aus Basiscozyklusvektoren zum aktuellen Gerüst, die so beschaffen ist, dass • dy(ook) = 1, d.h. Spannungsänderung um ein noch zu bestimmenden Wert q bei ook • dy(k) - da(k) = 0 für Bogen mit partner(k) ≠ 0, k kritisch und da(k) ≠ 0. gilt. Ist der Spannungs-Transformationsvektor dy ermittelt, muss der maximal mögliche Wert von q für die Transformationsgleichung y := y - q·dy bestimmt werden: Dazu untersucht man alle im Gleichgewicht befindlichen Bogen mit dy(k) ≠ 0, und wählt unter ihnen denjenigen, der p am meisten einschränkt – er möge mit spannKrit bezeichnet werden. Gilt ook = spannKrit, so sind wir fertig, ook befindet sich nach y := y - q·dy im Gleichgewicht. Andernfalls suchen wir einen Strom-Transformationsvektor dx so, dass x := x - p·dx zugehöriger Kosten-Strom für dass neue y ist. Dazu wird dx in ähnlicher Weise wie dy aus Basiszyklen zum Gerüst erzeugt: Ausgangspunkt ist der Basiszyklus zum Cogerüstbogen spannKrit, denn dieser Bogen geht in einen neuen Gleichgewichtszustand über. Der Zyklus kann einen Abstandsbogen k mit partner(k) = i ≠ 0 enthalten, dessen Partneraktivität Ai kritisch ist, sodass die Flussänderung dx(k) dass Gleichgewicht stört und durch eine weitere Flussänderung über den Basiszyklus z([AKn(i), EKn(i)]) ausgeglichen werden muss. Da weitere analoge Komplikationen möglich sind, definieren wir: Strom-Transformationsvektor dx der Basislösung eines NMKP ist eine Linearkombination aus Basiszyklusvektoren zum aktuellen Cogerüst, die so beschaffen ist, dass • dx(ook) = 1, d.h. Stromänderung um ein noch zu bestimmenden Wert p bei ook • dx(k) – dx*(i) = 0 für Bogen mit partner(k) = i ≠ 0 und dx*(i) ≠ 0. • gilt. Ist dx ermittelt, so wird ein maximales q bestimmt, das durch seine Einschränkung auf einem stromKrit genannten Bogen definiert ist. Die in einer Software realisierte algorithmische Erzeugung eines SpannungsTransformationsvektors dy erfolgt mit einem Objekt GlgSystem zur Aufstellung und Lösung des angegebenen Gleichungssystems wie folgt: • Mit dem Konstruktor public GlgSystem(int varNr) wird die Gleichung dy(ook) = 1 angelegt. • Die Methode public void addOrKorrGlchg(int varNr1, int varNr2, double koeff) o sucht, ob es schon eine zu varNr1 gehörende Gleichung gibt 114 Kapitel 5: Netzplantechnik gibt es eine varNr1 zugeordnete Gleichung, so wird deren varNr2 zugeordnetes Glied gesucht und um koeff vergrößert o gibt es noch keine varNr1 zugeordnete Gleichung, so wird das Gleichungssystem um eine neue Gleichung mit den beiden Variablen varNr1 (Koeffizient 1) sowie varNr2 (Koeffizient koeff) ergänzt. Die Methode public void loeseGlgSystem() berechnet die Lösung des einfachen Gleichungssystems mit dem Gaußschen Algorithmus. Anschließend können mit der Methode public IntDouble getItem(Gleichung r) jeweils varNr und wert abgefragt werden. o • Nach der Initialisierung von GlgSystem werden in einer Schleife die zu dem wachsenden Gleichungssystem gehörenden varN-ummer-n bestimmt und cz(varNr) erzeugt - varNr ist die Nummern eines kritischen Bogens. Nun wird für alle Bogen (= varNr1) mit Partner geprüft, ob sie kritisch sind und ob ihr partner (= varNr2) zum Cozyklus gehört. Ist beides der Fall, wird GlgSystem.addOrKorrGlchg(varNr1, varNr2, cz(varNr, varNr2)*v(varNr1)) aufgerufen. Bricht der Prozess ab, so wird mit der Lösung koeff = (koeff(varNr1), koeff(varNr2), …, koeff(varNrE)) die Linearkombination dy = koeff(varNr1)* cz(varNr1) + koeff(varNr2)* cz(varNr2) + …+ koeff(varNr1)* cz(varNr) gebildet, mit der eine neue Basislösung erzeugt werden kann. ook ook stromKrit k1 stromKrit k1 k2 spannKrit k2 spannKrit Bild 5.10: Änderung des Gerüsts nach Änderung der Basislösung Das Gerüst zur neuen Basislösung geht aus dem Gerüst zur alten Basislösung durch den Austausch des „spannungskritischen“ Bogens spannKrit gegen den „flusskritischen“ Bogen stromKrit hervor. Im allgemeinen Fall werden spannKrit und stromKrit nicht beide in einem Zyklus liegen. In diesem Fall liegt im Basiszyklus zu spannKrit mindestens ein gekoppelter kritischer Bogen, dessen Partneraktivität k1 (Nummer ihres Aktivitätsbogens) nicht kritisch ist, sodass der zu ihr gehörende Basiscozyklus cz(k1) zum Transformationsvektor dy gehört. Auch cz(k1) kann einen gekoppelten kritischen Bogen enthalten, dessen Partneraktivität k2 nicht kritisch ist usw. Bild 5.10 veranschaulicht die denkbare Situation (linke Skizze). Der Austausch spannKrit gegen stromKrit im Gerüst, könnte so erfolgen, dass spannKrit gegen k1, part(k1) gegen k2 und part(k2) gegen stromKrit ausgetauscht werden. Wegen der oben getroffenen Festlegung, dass Aktivitätsbögen nur dann in das Gerüst aufgenommen werden, Kapitel5: Netzplantechnik 115 wenn ihre Dauer einen kritischen Wert hat (minD oder normD), werden statt des Austauschs part(k1) gegen k2 bzw. part(k2) gegen stromKrit, der Anfangsknoten von part(k1) zusammen mit f(part(k1)) bzw. der Anfangsknoten von part(k2) zusammen mit f(part(k2)) geändert (rechte Skizze) – vgl. auch Bild 5.7. Wir verdeutlichen die eventuell notwendige Abstandsbogen-Transformation an einem Beispiel – vgl. Bild 5.11: Das Bild 5.11.1 zeigt ein Netz aus drei Aktivitäten mit einer Basislösung und den zugehörigen Kostenstrom bei cTN = 2. A1 20 10 0 20 -1 -1,5 A2 12 8 10 20 50% AKnN -1 -1 0 EKnN 20 A3 15 6 0 15 -1 0 x=0 x=2 Legende: Ai normD(i) at(i) minD(i) -cD(i) et(i) x*(i) Bild 5.11.1: Transformation einer Basislösung Aktivität A1 ist out-of-kilter, denn bei d(1) = normD(1) = 20 müsste x*(1) ≥ -1 gelten, im Widerspruch zu x*(1) = -1 + 0,5(-1) = -1,5. Der Basiscozyklus zum Out-of-kilter-Bogen [AKn(1), EKn(1)] ist durch die schraffierte Linie beschrieben: cz(1) = {[AKn(1), EKn(1)], [AKn(3), EKn(3)], [EKn(3), EKnN], [AKnN, EKnN]}. Ändert man über diesen Cozyklus die gegebene Spannung, so ändert man mit der Dauer d(1) auch den Mindestabstand auf [AKn(1), AKn(2)]. Folglich ist dy = cz([AKn(1), EKn(1)]) – 0,5·cz([AKn(1), AKn(2)]) der SpannungsTransformationsvektor der vorliegenden Basislösung, und y := y - 4dy gibt eine neue zulässige Basislösung, die Bild 5.11.2 zeigt. A1 20 10 0 16 -1 -1 50% A2 12 8 8 16 AKnN 0 -1 -2 EKnN 16 A3 15 6 0 15 -1 0 x=0 x=2 Bild 5.11.2: Die neue Basislösung 116 Kapitel 5: Netzplantechnik Beispiel zur Terminoptimierung – Bild 5.12: Wir greifen das Beispiel aus Abschnitt 5.3.2 (Bild 5.9) wieder auf, um die Unzulässigkeit der Lösung zu beseitigen. Legende: Ai normD(i) at(i) minD(i) -cD(i) et(i) x*(i) W = -1 x = -p A1 6 2 -1 0 6 0.6p partner = 1, f = 0.4 A2 12 partner = 1, f = -0.9, W = -10 4 -1 2,4 12,4 -0.8p A3 10 6 -1 12 18 0 A4 5 3 22 27 -1 0/0 partner = 2, f = 0.8 Bild 5.12.1: Beispiel zur Terminoptimierung – Startlösung – vgl. Bild 5.9 Für dieses Ziel wählen wir [AKn(3), EKn(1)] als Out-of-Kilter-Bogen. Um ihn ins Gleichgewicht zu bringen schicken wir einen Fluss der Stärke –p durch ihn. (Für p = -∞ würde der Bogen als im Gleichgewicht befindlich gelten.): Für p ≥ 1, 25 würde [AKn(2), EKn(2)] wegen x*([AKn(2), EKn(2)]) ≥ -1 oder -0,8p ≥ -1 aus dem Gleichgewicht geraden. Es muss d(2) ≤ normD(2) = 12 gelten. Mit p ≥ 1,125 und d(2) berechnet aus at(3) – et(2) = 1 zu d(2) = 5,75 ergibt sich die Lösung, die Bild 5.12.2 zeigt. Der Bogen [AKn(3), EKn(1)] muss im Austausch gegen den nicht mehr kritischen Aktivitätsbogen [AKn(2), EKn(2)] in das Gerüst. Dabei stoßen wir auf eine Situation wie sie oben – vergleiche Bild 5.7 – diskutiert wurde: Es entstünde ein Zyklus aus kritischen Bogen. Daher wird der Bogen [AKn(2), AKn(3)] in den Bogen [EKn(2), AKn(3)] transformiert – verbunden mit der Überführung seines Parameters f = 0,8 in f:= -1 + 0,8 = -0,2. W = -1 partner = 1, f = -0.9, W = -10 x = -p A1 6 2 0 6 -1 0,75 - p partner = 1, f = 0,4 (x = -1,25) A2 12 4 -1 2,4 8,15 -1 A3 10 6 -1 7 13 -p A4 5 3 -1 17 22 0 partner = 2, f = -0,2 (x = -1,25) Bild 5.12.2: Beispiel zur Terminoptimierung: - weiter unzulässig Die Lösung ist noch immer unzulässig. Zwar wird der mit dem Bogen [AKn(3), EKn(1)] geforderte Abstand jetzt eingehalten aber der Bogen ook = [AKn(4), AKn(1)] ist weiterhin out-of-kilter. Mit dem gleichen Vorgehen wie eben ändern wir den Strom durch die Vorgabe x(ook) = -p über den Basiszyklus [[AKn(4), AKn(1)], [AKn(1), EKn(1)], -[AKn(3), EKn(1)], [AKn(3), EKn(3)], [EKn(2), AKn(4)]]. Bei p > 1 würde A3 in einen Out-of-kilter-Zustand geraden: Es muss d(3) ≤ normD(3) = 10 gelten. Mit p = 1 und d(3) berechnet aus 0,9·d(1) – (0,4·d(1) + 0,8·d(2) + d(3)) = -10 zu d(3) = 8,4 ergibt sich die Lösung, die Bild 5.12.3 zeigt. Kapitel5: Netzplantechnik 117 W = -1 (x = -0,25) A1 6 2 -1 0 6 0,65 A2 12 partner = 1, f = 0,4 (x = -1,25) 4 -1 2,4 8,15 -1 partner = 1, f = -0.9, W = -10 (x = -1) A3 10 6 -1 7 15,4 -1 A4 5 3 -1 15,4 20,4 0 / 0 partner = 2, f = -0,2 (x = -1,25) Bild 5.12.3: Beispiel zur Terminoptimierung – zulässige Anfangslösung 5.4 Projekt-Kosten in Abhängigkeit von der Projektdauer Nehmen wir an – dies ist der Regelfall – die pet(i)-Werte seien so groß, dass sie praktisch nicht existieren. Dann stellt die zuläsige Anfangslösung, die von d(i) = normD(i) für alle Aktivitäten Ai ausgeht und bei cTN = 0 nur notwendige Kürzungen enthält, die billigste Lösung dar, allerdings auch die mit der längsten Gesamtdauer (etN). Es interessiert die Frage wie man diese Lösung mit möglichst geringen Kosten kürzen kann. Wir haben die Problematik schon im Abschnitt 3.3.2 für klassische Vorgangspfeilnetze behandelt, und wie dort lösen wir diese Aufgabe über eine parametrische Optimierung, indem wir petN = 0 setzen und die Überschreitung mit einem Parameter cTN = λ bewerten. Für die Anfangslösung gilt λ = 0. Der Netzbogen [AKnN, EKnN] (im Programm der Bogen mit der Nummer 1) ist in der Anfangslösung Cogerüstbogen. Über seinen Basiszyklusvektor z(1) kann der Parameter λ in den Kostenstrom x eingefügt werden: x(λ):= x + λ ·z(1). • Man berechne für jeden relevanten Bogen k bei welchem Wert λ(k) ≥ 0 er aus seinem Gleichgewicht geraden würde. Der Bogen mit dem kleinsten λ(k) möge Parameter-kritisch heißen, wir bezeichnen ihn mit ook: min{ λ(k) | λ(k) ≥ 0) = λ(ook). Falls λ(ook) < ∞: • Man ermittle für den Gerüstbogen ook ausgehend von cz(ook) den SpannungsTransformationsvektor dy(ook). Die bestehende Spannung y soll so geändert werden (y := y + q·dy(ook)), dass kein Bogen sein Gleichgewicht verliert, aber der Bogen 1 möglichst stark gekürzt wird: Der Bogen, den q–Wert für die maximale Änderungsmöglichkeit bestimmt, heiße Spannungs-kritisch, spannKrit. • y := y + q·cz(ook) Falls spannKrit ≠ ook: • • Der Cogerüstbogen spannKrit wird Gerüstbogen, der Gerüstbogen ook wird Cogerüstbogen. Man ermittle für den Cogerüstbogen ook ausgehend von z(ook) den Strom-Transformationsvektor dx(ook): Der bestehende Strom x muss an den geändert Gleichgewichtszustand von ook angepasst werden, wobei kein Bogen sein Gleichgewicht verlieren darf. • x := x + p·dx(ook) mit p das den Gleichgewichtszustand des Bogens ook sichert. Für das schon zur Demonstration der Herstellung einer Anfangslösung oben genutzte Beispiel 1 (vgl. Bild 5.12) wird nachfolgend der Prozess demonstriert. Er liefert die Projektdauer-Kosten-Funktion Bild 5.13.1, von der wir mit Bild 5.12.3 den ersten Punkt ermittelt haben, nämlich die Anfangslösung mit etN = 20,4 und Kürzungskosten = (normD(2) – d(2)) + (normD(3) – d(3)) = (12 – 5,75) + (10 – 8,4) = 7,85 ≈ 8 118 Kapitel 5: Netzplantechnik Kürzungskosten 18 17 16 15 14 13 12 11 10 9 8 etN 7 13 22 14 15 16 17 18 19 20 Bild 5.13.1: Projekt-Dauer-Kosten-Funktion für Beispiel 1 W = -1 (x = -0,25) A1 6 2 -1 0 6 0,65-0,9λ A2 12 partner = 1, f = -0.9, W = -10 (x = -1 + λ) 4 -1 2,4 8,15 -1 A3 10 6 7 15,4 -1 -1 A4 5 3 -1 15,4 20,4 -λ partner = 2, f = -0,2 (x = -1,25) partner = 1, f = 0,4 x = -1,25 x=λ Bild 5.13.2: Beispiel 1 zur Projekt-Dauer-Kosten-Optimierung Bild 5.13.2 zeigt die Anfangslösung aus Bild 5.12.3, allerdings wurde das Netz jetzt durch einen Netzbogen ergänzt, der (vereinfacht) AKn(1) mit verbindet EKn(1). Ihm wurde x(1) = λ zugewiesen, und über den Zyklus z(1) = [1, -[AKn(4), EKn(4)], -[AKn(4), AKn(1)]] wurde der Strom des Netzes entsprechend geändert. A4 würde für λ > 1 wegen x*(4) = -λ < -1 in einen Out-of-kilter-Zustand geraden, was durch Kürzung verhindert wird: d(4):= minD(4) = 3: ook = spannKrit = [AKn(4), EKn(4)], A4 bleibt kritisch – siehe Bild 5.13.3. Die neue Lösung liefert den Punkt (et(4), Kürzungskosten) = (18.4, 10.85) der Projekt-Dauer-Kosten-Funktion – siehe Bild 5.13.1. Kapitel5: Netzplantechnik 119 W = -1 x = -0,25 A1 6 2 -1 0 6 0,25/0,65-0,9λ A2 12 4 partner = 1, f = -0.9, W = -10 x = -1 + λ A3 10 6 -1 2,4 8,15 -1,25 / -1 -1 7 15,4 -1 / -1 partner = 2, f = -0,2 x = -1,25 partner = 1, f = 0,4 x = -1,25 A4 5 3 -1 15,4 18,4 -λ / -λ x = -1 x=p Bild 5.13.3: Beispiel 1 zur Projekt-Dauer-Kosten-Optimierung Die neue Lösung ist nur für λ = 1 stabil, aber für λ > 1 gerät der Bogen [AKn(4), AKn(1)] = ook aus dem Gleichgewicht. Gemäß Charakteristik (vgl. Bild 5.8.5) muss seine Spannung über cz(ook) = {ook, -[AKn(3), EKn(3)], [AKn(1), EKn(3)]} vergrößert werden. spannKrit = [AKn(3), EKn(3)], die Aktivität A3 erreicht minD(3) = 6; im Gerüst wird ook gegen spannKrit ausgetauscht; über den Zyklus z(ook) = [ook, [AKn(1), EKn(1)], -[EKn(1), AKn(3)], [AKn(3), EKn(3)], [EKn(3), AKn(4)]] ändern wir den Strom so, dass x(ook) = 0 gilt; – siehe Bild 5.13.4. (et(4), Kürzungskosten) = (16, 12.25) W = -1 x = -1,25 +λ A1 6 2 -1 0 6 1,25-λ /0,75-λ A2 12 4 -1 2,4 8,15 -1,25 / -1 partner = 1, f = -0.9, W = -10 x=0 A3 10 6 A4 7 13 -λ / -λ partner = 2, f = -0,2 x = -1,25 partner = 1, f = 0,4 x = -1,25 -1 5 3 13 16 -1 -λ / -λ x = -λ x=λ Bild 5.13.4: Beispiel 1 zur Projekt-Dauer-Kosten-Optimierung Der neue Zustand ist für -1,25 + λ ≤ 0, also für 1 ≤ λ ≤ 1,25 stabil, dann gerät [AKn(3), EKn(1)] aus dem Gleichgewicht, und seine Spannung muss größer als -1 werden: ook = [AKn(3), EKn(1)]; die Spannungsänderung geschieht über cz(ook) = {ook, -[AKn(2), EKn(2)], [AKn(4), AKn(1)], -[AKn(1), EKn(4)]}; dieser enthält [AKn(2), EKn(2)], also muss auf Grund der Kopplung cz([EKn(2), AKN(3)]) = {[EKn(2), AKn(3)], -[AKn(2), EKn(2)]} in den Transformationsvektor dy einbezogen werden: dy(ook) = 1, dy([EKn(2), AKn(3)]) + 0,2·(dy(ook) + dy([EKn(2), AKn(3)])) = 0; Lösung: dy(ook) = 1, dy([EKn(2), AKn(3)]) = 0,25; y := y + q·(cz(ook) + 0,25·cz([EKn(2), AKn(3)])); für q = 1,4 erreichen wir die maximale Änderung, y(pannKrit) = d(2) := 4, spannKrit = [AKn(2), EKn(2)]; im Gerüst wird ook gegen spannKrit getauscht; x(ook) := 0, es ergibt sich der Netzzustand, den Bild 5.13.5 zeigt. (et(4) = 14.6, Kürzungskosten = 14). 120 Kapitel 5: Netzplantechnik W = -1 x =0 A1 6 2 -1 0 6 0 / -0,4λ A2 12 partner = 1, f = -0.9, W = -10 x=0 4 -1 2,4 6,4 -λ / -0,8λ A3 10 6 -1 5,6 11,6 -λ / -λ 5 3 -1 11,6 14,6 -λ / -λ x = -λ partner = 2, f = -0,2 x = -λ partner = 1, f = 0,4 x = -λ A4 x=λ Bild 5.13.5: Beispiel 1 zur Projekt-Dauer-Kosten-Optimierung Die neue Lösung ist für 1,25 ≤ λ ≤ 2,5 stabil. Für λ > 2,5 gerät A1 aus dem Gleichgewicht. Es muss gekürzt werden. Der Verlauf ist formal wie folgt zu protokollieren: ook = [AKn(1), EKn(1)]; cz(ook) = {[ook, -[AKn(3), EKn(1)]}; auf Grund der Kopplung muss cz([AKn(1), AKn(2)]) = {[AKn(1), AKn(2)], -[AKn(3), EKn(1)], -[AKn(4), AKn(1)], [AKn(1), EKn(4)]} in den Transformationsvektor dy einbezogen werden: dy(ook) = 1, dy([AKn(1), AKn(2)]) - 0,4dy(ook) = 0; Lösung: dy(ook) = 1, dy([AKn(1), AKn(2)]) = 0,4; y := y - q·(cz(ook) + 0,4·cz([AKn(1), AKN(2)])); für q = 2,3 erreichen wir die maximale Änderung, y(pannKrit) := -1, spannKrit = [AKn(3), EKn(1)]; ook wird im Gerüst durch spannKrit ersetzt; x*(1) := -1: Stromänderung über den Zyklus z(ook) = [ook, -[AKn(3), EKn(1)], -[EKn(2), AKn(3)], -[AKn(2), EKn(2)], -[AKn(1), AKn(2)]] um p ändert x*(1) := -0,4·λ + p – 0,4·p, p = -1,7 + 0,7·λ. Es ergibt sich der Netzzustand, den Bild 5.13.6 zeigt; (et(4) = 13.7, Kürzungskosten = 16,3). Die neue Lösung ist für λ ≥ 2,5 stabil und die kürzeste aber auch teuerste Lösung. W = -1 x = 1,7 - 0,7λ A1 6 2 -1 0 3,7-1,7+0,7λ / -1 A2 12 4 partner = 1, f = -0.9, W = -10 x=0 -1 1,5 5,5 -λ / -0,8λ A3 10 6 A4 4,7 10,7 -λ / -λ partner = 2, f = -0,2 x = 1,7(1 - λ) partner = 1, f = 0,4 x = 1,7(1 - λ) -1 5 3 -1 10,7 13,7 -λ / -λ x = -p x=λ Bild 5.13.6: Beispiel 1 zur Projekt-Dauer-Kosten-Optimierung Als Beispiel 2 wollen wir das Beispiel d) aus Abschnitt 5.2 betrachten (vgl. Bild 5.5.4). Die folgende Rechnung liefert die Projektdauer-Kosten-Funktion Bild 5.14.1. Startpunkt ist der Terminplan mit d(1) = normD(1) = 10, d(2) = normD(2) = 10; etN = 12, Kürzungskosten = 0 – vgl. Bild 5.14.2. x = λ auf dem Netzbogen stimuliert die Kürzung: Bei λ > 1 würde A3 aus dem Gleichgewicht geraden, deshalb Kürzung um 1, dann wird [EKn(2), EKn(3)] kritisch – vgl. Bild 5.14.3. Der Strom mit x*(3) = -1 bewirkt, dass A2 bei λ > 2 aus dem Gleichgewicht geraden würde, deshalb Kürzung von A2 und A3 um jeweils 1, dann wird kritisch – vgl. Bild 5.14.4. Die neue Lösung ist für λ ≥ 2 stabil, also die Lösung mit der kürzesten Gesamtdauer. [EKn(1), EKn(2)] Kapitel5: Netzplantechnik 121 Kürzungskosten 3 2 1 etN 0 10 11 12 Bild 5.14.1: Projekt-Dauer-Kosten-Funktion für Beispiel 2 A1 10 10 0 10 A2 10 0/- 3 1 11 x = -λ, y ≥ 1 -1 A3 0/0 10 5 2 12 -1 -λ / -λ x = -λ, y ≥ 1 x=λ Bild 5.14.2: Beispiel 2 zur Projekt-Dauer-Kosten-Optimierung x = -λ + 1 A1 10 10 0 10 A2 0/- 10 3 1 11 x = -λ, y ≥ 1 -1 A3 -λ + 1 / -λ + 1 10 5 2 11 -1 -1 / -1 x = -1, y ≥ 1 x=λ Bild 5.14.3: Beispiel 2 zur Projekt-Dauer-Kosten-Optimierung x = -λ + 1 x = -λ + 2 A2 A1 10 10 0 10 -λ / - x = -2, y ≥ 1 10 3 1 10 -1 -1 / -1 x = -1, y ≥ 1 x=λ Bild 5.14.4: Beispiel 2 zur Projekt-Dauer-Kosten-Optimierung A3 10 5 2 10 -1 -1 / -1 122 Kapitel 5: Netzplantechnik Wir betrachten abschließend ein weiteres Beispiel 3. Es handelt sich um das Bespiel, das schon mit dem Beispiel im Abschnitt 5.3.3, Bild 5.11 angesprochen wurde. Das relativ triviale Beispiel ist durch die Kopplung des Abstandsbogens mit der Aktivität 1 nicht ganz uninteressant, aber vor allem soll es im nächsten Kapitel als Beispiel für Ressourceneinsatz-Planung dienen. Die zu entwickelnde Lösung wird als Ausgangslösung (minimale Projektdauer) für ein übersichtliches Beispiel zur Ressourceneinsatz-Optimierung dienen. Bild 5.15.1 enthält die Startlösung, die mit Dauer etN = 22 und Kürzungskosten = 0 in diesem Fall für x([AKnN, EKnN]) ≤ 1 optimal ist und die „Normaldauer“ des Projekts realisiert. A1 20 10 -1 0 20 -0.5λ f = 0.5 A2 12 8 AKnN 0 10 22 A3 15 6 -1 -λ EKnN 22 -1 x=0 0 15 0/0 x=λ Bild 5.15.1: Beispiel 3 zur Projekt-Dauer-Kosten-Optimierung x([AKnN, EKnN]) = λ; für λ > 1 gerät A2 aus dem Gleichgewicht: Kürzung der Aktivität A2 um 2 Zeiteinheiten - führt zur Netzdauer etN = 20, d(2) = 10 und Kürzungskosten = 2 – vgl. Bild 5.15.2. A1 20 10 -1 0 20 -0.5 - λ f = 0.5 A2 12 8 AKnN 0 10 20 A3 15 6 -1 0 15 0 -1 -1 EKnN 20 x=0 x=1+λ Bild 5.15.2: Beispiel 3 zur Projekt-Dauer-Kosten-Optimierung Für λ > 0,5 gerät A1 aus dem Gleichgewicht: Kürzung der Aktivität A1 um 4 Zeiteinheiten und der Aktivität A2 um 2 Zeiteinheiten führt zur Netzdauer etN = 16 und Kürzungskosten = 2 + 4·1,5 = 8. Zu beachten ist, dass der Cozyklus zum flusskritischen Bogen [AKn(1), EKn(1)] wegen der Kopplung mit einem Cozyklus zum Abstandsbogen [AKn(1), AKn(2)] zu verbinden ist – vgl. Bild 5.15.3. Kapitel5: Netzplantechnik 123 A1 20 10 -1 0 16 -1 f = 0.5 A2 12 AKnN 0 8 A3 15 6 -1 0 15 0 8 -1 EKnN 16 16 -1 - 2λ x=0 x =1,5+ λ Bild 5.15.3: Beispiel 3 zur Projekt-Dauer-Kosten-Optimierung Für λ > 0,5 gerät [EKn(1), EKnN] aus dem Gleichgewicht (x([EKn(1), EKnN]) = λ - 0,5): Die Kürzung von A1 ist zu verbinden mit einer Kürzung im Cozyklus zu [AKn(1), AKn(2)]: Dauer etN = 15 bei Kürzungskosten = 8+1·2 = 10 – vgl. Bild 5.15.4. Der Austausch von [EKn(1), AKnN] gegen [EKn(3), EKnN] im Gerüst muss mit einer Änderung des Bogens [AKn(1), AKn(2)] zu [EKn(1), AKn(2)] verbunden werden (f = 0,5 ändert sich zu f = -0,5). A1 20 10 -1 0 14 -1 x=0 f = -0.5 AKnN 0 A3 15 6 -1 0 15 -λ A2 12 8 -1 7 15 -2 EKnN 15 x=2+λ Bild 5.15.4: Beispiel 3 zur Projekt-Dauer-Kosten-Optimierung Für λ > 1 ist Aktivität A3 zu kürzen - um 2 Zeiteinheiten und Aktivität A1 um 4 Zeiteinheiten. Wir erhalten die minimalen Projektdauer etN = 13, die mit den Kürzungskosten = 10 + 2 + 4 = 16 zu realisieren ist - vgl. Bild 5.15.5. Sie ist für λ > 0 stabil. A1 20 10 -1 x=0 0 10 -1- 0,5λ f = -0.5 AKnN 0 A3 15 6 -1 0 13 -1 A2 12 8 5 13 x=3+λ Bild 5.15.5: Beispiel 3 zur Projekt-Dauer-Kosten-Optimierung -1 -2 -λ EKnN 13 124 Kapitel 5: Netzplantechnik Bild 5.15.6 zeigt die resultierende Projekt-Dauer-Kosten-Funktion. Kürzungskosten 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 etN 0 13 14 15 16 17 18 19 20 Bild 5.15.6: Projekt-Dauer-Kosten-Funktion für Beispiel 3 21 22 Kapitel 6: Planung des Ressourceneinsatzes in Arbeitsabläufen 125 6 Planung des Ressourceneinsatzes in Arbeitsabläufen 6.1 Grundlagen In der Einführung zu Kapitel 5 wurde bereits ausgeführt, dass Ablaufplanung im Allgemeinen von einem Verzeichnis ausgeht, das die zu leistenden Arbeiten aufzählt - Leistungsverzeichnis. In diesem Verzeichnis werden zu den aufgeführten Arbeiten Umfangsangaben gemacht, z.B. eine Anzahl von Kubikmeter auszuhebenden Erdreichs oder eine Anzahl von Kubikmeter zu errichtenden Mauerwerks und ähnliche. Bei der Durchführungsplanung werden aus den im Leistungsverzeichnis genannten „Leistungen“ Aktivitäten oder Vorgänge gebildet. Die Dauer einer solchen Aktivität hängt dann davon ab, mit welcher Intensität die zugehörige Arbeit ausgeführt wird, d.h., wie viele Arbeitskräfte und/oder Maschinen (z.B. Bagger) für ihre Durchführung eingesetzt werden. Der Planung des Einsatzes solcher ausführenden Arbeitskräfte und Maschinen ist dieses Kapitel gewidmet. Wir begeben uns damit in ein breites Gebiet, das mit Begriffen wie „Scheduling“, „Resource Allocation“, Maschineneinsatzplanung, … zu den wichtigsten Gebieten der Operations Research gehört. Den Begriff Ressource (Hilfsquelle) benutzen wir im Folgenden als Sammelbezeichnung für alle Hilfsmittel, die im zu planenden Prozess eine Rolle spielen. Ressourcen sind also, 1. finanzielle Mittel 2. alle möglichen Materialien 3. Arbeitkräfte, geordnet nach Gewerken 4. Maschinen der verschiedensten Zweckbestimmung – Maschinenarten 5. Räumlichkeiten bzw. Flächen. Nach der Art ihrer Nutzbarkeit müssen wir zwischen • Verbrauchsressourcen – finanzielle Mittel und Material sowie • erneuerbaren Ressourcen – Arbeitkräfte, Maschinen, Räume / Flächen unterscheiden. 6.1.1 Verbrauchsressourcen Materialien, Energie, Finanzmittel, ... sind im Allgemeinen mit einem Betrag um(i, r) zur Verfügung zu stellen, der meist zu Beginn der Bearbeitung einer Aktivität Ai benötigt wird (- um wie Umfang der Belastung der Ressource Rr). Dieser Betrag ist unabhängig von der Ausführungsdauer der Aktivität. Auf der Basis des mit Terminen versehenen Ablaufplans berechnet man aus diesen Angaben Bereitstellungspläne: Wann wie viel von einem fixierten Material benötigt wird. Es kann allerdings auch die Situationen geben, in denen ein gleichmäßiger Bereitstellungsstrom solcher Ressourcen zu planen ist. Dieses Problem kann analog zum folgenden Planungsproblem der erneuerbaren Ressourcen gelöst werden. 6.1.2 Erneuerbare Ressourcen „Erneuerbar“ heißt eine Ressource, wenn sie nach ihrer Nutzung durch eine Aktivität, in gleicher Weise von einer anderen genutzt werden kann – nachdem ein Bagger eine Grube ausgehoben hat, kann er eine zweite ausheben; im Unterschied zu Ziegelsteinen, die, wenn verbaut, nicht von einem weiteren Vorgang genutzt werden können. Die Eigenschaft der Erneuerbarkeit deckt sich mit der mathematischen Stromeigenschaft: Arbeitskräfte / Maschinen, die man von verschiedenen Seiten zusammengeführt hat, damit sie gemeinsam eine Aktivität ausführen, können, wenn sie das erledigt haben, ohne Verlust, zu verschiedenen anderen Aktivitäten weitergeleitet werden. Für erneuerbare Ressourcen ergeben sich einige Aufgaben der Einsatzoptimierung, z. B. die klassischen Optimierungsaufgaben: • „Minimiere bei vorgegebener Ablaufdauer die Anzahl der benötigten Einheiten einer bestimmten Ressourcenart“ oder • „Minimiere die Dauer des Gesamtablaufes bei vorgegebener Anzahl der in ihm eingesetzten Ressourceneinheiten einer oder auch mehrerer Ressourcenarten“. 126 Planung des Ressourceneinsatzes in Arbeitsabläufen Um solche Aufgaben genauer betrachten zu können bedarf es einiger Präzisierungen: Es ist sinnvoll zu unterstellen, dass für eine Aktivität Ai ein Arbeits-„Umfang“ um(i, r) vorgegeben ist, den die Ressourcenart Rr für sie zu erbringen hat. Ist lstg(i, r) die Leistung der Ressource Rr während der Bearbeitung von Ai, so ist der Ansatz, lstg(i, r) ≈ um(i, r) / d(i) (Leistung ist Arbeit pro Zeiteinheit) bzw. d(i) ≈ um(i, r) / lstg(i, r) (je stärker die Leistung, desto schneller die Ausführung des Prozesses), sinnvoll. Wir unterstellen im Folgenden: Für minD(i) ≤ d(i) ≤ normD(i) möge die Gleichung Genauigkeit gelten. d(i) = um(i, r) / lstg(i, r) mit hinreichender Die Schranken minD(i) und normD(i) werden somit als Gültigkeitsbereich der Gleichung d(i) = um(i, r) / lstg(i, r) definiert. Im allgemeinen Fall benötigt eine Aktivität mehrere Ressourcenarten Rr zu ihrer Ausführung. Die Gleichungen d(i) = um(i, r) / lstg(i, r) für verschiedene r könnten in einem solchen Fall verschiedene Werte von d(i) liefern. Dem begegnen wir, indem wir abgestimmte (parallele) Arbeit der ausführenden Ressourcen Rr am Prozess Ai unterstellen, also, d(i) = max{um(i, r) / lstg(i, r) | für r mit um(i, r) > 0 und Rr erneuerbar}. Diese Festlegung führt praktisch dahin, dass eine Ressource die Aktivitätsdauer d(i) definiert, und aus diesem Ergebnis folgen über lstg(i, r) = um(i, r) / d(i) die Leistungen der anderen am Vorgang beteiligten Ressourcen für seine Ausführung. Die Ressource, die die Aktivitätsdauer definiert, wird von einigen Autoren auch als „Leitressource“ bezeichnet. Der Hyperbelzweig, x(i, i, r) = lstg(i, r) = um(i, r) / d(i), minD(i) ≤ d(i) ≤ normD(i), in einem d-x–System, lässt sich leicht linear nähern. Es ist z. B. sinnvoll, wie es Bild 6.1 für das Beispiel um(i, r) = 80, minD(i) = 10, normD(i) = 20 zeigt, die ganzzahligen Werte von x(i, i, r) als Stützstellen einer stückweise linearen Näherung zu verwenden. Im Beispiel gilt, für 16 ≤ d(i) ≤ 20 x(i, i, r) = 9 - 1/4d(i), für 13,3 ≤ d(i) ≤ 16 x(i, i, r) = 11 - 3/8d(i), für 11,4 ≤ d(i) ≤ 13,3 x(i, i, r) = 13 - 21/40d(i), für 10 ≤ d(i) ≤ 11,4 x(i, i, r) = 15 - 7/10d(i). x(i, i, k) 9 8 7 6 5 4 3 d(i) 10 11 12 13 14 15 16 17 18 19 20 21 Bild 6.1: Lineare Näherung der Kopplungsgleichung x(i, i, r) = um(i, r) / d(i) - beispielhaft Wir formalisieren diese lineare Abhängigkeit durch x(i, i, r, d(i)) = gw(I, r, d(i)) – f(i, r, d(i))·d(i), mit • gw(i, r, d(i)) Grundwert Faktor • f(i, r, d(i)) - beide von d(i) abhängig. Kapitel 6: Planung des Ressourceneinsatzes in Arbeitsabläufen 127 An den inneren Eckwerten von d(i) – im Beispiel Bild 6.1 die Werte d(i) = 11,4; 13,3 und 16 – sind gw(i, r, d(i)) und f(i, r, d(i)) nicht eindeutig, weshalb im Folgenden gelegentlich gw(i, r, d(i) - ε) und f(i, r, d(i) + ε) für eine kleine Größe ε ≥ 0 herangezogen werden. Es existieren auch erneuerbare Ressourcen, für die die Leistung lstg(i, r) unabhängig von der Aktivitätsdauer ist und direkt vorgegeben wird, anstatt sie über die Vorgabe eines Arbeitsvolumens um(i, r) zu bestimmen. Das gilt z. B. für Raumnutzung: Ist etwa eine Aktivität Ai eine Unterrichtseinheit, die einen Unterrichtsraum benötigt, so ist für die Ressource Raum nur die Angabe, lstg(i, Raum) = 1 sinnvoll. Wie schon gesagt, können erneuerbare Ressourcen in einem Ressourcennetz als Strom dargestellt werden. Das Ressourcennetz einer erneuerbare Ressource Rr hat dann folgenden Aufbau. Es existieren: • ein Quellknoten Q(r) mit Bogen [Q(r), AKn(i)] und den Flüssen x(0, i, r) für jedes i mit um(i, r) > 0 • ein Senkenknoten S(r) mit Bogen [EKn(i), S(r)] und den Flüssen x(i, 0, r) für jedes i mit um(i, r) > 0 • ein Rückkehrbogen [S(r), Q(r)] mit dem Fluss x(0, 0, r) • zu jedem i mit um(i, r) > 0 der Fluss x(i, i, r) = lstg(i, r) = um(i, r) / d(i) • Umsetzbogen [EKn(i), AKn(j)]r mit den Flüssen x(i, j, r) – vgl. Bild 6.2. AKn(i1) x(0, i1, r) x(i1, i1, r) EKn(i1) x(i2, i1, r) x(i1, 0, r) EKn(i2) AKn(i2) Q(r) S(r) AKn(ie) EKn(ie) x(0, 0, r) Bild 6.2: Ressourcennetz - schematisch Die Maßeinheiten der Ressourcenflüsse werden wir als Ressourceneinheiten bezeichnen; es handelt sich um Arbeitskräfte, Maschinenanzahlen, Räume und dergleichen, also um Größen, die im Allgemeinen ganze Zahlen sein sollten. Die Forderung der Ganzzahligkeit werden wir jedoch nicht in die Aufgabenstellung einbringen, weil sich die Werte aus Umfangsangaben ergeben, die durch die Leistung geteilt werden, so dass z.B. die Angabe 1,5 Mann als 1 Mann interpretiert werden kann, der mit höherer als der normalen Leistung arbeiten muss, oder aber als 2 Mann, deren normale Leistungsfähigkeit nicht ausgeschöpft wird. Die Ressourcennetze (Bild 6.2) sind Zusätze zum Netzplan, den wir in diesem Zusammenhang auch als Zeitnetz bezeichnen wollen. Das Gesamtnetz besteht aus dem Zeitnetz und allen Ressourcennetzen. Zeitnetz und Ressourcennetze haben gemeinsame Knoten aber keine gemeinsamen Bogen. Stattdessen sind sie über Bogen gekoppelt, die jeweils einer Aktivität zuzuordnen sind: Der Fluss x(i, i, r) im Bogen [EKn(i), AKn(i)]r des Ressourcennetzes zur Ressource Rr ist, gemäß der linearen Näherung von x(i, i, r) = um(i, r) / d(i) nach Bild 6.1, linear abhängig von der Spannung y(i, i) = d(i) des Aktivitätsbogens [EKn(i), AKn(i)] des Zeitnetzes – zum Beispiel gilt für 16 ≤ d(i) ≤ 20 x(i, i, r) = 9 - 1/4d(i). Durch die stückweise lineare Näherung ist diese Abhängigkeit aber noch zusätzlich von d(i) abhängig (vgl. oben, Beispiel Bild 6.1). 128 Planung des Ressourceneinsatzes in Arbeitsabläufen 6.2 Kostenminimierung zeitabhängiger Ressourcenströme 6.2.1 Einführung Die im folgenden Abschnitt betrachtete allgemeine Ressourceneinsatz-Optimierung ist eine Kostenminimierung, die folgende Kostenarten berücksichtigen kann: • Planendtermin-Überschreitungskosten (mit Preisen cT(i) und cTN ) • Kapazitäts-Überschreitungskosten der erneuerbaren Ressourcen (mit Preisen cK(r)) sowie • Stillstandskosten der erneuerbaren Ressourcen (mit Preisen cS(r)). Zusätzlich könnten problemlos Umrüst- oder/und Umsetzkosten für die erneuerbaren Ressourcen berücksichtigt werden, worauf wir jedoch im Interesse der übersichtlicheren Darstellung nicht detailliert eingehen. Im Weiteren beziehen wir uns ausschließlich auf erneuerbare Ressourcen, weshalb wir vereinfachend auf das „erneuerbar“ verzichten. Unterstellen wir, dass für die Gesamtleistung, lstg(r) = x(0, 0, r), einer Ressource Rr eine Vorgabe kap(r) („Kapazität“ der Ressource) existiert, deren Überschreitung Kosten von cK(r) Geldeinheiten je Ressourceneinheit verursacht, so fallen auf den Rückkehrbogen eines Ressourcennetzes die Kosten cK(r)⋅(x(0, 0, r) - kap(r)) an, falls für den Fluss des Rückkehrbogens x(0, 0, r) > kap(r) gilt. Bild 6.3 skizziert die Charakteristik eines solchen Rückkehrbogens. y(0, 0, r) cK(r) x(0, 0, r) kap(r) Bild 6.3: Charakteristik des Rückkehrbogens eines Ressourcennetzes Zusammen mit den Planendtermin-Überschreitungskosten cTN·(etN – petN) bewerten KapazitätsÜberschreitungskosten die Abweichung der Ressourcenbedarfslinie, die im Bild 6.4 skizziert ist, von deren Rechteckform etN⋅x(0, 0, r). bed(t, r) x(0, 0, r) kap(r) t petN Bild 6.4: Ressourcenbedarfslinie - schematisch etN Kapitel 6: Planung des Ressourceneinsatzes in Arbeitsabläufen 129 Die Ressourcenbedarfslinie bed(t, r) gibt die Anzahl der benötigten Ressourceneinheiten der Ressource Rr zum Zeitpunkt t an. Für ihre Berechnung beachte man, dass sich der Ressourcenbedarf einer Aktivität Ai als Rechteck über der Zeitachse darstellt, dessen linker und rechter Rand bei at(i) bzw. et(i) liegen (Breite also = d(i)) und dessen Höhe lstg(i, r) Einheiten der Ressource Rr beträgt (lstg(i, r)·d(i) = um(i, r)). Die Lage dieses Rechtecks in Richtung der bed(t, r)-Achse ist nicht festgelegt; wir wollen jedoch unterstellen, dass die Rechtecke so tief, wie ohne Überdeckung möglich, in der t-bed(t, r)-Ebene gelagert sind. Die Bilder 6.5.1.2, 6.5.2.2 und 6.5.7.2 mögen als Veranschaulichung gelten. Die Resourcenbedarfslinie ist eine Treppenfunktion. • Das Integral unter dieser Kurve ist gleich U(r) = ∑{um(i, r) | für alle i}, also gleich der Gesamtarbeit, die die Ressource Rr zu leisten hat. • Der maximale Wert von bed(t, r) ist die Anzahl von Ressourceneinheiten, die mindestens zeitweilig zur Verfügung gestellt werden müssen. Er ist der Wert des Flusses x(0, 0, r) im Rückkehrbogen des Ressourcennetzes. Gilt bed(t, r) = const. zu allen Zeitpunkten des Realisierungszeitraums des Projekts, so liegt ein gewisser Idealfall vor, den die Ressourceneinsatz-Optimierung anstrebt, nämlich gleichmäßiger Ressourceneinsatz. In der Regel besitzt die Kurve jedoch Stufen, die an ihrem Anfang und Ende von der Praxis gebilligt werden, während die im Bild 6.4 schraffierten Lücken im Inneren des Arbeitszeitraums als weniger akzeptabel empfunden werden, denn sie stellen Ressourcenstillstand dar: erneuerbare Ressourcen, die im Allgemeinen bereitgestellt aber nicht genutzt werden. Diese verursachen Kosten, z.B. notwendige Lohnzahlungen. Folglich sind den Ressourcennetzen Ressourcenstillstands-, Umrüst- oder/und Umsetz-Kosten zuzuordnen: Wie schon ausgeführt, können im Netz einer Ressource Rr Umsetzbogen [EKn(i), AKn(j)]r existieren, in denen Flüsse x(i, j, r) aus Ressourceneinheiten (Arbeitskräfte, Maschinen usw.) fließen. Offensichtlich ist dabei x(i, j, r) > 0 nur sinnvoll, wenn at(j) ≥ et(i) gilt: Sollen x(i, j, r) Ressourceneinheiten von Ai nach Aj umgesetzt werden, so muss im Zeitnetz eine Abhängigkeit, diese Forderung vertreten. Die Forderung kann eventuell auch zu at(j) ≥ et(i) + umstZ(i, j, r) erweitert werden, falls Umsetzzeiten (umstZ) für die Vorbereitung und Durchführung des Umsetzvorgangs bzw. für den Transport der Ressourceneinheiten zu berücksichtigen sind. Beispielsweise könnten die Ressourceneinheiten Maschinen sein, die an der Aktivität Aj andersartige Arbeiten ausführen als an der Aktivität Ai, sodass sie „umgerüstet“ werden müssen, oder ein mobiler Kran wird von einer Baustelle auf eine andere „umgesetzt“. Wir verbinden daher mit einem Fluss x(i, j, r) Kosten in Höhe von cS(r)⋅(at(j) - et(i))⋅x(i, j, r), wobei cS(r) der Stillstandspreis der Ressource Rr heißen möge. Der Stillstandspreis beinhalte alle Kosten, die bei Nichtnutzung einer Einheit der erneuerbaren Ressource Rr während einer Zeiteinheit entstehen, insbesondere Lohnkosten für Arbeitskräfte bzw. Amortisation für Maschinen. Zu den durch das Umsetzen verursachten Stillstandskosten können Umrüst- oder/und Umsetzkosten kommen. Die nichtlinearen Kosten cS(r)⋅y(i, j)⋅x(i, j, r) (mit y(i, j) = at(j) - et(i)) sind bilinear in dem Sinne, dass sie linear sowohl im Zeitnetz, als auch in den Ressourcennetzen auftreten, wenn man eines der Netze isoliert, also Zeit oder Ressourceneinsatz als festgelegt, betrachtet. Sie können auch grob durch cS(r)⋅(y(i, j) + x(i, j, r)) linear angenähert werden, so dass man im Zeitnetz cS(r)⋅y(i, j) und im Ressourcennetz cS(r)⋅x(i, j, r) berücksichtigen kann. Zusammengefasst erhalten wir ein bilineares Problem der Kostenminimierung von Ressourcenströmen, die über die Aktivitätsbögen mit der Zeitspannung gekoppelt sind. Wir halten noch einmal fest, wenn man von festen Ressourcennetzen oder einem festen Zeitnetz ausgeht, hat man – die angegebenen linearen Näherungen vorausgesetzt – eine lineare Optimierungsaufgabe vor sich. Diese Aufgabe lässt sich mit dem algorithmischen Material des Minimalkosten-Strom- sowie des Minimalkosten-Potentialproblems gut lösen. Insbesondere gilt für sie der übliche Dualitätssatz des Minimalkosten-Strom- bzw. des Minimalkosten-Potential-Problems, der besagt, dass eine Lösung genau dann optimal ist, wenn sich jeder Bogen in einem seiner Gleichgewichtszustände befindet. Die Menge der Gleichgewichtszustände eines Bogens ist durch seine Charakteristik beschrieben. Im Falle der Kopplung von Bogen existiert für die Menge der gekoppelten Bogen nur eine gemeinsame Charakteristik. Im hier betrachteten Fall ist zu beachten, dass die Menge der im Zeitnetz gekoppelten Bogen einer Aktivität um die Bogen [AKn(i), EKn(i)]r der 130 Planung des Ressourceneinsatzes in Arbeitsabläufen Ressourcennetze erweitert ist. Folglich gilt für die Aktivitätscharakteristiken mit den nachfolgenden Festlegungen der Satz: Satz Die Menge der Gleichgewichtszustände einer der Aktivität Ai ist durch folgende Beziehungen gegeben: y*(i, normD(i)) ≤ y*(i, d(i) - ε) ≤ • • • x*(i) x*(i) ≤ y*(i, d(i) + ε), x*(i) ≤ y*(i, minD(i)), x(k) - dualer Kostenfluss des Bogens mit der Nummer k im Zeitnetz y(i, i, r) - duale Spannung des Bogens [AKn(i), EKn(i)]r im Ressourcennetz der Ressource Rr f(i, r, d(i)) – siehe oben: Kopplungsfaktor für Bogen [AKn(i), EKn(i)]r im Netz der Ressource Rr, mit dem dieser aktuell an den Aktivitätsbogen des Zeitnetzes gekoppelt ist; also der Faktor, mit dem gemäß der aktuellen linearen Näherung von x(i, i, r) = um(i, r) / d(i), x(i, i, r) mit d(i) verbunden ist: x(i, i, r, d(i)) = gw(i, r, d(i)) - f(i, r, d(i))·d(i) • • (Beispiel – vgl. Bild 6.1: Für d(i) = 20 gilt, x(i, i, r, 20) = 9 – 1/4·d(i), also f(i, r, 20) = 1/4.) x*(i) = x([AKn(i), EKn(i)]) + ∑{f(k)⋅x(k) | für Bogen k des Zeitnetzes, mit partner(k) = i}, (vgl. Abschnitt 5.3.1, S. 110) y*(i, d(i)) = ∑{f(i, r, d(i))⋅y(i, i, r) | für r mit um(i, r) > 0}: Das Fehlen expliziter Kosten in der Restriktion ergibt sich aus cD(i) = 0 für alle Aktivitäten, denn es ist in den meisten Fällen nicht sinnvoll, die Variation der Aktivitätsdauer explizit zusätzlich zu der Stimulation, die sich aus den Ressourcennutzungskosten indirekt ergibt, zu stimulieren, Eine Basislösung im Gesamtnetz ist durch ein Gerüst des Zeitnetzes und Cogerüste der Ressourcennetze gekennzeichnet. Wir bezeichnen die Bogen dieses Gerüsts im Zeitnetz und die Bogen dieser Cogerüste der Ressourcennetze als primal aktiv und alle anderen (nicht primal aktiven oder primal passiven) Bogen als dual aktiv. Satz Eine Basislösung der Aufgabe wird durch eine Gerüst-Cogerüst-Struktur im Gesamtnetz beschrieben, die folgende Eigenschaft besitzt: Höchstens einer der Bogen aus jeder Menge gekoppelter Bogen zur Aktivität Ai, {[AKn(i), EKn(i)]} U {[AKn(i), AKn(j)] | für Bogen k = [AKn(i), AKn(j)] des Zeitnetzes, mit partner(k) = i} U {[EKn(i), AKn(i)]r | für r mit um(i, r) > 0}), kann dual aktiv (bzw. primal passiv) sein. Das ergibt sich, weil über die Kopplungsgleichungen sowohl d(i) als auch y(i, i, r) und alle x(k) bestimmt sind, sofern nur eine der den Bogen zugeordneten Variablen festgelegt ist; also nur einer dieser Werte kann sich aus anderen Zusammenhängen ergeben – der entsprechende Bogen ist primal passiv, alle anderen sind primal aktiv. Aus diesem Satz ergibt sich die Bildung der Strom- und Spannungs-Transformationsvektoren einer Basislösung, die man jetzt besser als primale bzw. duale Transformationsvektoren bezeichnet: • Ausgehend von einem Bogen out der sich nicht im Gleichgewicht befindet, wird für eine sinnvolle Stromänderung der Basiszyklus (falls out Cogerüstbogen ist) bzw. der Basiscozyklus (falls out Gerüstbogen ist) als Ausgangsvektor v festgelegt. • Enthält v einen gekoppelten Bogen k, so wird der von ihm erzeugte Basisvektor bv(k) zu v hinzugenommen: v := v + α(k)·bv(k). • Für die Wertzuweisung zu den α(k) wird ein Gleichungssystem aufgestellt. Kapitel 6: Planung des Ressourceneinsatzes in Arbeitsabläufen 131 Zur Demonstration folgt ein Beispiel, dass vor allem die Wirkung der lokalen Strom-SpannungsOptimierung zeigen soll. Beispiel Das Beispiel ist das dritte Demonstrationsbeispiel für die Dauer-Kosten-Optimierung aus Abschnitt 5.4. Bild 6.5.1.0 zeigt das Netz mit dem Terminzustand, den auch Bild 5.15.5 zeigt, d.h. wir wählen als Anfangslösung der Optimierung die Lösung mit der „normalen“ Projektdauer (kürzeste Projektdauer bei minimaler Gesamtkürzung der Dauer der Aktivitäten; cD(i) = 1 für i = 1, 2, …, n, petN = 0, cTN =1). Der duale Kosten-Strom folgt aus cTN = 1; beachte x*(i) = f([AKn(1), AKn(2)])·x([AKn(1), AKn(2)]) = 0,5·(-1) = -0,5. Legende: Ai normD(i) at(i) A1 20 16 0 20 -0,25/ -0,5 / ∞ f = 0.5 15 0 et(i) um(i, 1) y*(i,d(i)-ε) / -x*(i) / y*(i, d(i)+ ε) 80 AKnN 0 A3 minD(i) 10 x=0 A2 12 8 24 10 22 -0,25/ -1 / ∞ EKnN 22 30 15 -0,2/ 0 / ∞ x=0 x=1 Bild 6.5.1.0: Ressourceneinsatzoptimierung - Zeitnetz Wir müssen zunächst die Ressourcenkosten hinzufügen indem wir ein Ressourcennetz – vgl. Bild 6.5.1.1 - „ankoppeln“. AKn(1) 0 Q(1) 0 AKn(2) 0 AKn(3) 0 x(1, 1, 1) = 4; f = 0,25 x(2, 2, 1) = 2; f = 0,25 x(3, 3, 1) = 2; f = 0,2 EKn(1) -1 EKn(2) -1 Q(1) -1 EKn(3) -1 y(0, 0, 1) = 1, x(0, 0, 1) = 8 Bild 6.5.1.1: Ressourcennetz zum Zeitnetz 6.5.1.0 cD(i)-Kosten spielen, wie schon erwähnt, keine sinnvolle Rolle mehr, also cD(i) = 0 für i = 1, 2, …, n; stattdessen wird jetzt eine Ressource R1 betrachtet, die an den Aktivitäten Arbeiten der angegebenen Umfänge zu leisten hat. Von ihrer Leistung an einer Aktivität hängt deren Dauer ab. Wir setzen kap(1) = 0, cK(1) = 1. Für die Kopplungen zwischen den Bogen [AKn(i), EKn(i)] und [AKn(i), EKn(i)]1 verwenden wir die nachfolgenden linearen Approximationen. (Die Approximationen ergeben sich aus der Betrachtung aller möglichen ganzzahligen Ressourceneinsatzwerte um(i, r) / d(i).): A1: Für 10 ≤ d(1) ≤ 11,4 gilt, x(1, 1, 1) = 15 – 0,7 d(1), f(1, 1, d(1)) = 0,7, für 11,4 ≤ d(1) ≤ 13,3 gilt, x(1, 1, 1) = 13 – 0,525d(1), f(1, 1, d(1)) = 0,525, f(1, 1, 11,4-ε) = 0,7, f(1, 1, 11,4+ ε) = 0,525, für 13,3 ≤ d(1) ≤ 16 gilt, x(1, 1, 1) = 11 – 0,375d(1), f(1, 1, d(1)) = 0,357, f(1, 1, 13,3-ε) = 0,525, f(1, 1, 13,3+ε) = 0,375, 132 Planung des Ressourceneinsatzes in Arbeitsabläufen für 16 ≤ d(1) ≤ 20 gilt, x(1, 1, 1) = 9 – 0,25 d(1), f(1, 1, d(1)) = 0,25, f(1, 1, 16-ε) = 0,375, f(1, 1, 16+ε) = 0,25, A2: Für 8 ≤ d(1) ≤ 12 gilt, x(2, 2, 1) = A3: Für 6 ≤ d(1) ≤ 7,5 gilt, x(3, 3, 1) = für 7,5 ≤ d(1) ≤ 10 gilt, x(3, 3, 1) = für 10 ≤ d(1) ≤ 15 gilt, x(3, 3, 1) = 5 – 0,25 9 – 0,7 7 – 0,4 5 – 0,2 d(2); d(3), d(3), d(3). Mit der neuen Kostenbetrachtung korrespondiert die Angabe der Werte y*(i, d(i)-ε) und y*(i, d(i)+ε) sowie minD(1)aktuell = 16 und minD(3)aktuell = 10 an den Aktivitäten im Bild 6.5.1.0. Im Ressourcennetz müssen die Bogen [AKn(i), EKn(i)]1 alle primal aktiv sein, woraus das Gerüst folgt, und aus y([Q(1), EKn(i)]) = y([AKn(i), S(1)]) = 0 sowie y(S(1), Q(1)] = cK(1) = 1 ergibt sich das Potential im Bild 6.5.1.1. Mit diesem Potential und den aus den d(i) folgenden Kopplungsfaktoren ergeben sich y*(1, 20) = -0,25, y*(2, 12) = -0,25 und y*(3, 15) = -0,2. Bild 6.5.1.2 demonstriert den Ressourceneinsatz sehr anschaulich durch Rechteck-Balken für jede Aktivität; Breite = Aktivitätsdauer, Höhe = Ressourcenbedarf pro Zeiteinheit (= aktuelle Leistung der Ressource an der Aktivität). Es ist eine Ressourcenbedarfslinie, wie sie oben definiert wurde. Die Gesamtkosten für dieses Netz betragen: Gesamtkosten = (etN –petN)·cTN + (x(0, 0, 1) – kap(1))·cK(1) = 22·1 + 8·1 = 30 bed(t, 1) 9 8 7 A3 6 5 A2 4 3 A1 2 1 0 t 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Bild 6.5.1.2: Ressourceneinsatz zum Zeitplan gemäß Bild 6.4.1.0 - Balkendiagramm Im Zustand von Bild 6.5.1.0 sind wegen x*(1) = -0,5 < y*(1, 20 - ε) = -0,25 und x*(2) = -1 < y*(2, 12 - ε) = -0,25 sowohl A1 als auch A2 nicht im Gleichgewicht, sondern müssen gekürzt werden. Wir wählen zunächst A1 und kürzen auf d(1) = 16, die aktuelle Minimaldauer dMind(1)aktuell. Es entsteht der Zustand, den Bild 6.5.2.0 zeigt. Kapitel 6: Planung des Ressourceneinsatzes in Arbeitsabläufen 133 A1 16 13,3 80 x=0 0 16 -0,375/ -0,5 /-0,25 f = 0.5 AKnN 0 A3 15 10 A2 12 8 8 20 24 -0,25/ -1 /∞ EKnN 20 30 x=0 0 15 -0,2/ 0 / ∞ x=1 Bild 6.5.2.0: Ressourceneinsatzoptimierung - Zeitnetz In Bild 6.5.2.0 ist A1 mit x*(1) = -0,5 bei y*(1, 20 - ε) = -0,375 weiter out-of-kilter, also weiter zu kürzen. Die Kürzung endet bei d(1) = minD(1)aktuell = 13,3 - siehe Bild 6.5.3.0 A113,3 11,4 80 x=0 0 13,3 -0,525/-0,5 /-0,375 A2 f = 0.5 AKnN 0 12 8 24 6,7 18,7 -0,25/ -1 / ∞ A3 15 10 EKnN 18,7 30 x=0 0 15 -0,2/ 0 / ∞ x=1 Bild 6.5.3.0: Ressourceneinsatzoptimierung - Zeitnetz Im Zustand von Bild 6.5.3.0 ist A1 im Gleichgewicht, aber A2 ist weiterhin out-of-kilter. Die notwendige Kürzung von A2 endet mit d(2) = 8,3, weil [EKn(3), EKnN] kritisch wird – siehe Bild 6.5.4.0. A3 ist dualkritisch; weil x*(3) ≥ -0,2 gelten muss, wird hier x(1, 1, 0) = -0,2 aktiv determiniert. A1 16 13,3 80 x=0 0 13,3 -0,525/-0,4/-0,375 f = 0.5 AKnN 0 A2 12 8 24 6,7 15 -025/ -0,8 /-0,25 A3 15 0 10 30 15 -0,2/ -0,2 /-0,2 x=1 Bild 6.5.4.0: Ressourceneinsatzoptimierung - Zeitnetz EKnN 15 134 Planung des Ressourceneinsatzes in Arbeitsabläufen A2 ist weiterhin out-of-kilter, wird aber jetzt zusammen mit A3 gekürzt. Die Kürzung endet – siehe Bild 6.5.5 – weil A2 seine Minimaldauer minD(2) = 8 erreicht. A1 16 13,3 0 13,3 80 x=0 -0,525/-0,4/-0,375 f = 0.5 AKnN 0 A2 12 8 24 EKnN 14,7 6,7 14,7 -∞/ -0,8 /-0,25 A3 15 10 30 0 14,7 -0,2/ -0,2/-0,2 x=1 Bild 6.5.5.0: Ressourceneinsatzoptimierung - Zeitnetz Die neue Lösung befindet sich im Gleichgewicht, ist also (lokal) optimal. Sie kostet Gesamtkosten ≈ 14,7·1 + 11·1 = 25,7. AKn(1) 0 Q(1) 0 AKn(2) 0 AKn(3) 0 x(1, 1, 1) = 6; f = 0,525 x(2, 2, 1) = 3; f = 0,25 x(3, 3, 1) ≈ 2; f = 0,2 EKn(1) -1 EKn(2) -1 Q(1) -1 EKn(3) -1 y(0, 0, 1) = 1, x(0, 0, 1) ≈ 11 Bild 6.5.5.1: Ressourcennetz zum Zeitnetz 6.5.5.0 Bild 6.5.5.2 demonstriert den Ressourceneinsatz wieder anschaulich durch Rechteck-Balken für jede Aktivität. Die Gesamtkosten für dieses Netz betragen jetzt: Gesamtkosten = (etN –petN)·cTN + (x(0, 0, 1) – kap(1))·cK(1) ≈ 14,7·1 + 11·1 = 25,7. Kapitel 6: Planung des Ressourceneinsatzes in Arbeitsabläufen 135 bed(t, 1) 11 10 A2 9 8 7 6 A1 5 4 3 2 1 A3 t 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Bild 6.5.5.2: Ressourceneinsatz zum Zeitplan gemäß Bild 6.5.5.0 6.2.2 Kostenminimierung des Ressourceneinsatzes – ein heuristischer Lösungsalgorithmus Die eigentliche Problematik des allgemeinen Ressourceneinsatzproblems besteht darin, dass Ressourcen genau dann von einer Aktivität Ai nach einer Aktivität Aj umgesetzt werden können, wenn at(j) ≥ et(i) gilt, aber at(j) ≥ et(i) muss im Zeitnetz nicht a priori als Restriktion vorgegeben sein. Folglich muss allgemein eine Umsetz-Restriktion gelten, die besagt, x(i, j, r) > 0 nur, wenn at(j) - et(i) ≥ 0 gilt: Umsetz-Restriktion: x(i, j, r) ≥ 0 und (at(j) - et(i))⋅x(i, j, r) ≥ 0 Diese für die Zulässigkeit einer Lösung notwendige Bedingung ist nichtlinear, und es gibt keine Möglichkeit, sie in einem konvexen oder gar linearen Modell anzunähern. Deshalb gehören Aufgaben der im Folgenden zu betrachtenden Klasse zu den NP-schwierigen Aufgaben, also zu Aufgaben, für die es bisher keinen befriedigenden Lösungsalgorithmus gibt. Auch wir können einen solchen natürlich nicht bieten, sondern wollen im Folgenden einen heuristischen Algorithmus diskutieren, der sich auf Strom-Spannungs-Optimierungen der oben beschriebene Art stützt, diese exakt löst und damit lokale Optima der Aufgabe liefert. Das Wesen der Heuristik besteht in der Auswahl der lokalen Optimierungen: Es wird eine geeignete Menge von Umsetzbogen gesucht; für deren Vertreter-Bogen im Zeitnetz (der eventuell erst neu eingeführt werden muss) wird dann at(j) ≥ et(i) gefordert, und danach werden die genauen Abstandwerte sowie die x(i, j, r)-Werte durch die oben demonstrierte lokale, exakte Strom-SpannungsOptimierung bestimmt. In unserem Beispiel könnte man – etwa bei der Betrachtung von Bild 6.5.5.2 – auf die Idee kommen, die Aktivitäten A3 und A2 in dieser Reihenfolge nacheinander auszuführen. Um die Wirksamkeit dieser Idee zu überprüfen, optimieren wir das Netz im Zustand des Bilds 6.5.5 in diesem Sinne – siehe die Bilder 6.6: Um x(3, 2, 1) > 0 zu realisieren, ist zunächst at(2) ≥ et(3) zu sichern, also ein neue Bogen [EKn(3), AKn(2)] in das Zeitnetz einzufügen und wie folgt in einen Gleichgewichtszustand zu bringen: 136 Planung des Ressourceneinsatzes in Arbeitsabläufen A1 16 13,3 80 0 13,3 -0,525 / x=0 -0,4 / -0,375 f = -0.5 AKnN 0 A2 12 6,65 A3 15 0 10 8 24 14,65 -∞/ -0,8- λ/ -0,25 EKnN 14,65 x = -λ 30 14,65 -0,2 / -0,2 / -0,2 x=1 Bild 6.6.1.0: Ressourceneinsatzoptimierung - Zeitnetz Der neue Bogen ist in einem unzulässigen Zustand, den wir durch x → -∞ (für y ≤ 0) wie üblich legitimieren könnten, wozu wir dem Bogen den Fluss x = -λ zuordnen, mit dem Ziel λ zu maximieren – siehe Bild 6.6.1.0. Im Bogen [EKn(3), EKnN] ist x = -0,2 + λ für λ > 0,2 unzulässig, weshalb A3 über den zugehörigen Cozyklusvektor zu verkürzen ist. Diese Transformation bricht bei den kritischen Wert d(3) = 10 zunächst ab – siehe Bild 6.6.2.0 – maximale Stromänderung über den Zyklus zum „spannungskritschen“ Bogen [AKn(3), EKn(3)]; „flusskritisch“ ist [EKn(3), EKnN], beide Bogen werden bezüglich Zugehörigkeit zum Gerüst getauscht. A1 16 13,3 80 0 13,3 -0,525 / x=0 -0,4 + 0,5λ / -0,375 f = -0.5 AKnN 0 A2 12 6,65 A3 10 7,5 0 10 30 8 14,65 24 -∞ / -1 / -0,25 EKnN 14,65 x = -0,2 - λ x=0 -0,4/-0,2-λ/-0,2 x=1 Bild 6.6.2.0: Ressourceneinsatzoptimierung - Zeitnetz Der neue Zustand ist nur für 0 ≤ λ ≤ 0,05 stabil, denn für λ > 0,05 würde A1 aus seinem Gleichgewichtszustand geraten (-0,525 ≤ -0,4 + 0,5λ ≤ -0,375), weshalb diese Aktivität über den zugehörigen Spannungs-Transformationsvektor zu verlängern ist. Die Verlängerung endet bei normDaktuell(1) = 16. Bild 6.6.3.0 zeigt den neuen Zustand. Kapitel 6: Planung des Ressourceneinsatzes in Arbeitsabläufen 137 A1 20 16 0 16 80 -0,375 / -0,375+0,5λ / -0,25 x=0 f = 0.5 AKnN 0 A3 10 7,5 A2 12 8 8 16 24 EKnN 16 -∞/ -1 / -0,25 x = -0,25 -λ 30 x=0 0 10 -0,4 /-0,25 -λ / -0,2 x=1 Bild 6.6.3.0: Ressourceneinsatzoptimierung - Zeitnetz Im Zustand von Bild 6.6.3.0 ist A3 für 0 ≤ λ ≤ 0,15 stabil. Für λ > 0,15 Kürzung von A3 auf d(3) = 8 - liefert den Zustand, den die Bilder 6.6.4.0 und 6.6.4.1 zeigen. Er ist stabil, also (lokal) optimal, so dass im Ressourcennetz (Bild 6.6.5.1) der Umsetzbogen [EKn(3), AKn(2)]1 eingeführt werden kann. A1 20 0 16 16 80 -0375/ -0,3 / -0,25 x=0 A2 12 f = 0.5 AKnN 0 8 A3 10 7,5 0 8 8 16 24 EKnN 16 -∞/ -1 / -0,25 30 x=0 -0,4 / -0,4 / -0,4 x=1 Bild 6.6.4.0: Ressourceneinsatzoptimierung - Zeitnetz AKn(1) 0 Q(1) 0 x(1, 1, 1) = 5 f = 0,375 EKn(1) -1 AKn(2) 0 x(2, 2, 1) = 3 f = 0,25 EKn(2) -1 AKn(3) 0 x(3, 3, 1) = 3,75 f = 0,4 EKn(3) -1 Q(1) -1 y(0, 0, 1) = 1, x(0, 0, 1) = 11,75 Bild 6.6.4.1: Ressourcennetz zum Zeitnetz 6.6.4.0 Eine Flussänderung im Basiszyklus zum Out-of-kilter-Bogen [EKn(3), AKn(2)]1 und eine anschließende Spannungsänderung über den Cozyklus zum flusskritischen Bogen [Q(1), AKn(2)]1 bringen das Gesamtnetz ins Gleichgewicht – Bilder 6.6.5.0 und 6.6.5.1. 138 Planung des Ressourceneinsatzes in Arbeitsabläufen A1 20 0 16 16 80 -0,375/ -0,3 / -0,25 x=0 A2 12 f = 0.5 AKnN 0 8 A3 10 7,5 0 8 8 24 16 -∞/ -1 / 0 EKnN 16 30 x=0 -0,4 / -0,4 / -0,4 x=1 Bild 6.6.5.0: Ressourceneinsatzoptimierung - Zeitnetz AKn(1) 0 AKn(2) -1 x(2, 2, 1) = 3 f = 0,25 EKn(2) -1 AKn(3) 0 x(3, 3, 1) = 3,75 f = 0,4 EKn(3) -1 x=0 Q(1) 0 EKn(1) -1 x(1, 1, 1) = 5 f = 0,375 Q(1) -1 y(0, 0, 1) = 1, x(0, 0, 1) = 8,75 Bild 6.6.5.1: Ressourcennetz zum Zeitnetz 6.6.5.0 bed(t, 1) 9 8 7 A3 A2 6 5 4 3 A1 2 1 0 t 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Bild 6.6.5.2: Ressourceneinsatz zu Bild 6.6.5.0 und 6.6.5.1 Bild 6.6.5.2 zeigt den neuen Ressourceneinsatzplan in anschaulicher Form. Seine Kosten betragen, Gesamtkosten = 16·1 + 8,75·1 = 24,75 (gegenüber 25,7 siehe oben), d.h. die Verbesserung ist nicht allzu groß aber deutlich, sie könnte noch etwas größer sein, wenn A2 von 3 Ressouceneinheiten ausgeführt werden könnte. Kapitel 6: Planung des Ressourceneinsatzes in Arbeitsabläufen 139 Am folgenden 2. Beispiel wird auf variable Aktivitätsdauer verzichtet, um die Umsetzproblematik schärfer zu fokussieren. Bild 6.7.1 zeigt ein Netz aus sechs Aktivitäten, die alle die Dauer minD = d = normD = 1 haben und alle eine Ressource R1 nutzen, aber mit verschiedenem Leistungsanspruch. Auf die Darstellung des Ressourcennetzes haben wir verzichtet, weil sein Informationsgehalt in diesem Fall gering ist. Wie im Beispiel 1 möge petN = 0, cTN = 1, kap(1) = 0, cK(1) = 1 gelten. Wir gehen vom Terminsystem der frühest-möglichen Termine aus, bei dem die Kosten 1·2 + 1·5 = 7 betragen, und betrachten die Ressourcenbedarfslinie: Zum Zeitpunkt t = 0 haben wir den stärksten Ressourcenbedarf bed(0, 1) = 5. Um die KapazitätsÜberschreitungskosten zu senken, müsste man eine der bei t = 0 beginnenden Aktivitäten verschieben. A1 ist dafür ungeeignet, weil mit ihr auch A4 verschoben wird und damit der Endtermin des Netzes, wodurch die eingesparten Kapazitäts-Überschreitungskosten durch Endtermin-Überschreitungskosten in gleicher Höhe (= 1) ersetzt würden. Verschieben wir A2 – Bild 6.6.2 - so wird durch die Folgeverschiebung von A5 und A6 auch der Netzendtermin um die Verschiebung verlängert, aber die Kapazitäts-Überschreitungskosten reduzieren sich um 2. Allerdings tritt eine neue Ressourcenbedarfsspitze der Größe bed(1, 1) = 4 jetzt bei t = 1 auf; Gesamtkosten = 1·3 + 1·4 = 7, also konstant. Eine zweite Verschiebung bei t = 1 würde, falls A2 verschoben wird, etN weiter verlängern und, falls A4 verschoben wird, die KapazitätsÜberschreitungskosten nicht reduzieren. Ai at(i) et(i) lstg(i, 1) Legende: A1 0 1 1 A4 bed(t, 1) 1 2 2 5 A1 4 A2 0 1 2 A5 1 2 1 A2 3 A4 2 A5 1 A3 0 1 2 A6 1 2 1 A3 A6 t 0 Bild 6.6.1: Ressourceneinsatzoptimierung - Beispiel 2 0 1 2 3 bed(t, 1) A1 0 1 1 A4 1 2 2 5 4 A2 0 1 2 A5 1 2 1 3 A4 A1 2 A5 1 A3 0 1 2 A6 1 2 1 Bild 6.6.2.: Ressourceneinsatzoptimierung - Beispiel 2 A3 A2 A6 t 0 0 1 2 3 Verschieben man dagegen im Ausgangszustand (Bild 6.6.1) A3 – Bild 6.6.3 – so wird zwar durch die Folgeverschiebung von A6 auch der Netzendtermin verlängert, und überdies reduzieren sich die Kapazitäts-Überschreitungskosten nicht – Spitze bed(1, 1) = 5 jetzt bei t = 1 – aber in einem weiteren Verschiebungsschritt (A3 → A4) kann man die Kapazitäts-Überschreitungskosten ohne weitere 140 Planung des Ressourceneinsatzes in Arbeitsabläufen Verlängerung des Netzendtermins auf 3 reduzieren, wodurch man die Gesamtkosten = 1·3 + 1·3 = 6 reduziert. Ersichtlich hat man damit das globale Optimum erreicht. bed(t, 1) 5 4 bed(t, 1) A4 3 3 2 A2 A3 A1 A5 2 A2 A3 A4 A1 A5 A6 1 1 A6 t 0 0 1 2 3 t 0 0 1 2 3 Bild 6.6.3: Ressourceneinsatzoptimierung - Beispiel 2 Das Beispiel ist geeignet, das Prinzip des Lösungsalgorithmus zu erkennen: 1. Ausgehend von einer Lösung der lokalen Aufgabe, werden die Ressourcenbedarfslinien von t = 0 bis t = etN aufgestellt und durchmustert: 2. Man suche die Ressource Rr* und den Zeitpunkt t*, für die bed(t*, r*) maximal ist. 3. Vorausgesetzt bed(t*, r*) > 0: Man bestimme alle Aktivitäten Ai, für die at(i) = t* gilt. 4. Unter den ausgewählten Aktivitäten lege man diejenige fest, Aj*, deren Verschiebung nach rechts am wirkungsvollsten erscheint. 5. Man suche unter den Aktivitäten Ai, für die at(i) ≤ t* und i ≠ j* gilt, einen geeigneten Partner Ai*, so dass Ai* → Aj* (at(j*) ≥ et(i*)) wirkungsvoll bezüglich einer Kostensenkung scheint. 6. Man installiere, sofern noch nicht vorhanden, im Zeitnetz den Bogen [EKn(i*), AKn(j*)] und in den Ressourcennetzen die Bogen [EKn(i*), AKn(j*)]r. 7. Man löse die neue lokale Aufgabe. Zur Verdeutlichung noch einmal der Blick auf das obige Beispiel 2: Bild 6.6.1 skizziert die optimale Lösung der lokalen Anfangsaufgabe. Es gilt, bed(0, 1) = 5 ist maximal (t* = 0, r* = 1). Für A1, A2 und A3 gilt at(i) = 0. A2 und A3 sind für eine Verschiebung geeigneter als A1, weil sie jeweils zwei statt einer Ressourceneinheiten abbauen. A3 scheint geeigneter als A2, weil von ihrer Verschiebung nur ein Nachfolger (A6) statt zwei (A5 und A6) betroffen sind. Folglich legen wir j* = 3 fest. A1 und A2 kommen als Vorläufer in Betracht; i* = 2 erscheint, wegen des gleichen Ressourcenbedarf wie A3, geeigneter als i* = 1. Bogen [EKn(2), AKn(3)] wird ins Zeitnetz und Bogen [EKn(2), AKn(3)]1 ins Ressourcennetz eingearbeitet – das bedeutet, A3 wird hinter A2 verschoben; es entsteht die Situation, die das linke Teilbild von Bild 6.6.3 zeigt. Der Algorithmus wird erneut ausgeführt: Es gilt, bed(1, 1) = 5 ist maximal (t* = 1, r* = 1). Für A1, A3 und A4 gilt at(i) = 1. A3 und A4 sind für eine Verschiebung geeigneter als A1, weil sie jeweils zwei statt einer Ressourceneinheiten abbauen. A4 scheint geeigneter als A3, weil von ihrer Verschiebung kein Nachfolger betroffen ist. Folglich legen wir j* = 4 fest. A1 und A3 kommen als Vorläufer in Betracht; i* = 3 erscheint, wegen des gleichen Ressourcenbedarfs wie A4, geeigneter als i* = 1. Bogen [EKn(3), AKn(4)] wird ins Zeitnetz und Bogen [EKn(3), AKn(4)]1 ins Ressourcennetz eingearbeitet – das bedeutet, A4 wird hinter A3 verschoben, es entsteht die Situation die das rechte Teilbild von Bild 6.6.3 zeigt. Ein weiterer Abbau der ausführenden Ressourceneinheiten ist nicht sinnvoll, denn ein Gesamtarbeitsvolumen von 9 Zeit- mal Ressourceneinheiten erfordert bei 2 Ressourceneinheiten pro Zeiteinheit wenigstens 4,5 Zeiteinheiten, d.h. mindestens 6,5 Geldeinheiten Kosten statt der erreichten 6 Geldeinheiten. Die Lösung ist ersichtlich global optimal. Kapitel 6: Planung des Ressourceneinsatzes in Arbeitsabläufen 141 Im folgenden heuristischen Algorithmus ist es unser Ziel, durch sukzessive Einfügung jeweils einer Umsetz-Restriktion die Ergebnisse einer lokalen Optimierung so zu verbessern, dass sie als global optimal erkennbar sind oder zumindest den Nutzer befriedigen. Die neue Umsetz-Restriktion wird durch Abschätzungen gemäß dem oben angegebenen Lösungsprinzip bestimmt. Die Heuristik dieses Prinzips erkennt man schon an Formulierung wie, „…am wirkungsvollsten erscheint …“, „…einen geeigneten Partner …“ und „…wirkungsvoll bezüglich einer Kostensenkung scheint …“. Diese Formulierungen folgen daraus, dass man in der lokalen Situation, in der man sich befindet, globale Einschätzung treffen möchte, aber aus Rechenzeitgründen dies nicht sinnvoll ist. Ein Algorithmus muss natürlich präzis ausführbare Anweisungen enthalten. Dazu betrachten wir die algorithmischen Schritte mit unscharfen Formulierungen genauer: Zunächst halten wir fest: Das lokale Optimum, von dem wir ausgehen, ordnet jeder Aktivität Ai einen Anfangstermin at(i) und eine Dauer d(i) zu. Diese Werte stellen insofern Minimalwerte dar, als dass die Unterschreitung eines at(i)-Wertes, sofern sie überhaupt möglich ist, nur durch Kürzung anderer Aktivitäten erreichbar ist, und Kürzung einer Aktivitätsdauer erhöht die Kosten der Ressourcennutzung – wir befinden uns in einem lokalen Optimum – zu einem Zeitpunkt, der vor dem betrachteten t* liegt. Daher werden generell nur „Rechts“-Verschiebungen von Aktivitäten betrachtet, also Vergrößerungen der aktuellen at(i)-Werte. Die Heuristik beginnt im Teilschritt 3, indem als Verschiebungskandidaten nur Aktivitäten zugelassen werden, die bei t = t* beginnen. Es ist durchaus nicht sicher, dass die Rechtsverschiebung einer Aktivität Ai mit at(i) < t* eine höhere Verschiebungen der Gesamtzeit verursacht als die der betrachteten Aktivitäten, aber die Rechtsverschiebung einer solchen Aktivität verringert mit Sicherheit die Ressourcenauslastung im Zeitraum [at(i), t*), woraus die Erwartung der schlechteren Gesamtauslastung der Ressourcen folgt. Am problematischsten ist die Entscheidung im Teilschritt 4: Unter reinem Projektzeitaspekt gilt für die Konkurrenz zweier Aktivitäten Ai und Aj die Regel, Ai vor Aj, falls (at(i) – nl(i)) < (at(j) – nl(j)) gilt, wobei nl(i) („Nachlauf“) die Zeit angibt, die nach Beendigung von Ai bis zum Projektende noch mindestens erforderlich ist. Diese Zeit – die Länge eines längsten Weges vom Endknoten EKn(i) der Aktivität Ai zum EKnN – ist leicht einmalig zu berechnen. Aber schon das obige Beispiel 2 zeigt, dass das Kriterium nicht ausreicht: In der im Bild 6.6.1 gezeigten Situation reduzieren die Verschiebungskandidaten A2 und A3 den lokalen Ressourcenbedarf um 2, während A1 ihn nur um 1 reduziert, so dass es sinnvoll erscheint, nur zwischen A2 und A3 zu entscheiden. Aber beide haben die gleiche Nachlaufzeit: nl(2) = nl(3) = 1. 6.2.3 Rechentechnische Realisierung Grundvoraussetzung für eine effiziente Ausführung des Algorithmus im Computer sind geeignete Datenstrukturen. Die grundlegende Datenstruktur für die Aufgaben, die wir in den Kapiteln 5 und 6 behandelt haben, ist der Netzplan. Für die zuletzt behandelte Aufgabe besteht der Netzplan aus einem „Zeitnetz“ und mehreren „Ressourcennetzen“, und auf diese Aufgabe mit dem höchsten Allgemeinheitsgrad wollen wir die Datenstruktur auch abstimmen. Wir haben gesehen, dass alle Teilnetze eines Netzplans eine feste Grundstruktur besitzen, nämlich • einen Quellknoten • einen Senkenknoten • Anfangs- und Endknoten für jede Aktivität, die zum Netz gehört • einen Netzbogen vom Quell- zum Senkenknoten im Zeitnetz und vom Senken- zum Quellknoten in jedem Ressourcennetz • zu jeder im Netz vertretenen Aktivität einen Aktivitätsbogen vom Anfangsknoten zum Endknoten der Aktivität • diverse Verbindungsbogen, die im Zeitnetz zeitliche Mindestabstände repräsentieren, während sie in den Ressourcennetzen immer vom Endknoten einer Aktivität zum Anfangsknoten einer anderen Aktivität führen und das Umsetzen von Ressourceneinheiten repräsentieren vgl. Bild 6.2. Im Hinblick auf diese Struktur führen wir die Datenstruktur „Plannetz“, kurz: PNetz ein: public class PNetz extends Graph { … } 142 Planung des Ressourceneinsatzes in Arbeitsabläufen Sie wird als Erweiterung der schon im Kapitel 1 gegebenen Datenstruktur Graph eingerichtet, um deren Basisalgorithmen zu nutzen: public PNetz(int resNr, int aktAnz, int bgAnz, Netzplan mttr) { super(2*(aktAnz+1),4*aktAnz+1+bgAnz); … } Jedes der betrachteten Netze besitzt maximal 2(aktAnz+1) Knoten, wenn aktAnz die Anzahl der in ihm enthaltenen Aktivitäten ist. Die Anzahl der Bogen beträgt (3aktAnz+1) + bgAnz, wenn bgAnz die Anzahl der Abhängigkeitsbogen im Zeitnetz bezeichnet, während in den Ressourcennetzen zunächst bgAnz = 0 gilt. Während der Ressourceneinsatzoptimierung können in allen Netzen Umsetzbogen hinzugefügt werden. Es erscheint realistisch, deren Maximalanzahl durch aktAnz abzuschätzen. Daraus ergibt sich der oben angeführte Aufruf des von Graph geerbten Konstruktors. Der Netzplan repräsentiert eine Verflechtung von Aktivitäten. Es ist daher nahe liegend, eine Datenstruktur Aktivitaet einzurichten: public class Aktivitaet extends Elementtyp { String schlNr, bez; double minD, normD, cDOrig, cD, cT,d=normD, fat, pet, set, xKopp, dxKopp; ResAngabe[] resBed; // Volumenangaben für r=0, ..., resAnzG-1 int aktBg; // Index des Aktivitätsbogens in netze[0] int bilRes =0; // Index der aktuellen Bilanzress int bilResBg=0; // Index des aktBg im Netz[bilRes] public Aktivitaet(String schlNr, String bez, int normD, int minD, double cD, int fat, int pet, double cT, int set) { … } Diese Datenstruktur speichert die Parameterwerte, die die Aktivität kennzeichnen (schlNr, bez, minD, normD, cDOrig, cT, fat, pet, set), zur Aktivität gehörende Variablen (d, xKopp, dxKopp) und einige weitere Größen, die zur Orientierung innerhalb der Datenstruktur Netzplan nötig sind. Die Datenstrukturen Netzplan, Aktivitaet und andere sind für den eigentlichen Verarbeitungsprozess nötig. Die langfristige Haltung von Datenmengen dieser Größe und Komplexität erfolgt über Files. Ein Netzplanfile kann als spezieller Vector, genannt Netzdatei, angesehen werden. Die Elemente dieses Vector sind vom Typ Netzdateisatz, der neben den bekannten Parameterwerten der Aktivität ihre Abhängigkeiten von anderen Aktivitäten in Form eines Vector aus Abhaengigkeit sowie ihren Ressourcenbedarf in Form eines Vector aus Ressourcenangaben vom Typ ResAngabe enthält: public class Abhaengigkeit { String vl; // Vorläufer-Schlüsselnummer int typ=0; int dauerProz=100; int festAbstd=0; public Abhaengigkeit() { } } public class ResAngabe { String resNr; double umf; public ResAngabe() { } } Kapitel 6: Planung des Ressourceneinsatzes in Arbeitsabläufen 143 Bei der Konstruktion der Datenstruktur Netzplan wird jeder Satz dieser Netzdatei (Netzdateisatz) in eine Aktivitaet überführt; damit verbunden werden die Netze aufgebaut: netze[r] (vom Typ PNetz) für r = 0, 1, …, bilResAnz (bilResAnz = Anzahl der zu bilanzierenden Ressourcen). Das Netz netze[0] ist das Zeitnetz. Das Netz netze[r] einer zu bilanzierenden Ressource r >0 enthält nur die Aktivitäten, die einen von Null verschiedenen Bedarf an der Ressource haben. Die Teilnetze sind weitestgehend selbständig. Die Gesamtheit aller Ressourcen wird wie der Netzplan langfristig als File – Typ Ressdatei - gehalten, das wir als Vector aus Ressourcen ansehen können: public class Ressource { public String schlNr, bez, mass; public int typ; public double kap, cKap, cStill; public Ressource() { } … } Diese Ressdatei enthält alle in der Netzdatei genannten Ressourcen, auch die Verbrauchsressourcen. Die Anzahl ihrer Datensätze beträgt resAnzRD (= Anzahl der in der Netzdatei genannten Ressourcen). Die Ressourcen, die in die Optimierung einbezogen werden sollen – wir sagen auch, die „bilanziert“ werden – werden in einem Vector bilResNrn aufgezählt. Dieser Vector wird interaktiv bei der Auftragserteilung für die Optimierung aufgebaut. Folglich hat der Konstruktor für einen Netzplan die folgende Gestalt: public Netzplan(Netzdatei nd, Vector bilResNrn) { … }. Es werden nur für die zu bilanzierenden Ressourcen Netze aufgebaut. Um der Problematik parallel arbeitender Ressourcen aus dem Weg zu gehen, wurde in der realisierten Version der Ressourceneinsatzoptimierung unterstellt, dass jede Aktivität höchstens eine dieser Ressourcen beansprucht. Aus der Sicht des Netzplans ist ein Bogen Bogen in einem der Teilnetze und muss folglich durch einen Typ BgNr angesprochen werden: public class BgNr { public int netz=0; public int bg=0; public BgNr() { } public BgNr(int nN, int bN) { netz=nN; bg=bN; } public boolean equals(BgNr bN) { if (bN==null) return false; return bN.netz==netz && bN.bg==bg; } } Neben der Bogenkopplung innerhalb netze[0] kann eine Kopplung des Aktivitätsbogens aus netze[0] mit einem Aktivitätsbogen in netze[bilRes] existieren. Um mit dieser Kopplung arbeiten zu können, ist in der Datenstruktur Aktivitaet neben bilRes die Nummer bilResBg des Aktivitätsbogens in netze[bilRes] vermerkt. Das Datenstrukturproblem für die Kopplung der Aktivitätsbögen der Teilnetze wird im Sinne einer Verkettung gelöst: An der Aktivität wird die zu bilanzierende Ressource explizit genannt: bilRes ist ihr Index im Vector bilResNrn und bilResBg dazu die Bogennummer/Index im Netz netze[bilRes]. 144 Planung des Ressourceneinsatzes in Arbeitsabläufen 5 3 4 3 9 2 5 6 7 6 4 8 1 2 4m-2 4m+1 2n+1 4m-1 4m 2n+2 1 Bild 6.7: Computerinterne Knoten- und Bogennummerierung im PNetz Literatur 145 Literatur [Be/Gh] [Nä/St] [Noz] [Sch] [Wa/Nä] Berge, C.; Ghouila-Houri, A.: Programme, Spiele, Transportnetze. Leipzig: Teubner, 1967 Nägler, G.; Stopp, F.:Graphen und Anwendungen. Stuttgart; Leipzig: Teubner, 1996 Nožička, F.; Guddat, J.; Hollatz, H.; Bank, B.: Theorie der linearen parametrischen Optimierung. Berlin: Akademie-Verlag, 1974 Schumann, F.: Software zur Lösung von Transportaufgaben. Diplomarbeit, vorgelegt an der HTWK Leipzig, IMN; Leipzig 2002 Walther, H.; Nägler, G.: Graphen Algorithmen Programme. Wien; New York: Springer, 1987 Stichwortverzeichnis ABg(Kn) 7 adjazent 6 AKn(Bg) 6 Aktivität 66 Anfangsknoten 6 Ausgangsbogen 6 einer Knotenmenge 16 eines Knotens 6 Basiscozyklus 17 Basislösung 46, 67, 79 Basiszyklus 15 Baum 11 BFS(int Start) 20 Binärbaum 12 vollständiger 13 Blatt Siehe Wurzelbaum, 12 Bogenliste 6 Bogenvektor 15 Branch-and-Bound-Verfahren 58 Breitensuche 20 Char(x(k)) 47 Charakteristik 47, 67 Cogerüst 14 Coyzklus 16 elementarer 16 cz(k) 17 CZ(K) 16 DFS(int Start) 20 Digraph 7 Dijkstra-Algorithmus 26 Dualitätssatz 46, 67, 79 eABg(i) 8 EBg(Kn) 7 Eckpunktlösung 45, 67 eEBg(i) 8 Eingangsbogen 6 einer Knotenmenge 16 eines Knotens 6 eInzBg(i) 8 EKn(Bg) 6 Endknoten 6 eNetz 25 Ereignis 31, 66 erreichbar 11 Erreichbarkeitsbaum 20 Etage Siehe Wurzelbaum, 12 etN 68 f(k) 76 Fluss 42 Gegenbogen 7 geplanten Endtermin 68 Gerüst 14 zur Startlösung 81 Gleichgewichtsgraph 67 Graph 8 Greedy-Prinzip 36 gross 74 Höhe Siehe Wurzelbaum, 12 InzBg(Kn) 7 inzident 6 istBg(k) 8 Kante 7 unabhängige 22 Kapazität eines Schnitts 51 Kette 10 alternierende 22 elementare 10 geschlossene 10 kFlusskrit 48, 69, 81 146 Sachwortverzeichnis Kirchhoffscher Knotensatz 42 Kirchhoffscher Maschensatz 43 Knappsackproblem 34 Knoten 6 exponierter 22 innerer Siehe Wurzelbaum, 12 Knotenliste 6 Komponente 11 stark zusammenhängende 22 zusammenhängende 21 kOut 48, 81 Kreis 10 negativer Länge 28 positiver Länge 32 kreisfrei 22 kSpannkrit 48, 69, 81 kuerzesteWege(int Start) 27 kürzeste Wege Algorithmus 26 Aufgabe 25 Kürzungspreis 66 laengsteWege() 33 längste Wege 31 Algorithmus 31 linker Nachbarknoten 7 Maximalfluss-Algorithmus 51, 54 Maximumpaarung 22 Algorithmus 23 Mehrgütertransport 41 Minimaldauer 66 Minimalgeruest() 36 Minimalgerüst 36 Minimalkosten-Stromproblem 39 MKSK 81 nABg(k) 8 Nachbarknoten des Knotens 7 nEBg(k) 8 negative Bogenbenennungen 7 Netzplan 31 Netzplantechnik 31 nInzBg(k) 8 Normaldauer 66 Optimalwertfunktion 60 Ordnung eines Knotens Siehe Wurzelbaum, 12 eines Wurzelbaums 12 topologische 31 out-of-kilter 48, 67 parallele Bogen 6 Partner(k) 76 pEtN 68 Potential 25 zugehöriges 81 Prioritätsheap 27 Projektdauer-Kosten-Funktion 72 rechter Nachbarknoten 7 Rückkehrbogen 38 Rundreiseproblem 57 Sammler 77 schlicht 6 Schlinge 7 Schnitt 16 setzWrz(i)) 18 Sohn Siehe Wurzelbaum, 12 Spannung 17 Stabilitätsintervall 60 stark zusammenhängend 11 Strom 15, 42 Stützbogen 18 Stützgerüst 11 Stützrichtung 18 StzBg(i) 18 StzRchtg(k) 18 tauschStzBg(kAlt, kNeu) 18 Tiefensuche 20 tOrd() 32 Ug(K') 14 ungerichteter Graph 7 Untergraph 14 Vater Siehe Wurzelbaum, 12 Verteiler 78 Weg 10 WrzBg 18 Wurzel 12 Wurzelbaum 11 60 X(k, λ) x(λ) 60 Zirkulation 42 zusammenhängend 11 Zyklus 10 Sachwortverzeichnis 147