viernes, 12 de octubre de 2012

PROLOG


hombre ('Antonio').
hombre ('Pedro').
hombre ('Juan').
hombre ('Alejandro').
mujer ('María').
mujer ('Lissethe').
mujer ('Carmen').
mujer ('Julia').

Consultar:
?-hombre (X).
?-mujer (Y).

Verificar si 5+5 es 10
?- 10 is 5+5.
El predicado consult sirve para "consultar" o cargar ficheros conteniendo código fuente en el intérprete.
?-consult(practica3_chunga).
?-consult(’c:/hlocal/practica3_suspensa’).
?-consult(’c:/hlocal/practica3_suspensa.pl’).
?- [practica3_chunga].
?- [’practica3_chunga’].
?- [’practica3_chunga.pl’].
?- [’c:/hlocal/practica3_chunga.pl’].













Para consultar en que directorio estamos:
?-pwd.
?- cd(’..’). %recorrer
?- ls.
?- cd('../santos'). %establecerá c:\..\santos como nuevo directorio de trabajo
?-cd('c:/.../prueba').
Para crear y editar un archivo.pl
?-crea(patos,marisol,sistemasB,a32).
?- edit(hola).
Editor clónico de emacs que viene incluido en el SWI Prolog.
?- emacs.%invoca el editor
?-emacs('mi_fichero.pl'). edita el fichero con emacs

Cierro la sesión en el intérprete
?- halt.


INPUT & OUTPUT
?-write(hola_mundo).
?-write(dame_tu_nombre:),
read(NOMBRE),
write(gusto_en_conocerle),nl,
write(NOMBRE).
?-read(Piedra).


OPERADORES
?- 5>5.

PREDICADOS
Se utilizan para expresar propiedades de los objetos. En Prolog los llamaremos hechos.
simbolo_de_predicado(arg1,arg2,...,argn).
CONECTORES LÓGICOS
La conjunción, “y”, en prolog ”,” ejm. X,Y.
La disyunción, “o”, en prolog “;”colocado entre los objetivos  ejm. X;Y.
La negación lógica no puede ser representada explícitamente en Prolog. La representamos con el predicado predefinido not o con \+: not(X), \+ X. “no”, tendrá éxito si el objetivo X fracasa.
La implicación o condicional, sirve para significar que un hecho depende de un grupo de otros hechos: “si ... entonces ...”. prolog :cabeza_de_la_regla :- cuerpo_de_la_regla.
/* Conjunción de predicados */
le_gusta_a(clara,jorge),le_gusta_a(clara,chocolate).
/* Disyunción de predicados */
le_gusta_a(clara,jorge); le_gusta_a(jorge,clara).
/* Negación de predicados */
not(le_gusta_a(clara,jorge)).
/* o también como */
\+ le_gusta_a(clara,jorge).
/* Condicional: REGLAS */
/* novios(Per1,Per2) <- Per1 y Per2 son novios */
novios(X,Y) :- le_gusta_a(X,Y),


Predicado: Relación, función u operador que regresa falso o verdadero.

HECHOS: Relación y esto se asume como un  hecho, y un predicado es un conjunto de hechos o reglas que tienen un mismo nombre y la misma cantidad de objetos relacionados,
legusta(pepe,pesca).
legusta(maria,bailar).
legusta(ana,pesca).
legusta(pepe,musica).
legusta(maria,musica).
legusta(ana,bailar).
Se pueden realizar las siguientes preguntas sobre la base de información:
- ¿Le gusta la música a Pepe y a Maria? :        
?-legusta(pepe,musica),legusta(maria,musica).
 - ¿Le gusta bailar a Pepe o a Maria le gusta la música?:          
?-legusta(pepe,musica);legusta(maria,musica).
 - ¿Le gusta bailar a Pepe y a Maria no le gusta la música?:     
?-legusta(pepe,musica),not(legusta(maria,musica)).
ACLARACION
Al tener por ejemplo dentro de nuestra base del conocimiento, los siguientes hechos:
sucesor(1,2).
sucesor(2,3).
sucesor(3,4).
sucesor(4,5).
sucesor(5,6).
sucesor(6,7).

Podemos realizar consultas como las siguientes:
sucesor(X,6).
sucesor(2,Y).
sucesor(X,Y).

REGLA: Una regla es una sola conclusión seguida por el signo :-  el cual hace la vez de SI condicional, seguida por una o mas relaciones de condición.
%%
%% declaraciones
%%
padrede(juan, maria). % juan es padre de maria
padrede(pablo, juan). % pablo es padre de juan
padrede(pablo, marcela).
padrede(carlos, debora).

% A es hijo de B si B es padre de A
hijode(A,B) :- padrede(B,A).
% A es abuelo de B si A es padre de C y C es padre B
abuelode(A,B) :- padrede(A,C), padrede(C,B).
% A y B son hermanos si el padre de A es también el padre de B y si A y B no son lo mismo
hermanode(A,B) :- padrede(C,A) , padrede(C,B), A \== B.       
 % A y B son familiares si A es padre de B o A es hijo de B o A es hermano de B
familiarde(A,B) :- padrede(A,B).
familiarde(A,B) :- hijode(A,B).
familiarde(A,B) :- hermanode(A,B).

EJEMPLOS
sum(X,Y,R) :- number(X),     number(Y), R is X+Y.
sum(X,X,R) :-     atom(X),     concat('2',X,R).
sum(X,Y,R) :-     concat(X,'+',Z),   concat(Z,Y,R).
CONSULTAS
?- sum(x,1,R). R = 'x+1' ?- sum(2,3,R). R = 5; R = '2+3' ?- sum(1,0.5,R). R = 1.5;
R = '1+0.5' ?- sum(x,x,R). R = '2x'; R = 'x+x' ?- sum(x,y,R). R = 'x+y'
EJMPLO:Querer
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).

Cláusula de Horn
La sintaxis de una cláusula de Horn en PROLOG tiene el siguiente aspecto:
hija (A, B) :- mujer (A), padre (B, A).
que podría leerse así: "A es hija de B si A es mujer y B es padre de A".



EJEMPLOS 1
Ejercicio 1: En este ejercicio y los siguientes vamos a realizar un ejemplo que describe la carta de un restaurante. Los objetos que interesan son los platos que se pueden consumir y una primera clasificación puede ser la siguiente:
·         Entradas: paella, gazpacho, consomé
·         Carne: filete de cerdo, pollo asado
·         Pescado: trucha, bacalao
·         Postre: flan, nueces con miel, naranja
Escribe como programa Prolog la clasificación de comidas   del restaurante. El programa constara de 10 cláusulas y los  predicados a usar son entrada/1, carne/1, pescado/1 y postre/1.            Prueba después el programa con preguntas como :                         
?- carne(X).                                                        
?- carne(X), postre(X).
entrada(mortadela).
entrada(ensalada).
entrada(atum).
carne(chuleta).
carne(pollo_asado).
carne(filete_de_cerdo).
pescado(trucha).
pescado(bacalao).
pescado(pejerrey).
postre(flan).
postre(nueces_con_miel).
postre(naranja). 
Ejercicio 2: Definir la relación "plato_principal(X)" que  indicara que un plato principal es un plato de carne o de  pescado.   
plato_principal(X):-    carne(X).
plato_principal(X):-    pescado(X).          
Ejercicio 3: Definir la relación "comida(X,Y,Z)" que indicara  que la comida consta de tres platos, una entrada "X", un plato  principal "Y" y un postre "Z".  Pidiéndole respuestas sucesivas a la pregunta ?- comida(X,Y,Z). podemos generar todas las posibles comidas del restaurante.      
comida(X, Y, Z):-      entrada(X), plato_principal(Y), postre(Z).    
EJEMPLOS 2
Ejercicio 4:Considera el siguiente programa que describe algunas relaciones familiares
padre(andres,bernardo).
padre(andres,belen).
padre(andres,baltasar).
padre(baltasar,david).
padre(david,emilio).
padre(emilio,francisco).
madre(ana,bernardo).
madre(ana,belen).
madre(ana,baltasar).
madre(belen,carlos).
madre(belen,carmen).
Extender el programa para definir las siguientes relaciones familiares
abuelo/2
progenitor/2
nieta/2
antepasado/2
descendiente/2
=====================================
abuelo(X, Y):-            padre(X, Z),    padre(Z, Y).
abuelo(X, Y):-            padre(X, Z),    madre(Z, Y).
progenitor(X, Y):-      padre(X, Y).
progenitor(X, Y):- madre(X, Y).
mujer(belen).
mujer(ana).
mujer(carmen).
nieta(X, Y):-   mujer(X), progenitor(Y, Z),   progenitor(Z, X).
antepasado(X, Y):-     progenitor(X, Y).
antepasado(X, Y):-     progenitor(X, Z),  antepasado(Z, Y).
descendiente(X, Y):- antepasado(Y, X).
Factorial de un número
function factorialRecursiva (n: integer): integer;
BEGIN
if n=0 then //o n<2
factorialRecursiva := 1
else (* para N>0*)
factorialRecursiva : = n * factorialRecursiva (n-1)
END;
% La sintaxis es factorial(N, F) -> Factorial de N es F (el resultado se guarda en F)
factorial(0, 1) :- !.%corte if-then-else-entonces
factorial(N, F) :- N>0, N1 is N - 1, factorial(N1, F1), F is N*F1.
 %el factorial se llama recursivamente dejando el resultado en F
?- factorial(5,F).
Fibonacci
% Author:
fibonacci(0,1).
fibonacci(1,1).
fibonacci(N,F) :-   N > 1, N1 is N-1, N2 is N-2,
fibonacci(N1,F1), fibonacci(N2,F2), F is F1+F2.
% Imprime el resultado y sale del programa.
imprimir(N) :-write('El numero '),write(N),
write(' de la serie de Fibonacci es: '), fibonacci(N,X),
write(X), nl, fail.%fracaso
LISTAS
La lista es una estructura de datos muy común en la programación no numérica.  Es una secuencia ordenada de elementos que puede tener cualquier longitud.  Ordenada significa que el orden de cada elemento es significativo.  Un elemento puede ser cualquier término e incluso otra lista.  Se representa como una serie de elementos separados por comas y encerrados entre corchetes.

Para procesar una lista, la dividimos en dos partes: la cabeza y la cola.  Por ejemplo:
Lista                Cabeza          Cola
[a,b,c,d]            a                [b,c,d]
[a]                                 a                [] (lista vacía)
[]                      no tiene       no tiene
[[a,b],c]           [a,b]             [c]
[a,[b,c]]             a                 [[b,c]]
[a,b,[c,d]]          a                 [b,[c,d]]
Para dividir una lista, utilizamos el símbolo "|".  Una expresión con la forma [X | Y] instanciará X a la cabeza de una lista e Y a la cola.  Por ejemplo:
Creación y consulta de listas
plantas([prolog, java , php, ruby, python, rebol, asp,c,net]).
lista([1,2,3,4,5,6,7,8,9,10]).
?-lista([Cabeza|Cola]).
   Cabeza=1
   Cola=[2,3]
?-lista([H,J|T]).
   H=1
   J=2
   T=[3]
Longitud de una lista
% La longitud de una lista vacia es 0.
% La longitud de cualquier lista es la longitud de la cola + 1.
longitud([],0).
longitud([H|T],N):-longitud(T,N0), N is N0 + 1.
?- longitud([a,b,c],L).
   3
?- longitud([a,b,c],4).
   No
Búsqueda de un elemento
% Si queremos determinar si un elemento pertenece a una lista.
% El elemento pertenece a la lista si coincide con la cabeza de la lista.
% El elemento pertenece a la lista si se encuentra en la cola de la lista.
 pertenece(X,[X|_]) :- !.
pertenece(X,[_|R]):- pertenece(X,R).
 ?- pertenece(b,[a,b,c]).
   Yes
?- pertenece(b,[a,[b,c]]).
   No
?- pertenece([b,c],[a,[b,c]]).
   Yes
Concatenar listas
% Si queremos concatenar dos listas lista.
% Concatenar una lista vacia con L es L.
% Concatenar X|L1 con L2 es poner el primer
% elemento de la primera lista (X) más la
% concatenación del resto de la lista (L1) con L2
 concatenar([],L,L).
concatenar([X|L1],L2,[X|L3]):-concatenar(L1,L2,L3).
 ?- concatenar([1,2],[3,4],R).
R = [1, 2, 3, 4].
Eliminar elemento de una lista
% Si queremos eliminar un elemento de la lista.
% Si X es la cabeza de la lista, la cola T es la lista sin X
% Si X no es la cabeza de la lista, conservamos la cabeza de la lista
%     como parte de la respuesta y continuamos eliminando X de la cola T.
elimina(X,[X|T],T).
elimina(X,[H|T],[H|T1]):- elimina(X,T,T1).
 ?- elimina(1,[1,2,3,4],R).
   R = [2,3,4]
?- elimina(1,R,[2,3]).
   R = [1, 2, 3] 
   R = [2, 1, 3] 
   R = [2, 3, 1]
Palindromo
Interesante porque podemos usar operaciones sobre listas para
manipular y hacer consultas sobre strings, por ejemplo si
tenemos la regla:
palindrome(X) :- reverse(X,X).
podemos hacer las consultas
?- palindrome("hola").
No
?- palindrome("anicocina").
Yes
?- palindrome("maripositatisopiram").
Yes
Numeros
masuno(X,Y):- Y is X+1.
xmasuno(X,Y):- Y = X+1.?-masumo(5,Y).?-xmasumo(5,Y).
XPCE/Prolog
Se hace uso de la librería XPCE, la cual ha sido desarrollada para el desarrollo en GUI Prolog.

XPCE ha escrito una dinámica orientada a objetos del núcleo. Métodos se puede definir en cualquier idioma. XPCE predefine un gran número de clases.

CARGANDO LA LIBRERÍA PCE

Para poder usar predicados para trabajar con gráficos bajo Prolog deberemos cargar la librería PCE.
:- use_module(library(pce)).

Esta línea lo que hace es decirle a Prolog que cargue la librería una vez ha terminado de compilar, antes de que desde el prompt de Prolog se nos deje hacer ninguna consulta.

Una vez cargada esta librería, ya disponemos de una serie de predicados para poder crear ventanas, botones, y una gran variedad de objetos.

CREANDO OBJETOS PARA LUEGO INTERACTUAR

Con la librería PCE se trabaja con un esquema orientado a objetos, en  donde podremos crear clases y trabajar con diferentes objetos, pudiendo llamar a métodos de dichos objetos (pasándoles los correspondientes parámetros) o llamar a métodos que nos devuelvan algún valor, y obviamente si creamos objetos, también podremos destruirlos.

Existen 4 predicados con los que se puede trabajar con XPCE/Prolog. Estos predicados sirven para crear objetos, enviar mensajes a objetos, recibir mensajes de objetos y liberar la memoria de los objetos.

·         new(?Reference, +NewTerm): Este predicado recoge dos parámetros, el primero recogería la referencia que se le asigna al nuevo objeto, ya que new se usa para crear objetos. El segundo parámetro le indicaría el objeto que se quiere crear.
·         send(?Receiver, +Selector(...Args...)): El primer parámetro del predicado es una referencia al objeto al que deseemos enviarle un mensaje. El segundo parámetro indicará el método al que queremos invocar, lo cual indicaremos junto a los argumentos que queremos enviarle al método.
·         get(?Receiver, +Selector(+Argument...), -Result): Los dos primeros parámetros tienen el mismo significado que para send, sin embargo el último parámetro sirve para recoger el valor que nos devuelva el método que hallamos invocado.
·         free(?Reference): libera la memoria asociada al objeto que se le indica en el primer parámetro.

Las referencias se usan para saber a que objeto nos referimos, así pues cada objeto que creemos deberá tener su propia referencia, ya que después toda memoria que  reservemos con new, será conveniente liberarla con free.

Las variable de referencia deben crearse con el símbolo @ y el nombre de la VAR. Posteriormente se liberara con free.

MANOS A LA OBRA: Crear un dialogo que contenga un botón y que al pulsar sobre el mismo cierre esa ventana.
:- use_module(library(pce)).
ejemplo:-
/*
* Crea el objeto dialogo en la variable D
*/
new(D,dialog('Nombre del Dialogo')),
/*
* Crea el objeto boton almacenandolo en la variable @boton de tal forma
* que al pulsar sobre el boton libere la memoria y cierre la ventana)
*/
new(@boton, button('Cerrar Dialogo',
and(message(D, destroy),message(D, free),message(@boton, free)))),
/*
* Inserta el botón en el diálogo
*/
send(D, append(@boton)),
/*
* Le envia el mensaje open al dialogo para que cree y muestre la ventana.
*/
send(D, open).

Otro ejemplo
:- use_module(library(pce)).
ejemplo_mensajes :-
% Crea el objeto dialogo en la variable D
new(D, dialog('Nombre del Dialogo')),
% Crea un boton que llama al predicado mostrar_mensaje
new(B, button('Mostrar en Consola',
message(@prolog, mostrar_mensaje, 'Este es el valor que tendra la variable P'))),
% Crea un boton para cerrar el dialogo
new(@boton, button('Cerrar Dialogo',
and(
message(D, destroy),
message(D, free),
message(D, free),
message(@boton, free)))),
% Inserta los botones en el diálogo
send(D, append(@boton)),
send(D, append(B)),
% Muestre la ventana.
send(D, open).
% Muestra un mensaje en la consola.
mostrar_mensaje(P) :-
write('La variable P vale '), write(P), nl.

2 comentarios:

  1. hola soy nuevo, usando prolog. En el primer ejemplo lo compile y lo corrí y tiene un error pero no logro indentificar cual es : [PCE error: @pce/pce: Object @prolog already exists]
    false.

    ResponderEliminar