Está en la página 1de 12

Unificación y Corte

María Elena Cárdenas Mosqueda


Unificación

Ejemplo:

tiene_un_hijo(X):-progenitor(X,Y).

“Y” no unifica con otra variable en la definición de la relación


“tiene_un_hijo”, por lo que es aconsejable sustituirla por una
variable anónima (en algunos entornos de programación PROLOG
se advierte sobre la conveniencia de ello).

tiene_un_hijo(X):-progenitor(X,_).

Es importante señalar que el alcance de una variable es la


cláusula donde aparece, y el alcance de una constante es todo el
programa PROLOG.
La operación más importante sobre términos es la
unificación. Dos términos pueden unificarse si son
idénticos o las variables de ambos términos pueden
instanciarse a objetos tales que después de la
sustitución de las variables por esos objetos, los
términos sean idénticos.

Ejemplos:
fecha(D,M,1998) = fecha(D1,mayo,A)
piloto(A,Londres) = piloto(londres,paris)
punto(X,Y,Z) = punto(X1,Y1,Z1)
f(X,a(b,c)) = f(Z,a(Z,c))
En el caso de que “?-X=Y” sea una pregunta PROLOG, puede
ocurrir varias cosas:

1. Una de las dos variables no esté instanciada pero la otra sí,


entonces el objetivo se satisface y la variable que no estaba
instanciada queda instanciada al valor de la variable que
estaba instanciada;
2. Ambas variables estén sin instanciar, entonces el objetivo se
satisface y además ambas variables quedan compartidas, es
decir, que cuando una de las dos variables se instancie, la otra
quedará instanciada a lo mismo;
3. Si X e Y son constantes ambas tiene que ser el mismo objeto, y
si son estructuras, tienen que tener el mismo funtor, el mismo
número de argumentos y que coincidan todos los argumentos.
Predicado de control: el corte

Es un predicado predefinido que permite al programador


intervenir en el mecanismo de búsqueda de soluciones de Prolog.

Definición y propiedades:

El corte es un predicado predefinido que se denota mediante un


punto de exclamación (!), no tiene argumentos, y cuya evaluación
es siempre cierta.

Se puede incluir, como un predicado más, en el cuerpo de las


reglas o en las consultas (por ejemplo a :- b, c, !, d.).
Ejemplo 1: cálculo de una función

Supóngase que se necesita definir un predicado en Prolog


que permita calcular la siguiente función fun:

0; si x <= 10
fun(x) = 1; si 10 < x <= 20
2; si x > 20

Una primera aproximación para la resolución del problema


anterior es definir un predicado f(X,Y), cierto si Y es igual a
fun(X), mediante las tres siguientes reglas:

f(X,0) :- X =< 10.


f(X,1) :- X>10, X =< 20.
f(X,2) :- X > 20.
Supóngase que se realiza la consulta

?- f(0,Z), Z>1.

La respuesta de Prolog será false, pero para llegar a dicha conclusión el sistema
tiene que recorrer las 3 posibles ramas del árbol la función que se está calculando
tiene la siguiente estructura condicional:

si X <= 10 entonces Y = 0;
si no: si X > 20, entonces Y = 1;
si no: Y = 2.
una forma de remediar la ineficiencia anterior es utilizando el predicado de corte
como se ha indicado al principio de este apartado:

f(X,Y) :- X =< 10, !, Y=0.


f(X,Y) :- X =< 20, !, Y=1.
f(_X,2).

Con esta nueva versión, la respuesta de Prolog a la consulta \?- f(0,Z), Z>1." será
también \no", pero ahora, gracias a la introducción del corte en la primera regla,
el sistema sólo tendrá que explorar la primera rama del árbol
Obsérvese que una forma más cómoda para representar esta
nueva versión consistiría en, al igual que en la primera versión,
realizar la unificación directamente en la cabeza de las reglas:

f(X,0) :- X =< 10, !.


f(X,1) :- X =< 20, !.
f(_X,2).

esta última versión es más cómoda de escribir, pero no siempre


es correcta, porque no funciona adecuadamente para ciertos
usos del predicado.
1. Resuelve correctamente consultas de la forma ?- f(5,Z).
2. Pero no siempre funciona en consultas con ambos
argumentos instanciados: por ejemplo en?- f(0,2). La
respuesta sería afirmativa, cuando debería ser negativa. Este
problema no se da en las versiones anteriores.
Ejemplo 2: cálculo del máximo de dos números

Calcular el máximo de dos números naturales se puede


implementar en Prolog mediante un predicado máximo(X,Y,Z),
cierto si Z es el máximo de X e Y. Una primera versión sería:

maximo(X,Y,X) :- X >= Y.
maximo(X,Y,Y) :- X < Y.

Dado que las dos opciones son mutuamente excluyentes, una


forma más cómoda y eficiente de expresar lo anterior es
utilizando el corte:

maximo(X,Y,Z) :- X >= Y, !, Z=X.


maximo(_X,Y,Y).
Otra posibilidad es modificar la versión anterior para que la
unificación se realice directamente en la cabeza de las
cláusulas:

maximo(X,Y,X) :- X >= Y, !.
maximo(_X,Y,Y).

Al igual que en el ejemplo anterior, resulta que esta última


versión no puede usarse de cualquier forma, porque con
ciertas consultas puede dar lugar a resultados erróneos:
por ejemplo,
? maximo(3,0,0).

Da una respuesta afirmativa, cuando debería ser negativa.


Ejemplo 3: pertenencia de un elemento a una lista

La forma más inmediata para representar en Prolog la pertenencia de un


elemento a una lista es la siguiente:

pertenece(C, [C|_]).
pertenece(C, [_|R]) :- pertenece(C,R).

En la definición anterior, las dos opciones no se consideran excluyentes, por lo


que si un elemento aparece varias veces en una lista, el predicado encontrará
todas sus posibles ocurrencias. Así, el predicado anterior podrá utilizarse no sólo
para averiguar si un elemento pertenece a una lista determinada sino también
para recorrer todos los elementos de una lista. Por ejemplo, la
respuesta del sistema ante la consulta pertenece(X,[a,b,c]).

?- pertenece(X,[a,b,c]).
X=a?;
X=b?;
X=c?;
no
Una versión más eficiente introduciendo un corte :

pertenece(C, [C|_]) :- !.
pertenece(C, [_|R]) :- pertenece(C,R).

Con esto se consigue una versión determinista y más eficiente del


predicado. Sin embargo, la introducción del corte y la consiguiente poda
del árbol hace que el predicado ya no se pueda usar, como con la
versión anterior, para enumerar todos los elementos de una lista.

En efecto, ahora se tendrá:

?- pertenece(X,[a,b,c]).
X=a?;
no

También podría gustarte