1 Sintaxis Bsica de VISUAL PROLOG 1.1 Aritmtica de VISUAL PROLOG 2 Datos simples y Estructuras de Datos: DOMINIOS [2.1 OBJETOS COMPUESTOS] [2.2 RBOLES] [2.3 LISTAS] [2.4 MATRICES] 3 Bibliografa Sintaxis Bsica de VISUAL PROLOG Hemos visto ya un buen nmero de convenciones que debemos utilizar para escribir programas en Prolog. La ltima parte de este tema la dedicaremos a conocer detalladamente las reglas sintcticas que hemos de seguir para que nuestras bases de conocimientos sean reconocidas por Visual Prolog. Como ya hemos estudiado, un programa Prolog no es ms que la especificacin de una base de conocimientos lgica con las caractersticas siguientes: Consta de una secuencia de oraciones, todas ellas verdaderas, que expresan un conjunto de realidades sobre los objetos del mundo representado, as como sobre sus relaciones. Todas las variables tienen cuantificacin universal implcita y cuando las variables aparecen en oraciones distintas se consideran tambin distintas. Se aceptan nicamente oraciones en forma de Clusula de Horn, es decir, las oraciones son atmicas, o bien una implicacin con un antecedente no negado y un consecuente generalmente "expresiones" separados por comas o por puntos y comas. Las comas significan conjuncin y los puntos y comas significan disyuncin. En vez de utilizar antecedentes negados en sus implicaciones, en Prolog se emplea un operador de negacin basado en el fallo: una meta no P se considera demostrada si el sistema no logra demostrar P. [NDICE] Aritmtica de VISUAL PROLOG Las expresiones aritmticas en Visual Prolog se componen de operandos (nmeros y variables), operadores (+, -, *, /, div, y mod) y parntesis: A = 1 + 6 / (11 + 3) * Z. Ver Tabla 1. Los nmeros "0x" o "0o" significan hexadecimal y octal respectivamente: 0xFFF = 4095; 86 = 0o112 + 12. Pgina 1 de 11 NDICE 30/10/2014 http://www.uhu.es/nieves.pavon/pprogramacion/temario/tema2/tema2.html El valor de una expresin se puede calcular si todas las variables estn unificadas en el momento de la evaluacin. El clculo ocurre entonces en un orden determinado por la prioridad de los operadores aritmticos. Los operadores de mayor prioridad son evaluados primero. Ver Tabla 2. [NDICE] Operaciones Operando 1 Operador Operando 2 Resultado entero +, -, * entero entero real +, -, * entero real entero +, -, * real real real +, -, * real real entero real / entero real real entero div entero entero entero mod entero entero Tabla 1 [NDICE] Orden de evaluacin Si la expresin contiene subexpresiones entre parntesis, las subexpresiones se evalan primero. Si la expresin contiene multiplicacin o divisin, estas operaciones son realizadas trabajando de izquierda a derecha a travs de la expresin. Las operaciones de suma y resta son llevadas a cabo de izquierda a derecha tambin. En el orden de evaluacin se tiene en cuenta, lgicamente, la precedencia de los operadores. Operador Prioridad + - 1 * / mod div 2 - + (unario 3 Tabla 2 [NDICE] Funciones y predicados Visual Prolog posee una gran cantidad de funciones y predicados matemticos para realizar las ms variadas operaciones. La lista completa se ofrece en la Tabla 3. Nombre Descripcin X mod Y Resto de X dividido entre Y. Pgina 2 de 11 NDICE 30/10/2014 http://www.uhu.es/nieves.pavon/pprogramacion/temario/tema2/tema2.html X div Y Cociente de X dividido entre Y. abs(X) Valor absoluto de X. cos(X) Coseno de X. sin(X) Seno de X. tan(X) Tangente de X. arctan(X) Arcotangente de X. exp(X) e elevado al valor almacenado en X. (Exponencial). ln(X) Logaritmo neperiano de X. log(X) Logaritmo en base 10 de X. sqrt(X) Raz cuadrada de X. random(X) Almacena en X un nmero aleatorio real entre 0 y 1. random(X, Y) Almacena en Y un nmero aleatorio en el intervalo 0 <= Y < X. round(X) Valor redondeado de X. El resultado es un nmero real. trunc(X) Valor truncado de X. El resultado es un nmero real. val(domain,X) Conversin explcita entre dominios numricos. Tabla 3 [NDICE] Comparaciones En Visual Prolog podemos comparar expresiones aritmticas, caracteres, cadenas de caracteres y smbolos. Las comparaciones de este tipo se realizan a travs de operadores relacionales. Ver Tabla 4. Smbolo Relacin < menor que <= menor o igual que = igual que > mayor que >= mayor o igual que <> o >< distinto Tabla 4 [NDICE] Comparacin de caracteres, cadenas de caracteres y smbolos Adems de las expresiones numricas, podemos comparar caracteres, cadenas y smbolos: 'a' < 'b'; "antony" > "antonia" y P1 = peter, P2 = sally, P1 > P2. Pgina 3 de 11 NDICE 30/10/2014 http://www.uhu.es/nieves.pavon/pprogramacion/temario/tema2/tema2.html Caracteres: Visual Prolog convierta la comparacin 'a' < 'b' a su expresin aritmtica correspondiente 97 < 98, usando el cdigo ASCII correspondiente a cada carcter. Cadenas de caracteres: Cuando se comparan dos cadenas o smbolos, la comparacin se realiza carcter a carcter en sus correspondientes posiciones. El resultado es el mismo que se consigue comparando el carcter inicial a menos que los dos sean iguales en cuyo caso se pasa al siguiente. Cuando se encuentran dos caracteres iguales, el proceso de comparacin termina y se produce el resultado. Smbolos: No pueden ser comparados directamente debido a la sintaxis. Primero deben ser unificados a variables o escritos como cadenas de caracteres. [NDICE] Datos simples y Estructuras de Datos: DOMINIOS En cualquier lenguaje de programacin necesitamos representar datos complejos. Podemos definir dato complejo como la agrupacin homognea o heterognea de otros datos que a su vez pueden ser tambin complejos o simples. As pues, a partir de esta definicin, los datos se pueden organizar de mltiples formas que ya conocemos: vectores, registros, listas, rboles, grafos, etc. Un programa en Visual Prolog utiliza distintas secciones para las declaraciones de tipos o dominios con el fin de crear estructuras complejas de datos (DOMAINS), predicados (PREDICATES), reglas y hechos que forman los predicados (CLAUSES) y metas (GOAL). En la seccin de predicados se definen las cabeceras de los predicados que vamos a utilizar en nuestros programas, es decir el nombre del predicado y el dominio o tipo de los argumentos del mismo. En la seccin de clusulas se define la implementacin de cada predicado declarado en PREDICATES. En la seccin GOAL se establece la meta principal del programa. Centrmonos ahora en la seccin DOMAINS y en cmo crear estructuras complejas: objetos compuestos, rboles, listas y matrices. [NDICE] OBJETOS COMPUESTOS Los objetos compuestos estn formados por un functor y un conjunto de argumentos. Por ejemplo, cuadro (NS, Autor, Estilo, Dimensiones) representa una estructura que almacena los datos ms relevantes para describir este tipo de obra de arte. El nombre cuadro es el functor y los elementos entre parntesis son los argumentos del objeto compuesto. Los argumentos (campos), de un objeto compuesto pueden ser datos simples o datos complejos. Para definir objetos compuestos es necesario introducirnos en el concepto de DOMINIO o DOMAINS. Como veremos en la seccin de prcticas, la seccin DOMAINS de un programa en Visual Prolog agrupa los dominios (tipos), no estndares en el sistema. Definir un dominio no es ms que establecer qu forma tendrn los objetos que pertenecen a dicho dominio o tipo, por ejemplo, para el caso del cuadro, el dominio sera as: un_cuadro= cuadro(INTEGER, STRING, STRING, STRING) Como hemos dicho, los argumentos de un objeto compuesto pueden ser complejos: un_comprador= comprador(STRING, un_cuadro) Pgina 4 de 11 NDICE 30/10/2014 http://www.uhu.es/nieves.pavon/pprogramacion/temario/tema2/tema2.html El dominio o tipo del ejemplo define a un comprador de un cuadro. Los objetos compuestos de este tipo almacenan una cadena que puede representar el DNI y el cuadro que posee. Veamos varios objetos de tipo un_comprador: comprador("111111111", cuadro(1239, "Martn Jimnez", "leo", "39x23")). comprador("122111111", cuadro(1449, "Surez Jimnez", "acuarela", "130x50")). comprador("111133331", cuadro(2232, "Martn Prez", "carboncillo", "100x100")). [NDICE] RBOLES Un rbol es una estructura con una definicin puramente recursiva, ya que se puede considerar como el elemento raz cuyos hijos son, a su vez, rboles. Si el rbol tiene nicamente dos hijos se denomina rbol binario. Este modelo especfico de rbol se utiliza mucho para resolver gran cantidad de problemas en aspectos de programacin. Un rbol se puede considerar, a su vez, un caso particular de grafo, donde todos los caminos son acclicos. La Figura 1 muestra un ejemplo de rbol. Figura 1 Ejemplo de rbol Muchos problemas de Inteligencia Artificial donde interviene el concepto de bsqueda se resuelven mediante la implementacin de rboles. Los rboles de juego o los utilizados en la resolucin de problemas relacionados con el procesamiento de lenguaje natural son casos muy concretos y descriptivos. Por lo tanto, podemos notar que el manejo eficiente de estas estructuras es sumamente importante para conseguir programas de calidad en este mbito de la Ciencia. Ya vimos que Prolog es un lenguaje que se adapta adecuadamente a este tipo de problemas. De hecho la tcnica de resolucin que utiliza Prolog se basa en la construccin de un rbol de bsqueda de soluciones, luego podemos concluir que el conocimiento de esta estructura es clave para este tipo de metodologa declarativa. Como en cualquier lenguaje, lo que necesitamos saber es la forma de declarar el rbol, ya que su implementacin se puede realizar de muchas formas, por ejemplo, aunque una lista es un caso particular de Pgina 5 de 11 NDICE 30/10/2014 http://www.uhu.es/nieves.pavon/pprogramacion/temario/tema2/tema2.html rbol, un rbol se puede representar a travs de listas, aunque en el caso de Visual Prolog, estudiaremos la construccin de rboles utilizando objetos compuestos recursivos. Dado que un rbol est formado por la raz y un conjunto de hijos, podemos representarlo utilizando la siguiente notacin: oracin (sujeto (artculo (el), sustantivo (hombre)), predicado (verbo (come), CD (pan))) El rbol generado se muestra en la Figura 2. Figura 2 rbol de anlisis de una frase en espaol Como se observa, el uso de un predicado con dos argumentos en el caso de rbol binario o N argumentos en el caso de rbol N-ario es una forma sencilla de representar un rbol. Mediante objetos compuestos recursivos del tipo arbol(nodo, hijoizq, hijoder), donde hijoizq e hijoder son tambin rboles, podemos representar un rbol binario. El rbol vaco se representa a travs del hecho vacio: arbol(1,arbol(2,arbol(4,vacio,vacio),arbol(5,vacio,vacio)),arbol(3,vacio,vacio)) En la seccin DOMAINS podemos crear un tipo rbol de enteros del modo siguiente: mi_arbol= arbol(INTEGER, mi_arbol, mi_arbol); vacio Operaciones con rboles representados mediante objetos compuestos recursivos domains arbol= nodo(integer, arbol, arbol); vacio lista= integer* predicates concatenar(lista, lista, lista) preorden(arbol, lista) inorden(arbol, lista) postorden(arbol, lista) Pgina 6 de 11 NDICE 30/10/2014 http://www.uhu.es/nieves.pavon/pprogramacion/temario/tema2/tema2.html clauses concatenar([],[],[]):-!. concatenar([],L2,L2):-!. concatenar(L1,[],L1):-!. concatenar([X|Y],L2,[X|Aux]):-concatenar(Y,L2,Aux). preorden(vacio,[]):-!. preorden(nodo(X,Izq,Der),[X|L]):-preorden(Izq,L1), preorden(Der,L2), concatenar(L1,L2,L). inorden(vacio,[]):-!. inorden(nodo(X,Izq,Der),L):-inorden(Izq,L1), inorden(Der,L2), concatenar(L1,[X|L2],L). postorden(vacio,[]):-!. postorden(nodo(X,Izq,Der),L):-postorden(Izq,L1), postorden(Der,L2), concatenar(L1,L2,L3), concatenar(L3,[X],L). goal inorden(nodo(1,nodo(2,nodo(4,vacio,vacio),nodo(5,vacio,vacio)),nodo(3,vacio,vacio)), L1), preorden(nodo(1,nodo(2,nodo(4,vacio,vacio),nodo(5,vacio,vacio)),nodo(3,vacio,vacio)), L2), postorden(nodo(1,nodo(2,nodo(4,vacio,vacio),nodo(5,vacio,vacio)),nodo(3,vacio,vacio)), L3). [NDICE] LISTAS Una lista se puede considerar como un caso particular de rbol del modo que se muestra en la Figura 3. Figura 3 Lista implementada en forma de rbol A su vez, una lista se puede considerar de forma recursiva. Es decir, siempre est formada por un elemento seguido de otra lista (ver Figura 4). Cuando la lista tienen un slo elemento podemos considerar que est formada por dicho elemento y la lista vaca. Esta definicin es muy interesante, ya que su conocimiento nos permitir llevar a cabo todos las operaciones que se pueden realizar sobre las listas con poco esfuerzo. Pgina 7 de 11 NDICE 30/10/2014 http://www.uhu.es/nieves.pavon/pprogramacion/temario/tema2/tema2.html Figura 4 Definicin recursiva de una lista Hemos de recordar que en Prolog no existen estructuras para realizar bucles luego todo los algoritmos que representemos se definirn de forma recursiva. El hecho de que la implementacin de la lista sea tambin recursiva facilita la construccin de operaciones sobre la misma. Es necesario comprender este tipo de estructura para construir algoritmos eficientes. La mayor parte de las operaciones que se realizan sobre una lista implica un recorrido de la misma, luego hemos de centrarnos en conocer cmo se lleva a cabo este algoritmo utilizando tcnicas de recursividad. Una lista se puede especificar en un predicado o en un objetivo a travs de: una constante: [a, b, c, 1, pepe] una variable: L la estructura [Cabeza|Cola] que almacenar el primer elemento en la variable Cabeza y el resto en la variable Cola. Las listas pueden ser homogneas o heterogneas, es decir, almacenar elementos del mismo tipo, o elementos de distinto tipo. Para definir un tipo de lista en particular es necesario declararla en la seccin DOMAINS. lista= elementos* (lista de una dimensin) lista2= elementos** (lista de dos dimensiones) lista3= elementos*** (lista de tres dimensiones)... Es interesante observar la sintaxis de definicin de una lista: elementos representa el dominio o tipo de los elementos que componen la lista. El tipo elementos puede representar un dominio simple, es decir, slo un tipo de elementos se corresponde con dicho dominio o un dominio complejo, donde varios tipos de elementos se corresponden con dicho dominio. Por ejemplo, una lista homognea de elementos simples estara definida como: lista= integer* Una lista heterognea de elementos estara definida como: listaenteros=integer* Pgina 8 de 11 NDICE 30/10/2014 http://www.uhu.es/nieves.pavon/pprogramacion/temario/tema2/tema2.html elementos= i(integer); s(symbol); c(char); le(listaenteros) lista= elementos* Ejemplo: domains listaenteros= integer* elementos= i(integer); c(char); s(symbol); le(listaenteros) lista= elementos* predicates recorrer(lista) clauses recorrer([]):-!. recorrer([X|Y]):-write(X), nl, recorrer(Y). goal recorrer([i(1),c('a'),s(pepe),i(5),c('b'),le([1,2,3])]). Se observa que la lista puede contener cuatro tipo de elementos distintos: enteros, caracteres, smbolos y listas de enteros. En la seccin de declaracin del dominio o tipo elementos no podemos escribir: elementos= integer; char; symbol; listaenteros para expresar que dicho dominio agrupa a cuatro tipos de elementos distintos sino que la sintaxis a utilizar es aquella que representa que elementos agrupa a cuatro tipos de objetos compuestos distintos. El resultado de la ejecucin de la meta es el siguiente: i(1) c('a') s("pepe") i(5) c('b') le([1,2,3]) yes Las operaciones tpicas que se pueden realizar sobre listas son: la insercin de elementos al principio, al final, en orden; borrado, bsqueda de elementos, recorrido, eliminacin de duplicados y, en general, todas las de las que se pueden realizar sobre conjuntos de elementos tales como: interseccin, unin, diferencia, pertenencia, comprobacin de lista vaca, concatenacin, etc. Las listas se pueden utilizar para implementar otras estructuras tales como listas circulares, vectores, pilas, colas, rboles, grafos y matrices. De cada estructura nos interesa saber cules son los algoritmos para acceder a ellas. Una vez que conocemos, perfectamente, el tipo de operaciones que las definen, cualquier tipo de implementacin es vlida. Por ejemplo, es frecuente usar una implementacin mediante listas para plasmar matrices. Por otro lado, es fundamental aplicar tcnicas de diseo descendente para resolver todos nuestros problemas e implementar las estructuras necesarias en nuestras aplicaciones. [NDICE] MATRICES Pgina 9 de 11 NDICE 30/10/2014 http://www.uhu.es/nieves.pavon/pprogramacion/temario/tema2/tema2.html Podemos definir matrices a partir de listas, primero de 2 dimensiones y, ms tarde, generalizar matrices de dimensin N. En un lenguaje imperativo, recorrer una matriz de dos dimensiones implica el uso de un par de bucles anidados, que proporcionan una complejidad computacional O(n2). Sin embargo, en Prolog, no disponemos de este tipo de estructuras de control, por tanto, cualquier operacin debe ser resuelta de forma recursiva mediante la declaracin formal de su enunciado. Un tratamiento elemento a elemento de las matrices tal y como se realiza en un lenguaje imperativo no es adecuado en Prolog, por tanto, conviene entender la estructura matriz como una lista de listas, y aplicar los algoritmos diseados sobre listas para resolver problemas matriciales. Una matriz de cuatro dimensiones se puede ver como la secuencia de un conjunto de matrices de tres dimensiones, una matriz de tres dimensiones como un conjunto de matrices de dos dimensiones, una matriz de dos dimensiones como un conjunto o lista de matrices de una dimensin (vector o lista), por ltimo, un vector o lista no es ms que una secuencia de elementos simples. Las definiciones dadas son recursivas, luego los algoritmos que debemos construir para realizar operaciones sobre este tipo de estructuras, as definidas, tambin sern recursivos. Operaciones con matrices bidimensionales domains fila=integer* matriz= fila* predicates sumafila(fila, fila, fila) sumar(matriz, matriz, matriz) clauses /*Predicado para calcular la suma de los elementos de una fila */ sumafila([],[],[]):-!. sumafila([], L2, L2):-!. sumafila(L1, [], L1):-!. sumafila([C1|Cola1], [C2|Cola2], Res):- S=C1+C2, sumafila(Cola1, Cola2, ColaRes), Res=[S|ColaRes]. /*Predicado de recorrido de las filas para sumar los elementos mediante el uso del predicado anterior */ sumar([],[],[]):-!. sumar([], L2, L2):-!. sumar(L1,[], L1):-!. sumar([C1|Cola1], [C2|Cola2], LR):-sumafila(C1, C2, Res), sumar(Cola1, Cola2, ColaRes), LR=[Res|ColaRes]. goal sumar([[1,2,3],[2,2,2],[4,4,4]],[[1,1,1],[2,1,2],[1,2,3]],R). [NDICE] Bibliografa Pgina 10 de 11 NDICE 30/10/2014 http://www.uhu.es/nieves.pavon/pprogramacion/temario/tema2/tema2.html [Adarraga, 1994] Adarraga, Pablo. Zaccagnini Jos Luis. "Psicologa e Inteligencia Artificial". Editorial Trotta. 1994. [NDICE] Pgina 11 de 11 NDICE 30/10/2014 http://www.uhu.es/nieves.pavon/pprogramacion/temario/tema2/tema2.html