2009-09-15 6 views
9

L'histoire suivante est tirée de N. Wirth (1976) Algorithms + Datastructures = Programs.Comment puis-je implémenter, "Je suis mon propre grand-père", dans Prolog?

J'ai épousé une veuve (appelons-la W) qui avait une fille adulte (appeler D). Mon père (F), qui nous rendait souvent visite, est tombé amoureux de ma belle-fille et l'a épousée. Par conséquent, mon père est devenu mon beau-fils et ma belle-fille est devenue ma mère. Certains mois plus tard, mon épouse a donné naissance à un fils (S1), qui est devenu le beau-frère de mon père, ainsi que comme mon oncle. Cette femme de mon père, qui est, ma belle-fille, avait aussi un fils (S2).

Je tente de modéliser ces relations Prolog donc finalement je serai en mesure de taper:

| ?- grandfather(i,i). 

et je serai donné un « oui » ou un « non » sur si je suis ou non mon propre grand-père.

Voici le code que je l'ai écrit à ce jour (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). 

En ce moment, je vais avoir beaucoup de mal avec les définitions circulaires pour que je sois dans une boucle infinie lors de l'exécution de la requête : grand-père (i, i).

Par exemple, j'ai:

(1 ms) oui {trace} | ? - grand-père (i, i). 1 1 Appel: grand-père (i, i)?
2 2 Appel: grand-parent (i, i)?
3 3 Appel: parent (i, _103)?
4 4 Appel: enfant (_127, i)?
5 5 Appel: parent (i, _151)?
6 6 Appel: enfant (_175, i)?
7 7 Appel: parent (i, _199)?
8 8 Appel: enfant (_223, i)?
9 9 Appel: parent (i, _247)?
10 10 Appel: enfant (_271, i)?
11 11 Appel: parent (i, _295)?
12 12 Appel: enfant (_319, i)?
13 13 Appel: parent (i, _343)?
14 14 Appel: enfant (_367, i)?
15 15 Appel: parent (i, _391)?
...

C'est parce que l'enfant se définit comme a avoir un parent et parent lui-même définit a avoir un enfant (comme vous le verrez dans les prédicats ci-dessus) que j'ai posté.

Quelqu'un peut-il m'aider à redéfinir mes prédicats pour ces relations afin que je puisse déterminer si je suis mon propre grand-père?

+0

Heh, j'ai eu en fait de le faire pour ma classe AI. Je me demande si j'ai encore le code ... Je regarderai quand je rentrerai à la maison. Je me souviens que ça me faisait mal au cerveau aussi. –

+5

Ils utilisent Prolog dans West Virgina? ;-) –

+0

@ T.E.D .: Shh! TheTXI vous entendra! –

Répondre

3

Mon parcours Prolog a été il y a très longtemps, mais ce que sur la suppression

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

et simplement remplacer toute utilisation de parent(A,B) avec child(B,A)? Vous pouvez toujours ajouter des faits sur les parents car la règle inverse est toujours disponible - vous pouvez également supprimer celle-ci mais dans ce cas vous ne pouvez plus utiliser de faits sur les parents et vous devrez écrire tous vos faits en tant qu'enfants (a, b) ainsi que.

Il est même non?

1

Notez que ma connaissance de Prolog est vieux (jamais que profond) ...

Je pense que vous avez besoin de faire des parents (ou l'enfant) principal (ne dépend pas d'autres relations).

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

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

est probablement ce qui cause les boucles.

5

j'ai enlevé tout ce qui était inutile dans votre code et changé quelques petites choses et c'est ce que j'ai fini avec:

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

On pourrait supposer que married(X,Y) :- married(Y,X), mais il conduit à des épreuves circulaires désagréables, donc nous Je vais juste mettre le mari d'abord par convention.

A propos de la parentalité, le même problème se pose. Nous devons considérer les beaux-parents comme de vrais parents, car l'énigme en dépend. Nous savons que vous ne pouvez jamais être votre propre ancêtre biologique!

Cependant, parent(X,Y) :- parent(Z,Y), married(X,Z) se heurte aux mêmes problèmes, donc je viens de faire bio_parent dénotent la parentalité biologique.

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

Notez que nous devons être explicite sur les deux parents, car il n'y a aucun moyen de conclure la parentalité biologique du mariage! En outre, votre façon de spécification était problématique. Vous avez eu quelque chose comme:

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

Cependant, ces règles Prolog ne pouvait pas déduire child(a,b), de sorte que vous retrouviez cinque fils qui ne sont pas les enfants! Cela s'est produit plusieurs fois dans votre code. Si vous dérivez b de a, indiquez toujours a comme le fait! À première vue, cela peut sembler une lacune de Prolog, mais ce n'est pas le cas. Rappelez-vous que chaque clause n'est qu'une façon de prouver un certain prédicat. Dans l'exemple ci-dessus, vous avez déclaré que chaque enfant mâle est un fils, et aussi a vient juste d'être un fils de b. Nulle part il est dit que d'être un enfant mâle est la seule façon que quelqu'un pourrait être un fils, cependant, peut-être l'exception.

Le prochain est un peu verbeux que notre définition de married nous oblige à traiter les pères étape séparément des belles-mères. Nous les unissons immédiatement aux beaux-parents .

step_father(X,Y) :- married(X,Z),bio_parent(Z,Y),\+bio_parent(X,Y). 
step_mother(X,Y) :- married(Z,X),bio_parent(Z,Y),\+bio_parent(X,Y). 
step_parent(X,Y) :- step_father(X,Y). 
step_parent(X,Y) :- step_mother(X,Y). 

Comme je l'ai dit plus haut, nous devons considérer les beaux-parents comme des parents!

parent(X,Y) :- step_parent(X,Y). 
parent(X,Y) :- bio_parent(X,Y). 

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

Il y avait aussi d'autres erreurs dans votre code que je sors, je viens de vous montrer quelques exemples afin que vous puissiez en tirer des leçons. Premièrement, vous dites ici que les femmes sont mariées et que les hommes sont mariés. Ainsi, les femmes hommes seraient célibataires. Cela devrait être l'inverse si, les femmes mariées sont appelées épouses!

% 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). 

Ici, j'ajouté la dernière ligne, que vous ne vous considérez pas comme d'habitude votre propre frère:

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

Ces deux derniers sont faits sur le mauvais prédicat à nouveau. Vous annulez la déduction de Prolog avec eux. Ils devraient être déduits, non déclarés comme des faits!

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

Maintenant, essayez le programme comme ceci. Et ne soyez pas surpris: vous ne serez pas le seul à être leur propre grand-père! ;-)

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). 

requête

?-grand(i,i). 
Questions connexes