2017-10-17 12 views
1

je définissais ma base de connaissances:Prolog Cut opérateur

edge(mammal,isa,animal). 
edge(human,isa,mammal). 
edge(simba,isa,human). 

edge(animal,swim,bybirth). 
edge(human,swim,mustlearn). 

path(X,Y) :- edge(X,isa,Y). 
path(X,Y) :- edge(X,isa,Z), path(Z,Y). 

swim(X,Y) :- edge(X,swim,Y). 
swim(X,Y) :- path(X,Z), swim(Z,Y). 

Maintenant, utiliser la base de connaissances ci-dessus, j'utilise les éléments suivants:

?- swim(simba,bybirth). 
?- swim(simba,mustlearn). 

Et pour les deux requêtes, Prolog renvoie true . Je veux que Prolog vérifie d'abord la propriété nager localement, puis regarde le parent direct, et ainsi de suite de façon hiérarchique. Et il devrait cesser de chercher dès que nous savons que Simba "doit apprendre" à nager, et ne devrait pas regarder plus loin. Ainsi, il devrait renvoyer false pour la première requête et true pour la seconde.

Je sais que cela doit être fait en limitant le retour arrière. J'ai essayé d'utiliser les opérateurs coupés et non, mais je ne pouvais pas réussir. Y a-t-il un moyen d'y parvenir?

Répondre

1

J'ai essayé et j'ai rencontré un problème aussi. Je pensais que cela pourrait fonctionner:

swim(X,Y) :- once((edge(X,swim,Y); path(X,Z), swim(Z,Y))). 

Il ne fonctionne pas, parce que si Y est déjà instanciée sur la manière, la première étape ne parviendra pas à unifier et il va essayer la deuxième voie passant par l'intermédiaire human. Ainsi, même si la requête ne produit qu'un seul résultat, elle peut être trompée en produisant swim(simba, bybirth). La solution est de forcer Prolog à engager à une fixation sur une autre variable, puis vérifier que la liaison après l'engagement:

swim(X,Y) :- 
    once((edge(X,swim,Method); path(X,Z), swim(Z,Method))), 
    Method = Y. 

Cela dit Prolog, il n'y a qu'une seule façon d'arriver à cette méthode, afin de trouver cette méthode, et puis il doit être Y. Si vous trouvez la mauvaise méthode, il ne va pas sur une recherche, il va juste échouer. Essayez-le!