Primeros pasos con Prolog Language

Programación de bases de datos

Prolog clasifica todo en:

  • Átomos: cualquier secuencia de caracteres que no comience con un alfabeto en mayúsculas. Por ejemplo: a, b, bien
  • Números - No hay una sintaxis especial para números, no se requiere declaración. Por ejemplo, 1, 22, 35.8
  • Variables - Una cadena que comienza con un carácter en mayúscula o guión bajo (_). Por ejemplo, X, Y, Abc, AA
  • Términos complejos - Están formados por un funtor y una secuencia de argumentos. El nombre de un término complejo es siempre un átomo, mientras que los argumentos pueden ser átomos o variables. Por ejemplo, padre(john,doe), pariente(a), madre(X,Y).

Una base de datos lógica contiene un conjunto de hechos y reglas.

Un término complejo con solo átomos como argumentos se llama hecho, mientras que un término complejo con variables como argumentos se llama regla.

Ejemplo de hechos en Prolog:

father_child(fred, susan).
mother_child(hillary, joe).

Ejemplo de una regla en Prolog:

child_of(X,Y):-
    father_child(Y,X)
    ;
    mother_child(Y,X).

Tenga en cuenta que ; aquí es como el operador o en otros idiomas.

Prolog es un lenguaje declarativo y puede leer esta base de datos de la siguiente manera:

fred es el padre de susan

Hillary es la madre de Joe.

Para todo X e Y, X es hijo de Y si Y es padre de X o Y es madre de X.

De hecho, un conjunto finito de hechos y/o reglas constituye un programa lógico.

El uso de dicho programa se demuestra haciendo consultas. Las consultas le permiten recuperar información de un programa lógico.

Para cargar la base de datos en el intérprete (suponiendo que haya guardado la base de datos en el directorio en el que está ejecutando el intérprete), simplemente ingrese:

?- [nameofdatabase].

reemplazando nameofdatabase con el nombre real del archivo (tenga en cuenta que aquí excluimos la extensión .pl del nombre de archivo).

Ejemplo de consultas en el intérprete para el programa anterior y los resultados:

?- child_of(susan,fred).
true

?- child_of(joe,hillary).
true

?- child_of(fred,susan).
false

?- child_of(susan,hillary).
false

?- child_of(susan,X).
X = fred

?- child_of(X,Y).
X = susan,
Y = fred ;
X = joe,
Y = hillary.

Las consultas anteriores y sus respuestas se pueden leer de la siguiente manera:

¿susan es hija de fred? - verdadero

es joe hijo de hillary? - verdadero

es fred un hijo de susan? - falso

¿susan es hija de hillary? - falso

¿De quién es hija Susan? - fred

Así es como programamos la lógica en Prolog. Un programa lógico es más formalmente: un conjunto de axiomas o reglas que definen relaciones (también conocidas como predicados) entre objetos. Una forma alternativa de interpretar la base de datos anterior de una manera lógica más formal es:

La relación padre_hijo se da entre fred y susan

La relación madre_hijo se da entre hillary y joe

Para todo X e Y, la relación hijo_de se cumple entre X e Y si la relación padre_hijo se cumple entre Y y X, o la relación madre_hijo se cumple entre Y y X.

Hola Mundo

Hello, World en el intérprete interactivo

Para imprimir “¡Hola, mundo!” en el intérprete de Prolog (aquí estamos usando swipl, el shell para SWI Prolog):

$ swipl
<...banner...>
?- write('Hello, World!'), nl.

?- es el indicador del sistema: indica que el sistema está listo para que el usuario ingrese una secuencia de objetivos (es decir, una consulta) que debe terminar con un . (punto).

Aquí la consulta write('Hello World!'), nl tiene dos objetivos:

  • write('Hello World!'): 'Hello World!' tiene que mostrarse y (,)
  • debe seguir una nueva línea (nl).

write/1 (el /1 se usa para indicar que el predicado toma un argumento) y nl/0 son predicados integrados (la definición la proporciona de antemano el sistema Prolog). Los predicados incorporados brindan funciones que no se pueden obtener mediante la definición pura de Prolog o para evitar que el programador tenga que definirlos.

La salida:

¡Hola, mundo!

si

termina con , lo que significa que la consulta se ha realizado correctamente. En algunos sistemas se imprime verdadero en lugar de .

Hola, mundo de un archivo

Abra un nuevo archivo llamado hello_world.pl e inserte el siguiente texto:

:- initialization hello_world, halt.

hello_world :-
    write('Hello, World!'), nl.

La directiva de inicialización especifica que se debe llamar al objetivo hello_world, halt cuando se carga el archivo. halt sale del programa.

Este archivo puede ser ejecutado por su ejecutable de Prolog. Las banderas exactas dependen del sistema Prolog. Si está utilizando SWI Prolog:

$ swipl -q -l hello_world.pl 

Esto producirá la salida ¡Hola, Mundo!. El indicador -q suprime el banner que generalmente se muestra cuando llama a ejecutar swipl. El -l especifica un archivo para cargar.

Instalación o configuración

SWI-Prólogo

Windows y Mac:

  • Descargue SWI-Prolog en el sitio web [oficial] (http://www.swi-prolog.org/download/stable)
  • Simplemente instale siguiendo las instrucciones del instalador.

Linux (PPA):

  • Agregue el PPA ppa:swi-prolog/stable a las fuentes de software de su sistema (los desarrolladores pueden elegir ppa:swi-prolog/devel):

    • Open a terminal (Ctrl+Alt+T) and type: sudo add-apt-repository ppa:swi-prolog/stable

    • Afterwards, update the package information: sudo apt-get update

  • Ahora instale SWI-Prolog a través del administrador de paquetes: sudo apt-get install swi-prolog

  • Ahora puede iniciar SWI-Prolog a través de la línea de comandos con el comando swipl

agregar/3

append([], Bs, Bs).
append([A|As], Bs, [A|Cs]) :-
    append(As, Bs, Cs).

append/3 es una de las relaciones de Prolog más conocidas. Define una relación entre tres argumentos y es verdadera si el tercer argumento es una lista que denota la concatenación de las listas que se especifican en el primer y segundo argumento.

En particular, y como es típico del buen código de Prolog, append/3 se puede usar en varias direcciones: se puede usar para:

  • añadir dos listas instanciadas total o parcialmente:

      ?- A = [1, 2, 3], B=[4, 5, 6], append(A, B, Y)
      Output:
      A = [1, 2, 3],
      B = [4, 5, 6],
      Y = [1, 2, 3, 4, 5, 6].
    
  • comprobar si la relación es verdadera para tres listas completamente instanciadas:

      ?- A = [1, 2, 3], B = [4, 5], C = [1, 2, 3, 4, 5, 6], append(A, B, C)
      Output:
      false
    
  • generar todas las formas posibles de agregar dos listas a una lista dada:

      ?- append(A, B, [1, 2, 3, 4]).
      Output:
      A = [],
      B = [1, 2, 3, 4] ;
      A = [1],
      B = [2, 3, 4] ;
      A = [1, 2],
      B = [3, 4] ;
      A = [1, 2, 3],
      B = [4] ;
      A = [1, 2, 3, 4],
      B = [] ;
      false.
    

Restricciones CLP(FD)

Todas las implementaciones serias de Prolog proporcionan restricciones CLP(FD). Nos permiten razonar sobre enteros de forma pura.

?- X #= 1 + 2.
X = 3.

?- 5 #= Y + 2.
Y = 3.