Se trata de construir un motor de inferencia (M.I.) en C,
C++, Java, o Pascal en su defecto, que soporte únicamente el encadenamiento
hacia atrás.
Consulta las reglas generales de entrega de prácticas.
1. El motor de inferencia se basará en lógica proposicional, debiendo soportar cláusulas de Horn: es decir, las reglas sólo tienen un consecuente y todos los precedentes están relacionados por el juntor y.
El programa debe tener un menú principal con las siguientes opciones:
Insertar
<H>echo Insertar <R>egla
<L>istado de la base de conocimiento
<E>ncadenamiento hacia atrás
Opción:
El formato y opciones del menú son libres, pero esas opciones deben estar.
La entrada de hechos y reglas es libre. Los hechos no tienen ningún formato especial. En cuanto a las reglas, se pueden pedir en el formato que se prefiera (incluso consecuentes y hechos por separado).
La opción de listado debe producir la salida de los hechos tal cuál están almacenados, y las reglas con el formato:
consecuente :- precedente1,precedente2,precedente3,...,precedenteN
La opción de encadenamiento hacia atrás debe pedir un hecho objetivo,. y mostrar por pantalla, al final de la inferencia, si ese hecho es cierto o falso. Por ejemplo, supongamos:
Insertar
<H>echo Insertar <R>egla
<L>istado de la base de conocimiento
<E>ncadenamiento hacia atrás
Opción: L
Reglas:
a :- b,c,d
Hechos:
b
c
d
Insertar
<H>echo Insertar <R>egla
<L>istado de la base de conocimiento
<E>ncadenamiento hacia atrás
Opción: E
Introduzca Objetivo: a
El objetivo es cierto.
Insertar
<H>echo Insertar <R>egla
<L>istado de la base de conocimiento
<E>ncadenamiento hacia atrás
Opción: L
Reglas:
a :- b,c,d
Hechos:
b
c
d a
En cuanto al diseño de la práctica, se aconseja que se diseñe una estructura llamada hecho. Una regla no es más que un hecho actuando como consecuente, más un conjunto indeterminado de hechos actuando como precedentes. Puede utilizarse, por ejemplo, un vector con un tope de 20 precedentes para implementar esto, aunque, por supuesto, lo más correcto sería un vector dinámico de precedentes.
Para guardar los hechos y las reglas, es posible utilizar un vector dinámico separado para cada una de estas dos tipos de datos.
En cuanto al algoritmo de encadenamiento hacia atrás, sólo debe ocuparse de confirmar o no una regla según sus precedentes existan en la base de reglas o no.
atras(objetivo:hecho):boolean
dev <- true
if (not(existe_hecho_en_BC(objetivo)))
regla_obj <- busca_regla_por_consecuente(lista_reglas,objetivo)
while (dev = true
and
num_reglas_disponibles_consecuente(lista_reglas,objetivo)<>0)
if (regla_encontrada(regla_obj))
n <- 0
precs <- 0
while (n < num_precedentes(regla_obj))
if (atras(precedente(regla_obj,n))
precs <- precs + 1
n <- n + 1;
end
if (precs<>num_precedentes(regla_obj))
dev <- false
else
añade_hecho_BC(objetivo)
end
else dev <- false;
regla_obj <- busca_sig_regla_por_consecuente(lista_reglas, objetivo);
end
end
end
return dev
end
La implementación del algoritmo es libre, si bien el
anterior puede servir de guía.
2. Introduce la siguiente regla:
a :- a
ó
if (a) then a.
y encadena hacia atrás con tu MI
utilizando como objetivo a. ¿ Que sucede ? Intenta resolverlo.
Entregad las respuestas a las
preguntas, y el código fuente, como práctica.