430 likes | 660 Views
II. Estructuras de datos en Prolog. Jorge Cabrera Gámez Departamento de Informática y Sistemas Universidad de Las Palmas de Gran Canaria. Tipos de datos. Datos. Términos simples. Estructuras. Constantes. Variables. Átomos. Números. Tipos de datos.
E N D
II. Estructuras de datos en Prolog Jorge Cabrera Gámez Departamento de Informática y Sistemas Universidad de Las Palmas de Gran Canaria Prolog II
Tipos de datos Datos Términos simples Estructuras Constantes Variables Átomos Números Prolog II
Tipos de datos Cadenas de caracteres y números y _, que comiencen con minúscula pepe nil x25 a_ED miss_jones x_ Datos Cadenas de caracteres especiales <--> ===> :-: Ojo con predefinidos, p.e. :- Términos simples Estructuras maýusculas: A, B, ... Z minúsculas: a, b, ... z números: 0, 1, 2, ... 9 car. especiales: + - * / <> = : . & _ ~ Números Enteros: 1, 3 10000 Reales: 1.00, -0.093 Cadenas de caracteres encerrados entre comillas simples ‘Pepe’ ‘Esther Colero’ ‘Ali Catados’ Constantes Variables Átomos Números Prolog II
1 ?- [user]. |: con_hijo(X) :- progenitor(X, Y). Warning: (user://1:9): Singleton variables: [Y] Tipos de datos Variables: Cadenas de caracteres, números y _, que comiencen con mayúscula o _ _pepe Nil _x25 A_ED _234 Datos El contexto léxico de una variable es la cláusula. La variable anónima: cuando una variable aparece una sola vez no es necesario inventarnos un nombre para ella. con_hijo(X) :- progenitor(X, Y). con_hijo(X) :- progenitor(X, _). Términos simples Estructuras Constantes Variables Átomos Números Prolog II
Tipos de datos Datos Términos simples Estructuras Constantes Variables • Estructuras: • Objetos que contienen datos como componentes. • Functores • Listas Átomos Números Prolog II
“Cualquier día de octubre de 1998”: fecha( Dia, octubre, 1998) Functor Functor: Ejemplo: una estructura para representar la fecha. fecha( 13, octubre, 1998) fecha Functor Argumentos 13 octubre 1998 Prolog II
Ejemplo: ficha( identidad( 'Luis', 'Perez', 'Martinez'), nacimiento( fecha( 10, 5, 1970), lugar('Teror', 'Gran Canaria')), direccion( calle( 'Perez Galdos', 41), poblacion( 'Las Palmas de Gran Canaria')), datos( 42232787, estudiante, 928234567)). ficha( identidad( 'Javier', 'Galindo', 'Martinez'), nacimiento( fecha( 1, 5, 1978), lugar('Guia', 'Gran Canaria')), direccion( calle( 'Ansite', 4), poblacion( 'Las Palmas de Gran Canaria')), datos( 42234347, estudiante, 928234117)). ficha( identidad( 'Maria', 'Garzon', 'Martin'), nacimiento( fecha( 1, 2, 1956), lugar('Guia', 'Gran Canaria')), direccion( calle( 'Gomera', 124), poblacion( 'Santa Brigida')), datos( 89234347, arquitecto, 928234227)). Prolog II
Ejemplo: ?- ficha( identidad( N, A1, A2), | nacimiento( _, lugar( 'Teror', 'Gran Canaria')), | _, _). N = 'Luis' A1 = 'Perez' A2 = 'Martinez' ; No ficha( identidad( 'Luis', 'Perez', 'Martinez'), nacimiento( fecha( 10, 5, 1970), lugar('Teror', 'Gran Canaria')), direccion( calle( 'Perez Galdos', 41), poblacion( 'Las Palmas de Gran Canaria')), datos( 42232787, estudiante, 928234567)). El nombre y apellidos de las personas nacidas en Teror de Gran Canaria Prolog II
A efectos de eficacia, resulta conveniente simplificar la estructura de representación ficha( 5123,identidad( 'Luis', 'Perez', 'Martinez')). nacimiento( 5123, fecha( 10, 5, 1970), lugar('Teror', 'Gran Canaria')). direccion( 5123, calle( 'Perez Galdos', 41), poblacion( 'Las Palmas de Gran Canaria')). datos( 5123, 42232787, estudiante, 928234567)). Prolog II
ficha ( 5123, identidad( 'Luis', 'Perez', 'Martinez')). ficha localizador identidad nombre apellido1 apellido2 Prolog II
Ejemplo (cont.): El nombre y apellidos de las personas nacidas en (cualquier) Teror y que residan en Las Palmas de Gran Canaria ?- ficha( X, identidad( N, A1, A2)), | nacimiento( X, _, lugar( 'Teror', _)), | direccion( X, _, poblacion('Las Palmas de Gran Canaria')). X = 5183 N = 'Luis' A1 = 'Perez' A2 = 'Martinez' ; No Prolog II
Ejemplo (cont.): El teléfono de todas las personas nacidas después de 1975 ?- nacimiento(X,fecha(_, _, Año), _), | datos( X, _, _, Telefono), | Año > 1975. X = 5184 Año = 1978 Telefono = 928234117 ; No Prolog II
Listas . (a, . ( b, . ( c, [ ] ))) . . (Cabeza, Cola ) a . . b c [ ] Prolog II
Listas (cont.) ?- Lista1 = [a, b, c], | Lista2 = .(a, .(b, .(c, []))). Lista1 = [a, b, c] Lista2 = [a, b, c] Yes . (a, . ( b, . ( c, [ ] ))) . a . [a, b, c ] = [ ] b . a b c c [ ] Prolog II
Listas (cont.) [a, [b, c ], d ] = [ ] a [ ] d c b ?- display( [a, [b, c], d]). .(a, .(.(b, .(c, [])), .(d, []))) Yes Prolog II
Listas (cont.) Las listas se manipulan dividiéndolas en cabeza y cola Lista [a,b,c] [a] [ ] [[el, gato], maulla ] [maulla, [el, gato ]] Cabeza a a no tiene [el, gato] maulla Cola [ b,c ] [ ] no tiene [maulla] [[el, gato]] Prolog II
Listas (cont.) Las listas se manipulan dividiéndolas en cabeza y cola Lista [a,b,c] [a] [ ] [[el, gato], maulla ] [maulla, [el, gato ]] ?- [X|Y] = [a, b, c]. X = a Y = [b, c] Yes ?- [X|Y] = [a]. X = a Y = [] Yes ?- [X|Y] = []. No ?- [X|Y] = [[el, gato], maulla]. X = [el, gato] Y = [maulla] Yes ?- [X|Y] = [maulla, [el, gato]]. X = maulla Y = [[el, gato]] Yes Prolog II
Listas (cont.) Una operación básica: unificación de listas Unificación X = se Y = ha Z = ido Unificación X = gato Y = [ ] Unificación X = yo Y = bebo Z = [ vino ] Unificación X = el Y = ratón Z = [ se, fue ] Unificación X = a Y = b Z = [ c ] U = u Unificación No unificables Lista1 [ X, Y, Z] [ gato ] [X, Y | Z ] [[el, Y], Z ] [ X, [ Y| Z ], U ] [ X, Y, X ] Lista2 [ se, ha, ido] [ X | Y ] [yo, bebo, vino ] [[X, ratón], [se, fué ]] [ a, [ b, c], u] [ a, b, c ] Prolog II
Listas (cont.) Cadenas de caracteres como listas de códigos ASCII ?- name( lógica, X). X = [108, 243, 103, 105, 99, 97] Yes ?- name(X, [108,243,103,105,99,97]). X = lógica Yes Prolog II
Definición eslista( [ ] ). eslista( [ _ | _ ] ). Operaciones elementales en Listas El predicado eslista es cierto si su argumento es una lista. ?- eslista([ ]). Yes ?- eslista( [a | [b , d]] ). Yes Prolog II
Definición pertenece ( X, [X | _ ] ). pertenece ( X, [ _ | Y] ) :- pertenece (X, Y). Operaciones elementales en Listas El predicado pertenece es cierto si su primer argumento pertenece a la lista que aparece como segundo argumento. ?- pertenece(a, [x,y,a,z]). Yes ?- pertenece(X, [a,b,c]). X = a ; X = b ; X = c ; No Prolog II
?- trace(pertenece). pertenece/2: call redo exit fail Yes ?- pertenece(a,[x,y,a,z]). T Call: ( 8) pertenece(a, [x, y, a, z]) T Call: ( 9) pertenece(a, [y, a, z]) T Call: ( 10) pertenece(a, [a, z]) T Exit: ( 10) pertenece(a, [a, z]) T Exit: ( 9) pertenece(a, [y, a, z]) T Exit: ( 8) pertenece(a, [x, y, a, z]) Yes pertenece ( X, [X | _ ] ). pertenece ( X, [ _ | Y] ) :- pertenece (X, Y). Prolog II
?- trace(pertenece). pertenece/2: call redo exit fail Yes ?- pertenece(a,[s,d,e]). T Call: ( 7) pertenece(a, [s, d, e]) T Call: ( 8) pertenece(a, [d, e]) T Call: ( 9) pertenece(a, [e]) T Call: ( 10) pertenece(a, []) T Fail: ( 10) pertenece(a, []) T Fail: ( 9) pertenece(a, [e]) T Fail: ( 8) pertenece(a, [d, e]) T Fail: ( 7) pertenece(a, [s, d, e]) No pertenece ( X, [X | _ ] ). pertenece ( X, [ _ | Y] ) :- pertenece (X, Y). Prolog II
?- pertenece(a,[f,a,c]). Yes ?- trace(pertenece). pertenece/2: call redo exit fail Yes ?- pertenece(a,[f,a,c]). T Call: (6) pertenece(a, [f, a, c]) T Call: (7) pertenece(a, [a, c]) T Call: (8) pertenece(a, [c]) T Call: (9) pertenece(a, []) T Fail: (9) pertenece(a, []) T Redo: (8) pertenece(a, [c]) T Fail: (8) pertenece(a, [c]) T Redo: (7) pertenece(a, [a, c]) T Exit: (7) pertenece(a, [a, c]) T Exit: (6) pertenece(a, [f, a, c]) Yes Ojo: Mal definido pertenece ( X, [ _ | Y] ) :- pertenece (X, Y). pertenece ( X, [X | _ ] ). Prolog II
Definición incluir ( [] , L, L). incluir ( [X | L1], L2, [ X | L3] ) :- incluir (L1, L2, L3). Operaciones elementales en Listas El predicado incluir proporciona una lista que es concatenación de otras dos. ?- incluir( X, [soy, pepe], [yo, soy, pepe]). X = [yo] Yes ?- incluir( [yo, no], [soy, pepe], L). L = [yo, no, soy, pepe] Yes Prolog II
Definición incluir ( [] , L, L). incluir ( [X | L1], L2, [ X | L3] ) :- incluir (L1, L2, L3). ?- incluir([yo],[soy, pepe],L). T Call: ( 7) incluir([yo], [soy, pepe], _G242) T Call: ( 8) incluir([], [soy, pepe], _G344) T Exit: ( 8) incluir([], [soy, pepe], [soy, pepe]) T Exit: ( 7) incluir([yo], [soy, pepe], [yo, soy, pepe]) L = [yo, soy, pepe] Yes incluir/3 es equivalente al predicado predefinido append/3 Prolog II
Definición cuenta( _, [], 0). cuenta(X, [X | Y], N) :- cuenta(X,Y,Z), N is Z+1. cuenta(X, [W| Y], Z) :- X \== W, cuenta(X,Y,Z). ¿ Es necesario ? Operaciones elementales en Listas El predicado cuenta devuelve el número de ocurrencias de un elemento en una lista simple (sin estructura). ?- cuenta( a, [t,r,a,g,a], N). N = 2 ; No Prolog II
cuenta( _, [], 0). cuenta(X, [X | Y], N) :- cuenta(X,Y,Z), N is Z+1. cuenta(X, [W| Y], Z) :- X \== W, cuenta(X,Y,Z). ?- cuenta( a, [t,r,a,g,a], N). N = 2 ; No cuenta( _, [], 0). cuenta(X, [X | Y], N) :- cuenta(X,Y,Z), N is Z+1. cuenta(X, [W| Y], Z) :- cuenta(X,Y,Z). ?- cuenta( a, [t,r,a,g,a], N). N = 2 ; N = 1 ; N = 1 ; N = 0 ; No Prolog II
Definición elimina( _ , [ ], [ ]). elimina( X, [X | Y], R) :- elimina( X, Y, R). elimina( X, [W| Y], [W | R]) :- X \== W, elimina( X, Y, R). Operaciones elementales en Listas El predicado elimina elimina todas las ocurrencias de un elemento en una lista simple (sin estructura). ?- elimina( i, [e,l,i,m,i,n,a], R). R = [e, l, m, n, a] Yes Prolog II
Definición sustituye( _ , _ , [ ], [ ]). sustituye( X, Y, [X | U], [Y | V]) :- sustituye( X, Y, U, V). sustituye( X, Y, [Z | U], [Z | V]) :- X \== Z, sustituye( X, Y, U, V). Operaciones elementales en Listas El predicado sustituye todas las ocurrencias de un elemento (1er arg.) por el 2º argumento en una lista simple (sin estructura). ?- sustituye( i, a, [e,l,i,m,i,n,a], R). R = [e, l, a, m, a, n, a] Yes Prolog II
Definición reverso( L1, L2):- rev( L1, [ ], L2). rev( [ ], L, L). rev( [X | Y], L1, L2) :- rev( Y, [X | L1], L2). Operaciones elementales en Listas El predicado reverso devuelve la lista inversa de una dada. ?- reverso( [1,2,3,4,5], R). R = [5, 4, 3, 2, 1] Yes Prolog II
reverso( L1, L2):- rev( L1, [ ], L2). rev( [ ], L, L). rev( [X | Y], L1, L2) :- rev( Y, [X | L1], L2). ?- reverso([1,2,3,4,5],R). T Call: ( 8) reverso([1, 2, 3, 4, 5], _G217) T Call: ( 9) rev([1, 2, 3, 4, 5], [], _G217) T Call: ( 10) rev([2, 3, 4, 5], [1], _G217) T Call: ( 11) rev([3, 4, 5], [2, 1], _G217) T Call: ( 12) rev([4, 5], [3, 2, 1], _G217) T Call: ( 13) rev([5], [4, 3, 2, 1], _G217) T Call: ( 14) rev([], [5, 4, 3, 2, 1], _G217) T Exit: ( 14) rev([], [5, 4, 3, 2, 1], [5, 4, 3, 2, 1]) T Exit: ( 13) rev([5], [4, 3, 2, 1], [5, 4, 3, 2, 1]) T Exit: ( 12) rev([4, 5], [3, 2, 1], [5, 4, 3, 2, 1]) T Exit: ( 11) rev([3, 4, 5], [2, 1], [5, 4, 3, 2, 1]) T Exit: ( 10) rev([2, 3, 4, 5], [1], [5, 4, 3, 2, 1]) T Exit: ( 9) rev([1, 2, 3, 4, 5], [], [5, 4, 3, 2, 1]) T Exit: ( 8) reverso([1, 2, 3, 4, 5], [5, 4, 3, 2, 1]) R = [5, 4, 3, 2, 1] Yes ?- trace(rev), trace(reverso). rev/3: call redo exit fail reverso/2: call redo exit fail Yes Prolog II
Definición sublista( S, L):- append( L1, L2, L), append(S, L3, L2). Definición sublista( S, L):- append( _, L2, L), append(S, _, L2). L L1 S L3 L2 Operaciones elementales en Listas El predicado sublista que comprueba si una lista (1er arg.) es parte de otra dada (2º arg.). ?- sublista( [a,s,f], [b,e,a,s,f,g,h]). Yes Prolog II
sublista( S, L):- append( _, L2, L), append(S, _, L2). ?- sublista( [a,s,f], [b,e,a,s,f,g,h]). [debug] ?- sublista( [a,s,f], [b,e,a,s,f,g,h]). T Call: (6) sublista([a, s, f], [b, e, a, s, f, g, h]) Call: (6) sublista([a, s, f], [b, e, a, s, f, g, h]) ? creep Call: (7) append(_G598, _G599, [b, e, a, s, f, g, h]) ? creep Exit: (7) append([], [b, e, a, s, f, g, h], [b, e, a, s, f, g, h]) ? creep Call: (7) append([a, s, f], _G599, [b, e, a, s, f, g, h]) ? creep Fail: (7) append([a, s, f], _G599, [b, e, a, s, f, g, h]) ? creep Exit: (7) append([b], [e, a, s, f, g, h], [b, e, a, s, f, g, h]) ? creep Call: (7) append([a, s, f], _G602, [e, a, s, f, g, h]) ? creep Fail: (7) append([a, s, f], _G602, [e, a, s, f, g, h]) ? creep Exit: (7) append([b, e], [a, s, f, g, h], [b, e, a, s, f, g, h]) ? creep Call: (7) append([a, s, f], _G605, [a, s, f, g, h]) ? creep Exit: (7) append([a, s, f], [g, h], [a, s, f, g, h]) ? creep T Exit: (6) sublista([a, s, f], [b, e, a, s, f, g, h]) Exit: (6) sublista([a, s, f], [b, e, a, s, f, g, h]) ? creep Yes Prolog II
Definición aplana([H|T], Lp):- aplana(H, Hp), aplana(T, Tp), append(Hp, Tp, Lp). aplana([], []). aplana(X, [X]). Operaciones elementales en Listas El predicado aplana transforma una lista compleja, que puede contener a otras listas como elementos, en una lista sin estructura. ?- aplana([a, [ [b], c] ], L). L = [a, b, c] Yes Prolog II
2 ?- trace(aplana). % aplana/2: [call, redo, exit, fail] Yes [debug] 3 ?- aplana([a,[b]],Lp). T Call: (7) aplana([a, [b]], _G486) T Call: (8) aplana(a, _L171) T Exit: (8) aplana(a, [a]) T Call: (8) aplana([[b]], _L172) T Call: (9) aplana([b], _L192) T Call: (10) aplana(b, _L213) T Exit: (10) aplana(b, [b]) T Call: (10) aplana([], _L214) T Exit: (10) aplana([], []) T Exit: (9) aplana([b], [b]) T Call: (9) aplana([], _L193) T Exit: (9) aplana([], []) T Exit: (8) aplana([[b]], [b]) T Exit: (7) aplana([a, [b]], [a, b]) Lp = [a, b] ; T Redo: (9) aplana([], _L193) T Exit: (9) aplana([], [[]]) T Exit: (8) aplana([[b]], [b, []]) T Exit: (7) aplana([a, [b]], [a, b, []]) Lp = [a, b, []] ; … Esta definición produce “basura” en el backtracking. aplana([H|T], Lp):- aplana(H, Hp), aplana(T, Tp), append(Hp, Tp, Lp). aplana([], []). aplana(X, [X]). Además, el uso de append/3 hace que sea muy ineficiente. Prolog II
2 ?- trace(aplana2). % aplana2/2: [call, redo, exit, fail] [debug] 11 ?- aplana2([a,[b]],Lp). T Call: (8) aplana2([a, [b]], _G501) T Call: (9) aplana2([a, [b]], [], _G501) T Call: (10) aplana2(a, [], _L189) T Exit: (10) aplana2(a, [], [a]) T Call: (10) aplana2([[b]], [a], _G501) T Call: (11) aplana2([b], [a], _L210) T Call: (12) aplana2(b, [a], _L231) T Exit: (12) aplana2(b, [a], [b, a]) T Call: (12) aplana2([], [b, a], _L210) T Exit: (12) aplana2([], [b, a], [b, a]) T Exit: (11) aplana2([b], [a], [b, a]) T Call: (11) aplana2([], [b, a], _G501) T Exit: (11) aplana2([], [b, a], [b, a]) T Exit: (10) aplana2([[b]], [a], [b, a]) T Exit: (9) aplana2([a, [b]], [], [b, a]) T Exit: (8) aplana2([a, [b]], [b, a]) Lp = [b, a] ; T Redo: (11) aplana2([], [b, a], _G501) T Exit: (11) aplana2([], [b, a], [[], b, a]) T Exit: (10) aplana2([[b]], [a], [[], b, a]) T Exit: (9) aplana2([a, [b]], [], [[], b, a]) T Exit: (8) aplana2([a, [b]], [[], b, a]) Lp = [[], b, a] … Una nueva definición que es más eficiente. aplana2(L,LP):- aplana2(L,[],LP). aplana2([H|T],A,LP):- aplana2(H,A,HA), aplana2(T,HA,LP). aplana2([],A,A). aplana2(X,A,[X|A]). Problema: La lista resulta invertida Prolog II
% Execution Aborted 12 ?- trace(aplana3). % aplana3/2: [call, redo, exit, fail] % aplana3/3: [call, redo, exit, fail] Yes [debug] 13 ?- aplana3([a,[b]],Lp). T Call: (8) aplana3([a, [b]], _G501) T Call: (9) aplana3([a, [b]], [], _G501) T Call: (10) aplana3([[b]], [], _L189) T Call: (11) aplana3([], [], _L210) T Exit: (11) aplana3([], [], []) T Call: (11) aplana3([b], [], _L189) T Call: (12) aplana3([], [], _L249) T Exit: (12) aplana3([], [], []) T Call: (12) aplana3(b, [], _L189) T Exit: (12) aplana3(b, [], [b]) T Exit: (11) aplana3([b], [], [b]) T Exit: (10) aplana3([[b]], [], [b]) T Call: (10) aplana3(a, [b], _G501) T Exit: (10) aplana3(a, [b], [a, b]) T Exit: (9) aplana3([a, [b]], [], [a, b]) T Exit: (8) aplana3([a, [b]], [a, b]) Lp = [a, b] ; … Lp = [a, b, []] … Un pequeño arreglo es suficiente … aplana3(L,LP):- aplana3(L,[],LP). aplana3([H|T],A,LP):- aplana3(T,A,HA), aplana3(H,HA,LP). aplana3([ ],A,A). aplana3(X,A,[X|A]). para que la lista salga en el orden correcto. Prolog II
Las palabras word(abalone). word(abandon). word(enhance). word(anagram). word(connect). word(elegant). Operaciones elementales en Listas El predicado crossword permite encontrar las palabras que forman un crucigrama de 6 palabras cruzadas (3 verticales y 3 horizontales) de siete letras cada una. ?- crossword(V1,V2,V3,H1,H2,H3). V1 = abalone, V2 = anagram, V3 = connect, H1 = abandon, H2 = elegant, H3 = enhance Yes Prolog II
word(abalone). word(abandon). word(enhance). word(anagram). word(connect). word(elegant). crossword(V1,V2,V3,H1,H2,H3):- word(V1), name(V1,[_,C12,_,C14,_,C16,_]), word(V2), name(V2,[_,C22,_,C24,_,C26,_]), word(V3), name(V3,[_,C32,_,C34,_,C36,_]), word(H1), name(H1,[_,C12,_,C22,_,C32,_]), word(H2), name(H2,[_,C14,_,C24,_,C34,_]), word(H3), name(H3,[_,C16,_,C26,_,C36,_]). a a c abandon a a n elegant o r e enhance e m t Una versión más sofisticada – y realista - podría partir de una “plantilla” de celdas libres y ocupadas para definir el crucigrama. ¿Alguien se anima? Prolog II
Sumario. • Los objetos simples en Prolog: átomos, variables y números. • Las estructuras sirven para representar objetos compuestos. • Las estructuras se construyen por medio de functores. • Cada functor se define por su nombre y aridad. • La misma variable en dos cláusulas representa dos cosas diferentes. El ámbito léxico de una variable es la cláusula. • La lista es una estructura versátil, compuesta de cabeza y cola. Prolog II