PROLOG (V): cut o corte , fail o fallo y not \+

El comando cut ! o corte hace que en la búsqueda de una solución y para evitar tiempo de proceso se da por buena la primera regla que se cumple con éxito por orden secuencial.

A la pregunta nota (8,Valor) devuelve Valor=notable, sin el ! tendriamos dos soluciones Valor = notable y Valor = sobresaliente

En otras palabras cut ! permite optimizar el tiempo de proceso, a cambio hay que ser cuidadoso con el orden de las reglas de más restrictiva a menos.

! siempre se cumple.

Fail no se cumple nunca y viene a ser el comando complementario a !.

Esta base de conocimiento nos dice que los corredores clasificados los inscritos que no han abandonado o se les ha descalificado, usando not

Se usa not o mejor \+ para negar una sentencia.

PROLOG (IV): Más que lógica

EXPRESIONES ARITMETICAS

Además de con expresiones lógicas, con PROLOG podemos trabajar con expresiones aritméticas , con números enteros (integer), racionales (rational) y en coma flotante (float) y tiene definidas las constantes pi y e

Veamos un ejemplo.

¿Es 5 el resultado de sumar 2 más 3? Verdadero.
¿Es 5 el resultado de sumar 2 más 4? Falso.

Pero hay muchísimas más como podemos ver en el manual de referencias, veamos unas pocas y así enteremos la nomenclatura que usa:

  • between(+Low, +High, ?Value) : Esta expresión es cierta si el valor de la variable (?Value) está comprendido en el intervalo cerrado (+Low,+Higth), así between(2,4,3)  es true.
  • succ(?Int1, ?Int2) : Esta expresión es cierta si el valor del numero entero de la variable ?int2 es el de ?Int1 incrementado en una unidad. Así succ(1,2) es true y succ(1,A) es A=2.
  • >, <, >=, =>, =/=, =:= o is : son los operadores lógicos correspondientes a menor que, mayor que, mayor o igual, menor o igual, desigual e igual. Por ejemplo 1.0 is sin(pi/2)  es true
  • round(+Expr) : redondea +Expr al entero más proximo. Por ejemplo A is round(1.2) nos devuelve A = 1.

LISTAS

Las listas es una estructura de datos que está implementada en PROLOG. Una lista es un conjunto ordenado de datos, que se escribe entre corchetes y separados por comas por ejemplo [X, Y, Z] . Disponemos de un completo conjunto de funciones para manipular listas en PROLOG.

  • = : permite asignar valores [X, Y, Z] = [juan, pablo, pedro]
  • member: indica si un valor está contenido en una lista member(juan,[juan, pablo, pedro]).
  • max_member: devuelve el elemento que ocupa la posición superior en la lista max_member(A,[juan, pablo, pedro]) devuelve A= pedro
  • min_menber: devuelve el elemento que ocupa la posición superior en la lista min_member(A,[juan, pablo, pedro]) devuelve A= juan
  • length([lista],Longitud) : devuelve la longitud de la lista. Así length([juan, pablo, pedro],Longitud) devuelve Longitud = 3.
  • append: une listas. Un ejemplo append([juan, pablo, pedro],[luis],A) devuelve A = [juan, pablo, pedro, luis].
  • delete (lista, elemento, nueva_lista): borra un elemento de una lista. Veamos un ejemplo delete([juan, pablo, pedro], juan, A) devuelve A = [pablo, pedro].
  • nth0(Index,[lista], elemento_buscado): devuelve el valor del indice del valor buscado en la lista, comenzando por 0. Un ejemplo como nth0(Index,[juan, pablo, pedro], pedro) nos devuelve Index = 2.
  • sort([lista], lista_ordenada): ordena una lista de entrada, devolviendo la lista ordenada sort([juan, pablo, pedro, andres], A) devuelve A = [andres, juan, pablo, pedro].

PROLOG (y fin): Para seguir aprendiendo

Comencemos por recordar que hay dos comandos de ayuda en el propio interprete PROLOG y estos son «help» y «apropos»

Preguntamos sobre el comando consult (carga del programa fuente en la memoria del interprete) con help y apropos

Un texto básico para comenzar a profundizar puede ser el del estándar ISO-PROLOG en él encontrará la razón por la que las variables comienzan por mayúscula o guion bajo, y otras curiosidades que he ido comentando y que un programador experto las considera obvias o evidentes.

Otra utilidad muy práctica es el editor e interprete en web de SWI-PROLOG llamado SWISH que permite desarrollar y programas sin necesidad de instalar ningun programa en nuestro dispositivo (por ejemplo desde la tablet o el móvil)

El mismo programa de PROLOG en SWISH

Existe un manual embebido en el propio SWISH que es muy práctico y además puede consultar un pequeño tutorial del SWISH de la universidad de Málaga y una guia del usuario muy didáctica.

También he encontrado útil el minimanual de Roberto torres de Alba y si prefiere leer el manual de referencia del SWI Prolog en formato libro aquí está el PDF.

Con esto doy por terminada esta introducción a lo que es PROLOG en 2020, un lenguaje que ayuda a pensar de forma lógica.

PROLOG (III): Un primer programa

El ciclo de programación es escribir y probar. Para escribir un programa podemos usar desde un sencillo Bloc de Notas, a un editor como el ZeroBrane Studio (el que uso últimamente y al que me aficioné desarrollando en LUA) a un entorno como Eclipse.

Sencillo programa genearologico en PROLOG

Vamos a analizar este primer programa:Los comentarios se pueden escribir entre «/*» «*/» o tras el signo «%«

Los hechos se escriben como relación(valor1,valor2) y así «José es el padre de Juan» se codifica como «padre(jose, juan).» Las sentencias se terminan en «.» y los valores comienzan por minuscula y el nombre de las variables con mayusculas.

Una regla (Clausula de Horn, cláusulas con al menos un literal positivo) como «la abuela es la madre de la madre o la madre del padre» se codifica como » abuela(A,C) :- madre(A,B), madre(B,C) ; madre(A,B), padre(B,C):«. Siendo «:-» el equivalente del «if» condicional la «,» es un «AND LOGICO» o «Y gramatical» y el «;» el «OR LOGICO» o «O gramatical«.

La forma de aprender a programar es programando, así que imagine cualquier campod e conocimiento y escriba su programa en PROLOG.

Antes de ejecutar nuestro programas tenemos que asegurarnos que el interprete va a poder localizar el fuente, para poderlo cargar e interpretar. Para ello lo primero que debemos conocer es cual es el directorio de trabajo de nuestro interprete, cosa que podemos conocer con el comando «working_directory(CWD, CWD).» o con «pwd»(Les sonará a los que han trabajado con UNIX alguna vez), en el caso que queramos modificar el directorio de trabajo por, por ejemplo «//Users/Juan/Applications/» ejecutariamos el comando de nuevo pero como «working_directory(CWD,»//Users/Juan/Applications/»).» Para conocer el contenido del directorio de trabajo usamos el comando, que en nuestro caso sería «directory_files(«/applications/»,DIR).»

En todos estos comandos el primer campo es el de entrada «+» y el segundo la salida ««.

Si nuestro programa se llama «familia.pl» podemos conocer su path absoluto con el comando «absolute_file_name(«prolog-1.pl»,A).» que en nuestro caso responde con «A = ‘/Users/Juan/Applications/prolog-1.pl’.«

Para cargar en memoria el programa ejecutamos el comando «consult(«/Users/Juan/Applications/familia.pl»).» , «consult(familia)» o su equivalente «[familia].» Si queremos recargar el programa podemos hacer «reconsult(familia)«

Ahora ya podemos comenzar a interpelar a nuestra base de conocimientos

En la primera entrada preguntamos «¿De quién es padre jose?» a lo que nos responde «juan», en la segunda «¿Es jose el padre de juan» a lo que nos responde «true» (cierto), en la tercera «¿jose es el padre de mariajo?» a los que nos responde «false» (falso), en la cuarta «¿Cómo se llaman los nietos de jose?» a lo que nos responde primeramente «damian» tras lo cual da «false» cuando le pedimos más con «;», la quinta es una repetición

De nuevo le invito a jugar con su imaginación a la hora de preguntar a la base de conocimiento

En el primer caso preguntamos por los hijos de jose o los de arturo mediante «;«, y en el segundo por los hijos comunes con «,«

Un listado exhaustivo de todos hechos se consigue con el comando findall, cuyo formato es findall(+Template, :Goal, -Bag) así para encontrar todos los hijos de cualquier padre haremos «findall(X,padre(_,X),Lista)«y nos devolverá «Lista = [juan, mariajo, damian]«

Si encontramos algún problema en la ejecución podemos invocar el modo de traceo mediante «trace» y salir de él con «nodebuger».

Por ultimo debe ser consciente que una misma base de conocimiento puede codificarse de muchas formas, por ejemplo la definición de padre y madre puede escribirse de la siguiente forma

Una posibilidad de las reglas en PROLOG es la recursividad, que permite una regla llamarse a si misma. Con el ejemplo del calculo del Factorial de un número lo veremos con facilidad

La primera regla define que el factorial de 0 es 1. En la segunda regla damos en N el valor del cual queremos calcular el valor de su factorial que nos devuelve en F, en donde Nsea mayor que 0, decrementa el valor de N, invoca a factorial y multiplica el resultado parcial por el valor de N

En entradas sucesivas analizaremos otros aspectos del lenguaje y por último hablaremos de manuales de usuarios (user manual) o cursos que le ayuden a profundizar en el manual de referencia de SWI-PROLOG que es muy extenso y poco didáctico como todos los «references manuals»