FB18 - Das Forum für Informatik

fb18.de / Off-Topic / Hard- und Softwarefragen

SWI Prolog

SWI Prolog 2007-12-02 16:42
Fred
Nach Jahren der Abstinenz möchte ich mal wieder ein bischen Prolog benutzen. Hab auch schon mein erstes Prädikat fertig implementiert, dass das letzte Element einer Liste findet [23] Die Aufgabe ist übrigens aus P-99: Ninety-Nine Prolog Problems.

Frage 1: Gibt es eine Möglichkeit, eine lange Beispiel-Liste unter einem Namen abzuspeichern, so dass ich nicht immer [a,b,c,d,e] zum Testen eingeben muss sondern z.B. einfach nur L?

Frage 2: Kann ich Testanfragen direkt in der pl-Datei speichern, so dass sie beim Öffnen der pl-Datei beantwortet werden?

Hab jetzt die ersten neun Aufgaben gelöst. Das macht ja richtig Spaß [28]
% P01 (*) Find the last element of a list. my_last(X, [X]). my_last(X, [_ | T]) :-     my_last(X, T). % P02 (*) Find the last but one element of a list. my_last_but_one(X, [X, _]). my_last_but_one(X, [_ | T]) :-     my_last_but_one(X, T). % P03 (*) Find the K'th element of a list. my_element_at(X, [X | _], 1). my_element_at(X, [_ | T], K) :-     my_element_at(X, T, I), K is I+1. % P04 (*) Find the number of elements of a list. my_number_of_elements(0, []). my_number_of_elements(K, [_ | T]) :-     my_number_of_elements(I, T), K is I+1. % P05 (*) Reverse a list. my_reverse([], []). my_reverse([H | T], Y) :-     my_reverse(T, A),     my_append(H, A, Y). % append an element to a list my_append(X, [], [X]). my_append(X, [H | T], [H | Y]) :-     my_append(X, T, Y). % P06 (*) Find out whether a list is a palindrome. my_palindrome(X) :- my_reverse(X, X), !. % P07 (**) Flatten a nested list structure. my_flatten([], []). my_flatten([H | T], Z) :-     (         is_list(H)      -> (             my_flatten(H, X),             append(X, Y, Z)         )       ; Z = [H | Y]     ),     my_flatten(T, Y). % P08 (**) Eliminate consecutive duplicates of list elements. compress([], []). compress([X, X | Xs], Ys) :- compress([X | Xs], Ys), !. compress([X | Xs], [X | Ys]) :- compress(Xs, Ys). % P09 (**) Pack consecutive duplicates of list elements into sublists. pack([], []). pack([X | Xs], [Y | Ys]) :- pack(X, [X | Xs], Y, Z), pack(Z, Ys). pack(X, [X | Xs], [X | Ys], Z) :- pack(X, Xs, Ys, Z), !. pack(_, Z, [], Z).

RE: SWI Prolog 2007-12-02 17:08
doodles
Frage 1: Gibt es eine Möglichkeit, eine lange Beispiel-Liste unter einem Namen abzuspeichern, so dass ich nicht immer [a,b,c,d,e] zum Testen eingeben muss sondern z.B. einfach nur L?

eine idee, die ich jetzt haette waere
liste_l([a,b,c,d,e])
als Fakt in die Datenbasis einzutragen und dann mit liste_l(L) L mit der Liste zu unifizieren. Vielleicht gibts noch ne andere Möglichkeit, aber wir haben jetzt auch gerade erst mit Listenverarbeitung in SE3 angefangen.

Frage 2: Kann ich Testanfragen direkt in der pl-Datei speichern, so dass sie beim Öffnen der pl-Datei beantwortet werden?

Da hatten wir etwas tolles in der Vorlesung. Leider habe ich das jetzt im Skript nicht gefunden.

Das sah irgendwie so aus:

testdaten(zutestendes_praedikat1).
testdaten(zutestendes_praedikat2).
testdaten(zutestendes_praedikat3).



test :- testdaten(_), write(testdaten), writeln(<IRGENDWIE JA, NEIN>), fail.

aber ich habs nicht mehr genau im kopf

so das beim aufruf von test alle möglichkeiten von testdaten ausprobiert werden und die jeweiligen ergebnisse ausgegeben.
Das mit dem <IRGENDWIE JA, NEIN> war glaub ich als extra regel, dass bei erfolg 'ja' geschrieben wird und bei miserfolg 'nein'.

Ich hoffe das hilft.


[edit]

AHH… ich habs gefunden

test :- test_daten(X), write(X), diagnose(X), fail.

diagnose(X) :- X, writeln(' yes').
diagnose(X) :- not(X), writeln(' no').

[/edit]

RE: SWI Prolog 2007-12-02 17:13
Fred
eine idee, die ich jetzt haette waere
liste_l([a,b,c,d,e])
als Fakt in die Datenbasis einzutragen und dann mit liste_l(L) L mit der Liste zu unifizieren.
Das ist schon mal ganz nett, danke [28]

2 ?- element_at(X,L,5),buchstaben(L). X = e, L = [a, b, c, d, e, f, g, h, i|...] Yes

RE: SWI Prolog 2007-12-02 19:05
low_level
test :- test_daten(X), write(X), diagnose(X), fail. diagnose(X) :- X, writeln(' yes'). diagnose(X) :- not(X), writeln(' no').

Das wäre mir zu rechenaufwendig. Es gibt in Prolog ein elegantes if-then-else:

diagnose(X) :- (call(X) -> write('yes') ; write('no')), nl.
Das "write" und "nl" habe ich getrennt, da ein x-beliebiges Prolog das Prädikat writeln/1 nicht kennen muss. Näheres dazu steht im ISO-Standard für Prolog, in der Bibliothek als R37056 erhältlich.

Roland

RE: SWI Prolog 2007-12-03 01:28
f0k
Frage 2: Kann ich Testanfragen direkt in der pl-Datei speichern, so dass sie beim Öffnen der pl-Datei beantwortet werden?
Wenn Du in die Datei direkt etwas hineinschreibst wie :- print('Holt mich hier raus')., wird es beim Öffnen der Datei ausgeführt. Ein gesondertes Testprädikat ist aber praktischer, das kann man dann auch tracen (siehe help(trace) und evtl. help(guitracer)).

RE: SWI Prolog 2007-12-03 15:55
Fred
In welchen Veranstaltungen am FB18 wird Prolog eigentlich benutzt? Ich erinnere mich noch an ein paar kleine Aufgaben in LOS, aber das war mehr freiwillig, d.h. kaum einer hat's gemacht. Gibt's Projekte, in denen man mit Prolog arbeitet? Das wäre doch bestimmt ganz interessant.

RE: SWI Prolog 2007-12-04 00:52
low_level
In welchen Veranstaltungen am FB18 wird Prolog eigentlich benutzt? Ich erinnere mich noch an ein paar kleine Aufgaben in LOS, aber das war mehr freiwillig, d.h. kaum einer hat's gemacht. Gibt's Projekte, in denen man mit Prolog arbeitet? Das wäre doch bestimmt ganz interessant.

Es gab mal bei Herrn Menzel die Vorlesung "Logikprogrammierung" (für Fortgeschrittene), die gehörte zu den Lehrveranstaltungen, die ich auch nach dem Studium noch in sehr guter Erinnerung behalten werde. Es war eine kleine Runde von 8 Teilnehmern, die alle sehr diskussionsfreudig waren. Zusammen mit Herrn Menzel haben wir uns dann aufgemacht, die Geheimnisse von Prolog aufzudecken. Herr Menzel hatte für jede Veranstaltung auch Folien vorbereitet, aber meistens haben wir die aufgrund der vielen sinnvollen Zwischenfragen nicht geschafft. :)

Roland

RE: SWI Prolog 2007-12-06 17:43
f0k
In welchen Veranstaltungen am FB18 wird Prolog eigentlich benutzt? Ich erinnere mich noch an ein paar kleine Aufgaben in LOS, aber das war mehr freiwillig, d.h. kaum einer hat's gemacht. Gibt's Projekte, in denen man mit Prolog arbeitet? Das wäre doch bestimmt ganz interessant.

In SE3 (Softwareentwicklung 3) wird entweder Prolog (und ein kleines bisschen Scheme) oder Scheme (und ein kleines bisschen Prolog) gelehrt, je nachdem, wofür man sich entscheidet. Das entspricht für euch Diplomer wohl am ehesten P1 (hieß das so?), aber mit Fokus auf einem der beiden Paradigmen.
In der vorlesungsfreien Zeit nach jedem Wintersemester findet außerdem ein zweiwöchiges Praktikum Logikprogrammierung statt. Letztes Semester haben wir dort das Brettspiel Carcassonne umgesetzt in SWI-Prolog mit XPCE, mit grafischer Oberfläche, Mehrspielermodus und Netzwerkunterstützung. Sehr empfehlenswert (das Praktikum, meine ich - das Spiel aber auch).

RE: SWI Prolog 2007-12-31 00:39
Fred
mit grafischer Oberfläche […] und Netzwerkunterstützung.
Klingt interessant! Da kann mein Vier-Gewinnt in 20 Zeilen leider nicht mithalten… [26]

spielen :-     write('  4 Gewinnt'), nl, Z = [0,0,0,0,0,0,0,3], flatten([Z,Z,Z,Z,Z,Z], E),     append(E, [4,4,4,4,4,4,4,4], F), anzeigen(F), spielen(F, 1, 2). spielen(F, X, Y) :-     repeat, spalte(S), zug(F, S, X, G), !, nl, anzeigen(G), nl,     (win(G, X) -> write(' Gewinner: '), write(X), nl ; spielen(G, Y, X)). spalte(S) :- repeat, get_code(C), S is C-48, S > 0, S < 8, !. zug(F, 1, X, G) :- zug(F, X, G), !. zug([H|F], S, X, [H|G]) :- T is S-1, zug(F, T, X, G). zug([0,A,B,C,D,E,F,G,Z|R], X, [X,A,B,C,D,E,F,G,Z|R]) :- Z > 0, !. zug([0,A,B,C,D,E,F,G|R], X, [0,A,B,C,D,E,F,G|Q]) :- zug(R, X, Q). anzeigen(F) :-     write('-------------'), nl, forall(member(X, F), drucken(X)),     write('-------------'), nl, write('1 2 3 4 5 6 7'), nl. drucken(0) :- write('  ').        drucken(1) :- write('X '). drucken(2) :- write('O ').        drucken(3) :- nl.        drucken(4). win([X,_,_,_,_,_,_,_, X,_,_,_,_,_,_,_, X,_,_,_,_,_,_,_, X |_], X). win([_,_,_,X,_,_,_,_, _,_,X,_,_,_,_,_, _,X,_,_,_,_,_,_, X |_], X). win([X,_,_,_,_,_,_,_, _,X,_,_,_,_,_,_, _,_,X,_,_,_,_,_, _,_,_,X |_], X). win([X,X,X,X|_], X).    win([_|R], X) :- win(R, X).    :- repeat,spielen,fail.
Hach, die gute alte Zeit der 20-Zeiler… [28]

RE: SWI Prolog 2007-12-31 15:02
f0k
Klingt interessant! Da kann mein Vier-Gewinnt in 20 Zeilen leider nicht mithalten… [26]
Hast es aber sehr elegant gelöst! Die Verwendung der 3 im Spielfeld gefällt mir zum Beispiel [23]

RE: SWI Prolog 2007-12-31 15:09
Fred
Was mir gerade auffällt… es ist gar kein Unentschieden vorgesehen [28]