Vous êtes sur la page 1sur 11

Algoritmo de unificación

ésar   s


11 de noviembre de 2018

Índice
1 Conceptos previos 1
1.1 Susbtituciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Unificación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2 Algoritmo de unificación 4

3 Implementación en Python 8

La unificación se puede ver como un «algoritmo para comparar átomos».


Permite hacer un pattern matching entre fórmulas atómicas de la lógica de
predicados.
Por ejemplo, si se tuvieran las fórmulas:

a (∀x)(∀y)(P (x, g(y)) → Q(f (x, y))


b (∀v)P (g(v), v)

y se quisiera aplicar modus ponens, tal como están no se podría. Pero, las
variables, dado que están cuantificadas universalmente, se pueden sustituir
por cualquier elemento. Por tanto, sustituyendo y por a, v por g(a) y x por
g(g(a)), podríamos transformarlas en:

a0 P (g(g(a)), g(a)) → Q(f (g(g(a)), a))


b0 P (g(g(a)), g(a))

y deducir: Q(f (g(g(a)), a))

1. Conceptos previos
1.1. Susbtituciones
Definición 1 (Ligadura). Una ligadura es un par de elementos: por una parte una variable
vi y por otra un término ti . Se representa por ti /vi . Y se lee: «la variable vi queda ligada
al término ti ». A ti se le denomina término de ligadura, y a vi variable de ligadura.
Algoritmo de unificación 1.1 Susbtituciones

Definición 2 (Sustitución). Una sustitución es un conjunto de ligaduras

{t1 /v1 , t2 /v2 , . . . , tn /vn }

con las siguientes condiciones:


• vi 6= vj para todo i y para todo j.
• vi no ocurre en tj ∀i, j.
Cuando todos los términos ti son términos básicos, es decir, sin variables en sus argu-
mentos, la sustitución se llama sustitución básica. La sustitución que no tiene ningún
elemento se llama sustitución nula y se representa por ε.
Algunos autores ([CR73] y [LVDG91]) no imponen unas condiciones tan rígidas para
una sustitución, para ellos es suficiente con la primera de estas condiciones y con que
la variable sea distinta del término. Pero, dado el uso que se hace de las sustituciones
en el algoritmo de unificación, al final, como se verá, ambas definiciones vienen a ser
equivalentes.

Ejemplo 1.1. ¿Cuáles de las siguientes son sustituciones y cuáles no?


{a/x, f (y)/z} es una sustitución.
{f (x)/x} no es una sustitución ya que la variable x ocurre en el término f (x).
{a/x, y/u, u/z} no es una sustitución.

Definición 3 (Particulariazación por sustitución). Sea θ = {t1 /v1 , t2 /v2 , . . . , tn /vn } una
sustitución, y E una expresión, entonces Eθ es la expresión que se obtiene de E reempla-
zando simultáneamente cada ocurrencia de las variables vi en E por los correspondientes
términos ti . Eθ es una particularización por sustitución o instancia de E. Si la sustitución θ
es una sustitución básica, Eθ recibe el nombre de particularización básica de E.

Ejemplo 1.2. Sea la expresión: E = P (x, f (y), b) y la sustituciones: θ1 = {a/x, z/y} y


θ2 = {a/x, b/y} entonces:
Eθ1 = P (a, f (z), b) es una particularización por sustitución de E, y
Eθ2 = P (a, f (b), b) es una particularización básica de E.

Definición 4 (Sustituciones distintas). Dadas dos sustituciones

θ1 = {t11 /v11 , t12 /v12 , . . . , t1n /v1n }


θ2 = {t21 /v21 , t22 /v22 , . . . , t2n /v2n }

se dice que θ1 es distinta de θ2 (θ1 6= θ2 ) si y sólo si se cumple:

• v1i 6= v2j para todo i y para todo j.


• v1i no ocurre en t2j ∀i, j.

De estas condiciones se deduce que no es lo mismo decir «θ1 es distinta de θ1 » que decir
«θ2 es distinta de θ1 ».

César Ignacio García Osorio 2 LSI – Univ. de Burgos


Algoritmo de unificación 1.1 Susbtituciones

Ejemplo 1.3. Sean θ1 = {f (x, y)/w} y θ2 = {a/x, b/y, c/z}, θ1 es distinta de θ2 pero
en cambio θ2 no es distinta de θ1 .

Definición 5 (Composición de sustituciones — versión I). Sean θ1 y θ2 dos sustitucio-


nes con θ1 6= θ2 . Se llama composición de θ2 con θ1 y se denota por θ1 ◦ θ2 a la sustitución
resultante de aplicar los siguientes pasos:

1. Aplicar θ2 sobre θ1 .
2. Añadir las ligaduras de θ2 al resultado del primer paso.

Ejemplo 1.4. Con las sustituciones del ejemplo 1.3 se tiene:

θ1 ◦ θ2 = {f (a, b)/w, a/x, b/y, c/z}

Definición 6 (Composición de sustituciones — versión II). Sean

θ = {t1 /x1 , t2 /x2 , . . . , tn /xn }


λ = {u1 /y1 , u2 /y2 , . . . , um /ym }

dos sustituciones. La composición de θ y λ es la sustitución, denotada por θ ◦ λ, que se


obtiene del conjunto

{t1 λ/x1 , t2 λ/x2 , . . . , tn λ/xn , u1 /y1 , u2 /y2 , . . . , um /ym }

eliminando cualquier elemento tj λ/xj para el que tj λ = xj , y cualquier elemento ui /yi


tal que yi sea alguno de {x1 , x2 , . . . , xn }.

Esta definición de composición de sustituciones es la que aparece en [LVDG91] y


en [CR73]. A primera vista, parece distinta a la primera definición dada, pero si las
sustituciones a las que se aplican son distintas (ver definición 4), el resultado obtenido
es el mismo. Los autores citados dan esta definición para la composición ya que, como
se ha comentado, la definición de sustitución es ligeramente diferente de la dada aquí.
Para estos autores una sustitución como {f (z)/x, y/z} es válida. A pesar de ello con el
uso habitual que se hace de las sustituciones en el algoritmo de unificación este tipo de
sustituciones no va aparecer. En el algoritmo de unificación las sustituciones con más
de una ligadura surgen por composición de sustituciones, pero al aplicar cualquiera de
las dos definiciones de composición vistas, las sustituciones finalmente obtenidas van a
verificar las condiciones dadas en la definición 2.
La composición de sustituciones verifica algunas propiedades:

• Es idempotente: E(θ ◦ θ) = Eθ.


• Es asociativa: E(λ ◦ σ)θ = Eλ(σ ◦ θ) y E(λ ◦ θ) = (Eλ)θ.
• NO es conmutativa: E(λ ◦ θ) 6= E(θ ◦ λ).

César Ignacio García Osorio 3 LSI – Univ. de Burgos


Algoritmo de unificación 1.2 Unificación

Definición 7 (Particularización de un conjunto de expresiones). Dado un conjunto


finito y no vacío de epxresiones Ω = {E1 , E2 , . . . , En } y una sustitución θ, se llama
particularización de Ω en θ y se denota por Ωθ al conjunto que resulta de aplicar θ a cada
una de las expresiones Ei del conjunto y de eliminar las particularizaciones repetidas.

Ejemplo 1.5. Sea Ω = {f (x), f (y), z}, θ1 = {f (x)/z} y θ2 = {f (a)/z, a/x, a/y}. Las
particularizaciones de Ω a θ1 y a θ2 son respectivamente Ωθ1 = {f (x), f (y)} y Ωθ2 =
{f (a)}.

1.2. Unificación
Definición 8 (Unificador). Sea Ω = {E1 , E2 , . . . , En } y θ una sustitución. Se dice que θ
es un unificador de Ω si y sólo si E1 θ = E2 θ = · · · = En θ, o de otro modo si y sólo si la
cardinalidad del conjunto Ωθ es uno. Si existe la sustitución que unifica un conjunto, se
dice del conjunto que es unificable.

Ejemplo 1.6. Sea Ω = {P (a, y, z), P (x, b, z)}. Tanto θ1 = {a/x, b/y} como θ2 =
{a/x, b/y, c/z} son unificadores para Ω.

Definición 9 (Unificador más general). Un unificador σ de un conjunto de expresiones


Ω = {E1 , E2 , . . . , En } es un unificador más general si y sólo si para cada unificador θ del
conjunto existe una sustitución λ tal que θ = σ ◦ λ.

Ejemplo 1.7. Considérese el conjunto de expresiones {R(x, f (a, g(y))), R(b, f (z, w))}.
Algunos posibles unificadores para este conjunto son:

θ1 = {b/x, a/z, g(c)/w, c/y}


θ2 = {b/x, a/z, f (a)/y, g(f (a))/w}
θ3 = {b/x, a/z, g(y)/w}
El último unificador es también un unificador más general. De la composición de este
unificador con la sustitución {c/y} se obtiene θ1 ; el segundo unificador se puede obtener de
la composición de θ3 con {f (a)/y}.

Definición 10 (Variantes alfabéticas). Dos expresiones E y E 0 son variantes alfabéticas


si y sólo si únicamente difieren en el nombre de las variables.
Teorema 1. Teorema de unificación En el caso de que un conjunto de expresiones sea unificable
el unificador más general existe y es único, con la excepción de que puedan existir variantes
alfabéticas.

2. Algoritmo de unificación
Antes de ver el algoritmo de unificación, hay que tener claro el concepto de conjunto
de desacuerdo.

César Ignacio García Osorio 4 LSI – Univ. de Burgos


Algoritmo de unificación

Definición 11 (Conjunto de desacuerdo). El conjunto de desacuerdo de un conjunto no


vacío de expresiones Ω está formado por las primeras subexpresiones (empezando
por la izquierda) de las expresiones en que éstas difieren. Para formar dicho conjunto,
se localiza el primer símbolo (empezando por la izquierda) en que se diferencian las
expresiones, y se ponen todas las subexpresiones que empiezan en dicho símbolo en un
conjunto.

Ejemplo 2.1. Sea el conjunto de expresiones

Ω = {P (x, f (y, z)), P (x, a), P (x, g(h(k(x))))}

el primer símbolo en que difieren las expresiones ocupa la posición quinta, ya que los
cuatro primeros símbolos «P (x,» son los mismos para todas ellas. Por tanto el conjunto
de desacuerdo consiste en las subexpresiones que comienzan en la posición quinta. Dicho
conjunto será {f (y, z), a, g(h(k(x)))}.

Algoritmo de unificación

Paso 1: Inicializar: k = 0, Wk = W , σk = .
Paso 2: Si la cardinalidad de Wk es uno, terminar; σk es el unificador más general de W .
En caso contrario, encontrar el conjunto de desacuerdo Dk de Wk .
Paso 3: Si existen los elementos vk y tk en Dk tales que vk es una variable que no ocurre en
tk , ir al paso 4. En caso contrario, parar; W no es unificable.
Paso 4: Hacer sk+1 = sk {tk /vk } y Wk+1 = Wk {tk /vk } (Obsérvese que Wk+1 = W σk+1 ).
Paso 5: Hacer k = k + 1, e ir al paso 2.

Ejemplo 2.2. Encontrar el unificador más general de

W = {P (a, x, f (g(y))), P (z, f (z), f (u))}

1 σ0 =  y W0 = W . Como W0 no tiene cardinalidad uno, σ0 no es un unificador más


general de W .
2 El conjunto de desacuerdo es D0 = {a, z}. En D0 hay una variable vk = z que no
ocurre en tk = a.
3 Hacer:
σ1 = σ0 ◦ {t0 /v0 } =  ◦ {a/z} = {a/z}

W1 = W0 {t0 /v0 }
= {P (a, x, f (g(y))), P (z, f (z), f (u))}{a/z}
= {P (a, x, f (g(y))), P (a, f (a), f (u))}
4 W1 no es de cardinalidad uno, por tanto hay que hallar el conjunto de desacuerdo D1
de W1 : D1 = {x, f (a)}.
5 De D1 se obtiene v1 = x y t1 = f (a).

César Ignacio García Osorio 5 LSI – Univ. de Burgos


Algoritmo de unificación

6 Hacer:
σ2 = σ1 ◦ {t1 /v1 } = {a/z} ◦ {f (a)/x}
= {a/z, f (a)/x}

W2 = W1 {t1 /v1 }
= {P (a, x, f (g(y))), P (z, f (z), f (u))}{f (a)/x}
= {P (a, f (a), f (g(y))), P (a, f (a), f (u))}
7 W2 no es de cardinalidad uno, por tanto hay que hallar el conjunto de desacuerdo D2
de W2 : D2 = {u, g(y)}. De D2 se obtiene v2 = u y t2 = g(y).
8 Hacer:
σ3 = σ2 ◦ {t2 /v2 } = {a/z, f (a)/x} ◦ {g(y)/u}
= {a/z, f (a)/x, g(y)/u}

W3 = W2 {t2 /v2 }
= {P (a, f (a), f (g(y))), P (a, f (a), f (u))}{g(y)/u}
= {P (a, f (a), f (g(y))), P (a, f (a), f (g(y)))}
= {P (a, f (a), f (g(y)))}.

9 Como W3 es de cardinalidad uno, σ3 = {a/z, f (a)/x, g(y)/u} es un unificador más


general para W . El algoritmo de unificación anterior siempre termina para un conjunto
finito no vacío de expresiones, ya que si no terminara debería generar una secuencia
infinita W0 σ0 , W1 σ1 , W2 σ2 , . . . de conjuntos finitos no vacíos de expresiones con la
propiedad de que cada uno de ellos contienen una variable menos que el anterior. Pero
esto es imposible, ya que W contiene un número finito de variables distintas.

Teorema 2. Finalización del algoritmo de unificación Si W es un conjunto de expresiones


finito no vacío y unificable, entonces el algoritmo de unificación siempre termina en el paso 2, y el
último σk es un unificador más general de W .

Demostración. Dado que W es unificable, sea θ cualquier unificador de W . Se demostrará


por inducción que para k = 0, 1, 2, . . ., existe una sustitución λk tal que θ = σk ◦ λk .

• Para k = 0, se tiene que para λ0 = θ dado que σ0 =  efectivamente se cumple


θ = σk ◦ λk .
• Supóngase que θ = σk ◦ λk se cumple para 0 ≤ k ≤ n. Si W σk tiene cardinalidad
uno, entonces el algoritmo terminará en el paso 2. Dado que θ = σn ◦ λn , se
tiene que σk es un unificador más general de W . Si W σk no es de cardinalidad
uno, entonces el algoritmo pasará a determinar el conjunto de desacuerdo Dn
de W σk . Como θ (= σn ◦ λn ) es un unificador de W , λn debe unificar Dn 1 . Sin
embargo, como Dn es un conjunto de desacuerdo debe haber como mínimo una
variable vn en Dn 2 . Sea tn cualquier otro elemento en Dn distinto de vn . Como λn
unifica Dn , se tienen que vn λn = tn λn . Si vn ocurriera en tn , entonces vn λn debería
ocurrir en tn λn , sin embargo, esto es imposible dado que vn y tn son distintos y
1
θ es un unificador de W , la cardinalidad de W θ es uno, como θ = σn ◦ λn se tienen que W θ =
W (σn ◦ λn ) = (W σn )λn lo que significa que la cardinalidad de (W σn )λn es uno , por tanto λn debe
unificar el conjunto de desacuerdo de (W σn ).
2
Ya que de no haber una variable, W no podría ser unificado.

César Ignacio García Osorio 6 LSI – Univ. de Burgos


Algoritmo de unificación

vn λn = tn λn . Por tanto, se tiene que vn no ocurre en tn , y el algoritmo de unificación


no termina en el paso 33 y continúa en el paso 4 haciendo σn+1 = σn ◦ {tn /vn }.
Sea λn+1 = λn − {tn λn /vn }4 . Entonces, como vn no ocurre en tn , se tiene que
tn λn+1 = tn (λn − {tn λn /vn }) = tn λn 5 . Por tanto, se tiene que:

{tn /vn } ◦ λn+1 = {tn λn+1 /vn } ∪ λn+1


= {tn λn /vn } ∪ λn+1
= {tn λn /vn } ∪ (λn − {tn λn /vn })
= λn

Es decir, λn = {tn /vn } ◦ λn+1 . Por tanto:

θ = σn ◦ λn = σn ◦ {tn /vn } ◦ λn+1 = σn+1 ◦ λn+1

Se obtiene finalmente que para todo k ≥ 0, hay una sustitución λk tal que θ =
σk ◦ λk . Puesto que el algoritmo de unificación debe terminar, y como no termina
en el paso 3, debe terminar en el paso 2. Como además θ = σk ◦ λk para todo k,
el último σk debe ser un unificador más general para W . Con lo que el teorema
queda demostrado.

3
Todo esto es bastante obvio si se tiene en cuenta que normalmente antes de la aplicación del algoritmo
de unificación se lleva a cabo un renombrado de variables, para que en dos expresiones distintas no
aparezca la misma variable.
4
Aquí no se está más que definiendo un nuevo elemento (un conjunto resultado de la diferencia de otros
dos). Si el elemento tn λn /vn no pertenece al conjunto λn , entonces λn+1 = λn . (No hay que perder de
vista que lo que se está intentando hacer es «pasar una ligadura» de la sustitución λ a la sustitución σ).
5
Como vn no ocurre en tn , el efecto de aplicar una sustitución a tn no va a depender de que la variable vn
aparezca o no aparezca ligada en la sustitución.

César Ignacio García Osorio 7 LSI – Univ. de Burgos


Algoritmo de unificación

3. Implementación en Python
La implementación en Python del algoritmo de unificación es relativamente inmediata.
Lo más relevante quizás sea la elección de cómo representar las fórmulas. El que sigue es
el código para una propuesta de implementación (diseñada siguiendo la estructura para
este algoritmo en Common Lisp de [Tan93]) donde las fórmulas se representan como
listas de listas en las que el primer elemento es el símbolo de predicado, representado
como una cadena, y los restantes son sus argumentos, representados como sublistas
para los argumentos que sean funciones, y como cadenas para los argumentos que sean
contantes o variables. Las variables se diferencian de las constantes porque la cadena
que las representa comienza por el carácter «?».
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 """Implementación de la unificación en Python."""
4
5 DEBUG = False
6
7 def subst(new, old, lst):
8 "Sustituye las ocurrencias de old por new in lst"
9 return [new if e == old else
10 e if type(e) != list else
11 subst(new, old, e) for e in lst]
12
13 def isVar(x):
14 "Comprueba si x comienza por ?"
15 return type(x) == str and x[0] == '?'
16
17 def disagreement(p, q):
18 "Devuelve las primeras subexpresiones en que difieren P y Q"
19 # Si P y Q son variables distintas, el desacuerdo es [P, Q]
20 if isVar(p):
21 if p == q: return None
22 else: return [p, q]
23 if isVar(q):
24 if p == q: return None
25 else: return [q, p]
26 # Si tanto P como Q listas vacias, no hay desacuerdo
27 if p == [] and q == []: return None
28 if q == [] or p == []: return ['fail', 'fail'] # no son unificables
29 # Si tanto P como Q no son ni NIL ni listas y son
30 # distintos ya he encontrado el conjunto de
31 # desacuerdo, aunque no ser'an unificables porque
32 # ninguno es una variable.
33 if type(p) != list or type(q) != list:
34 if p == q: return None
35 else: return [p, q]
36 d1 = disagreement(p[0], q[0])
37 if d1 != None:
38 return d1
39 return disagreement(p[1:], q[1:])

César Ignacio García Osorio 8 LSI – Univ. de Burgos


Algoritmo de unificación

40
41 def occursp(x, y):
42 "Comprueba si x ocurre en y."
43 if y == []: return False
44 if isVar(y): return x == y
45 if type(y)!=list: return False
46 return occursp(x, y[0]) or occursp(x, y[1:])
47
48 def unify(p, q, bdgs=[[True, True]], t=""):
49 "Implementación del algoritmo de unificación."
50 d = disagreement(p, q)
51 if DEBUG:
52 print(t+"unify( ", end="")
53 print(term2str(p), end=", ")
54 print(term2str(q)+" )")
55 # Si no hay desacuerdo, son unificables
56 if d == None: return bdgs
57 # Si hay desacuerdo, pero el primer elemento no es
58 # una variable, no puede deshacer el desacuerdo,
59 # p y q no son unificables
60 if not isVar(d[0]): return None
61 # Si el primer elemento es una variable, pero ocurre
62 # en el segundo no es posible la unificaci'on
63 if occursp(d[0], d[1]): return None
64 res = unify(subst(d[1], d[0], p),
65 subst(d[1], d[0], q),
66 [d]+subst(d[1], d[0], bdgs), "\t"+t)
67 if DEBUG:
68 print(t+subst2str(res))
69 return res
70
71
72
73 def list2str(lst):
74 """Los términos en los que el símbolo de función es un '.' se
75 consideran que representan una lista de cabeza el primer argumento
76 y de cola el segundo. Esta función los imprime en 'bonito'.
77 Los términos:
78 ['.','a',['.','b','nil']], ['.','1',['2','3']]
79 los imprime como:
80 [a, b] [1, 2 | 3 ]
81 """
82 l = lst
83 res = '['+term2str(l[1])
84 l = l[2]
85 while l[0] == '.':
86 res+=', '+term2str(l[1])
87 l = l[2]
88 if l == 'nil':
89 res+=']'
90 else:
91 res += ' | '+l+']'
92 return res

César Ignacio García Osorio 9 LSI – Univ. de Burgos


Algoritmo de unificación

93
94 def term2str(x):
95 "Transforma un término en una cadena para su impresión."
96 if type(x) != list:
97 return x
98 if len(x) > 1:
99 if x[0] == '.': # list format
100 return list2str(x)
101 else:
102 args = [term2str(a) for a in x[1:]]
103 return x[0]+'('+', '.join(args)+')'
104 else: return x[0]
105
106 def term2strOld(x): # Old version of term2str
107 if type(x) != list: return x
108 if len(x) > 1:
109 args = [term2strOld(a) for a in x[1:]]
110 return x[0]+'('+', '.join(args)+')'
111 else: return x[0]
112
113 def subst2str(x):
114 "Transforma una substitución en una cadena para su impresión."
115 if x is None: return '{}'
116 else: return '{ '+', '.join([lig2str(l) for l in x[-2::-1]])+' }'
117
118 def lig2str(x):
119 "Transforma una ligadura en una cadena para su impresión."
120 return term2str(x[1])+'/'+x[0]
121
122 def testTerm2str(x):
123 "Función para comprobar el funcionamiento de term2str."
124 print("El término", x, "como cadena es", term2str(x))
125
126 def testDisagreement(a, b):
127 "Función para comprobar el funcionamiento de disagreement."
128 print("El desacuerdo de", a, "y", b, "es", disagreement(a, b))
129
130 def testUnify(a, b):
131 "Función para comprobar el funcionamiento de unify."
132 print("El u.m.g. de", term2str(a), "y", term2str(b), "es", end=' ')
133 print(subst2str(unify(a, b)))
134
135
136
137
138 # Comprueba el funcionamiento de las funciones
139 if __name__ == '__main__':
140 if DEBUG:
141 testTerm2str(['P', ['f', '?x', 'a'], ['g', '?x']])
142 testTerm2str(['P', '?y', ['g', 'b']])
143 testTerm2str(['P', '?x', ['g', '?y']])
144 testTerm2str(['P', ['g', '?v'], '?v'])
145 testTerm2str(['P', [', ', '1', ['.', '2', '32']]])

César Ignacio García Osorio 10 LSI – Univ. de Burgos


Algoritmo de unificación Referencias

146 if DEBUG:
147 testDisagreement(['f', '?x'], ['f', 'a'])
148 testDisagreement(['P', '?x', 'b'], ['P', '?x', '?y'])
149 testDisagreement(['f', 'a'], ['f', 'a'])
150 testDisagreement(['P', '?x', 'b'], ['P', ['f', 'a'], '?y'])
151 if True:
152 testUnify(['f', '?x'], ['f', 'a', 'b'])
153 testUnify(['f', '?x'], ['f', 'a'])
154 testUnify(['P', '?x', '?y'], ['P', 'a', 'b'])
155 testUnify(['P', '?x', 'b'], ['P', 'a', '?y'])
156 testUnify(['P', ['f', '?x', 'a'], ['g', '?x']],
157 ['P', '?y', ['g', 'b']])
158 testUnify(['P', '?x', ['g', '?y']],
159 ['P', ['g', '?v'], '?v'])
160 print(unify(['P', '?x', ['g', '?y']], ['P', ['g', '?v'], '?v']))
161 testUnify(['L', ['.','?h','?t'],['i','?tl']],
162 ['L',['.','1',['.','2','n']],'?l'])

Referencias
[CR73] Chin-Liang Chang and Char-Tung Lee Richard. Symbolic Logic and Mechanical
Theorem Proving. Computer science classics. Academic Press, 1973.

[LM88] J-L. Lassez and K. Marriott. Unification revisited. In Jack Minker, editor,
Foundations of Deductive Databases and Logic Programming, volume 1, pages
587–625. Morgan Kauffmann, 1 edition, 1988.

[LVDG91] Peter Lucas and Linda Van Der Gaag. Principles of expert systems. Addison-
Wesley, 1991.

[Tan93] Steven L Tanimoto. The Elements of Artificial Intelligence Using Common LISP.
WH Freeman & Co., 1993.

César Ignacio García Osorio 11 LSI – Univ. de Burgos

Vous aimerez peut-être aussi