En évitant l'utilisation de coupe dans prédicat de valeur absolue Prolog
-
24-10-2019 - |
Question
Je l'ai mis en œuvre la fonction suivante dans Prolog avec le code suivant:
abs2(X, Y) :- X < 0, Y is -X.
abs2(X, X) :- X >= 0, !.
Comment puis-je mettre en œuvre cette fonction sans l'utilisation de coupe ( « ! »)?
La solution
Il y a la coupe "caché" dans le if-then-else construction de Prolog:
abs2(X,Y) :- X < 0 -> Y is -X ; Y = X.
Il est quelque chose d'une bizarrerie, mais Prolog ne backtrack sur le sous-but qui forme la « prémisse » d'un if-then ou if-then-else construction. Ici, si X <0 réussit le premier essai, le choix de « puis » clause sur la clause « else » est engagée (donc la description de ce comportement comme une coupure « cachée »).
Il y a plus d'un rôle pour une coupe dans la premier clause du prédicat ABS2 / 2 comme il est écrit dans la question. Comme Nicholas souligne, la coupe à la fin de la deuxième clause n'a pas d'effet (il n'y a pas de points de choix à gauche quand vous y arrivez). Mais comme Kaarel souligne, il y a un point de choix reste ouvert si la première clause réussit.
Alors, 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.
Les commentaires de Nicholas suggèrent également des moyens de « arithmetize » la valeur absolue (plutôt que d'utiliser une définition logique) et éviter « cut » de cette façon.
Autres conseils
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 .