2017-07-20 2 views
2

Je viens de commencer à apprendre Prolog, et je me pose des questions sur la première question de ce .Apprenez Prolog maintenant: Pourquoi répondre à la première requête de l'exercice 1.5?

%% Suppose we are working with the following knowledge base: 
wizard(ron). 
hasWand(harry). 
quidditchPlayer(harry). 
wizard(X) :- hasBroom(X), hasWand(X). 
hasBroom(X) :- quidditchPlayer(X). 

Comment Prolog répond aux requêtes suivantes?

  1. wizard(ron). -> true
  2. witch(ron). -> undefined procedure
  3. wizard(hermione). -> false
  4. witch(hermione). -> undefined procedure
  5. wizard(harry). -> true
  6. wizard(Y). -> Y = ron ; Y = harry.
  7. witch(Y). -> undefined procedure

En utilisant swipl sur Ubuntu, en important la base de connaissances pour cet exercice, d'abord en essayant bien sûr de déchiffrer ce que Prolog retournera, et finalement de vérifier par moi-même.

Ok choses assez ennuyeux jusqu'à présent, je l'ai vu quelques réponses à ces exercices sur Github (here, here et there), et je ne comprends pas la réponse à la première: %% 1. wizard(ron). -> true.

tout d'abord l'interprète se plaint de deux définition de ce qui est un wizard:

Warning: /tmp/prolog/ex15.pl:4: 
    Clauses of wizard/1 are not together in the source-file 
     Earlier definition at /tmp/prolog/ex15.pl:1 
     Current predicate: quidditchPlayer/1 
     Use :- discontiguous wizard/1. to suppress this message 

En second lieu, lors de l'interrogation que j'obtiens:

?- wizard(ron). 
true ; 
false. 

La façon dont je l'obtiens, d'abord Prolog renvoie le premier fait de la base de connaissances, puis applique la tête de règle et découvre que ron n'a ni balai ni baguette.

Tout cela a conduit à ma question: quelle subtilité ai-je manqué qui fait que les autres écrivent true comme réponse à cette requête?

+1

L'interprète ne se plaint pas vraiment sur le fait qu'il ya deux définitions pour l'assistant, il se plaint qu'il n'y a pas écrit immédiatement l'un après l'autre. –

+2

De plus, quelque chose est 'vrai' étant donné qu'il y a * au moins un chemin qui retourne' true' *. –

+3

Le 'exercise.pl' que vous pointez est mal structuré. Il définit 'wizard (ron) .', quelques autres faits différents, puis' wizard (X): - ... '. Cela signifie que la définition de 'wizard' est * discontiguous * et de nombreux interprètes Prolog ignorera' wizard (X) 'à ce stade. Vous devez garder toutes vos définitions 'wizard (_)' les unes à côté des autres. – lurker

Répondre

2

Quelle subtilité ai-je manqué qui rend d'autres réponses vraies comme réponse à cette requête?

`?- wizard(ron).` 
true; 
false 

Vous avez la clause (fait) wizard(ron). dans votre KB.

Pour rendre les choses plus claires, vous pouvez écrire le fait également que la clause de règle:

wizard(ron) :- true.

Comme vous pouvez le voir c'est assez notation redondante mais utile dans certains cas, comme la représentation générale de fait.

Ainsi, votre requête peut être interprété comme suit:

Y at-il un wizard appelé ron?

Puisque vous avez le fait wizard(ron) :- true.

Prolog d'abord unifier l'objectif et la tête. Dans votre cas, unify est une comparaison triviale car aucune variable ne se trouve dans le but et la tête.

Puis Prolog essaie de prouver le corps. Le corps est intégré prédicat true, de sorte que vous obtenez rapidement la réponse - vrai.

Ensuite, appuyez sur ';' vous lancez la recherche de la solution alternative. Puisqu'aucune (plusieurs) solution n'existe pour la requête wizard(ron), Prolog écrit faux.

L'opérateur de point désigne la fin de la clause. Donc, vous avez tapé des points à tort dans vos exemples:

-> Opérateur signifie si-alors-autre relation. Il peut être utilisé dans le corps de la clause.

Par exemple, vous pouvez écrire std_member/2 comme if_member/2

std_member(X, [ X | _ ]). 
std_member(X, [ _ | Xs ]) :- 
    std_member(X, [ _ | Xs). 

if_member(X, [ Y | Xs ]) :- 
    X = Y -> true; 
     if_member(X, Xs).