Manual Casero Prolog Beta 02

50
Prolog(Sin,Esfuerzo) :- en 44 minutos(Sin), y 15 segundos(Esfuerzo). francisco miguel garc´ ıa olmedo Departamento de ´ Algebra Universidad de Granada 18071 Granada, Espa˜ na 22 de mayo de 2011 ´ Indice 1. Introducci´ on 2 2. Utilizar Prolog 3 3. Sintaxis 5 3.1. ´ Atomos .................................... 5 3.2. umeros .................................... 6 3.3. Variables .................................... 6 3.4. erminos compuestos ............................. 6 3.5. Operadores .................................. 7 3.6. Funciones aritm´ eticas ............................. 10 3.7. Conectivas ................................... 10 3.8. Reglas ..................................... 11 3.9. Comentarios .................................. 12 4. Programas 12 5. Estructuras de Datos 15 5.1. ´ Arboles .................................... 15 5.2. Listas ..................................... 16 5.3. Coleccionando Soluciones. .......................... 19 5.3.1. findall/3 ............................... 19 5.3.2. bagof/3 ................................ 20 5.3.3. setof/3 ................................ 21 5.4. Conjuntos ................................... 21 5.5. La estructura de los t´ erminos ........................ 23 5.5.1. functor ................................ 23 5.5.2. arg ................................... 24 5.5.3. =.. ................................... 24 1

Transcript of Manual Casero Prolog Beta 02

Page 1: Manual Casero Prolog Beta 02

Prolog(Sin,Esfuerzo) :- en 44 minutos(Sin),

y 15 segundos(Esfuerzo).

francisco miguel garcıa olmedo

Departamento de AlgebraUniversidad de Granada18071 Granada, Espana

22 de mayo de 2011

Indice

1. Introduccion 2

2. Utilizar Prolog 3

3. Sintaxis 53.1. Atomos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53.2. Numeros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63.3. Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63.4. Terminos compuestos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63.5. Operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.6. Funciones aritmeticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.7. Conectivas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.8. Reglas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.9. Comentarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

4. Programas 12

5. Estructuras de Datos 155.1. Arboles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155.2. Listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165.3. Coleccionando Soluciones. . . . . . . . . . . . . . . . . . . . . . . . . . . 19

5.3.1. findall/3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195.3.2. bagof/3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205.3.3. setof/3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

5.4. Conjuntos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215.5. La estructura de los terminos . . . . . . . . . . . . . . . . . . . . . . . . 23

5.5.1. functor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235.5.2. arg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245.5.3. =.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

1

Page 2: Manual Casero Prolog Beta 02

5.5.4. name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

6. Recursos de Control en la Programacion 256.1. Recursion (recursion) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266.2. Unificacion (unification, matching) . . . . . . . . . . . . . . . . . . . . . 286.3. Reevaluacion (backtracking) . . . . . . . . . . . . . . . . . . . . . . . . . 296.4. Corte (cut) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

7. Usos del Corte 317.1. Confirmacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317.2. Advertencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327.3. Finalizacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327.4. Efectos indeseados, pero tolerables, del corte . . . . . . . . . . . . . . . . 337.5. Predicados de control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347.6. Otros ejemplos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

8. La I/O en Prolog 368.1. Lectura y escritura de terminos . . . . . . . . . . . . . . . . . . . . . . . 368.2. Lectura y escritura de caracteres . . . . . . . . . . . . . . . . . . . . . . . 378.3. Lectura y escritura en ficheros . . . . . . . . . . . . . . . . . . . . . . . . 38

9. Modificacion de la Base de Conocimiento 399.1. Adicion de Bases de Conocimiento externas . . . . . . . . . . . . . . . . 409.2. Manipulacion de la Base de Conocimiento . . . . . . . . . . . . . . . . . 41

10.Depuracion de Programas Prolog 43

A. Predicados Predefinidos 45

B. Notacion comparativa entre Logica y Prolog 50

Indice de figuras

1. Ejemplos de atomos, numeros y variables. . . . . . . . . . . . . . . . . . 62. Operadores aritmeticos y relacionales predefinidos en SWI-Prolog. . . . . 73. Definicion infija, prefija o sufija de un operador. . . . . . . . . . . . . . . 8

1. Introduccion

Prolog (proviene de “Programmation en Logique”) fue creado por Alain Colmerauery sus colaboradores alrededor de 1970 en la Universidad de Marseille–Aix, si bien en eldesarrollo del lenguaje intervino de forma esencial Robert Kowalski de la Universidadde Edimburgh. Las investigaciones de Kowalski proporcionaron el marco teorico, mien-tras que los trabajos de Colmerauer dieron origen al actual lenguaje de programacion,construyendo el primer interprete de Prolog.

2

Page 3: Manual Casero Prolog Beta 02

El lenguaje Prolog juega un importante papel dentro de la Inteligencia Artificial; dehecho se propuso como el lenguaje nativo de las maquinas de la quinta generacion, quese querıa que fueran Sistemas de Procesamiento de Conocimiento.

Prolog es un lenguaje de programacion para ordenadores que se basa en el lenguaje dela Logica de Primer Orden y que se utiliza para resolver problemas en los que entran enjuego objetos y relaciones entre ellos. Una de las ventajas de la programacion logica esque se especifica que se tiene que hacer (programacion declarativa) y no como se debehacer (programacion imperativa).

Los presentes notas son una reformulacion y adaptacion muy cercana al documento ori-ginal de los profesores Castel y Llorens. Estos autores han compuesto una introduccionmagnıfica a Prolog: es concisa, eficaz, clara, ilustrada y correcta. Despues de leerla, yapodemos ir a por los manuales y libros.

2. Utilizar Prolog

En un sistema Linux lo mas interesante es instalar SWI-Prolog, lo cual puede extenderseal resto de plataformas debido a que se trata de software libre. Si el sistema esta basadoen Debian (nos referimos, por ejemplo, a: un Debian, un Ubuntu, Guadalinex, etc.), lainstalacion se lleva a cabo con la orden:

sudo apt-get install swi-prolog

Si nuestro sistema es Windows o Mac OS X podemos llevar a cabo la instalacion desdela informacion que brinda la pagina oficial de SWI-Prolog.

http://www.swi-prolog.org/

y mejor aun, su pagina de descargas:

http://www.swi-prolog.org/download/stable

Recomendamos editar los ficheros .pl con Emacs, un editor polivalente con licencia GNUque esta disponible en todas las plataformas. Se trata de un clasico con mantenimientogarantizado que nos servira como editor auxiliar de cualquier lenguaje. Una guıa sucintade su uso es:

http://matematicas.unal.edu.co/hmora/emacs_man.pdf

En nuestro sistema Linux basado en Debian, la instalacion de Emacs se lleva a cabocomo sigue:

sudo apt-get install emacs emacs23-el prolog-el

Con el propio Emacs editaremos un fichero .emacs en nuestro directorio raız e incluire-mos en el el siguiente texto:

3

Page 4: Manual Casero Prolog Beta 02

(autoload ’run-prolog "prolog" "Start a Prolog sub-process." t)

(autoload ’prolog-mode "prolog" "Major mode for editing Prolog programs." t)

(autoload ’mercury-mode "prolog" "Major mode for editing Mercury programs." t)

(setq prolog-system ’swi)

(setq auto-mode-alist (append ’(("\\.pl$" . prolog-mode)

("\\.m$" . mercury-mode))

auto-mode-alist))

Ası habremos adecuado emacs para dar colorido y entender los ficheros .pl

Si nuestro sistema es Mac OS X podemos bajar de:

http://aquamacs.org/download.shtml

el fichero de instalacion de Aquamacs, que actualmente es Aquamacs-Emacs-2.2.dmg.Se trata de la mejor implementacion que conocemos de Emacs. Con Aquamacs no esnecesario completar la instalacion para que el editor se adecue a los ficheros .pl, puesesto viene hecho por defecto.

Si nuestro sistema es Windows, la instalacion de Emacs viene detallada en uno de lospuntos del famoso blog:

http://instalaremacsenwindows7.blogspot.com/

Aunque el blog habla de la instalacion en Windows 7, nosotros la hemos probado tam-bien en Windows Vista y funciona. Con pequenas modificaciones tambien vale estainformacion para Windows XP, si es que aun disfrutamos de el. No olvidar incluir enel .emacs que el muchachillo dice de crear, el texto de adaptacion antes mencionado;aquı sı que es necesario.

Con nuestro editor escribirıamos un fichero .pl, que por ejemplo y por hacer honor a lacostumbre, podrıa ser el fichero hola.pl con el siguiente contenido:

venga_saluda :- write(’hola mundo!’).

Ejecutaremos en el terminal, sea cual sea la plataforma, la orden:

swipl

y entraremos en el interprete de Prolog que nos permite escribir tras el “prompt”habitual de la marca:

?-

Esta es una sesion tıpica:

?- [’hola.pl’].

% hola.pl compiled 0.00 sec, 272 bytes

true.

?- listing.

4

Page 5: Manual Casero Prolog Beta 02

venga_saluda :-

write(’hola mundo!’).

true.

?- venga_saluda.

hola mundo!

true.

Y este es el momento en que comprendemos, con certeza y regocijo, que esta en el bote:¡hemos escrito nuestro primer programa en Prolog! Lo que pasa es que surge la pregunta:¿¡que facilon, no!? ¿pero . . . tan facil?.

Si hacemos:

?- help(help).

se despliega una ventana de ayuda con mucha calidad. No olvidar que cuando se haceuna pregunta, o sea se marca un objetivo, es necesario finalizar con punto “.” antes depulsar intro. Cuando queramos dejar el entorno interprete haremos:

?- halt.

Y ahora . . . ¡adelante!

3. Sintaxis

En la programacion de Prolog usaremos terminos que son de las siguientes clases:

1. Atomos.

2. Numeros.

3. Variables.

4. Terminos compuestos.

Ademas incluimos en esta leccion los siguientes aspectos:

1. Operadores

2. Comentarios

3.1. Atomos

Los atomos de Prolog son de tres tipos:

1. Una cadena de caracteres compuesta de letras mayuculas, minusculas, dıgitos y elcaracter de subrayado; debe comenzar por una letra minuscula. Ejemplos: don eladio guardiola,mantequilla y puerta2.

2. Cualquier cadena de caracteres encerrada entre comillas simples. Ejemplos: ’El

Gimp’, ’ ’ y tambien ’^& %#$& *’

5

Page 6: Manual Casero Prolog Beta 02

3. Todos los operadores, en particular los relacionados en la seccion Operadores yotros.

4. Las conectivas relacionadas en la seccion Conectivas.

5. Ciertas cadenas de caracteres especiales, por ejemplo: @=, ====>, ; y :-

Para saber si ciertas secuencias de caracteres son atomo tenemos atom(?Secuencia).

3.2. Numeros

Los numeros son de dos tipos:

1. enteros ; en la implementacion de Prolog-2 los enteros son los del intervalo [−223, 223−1] = [−8388608, 8388607].

2. reales ; decimales con signo en coma flotante consistentes en al menos un dıgito,opcionalmente un punto decimal seguido de la parte decimal. Cabe la notacioncientıfica siguiendo a la letra mayuscula “E”

3.3. Variables

En cuanto a las variables, empiezan con letras mayusculas o con el signo de subrayado ( ).Son las incognitas de los problemas y estan destinadas a representar objetos cualesquieradel universo del problema. Tiene un valor especial la variable anonima, que representa unvalor desconocido cuya identidad no interesa; las variables anonimas no estan compartidasentre sı. Una variable esta instanciada si representa a un valor concreto; puede estarinstancia o no.

Para saber si ciertas secuencias de caracteres son variable tenemos var(?Secuencia) ynonvar(?Secuencia).

atomos numeros variablesa 4 Xdon vito corleone -1.2 Dividendo primero’Anibal Lecter’ 1.2E+3 restob52 1.2E-3

Figura 1: Ejemplos de atomos, numeros y variables.

3.4. Terminos compuestos

Son sinonimos termino compuesto, estructura, hechos y predicado. Las estructuras tienenla siguiente sintaxis:

funtor(argumento1,...,argumentoN)

6

Page 7: Manual Casero Prolog Beta 02

donde funtor es un atomo y argumentok, con 1 ≤ k ≤ N , es termino. Ejemplos:

mujer(clara)

ama(X,prolog)

libro(programacion en Prolog,autores(Clocksin,Mellish),1981)

Admitimos el termino vacıo como termino.

3.5. Operadores

Encontramos predefinidos en Prolog los operadores de la tabla de la Figura 2. El manejode esos operadores ha sido “dulcificado” respecto a lo que es la representacion internade Prolog. Internamete Prolog usara is(11,+(2,*(3,3))), pero nosotros escribimos11 is 2 + 3 * 3. Aquı encontramos un primer detalle a subrayar: se ha hecho un usoinfijo permitido del operador *. Sabemos que un operador es prefijo, infijo o sufijo segunlo que indica la tabla de la Figura 3.

operadores sımbolos precendencia especificadorsigno positivo + 200 fx

signo negativo - 200 fx

potencia ^ o ** 200 xfx

producto * 400 yfx

division / 400 yfx

division entera // 400 yfx

resto division entera mod 400 yfx

suma + 500 yfx

resta - 500 yfx

igualdad = 700 xfx

distinto \= 700 xfx

menor que < 700 xfx

menor o igual que =< 700 xfx

mayor que > 700 xfx

mayor o igual que >= 700 xfx

evaluacion aritmetica is 700 xfx

Figura 2: Operadores aritmeticos y relacionales predefinidos en SWI-Prolog.

Prolog incorpora convenios para evitar ambiguedad en las expresiones. Considerese elsiguiente dialogo:

?- 15 is 2+3*3.

false.

?- 11 is 2+3*3.

true.

7

Page 8: Manual Casero Prolog Beta 02

Esto se explica en funcion de la precedencia, que es mayor para + que para *; ello haceque la representacion interna de 2+3*3 sea +(2,*(3,3)), es decir, + es el operador masexterno. De forma similar 11 is 2+3*3 es interpretada como is(11,+(2,*(3,3))), y nocomo is(11,+(2,*(3,3))), porque la precedencia de is es superior a la de +. Numeromas alto indica precedencia mas alta.

caracter especificadorinfijo xfx, xfy, yfxprefijo fx, fysufijo xf, yf

Figura 3: Definicion infija, prefija o sufija de un operador.

Prolog permite al programador definir sus propios operadores. La sintaxis de esta ope-racion es:

:- op(Precedencia, Tipo, Nombre).

donde Precedencia es un numero entre 0 y 1200. La precedencia de =, por ejemplo,es 700, la de + es 500 y la de * es 400. Tipo es un atomo que especifica el tipo y laasociatividad del operador. En el caso de + este atomo es yfx, que indica que + es unoperador infijo; f representa al operador, x e y los argumentos. Mas aun, x quiere significarque el argumento que ocupa su lugar es de precedencia inferior a la precedencia de + ey indica que el argumento que ocupa su lugar es de precedencia menor o igual que laprecedencia de +. Ası:

?- 2 + 3 + 4 = +(2,+(3,4)).

false

?- 2 + 3 + 4 = +(+(2,3),4).

true

?- 6 is 7-3-2.

false.

?- 2 is 7-3-2.

true.

Algunos ejemplos reales son:

:- op( 1200, xfx, [ :-, --> ]).

:- op( 1200, fx, [ :-, ?- ]).

:- op( 1100, xfy, [ ; ]).

:- op( 1000, xfy, [ ’,’ ]).

:- op( 700, xfx, [ =, is, =.., ==, \==,

=:=, =\=, <, >, =<, >= ]).

:- op( 500, yfx, [ +, -]).

8

Page 9: Manual Casero Prolog Beta 02

:- op( 500, fx, [ +, - ]).

:- op( 300, xfx, [ mod ]).

:- op( 200, xfy, [ ^ ]).

Los operadores no hacen que se efetue ningun tipo de operacion aritmetica. El predicadode evaluacion es el operador infijo is:

-Numero is +Expresion

donde Expresion es un termino que se interpreta como una expresion aritmetica, contodos sus valores instanciados. Numero puede ser una variable o una constante numerica.

?- 6 is 7-3-2.

false.

?- X is 7-3-2.

X = 2.

No obstante, observese tambien el siguiente dialogo:

?- 2+2 \= 4.

true.

?- 2+2 \== 4.

true.

?- 2+2 =\= 4.

false.

Como ejemplo, considerar que hemos editado el fichero endulzar.pl con el siguientecontenido:

:- op(500,xf,es_dulce).

endulza(azucar,cafe).

es_dulce(X) :- endulza(_,X).

Ahora tiene sentido el siguiente dialogo:

?- [’endulzar.pl’].

% endulzar.pl compiled 0.00 sec, 1,432 bytes

true.

?- cafe es_dulce.

true.

Acabamos de indicar a Prolog como traducir una notacion informal, cafe es dulce, auna notacion real suya es dulce(cafe). Ademas hemos dotado a Prolog de una basede datos para decidir sobre la cuestion cafe es dulce.

9

Page 10: Manual Casero Prolog Beta 02

3.6. Funciones aritmeticas

Prolog incorpora ciertas funciones aritmeticas entre las que destacamos: abs, sig, min,max, random, round, integer, float, sqrt, sin, cos, tan, log, log10, exp, etc. Comoejemplo de utilizacion tenemos el siguiente dialogo:

?- X is abs(-2).

X = 2.

?- X is min(-1,2*4+1).

X = -1.

?- X is min(2*4+1,13).

X = 9.

?- X is random(13).

X = 8.

?- X is random(13).

X = 5.

?- X is random(13).

X = 11.

?- X is sqrt(10).

X = 3.16228.

?- X is sin(2*pi/4).

X = 1.0.

?- X is log(e).

X = 1.0.

?- X is log(e**3).

X = 3.0.

?- X is log10(1000000).

X = 6.0.

3.7. Conectivas

Las conectivas logicas son las siguientes:

1. la conjuncion; se representa poniendo “,” entre los objetivos (hechos), por ejemplo;

X, Y

entrada(X), plato principal(Y), postre(Z)

10

Page 11: Manual Casero Prolog Beta 02

Para satisfacer una secuencia de objetivos separados por comas, deben ser satisfe-chos uno detras del otro de izquierda a derecha en el orden dado. La satisfaccion esbuscada sobre terminos del universo del problema, segun la relaciones establecidasen la base de datos del mismo. Para satisfacer la secuencia, deberan ser satisfechosen un mismo objeto todos los objetivos conjuntados. Los terminos satisfactorespueden ser uno, varios o ninguno.

2. la disyuncion; se representa poniendo “;” entre los objetivos (hechos):

X; Y

entrada(X); plato principal(Y); postre(Z)

La disyuncion tendra exito cuando lo tenga alguno de los objetivos que la componenen al menos un termino.

3. la negacion; se representa poniendo “not” o “\+” sobre el objeto (hecho):

not(X)

\+ X

Tendra exito cuando, y solo cuando, el objetivo negado (X en el ejemplo) fracasa.No es una verdadera negacion en el sentido logico, sino una negacion “por fallo”

Son combinaciones proposicionales de terminos:

1. !, fail

2. los termino compuesto.

3. (cpt 01, clt 02), siempre que cpt 01 y cpt 02 sean combinaciones proposiciona-les de terminos.

4. (cpt 01; clt 02), siempre que cpt 01 y cpt 02 sean combinaciones proposiciona-les de terminos.

5. not(cpt 01), siempre que cpt 01 sea una combinacion proposicional de terminos.

En las combinaciones proposicionales de terminos pueden desaparecer los parentesis siello no origina ambiguedad debido a la precedencia.

3.8. Reglas

En Prolog las reglas tienen la siguiente estructura:

cabeza_de_la_regla :- cuerpo_de_la_regla.

En una regla, cabeza de la regla es un termino (hecho) y puede ser el termino vacıo, esdecir, puede faltar. cuerpo de la regla es una combinacion proposicional de terminosy no puede ser vacıa. Muy frecuentemente el cuerpo de la regla es una conjuncion dehechos, por ejemplo:

comida(X, Y, Z) :- entrada(X), plato_principal(Y), postre(Z).

11

Page 12: Manual Casero Prolog Beta 02

en cuyo caso cada conjunto de la conjuncion se denomina objetivo. En la logica de primerorden, el objeto logico equivalente a la regla de Prolog es el de una clausula. El ejemplo:

p(X, Y) :- q(X,Z), q(Z,Y).

serıa equivalente a cualquiera de las siguientes formulas equivalentes:

∀x∀y(∃z(q(x, z) ∧ q(z, y))→ p(x, y))

∀x∀y(¬∃z(q(x, z) ∧ q(z, y)) ∨ p(x, y))

∀x∀y∀z(¬q(x, z) ∨ ¬q(z, y) ∨ p(x, y))

∀x∀y∀z(p(x, y) ∨ ¬q(x, z) ∨ ¬q(z, y))

∀x∀y∀z((q(x, z) ∧ q(z, y))→ p(x, y))

En una regla, la cabeza describe el hecho que se intenta definir; el cuerpo describe losobjetivos que deben ser satisfechos, como condicion suficiente, para que la cabeza seasatisfecha.

Un mismo nombre de variable representa el mismo objeto siempre que aparece en la regla.Ası, cuando X se instancia a algun objeto, todas las X de dicha regla tambien se instanciana ese objeto; o mejor, cuando X se instancia a algun objeto, la instanciacion tiene efecto entodo el ambito de la variable cuantificada universalmente y dicho cuantificador universalsobre esa variable desaparece temporalmente en el tanteo.

Bien entendido, debemos saber que hechos y reglas comparten una misma naturaleza, asaber, son clausulas de la logica de predicados.

3.9. Comentarios

Si en programacion imperativa es importante comentar los programas, en programaciondeclarativa la necesidad se acentua. Para comentar un parrafo de Prolog lo incluimosen un entorno “/* */” de acuerdo con el siguiente patron

/* Este es el parrafo que

queremos comentar para

ilustrar el contenido

del programa */

Pero si lo que queremos comentar es solamente un renglon, entonces lo hacemos precederpor el sımbolo “ %”

% reglon explicativo del programa

4. Programas

Confeccionar un programa en Prolog es establecer un universo finito de hechos y re-glas, o si se quiere —con mas precision— un universo finito de clausulas. Con ello seproporciona un “caldo primigenio” que Prolog aprovecha para establecer inferencias.Ası pues, se declaran hechos sobre objetos y relaciones, se definen reglas sobre los mismosy se hacen preguntas sobre esos objetos y sus relaciones. Ejecutar un programa es, dehecho, demostrar un teorema que versa sobre el universo de objetos y relaciones.

12

Page 13: Manual Casero Prolog Beta 02

Un sistema Prolog es una implementacion de un demostrador de teoremas por resolu-cion para clausulas de Horn. La estrategia de resolucion utilizada es un tipo de resolucionlineal y el metodo de busqueda esta basado en la iniciativa primero en profundidad. Elorden de las clausulas en un programa importa, ya que determina el orden en que lassoluciones seran encontradas. Un determinado orden puede conducir a fallos en el pro-grama mientras que otro no. Es de capital importancia el orden de las metas a alcanzardentro del cuerpo de la reglas.

Prolog considera la base de datos de cada programa como “contraste de verdad”, o sea,es cierta para el cada clausula que figure en la base de datos y falsa cualquier otra que nofigure en ella. Prolog responde true cuando puede demostrar algo y false cuando “nopuede demostrarlo”; por lo que debemos entender el false en el sentido de “no puedodemostrarlo con lo que se”.

Cuando se formula a Prolog una pregunta que incluye una variable, esta esta inicial-mente no instanciada. Inmediatamente se trata de instanciarla a terminos involucradosen la base de datos de forma que empareje con la pregunta (algoritmo de unificacion).Cuando encuentra un termino, o juego de terminos, que emparejan, muestra por pantallaaquello a lo que estan instanciadas entonces las variables involucradas en la pregunta comoprimera solucion del problema. Prolog queda entonces a la espera de instrucciones:

si pulsamos <enter>, cesa la busqueda.

si pulsamos ; reanuda la busqueda comenzando donde habıa dejado la marca en unintento por resatisfacer los hechos de la pregunta.

Ejemplo 4.1. Como ejemplo consideremos la siguiente base de datos que esta contenidaen el fichero u711.pl:

p(a).

p(X) :- q(X), r(X).

p(X) :- u(X).

q(X) :- s(X).

r(a).

r(b).

s(a).

s(b).

s(c).

u(d).

que a traves de nuestro SWI-Prolog nos proporciona el siguiente dialogo:

?- [’u711.pl’].

% u711.pl compiled 0.00 sec, 1,472 bytes

true.

13

Page 14: Manual Casero Prolog Beta 02

?- p(X).

X = a ;

X = a ;

X = b ;

X = d.

?- s(d).

false.

?- u(d).

true.

?- p(a), s(X).

X = a ;

X = b ;

X = c ;

X = a ;

X = b ;

X = c ;

false.

?- u(X), s(X).

false.

?- u(X), p(X).

X = d.

?- u(X); s(X).

X = d ;

X = a ;

X = b ;

X = c.

?- not(p(X)).

false.

?- not(p(a)).

false.

?- not(u(a)).

true.

Ejemplo 4.2. Considerar el siguiente codigo:

horoscopo(aries,21,3,21,4).

horoscopo(tauro,21,4,21,5).

horoscopo(geminis,21,5,21,6).

14

Page 15: Manual Casero Prolog Beta 02

horoscopo(cancer,21,6,21,7).

horoscopo(leo,21,7,21,8).

horoscopo(virgo,21,8,21,9).

horoscopo(libra,21,9,21,10).

horoscopo(escorpio,21,10,21,11).

horoscopo(sagitario,21,11,21,12).

horoscopo(capricornio,21,12,21,1).

horoscopo(acuario,21,1,21,2).

horoscopo(piscis,21,2,21,3).

signo(Dia,Mes,Signo) :- horoscopo(Signo,D1,M1,D2,M2),

((Mes = M1, Dia >= D1); (Mes=M2, Dia =< D2)).

e interpretar las respuestas a las siguientes preguntas:

?- signo(8,5,tauro).

?- signo(7,8,acuario).

?- signo(7,8,Signo).

?- signo(7,X,Signo).

?- signo(X,7,Signo).

La respuesta a:

?- signo(33,4,tauro).

true

es incorrecta. ¿Como se podrıa reparar para que el comportamiento fuese el siguiente?:

?- signo(33,4,tauro).

false.

Ejercicio 4.3. Hacer un programa para Prolog que en la base de datos contenga lasuperficie y el numero de habitantes de las provincias andaluzas. El programa debe sercapaz de responder correctamente cuando se le pregunte por la densidad de las diferentesprovincias.

5. Estructuras de Datos

5.1. Arboles

La estructura mas conocida y usada en Prolog es la de arbol. Si dado un terminocompuesto

funtor(argumento1,...,argumentoN)

consideremos funtor como un nodo de arbol y de el hacemos colgar los arboles corres-pondientes a cada uno de los argumentos argumentok, con 1 ≤ k ≤ N , entonces hemosentendido el termino compuesto como un arbol.

15

Page 16: Manual Casero Prolog Beta 02

5.2. Listas

La programacion, y sobre todo en matematica discreta, no puede prescindir del conceptode lista.

Los miembros de las listas pueden ser terminos o listas. La lista queda definida de lasiguiente forma:

[ ] es una lista, la lista vacıa.

.(miembro1,miembro2) es una lista siempre que miembro1 y miembro2 sean miem-bros de listas; en cuyo caso a miembro1 se le llama cabeza de la lista y a miembro2

se le llama cola de la lista.

Ejemplo 5.1.

.(a,[ ]) es una lista, la lista [a].

.(a,.(b,.(c,[ ]))) es una lista, la lista [a,b,c].

En general, si la lista L tiene cabeza X y cola Y, L es representada como

[X|Y]

Para manipular lista Prolog cuenta con diversos procedimientos entre los cuales tene-mos: is list, append, member, delete, select, nth0, nth1, last, reverse, flatten,length, merge, sort, msort, etc.

Ejemplo 5.2. miembro debe ser un procedimiento que compruebe si un determinadoelemento pertenece a una lista. La idea serıa, por ejemplo, que una solicitud a miembrode un club esta entre las solicitudes al mismo si es la primera o esta entre el resto. ¿Comoexpresarıamos esto?

1. Primera idea:

miembro(E,L) :- L=[X|Y], X=E.

miembro(E,L) :- L=[X|Y], miembro(E,Y).

2. Segunda idea:

miembro(E,[X|Y]) :- X=E.

miembro(E,[X|Y]) :- miembro(E,Y).

3. Tercera idea:

miembro(X,[X|Y]).

miembro(E,[X|Y]) :- miembro(E,Y).

4. Cuarta idea:

16

Page 17: Manual Casero Prolog Beta 02

miembro(X,[X|_]).

miembro(E,[_|Y]) :- miembro(E,Y).

Hemos de destacar los procedimientos de Prolog para ordenar listas, que tienen lasiguiente sintaxis:

msort(+Lista,-ListaOrdenada)

sort(+Lista,-ListaOrdenada)

y que funcionan como sugiere el siguiente dialogo:

?- msort([a,t,v,a,m,f,g,l],L).

L = [a, a, f, g, l, m, t, v].

?- sort([a,t,v,a,m,f,g,l],L).

L = [a, f, g, l, m, t, v].

?- msort([a,1,0,[b,a]],L).

L = [0, 1, a, [b, a]].

Para ilustrar el trabajo con listas damos los siguientes ejemplos:

/* miembro(Elem,Lista) <- el termino Elem pertenece a la lista Lista */

miembro(X,[X|_]).

miembro(X,[_|Y]) :- miembro(X,Y).

/* nel(Lista,N) <- el numero de elementos de la lista Lista es N */

nel([],0).

nel([_|Y],N) :- nel(Y,M),

N is M+1.

/* es_lista(Lista) <- Lista es una lista */

es_lista([]).

es_lista([_|_]).

/* concatena(L1,L2,L3) <- concatenacion de las listas L1 y L2

dando lugar a la lista L3 */

concatena([],L,L).

concatena([X|L1],L2,[X|L3]) :- concatena(L1,L2,L3).

/* ultimo(Elem,Lista) <- Elem es el ultimo elemento de la lista Lista */

ultimo(X,[X]).

ultimo(X,[_|Y]) :- ultimo(X,Y).

/* inversa(Lista,Inver) <- Inver es la inversa de la lista Lista */

inversa([],[]).

inversa([X|Y],L) :- inversa(Y,Z),

concatena(Z,[X],L).

17

Page 18: Manual Casero Prolog Beta 02

/* borrar(Elem,L1,L2) <- se borra el elemento Elem de la lista L1

obteniendose la lista L2 */

borrar(X,[X|Y],Y).

borrar(X,[Z|L],[Z|M]) :- borrar(X,L,M).

/* subconjunto(L1,L2) <- la lista L1 es un subconjunto de la lista L2 */

subconjunto([X|Y],Z) :- miembro(X,Z),

subconjunto(Y,Z).

subconjunto([],_).

/* insertar(Elem,L1,L2) <- se inserta el elemento Elem en la lista L1

obteniendose la lista L2 */

insertar(E,L,[E|L]).

insertar(E,[X|Y],[X|Z]) :- insertar(E,Y,Z).

/* permutacion(L1,L2) <- la lista L2 es una permutacion de la lista L1 */

permutacion([],[]).

permutacion([X|Y],Z) :- permutacion(Y,L),

insertar(X,L,Z).

Ejercicio 5.3. Hacer los siguientes ejercicios:

1. Leer, comprobar el funcionamiento y familiarizarse con los procedimientos antesdescritos.

2. Escribir un procedimiento zip que actue sobre dos listas produciendo una terceracuyo i-esimo elemento sea la lista con dos componentes formada por el i-esimo dela primera, como primer elemento, y por el i-esimo de la segunda, como segundo;es decir, debe producir el siguiente dialogo:

?- zip([1,2],[a,b,c],L).

L = [[1, a], [2, b]]

3. Escribir un procedimiento que obtenga el elemento que ocupa la posicion n de unalista o la posicion que ocupa el elemento e:

?- elemento(E,3,[a,b,c,d]).

E = c

?- elemento(c,N,[a,b,c,d]).

N = 3

4. Modificar el procedimiento borrar para que borre el elemento que ocupa la posicionn de la lista:

?- borrar(3,[a,b,c,d],L).

L = [a,b,d]

18

Page 19: Manual Casero Prolog Beta 02

5.3. Coleccionando Soluciones.

Dada una Base de Concocimiento, para determinadas preguntas sobre ella puede habervarias respuestas. Considerese por ejemplo el siguiente codigo:

hijo(martha,charlotte).

hijo(charlotte,caroline).

hijo(caroline,laura).

hijo(laura,rose).

descendiente(X,Y) :- hijo(X,Y).

descendiente(X,Y) :- hijo(X,Z), descendiente(Z,Y).

que, una vez cargado, admite la siguiente pregunta:

?- descendiente(martha,X).

X = charlotte ;

X = caroline ;

X = laura ;

X = rose ;

false.

Es decir, hay cuatro soluciones, a saber: X=charlotte, X=caroline, X=laura y X=rose.Prolog aporta las soluciones a una pregunta una a una, no obstante puede interesarque nos las entregue todas juntas, de forma limpia y en un formato apto para ser usadas.Prolog dispone de tres predicados primitivos al efecto: findall, bagof y setof. Enesencia, estos predicados recolectan las repuestas a una pregunta y las colocan en unalista; no obstante, hay importantes diferencias entre ellos.

5.3.1. findall/3

La sintaxis de findall es la siguiente:

findall(+Objeto,+Objetivo,-Lista)

y produce una lista Lista de objetos Objeto que satisfacen el objetivo Objetivo. Porejemplo:

?- findall(X,descendiente(martha,X),Z).

Z = [charlotte, caroline, laura, rose].

No obstante, Objeto no tiene por que ser un sımbolo de variable, puede contener unsımbolo de variable que este en el objetivo. Por ejemplo, hemos decidido construir unpredicado nuevo deMartha/1 que es verdadero solo para los descendientes de martha. Lollevamos a cabo con:

?- findall(deMartha(X),descendiente(martha,X),Z).

Z = [deMartha(charlotte), deMartha(caroline), deMartha(laura), deMartha(rose)].

es decir, Z contiene todos los valores de deMartha(X) que satisfacen el objetivo descendiente(martha,X).

19

Page 20: Manual Casero Prolog Beta 02

Un uso menor, de findall es el siguiente:

?- findall(Y,descendiente(martha,X),Z), length(Z,N).

Z = [_G458, _G455, _G452, _G449],

N = 4.

en el que no nos interesaba tanto las soluciones como el numero de ellas.

Finalmente observese el siguiente dialogo:

?- findall(X,descendiente(mary,X),Z).

Z = [].

Ejercicio 5.4. Basandose en findall, escribir un predicado la lista de los primeros 8numeros naturales.

5.3.2. bagof/3

El predicado primitivo findall es util, pero a veces puede resultar algo crudo. Porejemplo:

?- findall(Hijo,descendiente(Madre,Hijo),Lista).

Lista = [charlotte,caroline,laura,rose,caroline,

laura,rose,laura,rose,rose]

Pero nos gustarıa tener una lista para cada una de las instancias de Madre. Esto es justolo que hace:

bagof(Hijo,descendiente(Madre,Hijo),Lista)

Vease lo siguiente:

?- bagof(Hijo,descendiente(Madre,Hijo),Lista).

Madre = caroline,

Lista = [laura, rose] ;

Madre = charlotte,

Lista = [caroline, laura, rose] ;

Madre = laura,

Lista = [rose] ;

Madre = martha,

Lista = [charlotte, caroline, laura, rose].

Si queremos que bagof se comporte como findall, es posible:

?- bagof(Hijo,Madre^descend(Madre,Hijo),Lista).

List = [charlotte, caroline, laura, rose, caroline,

laura, rose,laura, rose,rose].

Hay una diferencia mas respecto a findall. Observese el siguiente dialogo y comparesecon el oportuno de findall:

20

Page 21: Manual Casero Prolog Beta 02

?- bagof(X,descendiente(mary,X),Z).

false.

Es posible usar findall y bagof conjuntamente. Observar el siguiente dialogo:

?- findall(List,bagof(Child,descendiente(Mother,Child),List),Z).

Z = [[laura, rose], [caroline, laura, rose], [rose],

[charlotte, caroline, laura, rose]].

Pero esto mismo es obtenido con:

?- bagof(List,Hijo^Madre^bagof(Hijo,

descendiente(Madre,Hijo),List),Z).

5.3.3. setof/3

El predicado predefinido setof/3 funciona como bagof, pero la lista resultado esta or-denada y no contiene repeticiones.

Considerar el sitguiente codigo:

edad(harry,13).

edad(draco,14).

edad(ron,13).

edad(hermione,13).

edad(dumbledore,60).

edad(hagrid,30).

Si lo cargamos, podemos efectuar al siguiente consulta:

?- findall(X,edad(X,Y),Lista).

Lista = [harry, draco, ron, hermione, dumbledore, hagrid].

?- setof(X,Y^edad(X,Y),Lista).

Lista = [draco, dumbledore, hagrid, harry, hermione, ron].

y aun mas explıcito es el siguiente:

?- findall(Y,edad(X,Y),Lista).

Lista = [13, 14, 13, 13, 60, 30].

?- setof(Y,X ^ edad(X,Y),Lista).

Lista = [13, 14, 30, 60].

5.4. Conjuntos

Prolog implementa unos predicados para manipular conjuntos. Para SWI–Prolog losconjuntos son listas sin repeticiones.

Destacamos los siguientes predicados:

21

Page 22: Manual Casero Prolog Beta 02

is set(+Lista); tiene exito cuando Lista es un conjunto.

?- is_set([1,2,3]).

true.

?- is_set([1,2,3,3]).

false.

list to set(+Lista,-Conjunto): Conjunto es el conjunto de elementos de Lista.Por tanto, Lista y Conjunto coinciden si Lista no tiene repeticiones; pero si lastiene, Conjunto es Lista sin repeticiones.

?- list_to_set([1,3,3,2],X).

X = [1, 3, 2].

?- list_to_set([1,3,2],X).

X = [1, 3, 2].

intersection(+Set1,+Set2,-Set3); Set3 es la interseccion de Set1 con Set2.Prolog no comprueba si Set1 y Set2 son conjuntos, por lo que Set3 podrıa noser conjunto.

?- intersection([1,3,2],[3,4,5,2],X).

X = [3, 2].

?- intersection([1,3,2,2],[3,4,5,2],X).

X = [3, 2, 2].

subtract(+Set,+Delete,-Result); elimina de Set todos los elementos del con-junto Delete.

?- subtract([1,2,3,3],[2],X).

X = [1, 3, 3].

?- subtract([1,2,3,3],[2,3],X).

X = [1].

union(+Set1, +Set2, -Set3); Set3 es la union de Set1 y Set2.

?- union([1,2],[2,3],X).

X = [1, 2, 3].

subset(+Subset, +Set): indaga si Subset es un subconjunto de Set.

?- subset([1],X).

X = [1|_G598].

?- subset([1],[1,2]).

true.

22

Page 23: Manual Casero Prolog Beta 02

Ejercicio 5.5. Redefinir intersection en un nuevo predicado interseccion(+Set1,+Set2,-Set3)

tal que si Set1 o Set2 no son conjuntos, Set3 sı lo sea. Extender esta accion al resto depredicados antes enumerados para los que quepa.

Ejercicio 5.6. El predicado subset presenta el siguiente comportamiento:

?- subset(X,[1,2,3]).

X = [].

¿Como podrıamos mejorarlo?

5.5. La estructura de los terminos

En Prolog un programa puede ser visto como una estructura. Para manejar las estruc-turas tenemos esencialmente los siguientes predicados:

functor

arg

=..

name

que tiene la utilidad que se explica seguidamente.

5.5.1. functor

La sintaxis de functor es:

functor(estructura,nombre,ariedad)

donde estructura es una estructura con nombre nombre y ariedad ariedad. Para ver sumanejo consideremos el siguiente dialogo:

?- functor(f(a,b),F,A).

F = f,

A = 2.

?- functor(coche,F,A).

F = coche,

A = 0.

?- functor(1+2,F,A).

F = +,

A = 2.

?- functor([1,2,3],F,A).

F = ’.’,

A = 2.

23

Page 24: Manual Casero Prolog Beta 02

?- functor(L,libro,2).

L = libro(_G286, _G287).

?- functor(1+2+3,+,2).

true.

?- functor(1+2+3,+,3).

false.

Ejercicio 5.7. Utilizar functor para decidir cuando un termino dado es compuesto.

5.5.2. arg

La sintaxis de arg es:

arg(?Posicion,?Estructura,?Argumento)

donde el argumento de la Estructura que ocupa la posicion Posicion es Argumento.Para ver su manejo consideremos el siguiente dialogo:

?- arg(2,ama(vicente,logica),X).

X = logica.

?- arg(2,ama(vicente,X),logica).

X = logica.

?- arg(2,es_feliz(roberta),X).

false.

?- arg(1,[a,b,c],Arg).

Arg = a.

?- arg(1,p(x,f(y)),Arg).

Arg = x.

?- arg(2,p(x,f(y)),Arg).

Arg = f(y).

5.5.3. =..

La sintaxis de =.. es:

?Estructura =.. ?Lista

donde si Estructura es instanciada, Lista sera una lista cuya primera componente (ca-beza) es el functor de Estructura y el resto (cola) los distintos argumentos de dichaestructura. Si Lista esta instanciada, creara una Estructura cuyo functor sera la cabe-za de la lista y cuyos argumentos seran los distintos elementos de la lista. Para ver sumanejo consideremos el siguiente dialogo:

24

Page 25: Manual Casero Prolog Beta 02

?- p(x,f(y),z) =.. L.

L = [p, x, f(y), z].

?- E =.. [+,2,3].

E = 2+3.

Ejercicio 5.8. Defınase un predicado llamado copy term el cual haga una copia deun termino reemplazando las variables que ocurran en el termino original por nuevasvariables en la copia.

Solucion. copy_term(X,_) :- var(X).

copy_term(X,X) :- atomic(X).

copy_term(X,Y) :- nonvar(X),

functor(X,F,A),

functor(Y,F,A),

A > 0,

X =.. [F|ArgsX],

Y =.. [F|ArgsY],

copy_terms_in_list(ArgsX,ArgsY).

copy_terms_in_list([],[]).

copy_terms_in_list([HIn|TIn],[HOut|TOut]) :- copy_term(HIn,Hout),

copy_terms_in_list(TIn,TOut).

5.5.4. name

La sintaxis de name es:

name(?Atomo,?Lista)

donde si Atomo es un atomo formado por los caracteres de la lista Lista. Puede tan-to crear un atomo con los caracteres de la lista como crear una lista de los caracterescorrespondientes al atomo. Para ver su manejo consideremos el siguiente dialogo:

?- name(prolog,L).

L = [112, 114, 111, 108, 111, 103].

?- name(Atomo,[112, 114, 111, 108, 111, 103]).

Atomo = prolog.

?- name(estacion,"estacion").

true.

6. Recursos de Control en la Programacion

Destacamos las siguientes herramientas:

25

Page 26: Manual Casero Prolog Beta 02

1. Recursion (recursion)

2. Unificacion (unification, matching)

3. Reevaluacion (backtracking)

4. Corte (cut)

6.1. Recursion (recursion)

En el apartado que hemos llamado Listas (subseccion 5.2) hemos visto como las reglasdefinitorias incluıan en su cuerpo el mismo termino termino que aparecıa en su cabeza.Esta practica es de extrema utilidad en programacion si no cae en el clasico problemade la “peticion de principio”. Para ello, uno de los argumentos de la definicion en lallamada recursiva debe decrecer o crecer, para poder unificar en determinado paso conuna clausula que ha sido establecida a modo de “condicion de parada”.

Ejemplo 6.1. Consideremos la definicion:

nel([],0).

nel([_|Y],N) :- nel(Y,M),

N is M+1.

que es un ejemplo de definicion recursiva. En ella la condicion de parada es

nel([],0).

y la clausula que hace evolucionar los parametros es:

nel([_|Y],N) :- nel(Y,M),

N is M+1.

El flujo del programa para nel([a,[b,c],d],N) en resumen serıa:

1. nel([a,[b,c],d],N) (comienzan las llamadas recursivas)

2. nel([[b,c],d],M1) (la lista decrece en “longitud”)

3. nel([d],M2)

4. nel([],M3) (actua la condicion de detencion)

5. M3=0 (comienza el calculo en retroceso)

6. M2=M3+1=0+1=1

7. M1=M2+1=1+1=2

8. N=M1+1=2+1=3

9. N=3 (concluye con el resultado)

Si se quiere se puede pedir a Prolog un informe del flujo del programa:

26

Page 27: Manual Casero Prolog Beta 02

?- trace, nel([a,[b,c],d],N), notrace.

Call: (7) nel([a, [b, c], d], _G726) ? creep

Call: (8) nel([[b, c], d], _G893) ? creep

Call: (9) nel([d], _G893) ? creep

Call: (10) nel([], _G893) ? creep

Exit: (10) nel([], 0) ? creep

^ Call: (10) _G898 is 0+1 ? creep

^ Exit: (10) 1 is 0+1 ? creep

Exit: (9) nel([d], 1) ? creep

^ Call: (9) _G901 is 1+1 ? creep

^ Exit: (9) 2 is 1+1 ? creep

Exit: (8) nel([[b, c], d], 2) ? creep

^ Call: (8) _G726 is 2+1 ? creep

^ Exit: (8) 3 is 2+1 ? creep

Exit: (7) nel([a, [b, c], d], 3) ? creep

N = 3.

o tambien:

?- trace(nel).

% nel/2: [call,redo,exit,fail]

true.

[debug] ?- nel([a,[b,c],d],N).

T Call: (6) nel([a, [b, c], d], _G1180)

T Call: (7) nel([[b, c], d], _G1288)

T Call: (8) nel([d], _G1288)

T Call: (9) nel([], _G1288)

T Exit: (9) nel([], 0)

T Exit: (8) nel([d], 1)

T Exit: (7) nel([[b, c], d], 2)

T Exit: (6) nel([a, [b, c], d], 3)

N = 3.

Los dos grandes errores en el planteamiento de una recursion son:

1. la recursion circular con la que se entra en un bucle que no termina nunca. Es loque tradicionamente ha recibido en nombre de “peticion de principio”. Por ejemplo:

padre(X,Y) :- hijo(Y,X).

hijo(A,B):- padre(B,A).

2. y la llamada recursion a izquierdas que esencialmente supone la “definicion indefi-nida porque sı”. Por ejemplo:

persona(X) :- persona(Y), madre(X,Y).

persona(adam).

27

Page 28: Manual Casero Prolog Beta 02

Ejemplo 6.2. Como ejemplo correcto traemos ahora el clasico y bello ejemplo de lasolucion a las Torres de Hanoi. El programa torres hanoi.pl contiene el siguiente texto:

mover(1,X,_,Z) :-

write(’Mueva el disco superior de ’),

write(X),

write(’ a ’),

write(Z),

nl.

mover(N,X,Y,Z) :-

N>1,

M is N-1,

mover(M,X,Z,Y),

mover(1,X,_,Z),

mover(M,Y,X,Z).

torres_hanoi(N) :- mover(N,izq,cen,der).

donde aparece:

1. Una condicion de parada siempre satisfacible dado que presupone un trabajo com-puesto de impresion por pantalla.

2. Una llamada recursiva con disminucion del parametro inicial, de forma que algunavez llegue a valer 1.

3. Una simplificacion de la llamada.

Ejercicio 6.3. Dar una implementacion que simule los numeros naturales y definir,dentro de esa simulacion, la suma y el producto.

6.2. Unificacion (unification, matching)

La unificacion constituye uno de los mecanismos esenciales de Prolog junto a la re-solucion, sin ambos serıa imposible extraer respuestas. Cuando se desencadena es parainstanciar variables de forma que dos terminos coincidan tras dicha instanciacion. Si losterminos t1 y t2 son unificables, Prolog encuentra una sustitucion de variables M tal queaplicada M a t1 da el mismo resultado que aplicada a t2. Si no son unificables, Prolog lopone de manifiesto. El algoritmo que usa es en esencia el clasico algoritmo de unificacionvisto en teorıa. Tener en cuenta el siguiente dialogo:

?- p(X,f(Y),a) = p(a,f(a),Y).

X = a,

Y = a.

?- p(X,f(Y),a) = p(a,f(b),Y).

false.

28

Page 29: Manual Casero Prolog Beta 02

?- p(X,f(Y),a) = p(Z,f(b),a).

X = Z,

Y = b.

?- p(X,f(Y),a) = p(Z,f(b),a), X is 1.

X = 1,

Y = b,

Z = 1.

?- p(X,f(Y),a) = p(Z,f(b),a), X=d.

X = d,

Y = b,

Z = d.

Cuando una varible deba ser instanciada a un termino que la contiene, la unificacion falla,como sabemos. Nos es de ayuda en este caso el procedimiento binario: unify with occurs check.Considerar lo siguiente:

?- X=f(X).

X = f(**).

?- unify_with_occurs_check(X,f(X)).

false.

?- X=f(X), X=a.

false.

a no puede ser unificada con f(X):

?- a \= f(X).

true.

6.3. Reevaluacion (backtracking)

La reevaluacion consiste en revisar lo hecho para intentar extraer una respuesta alter-nativa resatisfaciendo los objetivos. Cuando Prolog acaba de dar una respuesta, lareevaluacion se desencadena escribiendo y ejecutando ;. ¿Como busca Prolog respues-tas?:

Trata de satisfacer objetivos buscando en la base de conocimiento:

• si existe un hecho que pueda unificar con el objetivo, marca el lugar en la basede conocimientos e instancia todas las variables que coincidan previamente noinstanciadas. Si el hecho es la cabeza de una regla con cuerpo, intenta satisfacerlos objetivos del cuerpo de la regla.

• si no encuentra ningun hecho que unifique, el objetivo ha fallado e intentaresatisfacer el objetivo anterior.

29

Page 30: Manual Casero Prolog Beta 02

Resatisfacer consiste en intentar resatisfacer cada uno de los objetivos del cuerpo dela regla por orden inverso. Para ello intenta encontrar una clausula alternativa parael objetivo, en cuyo caso, se dejan sin instanciar todas las variables instanciadas alelegir la clausula previa. La busqueda es retomada desde donde se habıa dejado elmarcardor de posicion de objetivo.

Ejemplo 6.4. Considerar el programa digestion.pl:

acaba_de_comer(mosquito,sangre(pedro)).

acaba_de_comer(mosquito,nectar).

acaba_de_comer(mosquito,savia).

acaba_de_comer(pez,mosquito).

acaba_de_comer(serpiente,pez).

acaba_de_comer(oso,pez).

acaba_de_comer(aguila,serpiente).

acaba_de_comer(rana,mosquito).

acaba_de_comer(garza,rana).

acaba_de_comer(aguila,perdiz).

acaba_de_comer(perdiz,trigo).

esta_digiriendo(X,Y) :- acaba_de_comer(X,Y);

acaba_de_comer(X,Z),

esta_digiriendo(Z,Y).

que cargado en el entorno nos permitirıa:

?- [’digestion.pl’].

% digestion.pl compiled 0.00 sec, 148 bytes

true.

?- esta_digiriendo(X,Y).

Analıcese la extensa respuesta.

6.4. Corte (cut)

El termino corte de Prolog, representado por !, elimina opciones en un arbol de deri-vacion Prolog. El objetivo corte tiene exito cada vez que es considerado como objetivoactual, y el arbol de derivacion resulta podado de todas las otras opciones en el caminode regreso, incluyendo el punto en el arbol de derivacion en el que se introdujo el cortecomo parte de la secuencia de objetivos. El corte se satisface incondicionalmente, perono se puede resatisfacer. El corte se convierte en un impedimento que impide al procesode reevaluacion el franqueo del camino de vuelta hacia atras, convirtiendo en inaccesiblestodos los marcadores de las metas que se encuentran a su izquierda. Si se quiere, se puedeimaginar como una valvula que permite el paso en un sentido —del flujo del programa,pero que lo impide en el contrario.

30

Page 31: Manual Casero Prolog Beta 02

El corte es una intervencion en la forma automatica de aplicar recursion, unificacion yreevaluacion de Prolog, que sesga la misma. Optimiza el tiempo de ejecucion, no mal-gastando el tiempo en satisfacer objetivos que de antemano sabemos que no contribuirana una solucion. Optimiza el uso de la memoria no registrando puntos de reevaluacionpara un examen posterior. Aunque cabe que haga difıcil la comprension de un programa,su uso puede ser la diferencia entre que un programa funcione o que no funcione. En fin,el corte es imprescindible en la programacion con Prolog.

Ejercicio 6.5. Considerar el programa que fuera:

sumatorio(1,1) :- !.

sumatorio(N,S) :- N1 is N-1,

sumatorio(N1,S1),

S is N+S1.

y decir que ocurrirıa si en lugar de la primera lınea, tuviesemos simplemente sumatorio(1,1).

7. Usos del Corte

Vamos a destacar tres usos del corte:

Confirmacion

Advertencia

Finalizacion

7.1. Confirmacion

Con el corte podemos confirmar al flujo de Prolog de que si ha franqueado el corte, siguela regla correcta. Si las metas siguientes fracasan, debera fracasar el objetivo. Podemosejemplificar este uso en una simulacion del if-then-else clasico en programacion. Paraello, considerar el texto:

a :- b,!,c.

a :- d.

que expresado en una forma ineficiente (puede acabar intentando satisfacer b dos veces)pero mas clara, serıa

a :- b,c.

a :- not(b),d.

Como ejemplo de este uso nos vale tambien el programa correcto que figura en el Ejercicio6.5.

Ejercicio 7.1. Hacer un programa en Prolog que dada una lista de numero enteros,suprima de ella los numeros impares.

31

Page 32: Manual Casero Prolog Beta 02

7.2. Advertencia

Usando el corte en combinacion con el predicado de fallo fail podemos dar cuenta deque el hecho ha de fracasar sin intentar encontrar soluciones alternativas. fail siemprefracasa como objetivo. Considerese el siguiente programa no.pl en el que se define lanegacion por fallo; es realmente la definicion Prolog de not:

no(Q) :- call(Q), !, fail.

no(Q).

Explicaremos posteriormente el significado de call, pero adelantamos que call(P) fuerzaa que P sea un objetivo; tiene exito si lo tiene P y fracasa en otro caso. De hecho, lo quehacemos en P es tomar a P como una varible de termino.

7.3. Finalizacion

Podemos usar el corte para informar a Prolog que deseamos finalizar la generacion de so-luciones alternativas mediante reevaluacion. Considerese el siguiente programa divisionEntera.pl:

/* natural(Num) <- Num es un numero perteneciente a los Naturales */

natural(0).

natural(X) :- natural(Y),

X is Y+1.

/* diventera(Dividendo,Divisor,Cociente) <- Cociente es el resultado

de la division entera entre Dividendo y Divisor */

diventera(A,B,C) :- natural(C),

Y1 is C*B,

Y2 is (C+1)*B,

Y1=<A, Y2>A, !.

Que es un generador de numeros naturales hasta encontrar un valor de C que cumpla lacondicion:

B*C =<A <B*(C+1)

siendo A el dividendo y B el divisor de la division. La regla natural va generandoinfinitos numeros naturales, pero solo uno de ellos es el que nos interesa y sera el quepase la condicion. Ası, el corte al final de la regla impide que en un posible proceso dereevaluacion entremos en un bucle infinito: hemos encontrado la unica solucion y no hayninguna razon para volver a buscar otra.

Ejercicio 7.2. Encontrar en que falla la siguiente definicion de maximo:

max_mal(X,Y,Y) :- Y>X.

max_mal(X,Y,X).

y arreglarla. Justificar por que es ineficiente la siguiente version:

max_ineficiente(X,Y,Y) :- Y>X.

max_ineficiente(X,Y,X) :- not(Y>X).

32

Page 33: Manual Casero Prolog Beta 02

Ejercicio 7.3. Considerar el programa pruebaCorte.pl

p(e).

p(X) :- q(X),r(X).

p(X) :- u(X).

q(X) :- s(X).

r(a).

r(b).

s(a).

s(b).

s(c).

u(d).

Efectuar en pruebaCorte.pl los siguientes cambios e interpretar los resultados de pedira Prolog la pregunta p(X).:

con el programa tal cual.

sustituyendo la lınea segunda por p(X) :- !, q(X), r(X).

sustituyendo la lınea segunda por p(X) :- q(X),! , r(X).

sustituyendo la lınea segunda por p(X) :- q(X), r(X), !.

cambiando las lıneas 2 y 3 por las siguientes respectivamente:

p(X) :- u(X).

p(X) :- !,q(X),r(X).

cambiando las lıneas 1, 2 y 3 por las siguientes respectivamente:

p(e) :- !.

p(X) :- q(X),r(X).

p(X) :- u(X).

7.4. Efectos indeseados, pero tolerables, del corte

Mientras que un corte puede ser inofensivo, o incluso beneficioso, cuando se utiliza unaregla de una forma dada, el mismo corte puede provocar un comportamiento extrano si laregla se utiliza de otra forma. Considerar el programa discusionCorte.pl que contiene:

/* concatena(L1,L2,L3) <- concatenacion de las listas L1 y L2

dando lugar a la lista L3 */

concatena([],L,L) :- !.

concatena([X|L1],L2,[X|L3]) :- concatena(L1,L2,L3).

33

Page 34: Manual Casero Prolog Beta 02

Cuando se consideran objetivos de la forma:

?- [’discusionCorte.pl’].

% discusionCorte.pl compiled 0.00 sec, 5,736 bytes

true.

?- concatena([a,b,c],[d,e],X).

X = [a, b, c, d, e].

?- concatena([a,b,c],X,[a, b, c, d, e]).

X = [d, e].

el corte resulta muy adecuado, pero si tenemos el objetivo:

?- concatena(X,Y,[a,b,c]).

X = [],

Y = [a, b, c].

no ofrece todas las soluciones posibles.

Por tanto, la introduccion del corte debe contar, en todo caso, con el uso que se va ahacer de la regla.

7.5. Predicados de control

Existen unos predicados predefinidos que ayudan cuando queremos utilizar estructurasde control. Por ejemplo:

fail, siempre falla.

true, siempre tiene exito.

repeat, permite simular bucles junto con la combinacion corte–fail. Considerese elsiguiente ejemplo:

/*-----------------------------------------------------------*/

/* PROGRAMA PRINCIPAL */

/* */

menu :- cabecera,

repeat,

leer(Formula),

hacer(Formula).

hacer(X) :- integer(X), X=0.

hacer(’A’) :- cabecera, ayuda, !, fail.

hacer(’a’) :- cabecera, ayuda, !, fail.

34

Page 35: Manual Casero Prolog Beta 02

hacer(Formula) :- fbf(Formula),

formaNormal(Formula,FNC,FND),

escribirFormasNormales(FNC,FND),

pausa,!, fail.

hacer(_) :- pausa,!,fail.

/* */

/* Fin Programa Principal */

/* */

/*-----------------------------------------------------------*/

+Condicion ->+Accion, permite simular la estructura condicional: si-entonces ysi-entonces-sino

rojo(a).

negro(b).

clr(Y,rojo) :- rojo(Y),!.

clr(Y,negro) :- negro(Y),!.

clr(Y,desconocido).

% "color_alt" tiene el mismo efecto que "clr"

% "->" simula el uso de "!"

color_alt(X,C) :- red(X) -> C = red

;

black(X) -> C = black

;

C = unknown.

7.6. Otros ejemplos

Presentamos ejemplos de uso del corte en programas.

/* borrar(Elem,L1,L2) <- L2 es la lista resultado de borrar todas las

ocurrencias del elemento Elem de la lista L1 */

borrar(_,[],[]).

borrar(E,[E|L1],L2) :- !,borrar(E,L1,L2).

borrar(E,[A|L1],[A|L2]) :- borrar(E,L1,L2).

/* sust(E1,E2,L1,L2) <- L2 es la lista resultado de sustituir en la lista

L1 todas las ocurrencias del elemento E1 por E2 */

sust(_,_,[],[]).

sust(E1,E2,[E1|L1],[E2|L2]) :- !, sust(E1,E2,L1,L2).

sust(E1,E2,[Y|L1],[Y|L2]) :- sust(E1,E2,L1,L2).

35

Page 36: Manual Casero Prolog Beta 02

/* union(L1,L2,L3) <- L3 es ls lista-conjunto union de las

listas-conjuntos L1 y L2 */

union([],L,L).

union([X|L1],L2,L3) :- miembro(X,L2), !,

union(L1,L2,L3).

union([X|L1],L2,[X|L3]) :- union(L1,L2,L3).

8. La I/O en Prolog

Si se desea una mayor interaccion de Prolog con el usuario que la mera presentacionpor pantalla de los resultados a nuestras preguntas, por unificacion entre las mismas y labase clausular del programa, es preciso recurrir a otro tipo de predicados. Se trata de lospredicados Entrada/Salida, que cumplen por coherencia lo siguiente:

Se evaluan siempre a verdad.

Nunca se pueden resatisfacer: la reevaluacion continua hacia la izquierda.

Tiene un efecto lateral, no logico, durante su ejecucion: entrada o salida de uncaracter, termino, etc.

8.1. Lectura y escritura de terminos

Destacamos lo siguiente:

write(+Termino); si Termino esta instanciado a un termino, lo saca por pantalla.En caso contrario, se sacara por pantalla una variable numerada de forma unica(por ejemplo: G245).

nl; la salida posterior se presenta en la siguiente lınea de la pantalla.

write ln(+Termino); es equivalente a write(+Termino), nl

writef(+Formato,+Termino); escritura con formato.

tab(+X); desplaza el cursor a la derecha X espacios, para ello X debe estar instan-ciada a un entero (una expresion evaluada como un entero positivo).

sisplay(+Termino); se comporta como write(+Termino), excepto que pasa poralto cualquier declaracion de operadores que se haya hecho.

read(-Termino); lee el siguiente termino que se teclee desde el ordenador. Debe irseguido de un punto “.” y un “retorno de carro”. Instancia Termino al termino leıdo,si Termino no estaba instanciada. En caso contrario, los compara y se satisfara ofracasara dependiendo del exito de la comparacion.

Ejemplo 8.1. Considerese el fichero io ejemplo.pl que contiene lo siguiente:

36

Page 37: Manual Casero Prolog Beta 02

/* ibl(L) <- imprime la lista L de forma bonita, es decir

saca por pantalla los elementos de la lista

separados por un espacio y terminado en salto

de lınea */

ibl([]) :- nl.

ibl([X|Y]) :- write(X),

tab(1),

ibl(Y).

/* escribe_cadena(L) <- escribe en pantalla la lista L de

codigos ASCII en forma de cadena de

caracteres */

escribe_cadena([]).

escribe_cadena([X|Y]) :- put(X),

escribe_cadena(Y).

Que presenta el siguiente comportamiento:

?- [’io_ejemplo.pl’].

% io_ejemplo.pl compiled 0.00 sec, 1,084 bytes

true.

?- write(8+5*6),nl,display(8+5*6).

8+5*6

+(8,*(5,6))

true.

?- write(8+5*6), nl, display(8+5*6).

8+5*6

+(8,*(5,6))

true.

?- X=[esto,es,una,lista], write(X), nl, display(X), nl, ibl(X).

[esto,es,una,lista]

.(esto,.(es,.(una,.(lista,[]))))

esto es una lista

X = [esto, es, una, lista].

?- writef(’Atomo = %w\nNumero = %w\n’,[pepe,4.5]).

Atomo = pepe

Numero = 4.5

true.

8.2. Lectura y escritura de caracteres

Prolog trata los caracteres como enteros, haciendoles corresponder su codigo ASCII.Considerese lo siguiente:

37

Page 38: Manual Casero Prolog Beta 02

put(+Caracter); si Caracter esta instanciada a un entero entre 0 y 255, saca porpantalla el caracter correspondiente a ese codigo ASCII. Si Caracter no esta ins-tanciada o no es entero, proporciona error.

get(-Caracter); lee caracteres desde el teclado, instanciando Caracter al primercaracter imprimible que se teclee. Si Caracter ya esta instanciada, los comparasatisfaciendose o fracasando.

get0(-Caracter); igual que get(-Caracter) sin importar el tipo de caracter te-cleado.

skip(+Caracter); lee del teclado hasta el caracter Caracter o el final del fichero.

Ejemplo 8.2. Considerese el siguiente codigo incluıdo en el fichero io ejemplo.pl:

/* escribe_cadena(L) <- escribe en pantalla la lista L de

codigos ASCII en forma de cadena de

caracteres */

escribe_cadena([]).

escribe_cadena([X|Y]) :- put(X),

escribe_cadena(Y).

que proporciona el siguiente dialogo:

?- [’io_ejemplo.pl’].

% io_ejemplo.pl compiled 0.00 sec, 1,084 bytes

true.

?- escribe_cadena([80,114,111,108,111,103]).

Prolog

true.

?- put(80),put(114),put(111),put(108),put(111),put(103).

Prolog

true.

8.3. Lectura y escritura en ficheros

Existe un fichero predefinido llamado user. Al leer de este fichero se hace que al informa-cion de entrada venga desde el teclado, y al escribir, se hace que los caracteres aparezcanen al pantalla; este es el modo normal de funcionamiento. Pero pueden ser escritos termi-nos y caracteres sobre ficheros utilizando los mismos predicados que se acaban de ver. launica diferencia es que cuando queramos escribir o leer en un fichero debemos cambiar elcanal de salida activo o el canal de entrada activo, respectivamente.

Posiblemente queramos leer y escribir sobre ficheros almacenados en discos. Cada unode estos tendra un nombre de fichero que utilizaremos para identificarlo. En Prologlos nombres de ficheros se representan como atomos. Los ficheros tienen una longituddeterminada, es decir, contienen un cierto numero de caracteres. Al final del fichero hay

38

Page 39: Manual Casero Prolog Beta 02

una marca especial de fin de fichero. Cuando la entrada viene del teclado, puede generarseun fin de fichero tecleando el caracter de control ASCII 26 o Ctrl+Z. Se pueden tenerabiertos varios ficheros, si conmutamos el canal de salida activo sin cerrarlos (told),permitiendonos escribir sobre ellos en varios momentos diferentes, sin destruir lo escritopreviamente.

Destacamos lo siguiente:

tell(+NomFichero); si NomFichero esta instanciada al nombre de un fichero, cam-bia el canal de salida activo. Crea un nuevo fichero con ese nombre. Si NomFicherono esta instanciada o no es un nombre de fichero, producira un error.

telling(?NomFichero); si NomFichero no esta instanciada, la instanciara al nom-bre del fichero que es el canal de salida activo. En caso contrario, se satisface si esel nombre del fichero actual de salida.

told; cierra el fichero para escritura y dirige la salida hacia la pantalla.

see(+NomFichero); si NomFichero esta instanciada al nombre de un fichero, cambiael canal de entrada activo al fichero especificado. La primera vez que se satisface,el fichero pasa a estar abierto y empezamos al comienzo del fichero. Si NomFicherono esta instanciada o no es un nombre de fichero, producira un error.

seeing(?NomFichero); si NomFichero no esta instanciada, la instanciara al nombredel fichero que es el canal de entrada activo. En caso contrario, se satisface si es elnombre del fichero actual de entrada.

seen; cierra el fichero para lectura y dirige la entrada hacia el teclado.

Ejemplo 8.3.

/* secuencia normal de escritura */

... , tell(fichero), write(X), told, ...

/* conmutacion de ficheros */

... , tell(fichero), write(A), tell(user), write(B),

tell(fichero), write(C), told.

/* secuencia normal de lectura */

... , see(fichero), read(X), seen, ...

9. Modificacion de la Base de Conocimiento

Presentaremos una serie de predicados predefinidos en Prolog que nos permitiran mani-pular la Base de Conocimiento consultando, anadiendo, eliminando o modificando clausu-las.

39

Page 40: Manual Casero Prolog Beta 02

9.1. Adicion de Bases de Conocimiento externas

Si queremos que Prolog lea nuevas clausulas de un fichero que hemos preparado pre-viamente, podemos utilizar los predicados consult y reconsult. Esto sera convenientecuando tengamos que trabajar con programas de tamano considerable y no queramosteclear cada vez todas las clausulas. Ası, podremos crear el programa con nuestro editorde textos preferidos (sugerimos el uso de Emacs) para posteriores usos, con la ventajaanadida de que lo podremos modificar y ampliar en cualquier momento.

Destacamos lo siguiente:

consult(+Fichero); el predicado predefininido consult anade las clausulas exis-tentes en el fichero de nombre Fichero a la base de conocimiento de Prolog, alfinal de las ya existentes, sin destruir las anteriores. Como argumento pasamos unatomo con el nombre del fichero del que queremos leer las clausulas. Recordemosque un atomo esta formado por letras, dıgitos y el caracter de subrayado. Si que-remos que contenga otros caracteres (los dos puntos “:” para la unidad, la barra“/” para el directorio o el punto “.” para la extension1 deberemos encerrarlo entrecomillas simples.

reconsult(+Fichero); el predicado predefinido reconsult actua como consult

excepto que, de existir clausulas para un mismo predicado (nombre y ariedad), lasnuevas sustituyen a las existentes.2 Se suele utilizar para la correccion de erroresmientras se esta realizando el programa, ya que de esta manera la nueva versionsustituye a la anterior erronea. Tambien es interesante cuando queremos asegurarque se utilizan las clausulas que vamos a leer, y no otras posibles con el mismonombre que tuviese el sistema de alguna consulta anterior.

La mayor parte de las implementaciones permiten una notacion especial para consultaruna lista de ficheros, uno tras otro: la notacion en forma de lista. Consiste en ponerlos nombres de los ficheros en una lista y darla como objetivo a satisfacer. Si se quiereconsultar un fichero, se pone el nombre en la lista tal cual, mientras que si se quierereconsultar se pone el nombre precedido de un signo “-”. A modo de ejemplo considerese:

?- consult(fichero).

?- reconsult(fichero).

?- [fichero1, -fichero2, -’prueba’, ’/home/usuario/prueba’].

?- consult(’practica1.pro’).

?- reconsult(’/home/usuario/practica1.pl’).

?- [’/home/usuario/prueba.pl’].

1SWI-Prolog asume por defecto la extesion “.pl” y Prolog–2 toma la extension “.pro”. Peroesto dependera del sistema Prolog utilizado y se puede personalizar.

2SWI-Prolog no tiene un predicado reconsult ya que al consultar un fichero ya almacenado,automaticamente es reconsultado.

40

Page 41: Manual Casero Prolog Beta 02

?- [-’/home/usuario/prueba.pl’].

9.2. Manipulacion de la Base de Conocimiento

A veces es muy conveniente enriquecer la Base de Conocimiento con nuevas clausulas,incluso resultado de alguna computacion. A tal fin existen en Prolog predicados prede-finidos, entre los que destacamos los siguientes:

listing; escribe todas las clausulas de la Base de Conocimiento en el fichero desalida activo.

listing(+Predicado); muestra por el fichero de salida activo (pantalla por defecto)todas las clausulas que tienen como predicado el atomo al que esta instanciada avariable Predicado.

clause(?Cabeza,?Cuerpo); se hace coincidir Cabeza con la cabeza y Cuerpo con elcuerpo de una clausula existente en la Base de Conocimiento. Por lo menso Cabeza

debe estar instanciada. Un hecho es considerado como una clausula cuyo cuerpo estrue.

assert(+Clausula), asserta(+Clausula), assertz(+Clausula); estos predica-dos permiten anadir nuevas clausulas a la Base de Conocimiento. El predicadoasserta la anade al principio (observar la letra “a”) y assertz la anade al final(observar la letra “z”) de cualquier otra clausula del mismo tipo que hubiese en laBase de Conocimiento. En todos los casos, Clausula debe estar previamente instan-ciada a una clausula. Dicha clausula queda incorporada a la Base de Conocimientoy no se pierde aunque se haga reevaluacion. Como ejemplo considerar el siguientedialogo:

?- asignatura(X).

ERROR: toplevel: Undefined procedure: asignatura/1 (DWIM could not correct goal)

?- assert(asignatura(logica_informatica)).

true.

?- asserta(asignatura(flp)).

true.

?- assertz(asignatura(lmd)).

true.

?- asignatura(X).

X = flp ;

X = logica_informatica ;

X = lmd.

retract(+Clausula), retractall(+Clausula); nos permite eliminar una clausu-la de la Base de Conocimiento. Para ello, Clausula debe estar instanciada y se

41

Page 42: Manual Casero Prolog Beta 02

quitara la primera clausula de la Base de Conocimiento que empareje con ella. Si seresatisface el objetivo, se iran eliminando, sucesivamente, las clausulas que coinci-dan. Con retractall se eliminaran todas. Como ejemplo, considerese el siguiente:

?- listing(asignatura).

:- dynamic asignatura/1.

asignatura(flp).

asignatura(logica_informatica).

asignatura(lmd).

true.

?- retract(asignatura(lmd)).

true.

?- listing(asignatura).

:- dynamic asignatura/1.

asignatura(flp).

asignatura(logica_informatica).

true.

?- retract(asignatura(X)).

X = flp .

?- listing(asignatura).

:- dynamic asignatura/1.

asignatura(logica_informatica).

true.

abolish(+Predicado/Ariedad), abolish(+Predicado,+Ariedad); retira de la Ba-se de Conocimiento todas las clausulas del predicado Predicado. Debe estar iden-tificado completamente el predicado: nombre y ariedad. Considerar el siguientedialogo:

?- listing(asignatura).

:- dynamic asignatura/1.

asignatura(logica_matematica).

asignatura(flp).

asignatura(lmd).

:- dynamic asignatura/2.

42

Page 43: Manual Casero Prolog Beta 02

asignatura(logica_matematica, primero).

asignatura(flp, segundo).

asignatura(lmd, tercero).

true.

?- abolish(asignatura/1).

true.

?- listing(asignatura).

:- dynamic asignatura/2.

asignatura(logica_matematica, primero).

asignatura(flp, segundo).

asignatura(lmd, tercero).

true.

?- abolish(asignatura,2).

true.

?- listing(asignatura).

ERROR: toplevel: procedure ‘asignatura’

does not exist (DWIM could not correct goal)

10. Depuracion de Programas Prolog

Prolog contiene una serie de predicados predefinidos para supervisar el funcionamientode los programas durante su ejecucion. Ellos nos permitiran la depuracion y correccionde los mismos, pues hay errores difıciles de detectar. Los errores en programacion son denaturaleza sintactica, faciles de detectar y corregir, o de naturaleza semantica, que solopuedenn ser descubiertos revisando el planteamiento o siguiendo el proceso de inferenciapaso a paso. Es en ese ultimo punto donde entra en juego el contenido de esta seccion.

Tengamos en cuenta los siguiente:

Call; se intenta satisfacer dicho predicado

Exit; el predicado ha tenido exito y se ha satisfecho

Fail; el objetivo ha fracasado

Redo; se intenta resatisfacer el objetivo al haber fracasado un predicado posterior

Destacamos lo siguiente:

43

Page 44: Manual Casero Prolog Beta 02

trace, trace(+Predicado); activa el seguimiento exhaustivo de la traza de eje-cucion del as metas posteriores a la consecucion de este objetivo o del predicadoPredicado, viendo los distintos objetivos que intenta satisfacer y el resultado deesta accion. A partir de la consecucion de este objetivo, hay una interaccion entreel programador y la maquina Prolog, pidiendonos que confirmemos cada paso.Podemos utilizar las siguientes opciones del modo traza:

• <return>, <espacio> (avanzar); continua con la traza.

• a (abort); retorna a Prolog.

• b (break); inicia un nuevo nivel de Prolog.

• c (continue); continua con la traza.

• e (exit); abandona el sistema Prolog.

• f (fail); hace fallar a ese objetivo.

• g (goal stack); muestra la pila de objetivos cumplidos hasta el objetivo actual.

• i (ignore); ignora el objetivo actual, como si se hubiera cumplido.

• l (leap); realiza la pausa solo en los puntos espıa.

• n (nodebug); continua ejecucion en modo “no debug”.

• r (retry); reintenta satisfacer el objetivo.

• s (skip); salta el modo interactivo hasta que se cumple o falla ese objetivo.

notrace, notrace(+Objetivo); su efecto es el inverso del predicado anterior, esdecir, desactiva la traza. Con el argumento Objetivo, intenta satisfacer el objetivodesactivando la traza mientras dure su ejecucion.

spy(+Predicado); fija un punto espıa en el predicado Predicado para poder seguirsu funcionamiento. Predicado debe ser:

• un atomo: se ponen puntos espıa en todos los predicados con ese atomo, inde-pendientemente del numero de argumentos que tenga.

• una estructura (functor/ariedad): solo establecerıa puntos espıa en aquellospredicados con dicho functor y numero de argumentos.

• una lista: situarıa puntos espıa en todos los lugares especificados por cada unode los elementos de la lista.

Ejemplos:

?- spy(iniciar).

?- spy(iniciar/0).

?- spy(iniciar/1).

?- spy([iniciar,pertenece]).

nospy(+Predicado), nospyall; elimina los puntos espıa especificados en Predicado

(determinado de manera analoga a la referida en el punto anterior) o retira los pun-tos espıa activos en ese momento.

44

Page 45: Manual Casero Prolog Beta 02

debugging; permite ver una lista con los puntos espıa que se han establecido hastael momento. Como ejemplo:

?- debugging.

There are spypoints set on :

iniciar/0

iniciar/1

pertenece/2

debug, nodebug; inicializa y finaliza el depurador.

A. Predicados Predefinidos

Hacemos relacion de algunos predicados predefinidos en Prolog.

1. Adicion de Bases de Conocimiento externas:

consult(X); anadir las clausulas del fichero X a la base de conocimiento

reconsult(Y); las clausulas leıdas de fichero Y sustituyen a las existentes parael mismo predicado.

[X,-Y,Z]; notacion mas comoda para consult y reconsult

halt; salir del sistema Prolog

2. Construccion de objetivos compuestos (conectivas logicas):

X,Y; conjuncion de objetivos

X;Y; disyuncion de objetivos

\+ X; se cumple si fracasa el intento de satisfacer X

not(X); se cumple si fracasa el intento de satisfacer X

3. Clasificacion de terminos:

var(X); se cumple si X es en ese momento una variable no instanciada

nonvar(X); se cumple si X no es una variable sin instanciar en ese momento

atomic(X); se cumple si X representa en ese momento un numero o un atomo

atom(X); se cumple si X representa en ese momento un atomo de Prolog

numeric(X); se cumple si X representa en ese momento un numero

integer(X); se cumple si X representa en ese momento un numero entero

real(X); se cumple si X representa en ese momento un numero real

4. Control del programa:

true; objetivo que siempre se cumple

fail; objetivo que siempre fracasa

45

Page 46: Manual Casero Prolog Beta 02

!; corte. Fuerza al sistema Prolog a mantener ciertas elecciones

repeat; sirve para generar soluciones multiples mediante el mecanismo dereevaluacion

X ->Y; si X entonces Y. En combinacion con ; actua como Si-Entonces- Sino.

call(X); se cumple si tiene exito el intento de satisfacer X (instanciada a untermino)

5. Operadores artimeticos y relacionales:

X=Y; se cumple si puede hacer X e Y iguales (unificarlos)

X\=Y; se cumple si X=Y fracasa

X==Y; igualdad mas estricta

X\==Y; se cumple si fracasa ==

X<Y; predicado menor que

X>Y; predicado mayor que

X>=Y; predicado mayor o igual que

X=<Y; predicado menor o igual que

X@<Y; ordenacion de terminos. Predicado menor que

X@>Y; ordenacion de terminos. Predicado mayor que

X@>= Y; ordenacion de terminos. Predicado mayor o igual que

X@=<Y; ordenacion de terminos. Predicado menor o igual que

X is Y; se evalua la expresion a la que esta instanciada Y para dar comoresultado un numero, que se intentara hacer coincidir con X

X is string Y; se evalua la expresion a la que esta instanciada Y para darcomo resultado una cadena, que se intentara hacer coincidir con X

X & Y; operador concatenacion de cadenas de caracteres

X + Y; operador suma

X - Y; operador resta

X * Y; operador de multiplicacion

X / Y; operador de division

X // Y; operador de division entera

X mod Y; operador de resto de la division entera

X ** Y; operador de exponenciacion

X ^ Y; operador de exponenciacion

op(X,Y,Z); declara el operador de nombre Z con clase de precedencia X yposicion-asociatividad Y.

current op(X,Y,Z); busca el operador ya declarado de nombre Z con clase deprecedencia X y posicion-asociatividad Y.

46

Page 47: Manual Casero Prolog Beta 02

6. Funciones aritmeticas:

abs(X); devuelve el valor absoluto de la expresion X.

sign(X); devuelve -1 si X <0, 1 si X >0 y 0 si X = 0

min(X,Y); devuelve el menor de X e Y

max(X,Y); devuelve el mayor de X e Y

random(X); devuelve un entero aleatorio i ( 0 =<i <X ); la semilla es deter-minada por el reloj del sistema cuando se arranca SWI-Prolog

between(M,N,X); X toma los valores enteros comprendidos entre M y N

round(X); evalua la expresion X y la redondea al entero mas cercano

integer(X); evalua la expresion X y tiene exito si el resultado es entero

float(X); evalua la expresion X en un numero en coma flotante

truncate(X); trunca la expresion X en un numero entero

floor(X); devuleve el mayor numero entero menor o igual que el resultado dela expresion X

ceiling(X); devuleve el menor numero entero mayor o igual que el resultadode la expresion X

sqrt(X); raız cuadrada de la expresion X

sin(X); seno de la expresion X (angulo en radianes)

cos(X); coseno de la expresion X (angulo en radianes)

tan(X); tangente de la expresion X (angulo en radianes)

asin(X); arcoseno (angulo en radianes) de la expresion X

acos(X); arcocoseno (angulo en radianes) de la expresion X

atan(X); arcotangente (angulo en radianes) de la expresion X

log(X); logaritmo neperiano de la expresion X

log10(X); logaritmo en base 10 de la expresion X

exp(X); e elevado al resultado de la expresion X

pi; constante matematica π (3.141593)

e; constante matematica e (2.718282)

7. Manejo de listas:

[X|Y]; X es la cabeza e Y la cola de la lista

is list(X); se cumple si X es una lista o la lista vacıa []

append(X,Y,Z); Z es la concatenacion de las listas X e Y

member(X,Y); X es uno de los elementos de la lista Y

delete(X,Y,Z); borra el elemento Y de la lista X y da como resultado la listaZ

47

Page 48: Manual Casero Prolog Beta 02

select(X,Y,Z); selecciona el elemento X de la lista Y y da como resultado lalista Z

nth0(X,Y,Z); el elemento X-esimo de la lista Y es Z (empezando en 0)

nth1(X,Y,Z); el elemento X-esimo de la lista Y es Z (empezando en 1)

last(X,Y); X es el ultimo elemento de la lista Y

reverse(X,Y); Y es la lista invertida de X

length(X,Y); Y es la longitud de la lista X

merge(X,Y,Z); siendo X e Y listas ordenadas, Z es la lista ordenada con loselementos de ambas

sort(X,Y); Y es la lista ordenada de X (sin elementos duplicados)

msort(X,Y); Y es la lista ordenada de X

findall(X,Y,Z); Z es la lista de objetos X que satisfacen Y

findall(X,Y,Z); Z es la lista de objetos X que satisfacen Y

bagof/3; consultar ayuda (?- help(bagof).).

setof/3; consultar ayuda (?- help(setof).).

8. Predicados de Entrada/Salida:

get0(X); se cumple si X puede hacerse corresponder con el siguiente caracterencontrado en el canal de entrada activo (en codigo ASCII)

get(X); xe cumple si X puede hacerse corresponder con el siguiente caracterimprimible encontrado en el canal de entrada activo

skip(X); lee y pasa por alto todos los caracteres del canal de entrada activohasta que encuentra un caracter que coincida con X

read(X); lee el siguiente termino del canal de entrada activo

put(X); escribe el entero X como un caracter en el canal de salida activo

nl; genera una nueva lınea en el canal de salida activo

tab(X); escribe X espacios en el canal de salida activo

write(X); escribe el termino X en el canal de salida activo

write ln(X); escribe el termino X en el canal de salida activo y salta la lınea

writef(X,Y); escribe en el canal de salida activo, siendo X el formato e Y lalista con los argumentos a escribir

display(X); escribe el termino X en el canal de salida activo, pasando por altolas declaraciones de operadores

9. Manejo de ficheros:

see(X); abre el fichero X y lo define como canal de entrada activo

seeing(X); se cumple si el nombre del canal de entrada activo coincide con X

seen; cierra el canal de entrada activo, y retorna al teclado

48

Page 49: Manual Casero Prolog Beta 02

tell(X); abre el fichero X y lo define como canal de salida activo

telling(X); se cumple si X coincide con el nombre del canal de salida activo

told; cierra con un fin de fichero el canal de salida activo, que pasa a ser lapantalla

10. Maninpulacion de la Base de Conocimiento:

listing; se escriben en el fichero de salida activo todas las clausulas

listing(X); siendo X un atomo, se escriben en el fichero de salida activo todaslas clausulas que tienen como predicado dicho atomo

clause(X,Y); se hace coincidir X con la cabeza e Y con el cuerpo de unaclausula existente en la base de conocimiento

assert(X); permite anadir la nueva clausula X a la base de conocimientoasserta(X); permite anadir la nueva clausula X al principio de la base deconocimiento

assertz(X); permite anadir la nueva clausula X al final de la base de conoci-miento

retract(X); permite eliminar la primera clausula de la base de conocimientoque empareje con X

retractall(X); permite eliminar todas las clausulas de la base de conocimien-to que emparejen con X

abolish(X); retira de la Base de Conocimiento todas las clausulas del predi-cado X

abolish(X,Y); retira de la Base de Conocimiento todas las clausulas del pre-dicado de nombre X y numero de argumentos Y

11. Construccion y acceso a componentes de estructuras:

functor(E,F,N); E es una estructura con nombre F y numero de argumentosN

arg(N,E,A); el argumento numero N de la estructura E es A

E=..L; predicado univ. L es la lista cuya cabeza es el functor de la estructuraE y la cola sus argumentos

name(A,L); los caracteres del atomo A tienen por ASCII los numeros de la listaL

12. Depuracion de programas Prolog:

trace; activacion de un seguimiento exhaustivo, generando la traza de la eje-cucion de las metas siguientes

trace(X); activacion de un seguimiento del predicado X

notrace; desactiva el seguimiento exhaustivo

notrace(X); desactiva el seguimiento mientras dure la llamada al objetivo X

49

Page 50: Manual Casero Prolog Beta 02

spy(X); fijacion de puntos espıa en el predicado X

nospy(X); elimina los puntos espıa especificados

nospyall; elimina todos los puntos espıa

debugging; ver el estado del depurador y los puntos espıa se han establecidohasta el momento

debug; inicia el depurador

nodebug; desactiva el depurador

B. Notacion comparativa entre Logica y Prolog

formula clausula de Horn Prolog

regla∀(A ∨ ¬N1 ∨ · · · ∨ ¬Nm) {A,¬N1, . . . ,¬Nm} A :- ¬N1, . . . ,¬Nm∀((¬N1 ∨ · · · ∨ ¬Nm)→ A)

hecho ∀(A) {A} A.

objetivo∀(¬N1 ∨ · ∨ ¬Nm) {¬N1, . . . ,¬Nm} ?- ¬N1, . . . ,¬Nm¬∃(¬N1 ∧ · · · ∧ ¬Nm)

formula program. logica

regla∀(A ∨ ¬N1 ∨ · · · ∨ ¬Nm)

A← ¬N1, . . . ,¬Nm∀((¬N1 ∨ · · · ∨ ¬Nm)→ A)hecho ∀(A) A←

objetivo∀(¬N1 ∨ · ∨ ¬Nm) ← ¬N1, . . . ,¬Nm¬∃(¬N1 ∧ · · · ∧ ¬Nm)

50