Combinatorial and geometrical countingLEDAby Christian Uhrig
LEDA is one at max Plank Max-Plank-Institut for computer science in Saarbruecken developed class library for the comfortable solution of many problems of computer science, in particular from geometrical and combinatorial questions. Christian introduces us to programming with LEDA and explains in detail, what has it with this tools on itself, freely available for not-commercial purposes.
1. Why does it LEDA give?Already since more jeher Institut, on whom I work, had dedicated itself above all to the basic research. The different spheres of activity under the title efficient algorithms and data structures were summarized, under what we understand among other things combinatorial and geometrical counting. That does not certainly only sound now after a purely theoretical activity. Nevertheless we had to state gradually that our realizations (and those of our colleagues) could find only heavily or not at all the entrance into the practice. During our cause research we essentially encountered the following reasons:
Now one could conclude, there would at all be no implementations for algorithms from this forschungsgebiet. Far been missing. To many projects or theses (diploma) also the conversion of cleverer solution strategies belongs. There again and again those emerge in principle same data structures in completely easily modified form. And each student had programmed his own version of for example binary trees. On request, why like that is, we received into the following answers:
Combinatorial and geometrical counting represents one of the central areas of computer science. For this reason also most university curricula contain courses over data structures and efficient algorithms. Typical objects of this area are graphs, consequences, dictionaries, trees, shortest ways, rivers, illustrations, points, segments, lines, convex coverings and Voronoi diagrams (for the less usual terms it gives in the appendix an explanation); it forms the basis for such Anwendungungen like discrete optimization, planning, traffic control, CAD, diagram and much more besides. The fact that there was no standard library for data structures and algorithms stood for statistics (SPSS) in clear contrast to other disciplines as for example, numerical analysis (LINPACK, ICE LUGGAGE), symbolic counting (MAPLE, MATHEMATICA) or linear programming (CPLEX). The absence of a library had extremely negative effects in the past on the use of the area for entire computer science. The constantly repeating new implementing of fundamental data structures and algorithms obstructs the progress not only within the research, but above all also in the free economy. We already called the reasons for it. But on what now the absence of a library of efficient algorithms and data structures is to be led back? One of the largest differences between combinatorial or geometrical counting and other areas such as statistics, numerical analysis and linear programming is the use of complex data types. While the types built into programming languages are normally sufficient like whole or real numbers, vectors and stencils for other areas, like already suggested combinatorial and geometrical counting is based particularly on types such as cellars, queues, lists, dictionaries, consequences, graphs, points, lines and convex coverings. It requires therefore a programming environment, which makes all these types available. With the introduction of object-oriented programming such became possible an extension in efficient and elegant way. In the year 1989 we could begin therefore with the LEDA project. The goal was thus to develop a library of the data types and algorithms for combinatorial and geometrical counting. In the available article I would like to obtain a rough overview of this library, by calling the main characteristics and on the basis simple examples illustrate the use of the different parts. Into later expenditures I will continue to go into the detail and the underlying concepts of the different data structures as well as the conversion by programming to LEDA will more exactly describe. Parts of the text will orient themselves at different chapters of the book LEDA , Platform for Combinatorial and Geometric Computing of Kurt flour horn and Stefan close, which with Oxford University press will appear. 2. What now is LEDA?The substantial characteristics of LEDA can be outlined as follows:
2.1 Worte zählenWir möchten eine Folge von Worten (Zeichenketten, Strings) von der Standardeingabe lesen, die Anzahl der Vorkommen jedes einzelnen Strings zählen und schließlich eine Liste aller Strings zusammen mit ihrer Häufigkeit ausgeben. Die hierfür geeigneten LEDA Typen sind Strings (string ) und Dictionary Arrays. Der parametrisierte Typ
Dictionary Array (d_array<I,E> ) realisiert Felder mit frei
wählbarem Indextyp I und dem ebenfalls beliebigen
Elementtyp E . Hier verwenden wir ein Array mit Indextyp
string und Elementtyp int .
Das vollständige Programm ist in Abbildung 1 zu sehen:
#include <LEDA/d_array.h> int main(int argc, char** argv) { d_array<string,int> N(0); string s; while (cin >> s) N[s]++; forall_defined (s,N) cout << s << " " << N[s] << endl; } Abb. 1: Ein Programm, das die Anzahl der Vorkommen jedes Strings in einer Folge von Strings zählt.
Es beginnt mit einer 2.2 Kürzeste Wege in GraphenEin gerichteter Graph besteht aus einer Menge V von Knoten und einer Menge E von Kanten. Eine Kante e = (v, w) ist eine gerichtete Verbindung von ihrem Startknoten v zu ihrem Endknoten w. Nehmen wir nun an, daß für jede Kante e eine Reisezeit cost[e] in Minuten gegeben ist und daß es unsere Aufgabe ist, die minimale Reisezeit von einem bestimmten Knoten s zu jedem beliebigen anderen Knoten zu berechnen (Abbildung 2 zeigt ein Beispiel).
Abb. 2: Ein Graph mit Kantenbeschriftungen. Diese geben die Reisezeit (in Minuten) über die jeweilige Kante an. Die kürzeste Reisezeit von Knoten s zu Knoten c beträgt 4 Minuten.Dijkstra [Dij59] hat einen einfachen Algorithmus gefunden, der dieses Problem löst. Zu jedem Zeitpunkt während der Ausführung des Algorithmus gibt es eine Menge S, Teilmenge von V, von Knoten, für die die minimale Reisezeit bereits bekannt ist, während für alle anderen Knoten lediglich eine obere Schranke für die Reisezeit bekannt ist, d.h., eine Zeitspanne, in der man die Strecke auf jeden Fall bewältigen kann, die jedoch nicht notwendigerweise minimal ist. Für jeden Knoten v bezeichnen wir mit dist[v] die kürzeste bisher bekannte Reisezeit von s nach v. Anfangs ist dist[s] = 0, dist[v] = unendlich für jeden Knoten v != s, und S = leere Menge. In jedem Schritt wählen wir einen Knoten u aus V-S mit dem kleinsten Wert dist[u] (am Anfang ist u = s) und fügen ihn zu S. Für jede von u ausgehende Kante e = (u, w) setzen wir dist[v] auf den Wert dist[u] + cost[e], wenn dieser Wert kleiner ist als der aktuelle Wert von dist[v]. In unserem Beispiel ist s der erste Knoten, der zur Menge S kommt. Wenn dies geschieht, wird dist[a] auf 2 gesetzt und dist[c] auf 6. Dann fügen wir a zu S, dist[b] wird auf 3 gesetzt und dist[c] wird auf 5 erniedrigt, ... . Die Korrektheit dieses Algorithmus soll hier nicht bewiesen werden (Beweisidee: man zeigt, daß für alle Knoten v der Wert von dist[v] immer die kürzeste Reisezeit von s nach v entlang eines Pfades angibt, dessen Knoten alle mit Ausnahme des Endknotens zu S gehören). Wie können wir nun den Knoten in V-S mit dem kleinsten dist-Wert schnell finden? Eine geeignete Datenstruktur ist eine Warteschlange. Abbildung 3 zeigt die LEDA-Implementierung von Dijkstras Algorithmus.
#include <LEDA/graph.h> #include <LEDA/node_pq.h> void DIJKSTRA(const graph& G, node s, const edge_array<int>& cost, node_array<<nt>& dist) { node_pq<int> PQ(G); node v; forall_nodes(v,G) { dist[v] = (v == s) ? 0 :MAXINT; PQ.insert(v,dist[v]); } while (! PQ.empty()) { node u = PQ.del_min(); edge e; forall_adj_edges(e,u) { v = target(e); int c = dist[u] + cost[e]; if (c < dist[v]) { PQ.decrease_p(v,c); dist[v] = c; } } } } Abb. 3: Dijkstras Algorithmus für das Problem der Berechnung aller kürzesten Wege von einem Knoten aus.
Neben Graphen benutzt er
Wir möchten besonderes auf die große ähnlichkeit zwischen dem LEDA Programm und der Beschreibung des Algorithmus hinweisen. Die gleiche ähnlichkeit ist bei den meisten Graphenalgorithmen anzutreffen. In diesem Sinne erfüllt LEDA die Gleichung ``Algorithmus + LEDA = Programm''.
Erwähnenswert ist sicher auch, daß ein Programmierer von Dijkstras
Algorithmus nichts über die innere Funktionsweise von Graphen und
Knoten-Warteschlangen zu wissen braucht. Die Kenntnis der relevanten
Seiten im Handbuch genügt vollkommen. Abbildung 4
zeigt die Handbuchseite für Knoten-Warteschlangen (
Im letzten Abschnitt gibt diese Seite die Laufzeiten der verschiedenen Operationen für
Warteschlangen an: konstante Zeit für
Node priority queues (node_pq) 1. Definition An instance Q of the parametrized data type node_pq<I> is a set of pairs (v,i), where v is a node of some graph G and i belongs to some linearly ordered type I; i is called the information associated with node v. For any node v of G there can be at most one pair (v, ) in Q. 2. Creation node_pq<I> Q(G); creates an empty instance Q of type node_pq<I> for the nodes of graph G. 3. Operations void Q.insert(node v, I i) adds the node v with information i to Q. Precondition: There is no pair (v, ) in Q. I Q.inf(node v) returns the information of node v. bool Q.member(node v) returns true if (v,i) in Q for some i, false otherwise. void Q.decrease_inf(node v, I i) makes i the new information of node v. Precondition: i <= Q.inf(v)). node Q.find_min() returns a node with the minimal information (nil if Q is empty). void Q.del(node v) removes the pair (v, ) from Q. node Q.del_min() removes a node with minimal information from Q and returns it (nil if Q is empty). int Q.size() returns the number of pairs in Q. void Q.clear() makes Q the empty node priority queue. bool Q.empty() returns true if Q is the empty node priority queue, false otherwise. 4. Implementation Node priority queues are implemented by fibonacci heaps and node arrays. Operations insert, del_node, del_min take time O(log n), find_min, decrease_inf,empty take time O(1) and clear takes time O(m), where m is the size of Q. The space requirement is O(n), where n is the number of nodes of G. Abb. 4: Die Handbuchseite für Knoten-Warteschlangen.2.3 Konvexe HüllenStellen Sie sich eine endliche Menge L von Punkten in der Ebene vor, die von einem Gummiband umschlossen ist. Das Gummiband zeigt den Verlauf der sogenannten konvexen Hülle von L. Abbildung 5 zeigt ein Beispiel.
Abb. 5: Die konvexe Hülle einer Punktemenge in der Ebene. Die obere Hülle ist dick gezeichnet.Die konvexe Hülle ist eine der grundlegenden Strukturen in der algorithmischen Geometrie. Sie wird bei der Bildverarbeitung oder Mustererkennung oft als eine Annäherung an die Form einer Punktmenge benutzt. Wir erklären im folgenden, wie wir die konvexe Hülle berechnen, wenn die Punktmenge gegeben ist: wir beschränken uns der Einfachheit halber auf die sogenannte obere Hülle. Wenn wir die konvexe Hülle nämlich durch eine Gerade durch den Punkt der am weitesten links und den Punkt der am weitesten rechts liegt, durchschneiden, zerteilen wir sie in die obere und die untere Hülle von L (siehe Abbildung 5). Dabei ist ein Punkt p links von einem Punkt q, wenn entweder die x-Koordinate von p kleiner ist als die von q ist oder wenn die x-Koordinaten der beiden Punkte gleich sind und die y-Koordinate von p ist kleiner ist als die von q. Wir berechnen die obere Hülle einer Punktmenge L wie folgt: Zuerst sortieren wir die Menge L gemäß der oben definierten Links-Rechts Reihenfolge ihrer Punkte. Sei p_1, p_2, ... , p_n die gemäß dieser Reihenfolge aufsteigend sortierte Folge. Wir konstruieren die obere Hülle der Punkte p_1, ... , p_i inkrementell für alle i, 1 <= i <= n. Die Initialisierung ist einfach. Die obere Hülle von p_1 ist p_1. Setzen wir nun voraus, daß die obere Hülle der Punkte p_1, ... , p_i bereits berechnet ist und daß wir den Punkt p_i+1 abarbeiten. Wenn p_i = p_i+1, dann ist nichts zu tun. Wenn aber p_i != p_i+1, dann löschen wir den jeweils letzten Punkt der aktuellen oberen Hülle, solange diese mindestens aus zwei Punkten besteht und mit dem neuen Punkt p_i+1 keine Rechtskurve bildet (siehe Abb. 6).
Abb. 6: Die oberer Hülle nach dem Abarbeiten aller Punkte außer q. Wenn der Knoten q hinzugefügt wird, werden die letzten vier Punkte der aktuellen Hülle gelöscht, weil (q_i, q_i+1), q für 2 <= i <= 5 keine Rechtskurve bildet.
Dann addieren wir p_i+1 zur oberen Hülle; damit ist der
Iterationsschritt abgeschlossen.
Abbildung 7 zeigt die
LEDA Implementierung von diesem Algorithmus. Wegen der schon
erwähnten großen ähnlichkeit zwischen der algorithmischen
Beschreibung und dem LEDA Programm sind nur wenige zusätzliche Worte
notwendig, um das Programm zu erklären:
#include <LEDA/list.h> #include <LEDA/plane.h> list<point> u_hull(list<point> L) { L.sort(); // into left-to-right order list<point> Uh; point p = L.pop(); Uh.append(p); while (!L.empty()) { point q = L.pop(); // deletes the first element from L if (p == q) continue; list_item it = Uh.last(); while (Uh.length() >= 2 && right_turn(Uh[Uh.pred(it)],Uh[it],q)) { Uh.del_item(it); // deletes the last element from Uh it = Uh.last(); } Uh.append(q); p = q; } return Uh; }Abb. 7: Ein Programm zum Berechnen der oberen Hülle einer Punktmenge.
Es gibt noch eine weitere interessante Beobachtung bei dem Programm zur Berechnung der konvexen Hülle. Ein Punkt in LEDA kann beliebige rationale Koordinaten enthalten und alle Prädikate werden exakt (d.h. mit genauer rationaler Arithmetik) ausgerechnet. Beachten Sie auch, daß das Programm mehrfaches Auftreten des gleichen Punktes ebenso korrekt verarbeitet wie kollineare Punkte (solche Situationen werden degenerierte Fälle genannt). Es ist vorgesehen, daß alle geometrischen Algorithmen in LEDA mit allen degenerierten Fällen zurecht kommen und momentan trifft dies bereits für viele zu. Weitere Details hierzu können in [BMS94a], [BMS94b] und [MN94b] nachgelesen werden. 2.4 GrafikDer LEDA Datentyp window ist eine Schnittstelle zum jeweiligen Window System, bei Linux zu X11. Abbildung 8 illustriert den Gebrauch dieses Datentyps.
#include <LEDA/window.h> int main(int argc, char** argv) { window W; list<point> L; point p; while (W >> p) { L.append(p); W.draw_point(p); } W.draw_polygon(u_hull(L)); W.read_mouse } Abb. 8: Ein Programm, das den Algorithmus für die obere Hülle und die Schnittstelle zu XWindows illustriert.
Das Programm liest eine Folge von Punkten ein, gibt sie in einem Fenster aus und zeichnet ihre obere Hülle als Linienzug. Wieder reichen wenige Erklärungen aus: Die Definition window W definiert ein grafisches Fenster und öffnet es für die Mauseingabe. Durch Drücken der linken Maustaste gibt man einen Punkt ein (W >> p); beim Betätigen der rechten Maustaste wird W >> p als false ausgewertet. Der Punkt wird an die Liste L gehängt und im Fenster W gezeigt. Danach wird die obere Hülle berechnet und als Linienzug gezeichnet. Abbildung 9 zeigt ein Beispiel.
Abb. 9: Eine Ausgabe des Programms zum Berechnen der oberen Hülle.3. Was ist alles drin in LEDA?LEDA ist sehr umfangreich. Die Bibliothek enthält die meisten Datenstrukturen und Algorithmen, die in den einschlägigen Textbüchern beschrieben sind (siehe [AHU83], [CLR90], [Kin90], [Meh84], [NH93], [Woo93]). Man kann sie in die folgenden sechs Gebiete unterteilen: (1) Basistypen, (2) Zahlen, Vektoren und Matrizen, (3) Wörterbücher und Warteschlangen, (4) Graphen, (5) Geometrie und (6) Grafik.Die Basisdatentypen sind Strings, Listen, Schlangen, Keller, Felder, Partitionen und Bäume. Die Zahlentypen umfassen sowohl die eingebauten Typen (int, float, double) als auch Typen mit beliebiger Genauigkeit (integer, real). Der Typ integer entspricht der Menge der ganzen Zahlen im mathematischen Sinne, also ohne Beschränkung der Zahlengröße (wenn man mal von der Speichergröße absieht); real entspricht der Klasse der floating point Zahlen mit Mantisse und Exponent in beliebiger Genauigkeit. Es gibt auch Vektoren und Matrizen für all diese Zahlentypen. In der dritten Gruppe gibt es Warteschlangen, Wörterbücher, Wörterbuch- und Hashingfelder, Sortierte Folgen und persistente Wörterbücher. Der Graphenteil bietet verschiedene Arten von Graphen: gerichtete Graphen, ungerichtete Graphen und planare Graphen. Darüber hinaus gibt es noch weitere Datenstrukturen auf Graphen wie etwa Felder, die mit Knoten oder Kanten indiziert sind, Warteschlangen für Knoten, Knotenpartitionen und andere. Zusätzlich ist eine große Anzahl von Algorithmen auf Graphen und Netzwerken verfügbar: Kürzeste Wege, zweifache Zusammenhangskomponenten, starke Zusammenhangskomponenten, transitive Hülle, topologisches Sortieren, ungewichtetes und gewichtetes bipartites Matching, ungewichtetes allgemeines Matching, Netzwerkfluß, Netzwerkfluß mit minimalen Kosten, Planaritätstest, planare Einbettung, minimaler aufspannender Baum, usw.. Dem LEDA-Handbuch [NU95] kann man entnehmen, was es sonst noch alles gibt. 4. Wie ist es gemacht?Alle Datentypen und Algorithmen in LEDA sind vorkompiliert und in Bibliotheken abgespeichert. Ein Anwenderprogramm braucht nur die Header Files von den Datentypen, die in der Anwendung benutzt werden, einzubinden. Diese sind im allgemeinen kurz (sie bestehen nämlich nur aus den Deklarationen der member Funktionen des Typs) und enthalten wenig Programmtext. Da LEDA erlaubt, die Anwenderprogramme auf hohem Niveau zu formulieren, sind diese normalerweise kurz und elegant. Insgesamt resultiert daraus eine kurze Übersetzungszeit.Alle Datentypen in LEDA sind durch die asymptotisch effizienteste Implementierung realisiert, die bekannt ist. Für viele Datentypen werden verschiedene Implementierungen zur Verfügung gestellt. Beispielsweise kann der Benutzer bei den Wörterbüchern unter ab-Bäumen, AVL-Bäumen, BB[a]-Bäumen, Rot-Schwarz-Bäumen, Skiplisten und randomisierten Suchbäumen wählen (all dies sind Datenstrukturen, die im wesentlichen das Einfügen, Löschen und schnelle Auffinden von Daten gut unterstützen). Der Mechanismus zum Auswählen einer anderen Implementierung ist ziemlich bequem. Wenn man zum Beispiel die Definition des Wörterbuchfeldes N im Wörterzähl-Programm durch _d_array<string, int, skip_list> N(0) ersetzt, werden automatisch Skiplisten benutzt. Abstrakte Datentypen verstecken die Implementierungsdetails einer Datenstruktur. Allerdings kann die Abstraktion, wenn sie nicht sorgfältig durchgeführt wird, auch einen Effizienzverlust mit sich bringen, wie folgendes Beispiel erläutert. Ein Wörterbuch mit Schlüsseltyp K und Informationstyp I wird gewöhnlich als Abbildung von K nach I betrachtet. Nehmen wir nun an, jemand möchte zuerst auf die Information zugreifen, die zu einem Schlüssel k gehört, dann diese Information verändern, um schließlich die neue Information an den Schlüssel k zu binden. Ist ein Wörterbuch auf herkömmliche Weise definiert, werden dabei zwei Suchvorgänge notwendig: Beim ersten Suchen werden der Schlüssel k und die dazugehörige Information lokalisiert. Der zweite Suchvorgang lokalisiert k noch einmal und assoziiert eine neue Information mit k. Ein direkter Zugriff auf die Datenstruktur könnte jedoch die zweite Suche sparen. Man merkt sich einfach einen Zeiger auf die Position des Schlüssels k in der Datenstruktur und ersetzt den zweiten Suchvorgang durch direkten Zeigerzugriff. In LEDA wurde ein neues Item-Konzept eingeführt, um die durch die Abstraktion eingeführte Ineffizienz zu umgehen. Ein Wörterbuch wird als eine Sammlung von items (mit dem Typ dic_item) betrachtet, von denen jedes einen Schlüssel und eine Information enthält. Die Schlüssel, die mit verschiedenen Informationen assoziiert sind, sind verschieden. Eine Suche in einem Wörterbuch nimmt einen Schlüssel und gibt ein Item zurück (und nicht die darin enthaltene Information). Auf die Information kann nun über dieses Item zugegriffen werden. Das Wesentliche dabei ist, daß man das Item speichern und später direkt über dieses Item zugreifen kann, ohne es erneut suchen zu müssen. Auf diese Weise stellen Items die Abstraktion einer Position in einer Datenstruktur dar. Sie ermöglichen einerseits Effizienz und erlauben andererseits vollständige Verkapselung der zugrundeliegenden Datenstruktur. Unserer Meinung nach ist das Item-Konzept ein Schlüsselfaktor für die Effizienz von LEDA. Weitere Informationen dazu finden sie im LEDA-Handbuch [NU95] und in [MN92]. Natürlich müssen wir einen Preis für die Universalität von LEDA zahlen. Dr. Ullrich Lauther von der Siemens AG in München [Lau92] hat intensive Vergleiche zwischen mit LEDA implementierten Graphen- und Netzwerkalgorithmen und von Hand in C geschriebenen durchgeführt. Er erklärt, die LEDA Versionen seien um einen Faktor zwischen 2 und 10 (normalerweise etwa 4) langsamer als seine eigenen Versionen und benötigten zwischen 2 und 3,5 mal soviel Speicherplatz. Wir glauben, daß man dies in Anbetracht der Bequemlichkeit, die LEDA bietet, durchaus akzeptieren kann. Als Reaktion auf Lauthers Bericht haben wir mittlerweile einige grundlegenden Datenstrukturen (in erster Linie graph) neu implementiert, wodurch der Overhead auf einen Faktor von etwa 2 reduziert wurde. 5. Sind die Programme korrekt?Wie stellen wir Korrektheit der Programme in der LEDA-Bibliothek sicher?
1992 bekamen wir einen planaren Graphen zugesandt, den unser Programm für nicht planar erklärt hatte. Bei der Reimplementierung des Algorithmus [MMN93] erkannten wir, daß wir nur dann Vertrauen in die Korrektheit unserer Implementierung haben könnten, wenn diese ihre Antwort belegen würde.
Die neue Implementierung tut daher folgendes: Wenn der Eingabegraph
planar ist, dann liefert das Programm eine planare Einbettung, und wenn
der Eingabegraph nicht planar ist, dann liefert das Programm einen
sogenannten Kuratowski-Untergraphen, der die Nichtplanarität bezeugt
(es gibt einen mathematischen Beweis dafür, daß nicht-planare Graphen
einen solchen Graphen als Untergraphen besitzen müssen).
Ein Nutzer der Neuimplementierung muß nun nichts mehr glauben, er
erhält vielmehr für jeden Eingabegraphen einen Beweis für die
Korrektheit der Ausgabe. Diejenigen Leser, die Zugang zur LEDA-Bibliothek
haben, sollten die Vorführung Dabei wird auffallen, daß der Planaritätstest und das Erstellen der Zeichnung sehr schnell funktionieren (die entsprechenden Programme laufen in Linearzeit), daß aber das Finden der Kuratowskigraphen vergleichsweise lange dauert (die Laufzeit ist quadratisch). Wir haben auch für das letztere Problem jüngst einen Linearzeitalgorithmus gefunden, aber noch nicht implementiert [HMN96]. 7. LEDA im InternetEs gibt eine direkte Kontaktadresse, nämlichweiterhin eine World Wide Web Homepage eine newsgroup comp.lang.c++.leda und schließlich eine ftp -Adresse, wo man LEDA erhalten kann. ftp://ftp.mpi-sb.mpg.de/pub/LEDA. Die Benutzung von LEDA für akademische Forschung und Lehre ist kostenlos. Kommerzielle Interessenten sollten sich die entsprechenden Seiten im WWW ansehen oder sich an obige Email-Adresse wenden. 8. Eine kurze NachbetrachtungDie Arbeit an LEDA wurde 1989 begonnen und eine erste Version wurde 1990 für die öffentlichkeit zugänglich gemacht. Seither wird die Bibliothek ständig weiterentwickelt. LEDA wird inzwischen an sehr vielen Hochschulen und Forschungsinstituten eingesetzt (wir wissen von über Tausend Installationen), es gibt mittlerweile auch einige kommerzielle Benutzer. Es ist uns also gelungen, die Ergebnisse der Algorithmenformschung auch ausßerhalb der Informatik zugänglich zu machen.Ich sollte darauf hinweisen, daß LEDA nicht die einzige Bibliothek für Datenstrukturen ist. Andere sind [GOP90], [Boo87] ([Loc94] gibt einen Überblick) und die Standard Template Library (STL). Die Haupteigenschaft, die LEDA von den anderen Bibliotheken unterscheidet ist ihr Umfang. Keine andere Bibliothek enthält soviele Datentypen und Algorithmen aus dem Gebiet des kombinatorischen und geometrischen Rechnens. AnhangDie Erklärung der Begriffe ist hier sehr intuitiv gehalten, da ich der Meinung bin, daß dies für das Verständnis des Artikels und der Beispiele ausreicht und eine mathematisch genaue Definition u.U. eher verwirrt als erläutert.
Bibliographie
|
Der Autor |
Christian Uhrig ist Mitarbeiter am Max Plank Institut für Informatik und dort unter anderem für das LEDA-Projekt verantwortlich. Daneben ist er auch Geschäftsführer der LEDA Software GmbH, die eine kommerzielle Version von LEDA vertreibt und Support bietet. Zu erreichen ist er unter uhrig@mpi-sb.mpg.de |
Copyright © 1996 Linux Magazin