Un programa lógico definido  es un conjunto de reglas que expresan cosas ciertas. Cuando algo no es verdad, simplemente se omite, es decir no escribimos regla alguna. Pero Prolog posee un mecanismo para expresar negaciones y en esta sección veremos como lo logra. Suponga que queremos saber que alumnos no aprobaron determinada materia, para ello definimos un predicado “alumno_no_aprobo” de la siguiente manera:

alumno_no_aprobo(X,M):- curso(X,M), not aprobo(X,M).

y supongamos que tenemos la siguiente información:

curso(juan,matematicas).
curso(juan,historia).
curso(juan,fisica).
curso(maria,matematicas).
curso(maria,quimica).
curso(maria,fisica).
aprobo (juan,matematicas).
aprobo (juan,fisica).
aprobo (maria,matematicas).

Cuando peguntemos alumno_no_aprobo(juan,historia), el resultado será “yes”, dado que encontrará en la base curso(juan,historia) y no encontrará aprobo (juan,historia). En este caso, el predicado aprobo fallará, pero gracias al predicado not, toda la consulta será verdadera.

Con esto concluimos que not A será verdadero, siempre que A no pueda demostrarse. (que no es lo mismo a que sea falso). En algunas implementaciones de prolog el not se escribe not(A) con paréntesis.

 

Muchas veces podemos estar interesados en lograr una sola solución para un objetivo dado. Para estos casos se utiliza el predicado cut, que se escribe en Prolog como “!”. LA idea del cut, es cortar el árbol de búsqueda para reducir el número de respuestas que nos dará el intérprete. Veamos un ejemplo. Si realizamos la siguiente consulta:

?-member(X,[1,2]).

Todas las respuestas posibles posibles serían:

X=1;

X=2;

no

Ahora, si cambiamos nuestra consulta a:

?-member(X,[1,2]), !.
X=1;
no.

Al encontrar el cut, Prolog no vuelve atrás (backtrck) para encontrar otra respuesta. Hemos podado una rama del árbol. Veamos otro ejemplo:

enLasDos(X,L1,L2):-member(X,L1),member(X,L2).

Este predicado será verdadero si X pertenece a ambas listas L1 y L2. Entonces, la siguiente consulta:

?-enLAsDos(X,[1,2,3],[2,3,4]).
X=2;
X=3;
no

O, sea, tendremos la intersección de ambas listas, o bien todos los elementos comunes a ambas listas. Si uno está interesado en una de estas soluciones, digamos, la primera, podríamos hacer el siguiente cambio al predicado:

enLasDos(X,L1,L2):-member(X,L1),!,member(X,L2).

Y entonces, la misma consulta anterior, arroja el siguiente resultado:

?-enLasDos(X,[1,3],[1,2,3,4]).
X=1;
no

El efecto del cut se resume en lo siguiente:

  1. Podar todas las reglas debajo de él.
  2. Podar todas las alternativas de conjunciones que aparecen a su izquierda.
  3. No afecta la ejecución de los predicados a su derecha.

Hay que tener en cuenta que un mal uso del cut puede llevar a resultados erróneos en la ejecución de un programa lógico. Por ejemplo como el siguiente:

?-enLasDos(2,[1,2,3],[2,3,4]).
yes.

?-enLasDos(X,[1,2,3],[2,3,4]).
no

O sea, si bien en el primer caso encontró verdadero el hecho que 2 pertenezca a ambas listas, en el segundo caso no puede encontrar ningún valor para X que haga verdadero el predicado. Esto es porque el primer member instancia X en el primer elemento de la primera lista, o sea 1. Luego pasa el cut, lo que hace que el primer member no se vuelva a ejecutar. Luego se ejecuta el segundo member con el 1 y falla, dado que 1 no pertenece a la segunda lista. Como dijimos, el cut impide que se realice backtraking y se vuelva a ejecutar el primer member. Por lo tanto, la respuesta final, aunque incorrecta, es no.