Professional Documents
Culture Documents
PROLOG
Equipo #6
N4 Jueves
25/05/2010
Breve Historia
Una de las preocupaciones ms tempranas de la computacin de los aos cincuenta
fue la posibilidad de hacer programas que llevaran a cabo demostraciones automticas
de teoremas. As empezaron los primeros trabajos de inteligencia artificial que ms de
veinte aos despus dieron lugar al primer lenguaje de programacin que contempla,
como parte del intrprete, los mecanismos de inferencia necesarios para la
demostracin automtica.
Este primer lenguaje est basado en el formalismo matemtico de la Lgica de Primer
Orden y ha dado inicio a un nuevo y activo campo de investigacin entre las
matemticas y la computacin que se ha denominado la Programacin Lgica.
Estos mecanismos de prueba fueron trabajados con mucho entusiasmo durante una
poca, pero, por su ineficiencia, fueron relegados hasta el nacimiento de PROLOG,
ocurrido en 1970 en la Universidad de Marsella, Francia, en el seno de un grupo de
investigacin en el campo de la Inteligencia Artificial.
La Programacin Lgica tiene sus orgenes ms cercanos en los trabajos de prueba
automtica de teoremas de los aos sesenta. J. A. Robinson propone en 1965 una
regla de inferencia a la que llama resolucin, mediante la cual la demostracin de un
teorema puede ser llevada a cabo de manera automtica.
La resolucin es una regla que se aplica sobre cierto tipo de frmulas del Clculo de
Predicados de Primer Orden, llamadas clusulas y la demostracin de teoremas bajo
esta regla de inferencia se lleva a cabo por reduccin al absurdo.
La programacin lgica tiene sus races en el clculo de predicados, que es una teora
matemtica que permite, entre otras cosas, lograr que un computador pueda realizar
inferencias, capacidad que es requisito para que un computador sea una "mquina
inteligente".
La realizacin del paradigma de la programacin lgica es el lenguaje Prolog. El Prolog
estuvo un tiempo diseado para ejecutarse en minicomputadoras o estaciones de
trabajo, actualmente hay versiones en Prolog que pueden instalarse en computadores
personales como IBM-PC y PC-Compatibles.
Un programa escrito en PROLOG puro, es un conjunto de clausulas. Sin embargo,
PROLOG, como lenguaje de programacin moderno, incorpora mas cosas, como
instrucciones de Entrada/Salida, etc. Una clausula puede ser una conjuncin de hechos
positivos o una implicacin con un nico consecuente (un nico termino a la derecha).
La negacin no tiene representacin en PROLOG, y se asocia con la falta de una
afirmacin (negacin por fallo), segn el modelo de suposicin de un mundo cerrado
solo es cierto lo que aparece en la base de conocimiento o bien se deriva de esta.
FUNCIONAMIENTO
INSTALACION DE PROLOG EN PLATAFORMA DE WINDOWS
1.- Busque en la pgina ftp://ftp.amzi.com/misc/amzi_7-4-12_win.exe el
instalador que incluye JAVA+ECLIPSE+AMZI_PROLOG.*
*Nota: Esta es una versin de PROLOG de varias existentes
2.- Ejecute el archive amzi_7-4-12_win.exe
INSTRUCCIONES EN PROLOG
1. Hechos
Expresan relaciones entre objetos. Supongamos que queremos expresar el hecho
de que "un coche tiene ruedas". Este hecho, consta de dos objetos, "coche" y
"ruedas", y de una relacin llamada "tiene". La forma de representarlo en PROLOG
es:
tiene(coche,ruedas).
* Los nombres de objetos y relaciones deben comenzar con una letra
minscula.
* Primero se escribe la relacin, y luego los objetos separados por
Cabe sealar que la regla esta "al revs". Esto es as por el mecanismo
de deduccin hacia atrs que emplea PROLOG. Si cometiramos el *error* de
representarla como:
tiempo(lluvioso) :- suelo(mojado).
suelo(mojado).
PROLOG, partiendo del hecho de que el suelo esta mojado, deducira
incorrectamente que el tiempo es lluvioso.
Para generalizar una relacin entre objetos mediante una regla, utilizaremos
variables. Por ejemplo:
Representacin lgica | Representacin PROLOG
Es un coche(X) ----> | tiene(X,ruedas) :
tiene(X,ruedas) | es un coche(X).
Con esta regla generalizamos el hecho de que cualquier objeto que sea un coche,
tendr ruedas. Al igual que antes, el hecho de que un objeto tenga ruedas, no es
una condicin suficiente de que sea un coche. Por lo tanto la representacin
inversa sera incorrecta.
4. El mbito de las variables.
Cuando en una regla aparece una variable, el mbito de esa variable es
nicamente esa regla. Supongamos las siguientes reglas:
(1) hermana_de(X,Y) :- hembra(X), padres(X,M,P), padres(Y,M,P).
(2) puede_robar(X,P) :- ladron(X), le_gusta_a(X,P), valioso(P).
Aunque en ambas aparece la variable X (y la variable P), no tiene nada que ver la
X de la regla (1) con la de la regla (2), y por lo tanto, la instanciacin de la X en
(1) no implica la instanciacin en (2). Sin embargo todas las X de *una misma
regla* si que se instanciaran con el mismo valor.
5. Operadores
Son predicados predefinidos en PROLOG para las operaciones matemticas
bsicas. Su sintaxis depende de la posicin que ocupen, pudiendo ser infijos o
prefijos. Por ejemplo el operador suma ("+"), podemos encontrarlo en forma
prefija '+(2,5)' o bien infija, '2 + 5'.
Tambin dispone de predicados de igualdad y desigualdad.
X = Y igual
X \= Y distinto
X < Y menor
X > Y mayor
X =< Y menor o igual
X >= Y mayor o igual
6. La resolucin de objetivos
Un ejemplo sencillo.
Con los datos que conocemos, ya podemos construir un programa en PROLOG.
Necesitaremos un editor de textos para escribir los hechos y reglas que lo
componen. Un ejemplo sencillo de programa PROLOG es el siguiente:
quiere_a(maria,enrique).
quiere_a(juan,jorge).
quiere_a(maria,susana).
quiere_a(maria,ana).
quiere_a(susana,pablo).
quiere_a(ana,jorge).
varon(juan).
varon(pablo).
varon(jorge).
varon(enrique).
hembra(maria).
hembra(susana).
hembra(ana).
teme_a(susana,pablo).
teme_a(jorge,enrique).
teme_a(maria,pablo).
/* Esta linea es un comentario */
quiere_pero_teme_a(X,Y) :- quiere_a(X,Y), teme_a(X,Y).
querido_por(X,Y) :- quiere_a(Y,X).
puede_casarse_con(X,Y) :- quiere_a(X,Y), varon(X), hembra(Y).
puede_casarse_con(X,Y) :- quiere_a(X,Y), hembra(X), varon(Y).
Supongamos la pregunta:
?-puede_casarse_con(maria,X).
nueva bsqueda en la base de datos que tiene como resultado la coincidencia con
la regla:
(3) puede_casarse_con(maria,Y) :- quiere_a(maria,Y), hembra(maria), varon(Y).
Se repite todo el proceso anterior, buscando nuevas instanciaciones de la variable
Y que verifiquen el cuerpo de la regla. La primera coincidencia corresponde al
hecho
quiere_a(maria,enrique).
que provoca la instanciacin de la variable Y con el objeto 'enrique'. PROLOG tratar
de probar ahora el resto del cuerpo de la regla con las instanciaciones actuales:
hembra(mara), varn(enrique).
Un recorrido de la base de datos, da un resultado positivo en ambos hechos,
quedando probado en su totalidad el cuerpo de la regla (3) y por lo tanto su
cabeza, que no es ms que una de las soluciones al objetivo inicial.
X = enrique
PROLOG utiliza un mecanismo de bsqueda independiente de la base de datos.
Aunque pueda parecer algo ilgico, es una buena estrategia puesto que garantiza
el proceso de todas las posibilidades. Es til para el programador conocer dicho
mecanismo a la hora de depurar y optimizar los programas.
9. Entrada/Salida
PROLOG, al igual que la mayora de lenguajes de programacin modernos
incorpora predicados predefinidos para la entrada y salida de datos. Estos son
tratados como reglas que siempre se satisfacen.
* write.
Su sintaxis es:
write('Hello world').
Las comillas simples encierran constantes, mientras que todo lo que se encuentra
entre comillas dobles es tratado como una lista. Tambin podemos mostrar el
valor de una variable, siempre que este instanciada:
write(X).
* nl.
El predicado nl fuerza un retorno de carro en la salida. Por ejemplo:
write('linea 1'), nl, write('linea 2').
tiene como resultado:
linea 1
linea 2
* read.
Lee un valor del teclado. La lectura del comando read no finaliza hasta que se
introduce un punto ".". Su sintaxis es:
read(X).
Instancia la variable X con el valor ledo del teclado.
read(ejemplo).
Se evala como cierta siempre que lo tecleado coincida con la constante entre
parntesis (en este caso 'ejemplo').
Ejercicios y ejemplos
/*1-Determina si lo que recibe es una lista*/
lista([]):-!.
lista([X|Y]):-lista(Y).
/*------------------------------------------------------------------*/
/*2-Concatena dos listas*/
concatenar([],L,L).
concatenar([X|M],L,[X|Z]):-concatenar(M,L,Z).
/*------------------------------------------------------------------*/
/*3-Invierte la lista que recibe en el primer nivel*/
invertir([X],[X]).
invertir([X|M],Z):-invertir(M,S), concatenar(S,[X],Z).
/*------------------------------------------------------------------*/
/*4-Calcula la longitud de la lista*/
long([],0):-!.
long([X|Y],S):-long(Y,T),!, S is T + 1.
/*------------------------------------------------------------------*/
prefijo([],M):-!.
prefijo([X],[X|M]):-!.
prefijo([X|L],[X|M]):-prefijo(L,M).
prefijo([X|T],[L|M]):-lista(X),prefijo(X,L),prefijo(T,M).
/*------------------------------------------------------------------*/
/*16-Determina si la primer lista es sublista de la segunda*/
sublista([],L):-!.
sublista(L,[X|M]):-prefijo(L,[X|M]).
sublista(L,[X|M]):-lista(X), sublista(L,X).
sublista(L,[X|M]):-sublista(L,M).
/*------------------------------------------------------------------*/
/*17-Elimina todos los elementos de la lista 1 que est n en la 2*/
elim_l1_de_l2([],L,L):-!.
elim_l1_de_l2([X|M],L,S):-elimina_x(L,X,T),elim_l1_de_l2(M,T,S).
/*------------------------------------------------------------------*/
/*18-Elimina los elementos repetidos que est n en una lista*/
elim_repet([],[]):-!.
elim_repet([X|M],S):-not lista(X), elimina_x(M,X,T),elim_repet(T,Y),
concatenar([X],Y,S).
elim_repet([X|M],S):-lista(X), elim_l1_de_l2(X,M,T),elim_repet(X,Y),
elim_repet(T,J),concatenar([Y],J,S).
/*------------------------------------------------------------------*/
/*19-Arma una lista con todos los elementos que se encuentran antes */
/*de elemento x en la lista*/
hasta_x([X|M],X,[]):-!.
hasta_x([Y|M],X,[Y|S]):-hasta_x(M,X,S).
/*------------------------------------------------------------------*/
/*20-Arma una lista con todos los elementos que se encuentran despues*/
/*del elemento x*/
desde_x([Y|M],X,S):-X=\=Y,desde_x(M,X,S),!.
desde_x([X,Y|M],X,[Y|M]):-X=\=Y,!.
desde_x([Y|M],X,S):-desde_x(M,X,S),!.
/*------------------------------------------------------------------*/
/*21-Determina si una lista se encuentra en orden creciente o decreciente*/
creciente([X,Y|Z]):- X<Y,
creciente([Y|Z]).
creciente([X]).
decreciente([X,Y|Z]):- X>Y,
decreciente([Y|Z]).
decreciente([X]).
/*------------------------------------------------------------------*/
secuencia([],L,L):-!.
secuencia([X|Y],[X|L],[X|L]):-secuencia(Y,L,L).
cta_ocurr(L,[],0):-!.
cta_ocurr([X|Y],[X|M],N):-secuencia(Y,M,L1), cta_ocurr([X|Y],L1,T), N is T + 1.
cta_ocurr([X|Y],[R|M],N):-cta_ocurr([X|Y],M,N),!.
/*------------------------------------------------------------------*/
reversible([]):-!.
reversible(L):-invertir(L,R),lista_igual(L,R).
/*------------------------------------------------------------------*/
orden(L,[],0):-!.
orden([],L,0):-!.
orden([X],[X],1):-!.
orden([X|Y],[X|Z],S):-orden(Y,Z,T),!, S is T+1.
orden([X|Y],[R|Z],S):-orden(Y,Z,S).
/*------------------------------------------------------------------*/
/*25-Arma una lista con todas las posiciones del elemento X en la lista*/
list_posic(X,[],N,[]):-!.
list_posic(X,[X|M],N,L):-N1 is N + 1,list_posic(X,M,N1,G),P is N + 1,
concatenar([P],G,L).
list_posic(X,[Y|M],N,L):-N1 is N + 1,list_posic(X,M,N1,L).
concatenar([],L,L):-!.
concatenar([X|Y],L,[X|Z]):-concatenar(Y,L,Z).
/*------------------------------------------------------------------*/