Está en la página 1de 44

Bases de Datos

Meta-cláusulas
Meta-Predicados

1
Manipulación de la base de datos

Programa Prolog <----> Base de datos

Base de datos: Conjunto de cláusulas que hemos


ensamblado antes de iniciar la ejecución del
programa.
Prolog dispone de un conjunto de predicados
predefinidos para modificar la base de datos
de forma dinámica
Los predicados meta-lógicos permite controlar el algoritmo de
resolución facilitando la meta-programación. Esta consiste en
construir programas que manipulan otros programas
proporcionando una mayor expresividad al lenguaje.
2
Los predicados metalógicos son un tipo especial de
los no lógicos, cuya misión es interrogar al sistema
acerca del estado actual del proceso de resolución.
Para introducir al lector en la conveniencia de
disponer de un conjunto tal de facilidades.

var(X)  X es una variable. atomic(X)  X es un átomo o número.

atom(X)  X es un átomo. float(X)  X es un número real .

integer(X)  X es un entero. number(X)  X es un número.


.
?.-var (A) ?:-var ([X]) ?.-atom (f(a)). ?:-atom (‘Esto es’).
yes no no yes
3
PREDICADOS DE UNIFICACIÓN Y COMPARACIÓN DE
TÉRMINOS

X=Y  X e Y son unificables. No admite backtracking.

X= []. a= X. f(a,X)= f(Y,g(b)).


X= [] X= a. X= g(b)
yes yes Y=a.
yes
[X,a|L= [b,Y.
X= b 1+1=2.
L= []
yes no

X\=Y  X e Y no son unificables. No admite backtracki


X==Y  X e Y son idénticos. No admite backtracking.
X== s(c). X== Y. X= a, Y=a, X==Y.
no no yes

X\==Y  X e Y no son idénticos. No admite backtracking.

X@<Y  X es menor que Y según el orden estandar, que es de


menor a mayor:
 variables
 números , con su orden natural
 átomos, por orden alfabético • aridad
 términos complejos ordenados por: • funtor
• recursivamente por sus
argumentos
X@=<Y, X@>Y,X@>=Y
funtor(Est,N,A):La estructura Est tiene nombre N y
aridad A. No admite backtracking.
funtor(fa,b),N,A). funtor(E,f,3).
funtor(X,N,A).
N=f E=f(_A,_B._C)
A=2 no

arg(N,Est,X):X es unificable con el N-simo argumento


de Est. Los argumentos se enumenran desde 1. N y Est no
pueden ser variables. No admite backtracking.
arg(2,f(a,g(b)),X).
X=g(b)
yes arg0(N,Est,X):Como arg/3 pero
numerando desde 0.
Bases de Datos

Ejemplo:

7
Ejemplos:

8
Las bases de datos deductivas usan estas ideas para
desarrollar bases de datos basadas en la lógica
•a menudo se usa un subconjunto de los programas
lógicos
•se suele utilizar alguna variante del mecanismo
“bottom-up” como estrategia de ejecución.

9
asserta(X)

Añade la cláusula X como la primera cláusula de este


predicado. Como otros predicados de E/S siempre falla
en el backtracking y no deshace sus propios cambios.

assertz(X)

Como asserta/1, sólo que añade la cláusula X como la


última cláusula del predicado.

retract(X)

Borra la cláusula X de la base de datos. Como en los casos


anteriores no es posible deshacer los cambios debidos a
este predicado en el backtraking.
10
dynamic +Name/+Arity, ... informa al intérprete que la
definición del(os) predicado(s) puede cambiar durante la
ejecución (usando assert y/o retract ).

11
¿Es posible definir variables globales en Prolog?
Ejemplo adaptado del tutorial de Amzi Prolog

:-dynamic aquí/1. conectado(cocina, recibidor).


conectado(recibidor, cocina).
ir(Lugar):- conectado(cocina, despensa).
puedo_ir(Lugar),
conectado(despensa, cocina).
moverse(Lugar).
conectado(cocina, comedor).
puedo_ir(Lugar):- conectado(comedor, cocina).
aquí(X), conectado(comedor, estar).
conectado(X, Lugar). conectado(estar, comedor).
moverse(Lugar):-
retract(aquí(_)), aquí(cocina).
asserta(aquí(Lugar)).
SWI-Prolog
12
Ejemplo: ?- más_lento(A,B).

rápido(ana). A = juan
lento(juan). B = ana ;
más_lento(X,Y):-
lento(X), No
rápido(Y).

13
?- assert((rápido(patricia))).
Yes

?- listing(rápido).
rápido(ana).
rápido(patricia).
Yes
?- más_lento(A,B).

A = juan
B = ana ;

A = juan
B = patricia ;

No
14
?- más_rápido(A,B).

A = ana
B = juan ;

A = patricia
B = juan ;

?- assert( No
| (más_rápido(X,Y):-
| rápido(X),lento(Y))).

?- listing(más_rápido).
más_rápido(A, B) :-
rápido(A),
lento(B).
Yes 15
?- listing(rápido).
rápido(patricia).
Yes

?- más_rápido(A,B).
A = patricia
B = juan ;

?- listing(rápido). No
rápido(ana).
rápido(patricia).
Yes

?- retract(rápido(ana)).
Yes

16
?- más_rápido(A,B).

A = patricia
B = juan ;

A = patricia
B = tomás ;

?- assertz(lento(tomás)). No
Yes

?- listing(lento).
lento(juan).
lento(tomás).
Yes

17
?- más_rápido(A,B).

No

?- retractall(lento(X)).
Yes

?- listing(lento).
Yes

18
?- más_lento(A,B).
[WARNING: Undefined predicate:
`más_lento/2']

No

?- retract(
| (más_lento(X,Y):-
| lento(X), rápido(Y))).

X = _G339
Y = _G340
Yes

19
Otros predicados para manipulación de la base
de datos (SWI-Prolog)
retract/assert:
modificar la base de datos de cláusulas.
compilan el término que se les pasa como argumento.
son costosas.

recorda/erase:
permiten grabar/borrar una base de datos de
términos.
mecanismo más rápido que assert/retract, pero
no son cláusulas del programa

20
Construcción y descomposición de términos

Existen tres predicados predefinidos para


descomponer términos o construir nuevos
términos:

Term =.. L

functor(Term, F, N)

arg(N, Term, A)

21
?- f(a,b) =.. L.
L = [f, a, b]

?- T =.. [progenitor, miguel, maría ]


T = progenitor(miguel, maría)

?- Z =.. [p, X, g(X,Y) ].


Z = p(X, g(X,Y))

¿Por qué nos puede interesar descomponer un término


en sus componentes?

¿Por qué nos puede interesar construir un nuevo término


a partir de un functor y sus argumentos?

22
Ejemplo:

Consideremos un programa que manipula figuras


geométricas como cuadrados, círculos, ... , que se
representan por un functor que indica el tipo de
figura y unos argumentos que la definen:

cuadrado(Lado)
triángulo(Lado1, Lado2, Lado3)
círculo(Radio)

Una de las operaciones a realizar sobre las figuras

aumenta(Fig, Factor, Fig1)

23
Ejemplo: (Cont.)

Una posibilidad:

aumenta(cuadrado(A), F, cuadrado(A1)) :- A1 is A*F.

aumenta(círculo(R), F, circulo(R1)) :- R1 is R*F.

aumenta(rectángulo(A,B), F, rectángulo(A1,B1)) :-
A1 is A*F, B1 is B*F.

...

Funcionaría, pero no es elegante. Especialmente si


el número de figuras es grande.

24
Ejemplo: (Cont.)

Un intento para agrupar todas figuras que estén


parametrizadas por un único parámetro:

aumenta(Tipo(Par), F, Tipo(Par1)) :-
Par1 is Par*F.

No está permitido en Prolog ya que el functor


debe ser un átomo y no una variable.

25
Ejemplo: (Cont.)

La solución:

aumenta(Fig, F, Fig1) :-
Fig =.. [Tipo | Parámetros],
multiplica_lista(Parámetros, F, Parámetros1),
Fig1 =.. [Tipo | Parámetros1].

multiplica_lista([ ],_, [ ]).


multiplica_lista([ X | L], F, [ X1 | L1]) :-
X1 is F*X, multiplica_lista( L, F, L1).

26
Ejemplo:

Intentemos definir el predicado

sustituye(Subterm, Term, Subterm1, Term1)

Term1 se obtiene de la sustitución de todas las


ocurrencias de Subterm en Term por Subterm1.

?- sustituye(sen(x), 2*sen(x)*f(sen(x)), p, F).


F = 2*p*f(p)

27
Ejemplo:

?- sustituye(a+b, f(a, A+B), v, F).


A=a
B=b
F = f(a, v)

?- sustituye(a+b, A+B, v, F).


A=a
B=b
F=v

28
Ejemplo:

sustituye(Subterm, Term, Subterm1, Term1)

Si Subterm = Term entonces Term1 = Subterm1


en otro caso
Si Term es atómico entonces Term1 = Term
en otro caso la sustitución debe realizarse
en los argumentos de Term

?- 2*sen(x)*f(sen(x)) =.. [F | Args].


F=*
Args = [2*sen(x), f(sen(x))]

29
?- 2*sen(x)*f(sen(x))
?- sustituye(mi, =.. [F |tu,
[mi,perro, [en,mi,casa]], Args].
F).
F = [tu, perro,F[en,
= * tu, casa]]
Ejemplo: Yes Args = [2*sen(x), f(sen(x))]

sustituye(Term, Term, Term1, Term1):- !.

sustituye(_, Term, _, Term):- atomic(Term),!.

sustituye(Sub, Term, Sub1, Term1):-


Term =.. [F | Args],
sust_lista(Sub, Args, Sub1, Args1),
Term1 =.. [F | Args1].

sust_lista(_,[ ],_,[ ]).


sust_lista(Sub,[Term|Terms], Sub1, [Term1|Terms1]) :-
sustituye(Sub, Term, Sub1, Term1),
sust_lista(Sub, Terms, Sub1, Terms1).
30
¿Por qué no funciona sustituye/4 en el este caso?

?- sustituye(sen, sen(x), p, F).


F = p(x)
sen(x)

sustituye(Term, Term, Term1, Term1):- !.

sustituye(_, Term, _, Term):- atomic(Term),!.

sustituye(Sub, Term, Sub1, Term1):-


Term =.. [F | Args],
sustituye(Sub, F, Sub1, F1),
sust_lista(Sub, Args, Sub1, Args1),
Term1 =.. [F1 | Args1].

sust_lista(_,[ ],_,[ ]).


sust_lista(Sub,[Term|Terms], Sub1, [Term1|Terms1]) :-
sustituye(Sub, Term, Sub1, Term1),
sust_lista(Sub, Terms, Sub1, Terms1). 31
Más ejemplos con univ (=..) ...
:- op(100, xfx, isf).

R isf OPs :-
(
OPs =.. [F, A, C/D], integer(A) -> OPs1 =.. [F, A/1,C/D]
;
OPs =.. [F, A/B, C], integer(C) -> OPs1 =.. [F, A/B,C/1]
),
!,
R isf OPs1.

R isf OPs :-
OPs =.. [_, A, B],
integer(A),
integer(B),
!,
R is OPs.

R isf OPs:-
OPs =..[F,A,B],
R1 isf A,
R2 isf B,
OPs1 =..[F,R1,R2],
R isf OPs1. 32
Un uso habitual de =.. es el de sintetizar nuevos
objetivos:

obtener(Functor),
calcular(ArgList),
Objetivo =.. [Functor | ArgList]
Objetivo

o alternativamente, si sintácticamente se requiere


que el functor principal de un objetivo sea un átomo,

call(Objetivo)

33
Otras veces nos interesará extraer el functor
principal de un término

Se puede emplear =.., pero suele ser más práctico


y eficiente emplear functor y arg.

functor(Term, F, N)
es cierto si F es el functor principal de Term
y N es la aridad de F

arg(N, Term, A)
es cierto si A es el N-ésimo argumento de Term
cuando los argumentos se numeran de izda a dcha
empezando por 1.

34
Ejemplo:

?- functor( t( f(X), X, t), Fun, Arity).


Fun = t
Arity = 3

?- arg( 2, f( X, t(a), t(b)), Y).


Y = t(a)

?- functor( D, fecha, 3),


| arg(1,D,29), arg(2,D, junio), arg(3,D,1998).

D = fecha(29, junio, 1998)

35
Cómo cambiar un argumento (I)

setarg/3: deshace las asignaciones en el backtraking

?- F = f( X, t(a), t(b)), setarg(2,F,t(c)).


F = f(X, t(c), t(b))
Yes

setarg(+Arg, +Term, +Value)


Extra-logical predicate. Assigns the Arg-th argument of the
compound term Term with the given Value. The assignment is undone
if backtracking brings the state back into a position before the
setarg/3 call. See also nb_setarg/3.

This predicate may be used for destructive assignment to terms,


using them as an extra-logical storage bin. Always try hard to
avoid the use of setarg/3 as it is not supported by many Prolog
systems and one has to be very careful about unexpected copying as
well as unexpected not copying of terms.

36
Cómo cambiar un argumento (II)

nb_setarg/3: NO deshace las asignaciones en el backtraking

?- F = f( X, t(a), t(b)), nb_setarg(2,F,t(c)).


F = f(X, t(c), t(b))
Yes
nb_setarg(+Arg, +Term, +Value)
Assigns the Arg-th argument of the compound term Term with the
given Value as setarg/3, but on backtracking the assignment is
not reversed. If Term is not atomic, it is duplicated using
duplicate_term/2. This predicate uses the same technique as
nb_setval/2. We therefore refer to the description of nb_setval/2
for details on non-backtrackable assignment of terms. This
predicate is compatible to GNU-Prolog setarg(A,T,V,false), removing
the type-restriction on Value. See also nb_linkarg/3. Below is
an example for counting the number of solutions of a goal. Note
that this implementation is thread-safe, reentrant and capable of
handling exceptions. Realising these features with a traditional
implementation based on assert/retract or flag/3 is much more
complicated. 37
Como obtener todas las respuestas sin
backtracking

Una forma de obtener “todas las respuestas”:

* Agotar las posibilidades de vuelta-atrás

Otra:

* Emplear los predicados bagof, setof y findall

38
Las diferentes soluciones ?- bagof(Verdura,
bagof(X, P,por
agrupadas L) el valor de | item(Verdura,Precio),
item(Verdura,Precio),L).
L).
Precio
Produce la lista L de todos
Verdura los=objetos
_G315 X
que satisfacen el objetivo
PrecioP.=Normalmente
300
X es una variable en P.L = [coliflor] ;
Verdura = _G315
item(tomates, 120). Precio = 275
item(coliflor, 300). L = [pimiento] ;
item(pimiento, 275). Verdura = _G315
item(lechuga, 115). Precio = 115
L = [lechuga] ;
item(cebolla, 120).
Verdura = _G315
?- bagof(Verdura,
Precio item(Verdura,120),
= 120 L).
?- bagof(Precio,Verdura
bagof(Verdura,Verdura
bagof(Verdura, Precio^=^item(Verdura,50),L).
item(Verdura,Precio),
item(Verdura,
item(Verdura,115),
_G297 L). Precio),
L).
L).
L = [tomates, cebolla] ;
Precio
Verdura= =_G352
_G351L = [tomates, cebolla]
Verdura
No
Precio = =_G352
_G351Yes
No
L = [120,
[tomates,
300,coliflor,
275, 115,pimiento,
120] lechuga, cebolla]
39
?- setof(Precio,Verdura ^ item(Verdura,Precio), L).
setof(X, = P, L)
?- setof(Verdura,Precio
Precio _G352 ^ item(Verdura,Precio), L).
Verdura == _G351
Verdura _G351
LPrecioProduce
= _G352
= [115, la lista
120, 275, 300]L de todos los objetos X
(nóteseque
la satisfacen
L = [cebolla, el
deobjetivo
coliflor, lechuga,
eliminación P. Normalmente
pimiento,
duplicados y latomates]
ordenación de
menor Xa es
(nótese la una variable
ordenación
mayor) en P.
alfabética)

Similar a bagof, pero ahora se eliminan


los duplicados y los elementos de la lista
se ordenan: alfabéticamente y de menor
a mayor.

item(tomates, 120).
item(coliflor, 300).
item(pimiento, 275).
item(lechuga, 115).
item(cebolla, 120).
40
findall(X,
?- P, L)
?- findall(Verdura,item(Verdura,50),L).
findall(Verdura,item(Verdura,_),L).
Verdura
Verdura == _G279
_G273
] Producecoliflor,
LL == [[tomates, la listapimiento,
L de todos los objetos
lechuga, X
cebolla]
Yes que satisfacen el objetivo P. Si el objeto X
Yes
no verifica P, findall se verifica con L = [ ]
?- findall(Precio,item(_,Precio),L).
Precio Similar
= _G262a bagof y setof, pero ahora se
L = [120, incluyen en la
300, 275, lista
115, todos los elementos,
120]
Yes incluso aquellas soluciones que difieren en
otras variables de P

item(tomates, 120).
item(coliflor, 300).
item(pimiento, 275).
item(lechuga, 115).
item(cebolla, 120).
41
Otro ejemplo inspirado en el ejemplo del restaurante

Problema: Definir el predicado % menu


calorias_conocidas/0 que indique
todos los platos que no disponen entrada(paella).
entrada(gazpacho).
de la correspondiente definición entrada(langostinos).
de calorias entrada(consome).
entrada('sopa de fideos').

% Valor calorico de una racion carne(filete_de_cerdo).


calorias(paella, 200). carne(solomillo).
calorias(gazpacho, 150). carne(pollo_asado).
calorias(consome, 300).
calorias(filete_de_cerdo, 400). pescado(trucha).
calorias(pollo_asado, 280). pescado(bacalao).
calorias(trucha, 160).
calorias(bacalao, 300). postre(flan).
calorias(flan, 200). postre(natilla).
calorias(nueces_con_miel, 500). postre(nueces_con_miel).
calorias(naranja, 50). postre(naranja).
42
%
% Verificación de que todos los platos
7 ?-
% disponen de la correspondiente definición
% de calorías | calorias_conocidas.
% No hay definición de calorias para "langostinos".
No hay definición de calorias para "sopa de fideos".
calorias_conocidas :-
No hay definición de calorias para "solomillo".
verifica_plato(entrada),
No hay definición de calorias para "natilla".
verifica_plato(carne),
verifica_plato(pescado),
Yes
verifica_plato(postre).

verifica_plato(Plato):-
P =..[Plato, E],
setof(E,P,Es),
verifica_cal(Es).

verifica_cal([E|Es]):-
( calorias(E,_) -> true
;
format('No hay definición de calorias para \”~w\”.~n',[E])
),
verifica_cal(Es).

verifica_cal([]).
43
Conclusión

• Las implementaciones de Prolog proporcionan un

conjunto de predicados metalógicos sumamente útiles.

• Que permiten construir o descomponer términos

utilizando el operador =.., functor o arg.

• Que permiten modificar la base de datos clausal

utilizando assert, retract y sus variantes.

• Que proporcionan listas de objetos que satisfacen una

cierta condición empleando bagof, setof o findall.


44

También podría gustarte