Prolog Beleg - Aufgabe 5 - bearbeitet von: Gliederung: 1. Aufgabenstellung 2. Vorüberlegung 3. Erläuterung eines konkreten Beispiels 4. Vorstellen der Lösung unter Verwendung von 4.1. Prädikaten 4.2. Listen 4.3. Datenbasis 5. Zusammenfassung 1. Aufgabenstellung Erstellung eines PROLOG-Programms für folgendes Spiel: Ein Graph ist durch seine Knotenmenge {a1,…, an} und seine Kantenrelation kante(ai, aj) gegeben. Zwei Spieler wählen abwechselnd verschiedene Knoten a0, a1,… und zwar so, dass ai+1 und ai durch eine Kante verbunden sind. Für jeden Startknoten a0 bestimme man alle möglichen Zugfolgen und ermittle jeweils, welcher Spieler gewinnt. Der Graph sei ungerichtet und zusammenhängend. 2. Vorüberlegung Die Grundidee unseres Prologprogramms besteht darin, dass beginnend von einem variablen Startknoten alle möglichen Wege zu einem Endknoten ermittelt werden. Dabei werden folglich alle Möglichkeiten, die zwei Spieler wählen können, um sich auf dem Graphen zu bewegen, gefunden. Um das Ergebnis für jeden Startknoten nur einmal zu ermitteln, werden die bereits verwendeten Knoten für den Start in einer "globalen Variable" unter Verwendung der Datenbasis gespeichert. Die Ermittlung aller möglichen Wege erfolgt für alle möglichen Startknoten und der dabei zurück gelegte Weg wird in einer Liste gespeichert. Nach jedem Spielzug wird getestet, ob es bereits einen Sieger gibt. Hierzu wird der letzte Knoten mit noch möglichen Spielzügen, die von diesem weg führen könnten, verglichen. Gibt es keine Möglichkeit, diesen Knoten zu verlassen, hat der Spieler gewonnen, dem zuletzt einen Zug möglich war. Anhand der Anzahl der Listeneinträge lässt sich ermitteln, welcher Spieler gewinnt. Unter der Vorraussetzung, das Spieler A beginnt, verliert dieser, wenn es sich um eine ungerade Anzahl von besuchten Knoten handelt. Analog gewinnt Spieler A, wenn eine gerade Anzahl von Knoten im Spielverlauf erreicht wurde. 2 3. Erläuterung eines konkreten Beispiels Um unser Programm testen zu können, haben wir uns mehrere verschiedene Graphen überlegt, um die Korrektheit unseres Programms zu beweisen. Exemplarisch haben wir ein Beispiel aufgeführt, anhand dessen sich unser Programm und seine Ausgabe testen läst. Wesentlich für die Ermittlung einer korrekten Lösung ist die Einhaltung der Bedingungen, das es sich um einen ungerichteten, zusammenhängenden Graphen handelt, bei dem jede Kante nur einmal benutzt werden kann, der Besuch eines Knotens jedoch mehrmals möglich ist. Grundlage für dieses Beispiel ist der folgende Graph: 1 2 3 4 5 6 7 • Spieler A: roter Pfeil • Spieler B: blauer Pfeil • Spieler A beginnt Als Beispiel geben wir alle möglichen Zugfolgen vom Startknoten a1 an: Graph Zugfolge Gewinner 1 2 3 4 5 6 7 a1, a3, a2. a5, a6, a3, a4, a1 A a1, a3, a2. a5, a6, a3, a4, a7 A 1 2 3 4 5 6 7 3 1 2 3 4 5 6 7 a1, a3, a6. a5, a2, a3, a4, a1 A a1, a3, a6. a5, a2, a3, a4, a7 A a1, a3, a4. a1 A a1, a3, a4. a7 A 1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2 3 4 5 6 7 a1, a4. a7 B a1, a4, a3, a1 A 1 2 3 4 5 6 7 4 1 2 3 4 5 6 7 a1, a4, a3, a2, a5, a6, a3, a1 A a1, a4, a3, a6, a5, a2, a3, a1 A 1 2 3 4 5 6 7 4. Vorstellen der Lösungen Grundsätzlich müssen bei allen drei Programmen jeweils alle Kanten nur einmal eingegeben werden, obwohl es sich um ungerichtete Kanten handelt. 4.1. Prädikate Der wesentliche Unterschied zu den anderen Lösungsmöglichkeiten besteht darin, dass sowohl Knoten als auch Kanten durch Prädikate vor Programmstart gegeben sein müssen, da dies in diesem Fall die "Wissensgrundlage" unseres Programms darstellt. Bsp.: knoten(a1). knoten(a2). knoten(a3). … kante(a1, a3). kante(a1, a4). kante(a2, a3). … Das Programm lässt sich durch die Eingabe von 'loesung.' starten. 4.2. Listen In dieser Lösungsmöglichkeit wurden alle Prädikate knoten(ai) und Relationen kante(ai,aj) durch Listen ersetzt. Auch in diesem Fall besteht noch der Nachteil, dass die Listen vor Programmstart gegeben sein müssen müssen. Bsp.: liste_knoten([a1,a2,a3,a4,a5,a6,a7]). get_knoten(X):- liste_knoten(K), member(X,K). 5 graph_kante([[a1,a3],[a1,a4],[a2,a3],[a2,a5],…]]). zug(X,Y):- graph_kante(K), (member([X,Y],K); member([Y,X],K)). Um spezielle Knoten bzw. Kanten zu verwenden, ist die Erstellung der Prädikate get_knoten(X) und zug(X,Y) nötig. Diese Lösungsmöglichkeit unseres Problems lässt sich ebenfalls durch Eingabe von 'loesung.' starten. 4.3. Datenbasis Diese Möglichkeit zur Lösung unserer Aufgabe ist sehr allgemein gehalten. Zum Programmstart wird der Benutzer aufgefordert, die Anzahl der Knoten und Kanten anzugeben, bevor er diese eingeben kann. Sie werden wiederum in Listen aufbewahrt, welche in der Datenbasis gespeichert werden um allen Prädikaten zur Verfügung zu stehen. Bsp.: for_schleife_knoten(Beginn, Ende, Daten):- Beginn < Ende, Temp is (Beginn + 1), write((Beginn)), write('. Knoten: '), read(Y), append([Y],Daten,Liste), write(Liste), nl, retract(liste_knoten(Daten)), assert(liste_knoten(Liste)), for_schleife_knoten(Temp, Ende, Liste). Bei der Eingabe ist darauf zu achten, dass jede Eingabe trotzdem mit einem Punkt endet, und eine Kante in der Form [a1, a2]. eingegeben werden muss. Dieses Programm beginnt durch die Eingabe von 'start.' 5. Zusammenfassung Das erarbeitete Wissen der ersten beiden Lösungsmöglichkeiten für unseren Prolog Beleg sind die Grundlage für die Entwicklung des allgemeinen Programms zur Lösung des Problems laut Aufgabenstellung 5 gewesen. Als Hilfsmittel haben wir die Bücher • "Kurs in Logischer Programmierung" von Norbert E. Fuchs, erschienen 1990, Springer-Verlag Wien - New York, sowie • "Programmieren mit PROLOG" von Ulrich Geske, erschienen 1988, Akademie - Verlag Berlin verwendet. Diese bildeten jedoch nur die Grundlage für das bessere Verstehen von PROLOG. Zur Realisierung und zum Testen der Programme wurde die SWI-Prolog Version 5.0.10 verwendet. 6