2012-05-09 4 views
1

J'ai du mal à envelopper ma tête autour de la façon dont je retournerais une liste de tout le monde lié à une certaine personne. Donc, si je dis des parents (A, B), A serait une personne et B est une liste de toutes les personnes liées à cette personne. Je peux écrire toutes les règles supplémentaires nécessaires pour aider à faire cela. Voici ce que j'ai jusqu'ici.Trouver tous les parents avec Prolog

man(joe). 
man(tim). 
man(milan). 
man(matt). 
man(eugene). 

woman(mary). 
woman(emily). 
woman(lily). 
woman(rosie). 
woman(chris). 

parent(milan, mary). 
parent(tim, milan). 
parent(mary, lily). 
parent(mary, joe). 
parent(mary, matt). 
parent(chris, rosie). 
parent(eugene, mary). 
parent(eugene, chris). 

cousins(A, B) :- parent(C, A), parent(D, B), parent(E, C), parent(E, D), not(parent(C, B)), not(parent(D, A)), A \=B. 

paternalgrandfather(A, C) :- man(A), man(B), parent(B, C), parent(A, B). 

sibling(A, B) :- parent(C, A), parent(C, B), A \= B. 

Quelqu'un peut-il me guider sur la façon dont j'irais faire cela? Merci.

+0

Vous souhaitez une fonction récursive qui s'ajoute au résultat dans la récursivité. – keyser

Répondre

0

Je pense que vous devriez vous concentrer sur la relation 'vraie', c'est-à-dire parent(Old,Jung), les autres prédicats ne sont pas pertinents ici. L'hypothèse évidente est que les atomes apparaissant dans parent/2 sont des identifiants (c'est-à-dire que les noms sont uniques). De cette image semble que toutes les personnes ici sont des parents:

enter image description here

Ensuite, votre problème devrait être équivalent à trouver tous les sommets connectés en relation mère. Vous pouvez mettre en œuvre une profondeur première visite, en passant la liste des nœuds visités pour éviter, quelque chose comme

relatives(Person, Relatives) :- 
    relatives([], Person, [Person|Relatives]). 

relatives(Visited, Person, [Person|Relatives]) :- 
    findall(Relative, immediate(Person, Visited, R), Immediates), 
    ... find relatives of immediates and append all in relatives. 

immediate(Person, Visited, R) :- 
    (parent(Person, R) ; parent(R, Person)), 
    \+ member(R, Visited). 

boucles (notez que vous devez revenir aux parents et vers le bas pour les enfants!) Voyez si vous pouvez compléter cette fragment. Notez l'ordre des arguments dans les parents/3 est choisi pour faciliter maplist/3.

Si vous souhaitez étudier un code plus avancé, SWI-Prolog library(ugraph) propose un prédicat reachable(+Vertex, +Graph, -Vertices) qui le fait sur une représentation graphique basée sur une liste.

Voici l'extrait de code SWI-Prolog pour obtenir l'image (un fichier à nourrir dot):

graph(Fact2) :- 
    format('digraph ~s {~n', [Fact2]), 
    forall(call(Fact2, From, To), format(' ~s -> ~s;~n', [From, To])), 
    format('}\n'). 

vous pouvez appeler ainsi:

?- tell('/tmp/parent.gv'),graph(parent),told. 

puis question sur commande ligne dot -Tjpg /tmp/parent.gv | display

0

Je pense que vous devriez utiliser prédicat builtin findall/3 et peut-être SORT/2 pour éviter les doublons

Il irait dans ce sens:

relatives(Person, Relatives):- 
    findall(Relative, is_relative(Person, Relative), LRelatives), 
    sort(LRelatives, Relatives). 

is_relative(Person, Relative):- 
    (cousins(Person, Relative) ; paternalgrandfather(Person, Relative) ; sibling(Person, Relative)). 

Vous pouvez ajouter d'autres clauses à is_relative à obtenir plus de relations.

Questions connexes