programación logica prolog³n_prolog...programación logica prolog dr. oldemar rodríguez rojas...
Post on 21-Jan-2020
9 Views
Preview:
TRANSCRIPT
PROgramación LOGica
PROLOG
Dr. Oldemar Rodríguez Rojas
Escuela de Informática
Universidad de Nacional
¿Dónde bajar?
Strawberry PROLOG:
www.dobrev.com
PROLOG -> PROgramming in LOGig
Paradigma -> El lenguaje de la lógica puede se usado para programar
Padre de PROLOG -> Francés Alain Colmerauer
Fue desarrollado en 1970 en la Universidad de Marseilles
En el curso usaremos Strawberry PROLOG Versión 2.3
La interfaz
Ejemplo 1:
le_gusta(elena,tenis).
le_gusta(jony,football).
le_gusta(tomas,baseball).
le_gusta(erik,natacion).
le_gusta(marco,tenis).
le_gusta(_,tenis).
le_gusta(juan,X) :- le_gusta(tomas,X).
?-le_gusta(juan,tenis).
Las clausulas contienen hechos y reglas
Un hecho es: le_gusta(elena,tenis)
que corresponde a: "a elena le gusta el tenis"
Una regla es: le_gusta(juan,X):-le_gusta(tomas,X).
que corresponde a la regla lógica:
a tomas le gusta X => a juan le gusta X
o equivalentemente:
a juan le gusta X si a tomas le gusta X
Dos Corridas:
?-le_gusta(juan,baseball)
Yes.
?-le_gusta(jony,tenis)
Yes
Variables:
En la regla:
le_gusta(juan,X) :- le_gusta(tomas,X).
aparece la variable X
La variables deben comenzar con letra mayúscula.
Uso del fail
Cuando PROLOG tiene una meta internaencuentra solamente una solución para cadasubmeta y continua con la próxima submeta,por lo que encuentra solamente una solución.
Cuando PROLOG tiene una submeta a laderecha de una regla también encuentrasolamente una solución.
El uso del fail forzará el backtraking(reevaluación) en ambas situaciones con loque sí se encontrarán todas las soluciones.
EJEMPLO: Versión sin fail
padre(leonardo,katherine).
padre(carlos,jason).
padre(carlos,marilyn).
todos :-
padre(X,Y),
write(X),
write(" es el padre de "),
write(Y),nl.
?-todos.
Salida:
leonardo es el padre de katherine
Yes.
EJEMPLO: Versión con fail
padre(leonardo,katherine).
padre(carlos,jason).
padre(carlos,marilyn).
todos :-
padre(X,Y),
write(X),
write(" es el padre de "),
write(Y),nl,fail.
?-todos.
Salida:
leonardo es el padre de katherine
carlos es el padre de jason
carlos es el padre de marilyn
No.
Ejemplo de unificación de variables:
?-le_gusta(Persona,tenis),write(Persona).
Salida:
elena Yes
?-le_gusta(Persona,tenis),write(Persona),
write(" "), fail.
Salida:
elena marco _0 juan No.
Objetos y Relaciones
Toda clausula en PROLOG está conformada por relaciones que afectan a objetos.
Los nombres de las relaciones y de los objetos deben estar escritos en minúscula.
Ejemplo 2: Metas (Goals)
compuestascarro(toyota,130000,3,rojo,12000).
carro(ford,90000,4,gris,25000).carro(nissan,8000,1,rojo,30000).
?-carro(M,K,E,C,P), P < 24000, write(M), write(" "),write(K), write(" "),write(E), write(" "),write(C), write(" "),write(P), write(" ").
Salida:
toyota 130000 3 rojo 12000 Yes.
Observación:
la , es el AND
el ; es el OR
P<25000 invoca en realidad <(P,25000)
Variables AnónimasPara variables anónimas se utiliza "_", por ejemplo:
?-carro(_,_,Edad,_,Costo), Costo < 27000,write(Edad), write(" "),write(Costo), write(" "), fail.
Salida: 3 12000 4 25000 No.
Las variables anónimas pueden ser usadas en hechos, por ejemplo:
le_gusta(_,tenis).
se lee "a toda persona le gusta el tenis”
El mecanismo"Backtraking"
(reevaluación)
Ejemplo 3:
alumno(peter,9).alumno(paul,10).alumno(ana,9).alumno(susan,9).
?-alumno(P1,9), alumno(P2,9), not(P1=P2),write(P1), write(" "), write(P2),nl,fail.
Este programa responde:
peter ana
peter susan
ana peter
ana susan
susan peter
susan ana
No.
El mecanismo"Backtraking" funciona como sigue:
Ejemplo 4: Uso del Not
Queremos escribir un programa que le busque novio a Sofía. El programa contiene una "base de datos" con la lista de solteros y sus características, además contiene una regla para los requisitos pedidos por Sofía, a saber, el novio debe ser vegetariano y no fumador.
hombre(jose).
hombre(bill).
hombre(tom).
fumador(jorge).
fumador(tom).
vegetariano(jose).
vegetariano(tom).
sofia_hace_pareja(X) :- hombre(X), not(fumador(X)), vegetariano(X).
?-sofia_hace_pareja(X),
write("una posible pareja para Sofia es: "), write(X), nl.
La salida al ejecutar este programa es:
una posible pareja para Sofia es: joseNo.
hombre(jose).
hombre(bill).
hombre(tom).
fumador(jorge).
fumador(tom).
vegetariano(jose).
vegetariano(tom).
sofia_hace_pareja(X) :- hombre(X), not(fumador(X)), vegetariano(X).
?-sofia_hace_pareja(X),
write("una posible pareja para Sofia es: "), write(X), nl, fail.
La salida al ejecutar este programa es:
una posible pareja para Sofia es: joseNo.
hombre(jose).hombre(bill).hombre(tom).fumador(jorge).fumador(tom).vegetariano(jose).vegetariano(tom).sofia_hace_pareja(X) :- hombre(X), not(fumador(X)),
vegetariano(X).
?-sofia_hace_pareja(X),write("una posible pareja para Sofia es: "), write(X), nl, fail.
La salida al ejecutar este programa es:
una posible pareja para Sofia es: joseYes.
Ejemplo 5: un árbol genealógico
masculino(alan).masculino(carlos).masculino(luis).masculino(ivan).
femenino(ana).femenino(andrea).femenino(eugenia).femenino(damaris).
madre(eugenia,ana).madre(alan,damaris).
padre(alan,luis).padre(ana,carlos).padre(andrea,luis).padre(eugenia,alan).
padres(X,Y) :- madre(X,Y).padres(X,Y) :- padre(X,Y).
hermano(X,Y) :- /* El hermano of X es Y si */
masculino(Y) , /* Y es masculino y */
padres(X,P) , /* los padres de X son P y */
padres(Y,P) , /* los padres de Y son P y */
not(X=Y). /* X y Y no son el mismo */
hermana(X,Y) :- /* La hermana de X es Y si */
femenino(Y) , /* Y es femenino y */
padres(X,P) , /* los padres de X son P y */
padres(Y,P) , /* los padres de Y son P y */
not(X=Y). /* X y Y no son el mismo */
tio(X,U) :- /* El tio de X es U si */
madre(X,P) , /* la madre de X es P y */
hermano(P,U). /* el hermano de P es U. */
tio(X,U) :- /* el tio de X es U si */padre(X,P) , /* el padre de X es P y */hermano(P,U). /* el hermano of P es U */
abuelo(X,G) :- /* El abuelo de X es G si */padre(P,G) , /* si el padre de P es G */madre(X,P). /* y la madre de X es P. */
abuelo(X,G) :- /* El abuelo of X es G si */padre(X,P) , /* el padre de X es P */padre(P,G). /* el padre de P es G */
?-hermana(alan,X), write(X).
La Salida es:
andrea Yes.
Simulación de compuertas lógicas en
PROLOG
Escriba en PROLOG un programa para simular (producir) la tabla de verdad del XOR usando OR, AND, NOT:
cnot(1,0). cnot(0,1).cand(0,0,0). cand(0,1,0). cand(1,0,0). cand(1,1,1).cor(0,0,0). cor(0,1,1). cor(1,0,1). cor(1,1,1).
cxor(X,Y,Z) :-cnot(X,N1), cnot(Y,N2),cand(X,N2,N3), cand(Y,N1,N4),cor(N3,N4,Z).
?-cxor(I1,I2,S),write(I1), write(" "),write(I2), write(" "),write(S), write(" "), nl, fail.
Una corrida puede ser:
?-cxor(I1,I2,S)
1 1 0
1 0 1
0 1 1
0 0 0
No.
Variables Libres y Acotadas
Se dice que una variable es LIBRE si
PROLOG no conoce su valor.
Se dice que una variable es ACOTADA
si PROLOG conoce su valor.
Ejemplo:
le_gusta(elena,lectura).le_gusta(john,computadoras).le_gusta(john,ciclismo).le_gusta(leonardo,ciclismo).le_gusta(eric,natacion).le_gusta(eric,lectura).
?-le_gusta(X,lectura),le_gusta(X,natacion).
Por ejemplo, en la meta:
?-le_gusta(X,lectura), le_gusta(X,natacion).
en la submeta le_gusta(X,lectura) la variable X ocurre libre, mientras que en la submeta le_gusta(X,natacion) la variable X ocurre acotada. Pues cuando el mecanismo de backtraking inicia instancia la variable X con elena.
Objetos Compuestos
Un Objeto Compuesto consiste de un functory los sub-objetos que lo conforman, esto es:
functor(obj1,obj2,. . .,objn)
Un objeto compuesto puede se vacio:
functor() ó functor
Ejemplo: estudiante es un objeto compuesto
lee_estudiante(e(Nombre,Nota1,Nota2,Promedio,Resultado)):- write("Cual es su nombre? "), read(Nombre),
write("Nota en examen 1? "), read(Nota1),write("Nota en examen 2? "), read(Nota2),Promedio = (Nota1 + Nota2)/2,paso(Promedio,Resultado).
paso(Promedio,Resultado) :- Promedio >= 70,Resultado = 'S';Promedio < 70, Promedio >= 60,Resultado = 'A';Promedio < 60,Resultado = 'P'.
run:- lee_estudiante(E),nl,write(E),nl,nl,
write("Desea continuar(s/n)"),read(Ch), =(Ch,'n').
run:-nl,nl,write("Digite los datos de otro estudiante"),nl,nl,run.
?-run.
/* VER CORRIDA EJ8.SPJ */
Recursividad en PROLOG
Ejemplo 1:
u(1,2).
u(N,Res) :- N > 1,
N1 is N - 1, /* OJO dejar espacio después del - */
u(N1,Res1),
Res is (2 * Res1).
?-u(4,X), write(X).
Salida:
16Yes..
Ejemplo 2:
fibonacci(1,1).
fibonacci(2,1).
fibonacci(N,F) :-
N > 2,
M is N - 1,
K is N - 2,
fibonacci(M,G),
fibonacci(K,H),
F is G + H.
?-fibonacci(6,Res), write(Res).
Listas en PROLOG
Las Listas en PROLOG se manejan a
través de Recursión.
Las listas se encierran entre los
operadores [ ] y se separan por comas.
Ejemplos
[1, 2, 8]
[perro, gato, canario]
["Luisa", "Juan"]
PROLOG divide una lista en dos
partes:Head o cabeza (primer elemento de la lista)
Tail o resto (una lista menos la cabeza)
Ejemplos:
Lista Head Tail
[1,2,3] 1 [2,3]
[[1,2,3],[7,8],[]] [1,2,3] [[7,8],[]]
[] indefinido indefinido
[ | ] [] []
NOTA: PROLOG usa | como separador entre el Head y el Tail
Más ejemplos:
Lista 1 Lista 2 Instanciación
[1,2,3,4,7,8] [X|Y] X=1, Y=[2,3,4,7,8]
[7] [X|Y] X=7, Y=[]
[12,3,9,0] [X,Y|Z] X=12, Y=3, Z=[9,0]
[1,2] [3|X] falla
[caballo|Q] [P|blanco] P=caballo, Q=blanco
Ejemplos de programas con listas
Imprimir una lista
imprime_lista([]).
imprime_lista([H|T]) :- write(H), write(" "), imprime_lista(T).
?-imprime_lista([5,2,8,9,22]).
Pertenece a una lista
miembro(Nombre,[Nombre|_]).
miembro(Nombre,[_|Tail]):-miembro(Nombre,Tail).
?-miembro(2,[5,6,2,7,89,0]).
Lectura de una Lista
leerlista([X|Xr]):-read(X),leerlista(Xr).
leerlista([]).
?-leerlista(X),write(X).
Un ejemplo completo
append([],Lista,Lista).append([X|L1], L2, [X|L3]) :- append(L1,L2,L3).
pares(X,[X|_]) :- Z is X mod 2, Z is 0.pares(X,[_|Cola]) :- pares(X,Cola).
ultimo(X,[X]).ultimo(X,[_|Cola]) :- ultimo(X,Cola).
consecutivos(X,Y,[X,Y|_]).consecutivos(X,Y,[_|Cola]) :- consecutivos(X,Y,Cola).
invierte([],[]).invierte([H|T],L) :- invierte(T,Z), append(Z,[H],L).
burbuja(L,O) :- append(X,[A,B|Y],L),B < A,append(X,[B,A|Y],M),burbuja(M,O), !.
burbuja(L,L).
imprime([]).imprime([Head|Tail]) :- write(Head),nl,imprime(Tail).
leerlista([X|Xr]):- read(X),leerlista(Xr).leerlista([]).
CORRIDAS: (ver ej14.spj)
%?-leerlista(X),imprime(X).
%?-append([4,5,2,3],[5,62,23,3,0],L),write(L).
%?-pares(X,[3,4,6,9,7]),write(X).
%?-ultimo(X,[3,4,6,9,7]),write(X).
%?-consecutivos(6,9,[3,4,6,9,7]).
%?-invierte([3,4,6,9,7],X),write(X).
?-burbuja([3,4,6,9,7],X),write(X).
suma_lista([],0).
suma_lista([CABEZA|COLA], RESULT) :-
suma_lista(COLA,R1),
RESULT is CABEZA + R1.
multiplica_lista([],1).
multiplica_lista([CABEZA|COLA], RESULT) :-
multiplica_lista(COLA,R1),
RESULT is CABEZA * R1.
Más Ejemplos
suma_dos_listas([],[],[]).
suma_dos_listas([CABEZA1|COLA1], [CABEZA2|COLA2], [CABEZA3|COLA3]) :-
CABEZA3 is CABEZA1 + CABEZA2,
suma_dos_listas(COLA1, COLA2, COLA3).
producto_dos_listas([],[],[]).
producto_dos_listas([CABEZA1|COLA1], [CABEZA2|COLA2], [CABEZA3|COLA3]) :-
CABEZA3 is CABEZA1 * CABEZA2,
producto_dos_listas(COLA1, COLA2, COLA3).
Más Ejemplos
Uso del cut !
El cut ! tiene como objetivo prevenir el
backtraking no deseado, y sigue las
siguientes reglas:
Es imposible que backtraking sobrepase el
cut !.
Se usa cuando solo interesa un número
determinado de soluciones o cuando la
lógica del problema lo amerita.
Ejemplo:
pertenece[X,[X|_].
pertenece(X,[_|Y] :- pertenece(X,Y).
Goal: pertenece(X,[4,-2,1])
X=4,
X=-2,
X=1
3 solutions
Esto implica que cuando se evalua la siguiente meta
Goal: pertenece(4,[4,-2,1,4])
true
evalua 4 veces en forma innecesaria. Para evitar este backtraking innecesario se usa el cut !, como sigue:
pertenece[X,[X|_] :- !.
pertenece(X,[_|Y] :- pertenece(X,Y).
Ejemplos de sumatorias
sumar(1,1) .
sumar(N,Res) :- N1 is N - 1,
sumar(N1,R1),
Res is R1 + N.
armonica(1,1) .
armonica(N,Res) :- N1 is N - 1,
armonica(N1,R1),
Res is R1+1/N.
%?-sumar(20,X),write(X).
?-armonica(20,X),write(X).
Listas y Objetos Compuestos
imprime_estudiante(e(NOMBRE,NOTA1,NOTA2,PROMEDIO,RESULTADO))
:- write(" Nombre: "), write(NOMBRE), nl,
write(" Examen 1: "), write(NOTA1), nl,
write(" Examen 2: "), write(NOTA2), nl,
write(" Promedio: "), write(PROMEDIO), nl,
write(" Resultado: "), write(RESULTADO), nl.
datos_estudiante(e(NOMBRE, NOTA1, NOTA2, PROMEDIO, RESULTADO)):-
write("Nombre del Estudiante"),nl,
read(NOMBRE),nl,
write("Nota Del Examen #1"),nl,
read(NOTA1),nl,
write("Nota Del Examen #2"),nl,
read(NOTA2),nl,
PROMEDIO is (NOTA1 + NOTA2)/2,
resultado(PROMEDIO, RESULTADO).
Listas y Objetos Compuestos
resultado(P,R) :- P >= 70, R = 'S'.
resultado(P,R) :- P >= 60, P < 70, R = 'A'.
resultado(P,R) :- P < 60, R = 'P'.
imprime_lista([]).
imprime_lista([CABEZA|COLA]) :-
nl, nl,
imprime_estudiante(CABEZA),
write(" "),
imprime_lista(COLA).
lee_lista([CABEZA|COLA]) :-
datos_estudiante(CABEZA),
lee_lista(COLA).
lee_lista([]).
Listas y Objetos Compuestos
eliminacomp(N,[],[]).
eliminacomp(N,[e(NOMBRE,NOTA1,NOTA2,PROMEDIO,RESULTADO)|Yr],Yr):-=(N,NOMBRE).
eliminacomp(N,[Y|Yr],[Y|L]):- elimina(N,Yr,L).
invoca_datos_estudiante :-
lee_lista(L1),
write("RESULTADO:"),
imprime_lista(L1), nl,
write(" Nombre a borrar: "), read(N), nl,
eliminacomp(N,L1,L2),
imprime_lista(L2).
?-invoca_datos_estudiante.
El algoritmo de unificación usado por
PROLOG
Una variable libre puede ser unificada concualquier término, luego la variable seconsidera acotada.
Una constante puede ser unificada con simisma o con una variable libre.
Un objeto compuesto puede ser unificadocon un objeto compuesto, donde ambostengan los mismos functores y el mismonúmero de argumentos, de modo que lostérminos son unificados dos a dos.
GRACIAS….
top related