Prolog Fragen

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • Prolog Fragen

    Hallo erstmal,

    ich bin totaler Anfänger in Prolog und muß für die Uni ein Programm schreiben. Ich hab schon einiges hinbekommen, aber so ein paar kleine Probleme habe ich noch:

    1. Wie kann ich aus einer Liste wieder ein Atom oder String machen? Wenn ich die Liste ausgebe werden ja alle einzelnen Buchstaben mit Komma getrennt, die hätte ich aber gerne zusammen.

    2. Gibt es in Prolog so etwas wie "if"? Ich will dass der Benutzer etwas eingeben kann. Wenn er etwas bestimmtes eingibt soll auch etwas bestimmtes passieren. Gibt er etwas anderes bestimmtes ein soll etwas anderes bestimmtes passieren. Gibt er weder das eine noch das andere ein soll etwas anderes passieren. Leider hab ich dafür noch nichts gefunden.

    Das waren erstmal die Fragen... kann aber gut sein dass ich nachher noch mit weiteren Fragen komme.

    Vielen Dank schonmal an die, die mir antworten!

    Mike
  • 1. Sollst du wirklich solche kranken Sachen machen oder hast du vielleicht die Aufgabe falsch verstanden? Wie dem auch sei. Hier gibt es einige Infos:
    wwwcgi.rdg.ac.uk:8081/cgi-bin/…g/prolog/ploghelp/strings
    Dieses PDF gibt auch ein paar String-Funktionen preis:
    www-ai.cs.uni-dortmund.de/LEHR…me_MetaProgrammierung.pdf

    2. Mit den Prologregeln prüfst du Bedingungen ab. Das ist im Prinzip dein if. Gleichnamige Regeln verhalten sich vereinfacht gesehen wie OR und die Komma-Getrennten Bedingungen wie AND.
  • Wenn du schon so fragst mach ich wohl etwas falsch ;-).

    Ich erklär mal kurz was ich machen muss: der Benutzer gibt ein Verb ein, und rauskommen soll die Vergangenheitsform. Das ganze nur für die schwachen Vergangenheitsformen (also einfach anstatt der letzten beiden Buchstaben ein te... z.B. lachte) und die beiden Worte gehen und bleiben.

    Ich hab das jetzt so gemacht: Zuerst ein Wort X eingelesen. Das Wort dann mit atom_Chars in eine Liste mit einzelnen Chars verwandelt. Dann die Liste per reverse umgedreht. Jetzt mit dem "|" die ersten beiden Buchstaben vom Rest trennen. Dann den Rest ausgeben und noch ein "te" hinten dran schreiben. Problem ist eben nur, dass das Ganze jetzt so aussieht: [l, a, c, h]te. Ist natürlich unschön.

    Die beiden Spezialfälle hab ich ohne ein "if" nicht mit in die Funktion reingekriegt. Deshalb hab ich bisher einfach 3 Funktionen gemacht, eine in der noch mit drin steht, dass X nicht gehen und nicht bleiben ist, und in den anderen eben dass X gehen, bzw. bleiben ist. Hier ists natürlich unschön, dass man ein Wort 2 bzw. 3 Mal eingeben muss, weil das Programm eben die einzelnen Funktionen nacheinander macht. Leider scheint sich das Programm das eingelesene X ja nicht von einer Funktion zur nächsten zu merken.

    Was genau meinst du mit den Prologregeln, die Bedingungen abprüfen? Theoretisch ist mir das schon klar, z.B. wenn man überprüfen will ob jemand der Vorfahre von jemand anderem ist. Aber wenn das Programm eben je nach Variante etwas anderes machen muss, verstehe ich nicht, wie ich das programmieren soll...

    Edit: Ah, und jetzt hab ich noch ne andere Frage: Mit dem bagof Befehl erstelle ich ja mehrere Listen. Jetzt würde ich gerne jeweils auf das 1. Item jeder Liste zugreifen und die vergleichen. Ist das möglich? Da steht dann eine Zahl und ich will die kleinste Zahl herausfinden, die da auftauchen kann. Also brauche ich einen Zwischenspeicher, in dem ich jeweils den Inhalt des 1. Items der Listen kopiere, und eine Variable in die ich den Inhalt kopiere, falls der kleiner ist als was bisher in der Variable steckt. Das würde ich einfach mit X<Y, X is Y. machen, oder?

    The post was edited 1 time, last by LikeMike ().

  • Ohne Quellcode kann ich dir nur sehr oberflächlich helfen. Ich hoffe das ist dir klar. :)

    Schreibe mal das "te" nicht einfach hinten dran sondern tu es mit in die Liste. Dann versuche atom_Chars einmal umgedreht zu verwenden. Gute prolog-Programme funktionieren gleichzeitig in beide Richtungen. Gib also dann deine Liste hinnein und gibt das neue atom aus.

    Schau dir mal dieses Beispiel an:
    max1(X, Y, X) :- X>=Y.
    max1(X, Y, Y) :- X<Y.
    Die Regeln greifen also nur, wenn die dahinterstehenden Bedingungen erfüllt sind.

    Ich habe keine Ahnung wie du bagof verwendest. Wenn du aber 2 Listen hast, kann kommst du auch an ihre 2 ersten Elemente und dann kannst du sie auch vergleichen.
  • Ich bin wie gesagt noch ein absoluter Neuling in Prolog, deshalb sind mir wohl auch die ganzen Regeln noch nicht vollkommen klar...

    Aber das erste Problem konnte ich mit deiner Hilfe schonmal lösen! Ich bin selbst nicht drauf gekommen, dass ich atom_Chars auch umdrehen kann, jetzt hab ich eine schöne Ausgabe ohne die Kommas.

    Ich hab das schon ganz ähnlich wie deine Beispiele gemacht... das Problem ist nur, dass wenn ich bei jedem oben read(X) drinstehen habe, er eben nach der ersten Eingabe nur die oberste Regel anguckt, bei der 2. Eingabe die 2. Regel und bei der 3. dann die 3. Regel. Ist natürlich blöd wenn ich immer z.B. gehen dreimal eingeben muss, bevor er die richtige Regel gefunden hat und ging ausgibt. Ich müsste also entweder das X von der 1. Regel irgendwie speichern, und dafür sorgen, dass nachdem die erste Regel abbricht weil die Bedingung nicht erfüllt ist, er das X sofort für die 2. Regel überprüft.

    Also mal ein Quelltextbeispiel:

    Verb :- read(X), X=gehen, write("ging").

    Verb:- read(X), X=bleiben, write("blieb").

    ...

    Bagoff verwende ich denke ich ganz normal :-). Hier mal das Beispiel:

    findeWeg(X, Y) :-
    bagof(Weg1, wegsuche(X, Y, Weg1), Wege),

    Wenn ich da jetzt an den Header der Liste rankommen will ist das kein Problem ([[Laenge|_]|_]=Wege,), allerdings weiß ich nicht, wie ich an die Header der anderen Listen, die damit erstellt wurden rankomme. Also theoretisch brauche ich eine Schleife, in der ich nach jedem Durchgang den Header überprüfe und ggf. in eine andere Variable schreibe.
  • er eben nach der ersten Eingabe nur die oberste Regel anguckt, bei der 2. Eingabe die 2. Regel und bei der 3. dann die 3. Regel.

    Das macht er doch gar nicht oder ich verstehe nicht was du meinst. Wenn du read() aufrufst, werden ALLE read-Regeln geprüft (außer du machst einen Cut, aber damit solltest du dich erst einmal nicht beschäftigen) und es wird auch das Ergebnis von allen erfolgreichen read()-Regeln ausgegeben. Deswegen entsteht ja auch ein regelrechter Anfragebaum. Wenn du die Regel rekursiv neu aufrufst, werden wieder alle Regeln geprüft usw. (deswegen ist ja eine Abbruchbedingung so wichtig).

    bagof:
    Welch anderen Listen meinst du denn?
  • Hmm, ich versuchs nochmal so zu erklären, wahrscheinlich hab ich irgendeinen Denkfehler in meinem Programm:

    Ich rufe die Regel z.B. mit "verben" auf. in der Regel liest er dann das X. Jetzt hab ich 3 verschiedene Regeln die "verben" heissen. In der ersten steht mit drin, dass X weder gehen noch bleiben ist. In der zweiten, dass X gehen ist, und in der 3. dass X bleiben ist.Wenn der User jetzt verben eingibt, und danach eben das Verb, von dem er gerne die Vergangenheitsform hätte, hab ich folgendes Problem: Wenn er irgendein Verb ausser gehen und bleiben eingibt funktioniert es wunderbar. Wenn er gehen eingibt und Enter drückt erscheint einfach eine weiter leere Zeile. Gibt er dann nochmal gehen ein, dann funktioniert das (also quasi nach dem 1. Enter guckt er nur in die erste "verben" Regel, nach dem 2. Enter guckt er in die zweite "verben" Regel). Bei bleiben das Selbe, nur kommt da eben das richtige erst nach dem 3. Enter.

    Mit dem bagoff meine ich das so: Es gibt sagen wir mal 5 verschiedene Wege um ans Ziel zu kommen, also erstellt er auch 5 Listen. An erster Stelle der Liste steht immer die Anzahl der Stationen, die der Weg lang ist. Um jetzt herauszufinden, wieviele Stationen der kürzeste Weg lang ist, muss ich ja theoretische den Header von jeder der 5 Listen miteinenader vergleichen. So wie ich es bisher mache, bekomme ich nur den ersten Header... dank der relativ einfachen Knowledge Base ist das Ergebnis zwar auch immer richtig, aber der Lösungsweg stimmt natürlich nicht wirklich.