TUTORIAL DE PROLOG

( Ver 3.47)


Indice

INTRODUCCIÓN.

CAPÍTULO 1. COMO CORRER PROLOG.

CAPÍTULO 2. DEPURACIÓN.

CAPÍTULO 3. COMPILACIÓN.

CAPÍTULO 4. CONSTRUCCION DE PROCEDIMIENTOS.


INTRODUCCIÓN.

Prolog es un lenguaje de programación simple pero poderoso desarrollado en la Universidad de Marsella como una herramienta práctica para programación lógica. Desde el punto de vista del usario, la ventaja principal es la facilidad para programar, ya que se pueden escribir rapidamente y con pocos errores, programas claramente leíbles.

Para una introducción al Prolog, se recomienda que se consulte el libro de Closkin y Mellish (81), sin embargo, para beneficio de aquellos que no tiene acceso al libro y para aquellos que tienen conocimientos anteriores de lógica, se encuentra un sumario del lenguaje en el apéndice I de esta obra.

Este manual describe el Sistema Prolog que fue desarrollado en el Departamento de Inteligencia Artificial de la Universidad de Edimburgo expresamente para el DECsystem-10. Este sistema se compone de un intérprete y un compilador, ambos escritos también en Prolog. A nivel del usuario, el compilador se puede considerar como un procedimiento integrado en el sistema que puede ser llamado por el intérprete.

Ya compilado, un procedimiento se puede correr a una velocidad de 10 a 20 veces más rápida, así como su almacenamiento también se ve reducido. Sin embargo, se recomienda que los usuarios nuevos ganen experiencia con el intérprete antes de intenten usar el compilador. El interprete facilita el desarrollo y la prueba de programas así como también provee facilidades muy poderosas para la depuración del código.

Ciertos aspectos del Prolog no se han previsto en la instalación, por ejemplo el tipo de monitor en el que se va a usar, aspecto que lleva muchos de los procedimientos con los que el sistema cuenta. Este manual describe la instalación de la versión de Edimburgo bajo TOPS-10, versión 7.01, los usuarios de otro tipo de instalación se pueden referir al apéndice III.

Este manual se basa en la obra "User's Guide to DECsystem-10 Prolog" de L.M. Pereira, F.C.N. Pereira y D.H.D. Warren. Parte del capítulo 2 se tomo del libro de Byrd, (80). Comentarios muy utiles que se presentan en este manual fueron reslizados por Lawrence Byrd, Luis Jenkins, Richard O'Keefe, Fernando Pereira, Robert Rae y Leon Sterling.

El sistema Prolog es mantenido por el Departmento de Inteligencia Artificial y el Engineering Board Computing Committee del Science and Engineering Research Council.

Regresar al Indice


CAPÍTULO 1. COMO CORRER PROLOG.

El Prolog para el DECsystem-10 ofrece al usuario un ambiente de programación con herramientas para construir programas, depurarlos siguiendo su ejecución a cada paso y modificar partes de los programas sin tener que volver a comenzar todo el proceso desde el último error.

El texto en un programa en Prolog se crea en un archivo o en un número de archivos usando cualquier editor de texto estándar. El intérprete de Prolog puede ser instruido para que lea los programas contenidos en estos archivos. A esta operación se le llama consultar el archivo.

Regresar al Indice


1.1 Comienzo

Para correr el intérprete de Prolog, se deberá teclear el siguiente comando:

El intérprete responde con un mensaje de identificación y el indicador "| ?- " se presentará cuando el sistema esté listo para aceptar cualquier entrada, así, la pantalla se verá como sigue:

En este momento el intérprete estará ya esperando que el usuario ingrese cualquier comando por ejemplo: una pregunta o una orden (ver sección 1.4). No se pueden introducir cláusulas inmediatamente (ver sección 1.3). Este estado se llama nivel alto del intérprete. Mientras que se teclea un comando, el indicador permanecerá de la siguiente manera:

El indicador "?-" aparecerá solamente en la primera línea.

Regresar al Indice


1.2 Lectura de archivos con programas

Un programa esta compuesto por una secuencia de cláusulas que se pueden intercalar con directivas para el intérprete. Las cláusulas de un procedimiento no necesariamente tienen que ser consecutivas, pero si es necesario recordar que el orden relativo es muy importante.

Para Ingresar un programa desde un archivo, sólo se tiene que teclear el nombre del archivo dentro de corchetes y seguidos de un ENTER:

Esta orden le dice al intérprete que tiene que leer (consultar) el programa. La especificación del archivo tiene que ser un átomo de Prolog, también puede contener especificación de dispositivos y/o una extensión, pero no se debe incluir la ruta de ubicación. Notese que es necesario que todas estas especificaciones se coloquen dentro de comillas, por ejemplo:

Después de haber tecleado esto el archivo será leído,

Así las cláusulas que se han guardado en un archivo están listas para ser leídas e interpretadas, mientras que las directivas son ejecutadas al momento de ser leídas. Cuando se encuentra el fin del archivo, el intérprete pone en pantalla el tiempo que se ha gastado en la lectura y el número de palabras ocupadas por el programa. Cuando este mensaje se despliegue quiere decir que el comando se ha ejecutado con éxito.

También se pueden combinar varios archivos de la siguiente manera:

En este caso los tres archivos serán leídos.

Si un nombre de archivo se antecede del signo "menos" (-), por ejemplo:

Entonces este archivo o estos archivos serán releídos. La diferencia entre la lectura simple y la releída es que cuando un archivo es leído entonces todas las cláusulas en el archivo se añaden a la base de datos interna de Prolog, mientras que si se lee el archivo dos veces, entonces se tendrá una copia doble de todas las cláusulas.

Sin embargo, si un archivo es releído entonces las cláusulas de todos los procedimientos en el archivo reemplazarán a cualquier cláusula existente anteriormente. La reconsulta es útil para indicarle a Prolog las correcciones que se realizan a los programas.

Regresar al Indice


1.3 Ingreso de las cláusulas a la terminal

Las cláusulas se puede ingresar directamente en la terminal pero esto es recomendado solamente cuando éstas no se necesitan permanentemente y cuando son pocas. Para ingresar cláusulas desde la terminal, se debe dar el comando especial: give the special command:

y el indicador "| " mostrara que el intérprete está ahora en el estado de espera de cláusulas o directivas. Para ingresar al nivel más alto del intérprete se deberá teclear Contro + Z (^Z). Este es el equivalente al fin de archivo de archivo temporal virtual llamado ‘user’

Regresar al Indice


1.4 Directivas: Preguntas y comandos

Las directivas pueden ser preguntas y/o comandos. Ambas pueden ser formas de dirigir al sistema para alcanzar alguna o algunas metas. En el siguiente ejemplo, la función de pertenencia a una lista se defina como sigue:

(Notese que las variables sin valor asignado se representan como "_".)

La sintáxis completa para una pregunta es "?-" seguida por una secuencia de metas, por ejemplo:

Al nivel más alto del intérprete (en el que el indicador es como este: "| ?- "), una pregunta se puede teclear abreviando el "?-" que de hecho ya está incluído en el indicador. Así, en el nivel más alto, una pregunta se vería de la siguiente manera:

Recuerde que los términos en Prolog deben terminar con el punto ".", por lo que el Prolog no ejecutará nada hasta que Usted haya tecleado este punto y un ENTER al final de la pregunta.

Si la meta que se ha especificado en la pregunta puede ser satisfecha, y si no hay variables a considerar como en este ejemplo, entonces el sistema responde:

yes

Y la ejecución de la pregunta ha terminado.

Si en la pregunta se incluyen variables, entonces el valor final de cada variable es desplegado (excepto para las variables anónimas). Así la pregunta:

Podría ser respondida como:

En este momento el intérprete estará esperando que el usuario introduzca un ENTER o un punto "." Seguido de un ENTER. Si se teclea solamente ENTER, termina la pregunta y el sistema responde "yes". Sin embargo, si se teclea ".", el sistema realiza un backtracking y busca soluciones alternativas. Si no hay soluciones alternativas entonces el sistema responde:

no

La salida para algunas preguntas como la que se muestra abajo, donde un número precede a un "_" significa un nombre generado por el sistema para una variable, por ejemplo:

En el caso de los comandos, son similares a las preguntas excepto porque:

Los comandos inician con el símbolo ":-" . A nivel alto del intérprete simplemente basta con iniciar con el indicador "| ?- ". Cualquier salida pretendida debe ser programada explícitamente, por ejemplo, en el comando:

Dirije al sistema para que verifique si el número 3 pertenece a la lista [1,2,3], y a que redirija la salida hacia la variable "ok" si así es. La ejecución de un comando termina cuando todas las metas en el comando se han ejecutado de manera exitosa. No se muestran soluciones alternativas. Si no se encuentra solución entonces el sistema indica:

como una advertencia.

El uso principal de los comandos (en oposición al uso de las preguntas) es permitir a los archivos el contener las directivas que llaman a varios procedimientos, para los cuales el usuario no requiere salida impresa. En estos casos solo se requiere llamar a los procedimientos por su efecto, por ejemplo, si no quiere tener interacción con el intérprete durante la lectura de un archivo. Un ejemplo muy útil es el uso de una directiva que consulte una lista completa de archivos.

Si un comando como este se encuentra contenido en el archivo 'myprog' entonces, teclear lo siguiente sería la forma más rápida para cargar el programa entero:

Cuando se interactúa al nivel más alto del intérprete de Prolog, la distinción entre comandos y preguntas es normalmente muy importante. A este nivel se teclean las preguntas en forma normal. Solo si se lee de un archivo, entonces para realizar varias metas se deben usar comandos, por ejemplo; una directiva en un archivo debe ser precedida por un ":-", de otra manera serían tratados como cláusulas.

Regresar al Indice


1.5 Errores de sintáxis

Los errores de sintaxis se detectan durante la lectura. Cada cláusula o directiva, o en general cualquier término leido de un archivo o de la terminal, que provoca una falla, es desplegado en la terminal tan pronto como es leído por el sistema. Una marca indica el punto en la cadena de símbolos en donde al parser ha fallando en su análisis, por ejemplo:

Implica que el parser muestre:

Si el operador "." No ha sido declarado como operado infijo.

Notese que no se muestran comentarios que especifiquen el tipo de error. Si usted tiene duda acerca de qué cláusula contiene el error, puede usar el predicado:

Para enlistar todas las cláusulas que han sido eficientemente leídas, por ejemplo:


1.6 Predicados no definidos.

El sistema puede ocasionalmente también darse cuenta de que se han llamado a predicados que no tienen cláusulas, el estado de esta facilidad de identificación puede ser:

- 'trace', que causa que este tipo de errores sean desplegados en la terminal y que el proceso de depuración muestre la última vez que ha ocurrido.

O,

- 'fail', que causa que estos predicados fallen (este es el estado por default)

El predicado evaluable:

unifica a OldState con el estado actual y coloca a State como Newstate. Este falla si los argumentos no son los apropiados. La depuración de predicados evaluables imprime el valor de este estado a lo largo de otras informaciones. Es importante notar que se lleva casi un 70% más de tiempo correr al intérprete en esta modalidad. Se espera que esta facilidad se pueda mejorar en el futuro.

Regresar al Indice


1.7 Ejecución de programas e interrupción de éstos.

La ejecución de un programa se incia cuando se le da al intérprete una directiva en la cual se continenen llamadas a uno de los procedimientos del programa.

Sólo cuando la ejecución de una directiva se ha realizado por completo es cuando el intérprete va por otra directiva. Sin embargo, uno puede interrumpir la ejecución normal de ésta al presionar ^C mientras el sistema está corriendo. Esta interrupción tiene el efecto de suspender la ejecución y se despliega el siguiente mensaje:

En este momento el intérprete acepta comando de una sola letra, que correspondan con ciertas acciones. Para ejecutar una acción simplemente se deberá teclear el carácter correpondiente (en minúsculas) seguido de un ENTER. Los posibles comandos son:

Notese que no es posible romper la ejecución directamente desde el código compilado, cada una de las opciones "a", "b" y "t" piden que el intérprete realice una acción, por lo que la acción se seguirá realizando hasta que el código compilado devuelva en mando al intérprete.

Note también que la opción ("a") no saca al usuario cuando esta en modo [user] es decir insertando cláusulas desde la terminal. Tiene que teclear ^Z para parar este proceso o teclear ("e") para poder salir de Prolog.

Si se trata de abortar un programa con ^C y accidentalmente se llegara al nivel Monitor, (quizá porque se apretó ^C demasiadas veces), deberá teclear CONTINUE para regresar a la interrupción ^C.

Regresar al Indice


1.8 Salida del intérprete

Para salir del intérprete y regresar al nivel monitor, deberá teclear ^Z a nivel alto del intérprete, o llamar al procedimiento "halt" (pre-cargado por default), o usar el comando "e" (exit) seguido de una interrupción ^C. ^Z es diferentes de los otros dos métodos de salida, ya que imprime algunas estadísticas. Es posible regresar usando el comando del Monitor CONTINUE después de ^Z, si se arrepiente de haber querido salir.

Regresar al Indice


1.9 Ejecuciones anidadas, Break y Abort.

El sistema prolog integra una manera de suspender la ejecución de un programa e introducir nuevas directivas o cambiar metas a nivel alto del intérprete. Esto se logra si se llama a un predicado evaluable Break o tecleando "b" despues de una interrupción con ^C ( ver sección 1.7).

Esto causa que el intérprete suspenda la ejecución inmediatamente, a lo que el interprete contestará

Que quiere decir que se ha parado desde el nivel Break y que se pueden introducir preguntas de la misma manera en que se había hecho desde el nivel alto del intérprete.

El intérprete indica el nivel Break en el que el sistema se encuentra (por ejemplo, en Breaks anidados), imprimiendo el nivel de Break después de un yes o un no final a las preguntas. Por ejemplo, a nivel Break 2, se podría ver la respuesta así: uld look like:

Un ^Z cierra la interrupción que se había realizado y se reaundan las tareas. Una ejecución suspendida se puede abortar usando la directiva:

Dentro de un break.

En este caso no se necesitaa un ^Z para cerrar el break; Todos los niveles break se descartarán y se llega automáticamente al nivel más alto del intérprete.

Regresar al Indice


1.10 Guardado y restauración de estados de programas

Una vez que el programa ha sido leído, el intérprete tendrá disponible toda la información que sea necesaria para su ejecución, esta información se llama estado de programa.

El estado de un programa se puede grabar en disco para ejecuciones posteriores. Para guardar un programa en un archivo, realice la siguiente directiva:

Este predicado se puede llamar en cualquier momento, por ejemplo, puede ser muy útil a fin de guardar los estados de un programa inmediatos.

Cuando el programa ha sido guardado en un archivo, la siguiente directiva recuperaría el estado de un programa:

Después de esta ejecución el programa entonces podrá ser regresado exactamente al mismo punto en que se dejó al momento de salvarlo la ´´ultima vez.

Así, al ejecutarse esta orden con el mensaje propio del usuario, se obtendrá el mensaje "programa restaurado", por ejemplo.

Notese que cuando una versión de Prolog nueva se instala, todos los programas grabados se vuelven obsoletos.

Regresar al Indice


1.11 Inicialización

Cuando prolog inicia busca un archivo llamado 'prolog.bin' en la ruta default del usuario. Si se encuentra este archivo entonces se asume que el estado de un programa se ha restaurado. El efecto es el mismo que si se hubiera tecleado:

Si no se encuentra este archivo, entonces se busca en forma similar, el archivo 'prolog.ini'. Si se encuentra este archivo, sería lo mismo que haber tecleado:

La idea de este archivo es que el usuario pueda tener aquí los procedimientos y directivas que se usan usualmente de manera que no se tengan que teclear cada vez que se necesiten.

El archivo 'prolog.bin' parece ser que es útil cuando se usa con el plsys(run(_,_)) que permite correr otros programas desde dentro de Prolog. Esta facilidad permite también regresar al mismo punto si se corrió prolog desde otros programas. En este caso, el predicado evaluable save/2 debe ser usado paara salvar el estado del programa dentro de 'prolog.bin'.

Regresar al Indice


1.12 Entrada a prolog

Cuando se entra a prolog directamente en una interacción con la terminal, se escribe autoimaticamente el archivo 'prolog.log' en modo append. Esto es, si ya existe el archivo, en el directorio del usuario, entonces la nueva información se añade, si no es así, y el archivo no existe, entonces el archivo se crea.

Sugerencias o comentarios: e-mail: Lopezcua@proton.ucting.udg.mx


CAPÍTULO 2 DEPURACIÓN

Este capítulo describe las facilidades de depuración que están disponibles en el intérprete de Prolog, el propósito de estas facilidades es proveer información concerniente al control del flujo del programa, las principales facilidades del paquete de depuración son las siguientes:


2.1 El modelo de flujo del procedimiento Box Control

Durante la depuración de un programa se imprimen una secuencia de metas defectuosas a fin de mostrar el estado que el programa ha alcanzado durante esta ejecución. Sin embargo, para poder entender qué es lo que ocurre, es necesrio entender primero cuándo y por que el interprete imprime las metas. Como en otros lenguajes de programación, existen puntos principales de interés como los procedimientos de entrada y regreso, pero en Prolog, existe el backtracking que tiene una complejidad adicional. Una de las principales confusiones para los novatos es que los programadores tiene que enfrentar la cuestión de qué es lo que está ocurriendo en el momento en que una meta falla y el sistema inicia repentinamente el backtracking. El modelo Box de Prolog permite que el flujo del programa posibilite identificar cualquier punto en la ejecución en términos de localización en el texto del programa. Este modelo provee las bases para la depuración de un programa.

Examinando a fondo un procedimiento se tiene:

*--------------------------------------* Call | | Exit ---------> + descendant(X,Y) :- offspring(X,Y). + ---------> | | | descendant(X,Z) :- | <--------- + offspring(X,Y), descendant(Y,Z). + <--------- Fail | | Redo *--------------------------------------*

La primer cláusula establece que Y es descendiente de X si Y es resulatdo de X, y la segunda cláusula establece que Z es descendiente de X si Y lo es de X y si Z es descendiente de Y. En el diagrama, una caja se ha dibujada al rededor de todo el procedimiento y se han estipulado flechas para establecer el flujo de control con entradas y salidas de esta caja. Existen cuatro flechas por examinar durante el flujo:

En términos de este modelo, la información que nosotros obtenemos acerca de esta caja de procedimiento, es sólo acerca del flujo de control que se da a lo largo de estos cuatro puertos. Esto significa que a este nivel no importa con cual cláusula se hace matching y como se da satisfacción a las submetas, sino más bien como quisieramos conocer la meta inicial y la final tienen efecto.

Note que la caja que se ha dibujado para cercar el procedimiento tiene que ser vista como una caja de invocación, esto es, que hay una caja diferente para cada procedimiento, obviamente con algunos procesos recurrentes en todos los procedimiento, con diferentes llamadas y salidas en el flujo de control, pero estas para diferentes invocaciones. Por ello se les de una entero único de identificación a cada una de estas cajas.

Regresar al Indice


2.2 Predicados básicos de depuración.

El intérprete proporciona un rango de predicados evaluables para el control de las facilidades de evaluación, lo más basicos son los siguientes:

Regresar al Indice


2.3 Rastreo

El siguiente comando evaluable puede ser usado a fin de tener un control más efectivo del programa que se va a depurar.

o cualquiera otra combinación de estos y de los puertos descritos en la sección 4.12

El valor inicial del modo es "half", se puede cambiar si se modofica el archivo "prolog.ini".

Regresar al Indice


2.4 Spy-points

Para programas extensos o de cualquier extensión es practicamente imposible que el programador siga paso a paso todo lo que esta ocurriendo en cada módulo o en cada meta o submeta. Es por ello que se posibilita la tarea de formular puntos espías que permiten mantener un control exacto solamente en puntos clave elejidos por el usuario para el control total del programa y su curso.

La selección del modo que se realice no tiene ingerencia alguna en los puntos espías que se han elegido por parte del usuario.

Los puntos espías son conjuntos de establecimientos de variables y de predicados evaluables o también de operadores estándares.

spy X Coloca en On el modo de los puntos espías, se puede usar en cualquier predicado o punto del programa en una oración evaluable o en una directiva establecida previamente.

nospy X Funciona de manera similar a spy X pero en esta caso x es un conjunto de puntos espías definidos previamente y removidos.

Regresar al Indice


2.5 Formato de los mensaje de depuración.

Se puede ver el formato que tienen exactamente y a profundidad los mensajes de error, esto permitira realizar de una manera más eficiente las tareas de depuración de programas al posibilitar el conocimiento de los simbolos usados en cada mensaje como este

"**" indica que es un spy-point. Si este punto no es un conjunto de puntos espías predefinidos entonces el puntero se convierte en un ">". Que da las siguientes posibles combinaciones:

Notese que en esta caso las acciones son rastreadas a fin de mantener un centro exacto en el depurado durante el establecimiento de este tipo de mensajes.

Regresar al Indice


2.6 Opciones disponibles durante la depuración

Esta sección describe las opciones particulares que estan disponibles cuando el sistema te muestra despues de algun mensaje de depuracion. Todas las opciones son una letra como nemonico, y algunas pueden ser opcionales seguidas de un entero decimal. Algunas opciones solo requieren el terminador.

La unica opcion que se hace necesaria de recordar es "h" y un ENTER, ya que es la función que despliegará a las siguientes funciones:

Las primeras tres opciones son decisiones de control basicas ya que son las más frecuentemente usadas, cada una puede ser llamada con una sola tecla c <cr> Creep

Causa que el intérprete se vaya de un solo paso al siguiente puerto e imprima un mensaje. Si el puerto esta atascado se le pedira al usuario acciones posteriores, de otra manera el procedimiento continuará hasta terminar en la terminal.

Causa que el intérprete regrese ala ejecución del programa, solo para cuando un punto espía se ha encontrado, o cuando el programa termina

Es válido solamente en el puerto Redo, brinca sobre una ejecución entera o un procedimiento. El uso de esta directiva de compilación garantiza que el control será devuelto a la caja de control despues de la ejecución dentro de la caja. Cuando se da un cuasibrinco o cuasiskip en donde no se ignoran los puntos espías, la opción "t" después de un ^C desabilitará las máscaras.

Es como skip, excepto porque este brinco no oculta a los puntos espías para la depuración. Si existe un punto espía en la ejecución de una meta, entonces el control regresa al punto en donde la acción se debe realizar.

Da la posibilidad de hacer un fail rápio, llevando al programa al punto real de decisión anterior. Cuando el usuario sabe que algo hará fail, puede anticipar el punto de decisión y verificarlo rapidamente sin tener que repetir el proceso completo. Si se da una secuencia de Fails seguidos de una secuencia de Redos (o si la secuencia está vacía) se tienen mensajes estándares (como los mostrados anteriormente) excepto para los primeros dos caracteres donde será "=>". Cuando se llama a la acción exit, la operación de salida ocurriá normalmente.

Se puede usar en cualquiera de los cuatro puertos, aunque el puerto call no tenga efecto en realidad. Esto permite reestablecer la invocación cuando por ejemplo, el usuario se ha dado cuenta de que ha obtenido resultados algo raros. El estado de la ejecución es exactamente el mismo que el alcanzado durante la ejecución normal original. Si se proporciona un entero con el comando retry entonces se tomará como una especificación de que el sistema trate de invocar al puerto y no a la caja actual, por supuesto que a un puerto designado por el usuario. Desafortunadamente el proceso no puede ser garantizado. Se puede suplir con cuts (!) al interior del programa. Un mensaje de error "[ ** JUMP ** ]" se despliegará en la terminal para indicar que es lo que ha ocurrido.

es similar al retry ya que transfiere el contro al puerto fail desde la caja actual, en una posición en donde se estpá cercado a hacer un backtracking

Puede ser llamado en una salida y forzar a mover al puesrto Redo

Causa que se aborte la ejecución actual. Todas las ejecuciones se mantienen hasta que el usuario se asegura de que no las necesita conforme sube al mas alto nivel del intérprete (es equivalente al predicado evaluable abort)

Causa una salida irreversible del sistema de prolog, de regreso al Monitor (esta directiva es equivalente a Halt)

Despliega la tabla de opciones marcada arriba

Reimprime la meta actual usando print

Escribe la meta actual en la terminal usando write. Esto puede ser muy útil cuando la lista temporal de rutinas no hace lo que se espera de ella

Despliega la meta en turno, usando display (ver Write arriba).

Provee al usuario de una lista de las metas o submetas que ya se han cumplido en la ejecución de un programa, el orden se da en forma jerarquica hacia arriba de la secuencia que ha sido llamada. Usa los ancestros de cada predicado evaluable (ver pág 42). Si se proporciona un entero con esta directiva entonces se despliegan n antecesores desde el punto en que el usuario ha dado la directiva.

Permite llamar arbitrariamente a metas de Prolog, es un break de un solo paso muy efectivo, (ver mas adelante). El mensaje inicial "| :- " saldrá en la terminal y el comando entonces se lee desde la terminal y se ejecuta como si el usuario estuviera en el nivel más alto.

Llama al predicado evaluable break, pone al interprete al nivel mas alto con la ejecución aparte del modulo actual, cuando se finaliza el modo break (^Z) el sistema pregunta en que punto se hizo el rompimiento, y una nueva ejecución se separa de la suspendida, los números de invocación comienzan a partir de 1 desde su invocación.

[ Consult user Permite insertar clausulas y regresar a donde se estaba, es lo mismo que usar "@" seguida de "[user].".

Desactiva el modo debug, lo pone en Off, es la forma correcta de apagar el debug desde el modo de rastreo. No se puede usar "@" o "b" porque siempre activa el debug desde el regreso.

Regresar al Indice


2.7 Consultar de nuevo durante la depuración.

Es posible y a veces es útil reconsultar o releer un archivo a medias de la ejecución de un programa. Sin embargo, esto puede ocasionar que el sistema funcione de una manera impredecible debido a las siguientes circunstancias: un procedimiento se ha ejecutado con éxito, se ha redefinido por una consulta y después se ha reactivado por un backtracking. Cuendo el backtracking ocurre, todas las clausulas nuevas apaarecerán en el intérprete como posibilidades de alternativa de solución aún cuando se hayan usado ya clausulas o predicados exactamente iguales, así grandes cantidades de procedimientos no deseados ocasionarían backtracking. Este problema se evita si se hace el consult desde el pueto del procedimiento que será redefinido.

Sugerencias o comentarios: e-mail: Lopezcua@proton.ucting.udg.mx


CAPITULO 3. COMPILACIÓN

El compilador Prolog DECsystem-10 produce código más compacto y eficiente, el cual funciona de 10 a 20 veces más rápido que el interprete de código y requiere mucho menos almacenamiento en tiempo de ejecución. Los programas compilados con Prolog, son comparados en eficiencia, con programas desarrollados en LISP ( con el compilador LISP DECsystem-10 ), para realizar las mismas funciones. En contra de esto, la desventaja es que la compilación es varias veces más lenta que la "consulta" y mucha de la ayuda proporcionada por el depurador, como el seguimiento, no es aplicable al código compilado.

Regresar al Indice


3.1 Llamando al Compilador.

Para compilar el programa se usa la siguiente sentencia :

donde "Archivos" es cualquier nombre de archivo ( incluyendo el archivo ‘user’ ), o una lista de los nombres de los archivos que se desean compilar. Con esta instrucción, los procedimientos contenidos en dichos archivos serán compilados. A continuación se muestra un ejemplo con varios archivos :

Exteriormente, el efecto de "compile" es mucho muy parecido al de "reconsult". Si las cláusulas para algunos predicados aparecen en más de un archivo, el juego posterior de dichas cláusulas, sobre-escribe el anterior. La división del programa en archivos separados no implica ninguna estructura modular ( ningún procedimiento compilado puede llamar a cualquier otro ).

Regresar al Indice


3.2 Declaraciones Públicas.

Para hacer que un procedimiento compilado sea accesible por el interprete de código ( incluyendo directivas ) es necesario declarar dicho procedimiento como público, lo cual se realiza con el comando siguiente del compilador :

donde "Predicates" es una especificación del predicado, en la forma : Nombre / Arity , o también puede ser una conjunción de especificaciones semejantes, por ejemplo :

Las declaraciones públicas pueden aparecer en cualquier parte dentro de un archivo compilado; no es necesario que las declaraciones públicas procedan a el correspondiente procedimiento, ni tampoco que estén dentro del mismo archivo.

Regresar al Indice


3.3 Mezclando Código Compilado y Código Interpretado.

Para predicados públicos un procedimiento compilado sobre-escribe cualquier versión interpretada previa ( cf. reconsult ). De la misma forma una reconsulta subsecuente de la versión interpretada sobre-escribirá la versión compilada.

Es posible tener un procedimiento compilado con el mismo nombre y arity, así como muchos y diferentes procedimientos interpretados. Suponiendo que el procedimiento compilado no fue declarado para ser público, los dos procedimientos nunca intervendrán el uno con el otro, es decir, el código compilado utilizará la versión compilada mientras que el interpretador de código usará la versión interpretada.

Cuando una versión compilado se hace presente y sobre-escribe un procedimiento interpretado, éste último es reemplazado por la cláusula :

donde "P" es el objetivo más general para el predicado y "encore" es un predicado evaluable estándar ( análogo a "call" ), por medio del cual son accesibles todos los procedimientos compilados para los predicados públicos.

Hay dos formas en que el código compilado puede utilizar procedimientos interpretados :

Primero compilamos el siguiente archivo: :- public f/1, g/1.

No hay cláusulas para h/1. Después consultamos lo siguiente :

Ahora, si nosotros llamamos a " f "obtendremos :

Esto es, nosotros usamos tanto las cláusulas compiladas, como las interpretadas para " f ". De cualquier modo si llamamos a " g " :

podemos observar que " g " solo llama la versión compilada de " f ", así que la solución : X = b , no es encontrada. La segunda cláusula para " g " llama a " h ", y como no hay cláusulas compiladas para " h " esta llamada es pasada al interprete, el cual encuentra una solución : X = c.

Regresar al Indice


3.4 Declaraciones de Modo.

Cuando un programa va a ser compilado es conveniente incluir declaraciones de modo, las cuales informan al compilador que ciertos procedimientos serán usados en forma restringida, es decir, que algunos argumentos en la llamada siempre serán "entrada", mientras que otros siempre serán "salida". Esta información habilita al compilador para ser capaz de generar código más compacto y hacer un mejor uso del almacenamiento en tiempo de ejecución. Las declaraciones de modo también ayudan a que otras personas comprendan la operación del programa.

Una declaración de modo es indicada con una directiva del compilador de la forma :

donde "P" es el nombre de un procedimiento y "M" especifica los "modos" de sus argumentos. M consiste de cierto número de "elementos de modo" ( elementos que indican el modo deseado para los argumentos ), separados por comas, una para cada posición de los argumentos del predicado interesado. Los elementos de modo pueden ser de cualquiera de los 3 tipos siguientes :

es equivalente a omitir completamente la declaración.

Por ejemplo, si tenemos un procedimiento llamado "encadenar" y los dos argumentos primeros, siempre serán "entradas", podemos dar la siguiente declaración de modo :

En el caso de que en el procedimiento anterior el tercer argumento siempre será "salida", podemos reforzar la declaración de modo como sigue :

Además, esta permitido combinar varias declaraciones de modo en un solo comando, por ejemplo :

Para que una declaración de modo tenga efecto debe aparecer antes de las cláusulas del procedimiento correspondiente. Cuando una declaración de modo es violada por una llamada a un procedimiento, la forma precisa como reacciona depende de el objetivo y la cabecera de la cláusula. La llamada puede ser realizada con éxito como si no hubiera una declaración de modo o puede causar un mensaje de error y fracasar. Como el resultado preciso depende de los cambios en las versiones futuras del sistema, el usuario debió asumir que todas las declaraciones de modo que son violadas causaran un mensaje de error.

Las declaraciones de modo son ignoradas por el interprete.

Regresar al Indice


3.5 Indexación.

En contraste con el interprete, las cláusulas de un procedimiento compilado son indexadas de acuerdo al "functor" principal del primer argumento especificado en la cabecera de la cláusula. Esto significa que el subconjunto de cláusulas, son emparejadas con un determinado objetivo, hasta que el primer paso de la unificación interesada, sea hallada muy rápidamente, prácticamente en un tiempo constante ( un tiempo independiente del número de cláusulas ). Esto puede ser muy importante donde hay un gran número de cláusulas en un procedimiento.

La indexación también mejora la capacidad del sistema de Prolog para detectar la determinacia, la cual es importante en la conservación del espacio de trabajo.

Regresar al Indice


3.6 Optimización de la cola de Recursión.

El compilador incorpora "Optimización de la cola de recursión" para mejorar la velocidad y la eficiencia del espacio de procedimientos determinados. Cuando la ejecución alcanza el último objetivo en una cláusula que pertenece a un procedimiento, y provee que no hay puntos de retroseguimiento restantes, todo el espacio de trabajo asignado a los procedimientos locales es reclamado ANTES de finalizar la llamada y cualquier estructura que fue creada es eliminada. Esto significa que el programa puede realizar varias recursiones sin necesidad de exceder el limite en el espacio.

Por ejemplo :

donde "transform" es un procedimiento determinado, puede continuarse ejecutando indefinidamente, previendo que cada estructura individual "State", no sea demasiado larga. El procedimiento "cycle" es equivalente a un lazo iterativo de in lenguaje convencional.

Para lograr la ventaja de la optimización de la cola recursiva, debemos asegurarnos que Prolog pueda reconocer que el procedimiento es determinado en el punto donde la llamada recursiva toma lugar. Dicho en otra forma, el sistema debe ser capaz de detectar que no hay otras soluciones que deben ser encontradas para el objetivo actual, mediante subsecuente retroseguimiento. En general esto esta envuelto en la indexación del compilador Prolog DEC-10 y / o el uso de corte.

Regresar al Indice


3.7 Limitaciones Practicas.

Algunas consideraciones que debemos tomar en cuenta son :

Se puede notar que hay una pausa despreciable en el inicio y terminación de la compilación. Esto se debe a que el compilador reside en una capa separada, la cual debe ser intercambiada.

Sugerencias o comentarios: e-mail: Lopezcua@proton.ucting.udg.mx