Lógica: Uso de operadores (Paradigmas)

De Cuba-Wiki
Saltar a: navegación, buscar
Back.png Volver a la página de la materia

Not[editar]

El not es un metapredicado que unifica solamente si no es posible probar a partir de los hechos y reglas el objetivo planteado. Por ejemplo, dados los siguientes hechos:

estaBueno(java).
estaBueno(net).
estaBueno(cpp).

Si se pregunta por otro lenguaje, el motor no puede probarlo, por lo que lo considera falso (en realidad, fail, que significa que no pudo unificar):

estaBueno(vb).
fail.

Por lo tanto, el not devuelve verdadero si se lo aplica al goal:

not(estaBueno(vb)).
true.

Es importante notar que el not genera un corte implicito en el arbol de backtracking, el cual sera util para emular el cut a continuacion.

Cut[editar]

Supongamos un caso en el que tenemos una funcion que por algun motivo repite resultados. Por ejemplo, la siguiente funcion devuelve siempre 3 veces true si el primer numero que recibe es mayor que el segundo:

testGreater(Num, Smaller) :- between(1,3,X), Num > Smaller.

testGreater(10,5).
true ;
true ;
true.

testGreater(1,5).
fail.

Esto es porque el between genera 3 valores distintos para X, y por cada valor de X se verifica que Num > Smaller, y por cada vez devuelve true. En cambio, si no unifica, devuelve fail una unica vez.

Para evitar esto puede usarse el operador cut (!), que corta el arbol de backtracking una vez hallada una solucion:

testGreater(Num, Smaller) :- between(1,3,X), !, Num > Smaller.

testGreater(10,5).
true.

testGreater(1,5).
fail.

Ahora bien, en general el uso del cut no esta permitido, ni en parciales ni el TP. Para reemplazarlo de manera muy comoda y poco elegante puede usarse la doble negacion en el llamador.

Supongamos la siguiente funcion que usa al testGreater como estaba originalmente definido, y devuelve true si el numero es mayor a cinco:

testGreaterThanFive(Num) :- testGreater(Num, 5).

testGreaterThanFive(10).
true ;
true ;
true.

Como usa la funcion testGreater que devuelve 3 soluciones, esta tambien lo hace. Pero si se agrega una doble negacion sobre la llamada a testGreater, entonces se devuelve una unica solucion:

testGreaterThanFive(Num) :- not(not(testGreater(Num, 5))).

testGreaterThanFive(10).
true.

testGreaterThanFive(1).
fail.

Esto es porque el not() interno devuelve fail en cuanto encuentra una solucion verdadera para testGreater(10,5), que es la primera, cuando X vale 1. Una vez devuelto fail, no se devuelven sucesivos fails, a diferencia de lo que pasa con el true.

El not() externo se encarga de reconvertir ese fail al true original, pero como el interno se encarga de cortar el arbol (pues para probar que es falso que algo no es cierto, basta con encontrar un ejemplo en el que sí sea cierto), devuelve un unico true.