Question

Je dois simuler arbre en Prolog. Et j'ai un problème de prédicats symétriques. Faits:

parent(x,y).
male(x).
female(y).
age(x, number).

Règles:

blood_relation me donne des maux de tête. ce que je l'ai fait:

blood_relation(X,Y):-ancestor(X,Y).
blood_relation(X,Y):-uncle(X,Y);brother(X,Y);sister(X,Y);(mother(Z,Y),sister(X,Z));(father(Z,Y),sister(X,Z));(father(Z,Y),brother(X,Z)).
blood_relation(X,Y):-uncle(X,Z),blood_relation(Z,Y).

et je reçois je pense que des résultats satisfaisants (j'ai doubles impressions - ce que je peux résoudre ce problème), problème est que je veux que cette relation soit symétrique. Il est pas maintenant.

blood_relation(johns_father, joh):yes 
blood_relation(john,johns_father): no

so..is il un moyen de résoudre ce problème. Et j'ai besoin requête: Toutes les paires qui ne sont pas blood_relation ..

Mise à jour:

  

Quels types de relations est la première déclaration censée satisfaire?   blood_relation (X, Y): - blood_relation (X, Y)

.

sorry..it est une mauvaise copie / paste..it

blood_relation(X,Y):-ancestor(X,Y).

fixe ci-dessus.

ici sont d'autres règles:

father(X,Y):-parent(X,Y),male(X).  
mother(X,Y):-parent(X,Y),female(X).  
brother(X,Y):-parent(Z,X),parent(Z,Y),male(X).  
sister(X,Y):-parent(Z,X),parent(Z,Y),female(X).  
grandFather(X,Y):-parent(Z,Y),parent(X,Z),male(X).  
grandMother(X,Y):-parent(Z,Y),parent(X,Z),female(X).  
uncle(X,Y):-mother(Z,Y),brother(X,Z).  
ancestor(X,Y):-ancestor(X,Y).  
ancestor(X,Y):-parent(X,Z),ancestor(Z,Y).

Le frère de la mère est dans la définition de l'oncle. Il est un peu étrange. J'ai règles que je dois mettre en œuvre, et je ne sais pas comment je peux mettre en œuvre des règles en plus de cela. Je suis juste confuse.

Toute idée comment faire symétrique blood_relation? Et not_blood_relation est une nouvelle règle. Et j'ai besoin requête. Celui-ci est vraiment me donner des maux de tête. Peut-être parce que relation est écrit comme de la merde.

Et il n'y a plus de faits. C'est tout. Toutes les règles et tous les faits.

query .. not(blood_relation(X,Y)) ne fonctionne pas, et je ne sais vraiment pas pourquoi. Par exemple la requête:

age(X,Y), Y>18,  
not(parent(X,Z)),write(X),nl,fail.

fonctionne très bien

Était-ce utile?

La solution

Un peu ressemble à un devoir, non ...

Une astuce dont la plupart des débutants de Prolog ne pensent pas est la liste correspondance de motif. Pensez à un arbre comme [a1, [[a2], [b2, [[e3], [f3]]], [c2]]] comme dans <tree> = [racine, [<tree1>, <tree2>, ... ]]:

%Y is immediate child of X?
child(X,Y,[X|S]) :- member([Y|_],S).

%pick one tree in S and check
child(X,Y,[X|S]) :- member([Z|SS],S),child(Z,Y,[Z|SS]).

%X and Y end up with same root?
sib(X,Y,[R|T]) :- child(R,X,[R|T]), child(R,Y,[R|T]).

Je pense que vous pouvez améliorer cela comme, en utilisant des paires comme les racines, en ajoutant les sexes, en donnant des noms aux relations spécifiques des membres de l'arbre ...

Autres conseils

La solution naïf de fabrication d'un prédicat symétrique particulière est pas si loin de une convenable. Par souci de généralité, regardons une relation d'amitié afin que les gens ne sont pas trébuché sur oncles et autres.

Voici quelques faits détaillant une relation d'amitié (où, par exemple, les numéros sont ids utilisateur et l'ordre particulier des arguments venus de l'amitié qui a initié).

friends(1,2).
friends(5,2).
friends(7,4).

Vous penseriez d'abord une règle comme « friends(A,B) :- friends(B,A). » fixerait les choses, mais cela vous amène à une récursion infinie, car il dit que Prolog si elle troque juste l'argument une fois de plus, il pourrait fonctionner. Il y a un prédicat appelé « @</2 » qui vous indique si un terme (même une variable) vient avant l'autre dans le « ordre standard des termes ». Le sens technique n'est pas tout ce qui importe, mais ce qui nous importe est que pour deux termes différents, il est vrai que pour une commande d'entre eux. Nous pouvons l'utiliser pour briser la récursion infinie!

Cette règle unique prendra soin de faire symétrique « de friend/2 ».

friends(A,B) :- A @< B, friends(B,A).

propre que cela est, il existe un moyen d'approche que vous devrait prendre pour les grands projets. Rappelons que l'ordre des args dans ma liste des faits avait une signification réelle (qui a initié l'amitié). L'ajout de la règle finale détruits l'accès futur à ces informations et, pour d'autres personnes qui lisent le code, se cache la propriété symétrique en une seule ligne de code qui est facile d'ignorer face à un bloc de données codées en dur.

Condsider la solution de force industrielle:

friended(1,2).
friended(5,2).
friended(7,4).

friends(A,B) :- friended(A,B).
friends(A,B) :- friended(B,A).

Il est plus volumineux, mais il se lit proprement sans utiliser des prédicats obscurs et conserve les informations d'origine (que vous voudrez peut-être à nouveau un jour dans une application réelle).

-

Quant à trouver des paires que ne pas une propriété spécifique, assurez-vous d'inclure toujours un prédicat pour fournir un contexte dans la règle lorsque vous utilisez la négation de rechercher des individus réels.

potential_enemies(A,B) :- user(A), user(B), \+ friends(A,B).

Quels types de relations est la première déclaration censée satisfaire?

blood_relation(X,Y):-blood_relation(X,Y).

Cela ne vous tout ce que vous disent ne déjà « savoir » et ne va vous causer des maux de tête récursivité. Quant à la « non » réponse, est semble que vous ayez déjà obtenu toutes les réponses de la requête que vous allez obtenir, et l'interprète est juste vous dites qu'il n'y a pas plus.

Vous devriez vraiment publier plus de faits, et la définition de l'oncle / 2, et est-il une raison pour laquelle vous ne correspond pas à le frère d'une mère, juste sa sœur? Vous avez beaucoup d'autres problèmes à régler sur: -.)

Pour tout ce qui est pas une relation de sang, essayez ceci:

not_blood_relation(X, Y) :- blood_relation(X, Y), !, fail.
not_blood_relation(X, Y).

Et demandez-vous pourquoi cela fonctionne!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top