2011-01-26 2 views

Répondre

8

Il y a la coupe "cachée" dans le if-then-else construction de Prolog:

abs2(X,Y) :- X < 0 -> Y is -X ; Y = X. 

C'est un peu bizarre, mais Prolog ne revient pas sur le sous-objectif qui constitue la «prémisse» d'une construction if-then ou if-then-else. Ici, si X < 0 réussit le premier essai, alors le choix de la clause "then" sur la clause "else" est validé (d'où la description de ce comportement comme une coupe "cachée").

Il y a plus d'un rôle pour une coupe dans la première clause du prédicat ABS2/2 comme écrit dans la question. Comme le fait remarquer Nicholas, la coupure à la fin de la deuxième clause n'a aucun effet (il n'y a plus de points de choix quand vous y arrivez). Mais comme Kaarel le fait remarquer, il y a un point de choix laissé ouvert si la première clause réussit.

donc ce que je l'ai écrit, ce qui permet l'utilisation d'une coupure, est la suivante:

abs2(X,X) :- X >= 0, !. 
abs2(X,Y) :- Y is -X. 

commentaires de Nicholas suggèrent également des moyens de « arithmetize » la valeur absolue (plutôt que d'utiliser une définition logique) et éviter "couper" de cette façon.

+1

Ce que vous appelez" couper caché "ne se comporte pas comme une coupure:!/0 empêche également d'essayer des clauses alternatives, mais le local commit dans if-then-else ne le fait pas. Je trouve donc cette mauvaise terminologie. – mat

+2

@mat: Je serais heureux d'apprendre une meilleure terminologie. J'ai écrit "coupe cachée" comme une sorte de divulgation en offrant ma solution en évitant l'utilisation (apparente) de la coupe, de sorte que le lecteur peut juger si ma solution est valide ou un "triche". Comparez la documentation SWI-Prolog pour les prédicats de contrôle (section 2.4.7) pour une explication de la validation/coupure localisée dans "if-then-else". http://www.swi-prolog.org/pldoc/doc_for?object=section%282,%274.7%27,swi%28%27/doc/Manual/control.html%27%29%29 – hardmath

5

Mon Prolog est un peu rouillé, mais pourquoi avez-vous besoin même la coupe? Si vous écrivez le prédicat correctement, retours en arrière ne peut pas réussir, de sorte que la coupe est inutile:

abs(X, Y) :- number(X) , X < 0 , Y is -X . 
abs(X, X) :- number(X) , X >= 0 . 
+4

Votre code laisse encore un point de choix. Ce choix conduit à l'échec, mais il est néanmoins envisagé. Une coupe éviterait cela. – Kaarel

+3

Si vous savez que vous avez affaire à des valeurs entières, vous pouvez calculer ABS avec un point de choix en tripotant les bits: http://www-graphics.stanford.edu/~seander/bithacks.html#IntegerAbs –

+6

Une autre option est la : 'abs (X, Y): - Y est le signe (X) * X .' (en supposant que votre implémentation prologue supporte un signe/1 prédicat intégré). –

3

Pas besoin d'utiliser !

écrire simplement:

abs2(X,Y) :- Y is abs(X). 
Questions connexes