2011-01-26 15 views

Respuesta

8

Ahí está el corte "oculta" en la construcción if-then-else de Prolog:

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

Es algo así como una peculiaridad, pero Prolog no retrocede en el subgrupo que forma la "premisa" de una construcción if-then o if-then-else. Aquí, si X < 0 tiene éxito al primer intento, entonces se acepta la opción de la cláusula "then" sobre la cláusula "else" (de ahí la descripción de este comportamiento como un corte "oculto").

Hay más de un papel para un corte en la primera cláusula del predicado ABS2/2 como está escrito en la pregunta. Como señala Nicholas, el corte al final de la segunda cláusula no tiene ningún efecto (no quedan puntos de elección cuando llegas allí). Pero como señala Kaarel, hay un punto de elección que queda abierto si la primera cláusula tiene éxito.

Así que lo que yo he escrito, lo que permite el uso de un corte, es la siguiente:

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

comentarios de Nicholas también sugieren maneras de "arithmetize" el valor absoluto (en lugar de utilizar una definición lógica) y evitar "cortar" de esa manera.

+1

Lo que llamas" corte oculto "no se comporta como un corte:!/0 también impide que se prueben cláusulas alternativas, pero el local cometer en if-then-else no. Por lo tanto, encuentro esta terminología pobre. – mat

+2

@mat: Estaría encantado de aprender una mejor terminología. Escribí "corte oculto" como una especie de revelación al ofrecer mi solución evitando el uso (aparente) de corte, para que el lector pueda juzgar si mi solución es válida o una "trampa". Compare la documentación de SWI-Prolog para los Predicados de Control (Sec. 2.4.7) para obtener una explicación del compromiso/corte localizado en "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

Mi prólogo está un poco oxidado, pero ¿por qué incluso necesitas el corte? Si se escribe el predicado correctamente, dando marcha atrás no puede tener éxito, por lo que el corte es innecesaria:

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

Su código aún deja un punto de elección. Esta elección conduce al fracaso, pero, sin embargo, se considera. Un corte evitaría eso. – Kaarel

+3

Si sabe que está tratando con valores integrales, puede calcular ABS con un punto de elección mezclando bits: http://www-graphics.stanford.edu/~seander/bithacks.html#IntegerAbs –

+6

Otra opción es esta : 'abs (X, Y): - Y es el signo (X) * X .' (suponiendo que la implementación de su prólogo sea compatible con un predicado de signo/1 incorporado). –

3

¡No necesita usar !

escribe simplemente:

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