The Kilter Project Anforderungs- und Designspezifikation, 1.0 Verfasser: Susann Döring Martin Nguyen Andre Hagemeier Dmytro Malinov Stephan Krug Frederik Knust Status: Datum: © Prof. Dr. M. Rezagholi Abgeschlossen 14/05/2016 Anforderungs- und Designspezifikation The Kilter Project Dokumentenverwaltung Dokument-Historie Version Status Datum Verantwortlicher 0.1 Erstellung 19.01.2010 Susann Döring - 0.2 In Bearbeitung 29.01.2010 Susann Döring Beschreibung des Algorithmus eingefügt 0.3 In Bearbeitung 29.01.2010 Andre Hagemeier Einfügen des Sequenzdiagramms und erste Überprüfung 0.4 In Bearbeitung 02.02.2010 Martin Nguyen Anpassung der Beschreibung des Algorithmus 0.5 In Bearbeitung 02.02.2010 Susann Döring Änderung des Sequenzdiagramms 0.6 In Bearbeitung 09.02.2010 Dmytro Malinov Änderung Pseudocode 1.0 Abgeschlossen 09.02.2010 Stephan Krug, Frederik Knust Dokument wurde mit folgenden Tools erstellt: Microsoft Office Word OpenOffice.org Draw StarUML Diagramm3 Seite 2 / 19 Änderungsgrund Review Anforderungs- und Designspezifikation The Kilter Project Inhaltsverzeichnis 1 1.1 1.2 1.3 1.4 Einleitung ..................................................................................................................... 4 Zweck des Dokuments.............................................................................................. 4 Gültigkeit des Dokuments ......................................................................................... 4 Begriffsbestimmungen und Abkürzungen ................................................................. 4 Zusammenhang mit anderen Dokumenten ............................................................... 4 2 2.1 2.2 2.3 2.4 2.5 2.6 Allgemeine Beschreibung der gewünschten Software............................................. 4 Zweck der gewünschten Software ............................................................................ 4 Überblick über die geforderte Funktionalität .............................................................. 4 Abgrenzung und Einbettung der gewünschten Software ........................................... 5 Allgemeine Einschränkungen.................................................................................... 5 Vorgaben zu Hardware und Software ....................................................................... 5 Anforderungsquellen / Zielgruppen ........................................................................... 5 3 Detaillierte Beschreibung der Anforderungen (Leistungsmerkmale) ...................... 5 3.1 Lieferumfang ............................................................................................................. 5 3.2 Abläufe (Szenarien) von Interaktionen mit der Umgebung ........................................ 5 3.3 Geforderte Funktionen des Produkts ........................................................................ 6 3.4 Struktur und Verhalten der Software ......................................................................... 6 3.4.1 Beschreibung des Out-of-Kilter Algorithmus .................................................... 6 3.4.1.1 Allgemeine Beschreibung des Algorithmus ............................................. 6 3.4.1.2 Eröffnungsalgorithmus ............................................................................ 7 3.4.1.3 Out-of-Kilter Algorithmus ........................................................................ 7 3.4.2 Pseudocode..................................................................................................... 9 3.4.3 Sequenzdiagramm......................................................................................... 16 3.5 Schnittstellen der gewünschten Software................................................................ 17 3.6 Zu berücksichtigende Normen ................................................................................ 17 3.7 Qualitätsanforderungen / sonstige entwicklerorientierte Anforderungen .................. 17 4 4.1 4.2 4.3 4.4 4.5 Vorgaben des Auftraggebers an die Projektabwicklung ........................................ 17 Anforderungen an die Realisierung ......................................................................... 17 Abnahmebedingungen ............................................................................................ 17 Fertige und zugekaufte Komponenten .................................................................... 18 Lieferbedingungen .................................................................................................. 18 Gewährleistung ....................................................................................................... 18 5 Durchführbarkeitsuntersuchungen.......................................................................... 18 6 Bewertung der Anforderungen................................................................................. 18 7 Verpflichtungen des Auftraggebers ......................................................................... 18 8 Literaturverweise....................................................................................................... 18 9 Anhang ....................................................................................................................... 19 Seite 3 / 19 Anforderungs- und Designspezifikation The Kilter Project 1 Einleitung 1.1 Zweck des Dokuments In diesem Dokument wird die zu entwickelnde Anwendung beschrieben, das heißt, es wird der Zweck, die einzelnen Funktionen sowie die Schnittstelle der Anwendung beschrieben. Außerdem wird auf die Struktur der Anwendung und der darin vorhandenen Komponenten eingegangen. Ebenso wird der Out-of-Kilter Algorithmus in seiner Funktionsweise und seinem Ablauf beschrieben. Damit werden sowohl dem Auftraggeber als auch dem Projekt-Team der Anwendungsumfang und die Anwendungsalternativen verdeutlicht. Adressatenkreis dieses Dokuments ist somit der Auftraggeber und Auftragnehmer. 1.2 Gültigkeit des Dokuments Dieses Dokument gilt nur für das Teilprojekt „The Kilter Project“. Dieses Teilprojekt ist dem Projekt „Optimization & Visualization“ zugeordnet. 1.3 Begriffsbestimmungen und Abkürzungen Nicht relevant. 1.4 Zusammenhang mit anderen Dokumenten Es existiert kein Zusammenhang zu anderen Dokumenten, da sich das Teilprojekt lediglich mit der Entwicklung einer Anwendung, die den Algorithmus „Out-of-Kilter“ umsetzt, befasst. Somit wird kein System aufgesetzt oder eine Benutzerschnittstelle implementiert. Ein Lastenheft wurde zudem nicht vom Auftraggeber angefertigt. 2 Allgemeine Beschreibung der gewünschten Software 2.1 Zweck der gewünschten Software Die Anwendung soll an Hand des Out-of-Kilter Algorithmus in einem kapazitierten gerichteten Netzwerk den kostenminimalen Fluss identifizieren. Nach Übergabe der erforderlichen Daten, wie Knoten und Kanten mit ihren entsprechenden Eigenschaften, aus der Benutzerschnittstelle über eine definierte Schnittstelle, wird die Anwendung das gegebene Netzwerk nach dem Out-of-Kilter Algorithmus optimieren. Die Ergebnisse inklusive der Zwischenergebnisse werden an die Benutzerschnittstelle über eine definierte Schnittstelle übergeben. 2.2 Überblick über die geforderte Funktionalität Funktionen der Anwendung: Aufnahme der Ausgangswerte von der Benutzerschnittstelle über eine definierte Schnittstelle Netzwerkoptimierung, das heißt den kostenminimalen Fluss in gerichteten kapazitierten Netzwerken nach dem Out-of-Kilter Algorithmus identifizieren Übergeben der Ausgabewerte pro Iteration an die Benutzerschnittstelle über eine definierte Schnittstelle Fehlerhafte Ausgangswerte werden abgefangen und an die GUI übergeben Nicht durch die Anwendung umgesetzte Funktionen: Benutzerschnittstelle für die Eingabe der Ausgangswerte zur Verfügung stellen Darstellung der Ausgabewerte der Anwendung in einer Benutzerschnittstelle Speicherung der Zwischenergebnisse und des Endergebnisses Darstellung der Fehler über eine Fehlermeldung Seite 4 / 19 Anforderungs- und Designspezifikation 2.3 The Kilter Project Abgrenzung und Einbettung der gewünschten Software Die Anwendung erhält die Ausgangswerte des Netzwerkes, das heißt die Knoten und Kanten mit den entsprechenden Eigenschaften, aus einer GUI über eine Schnittstelle. Die Anwendung berechnet schrittweise die optimale Lösung zur Netzwerkoptimierung an Hand des Out-of-Kilters. Die Ausgabewerte werden pro Schritt an die GUI Oberfläche übergeben, wo sie grafisch dargestellt werden. Dabei ist die GUI für die grafische Darstellung des Netzwerkes verantwortlich. Die Entwicklung dieser Benutzerschnittstelle wird durch das Teilprojekt „The Kilter Project GUI“ umgesetzt. Für die Speicherung der Zwischenergebnisse sowie des Endergebnisses der Netzwerkoptimierung ist ebenfalls dieses Teilprojekt verantwortlich. Am Ende des Teilprojekts „The Kilter Project“ wird die entwickelte Anwendung an das Teilprojekt „The Kilter Project GUI“, welches für die Entwicklung der GUI verantwortlich ist, übergeben. Die Anwendung wird dann in die Anwendung des Teilprojekts „The Kilter Project GUI“ integriert. 2.4 Allgemeine Einschränkungen Die GUI Oberfläche ruft zur Übergabe der Ausgangwerte die Methode initialize() in der Anwendung auf. Dieser Methode werden alle Knoten und Kanten mit ihren Eigenschaften übergeben. Zur Darstellung der Zwischenergebnisse und des Endergebnisses wird eine Methode iterationCompleted() innerhalb der GUI aufgerufen. 2.5 Vorgaben zu Hardware und Software Java Programmierung Java Runtime Environment Keine Vorgaben zu Hardware, da nicht relevant 2.6 Anforderungsquellen / Zielgruppen Auftraggeber: VWA Württembergische Verwaltungs- und Wirtschafts-Akademie e.V. Stuttgart Betreiber von: Stromnetzen Wassernetzen Datennetzen (IT) die an der Optimierung ihres Netzwerkes nach dem Out-of-Kilter Algorithmus interessiert sind. 3 Detaillierte Beschreibung der Anforderungen (Leistungsmerkmale) 3.1 Lieferumfang Projektergebnis: Bibliothek, die Methoden zum Berechnen des Out-of-Kilter Algorithmus bereitstellt Hauptfunktionalität: Netzwerkoptimierung nach dem Out-of-Kilter Algorithmus, das heißt für gerichtete, kapazitierte Netzwerke wird der kostenminimale Fluss zum Ausgleich des Netzwerkes berechnet. 3.2 Abläufe (Szenarien) von Interaktionen mit der Umgebung Use Case: Netzwerk optimieren nach dem Out-of-Kilter Algorithmus Seite 5 / 19 Anforderungs- und Designspezifikation The Kilter Project Anwendung zur Netzwerkoptimierung nach dem Out-of-Kilter Algorithmus Netzwerk optimieren GUI Oberfläche 3.3 Geforderte Funktionen des Produkts Bezeichnung Zusammenfassung Akteure Vorbedingung Ablaufbeschreibung Verwendungen (IncludeBeziehungen) Erweiterungen (ExtendBeziehungen) Alternativen Nachbedingung Fehlschlag 3.4 3.4.1 Netzwerk optimieren Der Anwendungsfall optimiert das Netzwerk nach dem Out-of-Kilter Algorithmus. Die Optimierung erfolgt schrittweise, wobei die Zwischenergebnisse und das Endergebnis an die GUI Oberfläche übergeben werden. Die GUI löst den Anwendungsfall durch Aufrufen einer Methode aus. Dabei übergibt die GUI Oberfläche die Ausgangswerte in Form von Knoten und Kanten Objekten mit dazugehörigen Eigenschaften. Weiterhin werden der GUI Oberfläche die Zwischenergebnisse und das Endergebnis zur grafischen Darstellung übergeben. GUI Oberfläche löst den Anwendungsfall durch Aufrufen einer Methode initialize() aus. GUI Oberfläche übergibt die Objekte Knoten und Kanten mit den dazugehörigen Eigenschaften. siehe Sequenzdiagramm Keine Keine Keine Der Anwendungsfall übergibt schrittweise die Zwischenergebnisse zur Optimierung des Netzwerkes an die GUI Oberfläche, genauso wie das Endergebnis. Dies geschieht wiederum durch Aufrufen der Methode IterationCompleted (), die die Knoten und Kanten Objekte mit ihren geänderten Eigenschaften übergibt. Keine Übergabe der Zwischenergebnisse und des Endergebnisses an die GUI Oberfläche. Struktur und Verhalten der Software Beschreibung des Out-of-Kilter Algorithmus 3.4.1.1 Allgemeine Beschreibung des Algorithmus Der Ausgangspunkt der Problemlage ist ein asymmetrisches Netzwerk aus Knoten und Verbindungen. Asymmetrisch bedeutet, dass die Verbindungen, die von einem Knoten zu Seite 6 / 19 Anforderungs- und Designspezifikation The Kilter Project einem anderen gehen, nur in eine Richtung laufen. Über diese Verbindungen kann nur eine bestimmte Menge an Fluss transportiert werden, das heißt sie besitzen jeweils Mindest- und Maximalkapazitäten. Darüber existieren für jede Verbindung spezifische Transportkosten für jede Flusseinheit. Zusätzlich besitzen die Knoten bestimmte Kapazitäten. Das Ziel des Algorithmus ist nun der Ausgleich von Über- und Unterkapazitäten der Knoten durch einen kostenminimalen Fluss. Voraussetzung für das Funktionieren des Algorithmus ist die Vorgabe eines Netzwerkes, in welchem überhaupt ein zulässiger Zirkulationsfluss existieren kann. Der Gesamtalgorithmus besteht aus zwei Unteralgorithmen, dem Eröffnungsalgorithmus und dem Out-of-Kilter Algorithmus. Der Eröffnungsalgorithmus sorgt dafür, dass in dem vorgegebenen Netzwerk die Knotenkapazitäten ausgeglichen werden. Ist dies nicht möglich, wird eine Näherungslösung gesucht. Die gefundene Lösung, welche bis dahin weder Kosten noch Verbindungskapazitäten berücksichtigt, wird an den Out-of-Kilter Algorithmus übergeben, welcher den Fluss dahingehend modifiziert, dass der gesamte Zirkulationsfluss erstens zulässig (das heißt innerhalb der Kapazitätsgrenzen der Verbindungen) und zweitens kostenminimal wird. Die Knotenkapazitäten werden durch den Out-of-Kilter Algorithmus nicht mehr verändert, so dass sichergestellt wird, dass der anfangs berechnete ausgeglichene Zustand der Knotenkapazitäten erhalten bleibt. Im Folgenden werden die Algorithmen grob erklärt, der tatsächliche Ablauf wird anschließend als Pseudocode dargestellt. Dies kann im Detail auch etwas von der folgenden Beschreibung abweichen, um eine leichter zu programmierende Lösung zu erreichen (z. B. Vermeidung des Terms „unendlich“). 3.4.1.2 Eröffnungsalgorithmus Der Eröffnungsalgorithmus beginnt damit, die Summe aller Knotenkapazitäten der Bedarfsund Angebotsknoten zu berechnen. Ist die Summe ungleich Null, wird ein Hilfsknoten mit der entsprechenden Kapazität und Verbindungen erstellt, der dafür sorgt, dass die Kapazitäten am Anfang ausgeglichen werden.1 Dieser Hilfsknoten mitsamt seiner Verbindungen wird unmittelbar vor Abschluss des Algorithmus, das heißt vor der Rückgabe des Endergebnisses, gelöscht. Ist die Summe der Knotenkapazitäten gleich Null, muss kein Hilfsknoten erstellt werden. Die Kosten der Verbindungen des Hilfsknoten müssen höher als die Kosten der „echten“ Verbindungen gewählt werden, sodass der Hilfsknoten tatsächlich nur für den Ausgleich der Über- bzw. Unterkapazitäten genutzt wird. An diesem Punkt beginnt der Ausgleich der Knotenkapazitäten. Folgender Vorgang wird durchgeführt, bis alle Knotenkapazitäten gleich Null sind: Es wird ein beliebiger Knoten mit Überschuss ausgewählt. Nun wird ein beliebiger Knoten mit Nachfrage gewählt, zu dem ein gültiger Pfad vom Angebotsknoten aus existiert. Daraufhin wird die betragsmäßig kleinere Kapazität der beiden Knoten vom Angebotsknoten abgezogen und beim Bedarfsknoten aufaddiert. Zu den Verbindungen, welche den Pfad zwischen den Knoten bilden, wird dieser Betrag als Fluss hinzugefügt. Das Ergebnis des Eröffnungsalgorithmus liefert dem Out-of-Kilter Algorithmus die Flüsse, welche zum Ausgleich der Knotenkapazitäten sorgen. Der Out-of-Kilter übernimmt allerdings die nicht modifizierten Knotenvariablen für die Berechnung des kostenminimalen Flusses, nicht die vom Eröffnungsalgorithmus auf Null gesetzten Kapazitäten. 3.4.1.3 Out-of-Kilter Algorithmus Das Grundprinzip des Out-of-Kilter Algorithmus ist, Schritt für Schritt das Netzwerk zu optimieren, indem die Pfeile zwischen den Knoten „in kilter“ gebracht werden. Der Out-ofKilter Algorithmus ändert nicht mehr den Betrag, der aus einem Knoten anfangs ein- bzw. ausfließt. So wird garantiert, dass der durch den Eröffnungsalgorithmus erzielte Kapazitätsausgleich erhalten bleibt. Ob ein Pfeil „in kilter“ ist, wird anhand verschiedener Zustände des Pfeils definiert. Zur Berechnung dieser Pfeile werden jeweils der zugehörige 1Ungültige Spezialfälle (z. B. ein Knoten hat Bedarf, allerdings nur ausgehende Verbindungen oder es existieren ausschließlich Angebotsknoten) können nicht verarbeitet werden, der Algorithmus bricht mit Fehlermeldung ab. Seite 7 / 19 Anforderungs- und Designspezifikation The Kilter Project Fluss, die Minimal- und Maximalkapazitäten, sowie eine neue Pfeilvariable, welche wir im Folgenden als Nettokosten eines Pfeils bezeichnen, genutzt. Anhand dieser Variablen lassen sich nun die „kilter“ Zustände der Pfeile errechnen. Im Wesentlichen betrachtet man hierbei, ob die Nettokosten größer, kleiner oder gleich Null sind und leitet dann den optimalen Fluss (z. B. wenn die Kosten größer Null sind, muss der Fluss der Minimalkapazität des Pfeils entsprechen) ab. Ist dieser optimal, ist der Pfeil in einem „in kilter“ Zustand, wenn nicht, in einem der „out of kilter“ Zustände. Es gibt neun Zustände: in kilter I: Nettokosten < 0 und Fluss = Minimalkapazität in kilter II: Nettokosten > 0 und Fluss = Maximalkapazität in kilter III: Nettokosten = 0 und Fluss im zulässigen Kapazitätsbereich out of kilter I: Nettokosten < 0, aber Fluss < Minimalkapazität out of kilter II: Nettokosten < 0, aber Fluss > Minimalkapazität out of kilter III: Nettokosten > 0, aber Fluss < Maximalkapazität out of kilter IV: Nettokosten > 0, aber Fluss > Maximalkapazität out of kilter V: Nettokosten = 0, aber Fluss < Minimalkapazität out of kilter VI: Nettokosten = 0, aber Fluss > Maximalkapazität Man wählt einen beliebigen „out of kilter“ Pfeil aus und versucht, einen sogenannten Semizyklus des Gesamtnetzwerkes auszuwählen, der diesen „out of kilter“ Pfeil enthält. Dieser Vorgang wird als Markierungsprozess bezeichnet. Der Markierungsprozess beginnt, indem man einen der beiden Knoten des ausgewählten „out of kilter“ Pfeils markiert. Welcher Knoten wie markiert wird, hängt vom kilter Zustand ab. Die folgende Tabelle bildet das Regelwerk ab, dabei sind bei den Minimal- und Maximalkapazitäten und dem Fluss die Werte des verbindenden Pfeils gemeint: Zustand des Pfeils <p, q> out of kilter I out of kilter III und V out of kilter II und VI out of kilter IV Zu markierender Knoten q q p p Marke des markierten Knotens p+, kilterdelta(q) = Minimalkapazität – Fluss p+, kilterdelta(q) = Maximalkapazität – Fluss q-, kilterdelta(q) = Fluss – Minimalkapazität q-, kilterdelta(q) = Fluss – Maximalkapazität Erklärungen zur Marke (Beispiel markierter Knoten q, Marke p+, kilterdelta(q)) p+ bedeutet, dass der Knoten q vom Knoten p vorwärts markiert wurde, das bedeutet der Pfeil geht von p nach q und es wurde der Endknoten des Pfeils markiert (also vorwärts im Sinne von Pfeilrichtung). Ein minus würde dagegen bedeuten, dass der Anfangsknoten rückwärts markiert wurde. Das kilterdelta ist der Wert, um den der Fluss des Pfeiles verändert werden müsste, um „in kilter“ gebracht zu werden. Im weiteren Markierungsprozess wird für jeden Pfeil ein kilterdelta berechnet. Am Ende wird das niedrigste kilterdelta der Pfeile im Semizyklus gewählt. Mit diesem Betrag werden die Flüsse, die den Pfad des Semizyklus bilden, modifiziert. Die weitere Bildung des Semizyklus geschieht folgendermaßen: Vom markierten Knoten aus werden alle noch nicht markierten, benachbarten Knoten geprüft, ob man sie nach dem folgenden Regelwerk markieren kann. Es müssen folgende Bedingungen erfüllt sein, um die jeweilige Markierung durchführen zu können, wobei unser Ausgangsknoten Knoten p und der zu betrachtende Knoten k ist: a) Benachbarter Knoten ist der Vorgängerknoten (Anfangsknoten des verbindenden Pfeils) a1) Nettokosten >= 0 und Fluss > Minimalkapazität; Markierung: p-, kilterdelta(k) = min(kilterdelta(p), Fluss – Minimalkapazität) a2) Nettokosten < 0 und Fluss > Maximalkapazität; Markierung: p-, kilterdelta(k) = min(kilterdelta(p), Fluss – Maximalkapazität) Seite 8 / 19 Anforderungs- und Designspezifikation The Kilter Project b) Benachbarter Knoten ist der Nachfolgerknoten b1) Nettokosten > 0 und Fluss < Minimalkapazität; Markierung: p+, kilterdelta(k) = min(kilterdelta(p), Minimalkapazität – Fluss) b2) Nettokosten <= 0 und Fluss < Maximalkapazität; Markierung: p+, kilterdelta(k) = min(kilterdelta(p), Maximalkapazität – Fluss) Sind alle benachbarten Knoten geprüft und ggf. markiert, wählt man einen anderen markierten Knoten aus und prüft dessen Nachbarn nach obigem Regelwerk auf mögliche Markierungen. Dies führt man solange durch bis einer der beiden Abbruchbedingungen erfüllt ist: a) Der zweite Knoten des zuerst betrachteten „out of kilter“ Pfeils wurde markiert. In dem Fall wurde ein vollständiger Semizyklus gefunden und es schließt sich eine Flussänderung an. Den Semizyklus konstruiert man rückwärts: Man beginnt beim letzten markierten Knoten (der zweite markierte Knoten des Anfangspfeils), betrachtet dessen Markierung, welche aussagt, über welche Verbindung in welche Richtung der Knoten markiert wurde. Man geht diese Verbindung zurück, erhält den nächsten Knoten, dessen Markierung man betrachtet usw. bis man zum anderen Ende des Ausgangspfeils zurückkommt. Nun hat man den Semizyklus mit allen betroffenen Knoten, deren Markierungen und den Pfeilen. Jetzt nimmt man das kilterdelta des letzten Knotens (entspricht dem niedrigsten im Semizyklus) und modifiziert die Flusswerte innerhalb des Semizyklus damit folgendermaßen: a1) Wurde über den Pfeil vorwärts gerichtet markiert (der Endknoten hat die Markierung „Anfangsknoten des Pfeils+“), so wird auf den bisherigen Fluss des Pfeils das kilterdelta addiert. a2) Wurde über den Pfeils rückwärts gerichtet markiert (der Anfangsknoten hat die Markierung „Endknoten des Pfeils–“), so wird vom Fluss das kilterdelta subtrahiert. b) Beim Durchgehen des Markierungsprinzips gibt es keine markierbaren Nachbarknoten mehr und der zweite Knoten des Anfangspfeils wurde nicht markiert. Dann schließt sich eine Knotenvariablenänderung an. Hierbei addiert man bei allen unmarkierten Knoten zu deren Knotenvariablen den Wert µ. µ errechnet sich folgendermaßen: Man betrachtet alle Pfeile, die von markierten zu unmarkierten Knoten gehen und deren Nettokosten größer als Null, sowie deren Fluss kleiner gleich den Maximalkapazitäten sind. Existiert kein Pfeil, der die Bedingungen erfüllt, wird der Zwischenwert µ1 gleich unendlich gesetzt. Ansonsten wird µ1 gleich den niedrigsten Nettokosten der Pfeile, welche die Bedingungen erfüllen, gesetzt. Danach nimmt man die Pfeile, die von unmarkierten zu markierten Knoten gehen, deren Nettokosten kleiner als Null und deren Fluss größer gleich den Minimalkapazitäten sind. Existiert kein Pfeil, der die Bedingungen erfüllt, wird der Zwischenwert µ2 gleich unendlich gesetzt. Ansonsten wird µ2 gleich den niedrigsten negativen Nettokosten der Pfeile, welche die Bedingungen erfüllen, gesetzt. Der Endwert µ wird nun gleich dem kleineren der beiden Werte gesetzt. Ist µ unendlich, existiert kein zulässiger Zirkulationsfluss2. Dieser Vorgang des Markierungsprozesses mit anschließender Flussänderung oder Knotenvariablenänderung wird durchgeführt bis alle Pfeile „in kilter“ sind. Dann liegt der kostenminimale Fluss vor. 3.4.2 Pseudocode 3.4.2.1 Erläuterung der auftretenden Mengen und Variablen i = Variable für einen Knoten p = Variable für einen Knoten eines Pfeils q = Variable für einen Knoten eines Pfeils Knotenvariable 2 Beweis siehe Gal, T. (1992), S. 127 Seite 9 / 19 Anforderungs- und Designspezifikation The Kilter Project P(i) = Menge der Vorgängerknoten von Knoten i S(i) = Menge der Nachfolgerknoten von Knoten i N(i) = Menge der markierbaren Knoten von Knoten i aus H = Menge der zu markierenden Knoten L = Menge der markierten Knoten X = Menge der unmarkierten Knoten M = Menge der betrachtbaren Knoten a = Variable für einen Pfeil zustand(a) = Zustand des Pfeils a Fluss reduzierteKosten zustand minKap maxKap startknoten endknoten kilterdelta(i) = Zwischenwert für jeden Knoten, um das endDelta zu berechnen endDelta = Flusswert, um den der Pfeil im markierten Semizyklus geändert werden muss, um in kilter zu kommen, der die geringste Änderung benötigt Markierungsstart = Markiert, ob eine neue Iteration beginnt, wird im Markierungsprozess genutzt Markierungsende = wird von Markierungsprozess genutzt, um herauszufinden, wann ein vollständiger Semizyklus erreicht wurde (eine Abbruchbedingung für den Markierungsprozess) Semizyklus = markiert, ob Markierungsprozess einen vollständigen semizyklus gefunden hat n = Wert, um den Knotenvariablen geändert werden n1, n2 = Zwischenwerte, um n zu errechnen 3.4.2.2 Eröffnungsalgorithmus /* Das Ziel des Eröffnungsalgorithmus ist der Ausgleich der Knotenkapazitäten durch das Setzen von Initialflüssen. Diese greift der out-of-kilter Algorithmus auf und optimiert den Fluss hinsichtlich der Kosten. Die Veränderung der Knotenkapazitäten im Eröffnungsalgorithmus darf nicht die Knotenvariablen ändern, die der out-of-kilter Algorithmus nutzt. */ WENN Summe aller Knotenkapazitäten 0 DANN Baue Hilfsknoten mit Knotenkapazität = 0 – Kapazitätssumme aller vorhandenen Knoten WENN Summe aller Knotenkapazitäten > 0 DANN Baue Pfeile von allen Bedarfsknoten zu Hilfsknoten Baue Pfeile von Hilfsknoten zu allen Überschussknoten WENN Summe aller Knotenkapazitäten < 0 DANN Baue Pfeile von Hilfsknoten zu allen Bedarfsknoten Baue Pfeile von allen Überschussknoten zu Hilfsknoten Solange es einen Knoten mit Überschuss gibt Betrachte ihn Führe aus Suche Knoten mit Bedarf Seite 10 / 19 Anforderungs- und Designspezifikation The Kilter Project Suche Pfad von Knoten mit Überschuss zu Knoten mit Bedarf mit freier Pfeilkapazität Bis Knoten mit Bedarf gefunden wurde, zu dem ein Pfad von gewähltem Überschussknoten existiert Erhöhe den Fluss aller betroffenen Pfeile des gewählten Pfades um den kleinsten Wert (Angebot, Bedarf, Pfeilkapazität) Verändere die Knotenkapazitäten entsprechend Ende Schleife Starte out-of-kilter 3.4.2.3 out-of-kilter Algorithmus Pfeil- und Knotengrundvariablen setzen Solange nicht alle Zustände positiv sind Wähle einen beliebigen ook-Pfeil a // Pfeil, dessen Zustand negativ ist Setze Markierungsstart = wahr Starte Markierungsprozess WENN Semizyklus = Wahr DANN Ändere Flusswerte WENN Semizyklus = Falsch DANN Ändere Knotenvariablen Pfeilzustände und Knotennachbarn berechnen // An dieser Stelle sind Zwischenergebnisse zurück zu geben Ende Schleife (Alle Pfeile sind in-kilter, optimale Lösung erreicht) WENN Hilfsknoten p existiert DANN Für alle Knoten q, die mit dem Hilfsknoten verbunden sind führe aus WENN Knoten q P(p) DANN Erhöhe Knotenkapazität(q) um Fluss des Pfeiles // Mit Knotenkapazität ist nun wieder die durch den // Eröffnungsalgorithmus modifizierte Kapazität gemeint WENN Knoten q S(p) DANN Verringere Knotenkapazität(q) um Fluss des Pfeiles Lösche Hilfsknoten und Pfeile, die mit ihm verbunden sind Funktion Pfeil- und Knotengrundvariablen setzen Für jeden Pfeil a setze Anfangsknoten Endknoten Initialfluss Minimalkapazität Maximalkapazität Für jeden Knoten i setze Knotenvariable Menge der Vorgängerknoten P(i) Menge der Nachfolgerknoten S(i) Pfeilzustände und Knotennachbarn berechnen Seite 11 / 19 Anforderungs- und Designspezifikation The Kilter Project Pfeilzustände und Knotennachbarn berechnen Für jeden Pfeil a führe aus Setze reduzierteKosten(a) = pfeilkosten(a) + knotenvariable(startknoten) – knotenvariable(endknoten) kalkuliereZustand Für jeden Knoten führe aus Setze Menge der Vorgänger P(i) Setze Menge der Nachfolger S(i) // Setzen der markierbaren Nachbarn jedes Knotens; wird im Markierungsprozess verwendet Für alle Knoten i führe aus N(i) ← leer Setze Pfeil a = Pfeil zwischen i und j Für alle Knoten j P(i) führe aus WENN (reduzierteKosten(a) < 0 UND Fluss(a) > maxKap(a)) ODER (reduzierteKosten(a) 0 UND Fluss(a) > minKap(a)) DANN ergänze N(i) = N(i) u { j } Für alle Knoten j S(i) führe aus WENN (reduzierteKosten(a) > 0 UND Fluss(a) < minKap(a)) ODER (reduzierteKosten(a) 0 UND Fluss(a) < maxKap(a)) DANN ergänze N(i) = N(i) u { j } kalkuliereZustand WENN reduzierteKosten(a) > 0 DANN WENN Fluss(a) < minKap(a) DANN setze zustand(a) = -1 WENN Fluss(a) > minKap(a) DANN setze zustand(a) = -2 WENN Fluss(a) = minKap(a) DANN setze zustand(a) = +1 WENN reduzierteKosten(a) < 0 DANN WENN Fluss(a) < maxKap(a) DANN setze zustand(a) = -3 WENN Fluss(a) > maxKap(a) DANN setze zustand(a) = -4 WENN Fluss(a) = maxKap(a) DANN setze zustand(a) = +2 WENN reduzierteKosten(a) = 0 DANN WENN Fluss(a) < minKap(a) DANN setze zustand(a) = -5 WENN Fluss(a) > maxKap(a) DANN setze zustand(a) = -6 WENN minKap(a) < Fluss(a) < maxKap(a) DANN setze zustand(a) = +3 /* Erläuterungen: - positiver Zustand steht für einen in-kilter Pfeil, negativ für out-of-kilter - Zustände -1, -3 und -5 benötigen eine Flussvergrößerung um in-kilter zu kommen - Zustände -2, -4 und -6 eine Flussverkleinerung */ Markierungsprozess Setze p = Anfangsknoten des betrachteten out-of-kilter Pfeils a Setze q = Endknoten des betrachteten out-of-kilter Pfeils a WENN Markierungsstart = Wahr, DANN Setze Semizyklus = Falsch WENN Zustand = -1 DANN Markiere q mit der Marke(q) = p+ Setze kilterdelta(q) = minKap(a) – Fluss(a) WENN Zustand = -3 ODER -5 DANN Markiere q mit der Marke(q) = p+ Setze kilterdelta(q) = maxKap(a) – Fluss(a) Seite 12 / 19 Anforderungs- und Designspezifikation The Kilter Project WENN Zustand = -2 ODER -6 DANN Markiere p mit der Marke(p) = qSetze kilterdelta(p) = Fluss(a) – minKap(a) WENN Zustand = -4 DANN Markiere p mit der Marke(p) = qSetze kilterdelta(p) = Fluss(a) – maxKap(a) Setze Markierungsstart = Falsch Setze Markierungsende = der nicht markierte Knoten des Startpfeils a Setze Knoten p = markierter Knoten Setze Menge L der markierten Knoten auf p: L ← {p} Setze Menge M der der betrachbaren Knoten auf p: M ← {p} Solange Menge M der betrachtbaren Knoten != { } Wähle p = beliebiger Knoten in der Menge der betrachtbaren Knoten // Von diesem Knoten aus wird der weitere Pfad für den Semizyklus gesucht Setze Menge H der zu markierenden Nachbarknoten auf alle markierbaren Nachbarknoten von p, die nicht bereits markiert sind: H ← N(p) \ L // legt die Liste der in diesem Durchlauf zu markierenden Knoten fest Erhöhe Menge L der markierten Knoten um H: L ← L u H // die Knoten in Menge H werden in diesem Durchlauf markiert; sie werden schon vorab in die Menge der markierten Knoten gelegt Lösche p aus Menge M der betrachtbaren Knoten und ergänze sie um die Menge H der zu markierenden Knoten: M ← (M \ {p}) u H //sorgt dafür, dass alle relevanten Knoten nacheinander betrachtet und dann von der „to-Do-Liste“ gestrichen werden, insofern nicht vor Abarbeitung ein Semizyklus gefunden wird Für alle Knoten q in Menge H führe aus // Markierung der benachbarten Knoten Setze a = Pfeil zwischen p und q WENN q P(p) UND reduzierteKosten(a) 0 UND Fluss(a) > minKap(a) DANN Markiere q mit Marke(q) = pSetze kilterdelta(q) = min(kilterdelta(p), minKap(a) – Fluss(a)) WENN q P(p) UND reduzierteKosten(a) < 0 UND Fluss(a) > maxKap(a) DANN Markiere q mit Marke(q) = pSetze kilterdelta(q) = min(kilterdelta(p), maxKap(a) – Fluss(a)) WENN q S(p) UND reduzierteKosten(a) > 0 UND Fluss(a) < minKap(a) DANN Markiere q mit Marke(q) = p+ Setze kilterdelta(q) = min(kilterdelta(p), Fluss(a) – maxKap(a)) WENN q S(p) UND reduzierteKosten(a) 0 UND Fluss(a) < maxKap(a) DANN Markiere q mit Marke(q) = p+ Setze kilterdelta(q) = min(kilterdelta(p), Fluss(a) - maxKap(a)) WENN q = Markierungsende DANN Setze Semizyklus = Wahr Setze endDelta = kilterdelta(q) Terminiere Funktion Schleife Ende Seite 13 / 19 Anforderungs- und Designspezifikation The Kilter Project Ändere Flusswerte /* Der Semizyklus wird rückwärts Knoten für Knoten anhand der Markierungen konstruiert, ausgehend und endend beim Knoten, der das Markierungsende darstellt. Die Marken (z. B. „B-„) werden dabei folgendermaßen gelesen: Man gehe davon aus, dass man gerade den markierten Knoten A betrachtet und wissen will, von welchem Pfad man diesen Knoten betrachtet hat. Die erste Stelle („B“) bezeichnet den Knoten, von dem aus A markiert wurde. Die zweite Stelle („-“) repräsentiert die Markierungsrichtung, wobei – bedeutet, dass A rückwärts von B aus markiert wurde (der entsprechende Pfeil beginnt bei A und endet bei B). + bedeutet, dass A vorwärts von B aus markiert wurde (der Pfeil geht von B nach A). Wurde rückwärts markiert, wird der Fluss des betroffenen Pfeils um das kilterdelta verringert, wurde vorwärts markiert, entsprechend um das kilterdelta erhöht. */ Setze Knoten q = Markierungsende Wiederhole Setze Knoten p = q Setze Knoten q = Knoten der Marke von p Setze Pfeil a = Pfeil zwischen p und q WENN Marke(p) ein „+“ enthält DANN Fluss(a) = Fluss(a) + endDelta // Flussvergrößerung WENN Marke(p) ein „-“ enthält DANN Fluss(a) = Fluss(a) – endDelta // Flussverkleinerung bis q = Markierungsende Ändere Knotenvariablen /* Konnte kein vollständiger Semizyklus gefunden werden, der den betrachteten out-of-kilter Pfeil, enhält, so schließt sich keine Fluss- sondern eine Knotenvariablenänderung an. Hierbei werden die Knotenvariablen aller unmarkierten Knoten um n verändert. n berechnet sich hierbei wie folgt: Erst werden alle Pfeile betrachtet, die von markierten zu unmarkierten Knoten gehen. n1 wird gleich den niedrigsten reduzierten Kosten des Pfeils gesetzt, der bestimmte Bedingungen erfüllt (reduzierte Kosten > 0 und Fluss des Pfeils <= der maximalen Kapazität des Pfeils). Erfüllt keiner der Pfeile die Bedingungen, wird n1 = 0 gesetzt. Anschließend werden alle Pfeile betrachtet, die von unmarkierten zu markierten Knoten gehen. n2 wird gleich den niedrigsten negativen reduzierten Kosten des Pfeils gesetzt, der bestimmte Bedingungen erfüllt (reduzierte Kosten < 0 und Fluss des Pfeils >= der minimalen Kapazität des Pfeils). Erfüllt keiner der Pfeile die Bedingungen, wird n2 = 0 gesetzt. Ist n1 = n2 = 0, wird der Algorithmus abgebrochen, da unter diesen Umständen kein zulässiger Zirkulationsfluss gefunden werden kann. Ansonsten wird n gleich dem kleineren Wert von n1 bzw. n2 gesetzt. */ Für alle Knoten i führe aus WENN i L DANN erhöhe Menge X der unmarkierten Knoten um i: X ← X u {i} Setze n1 = 0 Setze n2 = 0 Für alle Pfeile a führe aus Setze Knoten p = Anfangsknoten des Pfeils a Setze Knoten q = Endknoten des Pfeils a WENN p L UND q X UND reduzierteKosten(a) > 0 UND Fluss(a) maxKap(a) DANN Seite 14 / 19 Anforderungs- und Designspezifikation The Kilter Project WENN n1 = 0 DANN n1 = reduzierteKosten(a) WENN n1 0 DANN n1 = min(n1, reduzierteKosten(a)) WENN p X UND q L UND reduzierteKosten(a) < 0 UND Fluss(a) minKap(a) DANN WENN n2 = 0 DANN n2 = – reduzierteKosten(a) WENN n2 0 DANN n2 = min(n2, – reduzierteKosten(a)) WENN n1 = 0 UND n2 = 0 DANN terminiere Algorithmus Setze n = min(n1, n2) Für alle Knoten i X führe aus Setze Knotenvariable(i) = Knotenvariable(i) + n Seite 15 / 19 Anforderungs- und Designspezifikation 3.4.3 The Kilter Project Sequenzdiagramm GUI 1: new Core () Core 2: addIterationCompletedListener (gui) 3: initialize (nodes, connections) (Compensationnode necessary) 4: addCompensationNode () 5: Core.compute () (not initialize) 6: throwNewInvalidDataException 7: prepareForKilter() (Nodes can not be balanced) 8: InvalidDataException 9: outOfKilter () 10: mark () 11: getSemiCycle () (Detected infinite Loop) 12: infiniteLoopException () 13: IterationCompleted (nodes, connections) 14: IterationCompleted (null, null) Seite 16 / 19 Anforderungs- und Designspezifikation 3.4.4 The Kilter Project Klassendiagramm Siehe Anhang: Anlage 1 Die API für die Methoden ist auf der CD unter TheKilterProjekt/doc/index.html zu finden. 3.5 Schnittstellen der gewünschten Software Schnittstelle zu der GUI Oberfläche: Datenimport der Ausgangswerte des Netzwerkes aus der GUI Oberfläche über die Methode initialize() Datenexport der Ausgabewerte für die einzelnen Schritte des Out-of-Kilter Algorithmus zur GUI Oberfläche durch das Aufrufen der Methoden IterationCompleted() in der GUI Übergabe der Knoten und Kanten mit ihren Eigenschaften von und zur GUI Oberfläche Knoten: ID Name Ein- und ausgehende Verbindungen Kapazität Kanten: ID Name Kosten Minimale und maximale Kapazität Aktuelle Kapazität Quell- und Zielknoten 3.6 Zu berücksichtigende Normen Nicht relevant 3.7 Qualitätsanforderungen / sonstige entwicklerorientierte Anforderungen Da der Out-of-Kilter Algorithmus ein sehr umfassender Algorithmus ist, führt die Berechung des Algorithmus bei einem komplexen Netzwerk mit vielen Knoten und Kanten zu einer hohen Komplexität. In diesem Fall müsste zur Berechnung des Out-of-Kilter Algorithmus eine entsprechend leistungsfähige Hardware bereitgestellt werden. Die Anwendung zur Berechnung des Out-of-Kilter Algorithmus kann für alle Netzwerkoptimierungsproblem verwendet werden, sofern ein gerichtetes Netzwerk mit Kosten, minimalen und maximalen Kapazitäten besteht. 4 Vorgaben des Auftraggebers an die Projektabwicklung 4.1 Anforderungen an die Realisierung Entwicklungsmethode frei wählbar Projektpräsentation: 12.02.2010 Abgabe der Anwendung und der Dokumentation: 19.02.2010 bis 13.00Uhr 4.2 Abnahmebedingungen Projektdokumentation: 2 gedruckte und geheftete oder gebundene Exemplare inklusive unterschriebener Selbstständigkeitserklärung Zusätzlich eine Text-Datei auf in Papierhülle eingeklebter und beschrifteter CD Anwendung: auf einer CD (inklusive Installationsanleitung) zum Anwenden und Testen Seite 17 / 19 Anforderungs- und Designspezifikation 4.3 The Kilter Project Fertige und zugekaufte Komponenten nicht relevant 4.4 Lieferbedingungen Keine weiteren Bedingungen, die nicht in Abschnitte 4.1 und 4.2 schon aufgeführt sind. 4.5 Gewährleistung Nicht relevant 5 Durchführbarkeitsuntersuchungen Nicht relevant 6 Bewertung der Anforderungen Nicht relevant 7 Verpflichtungen des Auftraggebers Nicht relevant 8 Literaturverweise Gal, T. (1992): Grundlagen des Operations Research 2. Graphen und Netzwerke – Netzplantechnik – Transportprobleme – Ganzzahlige Optimierung. 3. Auflage, Berlin, Heidelberg, 1992. Seite 18 / 19 Anforderungs- und Designspezifikation 9 Anhang Anlage 1: Klassendiagramm Seite 19 / 19 The Kilter Project