Está en la página 1de 0

54 54

List as en Prolog
Estecaptulointroduceel conceptodelista, un tipodedatodegran influencia
dentrodela inteligencia artificial. Secomienza con una introduccin a listas en
Prologya la forma deprocesamientodelas mismas.
as listas son una herramienta importante en la matemtica moderna y en la computacin
simblica. Quien est familiarizado con ella, sabe que las listas son una estructura esencial en
el lenguaje LISP. El objetivo aqu es mostrar cmo pueden utilizarse las listas para
acrecentar la potencia y el alcance de los programas Prolog
Listas como sujetos
Los predicados que se han definido hasta ahora se aplicaron a individuos simples, se definieron por
ejemplo:

hombre(juan).
hombre(predro).
mujer(ana).
mujer(maria).

dondejuan, pedro, ana y maria son individuos particulares.

Sin embargo, en el lenguaje corriente es muy comn la referencia a conjuntos de cosas. Supongamos
que se desea expresar en forma de relaciones al contenido de la frase: Lostomates, laspapas, loszapallosy
lascolesson vegetales. De acuerdo a la forma en que se trabaj en los captulos anteriores, se podra haber
escrito el siguiente grupo de relaciones:

vegetales(tomates).
vegetales(papas).
vegetales(zapallos).
vegetales(coles).

este hecho tambin se puede representar refirindose a los tomates, patatas, zapallos y coles como a una
lista. En tal caso, el predicado vegetalesse aplicara a un solo sujeto, la lista completa:

vegetales([tomates,papas,zapallos,coles])
Captulo
5
L
P R O G R A M A C I N L G I C A

55 55
logrando de esta manera una representacin mucho ms clara y concisa de la informacin contenida en
la frase.

Una lista en Prolog se define como una coleccin de trminos, encerrados entre corchetes y separados
por comas, donde trmino es una de las siguientes cosas:

o Una constante (smbolo)
o Un nmero
o Una variable
o Una lista

Obsrvese que esta definicin de lista es recursiva, ya que un elemento puede ser tanto un tomo
(constante, nmero o variable), como otra lista. Los siguientes son ejemplos de listas vlidas:

[tomates,papas,zapallos,coles]
[juan,pedro,jose]
[m,k,45,r,pi, Juan Perez]
[a,b,[c,e],[f,g]]

El ltimo caso es una lista de cuatro elementos donde los dos primeros son tomos y los dos ltimos
listas. Una lista puede estar formada por otras listas con cualquier nivel deanidamiento. As por
ejemplo:

[[a,b],[[c],d]]

es una lista de listas, cuyo primer elemento es una lista de dos elementos (los tomos a y b) y su
segundo elemento tambin es una lista de dos elementos, donde a su vez el primero es una lista de un
elemento.

Una lista puede ser vaca, la lista vaca en Prolog se denota como:

[ ]

Volviendo al ejemplo de los vegetales, la consulta:

?- vegetales(tomates).

tendr diferente respuesta segn se utilice una u otra forma de representacin. En el primer caso, la
respuesta ser positiva, mientras que en el segundo ser negativa, debido a que el elemento tomates no
puede aparearse con la lista completa.

En este sentido la utilizacin de listas, aunque favorable en trminos de la representacin de
conocimiento, no posibilita consultar directamente a la base de datos acerca de sus elementos
individuales.
P R O G R A M A C I N L G I C A

56 56
Listas de longitud fija

Para obtener cada uno de los elementos de una lista se utiliza el concepto de patrn de lista. Un patrn
no es ms que otra lista (compuesta en su mayor parte de variables), que se intenta unificar con la
primera. El intrprete con el fin de lograr dicha unificacin instancia las variables del patrn con los
elementos de la lista.

De manera que si se unifica el patrn [X] con la lista [a], la variable X se instanciar con el elemento a.
Del mismo modo, para obtener cada uno de los elementos en la lista de vegetales, se puede realizar la
siguiente consulta:

?- vegetales([A,B,C,D]).
A = tomates
B = papas
C = zapallos
D = coles

Quedando instanciadas cada una de las variables con el vegetal correspondiente de la lista. Otros
ejemplos posibles son:

?- [X] = [a]
X = a
Yes

?- [X,Y]=[a,b].
X = a
Y = b
Yes

?- [X,Y,Z] = [a,b,c].
X = a
Y = b
Z = c
Yes

?- [X,Y,Z,W] = [a,b,c,d].
X = a
Y = b
Z = c
W = d
Yes

Ntese que este ejemplo puede continuar indefinidamente, de manera que para obtener los N
elementos de una lista esta debe unificarse con un patrn formado por N variables.

Este mtodo slo puede ser utilizado en el caso que se conozca con exactitud la cantidad de elementos
de una lista, pero no puede ser aplicado con listas de longitud desconocida.

Listas de longitud desconocida
P R O G R A M A C I N L G I C A

57 57
Dada una lista de N elementos:

[e1,e2,e3, ...,eN]

el primer elemento de denomina la cabeza de la lista y el resto su cola:


la cola, a su vez, es una lista que puede dividirse nuevamente en cabeza y cola:

y as continuando hasta llegar a la lista de un elemento cuya cola es vaca.

De esta manera en los casos es que la longitud de la lista es desconocidaes posible utilizar un patrn
que permita separar la cabeza y la cola, este patrn se representa en Prolog de la siguiente manera:

[Cabeza|Cola]
donde el smbolo | significa seguido de. La variable Cabeza se instancia con el primer elemento y la
variable Cola se instancia con una lista formada por el resto de los elementos de la lista.

Para el ejemplo anterior:

Cabeza = e1
Cola = [e2,e3,...,eN]

y en el caso de la lista de vegetales:

Cabeza = tomates
Cola = [papas,zapallos,coles]

Es posible escribir una regla que relacione una lista con su cabeza, y otra que relacione una lista con su
cola (las funciones CAR y CDR en Lisp respectivamente), de la siguiente manera:

es_cabeza(Cab,[Cab|Cola]).

es_cola(Cola,[Cab|Cola]).

Obsrvese que la cabeza de una lista puede ser tanto un elemento como una lista (en caso de ser una
lista de listas) pero la cola es, en s misma, una lista. Por lo tanto, las listas constituyen lo que se
denomina una estructura de datos recursiva, puesto que los objetos que la constituyen pueden contener,
como subestructura recursiva, objetos del mismo tipo.

Los siguientes son ejemplo de intentar unificar distintas listas con el patrn [X| Y]:

[a] X = a
Y = []
4 43 4 42 1
Cola
eN e e e Cabeza ] ,..., 3 , 2 , 1 [
43 42 1
Cola
eN e e Cabeza ] ,..., 3 , 2 [
P R O G R A M A C I N L G I C A

58 58
[a,b] X = a
Y = [b]
[a,b,c,d] X = a
Y = [b,c,d]
[[a,b],c] X = [a,b]
Y = [c]
[[a,b]] X = [a,b]
Y = []
[[a,b],[c,d]] X = [a,b]
Y = [[c,d]]

El patrn [X| Y] est asegurando que la lista va ha tener al menos un elemento ya que este no puede
unificarse con la lista vaca. Del mismo modo se puede se utiliza un patrn [X,Y| Z] para separar los
dos primeros elementos y la cola de una lista de al menos dos elementos. Ejemplos con este patrn son:

[a] Falla
[a,b] X = a
Y = b
Z = []
[a,b,c,d] X = a
Y = b
Z = [c,d]
[[a,b],c] X = [a,b]
Y = c
Z = []

Y en general puede usarse patrones para obtener los primeros N elementos de una lista de al menos N
elementos, anteponiendo N variables al smbolo | .
Por otro lado, para el caso de listas de listas, es posible disear patrones para obtener elementos de las
sublistas, por ejemplo:

[[X]|Y]
una lista de al menos un elemento, cuya cabeza es una lista de
exactamente un elemento
[[X|Y]|Z]
una lista de al menos un elemento cuya cabeza sea tambin una
lista de al menos un elemento
[[X,Y|Z]]
una lista cuyo nico elemento es una lista de al menos dos
elementos

En este punto ya es posible dar una definicin ms precisa de lista, se puede decir que L es una lista si:

o es la lista vaca
o existe otra lista L1 tal que [H| L1] es una lista.

esto puede ser directamente traducido a Prolog, en la construccin de un predicado es_lista quesea
verdadero cuando su nico sujeto sea efectivamente una lista:

es_lista([]).
es_lista([Cab|Cola]) :-
es_lista(Cola).

De esta manera probar que [a,b] es una lista se reduce a probar:
P R O G R A M A C I N L G I C A

59 59
es_lista([b])

y esto a su vez en:

es_lista([])

lo cual se conoce que es verdadero.

Problema Resuelto N1
Construir un predicado que relacione una lista con su cantidad de elementos. Por
ejemplo:

?- longitud_de([a,b,c,d,e],X).
X = 5

Respuesta

Se puede decir que la longitud de una lista es:

o cero si es la lista vaca
o uno ms la longitud de la cola en cualquier otro caso

Lo primero puede representarse en Prolog mediante el hecho:

longitud_de([],0).

Mientras que la segunda afirmacin dara lugar a la regla:

longitud_de([X|Y],L) :-
longitud_de(Y,Lc),
L is Lc + 1.

Es decir, la longitud de una lista es la longitud de la cola ms uno (la cabeza).
Listas como conjuntos
Una lista puede utilizarse para representar conjuntos en Prolog, siempre que cumpla con las
propiedades de los conjuntos de no tener elementos repetidos. De manera que:

Atomo Elemento
Lista Conjunto

En Prolog es posible definir conjuntos por comprensin o por extensin. Por ejemplo el conjunto H
que se define por extensin de la siguiente manera:

H = {juan,luis,pedro}

puede definirse en Prolog mediante la lista:


P R O G R A M A C I N L G I C A

60 60
[juan,luis,pedro]

la cual debe ser sujeto de algn predicado, por ejemplo:

padre(jose, [juan,luis,pedro])

El mismo conjunto puede definirse por comprensin de la siguiente manera:

H = {X| X es hijo de jose}

en el mismo sentido existe en Prolog el predicado findall:

findall(Variable,Predicado,Lista)

donde Lista se unifica con la lista de las instancias de V para las cuales Predicado es verdadero. Por
ejemplo, si se encuentran los siguientes hechos almacenados en la base de datos:

padre(jose, juan)
padre(jose, luis)
padre(jose, pedro)

la siguiente consulta permitir obtener la definicin por comprensin del mismo conjunto mencionado
anteriormente:

?- findall(X,padre(jose,X),L).
L = [juan,luis,pedro])

Problema Resuelto N2
Definir el predicado pertenece que ser verdadero cuando un elemento pertenezca a
un conjunto dado. Por ejemplo:

?- pertenece(f,[a,b,d,f,e]).
Yes

?- pertenece(u,[a,b,d,f,e]).
No

Respuesta

Un elemento pertenece a un conjunto C, representado mediante una lista si:

o es la cabeza de la lista (es un elemento del conjunto C)
o pertenece a la cola de la lista (pertenece a algn subconjunto de C)

La primera opcin se representa en Prolog mediante el siguiente hecho:

pertenece(X,[X|_]).

mientras que la segunda situacin se puede expresar mediante la regla:



P R O G R A M A C I N L G I C A

61 61
pertenece(X,[Y|Z]) :-
pertenece(X,Z).
Vectores
En Prolog, puede considerarse a los vectores como conjuntos ordenados representados en forma de
listas. Se presenta a continuacin una serie de ejemplos en los que se demuestra el tratamiento de
arreglos, en forma de listas.

Problema Resuelto N3
Construir un conjunto de reglas para calcular la suma de dos vectores representados
mediante listas.

Respuesta
El primer ejemplo considerado, es la suma de vectores, y el algoritmo procedural
para su resolucin es el siguiente:

Para i =1 hasta n
S(i) = A(i) + B(i)
fin para

donde A y B son los vectores a sumar, y S el vector resultado.

Para su definicin en Prolog, puede considerarse un predicado ternario es_suma_de_vectores, cuyos sujetos
sean el vector suma S y los vectores sumandos A y B. Utilizando la tcnica recursiva, puede pensarse
que un vector S es la suma de otros dos vectores A y B, si la cabeza de S es la suma de las cabezas de A
y B, y adems el vector cola de S es la suma de los vectores cola de A y B; y la suma es un vector vaco,
si los vectores a sumar son vacos (caso embrionario).

El conjunto de reglas lgicas necesarias para definir la suma de vectores en Prolog se definen entonces
de la siguiente manera (los prefijos Cay Co son utilizados para referirse a la cabeza y cola de una lista,
respectivamente):

es_suma_de_vectores ([ ], [ ], [ ]).

es_suma_de_vectores ([CaS | CoS], [CaA | CoA], [CaB | CoB]) :-
CaS is CaA + CaB,
es_suma_de_vectores (CoS, CoA, CoB).

Problema Resuelto N4
Construir un juego de reglas que relacione un vector con el mismo vector ordenado
mediante el mtodo de seleccin.

Respuesta
Una de las numerosas formas de ordenamiento de vectores, es el mtodo de
seleccin. El algoritmo de ordenamiento por seleccin de un vector de n elementos
queda definido a travs de los siguientes pasos:

o Encontrar el mayor elemento del vector.
o Intercambiar el elemento mayor con el elemento de subndice n.


P R O G R A M A C I N L G I C A

62 62
o A continuacin se busca el elemento mayor en el vector hasta el subndice n-1, y se intercambia con
el elemento de esa posicin, por consiguiente, se sita el segundo elemento mayor en la posicin n-
1.
o A continuacin se busca el elemento mayor en el vector hasta n-2, y as sucesivamente.

Enfoque Procedural:

Para j=n hasta 2 decrementando 1
Mayor = V(j)
Posicion = j
Para i = j-1 hasta 1 decrementando 1
Si V(i) > Mayor
Mayor <- V(i)
Posicion <- j
fin si
fin para
intercambiar (V(j), V(Posicion))
fin para

Enfoque Lgico: Debido a que con listas es mas natural la referencia al primero (la cabeza) que al
ltimo, en el juego de reglas que se propone a continuacin se trabaja con el anlogo lgico de la
bsqueda del menor y el intercambio con la cabeza. En lenguaje natural: "Un vector VO representado
en forma de lista es_ordenado_deotro vector V, si la cabeza de VO es el elemento menor de V y la cola
de VO es_ordenado_deel vector formado por los elementos de V menos el menor".

es_ordenado_de ([ ], [ ]).
es_ordenado_de ([Menor | Ordenado], V) :-
es_el_menor_de (Menor, V),
es_V_sin_el_menor (V1, V, Menor),
es_ordenado_de (Ordenado, V1).

El predicado es_el_menor_derelaciona el tomo menor con la lista a la que pertenece.

Una posibilidad es que el menor sea la cabeza, es decir: "la cabeza de una lista es el menor de sus
elementos, si es menor que el menor de la cola", en cdigo:

es_el_menor_de (CaV, [CaV | CoV]) :-
es_el_menor_de (X, CoV),
CaV < X.

La otra posibilidad es que el menor sea un elemento de la cola, es decir: "un elemento es el menor de
una lista si es el menor de la cola y adems es menor que la cabeza", en cdigo:

es_el_menor_de (X, [CaV | CoV]) :-
es_el_menor_de (X, CoV),
X < CaV.

Para la definicin del caso embrionario, se parte del hecho que el elemento de una lista de un solo
elemento es el menor de la lista:

es_el_menor_de (CaV, [CaV]).
P R O G R A M A C I N L G I C A

63 63

Finalmente, el vector V1 es el formado por todos los elementos del vector V menos el elemento X.

es_V_sin_el_menor (CoV, [X | CoV], X).

es_V_sin_el_menor ([CaV | VA], [CaV | CoV], X) :-
CaV <> X,
es_V_sin_el_menor (VA, CoV, X).

También podría gustarte