2017-11-04 1 views
3

Ich programmiere eine Familie in Prolog und ich habe Probleme mit der Umsetzung des Neffen. Wenn ich frage, ob Erick der Neffe von Alberto ist, ist es wahr, wenn es falsch zurückkehren sollte, weil Alberto der Vater von Erick ist, aber es funktioniert für alle anderen Fälle, die wahr sein sollten. Wenn mir jemand helfen könnte, wäre ich sehr dankbar. Mein Code:Neffe meines eigenen Vaters in Prolog

man(beto). 
man(fransisco). 
man(alberto). 
man(jaime). 
man(manolo). 
man(nolo). 
man(lito). 
man(manuel). 
man(erick). 
man(jesu). 
man(jesus). 
woman(emi). 
woman(harumi). 
woman(haru). 
woman(yuneisi). 
woman(yasmeli). 
woman(mioara). 
woman(elia). 
woman(iza). 
woman(alice). 
woman(ofelia). 
woman(arlet). 
parent(manuel, alberto). 
parent(ofelia, alberto). 
parent(manuel, jaime). 
parent(ofelia, jaime). 
parent(manuel, manolo). 
parent(ofelia, manolo). 
parent(alberto, erick). 
parent(alberto, beto). 
parent(alberto, fransisco). 
parent(emi, erick). 
parent(emi, beto). 
parent(manolo, nolo). 
parent(manolo, arlet). 
parent(nolo, lito). 
parent(iza, lito). 
parent(mioara, yuneisi). 
parent(mioara, yasmeli). 
parent(jaime, yuneisi). 
parent(jaime, yasmeli). 
parent(jesus_padre, jesu) 
parent(jesus_padre, alice). 
parent(jesus_padre, haru). 
parent(harumi, haru). 
parent(harumi, jesu). 
parent(harumi, alice). 
father(X,Y) :- parent(X,Y), man(X). 
mother(X,Y) :- parent(X,Y), woman(X). 
brother(X,Y) :- man(X), parent(F, X), parent(F, Y). 
sister(X,Y) :- woman(X), parent(P, X), parent(P, Y). 
grandpa(X,Y) :- father(F,Y), father(X,F), man(X). 
grandma(X,Y) :- father(F,Y), mother(X,F), woman(X). 
son(X,Y) :- father(Y,X), man(X). 
nephew(X,Y) :- father(F,X), brother(F,Y). 
+1

Code sollte nicht funktionieren, weil Sie einen Syntaxfehler in der Zeile „parent (jesus_padre, jesu)“ haben, vergessen Sie einen Punkt stellen das Ende. Es sollte jetzt funktionieren und noch ein Tipp: Tippen Sie "Guitracer" und dann "Tracer" Wenn Sie irgendwelche Fehler haben, können Sie sehen, wo es scheitert –

Antwort

5

Neben dem fehlenden Punkt nach parent(jesus_padre, jesu) Wie von @LuaiGhunim gibt es ein paar anderen Probleme mit den Prädikaten sind. Deine Definition von Bruder/2 ist zu allgemein. Niemand ist sein eigener Bruder, aber wenn Sie Ihr Prädikat Abfrage finden Sie mehrere solcher Fälle:

?- brother(X,X). 
X = beto ; 
X = beto ; 
X = fransisco ; 
X = alberto ; 
X = alberto ; 
X = jaime ; 
X = jaime ; 
X = manolo ; 
X = manolo ; 
X = nolo ; 
X = lito ; 
X = lito ; 
X = erick ; 
X = erick ; 
X = jesu ; 
X = jesu ; 
false. 

Sie können dies leicht beheben, indem das Hinzufügen eines Ziel dif/2:

brother(X,Y) :- 
    dif(X,Y), 
    man(X), 
    parent(F, X), 
    parent(F, Y). 

Nun ist die Abfrage oben nicht als es sollte:

Sie werden noch zweimal viele Paare erhalten:

?- brother(X,Y). 
X = beto,    % <- 1st occurrence 
Y = erick ;    % <- 1st occurrence 
X = beto, 
Y = fransisco ; 
X = beto,    % <- 2nd occurrence 
Y = erick ;    % <- 2nd occurrence 
. 
. 
. 

Der Grund dafür ist, dass Sie es über die Mutter oder den Vater ableiten können. Im obigen Beispiel (beto und erick) gelangen Sie über emi oder alberto dorthin. Diese Lösungen können redundant sein, aber sie sind korrekt. Das gleiche gilt für Ihre Prädikat Schwester/2:

?- sister(X,X). 
X = haru ; 
X = haru ; 
X = yuneisi ; 
X = yuneisi ; 
X = yasmeli ; 
X = yasmeli ; 
X = alice ; 
X = alice ; 
X = arlet. 

Das Heilmittel ist das gleiche wie oben:

sister(X,Y) :- 
    dif(X,Y), 
    woman(X), 
    parent(P, X), 
    parent(P, Y). 

?- sister(X,X). 
false. 

?- sister(X,Y). 
X = haru, 
Y = jesu ; 
X = haru, 
Y = alice ; 
X = haru, 
Y = jesu ; 
. 
. 
. 

Deine Definition von Oma/2 und Opa/2 auf der anderen Seite zu spezifisch ist. Um dies zu sehen sich die folgenden Fakten zu Ihrem Code hinzu:

man(m1). 
man(m2). 

woman(w1). 
woman(w2). 
woman(w3). 

parent(m1,w1). 
parent(w1,w2). 
parent(w2,w3). 

Dann sollten Sie die folgenden Abfragen erfolgreich sein, aber sie scheitern statt:

?- grandpa(m1,w2). 
false. 

?- grandma(w1,w3). 
false. 

Der Grund dafür ist, dass die Zwischen Eltern in Ihrer Definition von Opa/2 und Oma/2 ist ein Vater/2, wo es ein Elternteil/2 sein sollte. Zusätzlich sind die letzten Ziele (man(X) und woman(X)) redundant, da sie bereits von vater/2 bzw. mother/2 gedeckt sind. Stattdessen könnte man die beiden Prädikate wie so definieren:

grandpa(X,Y) :- 
    parent(F,Y), 
    father(X,F). 

grandma(X,Y) :- 
    parent(F,Y), 
    mother(X,F). 

Nun werden die obigen Abfragen das gewünschte Ergebnis ergeben:

?- grandpa(m1,w2). 
true. 

?- grandma(w1,w3). 
true. 

schließlich ein Neffe nach dem Cambridge Dictionary ist ein Sohn deiner Schwester oder Bruder oder ein Sohn der Schwester oder des Bruders deines Ehemannes oder deiner Frau. Da Sie keine Prädikate für Ehemänner und Ehefrauen haben, bleibe ich mit dem Sohn Ihrer Schwester oder Ihres Bruders Teil. Wenn Sie Fakten für Ehemänner und Ehefrauen hinzufügen, können Sie zusätzliche Regeln hinzufügen, um den anderen Teil der Definition abzudecken.Sie können wie so den ersten Teil der Definition in Prolog schreiben:

nephew(X,Y) :- 
    man(X), 
    dif(F,Y), 
    parent(P,F), 
    parent(P,Y), 
    parent(F,X). 

Wenn Sie das Prädikat Abfrage gibt es keine erick/alberto Lösung mehr:

?- nephew(erick,X). 
X = jaime ; 
X = manolo ; 
X = jaime ; 
X = manolo ; 
false. 
+1

Vielleicht bin ich Old School, aber ich verstehe nicht, warum dif/2 vorschlagen wenn ein Standard-Builtin funktionieren würde ... Was ist mit Benutzern einfacher Prologs, die bereit sind, das Basic zu lernen? – CapelliC

+3

@CapelliC: Ich würde argumentieren, dass dif/2 ist einfacher zu verwenden als die Alternativen, vor allem für neue Benutzer. Berücksichtigen Sie die folgenden Abfragen: '? - A \ = B.' ergibt 'false.', während'? - dif (A, B) .' ergibt 'dif (A, B) .', dh die Bedingung wird weitergegeben . Folglich ergibt "? - A \ = B, A = a, B = b" 'falsch.aber'? - A = a, B = b, A \ = B. 'gelingt mit' A = a, B = b. Auf der anderen Seite "? - A = a, B = b, dif (A, B)." Und "? - dif (A, B), A = a, B = b." beide ergeben 'A = a, B = b.'. Als Konsequenz muss man sicherstellen, dass ... – tas

+2

@CapelliC: ... dass ein Ziel mit \ =/2 gepostet wird, nachdem beide Argumente geerdet sind, da sogar '? - A = a, A \ = B, B = b. ergibt "falsch". Dies kann zu Fehlern führen, die für neue Benutzer schwer zu finden sind. Ich bin mir bewusst, dass dif/2 nicht in allen Prolog-Implementierungen verfügbar ist, aber es ist in vielen. Und ich bin sicherlich nicht dagegen, Standard-Einbauten zu verwenden, ich finde nur dif/2, um die leichtere/elegantere Wahl zu sein, also schlage ich es vor :-) – tas

1

Prolog geht es um Beziehungen ist. Joins spielt eine fundamentale Rolle. So kann man oft in Begriffen von "Ausbeuten" oder Funktionen über die Datenbank denken und den Datenzugriffsplan mittels Joins (Klauseln, d. H. Logischen Formeln) entwerfen und steuern, die Datensätze erzeugen - wie SQL. Die prozedurale Ausführung über die abgerufenen Daten wird in (fast) der gleichen Sprache ausgedrückt: Joins, geben uns einen Vorgeschmack auf deklarative Programmierung. Wie auch immer, hier sind die von @tas in Standard-Prolog bereitgestellt Klauseln:

brother(X,Y) :- 
    man(X), 
    parent(F, X), 
    parent(F, Y), 
    X\=Y. 

sister(X,Y) :- 
    woman(X), 
    parent(P, X), 
    parent(P, Y), 
    X\=Y. 
+1

Die Definition wird falsch, wenn man 'X \ = Y' noch ein Tor vorlegt. Wenn Sie ['iso_dif (X, Y)'] (https://stackoverflow.com/a/20238931) verwenden, kann dies nicht passieren! Es gibt einen sauberen Fehler aus. So können Sie auch im Standard Prolog korrekte und robuste Programme schreiben! – false