Title: Sin ttulo de diapositiva
1III. Exploración en Prolog
Jorge Cabrera Gámez Departamento de Informática y
Sistemas Universidad de Las Palmas de Gran Canaria
2La exploración en Prolog
Exploración en profundidad
Estrategias
Exploración sistemática de todas las posibilidades
Exploración secuencial de izquierda a derecha de
las condiciones and,tanto en las reglas como en
el teorema
Exploración secuencial de arriba a abajo de las
condiciones or, desde el principio al final de la
base de datos
3La exploración en Prolog
Consideremos el siguiente programa
a(X) - b(X). a(w). b(X) - c(X),
d(X). b(y). b(w). c(w). d(z).
a1 (X) - b(X). a2 (w). b1 (X) - c(X), d(X). b2
(y). b3 (w). c(w). d(z).
?- a(X).
y la pregunta
4La exploración en Prolog
a(X) a1(X)
a2(X) b1(X)
b2(X) b3(X) a2(X) c(X), d(X)
b2(X) b3(X) a2(X) X
w c(w), d(w) b2(X) b3(X)
a2(X) d(w) b2(X) b3(X)
a2(X) Fail, backtrack b2(X)
b3(X) a2(X) X y
b2(y) b3(X) a2(X)
b3(X) a2(X) 1. Solución X
y b3(X) a2(X)
5La exploración en Prolog
1. Solución X y b3(X) a2(X)
X w b3(w) a2(X)
a2(X) 2. Solución X w a2(X)
X w a2(w) 3. Solución X
w
6?- a(X). T Call a1 ( 7) a(_G93) T Call b1
( 8) b(_G93) T Call c ( 9) c(_G93) T Exit
c ( 9) c(w) T Call d ( 9) d(w) T
Fail d ( 9) d(w) T Redo b2 ( 8)
b(_G93) T Exit b2 ( 8) b(y) T Exit a1
( 7) a(y) X y T Redo b3 ( 8) b(_G93) T
Exit b3 ( 8) b(w) T Exit a1 ( 7) a(w) X
w T Redo a2 ( 7) a(_G93) T Exit a2 ( 7)
a(w) X w No
a1 (X) - b(X). a2 (w). b1 (X) - c(X), d(X). b2
(y). b3 (w). c(w). d(z).
1. Solución X y 2. Solución X w 3. Solución X
w
7El predicado cut (!)
Consideremos la siguiente base de conocimiento ...
a(X) - b(X). a(w). b(X) - c(X),
d(X). b(y). b(w). c(w). d(z).
a1 (X) - b(X). a2 (w). b1 (X) - c(X), d(X). b2
(y). b3 (w). c(w). d(z).
?- a(X).
1. Solución X y 2. Solución X w 3. Solución X
w
8El predicado cut (!)
Introduzcamos una ligerísima variación ...
a(X) - b(X). a(w). b(X) - c(X), !,
d(X). b(y). b(w). c(w). d(z).
a1 (X) - b(X). a2 (w). b1 (X) - c(X), !,
d(X). b2 (y). b3 (w). c(w). d(z).
9La exploración en Prolog
a(X) a1(X)
a2(X) b1(X)
b2(X) b3(X) a2(X) c(X), !,
d(X) b2(X) b3(X) a2(X)
X w c(w), !, d(w) b2(X) b3(X)
a2(X) !, d(w) b2(X)
b3(X) a2(X) d(w)
a2(X) Fail, backtrack
a2(X) X w a2(w) 1.
Solución X w
Una única solución !!!
10El predicado cut (!)
?- a(X). T Call a1 ( 7) a(_G93) T Call b1 (
8) b(_G93) T Call c ( 9) c(_G93) T Exit c
( 9) c(w) ----- PODA b ------ T Call d (
9) d(w) T Fail d ( 9) d(w) T Fail b1 ( 8)
b(_G93) --- b2 y b3 han sido podadas --- T
Redo a2 ( 7) a(_G93) T Exit a2 ( 7) a(w) X
w No
a1 (X) - b(X). a2 (w). b1 (X) - c(X), !,
d(X). b2 (y). b3 (w). c(w). d(z).
11?- a(X). T Call a1 ( 7) a(_G93) T Call b1
( 8) b(_G93) T Call c ( 9) c(_G93) T Exit
c ( 9) c(w) T Call d ( 9) d(w) T
Fail d ( 9) d(w) T Redo b2 ( 8)
b(_G93) T Exit b2 ( 8) b(y) T Exit a1
( 7) a(y) X y T Redo b3 ( 8) b(_G93) T
Exit b3 ( 8) b(w) T Exit a1 ( 7) a(w) X
w T Redo a2 ( 7) a(_G93) T Exit a2 ( 7)
a(w) X w No
?- a(X). T Call a1 ( 7) a(_G93) T Call b1 (
8) b(_G93) T Call c ( 9) c(_G93) T Exit c
( 9) c(w) ----- PODA b ------ T Call d (
9) d(w) T Fail d ( 9) d(w) --- b2 y b3 han
sido podadas --- no hay backtracking posible para
la llamada ( 8) por lo que falla. T Fail b1 (
8) b(_G93) T Redo a2 ( 7) a(_G93) T Exit a2
( 7) a(w) X w No
12El predicado cut (!) (como ejercicio)
Qué diferencias se presentan cuando introducimos
otra ligerísima variación añadiendo una nueva
definición del predicado c/1 en estas dos
versiones del programa ?
a1 (X) - b(X). a2 (w). b1 (X) - c(X), d(X). b2
(y). b3 (w). c1 (y). c2 (z). d(z).
a1 (X) - b(X). a2 (w). b1 (X) - c(X), !,
d(X). b2 (y). b3 (w). c1 (y). c2 (z). d(z).
13 a(X) a1(X)
a2(X) b1(X)
b2(X) b3(X) a2(X) c1(X),
d(X) c2(X), d(X) b2(X) b3(X)
a2(X) X y c1(y), d(y)
c2(X), d(X) b2(X) b3(X) a2(X)
d(y) c2(X), d(X) b2(X)
b3(X) a2(X) Fail, backtrack
c2(X), d(X) b2(X)
b3(X) a2(X) X z c2(z),
d(z) b2(X) b3(X)
a2(X) d(z)
b2(X) b3(X) a2(X)
b2(X) b3(X) a2(X) 1.
Solución X z
14 b2(X) b3(X) a2(X)
X y b2(y) b3(X)
a2(X) b3(X) a2(X)
2. Solución X y b3(X) a2(X)
X w b3(w) a2(X)
a2(X) 3. Solución X w
a2(X) X w a2(w) 4.
Solución X w
15Cut Es un predicado extra-lógico que siempre se
evalúa a cierto. Provoca la poda o eliminación
de alternativas. Concretamente impide que se
intente la verificación de las opciones
pendientes de los predicados a la izquierda del
mismo
16Ejemplo
incluido( X, X _ ). incluido( X, _ Y )
- incluido( X, Y).
incluido( X, X Y, Y). incluido( X, _ Y ,
Z) - incluido( X, Y, Z).
?- incluido(a,a,b,a,c,o). true true false.
?- incluido(a,a,b,a,c,o,R). R b, a, c, o
R c, o false.
17Ejemplo
incluido( X, X _ ). incluido( X, _ Y )
- incluido( X, Y).
incluido( X, X Y, Y). incluido( X, _ Y ,
Z) - incluido( X, Y, Z).
?- incluido(a,a,b,a,c,o,R),!. R b, a, c, o
false.
?- incluido(a,a,b,a,c,o,R). R b, a, c, o
R c, o false.
18Ejemplo
Generación de estructuras alternativas
predicado - condicion, !, accion1. predicado -
accion2
max( X, Y, Z)- XgtY, Z is X. max( X, Y, Z)- Z is
Y.
max( X, Y, Z)- XgtY, !, Z is X. max( X, Y, Z)- Z
is Y.
?- max( 2, 3, Z). Z 3 No
?- max( 2, 3, Z). Z 3 No
?- max( 3, 2, Z). Z 3 Z 2 No
?- max( 3, 2, Z). Z 3 No
19Generación de estructuras alternativas
En muchas implementaciones de Prolog se dispone
del operador -gt, cuya semántica es equivalente
a la construcción (Condición, !, Acción1
Acción2) Más concretamente, su definición en
muchos sistemas es la siguiente Condición
-gt Acción1 _ - Condición, !, Acción1.
Condición -gt _ Acción2 - !, Acción2.
Condición -gt Acción - Condición, !, Acción.
20El operador -gt puede encadenarse para simular
la construcción case, presente en otros
lenguajes imperativos case - ( Condición1 -gt
Acción1 Condición2 -gt Acción2
CondiciónN gt AcciónN OtroCaso ).
21El predicado Fail
22?- un_libro_de('Saramago'). Todos los nombres Yes
?- todos_los_libros_de('Saramago'). Todos los
nombres Cuadernos de Lanzarote Ensayo sobre la
ceguera El Evangelio según Jesucristo No
23todos_los_libros_de(X) - libro(Y,X), write(Y),
nl, fail.
T Redo ( 8) libro(_L143, 'Saramago') T Exit
( 8) libro('Ensayo sobre la ceguera',
'Saramago') T Call ( 8) write('Ensayo sobre la
ceguera') Ensayo sobre la ceguera T Exit ( 8)
write('Ensayo sobre la ceguera') T Call ( 8)
nl T Exit ( 8) nl T Call ( 8) fail T Fail
( 8) fail
T Redo ( 8) libro(_L143, 'Saramago') T Exit
( 8) libro('El Evangelio según Jesucristo',
'Saramago') T Call ( 8) write('El Evangelio
según Jesucristo') El Evangelio según
Jesucristo T Exit ( 8) write('El Evangelio
según Jesucristo') T Call ( 8) nl T Exit (
8) nl T Call ( 8) fail T Fail ( 8) fail No
?- todos_los_libros_de('Saramago'). T Call (
8) libro(_L143, 'Saramago') T Exit ( 8)
libro('Todos los nombres', 'Saramago') T Call (
8) write('Todos los nombres') Todos los
nombres T Exit ( 8) write('Todos los
nombres') T Call ( 8) nl T Exit ( 8) nl T
Call ( 8) fail T Fail ( 8) fail
T Redo ( 8) libro(_L143, 'Saramago') T Exit
( 8) libro('Cuadernos de Lanzarote',
'Saramago') T Call ( 8) write('Cuadernos de
Lanzarote') Cuadernos de Lanzarote T Exit ( 8)
write('Cuadernos de Lanzarote') T Call ( 8)
nl T Exit ( 8) nl T Call ( 8) fail T Fail
( 8) fail
24Fail Es un predicado que nunca se evalúa a
cierto. Provoca la vuelta atrás o backtracking
y por tanto, que se explore la
siguiente alternativa.
25La negación el operador Not
A María le gustan todos los animales excepto las
serpientes
Cómo podemos decir esto en Prolog?
Veamos la parte fácil
gusta(maría, X)- animal(X).
Ahora es necesario excluir a las serpientes
Si X es una serpiente entonces gusta(maría, X)
no es verdadero, en otro caso si X es un animal
entonces a María le gusta X
26La negación el operador Not
Si X es una serpiente entonces gusta(maría, X)
no es verdadero, en otro caso si X es un animal
entonces a María le gusta X
gusta( maría, X) - serpiente(X), !,
fail. gusta( maría, X) - animal(X).
gusta( maría, X) - serpiente(X), !,
fail animal(X).
27La negación el operador Not
Consideremos otro caso Intentemos definir el
predicado diferente(X,Y)
Si X e Y son unificables entonces diferente( X,
Y) falla, en otro caso diferente( X, Y) es
verdadero
diferente(X, Y) - X Y, !, fail true.
28La negación el operador Not
Estos dos ejemplos sugieren la posible utilidad
de un operador Not, de manera que not(Objetivo
) sea verdadero si Objetivo es falso
not(P) - P, !, fail true
gusta( maría, X) - serpiente(X), !,
fail animal(X).
diferente(X, Y) - X Y, !, fail true.
29La negación el operador Not
diferente(X, Y) - X Y, !, fail true.
gusta( maría, X) - serpiente(X), !,
fail animal(X).
diferente(X, Y) - not( X Y ).
gusta( maría, X) - animal(X), not( serpiente(
X )).
gusta( maría, X) - animal(X), not serpiente( X
).
gusta( maría, X) - animal(X), \ serpiente( X
).
30Un uso interesante de not
forall(A,B) - \ (A, \B).
forall(Cond, Action)
semidet For all alternative
bindings of Cond, Action can be proven.
3 ?- forall(member(Result Formula, 2 1 1,
4 2 2), Result Formula). true.
4 ?- forall(member(Atom, ejem, aja, ojú),
name(Atom,_,106_)). true.
31Problemas con cut y not
Consideremos el siguiente ejemplo p - a, b. p -
c. El significado declarativo de este programa
es p es cierto si a y b son ciertos o si c es
cierto p ltgt (a ? b) ? c Podemos cambiar el
orden de las cláusulas sin afectar el significado
declarativo del programa
32Problemas con cut y not
Si ahora insertamos una poda p - a, !, b. p -
c. El significado declarativo de este programa
es ahora p es cierto si a y b son ciertos o si
a no es cierto y c es cierto p ltgt (a ? b) ?
(a ? c)
33Problemas con cut y not
Si se intercambia el orden de las cláusulas p -
c. p - a, !, b. El significado declarativo de
este programa cambia a p es cierto si c es
cierto o si a y b son ciertos p ltgt c ? (a ? b)
34Problemas con cut y not
La base de datos contiene nombres de
personajes cuya inocencia o culpabilidad es
conocida.
inocente( peter_pan). inocente( X) -
ocupación(X, duende). inocente(
winnie_the_pooh). inocente( mary_poppins). culpab
le(X) - ocupación(X, ladrón). culpable(joe_bloggs
).
35Problemas con cut y not
inocente( peter_pan). inocente( X) -
ocupación(X, duende). inocente(
winnie_the_pooh). inocente( mary_poppins). ocupaci
ón(david_el_gnomo, duende). culpable(X) -
ocupación(X, ladrón). culpable(joe_bloggs).
inocente( peter_pan). inocente( X) -
ocupación(X, duende). inocente(
winnie_the_pooh). inocente( mary_poppins). ocupaci
ón(david_el_gnomo, duende). culpable(X) -
ocupación(X, ladrón). culpable(joe_bloggs). culpab
le(X) - \ inocente(X).
Considérese el siguiente diálogo sobre heidi,
cuya inocencia es conocida por todos excepto por
la base de datos de la Policía.
?- inocente( heidi). No.
?- culpable( heidi). Yes.
36Problemas con cut y not
Consideremos ahora este programa buena_comida(
jean_luis). caro(jean_luis). buena_comida(francesc
o). aceptable(Restaurante) - not(caro(Restaurant
e)).
?- buena_comida(X), aceptable(X). X francesco.
?- aceptable(X), buena_comida(X). No.
37Problemas con cut y not
?- aceptable(X),buena_comida(X). T Call ( 8)
aceptable(_G237) T Call ( 9)
not(caro(_G237)) T Call ( 10) caro(_G237) T
Exit ( 10) caro(jean_luis) T Fail ( 9)
not(caro(_G237)) T Fail ( 8)
aceptable(_G237) No
buena_comida( jean_luis). caro(jean_luis). buena_c
omida(francesco). aceptable(Restaurante)
- not(caro(Restaurante)).
38Problemas con cut y not
Es mala práctica desarrollar programas que
destruyen la correspondencia entre el
significado lógico y procedimental de un
programa sin una buena razón para hacerlo.
Una solución especificar la negación como
indefinida cuando se realiza el intento de
negar un término que contiene variables
no instanciadas.
39Problemas con cut y not
buena_comida( jean_luis). caro(jean_luis). buena_c
omida(francesco). aceptable(Restaurante)
- ground(caro(Restaurante)), !, \
caro(Restaurante) write('No puedo negar algo
Indefinido'), nl, fail.
?- buena_comida(X), aceptable(X). X francesco
No ?- aceptable(X), buena_comida(X). No puedo
negar algo Indefinido No
40Sumario.
- True siempre se verifica y Fail siempre falla.
- Cut previene la exploración de alternativas.
- Cut puede mejorar la eficiencia de un programa.
- Cut permite formular conclusiones mutuamente
- excluyentes mediante reglas de la forma
- If Condición then Conclusión1 else Conclusión2
- Cut permite introducir el operador not La
negación - como fallo.
- Cut y Not deben ser utilizados con prudencia.