web-dev-qa-db-fra.com

Quel est le «non» logique dans Prolog?

Le problème auquel je suis confronté est un peu banal. Je veux utiliser logique pas dans Prolog, mais il semble que not/1 n'est pas la chose que je veux:

course(ai).
course(pl).
course(os).

have(X,Y) :- course(X),course(Y),not(X = Y).

Je demande:

have(X,Y), write(X-Y), nl , fail.

Et je n'obtiens pas le résultat que je veux :(

35
Masood Delfarah

Au lieu de not(X = Y), vous devez écrire \+ X = Y Ou X \= Y. Mais pensez à utiliser à la place dif(X,Y). dif/2 Est présent en B, SWI, YAP, SICStus. Pour voir la différence:

?- X = b, dif(a, X).
X = b.

?- X = b, \+ a = X.
X = b.

Jusqu'à présent, tout semble aller pour le mieux. Mais que se passe-t-il si nous échangeons simplement l'ordre des deux objectifs?

?- \+ a = X, X = b.
false.

?- dif(a, X), X = b.
X = b.

(\+)/1 Nous donne maintenant un résultat différent, car il y a une réponse pour a = X, L'objectif \+ a = X Échouera.

(\+)/1 N'est donc pas une négation, mais signifie non prouvable à ce moment .

ne approximation sûre de dif/2 Est également possible dans ISO Prolog.

36
false

Dans SWI-Prolog et GNU Prolog, ce qui suit devrait fonctionner:

have(X, Y) :- course(X), course(Y), X \= Y.

Dans SWI-Prolog, vous pouvez également utiliser dif/2, ce qui peut être plus pratique car vous pouvez l'utiliser plus tôt dans le prédicat:

have(X, Y) :- dif(X, Y), course(X), course(Y).
14
Fred Foo

En complément de la réponse de l'utilisateur "fausse" ci-dessus, c'est-à-dire.

"Au lieu de (X = Y), vous devez écrire\+ X = Y,"

Cela pourrait donner l'impression que:

une. "pas" et "\ +" sont des choses différentes

b. Le\+ fonctionnera alors que le non ne fonctionnera pas, err.

Ma compréhension est que "pas" et "\ +" sont équivalents, mais que\+ est préféré dans les programmes Prolog modernes, car il transmet un sens plus intuitif. Plus précisément, alors que "non" pourrait suggérer "n'est pas vrai" pour le codeur imprudent, "\ +" suggère "n'est pas prouvable", ce qui est beaucoup plus proche de la vérité de ce que cette opération dit réellement. Dans Prolog, le "non" est un exemple de "négation comme échec", mais il est estimé que\+ rendra plus clair au programmeur ce qui est précisément affirmé dans une règle donnée. Donc vous POUVEZ utiliser "non" (la plupart des implémentations PL le gardent pour une compatibilité descendante) mais pour être un programmeur PL idiomatique moderne, vous devriez probablement préférer utiliser\+.

5
Kaitain

En lisant Samuel Kamin livre au chapitre 8, prologue, j'ai trouvé cette solution qui convient également ici et explique comment utiliser le cut:

La coupure est un moyen de donner au programmeur un contrôle supplémentaire sur le calcul en lui permettant d'indiquer les endroits où le retour en arrière est interdit. Plus précisément, la coupure est écrite comme un point d'exclamation (!) Se produisant comme un objectif dans le côté droit d'une clause telle que:

G :- H, !, R.

Supposons que cette clause soit choisie pour satisfaire un objectif g avec lequel G nifie . Une tentative est faite pour satisfaire H. En cas de succès, R est prouvé. Si la preuve de R réussit, alors g est prouvé ; dans ce cas, la coupe n'a aucun rôle à jouer. Si, cependant, la preuve de R échoue , plutôt que de revenir en arrière et d'essayer de re-prouver H, la présence de la coupure provoque l'échec immédiat de l'objectif g ; cela se produit même s'il existe d'autres clauses qui pourraient s'appliquer à g. Un exemple est la définition de différent de :

equals(X, X).
not-equals(X, Y) :- equals(X, Y), !, fail.
not-equals(X, Y).

not-equals(X, Y) devrait réussir si X n'est pas égal à Y, et échouer si c'est le cas; X et Y doivent être liés à expressions au sol (c'est-à-dire n'ont pas de variables libres) lorsqu'ils tentent de satisfaire cet objectif.

2
Niloct

Comme vous l'avez dit, OP, c'est trivial.

Essayer

course(ai).
course(pl).
course(os).

have(X,Y) :- course(X), course(Y), X \== Y).

Cela devrait corriger votre prédicat.

Si vous cherchez une longueur d'avance, en termes mathématiques, vous recherchez probablement la solution à (n C 2) par opposition à (n P 2) que votre prédicat fournit actuellement - combinaison au lieu de permutation, choix de sélection par opposition aux arrangements de choix de sélection. C'est ce que je pense.

Si c'est ce que vous voulez, je vous suggère d'essayer

course(ai).
course(pl).
course(os).

have(X,Y) :- course(X), course(Y), X @< Y).

Ce qui empêcherait les résultats inversés en double.

@< signifie atomiquement moins que. < est pour les entiers, @< est pour les atomes.

1
iGbanam