El corte
El corte es un predicado predefinido que no
recibe argumentos. Se representa mediante un signo de admiración
(!).
Sin duda, es el predicado más difícil de entender. El
corte tiene la espantosa propiedad de eliminar los puntos de
elección del predicado que lo contiene.
Es decir, cuando se ejecuta el corte, el resultado del objetivo
(no sólo la cláusula en cuestión)
queda comprometido al éxito o fallo de los
objetivos que aparecen a continuación. Es como si a Prolog
"se le olvidase" que dicho objetivo puede tener varias soluciones.
Otra forma de ver el efecto del corte es pensar que solamente tiene
la propiedad de detener el backtracking cuando éste se produce.
Es decir, en la ejecución normal el corte no hace nada. Pero
cuando el programa entra en backtracking y los objetivos se recorren
marcha atrás, al llegar al corte el backtracking se detiene
repentinamente forzando el fallo del objetivo.
Ejemplo
Para entender de manera simple el uso del corte vamos a comparar dos
predicados que solamente se diferencian en un corte:
% Sin corte.
p(X,Y) :-
X > 15,
Y > 50.
p(X,Y) :-
X > Y,
% Con corte.
q(X,Y) :-
X > 15,
!,
Y > 50.
q(X,Y) :-
X > Y,
Veamos que ocurre si ejecutamos el objetivo
p(25,12):
- Obsérve que ambas cláusulas unifican con la cabeza, luego
existen dos puntos de elección
que se anotan.
- Prolog entra por el primer punto de elección (primera
cláusula) eliminandolo.
- Prolog ejecuta el primer objetivo del
cuerpo (X>15), que tiene
éxito.
- Prolog ejecuta el segundo objetivo del
cuerpo (X>50), que falla.
- Empieza el backtracking.
- Se recorren ambos objetivos hacia atrás pero no hay
variables que se hayan ligado en ellos.
- Encontramos el segundo punto de elección
(segunda cláusula) que detiene el backtracking
eliminandolo en el proceso. La ejecución continúa
hacia delante.
- Prolog ejecuta el cuerpo de la segunda cláusula que
consiste en X>Y. Este objetivo tiene
éxito.
- El objetivo p(25,12) tiene
éxito.
Ahora comprobamos lo que ocurre cuando éxiste el corte,
ejecutamos q(25,12):
- Ambas cláusulas unifican con la cabeza, luego
existen dos puntos de elección
que se anotan.
- Prolog entra por el primer punto de elección (primera
cláusula) eliminandolo.
- Prolog ejecuta el primer objetivo del
cuerpo (X>15), que tiene
éxito.
- Se ejecuta el segundo objetivo del cuerpo que es el corte. Por
tanto, se eliminan todos los puntos de elección anotados
que son debidos al objetivo
q(25,12). Solamente
teníamos uno, que se elimina.
- Prolog ejecuta el tercer objetivo del
cuerpo (X>50), que falla.
- Empieza el backtracking.
- Se recorren ambos objetivos hacia atrás pero no hay
variables que se hayan ligado en ellos.
- No encontramos ningún punto de elección porque
fueron eliminados por el corte.
- El objetivo p(25,12) falla.
Como puede comprobar, los resultados son sustacialmente diferentes.
La segunda cláusula del predicado
q/2 ni siquiera
ha llegado a ejecutarse porque el corte ha comprometido el
resultado del objetivo al resultado de
Y>15 en la primera cláusula.
Usos del corte
El corte se utiliza muy frecuentemente, cuanto más diestro es el
programador más lo suele usar. Los motivos por los que se
usa el corte son, por orden de importancia, los siguientes:
- Para optimizar la ejecución. El corte sirve para evitar
que por culpa del backtracking se exploren puntos de
elección que, con toda seguridad,
no llevan a otra solución (fallan). Para los entendidos,
esto es podar el árbol de
búsqueda de posibles soluciones.
- Para facilitar la legibilidad y comprensión del algoritmo
que está siendo programado.
A veces se situan cortes en puntos donde, con toda seguridad, no
van a existir puntos de elección para eliminar, pero ayuda a
entender que la ejecución sólo depende de la
cláusula en cuestión.
- Para implementar algoritmos diferentes según la
combinación de argumentos de entrada. Algo similar
al comportamiento de las sentencias case en los
lenguajes imperativos.
- Para conseguir que un predicado solamente tenga una
solución. Esto nos puede interesar en algún
momento. Una vez que el programa encuentra una solución
ejecutamos un corte. Así evitamos que Prolog busque otras
soluciones aunque sabemos que éstas existen.
Corte y fallo
Es muy habitual encontrar la secuencia de objetivos corte-fallo:
!,fail. El predicado
fail/0 es
un predicado predefinido que siempre falla.
Se utiliza para detectar prematuramente combinaciones de los argumentos
que no llevan a solución, evitando la ejecución de un
montón de código que al final va a fallar de todas
formas.
© Copyright 2000-2001
Angel Fernández Pineda.