2009-09-15 7 views
9

Die folgende Geschichte stammt aus N. Wirths (1976) Algorithmen + Datenstrukturen = Programme.Wie kann ich in Prolog "Ich bin mein eigener Opa" umsetzen?

heiratete ich eine Witwe (lassen Sie uns ihre W nennen) , der eine Tochter grown-up hatte (nennen wir sie D). Mein Vater (F), der uns oft besuchte , verliebte sich in meine Stieftochter und heiratete sie. Also, mein Vater wurde mein Schwiegersohn und meine Stieftochter wurde meine Mutter. Einige Monate später gebar meine Frau einen Sohn (S1), der der Schwager meines Vaters, sowie als mein Onkel wird. Diese Frau meines Vaters, das heißt, meine Stieftochter, hatte auch einen Sohn (S2).

Ich bin versucht, diese Beziehungen in Prolog zu modellieren, um schließlich werde ich in der Lage sein, zu geben:

| ?- grandfather(i,i). 

Und ich werde ein „Ja“ oder „Nein“ zu geben ob ich mein eigener Opa bin oder nicht.

Hier ist der Code, den ich bisher geschrieben habe (grandpa.pl):

aunt(X,Y):- 
    sibling(X,Z), 
    parent(Z,Y), 
    female(X). 

brother(X,Y):- 
    sibling(X,Y), 
    male(X). 

brother_in_law(X,Y):- 
    child(X,Z), 
    married(Z,W), 
    parent(W,Y), 
    not(sibling(X,Y)), 
    male(X). 

brother_in_law(s1,f). 

child(X,Y):- 
    parent(Y,X). 

daughter(X,Y):- 
    parent(Y,X), 
    child(X,Y), 
    female(X). 

daughter(d,w). 

father(X,Y):- 
    parent(X,Y), 
    male(X). 

father(f,i). 

father_in_law(X,Y):- 
    child(X,Z), 
    married(Y,Z), 
    not(child(X,Y)), 
    male(X). 

grandparent(X,Y):- 
    parent(X,Z), 
    parent(Z,Y). 

grandmother(X,Y):- 
    grandparent(X,Y), 
    female(X). 

grandfather(X,Y):- 
    grandparent(X,Y), 
    male(X). 

grandchild(X,Y):- 
    child(X,Z), 
    child(Z,Y). 

married(X,Y):- 
    wife(X,Y), 
    female(X). 

married(X,Y):- 
    husband(X,Y), 
    male(X). 

married(i,w). 
married(f,d). 

mother(X,Y):- 
    parent(X,Y), 
    female(X). 

parent(X,Y):- 
    child(Y,X). 

sibling(X,Y):- 
    parent(Z,X), 
    parent(Z,Y). 

sister(X,Y):- 
    sibling(X,Y), 
    female(X). 

son(X,Y):- 
    parent(Y,X), 
    male(X). 

son(s1,w). 
son(s2,d). 

son_in_law(X,Y):- 
    child(X,Z), 
    not(child(X,Y)), 
    married(Z,Y), 
    male(X). 

son_in_law(f,i). 

step_daughter(X,Y):- 
    child(X,Z), 
    married(Z,Y), 
    not(child(X,Y)), 
    female(X). 

step_daughter(d,i). 

step_parent(X,Y):- 
    married(X,Z), 
    parent(Z,Y), 
    not(parent(X,Y)). 

step_father(X,Y):- 
    step_parent(X,Y), 
    male(X). 

step_mother(X,Y):- 
    step_parent(X,Y), 
    female(X). 

step_mother(d,i). 

uncle(X,Y):- 
    sibling(X,Z), 
    parent(Z,Y), 
    male(X). 

uncle(s1,i). 

Gerade jetzt eine Menge Ärger mit Kreis Definitionen Ich habe, so dass ich in Endlosschleifen erhalten, wenn die Abfrage ausgeführt werden : Großvater (ich, ich).

Zum Beispiel habe ich:

(1 ms) ja {trace} | ? - Großvater (ich, ich). 1 1 Anruf: Großvater (ich, ich)?
2 2 Anruf: Großeltern (i, i)?
3 3 Anruf: Eltern (i, _103)?
4 4 Anruf: Kind (_127, i)?
5 5 Anruf: Eltern (i, _151)?
6 6 Anruf: Kind (_175, i)?
7 7 Anruf: Eltern (i, _199)?
8 8 Anruf: Kind (_223, i)?
9 9 Anruf: Eltern (i, _247)?
10 10 Anruf: Kind (_271, i)?
11 11 Anruf: Eltern (i, _295)?
12 12 Anruf: Kind (_319, i)?
13 13 Anruf: Eltern (i, _343)?
14 14 Anruf: Kind (_367, i)?
15 15 Anruf: Eltern (i, _391)? Diese
...

ist, weil Kind definiert sich wie ein Elternteil hat, und Eltern definiert sich ein Kind hat, die (wie in den oben genannten Prädikate sehen werde ich geschrieben).

Kann mir jemand helfen, meine Prädikate für diese Beziehungen neu zu definieren, damit ich feststellen kann, ob ich mein eigener Opa bin?

+0

Heh, ich hatte eigentlich, dass für meine AI-Klasse zu tun. Ich frage mich, ob ich noch den Code habe ... Ich werde nachsehen, wenn ich nach Hause komme. Ich erinnere mich, dass es auch mein Gehirn schmerzte. –

+5

Sie verwenden Prolog in West Virgina? ;-) –

+0

@ T.E.D .: Shh! Der TXI wird dich hören! –

Antwort

3

Mein Prologs Kurs hat vor langer langer Zeit, aber was

parent(X,Y):- 
    child(Y,X). 

zu entfernen und nur jede Nutzung von parent(A,B) mit child(B,A) zu ersetzen? Sie können immer noch Fakten über Eltern hinzufügen, weil die inverse Regel immer noch verfügbar ist - Sie könnten diese auch entfernen, aber in diesem Fall können Sie keine Fakten über Eltern mehr verwenden und Sie müssen alle Ihre Fakten als Kind schreiben (a, b) auch.

Es ist das gleiche, nicht wahr?

1

Beachten Sie, dass mein Wissen über Prolog alt ist (und nie tief) ...

Ich glaube, Sie brauchen, um Eltern zu machen (oder Kind) primäre (nicht auf andere Beziehungen abhängig).

child(X,Y):- 
    parent(Y,X). 

parent(X,Y):- 
    child(Y,X). 

ist, was wahrscheinlich die Schleifen verursacht.

5

entfernte ich alles, was in Ihrem Code nicht notwendig war und änderte ein paar Dinge, und das ist, was ich am Ende mit:

% married(Husband, Wife) 
married(i,w). 
married(f,d). 

Man würde annehmen, dass married(X,Y) :- married(Y,X), aber es führt zu bösen Kreis Beweise, so dass wir Ich werde den Ehemann zuerst per Konvention festlegen.

Über Elternschaft, ähnliches Problem entsteht. Wir müssen Stiefeltern als echte Eltern betrachten, weil das Rätsel davon abhängt. Wir wissen, dass du niemals dein eigener biologischer Vorfahre sein kannst!

Allerdings läuft parent(X,Y) :- parent(Z,Y), married(X,Z) in die gleichen Probleme, so habe ich gerade gemacht bio_parent bezeichnen biologische Elternschaft.

bio_parent(f,i). 
bio_parent(w,d). 
bio_parent(w,s1). 
bio_parent(i,s1). 
bio_parent(d,s2). 
bio_parent(f,s2). 

Bitte beachte, dass wir über beide Eltern ausdrücklich sein müssen, da gibt es keine Möglichkeit biologische Elternschaft aus der Ehe zu schließen! Auch Ihre Art der Spezifikation war problematisch. Sie hatte so etwas wie:

son(X,Y) :- child(X,Y), male(X). 
son(a,b). 

jedoch von diesen Regeln könnten Prolog nicht folgern child(a,b), so dass Sie whith Söhne gelandet, die keine Kinder waren! Dies ist ein paar Mal in Ihrem Code passiert. Wenn Sie b von a ableiten, geben Sie immer a als Tatsache an! Auf den ersten Blick scheint dies ein Mangel von Prologs zu sein, ist es aber nicht. Denken Sie daran, dass jede Klausel nur eine Möglichkeit ist, ein bestimmtes Prädikat nachzuweisen. Im obigen Beispiel haben Sie angegeben, dass jedes männliche Kind ein Sohn ist, und auch a ist so, dass es ein Sohn von b ist. Nirgendwo wird gesagt, dass ein männliches Kind die einzige Möglichkeit ist, dass jemand ein Sohn sein könnte, a könnte nur die Ausnahme sein.

Die nächste ist ein bisschen wortreich wie unsere Definition von married zwingt uns Step Väter getrennt von Stiefmütter zu behandeln. Wir vereinheitlichen sie sofort zu den Eltern, sofort.

Wie ich oben gesagt habe, müssen wir Schritteltern als Eltern betrachten!

Es gab auch einige andere Fehler in Ihrem Code, die ich herausnahm, ich zeige Ihnen nur einige Beispiele, damit Sie daraus lernen können.

Erstens, hier sagen Sie, dass weibliche Frauen verheiratet sind und männliche Ehemänner verheiratet sind. Also, männliche Ehefrauen wären unverheiratet. Sollte es umgekehrt sein, werden verheiratete Frauen Frauen genannt!

% wrong: 
% 
% married(X,Y):- 
% wife(X,Y), 
% female(X). 
% 
% married(X,Y):- 
% husband(X,Y), 
% male(X). 
% 
% right: 
% wife(X,Y) :- married(Y,X). % according to our new definition of 'married' 
% husband(X,Y) :- married(X,Y). 

Hier habe ich die letzte Zeile, wie Sie selbst Ihre eigenen Geschwister normalerweise nicht berücksichtigen:

% sibling(X,Y):- 
% parent(Z,X), 
% parent(Z,Y), 
% X \= Y. % added this 

Die letzten beiden sind Fakten auf dem falschen Prädikat wieder. Sie überschreiben grundsätzlich Prologs Abzug mit ihnen. Sie sollten abgezogen werden, nicht als Fakten angegeben!

% son_in_law(f,i). 
% step_mother(d,i). 

Jetzt versuchen Sie das Programm so. Und seien Sie nicht überrascht: Sie sind nicht die Einzigen, die ihre eigenen Großeltern sind! ;-)

0
couples(i,w). 
mother_of(w,d). 
father_of(f,i). 
couples(f,d). 
son_in_law(f,i). 
mother_of(d,i). 
mother_of(w,s1). 
mother_of(d,s2). 
grand(F,C):- son_in_law(F,C),couples(H,D),mother_of(D,C). 
grand(F,C):- father_of(F,D),father_of(D,C). 

Abfrage

?-grand(i,i).