Prolog de Primer Orden

Anuncio
Prolog de Primer Orden
• Prolog es un ejemplo de un paradigma de programación llamado programación
en lógica.
• Un programa en Prolog puro de primer orden es un conjunto de cláusulas de
horn definitivas de primer orden.
• Una cláusula de horn definitiva de primer orden es una cláusula, cuantificada
universalmente y que contiene exactamente un literal positivo. Por ejemplo:
∀xyz (P (x, y) ∨ ¬Q(x, y) ∨ ¬R(x, y, z))
• En programación en lógica, esta cláusula se anota simplemente como:
P (x, y) ← Q(x, y), R(x, y, z)
• Los predicados se anotan con letras minúsculas. Si p de aridad n, se acostumbra
a llamarlo por p/n.
Jorge Baier Aranda, PUC
<< Atrás
174
• Al igual que en lógica de predicados, un término puede ser:
Constantes: Estas pueden ser:
Átomos: Sı́mbolos que comienzan con letra minúscula, por ej. x, y, a,
etc. Sı́mbolos encerrados en comillas simples, por ej. ’X’, ’ 5’, ’ x23’,
’a’,, etc.
Números: Enteros y/o reales. Por ej. 4, 9.5, etc..
Caracteres y textos (strings): Los carácteres y los strings se encierran entre
comillas dobles. Por ej. "f", "fam", etc.
Variables: Sı́mbolos que comiencen con letra mayúscula o con un guión bajo
’ ’. Por ej., X, 5, x23.
Functores: Son términos de función. Por ej., padre(X,bonifacio), etc.
Un functor tiene una aridad asociada. Si f es el nombre de un functor, f /m
denota que f tiene aridad m.
• Un programa prolog está compuesto por cláusulas de horn con la siguiente sintaxis
l:-l1, . . . , ln,
donde l, y l1, ..., ln son literales positivos.
Jorge Baier Aranda, PUC
<< Atrás
175
En el caso en que n = 0, la cláusula se llama hecho y se anota simplemente
como
l.
Cuando n > 0 se acostumbra a llamar reglas a las cláusulas.
• Por ejemplo, la siguiente cláusula (o regla) Prolog:
ancestro(X,Y) :- progenitor(X,Z),ancestro(Z,Y).
corresponde a la siguiente cláusula de primer orden:
∀x∀y∀z (progenitor(x, z) ∧ ancestro(z, y) → ancestro(x, y))
que, a su vez, es equivalente a:
∀x∀y (∃z (progenitor(x, z) ∧ ancestro(z, y)) → ancestro(x, y))
Esto significa que toda variable que no se menciona en forma explı́cita en la
cabeza de una regla se debe suponer como cuantificada existencialmente en la
cola de ella.
Jorge Baier Aranda, PUC
<< Atrás
176
• El siguiente ejemplo se puede ver como una base de datos de una familia.
padre(alberto,juan).
madre(julia,juan).
padre(pedro,maria).
madre(helena,maria).
padre(juan,olga).
madre(maria,olga).
padre(juan,’Alberto Jr.’).
progenitor(X,Y) :- padre(X,Y).
progenitor(X,Y) :- madre(X,Y).
ancestro(X,Y) :- progenitor(X,Y).
ancestro(X,Y) :- progenitor(X,Z),ancestro(Z,Y).
• Este programa es una teorı́a de primer orden. Prolog permite consultar qué cosas
se deducen de él. La respuesta la entrega usando un mecanismo de demostración
que veremos más adelante.
Jorge Baier Aranda, PUC
<< Atrás
177
• Las siguientes son consultas que se pueden hacer al intérprete.
?- progenitor(juan,olga).
Yes.
?- progenitor(X,juan).
X = alberto
Yes
• La segunda consulta se
progenitor(X,juan)?”.
puede
leer
como
“¿existe
un
X
tal
que
obtienen
de
la
consulta
• Al ingresar ; Prolog busca otra respuesta.
• Estas son todas las
progenitor(X,juan).
respuestas
que
se
X = alberto ;
X = julia ;
No
Jorge Baier Aranda, PUC
<< Atrás
178
• La siguiente consulta pregunta por todos los X que son descendientes de alberto,
?- ancestro(alberto,X).
X = juan ;
X = olga ;
X = ’Alberto Jr.’ ;
No
• ¿Qué significa la siguiente consulta?
?- ancestro(p,q).
No
• ¿Qué significa este comportamiento desde el punto de vista lógico?
• Si un intérprete de Prolog logra demostrar una consulta φ dado un programa P,
entonces diremos que:
P `p φ
• La pregunta anterior se puede reformular como: ¿Podemos establecer una
correspondencia entre |= y `p?
Jorge Baier Aranda, PUC
<< Atrás
179
Algoritmo de Resolución de P ROLOG
• A continuación presentamos una simplificación del algoritmo de resolución de
Prolog de primer orden.
• En el pseudo código del algoritmo se utiliza las siguientes convenciones.
GL0: Lista de literales correspondientes al objetivo o consulta inicial.
GL: Lista de objetivos (literales positivos).
ren: Un procedimiento que recibe una lista de literales y renombra las variables
con nombres nuevos. Es usual que estos nombres sean de la forma n donde
n es un número entero.
PP y PP aux: Dos procedimientos que reciben una lista de objetivos y retornan
una sustitución o #Falso si no hay sustitución posible. PP aux recibe además
de la lista de objetivos, un ı́ndice a una cláusula dentro del programa.
UMG Prolog: El procedimiento UMG sin occurs check (ya veremos de que se trata
esto).
Jorge Baier Aranda, PUC
<< Atrás
180
c1, c2, . . . cm: Las cláusulas del programa.
#m: Constante que se inicializa como el número de cláusulas del programa.
Cabeza y Cola: dos funciones sobre reglas o listas de objetivos. Si x es una
lista, entonces Cabeza(x) es el primer literal de x y Cola(x) es el resto de la
lista. Si x es una cláusula, Cabeza(x) es la cabeza de la cláusula y Cola(x)
es el cuerpo.
aplicarSust : Aplica una sustitución a un conjunto de variables cláusulas.
composición: Permite componer dos sustituciones.
• Dado que GL0 es el objetivo inicial, el procedimiento prolog se invoca como:
PP(ren(GL0), nil)
Jorge Baier Aranda, PUC
<< Atrás
181
• A continuación se muestra la implementación de las funciones necesarias para la
resolución:
function PP(GL,S)
/* devuelve una sustitución que satisfaga GL o devuelve #Falso */
{
if GL=nil return(S);
PP_aux(GL,S,1)
}
function PP aux(GL,S,i)
/* devuelve sustitución que satisfaga GL o #Falso */
{
cláusula C’; /* variables auxiliares */
sustitución S’, S’’;
if i>#m return(#Falso);
C’:= ren(C[i]);
S’:= UMG_Prolog(Cabeza(GL),Cabeza(C’));
if S’=#Falso return(PP_aux(GL,S,i+1));
S’’:=PP(aplicarSust(S’,append(Cola(C’),Cola(GL))),
composición(S,S’));
if S’’=#Falso return(PP_aux(GL,S,i+1));
return(S’’);
Jorge Baier Aranda, PUC
<< Atrás
182
}
• Tal como sugerimos en resolución de primer orden, este algoritmo renombra
variables antes de aplicar la regla de resolución.
• Si Prolog responde NO cuando este algoritmo retorna #Falso, ¿qué significa que
Prolog responda NO?
• ¿qué le falta a este algoritmo?
– Resatisfacción de consultas. ¿cómo podemos implementar esto?
– ¿Cómo podemos incorporar negación?
Jorge Baier Aranda, PUC
<< Atrás
183
Árboles de demostración
• En Prolog es posible rastrear la demostración de un objetivo a través del
comando trace.
• Una vez que el intérprete está en modo trace, toda demostración de una consulta
es mostrada paso a paso.
• Volvamos a considerar el ejemplo de la base de datos familiar.
• El siguiente ejemplo muestra un trace de la ejecución de la consulta
ancestro(alberto,olga). [trace] ?- progenitor(maria,X).
Call:
Call:
Fail:
Redo:
Call:
Exit:
Exit:
(6)
(7)
(7)
(6)
(7)
(7)
(6)
progenitor(maria, G384) ? creep
padre(maria, G384) ? creep
padre(maria, G384) ? creep
progenitor(maria, G384) ? creep
madre(maria, G384) ? creep
madre(maria, olga) ? creep
progenitor(maria, olga) ? creep
X = olga ;
Jorge Baier Aranda, PUC
<< Atrás
184
Fail:
Fail:
No
(7) madre(maria, G384) ? creep
(6) progenitor(maria, G384) ? creep
• Esta demostración se puede resumir en el siguiente árbol de demostración:
progenitor(maria,X)
X= G384
progenitor(maria,
G384)
....
.......... .....................
..........
......
..........
..........
..........
..........
.
.
.
.
.
.
.
.
.
.
..........
..........
..........
..........
..........
.
.
.
.
.
.
.
.
.
...
..........
..........
..........
padre(maria, G384)
...........
...........
...........
...........
...........
...........
...........
...........
...........
...........
...........
...........
...........
.....
madre(maria, G384)
.
×
G384=olga
• En forma resumida, en un árbol de demostración:
– Cada nodo no hoja tiene como etiqueta un objetivo a demostrar o los sı́mbolos.
– Los nodos hoja están etiquetados con o ×.
– Si un nodo n es padre de un nodo h, entonces h es el resultado de aplicar la
regla de resolución entre n y alguna cláusula del programa.
Jorge Baier Aranda, PUC
<< Atrás
185
– La etiqueta que une a n con h es la sustitución aplicada en la resolución.
– Una demostración exitosa de un objetivo está dada por las resoluciones que dan
origen a una rama que termina en un nodo hoja etiquetado con (cláusula
vacı́a).
– Ejercicio: construya un árbol de demostración para ancestro(olga,X).
• Una observación interesante es que Prolog siempre recorre el árbol de
demostración en profundidad.
Jorge Baier Aranda, PUC
<< Atrás
186
¿Es un Programa Prolog un Programa en Lógica?
• ¿Por que nos hacemos esta pregunta?
• Serı́a ideal que Prolog el método de resolución de Prolog representara
exactamente la noción de consecuencia lógica.
• Es decir, si P es un programa, entonces
P |= ϕ ssi P `p ϕ
• Supongamos que en el ejemplo de la familia, preguntamos por padre(hugo,X)
• Prolog responderá que NO. ¿Significa esto que del programa se deduce
¬∃X padre(hugo, X)?
La respuesta es no, porque hay un modelo del programa en el cual dicha fórmula
es satisfacible!
Jorge Baier Aranda, PUC
<< Atrás
187
• De hecho, si P es un programa Prolog puro, entonces, nunca es posible que
P |= ¬`,
donde ` es un literal de primer orden.
• Esto es una conclusión directa del siguiente teorema.
Teorema 7. Un conjunto de cláusulas de Horn de primer orden es siempre
consistente.
Demostración: Basta con encontrar una interpretación con un dominio A en
que las extensiones de todo predicado n-ario contiene exactamente a An. Tal
interpretación es un modelo para el conjunto, porque todas las cláusulas tienen
un literal positivo.
• Cabe preguntarnos qué relación hay entre la lógica de primer orden y Prolog.
• Si la correspondencia no es exacta, ¿podemos, al menos dar a Prolog una
semántica precisa?
Jorge Baier Aranda, PUC
<< Atrás
188
• A continuación veremos cómo hacer esto.
Jorge Baier Aranda, PUC
<< Atrás
189
Significado Declarativo de una Respuesta de P ROLOG
• Hasta el momento hemos visto que Prolog puede responder a preguntas con
variables libres.
• ¿Qué significa desde el punto de vista lógico que Prolog demuestre p(X,Y)?
• Recordemos que en lógica de primer orden es posible tener un sinfin de
interpretaciones distintas.
• Para dar semántica a Prolog, utilizaremos una noción restringida de
interpretación.
• Estas interpretaciones tendran como universo a los universos de Herbrand.
Jorge Baier Aranda, PUC
<< Atrás
190
Modelos de Herbrand
• Un universo de Herbrand es una estructura que se origina de la sintaxis del
lenguaje.
• Veamos antes un par de definiciones.
Definición 26. Un término instanciado (ground term) de un lenguaje de primer
orden, es un término que no contiene variables.
Definición 27. Un universo de Herbrand está formado por todos los términos
instanciados del lenguaje.
• Veamos un ejemplo
Supongamos el programa:
p(f(X)):- q(g(X)).
p(f(X)):- p(X).
p(a).
q(a).
Jorge Baier Aranda, PUC
<< Atrás
191
• En este programa tenemos los términos de función f y g y las constantes a y b.
• El universo de Herbrand es:
{a, b, f (a), g(a), f (b), g(b), f (f (a)), f (g(a)), g(f (a)), g(g(b)), . . .}
• Desde el punto de vista intuitivo un universo de Herbrand es un universo mı́nimo
pues no tiene elementos que no se pueden nombrar usando la sintaxis del lenguaje.
• Si P es un programa construido sobre
h{R1, . . . , Rn}, {f1, . . . , fn}, {C1, . . . , Cn}i, entonces
los
sı́mbolos
S
=
H = hDH, {R1H, . . . , RnH}, {f1H, . . . , fnH}, {C1H, . . . , CnH}i,
donde DH es el universo de Herbrand de P, es una estructura de Herbrand para
ese lenguaje.
• La interpretación de los términos del lenguaje da una correspondencia unı́voca
entre los términos del lenguaje y los objetos del universo. Ası́, una interpretación
Jorge Baier Aranda, PUC
<< Atrás
192
de Herbrand es tal que:
I(Cn) = Cn
I(fn(t1, . . . , tn)) = fn(I(t1), . . . , I(tn))
• La pregunta clave es qué es lo que se deduce de un programa en un universo de
Herbrand.
• No podemos deducir más que propiedades acerca de los objetos del universo.
• Por ejemplo, si tenemos el programa P:
numero(0).
numero(s(X)) :- numero(X).
suma(X,0,X).
suma(X,s(Y),Z) :- suma(s(X),Y,Z).
Los únicos hechos que podrı́amos llegar a deducir son:
{numero(0), suma(0, 0, 0), numero(s(0)), suma(s(0), 0, 0),
suma(s(0), s(0), 0), suma(s(0), s(0), s(0)), . . .}
Jorge Baier Aranda, PUC
<< Atrás
193
• Esta secuencia de propiedades de objetos concretos es lo que se conoce como
una base de Herbrand.
• Formalmente,
Definición 28. [Base de Herbrand] Sea P un programa en lógica construido
sobre los sı́mbolos S = h{R1, . . . , Rn}, {f1, . . . , fn}, {C1, . . . , Cn}i
B(P) = {Ri(t1, . . . , tn) | Ri es un sı́mbolo de predicado de aridad n y
tj es un término instanciado (1 ≤ j ≤ n)}
• Un Modelo de Herbrand mı́nimo para P, escrito por IH (P), es un subconjunto
de B(P), pero que contiene exactamente los hechos que se deducen de un
programa.
Jorge Baier Aranda, PUC
<< Atrás
194
• En el programa ejemplo, un modelo mı́nimo de Herbrand es:
{numero(0), numero(s(0)), numero(s(s(0))), . . .
suma(0, 0, 0), numero(0, s(0), s(0)), numero(s(0), s(0), s(s(0))), . . .}
• Formalmente,
Definición 29. Un Modelo mı́nimo de Herbrand IH (P) para un programa en
lógica P es un subconjunto de B(P) tal que si r ∈ IH (P) entonces existe una
clausula
ch : −c1, . . . , cn
en P y una sustitucion θ tal que:
– chθ ≡ r
– ciθ ∈ IH (P) con 1 ≤ i ≤ n
• Ahora si preguntamos a Prolog por una lista de objetivos GL, entonces GL es
verdadero si existe una sustitución θ tal que para cada g ∈ GL, se cumple que
gθ ∈ IH (P)
Jorge Baier Aranda, PUC
<< Atrás
195
• Este es el que se conoce como significado declarativo de un programa Prolog.
• También podemos decir que lo que Prolog hace, en el fondo, al demostrar un
objetivo p(X,Y) es encontrar una demostración constructiva
∃X∃Y p(X, Y)
• La demostración es constructiva porque Prolog encuentra valores para X e Y
para los que p(X,Y) es consecuencia lógica del programa.
• En el área de bases de datos deductivas es común tratar a las consultas que
requieren valores como respuesta como consultas con variables libres.
De esta manera la consulta
∃Rut alumno(N ombre, Rut, Dir)
Se interpreta como una consulta en la que se pregunta por el N ombre y Dir de
las tuplas de la tabla alumno.
Jorge Baier Aranda, PUC
<< Atrás
196
Propiedades de la Resolución Prolog
• ¿Es Prolog correcto?
La resolución Prolog serı́a correcta si es que corresponde exactamente a la
regla de primer orden.
Lamentablemente, el mecanismo de resolución de Prolog no realiza occurs
check .Esto hace que el intérprete no reconozca casos en los cuales no se puede
realizar unificación:
?- X=f(X).
X = f(f(f(f(f(f(f(f(f(f(...))))))))))
Nota: de hecho, algunos Prolog se ’caen’ con la consulta X=f(X),write(X).
Para ver más claro el poblema, consideremos el siguiente programa:
q :- p(X,X).
p(X,Y) :- X=f(Y).
La respuesta a la consulta q es, incorrectamente, Yes.
Jorge Baier Aranda, PUC
<< Atrás
197
• Prolog tampoco es completo.
• La fuente de incompleción de Prolog es:
– La manera en que se recorre el árbol (en profundidad) de demostración hace
que Prolog pueda caer en loops infinitos.
Consideremos el siguiente programa:
numero(s(X)) :- numero(X).
numero(0).
sin embargo, observen el comportamiento frente a la siguiente consulta.
?- numero(X).
ERROR: Out of local stack
Si cambiamos el programa original por:
numero(0).
numero(s(X)) :- numero(X).
obtenemos
?- numero(X).
X = 0 ;
X = s(0) ;
X = s(s(0)) ;
X = s(s(s(0))) ;
...
Jorge Baier Aranda, PUC
<< Atrás
198
En otras palabras, esto significa que el significado declarativo de Prolog es
distinto al significado procedural de prolog.En ambos programas, el significado
declarativo es el mismo, pero el intérprete no entrega las mismas respuestas.
Jorge Baier Aranda, PUC
<< Atrás
199
Negación como Falla
• Hasta ahora, nuestros programas Prolog son incapaces de representar la noción
de negación.
• Por ejemplo, supongamos que quisiéramos agregar la siguiente información como
una regla:
“Maria adora a los animales, excepto a las gatos”
• Una forma natural de hacer esto en primer orden serı́a:
∀x (animal(x) ∧ ¬gato(x) → adora(M aria, x))
• En Prolog, usaramos la siguiente regla:
adora(maria,X) :- animal(X), not gato(X).
• En general, el intérprete de Prolog responde SI para un objetivo not G si es
que no pudo demostrar G usando resolución a partir del programa.
Jorge Baier Aranda, PUC
<< Atrás
200
Problemas con Negación como Falla
• Es necesario ser extremadamente cuidadoso cuando se utiliza negación como
falla.
• En general, hay que evitar que hayan variables no unificadas en objetivos
precedidos por not.
• Supongamos el siguiente ejemplo:
animal(piolin).
animal(silvestre).
animal(porky).
pajaro(piolin).
gato(silvestre).
chancho(porky).
adora(maria,X) :- animal(X), not(gato(X)).
• ¿Qué respuestas da Prolog a la consulta adora(maria,X).
• Exactamente las que esperábamos, X=piolin, X=porky.
Jorge Baier Aranda, PUC
<< Atrás
201
• Cambiemos ahora la última regla por:
adora(maria,X) :- not(gato(X)),animal(X).
• ¿Qué obtenemos ahora como respuesta a adora(maria,X)?
• Inesperadamente, la respuesta que da Prolog es NO. ¿Por qué?
Jorge Baier Aranda, PUC
<< Atrás
202
Estructuras de Datos en Prolog
• La semántica de modelos mı́nimos subyacente de Prolog, permite expresar en
forma sencilla estructuras de datos que no se pueden modelar en primer orden.
• Por ejemplo, más adelante veremos que no es posible construir un conjunto de
axiomas tales que fuercen a tener modelos cuyo dominio sean los naturales.
• En Prolog cosas como estas son muy sencillas de expresar.
• De hecho, ya hemos visto algo de esto. Supongamos que utilizamos el predicado
numero para identificar a los naturales.
• Podemos considerar al primer número como 0, al sucesor de 0 como s(0), al
sucesor de éste como s(s(0)).
• Si bien los nombres que usamos para los números son distintos (no usamos
1, 2, 3, . . .), esta representación es suficiente.
• El predicado numero se puede expresar fácilmente como:
Jorge Baier Aranda, PUC
<< Atrás
203
numero(0).
numero(s(X)) :- numero(X).
• Supongamos ahora que queremos construir un predicado suma(X,Y,Z) que es
verdadero cuando Z es la suma de X e Y en esta representación.
• Una posibilidad es la siguiente:
suma(0,X,X).
suma(s(X),Y,Z):- suma(X,s(Y),Z).
• Esto se basa en la siguiente propiedad de la suma: (x + 1) + y = x + (y + 1)
• Un ejemplo de ejecución es el siguiente:
?- suma(s(s(0)),s(s(s(0))),X).
X = s(s(s(s(s(0))))) ;
No
• Notable es el hecho que parámetros que podrı́amos haber pensado como entradas,
también pueden ser parámetros de salida.
Jorge Baier Aranda, PUC
<< Atrás
204
• Por ejemplo la consulta suma(s(s(0)),X,s(s(s(0)))) significa “¿qué número
debo sumarle a 2 para que de 3?” puede ser respondida por Prolog usando la
implementación que hemos visto: ?- suma(s(s(0)),X,s(s(s(0)))).
X = s(0) ;
No
• Esto se debe a que la regla de alguna manera expresa “como funciona” la suma
en los naturales. Prolog se limita simplemente a demostrar.
• ¿Cómo podemos implementar la multiplicación?
mult(0,X,0).
mult(s(X),Y,Z) :- mult(X,Y,U),suma(U,Y,Z).
• ¿En qué propiedad de la multiplicación está basada esta regla?
• Podremos ahora usar a Prolog para resolver la ecuación:
3x + 1 = 7
Jorge Baier Aranda, PUC
<< Atrás
205
• La respuesta es sı́! Con la siguiente consulta:
?- suma(U,s(0),s(s(s(s(s(s(s(0)))))))),mult(X,s(s(s(0))),U).
U = s(s(s(s(s(s(0))))))
X = s(s(0))
Yes
• ¿Podrá encontrar las soluciones de x2 − 3x + 2 = 0?
• Primer intento. Usando la consulta:
mult(X,X,U),mult(s(s(s(0))),X,V),suma(Z,V,U),suma(Z,s(s(0)),0).
Resultado: Prolog no responde. ¿Por qué ocurre esto?
• Segundo intento: Usando la consulta
mult(X,X,U),mult(s(s(s(0))),X,V),suma(U,s(s(0)),Z),suma(V,0,Z).
Jorge Baier Aranda, PUC
<< Atrás
206
Resultado: X = s(0)
U = s(0)
V = s(s(s(0)))
Z = s(s(s(0))) ;
X = s(s(0))
U = s(s(s(s(0))))
V = s(s(s(s(s(s(0))))))
Z = s(s(s(s(s(s(0))))))
Funciona!
• Como conclusión: Prolog no resuelve todo (esto es consecuencia de que es
incompleto).
• Para que encuentre las respuestas es necesario que el programador se preocupe
de ordenar la búsqueda, que no es lo ideal.
Jorge Baier Aranda, PUC
<< Atrás
207
Manejo de Listas
• Es posible también manejar listas en Prolog.
• La siguiente es una definición inductiva de lista.
– La lista vacı́a nil, es una lista.
– Si L es una lista, entonces a · L también es una lista.
• De esta manera, la lista formada por los números 1,2 y 3 se ve bajo esta definición
como
1 · 2 · 3 · nil
y que en la representación gráfica usual se verı́a como:
1
...........
......
2
...........
......
3
.
.....
.....
.....
....
.
.
.
.
....
.....
.....
.....
.....
.
.
.
.
..
.....
.....
• En Prolog, representaremos el constructor de listas · por el functor cons. Ası́:
lista(nil).
lista(cons(X,L)) :- lista(L).
Jorge Baier Aranda, PUC
<< Atrás
208
Concatenación de Listas
• La operación de concatenación de lista ◦ sirve para juntar dos listas en una sola.
• La concatenación se puede definir inductivamente por:
– nil ◦ L = L, con L lista.
– (a · L1) ◦ L2 = a · (L1 ◦ L2), con L1 y L2 listas.
• La implementación de esta definición es directa:
conc(nil,L,L).
conc(L,L2,Z) :- L=cons(X,L1),conc(L1,L2,U),Z=cons(X,U).
• Esta última definición se puede reemplazar por:
conc(nil,L,L).
conc(cons(X,L1),L2,cons(X,U)) :- conc(L1,L2,U).
• La siguiente es una muestra de ejecución:
Jorge Baier Aranda, PUC
<< Atrás
209
?- conc(cons(a,nil),cons(b,cons(c,nil)),L).
L = cons(a, cons(b, cons(c, nil))) ;
No
• Nuevamente, podemos usar los parámetros como entrada salida, como en la
siguiente consulta:
?- conc(X,Y,cons(1,cons(2,cons(3,nil)))).
X = nil
Y = cons(1, cons(2, cons(3, nil))) ;
X = cons(1, nil)
Y = cons(2, cons(3, nil)) ;
X = cons(1, cons(2, nil))
Y = cons(3, nil) ;
X = cons(1, cons(2, cons(3, nil)))
Y = nil ;
Jorge Baier Aranda, PUC
<< Atrás
210
No
• Siguiendo estas mismas ideas es posible implementar otras estructuras de datos,
como por ejemplo árboles o colas.
Jorge Baier Aranda, PUC
<< Atrás
211
Otra Aplicación: Búsqueda y Cálculo de Situaciones
• El cálculo de situaciones es una familia de lenguajes lógicos de primer orden más
inducción.
• Es una familia de lenguajes con tipos.
• En las lógicas con tipos las variables pertenecen a un tipo especı́fico.
• Este lenguaje ha sido usado en inteligencia artificial para modelar mundos
dinámicos.
• En el cálculo de situaciones se distinguen los siguientes elementos:
– Situaciones. Hay una única situación inicial, S0. Todas las situaciones
siguientes se obtienen como resultado de ejecutar alguna secuencia de acciones
en S0.
Si s es una situación, diremos que do(a, s) es la situación que resulta de
ejecutar a en s.
– Acciones. Son los elementos que sirven para cambiar de una situación a otra.
Jorge Baier Aranda, PUC
<< Atrás
212
– Predicado especial P oss. P oss(a, s) es verdadero ssi la acción a es posible
en la situación s.
– Fluentes. Son predicados que sirven para representar las propiedades del
mundo. Estos predicados tienen siempre un único argumento de situación.
Por ejemplo,
sobreElP iso(x, s)
Puede significar que el objeto x se encuentra sobre el piso en la situación s.
• Tal como en los lenguajes ordinarios de primer orden tenemos objetos del dominio
y predicados sin términos de situación.
• Éstos últimos se utilizan para especificar propiedades que no cambian al ejecutar
acciones.
Jorge Baier Aranda, PUC
<< Atrás
213
El mundo de Bloques
• Modelaremos el mundo de bloques de la figura en el Cálculo de Situaciones y
veremos qué tareas de razonamiento podemos realizar.
C
B
A
D
M1
M2
M3
• En el mundo de bloques de la figura, existen tres mesas (M1, M2 y M3 y un
conjunto de bloques.
• Siempre es posible tomar un bloque libre (que no tiene bloques sobre él) y ubicarlo
sobre otro bloque.
• Las mesas M1, M2 y M3 no son manipulables.
Jorge Baier Aranda, PUC
<< Atrás
214
• Llamaremos objeto tanto a mesas como bloques.
• Para el modelo en el cálculo de situaciones usaremos los el siguiente fluente:
– sobre(x, y, s): Verdadero ssi el bloque x está sobre el objeto y en la situación
s.
• Y la siguiente acción
– mover(x, y): Mueve el objeto x sobre y.
• La teorı́a consta de una serie de axiomas.
• Axiomas para propiedades estáticas:
manipulable(x) ↔ x = A ∨ x = B ∨ x = C ∨ x = D
objeto(x) ↔ x = A ∨ x = B ∨ x = C ∨ x = D ∨ x = M1 ∨ x = M2 ∨ x = M3
Jorge Baier Aranda, PUC
<< Atrás
215
• Axiomas de precondición para acciones:
P oss(mover(x, y), s) ↔¬x = y ∧ ¬∃zsobre(z, x, s)∧
¬∃zsobre(z, y, s) ∧ manipulable(x)
• Axiomas de efecto para el fluente sobre. Estos axiomas se usan para especificar
cuando cambian las propiedades dinámicas del dominio.
∀axyzs (P oss(a, s) ∧ a = mover(x, y, s) ∧ sobre(x, z, s) → sobre(x, y, do(a, s))).
∀axyzs (P oss(a, s) ∧ a = mover(x, y, s) ∧ sobre(x, z, s) → ¬sobre(x, z, do(a, s))).
• Estos axiomas no son suficientes para especificar completamente como cambia el
fluente sobre(x, y, s) (¿por qué?)
Para ello, escribimos el siguiente axioma de estado sucesor :
Jorge Baier Aranda, PUC
<< Atrás
216
∀as (P oss(a, s) → (sobre(x,y, do(a, s)) ↔
a = mover(x, y)∨
sobre(x, y, s) ∧ ¬∃ za = mover(y, z)))
• Axiomas para determinar la situación inicial.
∀xy sobre(x, y, S0) ↔ (x = A ∧ y = M1∨
x = B ∧ y = A∨
x = C ∧ y = B∨
x = A ∧ y = M1 ∨
x = D ∧ y = M2 )
• Además es necesario agregar axiomas de nombres únicos para objetos del dominio.
¿por qué?
Jorge Baier Aranda, PUC
<< Atrás
217
• Si agrupamos todos estos axiomas dentro de una teorı́a Σ, es sencillo verificar
que:
Σ |=sobre(C, D, do(mover(C, D), S0))∧
¬∃x sobre(x, B, do(mover(C, D), S0))
Jorge Baier Aranda, PUC
<< Atrás
218
La especificación en Prolog
• La traducción de esta teorı́a a un programa Prolog es directa.
• El siguiente es el programa Prolog correspondiente:
% Predicados estáticos
manipulable(X) :- X=a; X=b; X=c; X=d.
objeto(X) :- X=a; X=b; X=c; X=d; X=m1; X=m2;X=m3.
% Axioma de precondicion
poss(mover(X,Y),S) :manipulable(X),
objeto(Y),
\+ X=Y,
\+ sobre(Z,X,S),
\+ sobre(Z,Y,S).
% Axioma de estado sucesor
Jorge Baier Aranda, PUC
<< Atrás
219
sobre(X,Y,do(A,S)) :poss(A,S),
sobre(X,Y,S),
\+ A=mover(X,Z).
sobre(X,Y,do(A,S)) :poss(A,S),
A=mover(X,Y).
% Descripción de la situación inicial
sobre(a,m1,s0).
sobre(b,a,s0).
sobre(c,b,s0).
sobre(d,m2,s0).
% Situaciones legales
legal(s0).
legal(do(A,S)) :legal(S),
Jorge Baier Aranda, PUC
<< Atrás
220
poss(A,S).
• Ahora podemos hacer las siguientes consultas:
?- sobre(X,Y,do(mover(c,d),s0)).
X = a
Y = m1 ;
X = b
Y = a ;
X = d
Y = m2 ;
X = c
Y = d ;
No
Jorge Baier Aranda, PUC
<< Atrás
221
?- legal(S),sobre(b,m1,S),sobre(a,b,S).
S = do(mover(a, b), do(mover(b, m1), do(mover(a, m3),
do(mover(b, c), do(mover(c, d), s0))))) ;
S = do(mover(a, b), do(mover(b, m1), do(mover(a, c),
do(mover(b, m3), do(mover(c, d), s0))))) ;
S = do(mover(a, b), do(mover(b, m1), do(mover(a, d),
do(mover(b, c), do(mover(c, m3), s0)))))
• ¿Hay inteligencia detrás de esto?
Jorge Baier Aranda, PUC
<< Atrás
222
Descargar