Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Habitualmente, programar un
ordenador significa dar una sucesión de tareas que, al ejecutarlas paso a paso, permiten
resolver un problema concreto. Sin embargo, el proceso que se sigue en la programación
lógica es completamente distinto: un programa en un lenguaje de programación lógica está
formado por un conjunto de hechos, junto con un conjunto de condiciones que debe
verificar la solución... el ordenador, usando un motor de inferencia, debe "deducir" la
solución a partir de los hechos y las condiciones dadas.
Uno de los posibles usos de Prolog es como lenguaje de programación interactivo, lo que
quiere decir que el ordenador y el programador sostienen una especie de conversación
donde Prolog espera que se le introduzcan los hechos y reglas que definen el problema que
se quiere resolver y, a continuación, si se hacen las preguntas adecuadas, buscará las
respuestas y las presentará por pantalla.
Los nombres de las relaciones deben comenzar con una letra minúscula.
Los objetos se escriben separados por comas y encerrados entre paréntesis.
Al final del hecho debe ir un punto.
Las reglas
Las reglas funcionan como las fórmulas condicionales habituales en lógica. Reflejan que la
verdad de un hecho depende de la verdad de otro hecho o grupo de hechos. Consta de una
cabeza y un cuerpo, donde este último puede estar formado por varios hechos (también
llamados objetivos). Su sintaxis general es:
objetivo1∧⋯∧objetivon→cabeza
Los objetivos van separados por comas (que representan conjunciones) y al final debe ir un
punto. Por ejemplo:
Las variables
Los nombres de las variables deben comenzar con letra mayúscula o con el carácter (_).
Existe una variable especial, la variable anónima o blanca, que se utiliza de la misma
manera que las demás variables pero nunca toma ningún valor.
Nuestro objetivo es demostrar, a partir de esta base de conocimientos, que el animal es una
cebra.
Para representar una regla, debemos elegir previamente los símbolos para los átomos que
aparecen en la regla:
es_ungulado∧tiene_rayas_negras→es_cebra
Para representar los hechos basta elegir los símbolos de los átomos. Por ejemplo, el hecho
2 se representa en Prolog por:
tiene_rayas_negras.
:- set_prolog_flag(unknown,fail).
Una vez en Prolog, podemos cargar el fichero anterior e intentar ver si se puede deducir el
resultado que buscábamos. Una sesión interactiva que hiciera esto en SWI-Prolog podría
ser de la siguiente forma (el símbolo ?- es el prompt y lo que viene a continuación en su
misma línea lo introduce el usuario; la respuesta de Prolog se muestra en la linea, o líneas,
siguientes a la interacción del usuario):
?- [animales].
Yes
?- es_cebra.
Yes
En este árbol, cada estado es una pila de problemas por resolver. El estado inicial consta
de un único problema (es_cebra). A partir de este estado buscamos en la base de
conocimientos una regla cuya cabeza coincida con el primer problema de la pila (en nuestro
caso, esta búsqueda da como resultado la regla 1). Sustituimos el problema por el cuerpo de
la regla. dando lugar a la pila de problemas es_ungulado, tiene_rayas_negras. Para el
primer problema (es_ungulado) tenemos dos reglas cuyas cabezas coinciden (las reglas 2 y
3). Consideramos en primer lugar la regla 2, produciendo la pila de problemas rumia,
es_mamífero, tiene_rayas_negras, que no coincide con la cabeza de ninguna regla, por lo
que se produce un fallo y se considera la otra elección, la regla 3, que genera la pila de
problemas es_mamífero, tiene_pezuñas, tiene_rayas_negras. Cada uno de los problemas
restantes coincide con uno de los hechos (reglas sin cuerpo), por lo que obtenemos una
solución al problema inicial.
La siguiente figura muestra una representación del proceso que se sigue en la rama exitosa
del árbol anterior:
Ejemplos en Lógica de Primer Orden
Primer ejemplo
Para mostrar un ejemplo que contiene elementos de un lenguaje de primer orden vamos a
trabajar sobre la siguiente base de conocimientos:
Hechos:
Que, usando el predicado located_in, podemos representar con las siguientes clausulas:
located_in(atlanta,georgia). % Clause 1
located_in(houston,texas). % Clause 2
located_in(austin,texas). % Clause 3
located_in(toronto,ontario). % Clause 4
Reglas:
Vamos a ver cuál es el árbol de deducción que sigue Prolog para resolver la siguiente
clausula:
located_in(toronto,north_america).
Hechos:
∀X[divide(2,X)∧divide(3,X)→divide(6,X)]
y su representación Prolog es
divide(2,6). % Hecho 1
divide(2,4). % Hecho 2
divide(2,12). % Hecho 3
divide(3,6). % Hecho 4
divide(3,12). % Hecho 5
divide(6,X) :- divide(2,X), divide(3,X). % Regla 1
?- divide(6,X).
X = 6 ;
X = 12 ;
false.
La forma de interactuar con Prolog para obtener el resultado anterior es como sigue:
después de obtener la primera respuesta se pide la búsqueda de otra solución pulsando
punto y coma (;). Si en este proceso se obtiene como respuesta false significa que no hay
más respuestas.
Los números naturales se pueden representar mediante una constante 0 (que representa el
cero) y un símbolo de función unitaria s (que representa la función sucesora). De esta
forma, 0, s(0), s(s(0)),... representan los números naturales 0,1,2,...
0 + Y = Y
s(X) + Y = s(X+Y)
∀Y[suma(0,Y,Y)]
∀X,Y,Z[suma(X,Y,Z)→suma(s(X),Y,s(Z))]
y éstas en Prolog:
suma(0,Y,Y). % R1
suma(s(X),Y,s(Z)) :- suma(X,Y,Z). % R2
Vamos a ver cómo Prolog responde a diversas cuestiones a partir de esta defnición. La
primera cuestión es calcular la suma de s(0) y s(s(0)). La forma de plantear esta pregunta en
Prolog, y la respuesta obtenida, sería (suma.pl):
?- suma(s(0),s(s(0)),X).
X = s(s(s(0))).
Para evitar conflicto entre las variables se cambian de nombre, añadiendo el índice 0 a las
del objetivo inicial, y el nivel del nodo en el árbol para el resto de cláusulas del programa.
El nodo inicial sólo tiene un sucesor con la regla 2, porque es la cabeza de la única regla
con la que unifica; efectivamente el átomo suma(s(0),s(s(0)),X0) no es unificable con
suma(0,Y1,Y1) porque los primeros argumentos son átomos sin variables distintos y sí es
unificable con suma(s(X1),Y1,s(Z1)) mediante la sustitución {X1/0, Y1/s(s(0)),
X0/s(Z1)} que, aplicada a ambos átomos, da el átomo suma(s(0),s(s(0)),s(Z1)). Lo mismo
sucede con el segundo nodo. Finalmente, la respuesta se calcula componiendo las
sustituciones realizadas en la rama de éxito a las variables iniciales: X se sustituye
inicialmente por X0, en el primer paso se sustituye X0 por s(Z1) y en el segundo
se sustituye Z1 por s(s(0)) con lo que el valor por el que sustituye X es s(s(s(0))).
y plantear la pregunta:
?- suma(X,s(s(0)),s(s(s(0)))).
X = s(0) ;
false.
. Tampoco para este problema se necesita un nuevo programa, basta realizar la siguiente
consulta:
?- suma(X,Y,s(s(0))).
X = 0,
Y = s(s(0)) ;
X = s(0), Y = s(0) ;
X = s(s(0)),
Y = 0 ;
false.
SWI-Prolog's Home
GNU Prolog's Home
Prolog Programming in Depth , Michael A. Covington, Donald Nute, and André
Vellino. Second edition, Prentice-Hall, 1997.
Prolog programming for artificial intelligence , I. Bratko. Pearson, 2001
Prolog WikiBoook
Learn Prolog Now! , curso online.
Prolog Problems
Introducción a la programación lógica con Prolog. Publicaciones del Grupo de
Lógica Computacional. Universidad de Sevilla, 2006.
Ejercicios de programación declarativa con Prolog. Publicaciones del Grupo de
Lógica Computacional. Universidad de Sevilla, 2006.
Curso de Lógica Informática (Temas 13 y 14). Dpt. Ciencias de la Computación e
Inteligencia Artificial, Universidad de Sevilla, 2013-2014.