1.-prolog
TRANSCRIPT
Docente: Ing. María Nícida Malca Quispe 1
UNIVERSIDAD NACIONAL PEDRO RUIZ GALLO
FACULTAD DE CIENCIAS FÍSICAS Y MATEMÁTICAS
ESCUELA PROFESIONAL DE COMPUTACIÓN E INFORMÁTICA
INTELIGENCIA ARTIFICIAL
UNIDAD II: Introducción AL Lenguaje de programación
Lógica
3. FUNDAMENTOS DE PROLOG........................................................................................................................................ 2
3.1 PROGRAMACIÓN LÓGICA ........................................................................................................................................... 3
3.2 PROGRAMAS EN PROLOG ......................................................................................................................................... 3
3.3 COMENTARIOS .......................................................................................................................................................... 13
4. ENTORNO DE DESARROLLO PROLOG ...................................................................................................................... 13
5. FUNDAMENTOS DE VISUAL PROLOG ........................................................................................................................ 14
Docente: Ing. María Nícida Malca Quispe 2
3. FUNDAMENTOS DE PROLOG
PROLOG es un lenguaje interpretado basado en la lógica de predicados de primer orden. Puede ser visto
como un lenguaje de programación o como un demostrador mecánico de teoremas.
Un predicado representa una propiedad o relación de un determinado objeto del universo del discurso. Un
predicado de primer orden es aquel que se refiere a propiedades de objetos y relaciones entre ellos:
Ejm:
rubia(sara).
moreno(carlos).
novia(sara,carlos).
primos(X,Y):-progenitor(A,X),progenitor(B,Y),hermanos(A,B).
La lógica de predicados de primer orden estudia razonamientos de tipo deductivo, exactos (true/false)
y basados en predicados de primer orden.
Fue implementado a principios de los años 70 por Alain Colmerauer y junto con Lisp son los lenguajes que
históricamente se han utilizado para construir aplicaciones en gran parte de las ramas de IA.
En Prolog, las soluciones se alcanzan deduciendo lógicamente una cosa de algo ya conocido. Un programa
Prolog no es una secuencia de acciones, sino una colección de hechos, junto con una secuencia de
reglas para extraer conclusiones a partir de los hechos.
Prolog es un lenguaje declarativo, lo que significa que un programa escrito en Prolog está mucho más
cercano al lenguaje natural que los lenguajes imperativos (Basic, C, Pascal, etc).
El lenguaje incluye una máquina de inferencia, que no es más que un procedimiento general para
razonar acerca de la información. Esta máquina de inferencia se encarga de responder a las preguntas que se
realicen al sistema, intentando deducir la información a partir de los hechos conocidos y de las reglas del
programa.
Aunque Prolog no permite escribir programas mediante sentencias del lenguaje natural (el compilador sería
increíblemente complejo), la sintaxis está bastante cercana.
Concretamente, se usa un subconjunto de la lógica de predicados para representar la información. Por ejemplo:
Lenguaje natural Lógica de Predicados
Un coche es divertido.
Una rosa es roja.
A Juan le gusta un coche si es divertido.
divertido(coche).
roja(rosa).
gusta(juan,Coche) si divertido(Coche).
Prolog es un lenguaje declarativo e interpretado. Esto quiere decir que el lenguaje se usa para representar
conocimientos sobre un determinado dominio y las relaciones entre objetos de ese dominio. A partir de
ese conocimiento, el propio sistema deduce respuestas a cuestiones que se le planteen, es decir, realiza una
inferencia.
El dominio lo constituyen un conjunto de objetos, y el conocimiento se formaliza mediante un conjunto de
relaciones (reglas) que describen de forma simultánea propiedades de los objetos y sus interacciones.
Por tanto, escribir un programa de Prolog consiste en declarar el conocimiento disponible acerca de:
Objetos: Tanto sus propiedades (por ejemplo, X es par, X es un hombre) como las relaciones entre ellos
(por ejemplo, X es múltiplo de Y, X es padre de Y).
Reglas: Determinan interacciones lógicas entre los objetos, del tipo “si ocurren q y r, entonces ocurre p”.
Docente: Ing. María Nícida Malca Quispe 3
La ventaja de este tipo de lenguaje frente a lenguajes procedimentales (como Java, C) es que no hay que
preocuparse de cómo resolver algo; la desventaja es que la resolución automática no siempre es eficiente.
3.1 PROGRAMACIÓN LÓGICA
La programación lógica implica el uso de:
Hechos y reglas para representar la información
Deducciones para responder consultas
Los programadores proporcionamos los hechos y las reglas, mientras que el lenguaje usa la
deducción para calcular respuestas a consultas.
Un programa lógico se configura como un conjunto de hechos (asertos o proposiciones) y de reglas lógicas
previamente establecidas, que generan conclusiones ya sea a partir de una serie de preguntas o cuestiones
lógicas, de modo que tales conjuntos de hechos o asertos y reglas permitirán deducir nuevos hechos.
Un programa se estructura de la siguiente forma:
Lógica + Control + Estructuras de datos = Programa
, donde:
A. Lógica: Constituida por
a. Hechos: Que permiten establecer relaciones entre objetos o propiedades de éstos.
Ejemplo:
Chita es amiga de Tarzan
OBJETOS: Chita y Tarzan
RELACION: amiga
b. Reglas Lógicas: Expresan que un hecho depende de un grupo de otros hechos.
Ejemplo:
X es el abuelo paterno de Y si
X es el padre de Z
Z es el padre de Y
B. Control: Inherente al sistema, son las estrategias a seguir para investigar las cuestiones lógicas.
Ejemplo: estrategia de búsqueda “primero en profundidad”.
C. Estructura de Datos: Son los elementos que soportan la base de conocimiento y cuestiones lógicas.
Ejemplo: variables, listas, constantes, etc.
3.2 PROGRAMAS EN PROLOG
Los programas en Prolog se componen de cláusulas de Horn que constituyen reglas del tipo "modus
ponendo ponens", es decir, "Si es verdad el antecendente, entonces es verdad el consecuente":
p1(…) ∧ p2(…) ∧… ∧ pm(…) p(t1, t1, …, tn)
, donde tan p como las pi son símbolos predicados con sus argumentos entre paréntesis. Los argumentos de
un predicado se les denominan términos.
La regla anterior se interpreta como: “Si se verifican p1, p2,… y pn entonces se verifica p”.
Cabeza: Consecuente Cuerpo: Antecedente
Docente: Ing. María Nícida Malca Quispe 4
No obstante, en Prolog la forma de escribir las cláusulas de Horn es al contrario de lo habitual. Primero se
escribe el consecuente y luego el antecedente:
Las reglas son implicaciones lógicas, que pueden tener varios antecedentes pero un único consecuente.
Ejemplo
humano(X) → mortal(X).
, que utilizando la sintaxis de Prolog se escribe:
mortal(X):- humano(X).
Las cláusulas de Horn son expresiones condicionales, siendo el símbolo “:-”, el condicional o símbolo de
implicación (normalmente en lógica se utiliza el símbolo).
Así la cláusula anterior podría leerse de la siguiente forma:
Cuando m=0, la cláusula no tiene parte derecha (antecedente), en este caso diremos que se trata de un hecho
o afirmación.
Los hechos son afirmaciones que consideramos ciertas en el programa.
Cuando la cláusula no tiene parte izquierda, se trata de una pregunta; este tipo de cláusulas se utilizan para
realizar la entrada/salida del programa.
3.2.1 Predicados, Cláusulas y Términos
En Prolog un programa está constituido por una secuencia de cláusulas (a veces llamadas fórmulas o
sentencias). Estas cláusulas deben representar todo el conocimiento necesario para resolver el
problema.
Se pueden diferenciar tres tipos de cláusulas:
Hechos (afirmaciones): Se puede representar objetos, propiedades de objetos, relaciones entre
objetos.
Reglas
Consultas/Preguntas
Cada cláusula puede estar formada por instancias de uno o varios predicados. Las cláusulas deben
terminar obligatoriamente en un punto (.)
Los predicados expresan una relación entre un conjunto de objetos, denominados términos.
Con un predicado podemos representar algo que sucede en el mundo real (hecho), o una regla (regla
de inferencia), que nos permite deducir hechos que suceden en ese dominio mediante la aplicación de
la misma.
Cada predicado está definido unívocamente por su nombre y su aridad. La aridad es el número de
argumentos (parámetros, o términos) de un predicado.
Docente: Ing. María Nícida Malca Quispe 5
Ejemplo, se tienen las siguientes cláusulas (hechos):
humano(pepe).
humano(juan).
Para referenciar este predicado se utiliza únicamente su nombre y aridad: humano/1.
Cada predicado en Prolog puede estar definido por una o más cláusulas. En el ejemplo, humano/1
está definido por dos cláusulas.
Aridad Tipo de
predicado Representa Predicado
Instanciad de
predicados
0 Hechos simples o
Proposiciones.
Llueve/0 llueve.
1 Monádico Propiedades entre
objetos.
alto/1 mujer/1 moreno/1 hombre/1
alto(juan).
mujer(X).
moreno(X).
hombre(Y).
>1 Poliádico Relaciones entre
objetos.
padre_de/2
madre_de/2
tiene/2
le_gusta_a/2
regala/3
padre_de(jose,manuel).
padre_de(Padre,Hijo).
madre_de(Madre,Hijo).
tiene(Per,Obj).
le_gusta_a(X,Y).
regala(Per1,Obj,Per2).
Todas las cláusulas cuyas cabezas tienen el mismo nombre y aridad forman un predicado (o una
definición de procedimiento). Por ejemplo, veamos un predicado formado por tres cláusulas, dos de las
cuales son hechos y la otra es una regla:
elefante(dumbo).
elefante(jumbo).
elefante(X):-gris(X),mamífero(X),tieneTrompa(X).
Nótese que este predicado nos da tres formas distintas de llegar a la conclusión de que X es un elefante;
o es dumbo, o es jumbo, o es gris, mamífero y tiene trompa.
Términos
Docente: Ing. María Nícida Malca Quispe 6
3.2.2 Términos
Son construcciones simbólicas que representan objetos del universo del discurso, y pueden ser:
Términos simples:
constantes simbólicas o numéricas
Ejemplo: a, x, juan, “2”, caso_1, -1.73
Variables
Ejemplo: Algo, X, Hombre, _caso_1
Términos estructurados
listas
funciones
Constantes
Dan nombre a objetos concretos del dominio, representan individuos conocidos:
juan, maria, 20
Hay dos clases de constantes: átomos y números.
Átomo:
Los átomos hacen las funciones de identificadores en Prolog.
Un átomo puede ser cualquier combinación de letras y números (y algunos signos).
Comenzar con una letra minúscula.
Pueden contener el carácter “_” (subrayado).
Si van entre comillas dobles (“ ”), puede contener cualquier carácter.
Ejemplo:
Válidos No Válidos
unatomo
otro_atomo
“Atomo”
“2+3”
“un atomo”
un atomo
_otro_atomo
Atomo
2+3
Números:
Se utilizan para representar números de forma que se puedan realizar operaciones aritméticas.
Depende de la implementación.
Al menos integer y float (enteros y flotantes).
Docente: Ing. María Nícida Malca Quispe 7
Variables
Representan objetos cualesquiera del Universo u objetos desconocidos en ese momento, es decir,
son las incógnitas del problema.
Una variable está:
instanciada cuando existe un objeto representado por ella.
no instanciada cuando todavía no se sabe lo que representa la variable.
Cuando una variable es instanciada su contenido no puede cambiar. Una variable puede ser instanciada
a cualquier otro término, incluida otra variable.
No son equivalentes a las variables en los lenguajes procedurales, sino a las variables lógicas o
matemáticas.
El nombre de una variable ha de comenzar por una mayúscula o “_”, y puede contener cualquier
combinación de letras, números y el carácter subrayado (_).
Ejemplo:
Suma
X2
_32 _
Algo
_
El carácter subrayado “_” solamente, es un tipo de variable especial que se denomina variable
anónima. Ésta se utiliza para escribir variables sin necesidad de darles un nombre. Cada aparición del
carácter subrayado representa una variable distinta. Esta variable no queda instanciada, pues no
necesitaremos su valor.
3.2.3 Hechos, Consultas y Reglas
Hechos
Los hechos son el mecanismo básico para representar:
Objetos/personas/conceptos.
Propiedades de los objetos.
Relaciones entre los objetos.
En Prolog, una relación entre objetos recibe el nombre de predicado. En el lenguaje natural, una
relación se expresa mediante sentencias. Por ejemplo:
Juan tiene un perro.
Elena tiene un coche.
Juan tiene un libro.
Docente: Ing. María Nícida Malca Quispe 8
Por el contrario, en Prolog usamos un símbolo de predicado que contiene (entre paréntesis) los distintos
objetos a los que afecta dicho predicado. Por ejemplo, las tres sentencias anteriores se expresarían así:
tiene(juan,perro).
tiene(elena,coche).
tiene(juan,libro).
Los hechos no sólo pueden expresar relaciones entre objetos, sino también propiedades de los mismos.
Por ejemplo, las sentencias del lenguaje natural “Juan es alto.” o “Elena es rubia.” se expresarían en
Prolog así:
alto(juan).
rubia(elena).
Los hechos son las sentencias más sencillas. Un hecho es una fórmula:
p(t1, ..., tn)
, e indica que se verifica la relación (predicado) p sobre los objetos (términos) t1, ..., tn.
Ejemplos:
es_padre(abraham, isaac), es un hecho que indica “Abraham es padre de Isaac”
es_hombre(abraham), es un hecho que indica “Abraham es un hombre”
suma(3,2,5), es un hecho que indica “la suma de 3 y 2 es 5”
Un conjunto de hechos constituye un programa (la forma más simple de programa lógico) que
puede ser visto como una base de datos que describe una situación. Por ejemplo, el siguiente
programa refleja la base de datos de las relaciones familiares que se muestran en el siguiente gráfico:
Todos los hechos de este programa son hechos de base (sin variables), pero también se pueden
introducir hechos con variables como axiomas, por ejemplo:
suma(0, X, X).
En ellos, las variables se consideran cuantificadas universalmente. Es decir:
x suma(0, x, x)
Al igual que el hecho es_mujer(sarah) establece la verdad de la sentencia "Sarah es mujer", el hecho
suma(0, X, X) establece la verdad para cualquier valor que pueda tomar la variable, es decir, nos dice
que "para todo término x, la suma de 0 con x es x" . Equivale a un conjunto de hechos de base
como serían: suma(0, 1, 1), suma(0, 2, 2), etc.
Docente: Ing. María Nícida Malca Quispe 9
Algunas consideraciones para definir los hechos:
El nombre de los objetos y relaciones empiezan una letra minúscula.
Primero se escribe la relación y después los objetos a modo de argumentos (términos), entre
paréntesis y separados por comas (,).
Se permite “_” para separar caracteres.
Al final debe aparecer un punto (.)
Consultas
Una vez que se tiene el programa describiendo una situación, se pueden hacer preguntas
(consultas) para obtener información acerca de él. Por ejemplo, podemos hacer preguntas al
Programa 1 del tipo siguiente:
Estas preguntas sencillas se llaman fines (metas). Como puede verse en la lectura de las preguntas, en
éstas se consideran las variables cuantificadas existencialmente. También se pueden hacer
preguntas más complejas, como CONJUNCIÓN de metas, de la forma:
Reglas
Las reglas nos permiten deducir hechos a partir de otros hechos. Por ejemplo, dadas los siguientes
hechos:
Juan tiene un perro.
Elena tiene un coche.
Juan tiene un libro.
Juan es alto.
Elena es rubia.
, y las siguientes reglas:
Pedro tiene todo lo que tiene Juan.
Ana es rubia si lo es Elena.
Podemos deducir los nuevos hechos:
Pedro tiene un perro.
Pedro tiene un libro.
Ana es rubia.
Docente: Ing. María Nícida Malca Quispe 10
Las reglas anteriores se codificarían en Prolog así:
tiene(pedro,X):- tiene(juan,X).
rubia(ana):- rubia(elena).
Las reglas de inferencia se pueden definir como la especificación de una relación entre predicados
y argumentos, que permiten plasmar el hecho de que si la parte derecha del predicado se cumple, se
cumple la parte izquierda.
El símbolo “:-” se pronuncia simplemente “si”, y sirve para separar las dos partes de la regla: la
cabeza y el cuerpo. Desde el punto de vista lógico, el símbolo “:-” equivale a una implicación de
derecha a izquierda ().
Las reglas son sentencias de la forma:
A :- B1 , ... , Bn.
, donde A y cada Bi son predicados. A es la cabeza de la regla y los Bi's componen el cuerpo de la
regla. La correspondencia entre símbolos es la siguiente:
Lógica de Primer Orden Prolog
:-
,
;
Ejemplo: Una regla que define la relación “ser hijo” a partir de las relaciones dadas podría ser:
es_hijo(X,Y) :- es_padre(Y,X), es_hombre(X).
, que se leería de la forma: “para cualesquiera X e Y, X es hijo de Y si Y es padre de X y X es hombre",
ya que se corresponde con la fórmula lógica:
x y ( (es_padre(y,x) es_hombre(x)) es_hijo(x,y))
De igual forma se definirían otras relaciones mediante reglas:
es_hija(X,Y) :- es_padre(Y,X), es_mujer(X).
es_abuelo(X,Y) :- es_padre(X,Z), es_padre(Z,Y).
La última regla podría leerse "para cualesquiera X e Y, X es abuelo de Y, si existe algún Z tal que X
es padre de Z y Z es padre de Y", que se corresponde con la fórmula:
x z ( z(es_padre(x,z) es_padre(z,y)) es_abuelo(x,y))
Con estas tres nuevas relaciones entre objetos y los hechos de base anteriores podemos crear el
siguiente Programa 2.
Ahora podemos hacer preguntas al Programa 2 sobre las nuevas relaciones introducidas:
Docente: Ing. María Nícida Malca Quispe 11
Otras preguntas y respuestas a este programa serían:
g
Como se observa, las reglas de inferencia permiten llevar a cabo la deducción de metas. Para que
las reglas de inferencia sean aplicables, en general, deberá existir un conjunto de hechos sobre los
que apoyarse para que las demostraciones se puedan realizar.
Las metas representan los problemas específicos, basados en los problemas generales
expresados en la base de conocimientos que deseamos que el demostrador automático de teoremas
resuelva. Si nos fijamos, para escribir programas en Prolog, siempre debemos tener en cuenta que
el demostrador resuelve las metas comenzando por los predicados situados en la zona superior
(de arriba a abajo), y para cada predicado el proceso de unificación se lleva a cabo de izquierda a
derecha.
Cuantificación de Variables
Los símbolos de cuantificación para las variables, están implícitamente determinados.
Si las fórmulas atómicas de un programa lógico contienen variables, el significado de estas es:
Las variables que aparecen en los hechos están cuantificadas universalmente.
Significa que a jorge le gusta cualquier cosa.
Las variables que aparecen en la cabeza de las reglas están cuantificadas universalmente.
Docente: Ing. María Nícida Malca Quispe 12
Las variables que aparecen en el cuerpo de la regla, pero no en la cabeza, están cuantificadas
existencialmente.
Significa que para toda pareja de personas, una será el abuelo de otra si existe alguna persona de
la cual, el primero es padre y a su vez es padre del segundo.
Las variables que aparecen en las preguntas (metas) están cuantificadas existencialmente.
Pregunta si existe algo que le guste a jorge, ya que utilizamos refutación y por tanto negamos lo
que queremos demostrar
Conectivos Lógicas
Siendo X e Y instancias de predicados, se tiene:
La conjunción “y” (X,Y)
Objetivos separados que Prolog debe satisfacer, uno después de otro, por orden Para que se
satisfaga la secuencia se tendrán que satisfacer todos los objetivos.
La disyunción “o” (X;Y)
Tendrá éxito si se cumple alguno de los objetivos que la componen. También la podemos
representar poniendo cada miembro de la disyunción en una cláusula aparte.
La negación lógica (not X)
NO puede ser representada explícitamente en Prolog. Se puede utilizar el predicado estándar not.
La implicación o condicional (:-)
Sirve para especificar que un hecho depende de un grupo de otros hechos. Se usa el símbolo “:-”
para representar lo que llamamos una regla.
La cabeza describe el hecho que se intenta definir; el cuerpo describe los objetivos que deben
satisfacerse para que la cabeza sea cierta:
Cláusulas Generales usando Variables
El uso de variables en Prolog nos permite escribir sentencias de carácter general.
Por ejemplo, la sentencia “Pedro tiene todo lo que tiene Juan” se puede escribir en
Prolog así:
tiene(pedro,Algo) :- tiene(juan,Algo).
En una consulta simple, las variables nos pueden servir para que que Prolog encuentre un dato. Por
ejemplo, la consulta:
tiene(X,coche).
, nos devuelve en la variable X el nombre de la persona que tiene un coche (o de las personas que lo
tienen, si hay más de una).
La elección de un nombre adecuado para las variables suele hacer el programa más legible. Por
ejemplo, la consulta anterior estaría mejor así:
tiene(Persona,coche).
Docente: Ing. María Nícida Malca Quispe 13
Variables Anónimas
Cuando sólo deseamos extraer cierta información de una consulta, se usa un tipo especial de variables
denominadas variables anónimas. En Prolog, una variable anónima se denota por un símbolo de
subrayado (“_”).
Por ejemplo, consideremos la siguiente regla:
hijo(X) :- padre (X,Y).
La regla dice, para toda X, X tiene un hijo si X es el padre de alguna Y. Nosotros estamos definiendo la
propiedad hijo el cual, no depende del nombre del hijo. Entonces, aquí hay un lugar en donde podemos
usar una variable anónima. Si rescribimos la cláusula:
hijo(X) :- padre(X,_).
Asignación de valores a las Variables
En Prolog no existe una instrucción de asignación. Esto resulta una de las diferencias fundamentales
entre Prolog y el resto de lenguajes de programación.
Las variables en Prolog toman valores al ser “igualadas” a constantes en los hechos o reglas del
programa.
Hasta el momento en que una variable toma un valor, se dice que está desinstanciada; cuando ha
tomado un valor, se dice que está instanciada (a dicho valor).
Sin embargo, una variable sólo permanece instanciada hasta el momento en que obtenemos una
solución. Después, se desinstancia, y se procede a buscar nuevas soluciones.
En consecuencia, no es posible utilizar las variables de Prolog para almacenar información.
3.3 COMENTARIOS
Los comentarios en un programa Prolog se pueden escribir de dos formas distintas:
Si se trata de un comentario que ocupa varias líneas, debemos comenzarlo con /* y terminarlo con */
Cuando el comentario es breve, podemos usar el símbolo %, el cual provoca que todo lo que quede a
su derecha en la misma línea se considere un comentario.
4. ENTORNO DE DESARROLLO PROLOG
Prolog es un lenguaje de programación seminterpretado. Su funcionamiento es muy similar a Java. El codigo
fuente se compila a un código de byte el cuál se interpreta en una máquina virtual denominada Warren Abstract
Machine (comúnmente denominada WAM).
Por eso, un entorno de desarrollo Prolog se compone de:
Un compilador. Transforma el código fuente en código de byte. A diferencia de Java, no existe un standard
al respecto. Por eso, el codigo de byte generado por un entorno de desarrollo no tiene por que funcionar en
el intérprete de otro entorno.
Un intérprete. Ejecuta el código de byte.
Un shell o top-level. Se trata de una utilidad que permite probar los programas, depurarlos, etc. Su
funcionamiento es similar a los interfaces de línea de comando de los sistemas operativos.
Docente: Ing. María Nícida Malca Quispe 14
Una biblioteca de utilidades. Estas bibliotecas son, en general, muy amplias. Muchos entornos incluyen
(afortunadamente) unas bibliotecas standard-ISO que permiten funcionalidades básicas como manipular
cadenas, entrada/salida, etc.
Generalmente, los entornos de desarrollo ofrecen extensiones al lenguaje como pueden ser la programación
con restricciones, concurrente, orientada a objetos, etc.
Existe un standard ISO que dicta las típicas normas con respecto a la sintaxis del lenguaje y a las bibliotecas
básicas que se deben ofrecer. Actualmente el standard no contempla todos los aspectos del lenguaje, y
además, no todos los entornos siguen el standard al pie de la letra. Por eso, programas que funcionan en unos
entornos podrían no funcionar en otros, o lo que es peor, funcionar de forma diferente.
5. FUNDAMENTOS DE VISUAL PROLOG
Características del lenguaje
Visual Prolog es un lenguaje de programación de quinta generación especialmente orientado al desarrollo de
aplicaciones de bases de datos, interfaces basadas en lenguaje natural, parsers y compiladores, sistemas
expertos, etc.
Los tiempos de desarrollo de una aplicación en Visual Prolog pueden llegar a ser hasta 10 veces menor que en
otro lenguaje de programación como C o Pascal, debido al alto nivel de abstracción del lenguaje. Pese a ello,
dispone de un compilador capaz de generar código máquina tan eficiente como un buen compilador de C.
Por otro lado, Visual Prolog es un lenguaje “abierto”, es decir, permite generar rutinas que se pueden invocar
desde aplicaciones escritas en C, C++ o ensamblador.
De forma análoga, una aplicación en Visual Prolog puede invocar rutinas escritas en los lenguajes C, C++,
Pascal o ensamblador.
Programas en Visual Prolog
Para la resolución de preguntas (metas), utiliza la estrategia de primero hacia abajo (recorrido del árbol en
profundidad). Por todo esto, el orden de las cláusulas (hechos y reglas) de un determinado procedimiento es
importante, para determina el orden en que las soluciones serán encontradas.
A diferencia de otras versiones de Prolog, Visual Prolog es un compilador de Prolog con tipos. Esto significa que
hay que declarar los tipos de los objetos sobre los que actúa cada predicado. De esta forma, el compilador
Prolog puede generar código máquina tan eficiente como un programa compilado en C o Pascal.
En general, un programa Visual Prolog incluye cuatro secciones básicas: clauses, predicates, domains, y goal.
La sección clauses forma el núcleo de un programa Visual Prolog. Aquí es donde aparecen los hechos y las
reglas con los que el sistema va a trabajar para ejecutar un objetivo.
La sección predicates contiene la declaración de los predicados definidos en la sección clauses, indicando
el tipo de sus argumentos.
La sección domains se emplea para declarar dominios (tipos de datos) que no estén predefinidos en el
sistema.
Declarar algunos HECHOS sobre los objetos y sus
relaciones.
Definir algunas REGLAS sobre los objetos y sus relaciones
Hacer PREGUNTAS sobre los objetos y sus relaciones.
Docente: Ing. María Nícida Malca Quispe 15
La sección goal contiene el objetivo inicial que provoca el comienzo de la ejecución del programa (algo así
como el cuerpo principal del programa).
a) La sección “clauses”
En la sección clauses se incluyen la definición de hechos y reglas.
Una restricción del lenguaje es que todas las cláusulas que definan un mismo predicado deben aparecer
consecutivamente en el programa. Una secuencia de cláusulas definiendo un mismo predicado, se llama un
procedimiento.
Cuando Prolog intenta resolver un objetivo, comienza a recorrer todas las cláusulas de la sección clauses en el
orden de aparición de las mismas. Cada vez que encuentra una cláusula a la que se pueda igualar el objetivo,
se anota la posición de la misma para la búsqueda de soluciones alternativas (backtracking).
Sintaxis de las reglas
Una regla está compuesta por dos partes: la cabeza y el cuerpo, separados por el símbolo “:-” (que se
interpreta como un “si”). La sintaxis genérica para una regla es:
cabeza :- subobjetivo1, subobjetivo2, ..., subobjetivoN.
Los subobjetivos en el cuerpo de una regla se pueden interpretar como llamadas a procedimiento, las cuales,
si tienen éxito, provocarán que ciertas variables se instancien a ciertos valores.
Es decir, desde el punto de vista procedural, la regla anterior se interpreta así:
“para ejecutar el procedimiento cabeza, hay que ejecutar las llamadas a procedimiento subobjetivo1,
subobjetivo2,. . . , subobjetivoN”.
Para ejecutar una regla con éxito, todos los subobjetivos del cuerpo deben de poder ejecutarse también con
éxito. Si al menos uno de ellos falla, Prolog intenta la ejecución de otra regla alternativa (si la hay). En esto
consiste el mecanismo de backtracking.
b) La sección “predicates”
Si definimos un predicado en la sección clauses, debemos declararlo en la sección predicates, o bien Visual
Prolog nos dará un error. Declarar un predicado sirve para decirle al sistema cuál es el tipo de los argumentos
de un predicado.
Visual Prolog incluye un número importante de predicados predefinidos (“built-in predicates”), como, por
ejemplo, write, read, +, sqrt, etc. Este tipo de predicados no deben ser declarados en la sección predicates. Se
puede encontrar información sobre los predicados predefinidos en el menú de ayuda de Visual Prolog.
Cómo declarar predicados definidos por el usuario
Una declaración de predicado comienza con el nombre del predicado. A continuación, entre paréntesis,
aparecen los tipos de sus (cero o más) argumentos.
nombrePredicado(tipo_arg1,tipo_arg2,...,tipo_argN)
Observa que, a diferencia de lo que ocurre en la sección clauses, aquí no terminamos la declaración con un
punto.
El nombre de un predicado debe comenzar con una letra (minúscula), seguida de cualquier número de letras,
dígitos o subrayados. Los nombres de predicado tienen una longitud máxima de 250 caracteres.
En los nombres de los predicados no pueden aparecer espacios en blanco, signos aritméticos, asteriscos, u
otros caracteres no alfanuméricos (únicamente son válidos a..z, A..Z y 0..9).
Docente: Ing. María Nícida Malca Quispe 16
Los argumentos de un predicado deben pertenecer a un dominio. El dominio puede ser un dominio estándar, o
bien un dominio definido en la sección domains. Veamos algunos ejemplos:
Si declaramos un predicado mi predicado en la sección predicates como sigue:
predicates
mi_predicado(symbol, integer)
, entonces no es necesario declarar los dominios de sus argumentos en la sección domains, ya que symbol e
integer son dominios estándar. Sin embargo, si declaramos el predicado así:
predicates
mi_predicado(nombre, numero)
, entonces necesitaremos declarar los dominios nombre y número en la sección domains. Por ejemplo, si
queremos definirlos simplemente del tipo symbol e integer, respectivamente, lo haríamos así:
domains
nombre = symbol
numero = integer
predicates
mi_predicado(nombre, numero)
El siguiente fragmento de programa muestra una declaración de dominios y predicados algo más compleja:
domains
person, activity = symbol
car, make, color = symbol
mileage, years_on_road, cost = integer
predicates
likes(person, activity)
parent(person, person)
can_buy(person, car)
car(make, mileage, years_on_road, color, cost)
green(symbol)
ranking(symbol, integer)
Cuando declaramos un argumento del tipo symbol, estamos indicándole al compilador que sólo podrá contener
una constante alfanumérica, mientras que integer hace referencia a un número entero.
c) La sección “domains”
La sección domains nos permite conseguir esencialmente dos cosas:
Docente: Ing. María Nícida Malca Quispe 17
Podemos darle nombres particulares a ciertos dominios, pese a que éstos ya estén predefinidos (dominios
estándar), facilitando la legibilidad del programa, y se detecta un mayor número de errores en tiempo de
compilación.
Permite declarar estructuras de datos complejas que no están predefinidas.
Por ejemplo, supongamos que queremos declarar un predicado que vamos a usar para escribir la siguiente
relación:
Paco es un hombre de 45 años.
Usando los dominios estándar, podríamos declarar el siguiente predicado:
predicates
persona(symbol, symbol, integer)
Aunque la declaración es correcta, resultaría mucho más legible el código si lo hacemos así:
domains
nombre, sexo = symbol
edad = integer
predicates
persona(nombre, sexo, edad)
Además, con una declaración de esta forma, el compilador detectaría que la siguiente cláusula es incorrecta:
mismo_sexo(X,Y) :- persona(X,Sex,_), persona(Sex,Y,_).
, mientras que con la declaración original la compilaría sin problemas (ya que los dos primeros argumentos eran
symbol).
d) La sección “goal”
Esencialmente, la sección goal contiene lo mismo que aparece en el cuerpo de cualquier regla, es decir, no es
más que una secuencia de subobjetivos.
La única diferencia es que la secuencia de subobjetivos en la sección goal se ejecuta automáticamente al
ejecutar el programa (sería equivalente al “cuerpo principal” del programa).
Si alguno de los subobjetivos de goal falla, el programa completo falla (pese a que, desde un punto de vista
externo, esto no marca ninguna diferencia, simplemente se termina la ejecución).
Dominios Estándar
Visual Prolog dispone de varios dominios estándar que se pueden emplear en la declaración de los predicados.
Estos dominios no deben declararse en la sección domains.
Los dominios estándar para los números enteros son:
Docente: Ing. María Nícida Malca Quispe 18
En general, los dominios integer y unsigned suelen ser suficientes y, además, se adaptan bien a la plataforma
en que se esté trabajando.
La siguiente tabla muestra el resto de dominios estándar de Visual Prolog:
Los objetos de tipo symbol y string se pueden intercambiar sin problemas. Sin embargo, Visual Prolog los
almacena de forma distinta:
un objeto de tipo symbol se almacena en una tabla de símbolos, y se identifica únicamente por la dirección
en la que está almacenado (el ajuste entre este tipo de objetos resulta muy eficiente)
un objeto de tipo string se almacena como un vector de caracteres (con lo que el ajuste entre este tipo de
objetos es algo más lento, ya que tiene que comparar los dos strings carácter a carácter).
La elección de uno u otro dominio dependerá del uso que le vayamos a dar en el programa. Por ejemplo, si no
vamos a necesitar acceder a los caracteres del objeto, lo más adecuado sería definirlo como symbol.
Observa que las secciones predicates, clauses y goal son obligatorias en todos los programas. La sección
domains, por ejemplo, es opcional. Concretamente, si todos los dominios empleados en la sección predicates
son estándar, la sección domains no es necesaria.
Algunos Predicados Estándar
Existe un conjunto de predicados predefinidos en Prolog que podrás utilizar en tus programas.
Docente: Ing. María Nícida Malca Quispe 19
Predicados (operadores) de comparación
X < Y X e Y han de estar instanciadas a dos valores numéricos; comprueba que la primera sea menor que la segunda.
X > Y X e Y han de estar instanciadas a dos valores numéricos; comprueba que la primera sea mayor que la segunda.
X <= Y X e Y han de estar instanciadas a dos valores numéricos; comprueba que la primera sea menor o igual que la
segunda.
X >= Y X e Y han de estar instanciadas a dos valores numéricos; comprueba que la primera sea mayor o igual que la
segunda.
X = Y Unifica X a Y.
Entrada/Salida estándar
A continuación, se muestran algunos predicados básicos para poder realizar operaciones de entrada/salida
desde/sobre el terminal de salida de la computadora.
nl Escribe una línea en blanco (caracter newline) sobre la salida estándar actual.
readln(-Term)
readreal(-Term)
readint(-Term)
Lee un término desde la entrada estándar del dispositivo.
write(+Term)
writef(+Term)
Escribe el término Term sobre la salida estándar.
La sección “constants”
En un programa, es posible definir constantes simbólicas dentro de la sección constants.
La sintaxis es la siguiente:
constants
<id> = <definicion>
, donde <id> es el nombre de la constante simbólica, y <definition> es el valor que le estamos asignando a
dicha constante. Por ejemplo, podemos encontrar una declaración de constantes como esta:
constants
cero = 0
uno = 1
dos = 2
cien = (10*(10-1)+10)
pi = 3.141592653
Como es habitual, antes de realizar la compilación del programa, Visual Prolog reemplaza la aparición de cada
constante simbólica en el código por su valor.
Existen, sin embargo, unas pocas restricciones sobre el uso de constantes simbólicas:
La definición de una constante no puede autoreferenciarse. Por ejemplo:
error = 2*error
, generaría un mensaje de error.
El sistema no distingue entre mayúsculas y minúsculas en los nombre de constantes. Por tanto, aunque se
declare una constante:
Docente: Ing. María Nícida Malca Quispe 20
constants
Dos = 2
, en el programa habrá que emplearla en minúsculas (para evitar que se confunda con una variable). Es
decir, escribiremos:
goal
A = dos, write(A).
, y no:
goal
A = Dos, write(A).
(lo que produciría un error).
Pueden aparecer varias secciones de declaración de constantes en un programa, pero ´estas deben
declararse siempre antes de la primera vez que se usen.
La declaración de una constante es válida desde el punto en el que se define hasta el final del fichero fuente,
pero no pueden declararse varias constantes con el mismo identificador.
Aridad múltiple
La aridad de un predicado es el número de argumentos que tiene. Podemos definir varios predicados con el
mismo nombre y distinta aridad. Visual Prolog permite la definición de un predicado con distintas aridades,
exigiendo únicamente que sus definiciones deben aparecer agrupadas tanto en la secci´on predicates como en
la sección clauses. Por lo demás, cada versión del predicado con una aridad distinta se considera como un
predicado completamente distinto.
Ejemplo:
domains
person = symbol
predicates
nondeterm father(person)
nondeterm father(person,person)
clauses
father(adam,seth).
father(abraham,isaac).
father(Man):- father(Man,_).
goal
father(X).
Variables lógicas, sustituciones e instancias.
Una variable lógica significa la especificación de algo indeterminado.
Por ejemplo
padre(juan,X).
, para obtener la respuesta X=maria (si está definido en la base de conocimientos)
Docente: Ing. María Nícida Malca Quispe 21
Una consulta que contiene variables se debe comprender como encontrar los valores que se pueden
asignar a la variable para que la consulta sea una consecuencia lógica del programa (verdadero).
Las variables tienen aquí un significado distinto al del que tienen en los lenguajes del paradigma imperativo:
no son una posición de memoria, sino una incógnita, una indeterminación de la identidad de los valores
que cumplen una relación.
En este paradigma de programación, una variable una vez ligada a un valor no puede cambiar de estado.
Sea el siguiente programa:
predicates
prueba
clauses
prueba:- Resultado = 3 + 2, write (Resultado), nl,Resultado = 3 - 2, write (Resultado).
goal
prueba.
Donde el predicado write emite por pantalla variables o literales, y nl emite un carácter <ENTER>, ¿qué sucede
al ejecutarse?
Aparece en pantalla:
5
false.
Para entender el concepto de variable, veamos paso por paso cada hecho.
Prueba será verdadero si se logran verificar los cuatro antecedentes: Resultado debe ser igual a 3 + 2.
Como inicialmente Resultado no está ligado a ningún valor, se produce una asignación de Resultado a 5.
El siguiente hecho imprime el valor 5 por pantalla, y como ambos hechos se cumplen, la sentencia continua (el
objetivo es probar que prueba es verdadero).
Luego se imprime un <ENTER> y continua con el siguiente hecho, que pide que la variable Resultado sea
igual a 3 – 2. Resultado ya está asignado a 5, por lo tanto, se produce una comparación 5 = 1, y por lo
tanto, el predicado prueba falla.
En resumen:
La variable, una vez ligada a un valor, no puede volverse a asignar a otro, y por eso el hecho X = X + 1 es
siempre falso.
Principio de Funcionamiento
La Programación Prolog se basa en la generación de una Base de Conocimiento y la posterior consulta a
la misma en busca de hechos explícitamente declarados u otros que se puedan inferir de los antedichos
(mediante el empleo de reglas).
Sea el siguiente programa Prolog:
domains
nombre=symbol
predicates
varon(nombre)
mujer(nombre)
Docente: Ing. María Nícida Malca Quispe 22
clauses
varon(marcos).
varon(nicolas).
mujer(victoria).
mujer(laura).
goal
varon(Quien).
Al ejecutar el programa anterior, prolog buscará unificar (match) la consulta con las cláusulas. Su respuesta
será:
Quien= marcos
Quien= nicolas
Si la consulta fuera mujer(victoria), la respuesta sería:
True (verdadero)
De esto se desprende que una consulta puede ser una búsqueda o una validación (V/F).
Pero la potencia de Prolog se manifiesta cuando usamos relaciones múltiples y reglas, por ejemplo:
domains
nombre=symbol
predicates
progenitor(nombre,nombre)
varon(nombre)
mujer(nombre)
padre(nombre,nombre)
clauses
varon(juan).
varon(carlos).
mujer(paola).
mujer(mirta).
progenitor(mirta,juan).
progenitor(carlos,paola).
padre(X,Y):- progenitor(X,Y),varon(X).
1º Consulta: padre(X, juan): Árbol de objetivos:
Docente: Ing. María Nícida Malca Quispe 23
2º Consulta: padre(mirta,juan).
En primer lugar se aparea la consulta padre(mirta,juan) con la cabeza de la regla:
padre(X,Y) :-progenitor(X,Y),varon(X)
, unificando mirta a X y juan a Y, ahora deja una marca para el Backtraking y aumenta un nivel de interioridad
buscando solución a progenitor(mirta,juan) y a varon(mirta) desde el principio.
La primera resulta Verdadera, pero la segunda Falsa, por lo que la unificación de la consulta original con esta
regla resultó ser inútil. Es aquí donde el interprete regresa al estado donde dejó la marca y sigue analizando la
cláusula siguiente a padre(X,Y):-progenitor(X,Y),varon(X). Como esta es la última cláusula el análisis termina
y la respuesta será que la afirmación padre(mirta,juan) es Falsa.