Prof. Rafael Martínez Tomás Desarrollo de Sistemas Basados en el Conocimiento en Clips Objetivos y resumen inicial ➤ Qué es lo diferente en este tipo de programación, una estructura y una orientación ➤ SBC y Sistemas Expertos ➤ Programación basada en reglas (conocimiento en general) versus programación procedimental ➤ Necesidad de explicación del conocimiento ➤ Flexibilidad de entradas, conocimiento disponible parcial ➤ Para qué tipos de problemas Conocimiento e Inferencia CONOCIMIENTO Una persona con un préstamo debe tener al menos 18 años de edad Una persona con un sueldo hasta $10,000 puede obtener un préstamo máximo de $2,000 Una persona con un sueldo entre $10,000 y $20,000 puede tener un préstamo máximo de $3,000 ◆ INFORMACiÓN Eduardo tiene un préstamo de $2,500 Juan tiene un préstamo de $1,750 INFORMACIÓN Gina Smith tiene una comunicación interauricular, 1 cm x 3,5 cm ◆ Si A entonces B A B CONOCIMIENTO El tabique auricular divide las cámaras de la aurícula derecha e izquierda del corazón humano. Si A y B entonces C A B Si A entonces B Si B entonces C A C B, C Representación y búsqueda Se dispone de dos cántaros de agua, uno de 4 litros y otro de 3 litros de capacidad, siendo ésta la única información que se tiene de los mismos. Existe una bomba de agua con la que se pueden llenar los cántaros. Se desea que el cántaro de 4 ls. de capacidad quede lleno por la mitad y el de 3 ls. vacío. 1. (x, y) --> (4, y) Llenar el cántaro de 4 ls. si x < 4 2. (x, y) --> (x, 3) Llenar el cántaro de 3 ls. si y < 3 3. (x, y) --> (0, y) Vaciar en el suelo el cántaro de 4 ls. si x > 0 4. (x, y) --> (x, 0) Vaciar en el suelo el cántaro de 3 ls. si y > 0 5. (x, y) --> (4, y − (4 − x)) Verter agua del cántaro de 3 ls. al de 4 hasta llenarlo. si x + y ³ 4, y>0y x<4 6. (x, y) --> (x − (3 − y), 3) Verter agua del cántaro de 4 ls. al de 3 hasta llenarlo. si x + y ³ 3, x>0e y<3 7. (x, y) --> (x + y, 0) Verter todo el agua del cántaro de 3 ls. al de 4. si x + y £ 4 e y>0 8. (x, y) --> (0, x + y) Verter todo el agua del cántaro de 4 ls. al de 3. !4 Buscando la solución !5 El problema de la búsqueda Espacio del problema o espacio de representación Conjunto de estados + Conjunto de operadores Instancia del problema Espacio del problema + Estado inicial + Estado objetivo o meta !6 Búsqueda en Árboles ABIERTA = (inicial) mientras NoVacia(ABIERTA) hacer n=ExtraePrimero(ABIERTA); si EsObjetivo(n) entonces devolver Camino(inicial, n); {desde TABLA_A} fin-si; nodo anterior S=Sucesores(n); q n para cada q de S hacer pone q en la TABLA_A con Anterior(q)=n Coste(inicial, q)= Coste (inicial, n)*Coste(n,q); Inserta q en ABIERTA; fin-para; fin-mientras; devolver “no encontrado”; coste desde inicio !7 Búsqueda en Grafos • Parte de un grafo dirigido simple, definido implícitamente a partir de un nodo inicial y una serie de operadores o reglas de producción. • Cada regla tiene un coste, de tal forma que no existen caminos infinitos. Es localmente finito, cada nodo tiene un nº finito de sucesores ABIERTA = (inicial) mientras NoVacia(ABIERTA) hacer n=ExtraePrimero(ABIERTA); si EsObjetivo(n) entonces devolver Camino(inicial, n); fin-si; S=Sucesores(n); Añade S a la entrada de n en la TABLA_A para cada q de S hacer si (q pertenece a TABLA_A) entonces Rectificar(q, n, Coste(n,q)); Ordenar(ABIERTA); {si es preciso} nodo si no pone q en la TABLA_A con B Anterior(q)=n Coste(inicial, q)= Coste (inicial, n)*Coste(n,q); ABIERTA=Mezclar (q, ABIERTA); genérica fin-si fin-para; fin-mientras; devolver “no encontrado”; anterior anterior coste desde inicio 1 lista de sucesores c(2),d(2) !8 Rectificación de nodos Funcion Rectificar(n, p, costepn); si (Coste(inicial, p) + costepn < Coste(inicial, n)) entonces Modifica la entrada del nodo n en la TABLA_A con Coste(inicial, n) = Coste(incial, p) + costepn; Anterior(n) = p; RectifcarLista(n); fin-si Funcion RectificarLista(n); LISTA = Sucesores(n); para cada q de LISTA hacer Rectificar(q, n, Coste(n,q); fin-para !9 Un ejemplo en lógica El cabo Romerales de la policía de Colmenarete se enfrenta a un nuevo caso de robo. El dueño de una joyería denuncia a Paco Navaja, Pedro Boina y José el Melenas, porque dice que el o los ladrones de su establecimiento debe estar entre ellos tres. Romerales conoce bien a los tres, de los que dispone de un gran historial. De estos archivos se deduce que Paco Navaja trabaja siempre con un cómplice, pero solo uno. Los otros dos rufianes nunca trabajarían ellos dos juntos sin un tercero. Estos dos han declarado dando sendas coartadas el uno del otro. Si uno de ellos fuera inocente, no tendría por qué mentir y el otro, por tanto, también sería inocente. ¿A qué conclusión llegó el cabo Romerales? Paco es culpable: p Pedro es culpable: q José es culpable: r Paco Navaja trabaja siempre con un cómplice, pero solo uno: p -> (q xor r) Los otros dos rufianes nunca trabajarían ellos dos juntos sin un tercero: (q and r) -> p Si uno de ellos fuera inocente, no tendría por qué mentir y el otro, por tanto, también sería inocente: -q <-> -r !10 Un ejemplo de tarea: Planificación ◆ Establecer una series de pasos que conduzcan a la consecución de un objetivo. ◆ Se fundamenta en algoritmos de búsqueda en un espacio de estados, Depositar(x), Precond: Agarrado(x) Añadir: Sobre-la-mesa(x) ∧ Brazo-Libre ➤ estado inicial Eliminar: Agarrado(x) ➤ operadores cuyos resultados se evalúan ➤ un estado que satisfaga las restricciones de objetivo final Apilar(x,y), Precondición: Despejado(y) ∧ Agarrado(x) Añadir: Brazo-Libre ∧ Sobre(x,y) Eliminar: Despejado(y) ∧ Agarrado(x) Desapilar(x,y), Precond: Sobre(x,y) ∧ Despejado(x) ∧ Brazo-Libre SOBRE(B,A) ∧ SOBRE-LA-MESA(A) ∧ SOBRE-LA-MESA(C) ∧ SOBRE-LA-MESA(D) ∧ BRAZO-LIBRE Añadir: Agarrado(x) ∧ Despejado(y) Eliminar: Sobre(x,y) ∧ Brazo-Libre Coger(x), Precond: Despejado(x) ∧ Sobre-la-mesa(x) ∧ Brazo-Libre Añadir: Agarrado(x) SOBRE(C,A) ∧ SOBRE(B,D) ∧ SOBRELA-MESA(A) ∧ SOBRE-LA-MESA(D) Eliminar: Sobre-la-mesa(x) ∧ Brazo-Libre !11 Representación en reglas REGLAS: IF está disponible el recuento completo de células sanguíneas y el número de células blancas es menor de 2500 THEN las siguientes bacterias podría causar la infección: E.coli (0.75) Pseudomonas-aeruiginosa (0.5) Klebsiella-pneumoniae (0.5) !12 Inferencia sobre reglas • Encadenamiento hacia adelante: regla 1: IF A entonces B regla 2: IF B entonces C Dado A podemos afirmar B, con lo que llegamos a afirmar C • Encadenamiento hacia atrás: regla 1’: IF A y D entonces B Planteamos C, lo que obliga a buscar B, lo que obliga a buscar A y D !13 Sistemas Basados en el Conocimiento (SBCs) Representación explícita del conocimiento utilizado para resolver el problema. Estructura: conocimiento If... Then... motor de inferencia datos resultados ➤ un componente declarativo, denominado base de conocimiento, que representa lo que se supone conoce un agente especializado en un determinado tipo de problemas, ➤ un procedimiento diseñado para simular un proceso de razonamiento cuyas premisas son los datos pregunta y que llega a las posibles respuestas usando los elementos de la base de conocimiento !14 Necesidad de modelado conceptual Regla 1: If..Then.. Regla 2: If..Then.. Regla 3: If..Then.. Regla 4: If..Then.. Regla 5: If..Then.. Regla 6: If..Then.. Regla 7: If..Then.. .. Regla 2001: If..Then.. Reglas inferencia A Regla 1: If..Then.. Regla 7: If..Then.. Regla 23: If..Then.. Base de conocimiento única y plana Reglas asociadas a sus correspondientes procesos de razonamiento. Hechos Inferencia A Reglas inferencia B Regla 31: If..Then.. Regla 57: If..Then.. Regla 96: If..Then.. Hechos Inferencia B Hechos !15 Diferenciación del conocimiento ◆ Conocimiento del dominio (ontologías) ◆ Conocimiento inferencial ◆ Conocimiento de tareas Diferentes PSM-Tareas infiriendo sobre un mismo conocimiento del dominio !16 Tipos de problemas Tareas Análisis Identifica Monitoriza Clasifica Síntesis Modificación Predice Predice Comportamiento Repara Predice Valores Supervisión Control Plan Configura Modela Diseña Diagnostica !17 Tipos de diagnóstico ! Diagnose !! Sugest-Confirm ! Refine!! Sugest ! Heuristic ! Abstract Match ! ! Sistematic ! ! Confirm! ! Diagen ! ! ! Cover-differentiate - ! ... ! ... Ejemplo de modelo de interpretación: Diagnóstico Abductivo alarma hemorragia Prueba de RumpellLeede = Negativa reglas de dependencia de alteraciones recubre modelo causal obtiene hipótesis predice hallazgo esperado Fragilidad vascular alta Prueba de Rumpellmodelo de manifestaciones Leede = Positiva hallazgo observado compara resultado distinto Diagnóstico Heurístico Datos abstractos Portador comprometido refine Datos Solución Match causal Infección Gramnegativa Inmunosuprimido Abstracción por generalización Leucopenia Abstracción por definición WBC bajo Abstracción cualitativa Solutiones abstractas abstract Abstracción por generalización Recuento de células blancas menor de 2500 match Refinamiento (subtipo) Infección E.coli El ciclo del conocimiento • • Externalización Socialización • • • In (Patel et al, 2009) by Stefanelli Internalización Combinación Adquisición del conocimiento: del texto al modelo !22 Aprendiaje automático Wij$ Wjk$ Entradas$ Salidas$ Capa$ entradas$ deep learning Capa(,s)$ oculta$ RNA’s$ CLUSTERING( APRENDIZAJE$ BAYESIANO$ SVM$ Capa$ salidas$ APRENDIZAJE$ POR$REFUERZO$ Presión(Arterial?( APRENDIZAJE$ DE$CONCEPTOS$ ALGORITMOS$ EVOLUTIVOS$ A lt a( Aplicaciones( SI( Gota?( APRENDIZAJE$ DE$REGLAS$ APRENDIZAJE$ ESTADÍSTICO$ SI( N o S í No rm al( NO( B aj a( Hipo2roidismo?( SI( N o S í NO( ÁRBOLES$DE$DECISIÓN$ Motores(de(búsqueda,(diagnós2co(médico,(detección(de(fraude(en(el(uso(de( tarjetas(de(crédito,(análisis(del(mercado(de(valores,(clasificación(de( secuencias(de(ADN,(reconocimiento(del(habla(y(del(lenguaje(escrito,(juegos(y( robó2ca.( !23 C Language Integrated Production System, CLIPS Desarrollada por Software Technology Branch de la NASA/Lyndon B. Johnson Space Center Características: - 3 paradigmas de programación: * programación basada en reglas: reglas+ hechos (facts) * programación procedural: funciones * programación orientada a objetos: objetos+paso de mensajes - CLIPS es una herramienta escrita en C - Plena integración con otros lenguajes como C y ADA - Desde un lenguaje procedural se puede llamar a un proceso CLIPS, éste realiza su función y luego le devuelve el control al programa. - Se puede incorporar código procedural como funciones externas en CLIPS - Las reglas pueden hacer "pattern-matching" sobre objetos (COOL) y hechos formando así un sistema integrado. - Encadenamiento hacia adelante. - CLIPS tiene una sintaxis estilo LISP que utiliza paréntesis como delimitadores. - Tiene versión en java (Jess) y versión con lógica difusa fuzzy (FuzzyClips) Componentes: - Memoria Global o Base de Hechos (hechos + instancias de objetos) - Base de Conocimientos o Reglas (reglas) - Motor de Inferencia (control) !24 Hechos (facts) • Los hechos representan un conjunto de variables, propiedades y valores que éstas pueden tomar. • Número ilimitado de campos separados por blancos y encerrados entre paréntesis balanceados. Los campos pueden tener o no un nombre asignado. • Todos los hechos tienen un identificador por el que puede ser referenciado. • CLIPS define por defecto un hecho inicial (initial-fact) cuando se carga la aplicación. • Todos los hechos se insertan en la lista fact-list. Se puede ver esta lista con el comando (facts) Ejemplos: (Antonio 45678 conductor Barcelona) (Empleado (nombre Antonio) (id 45678) (puesto conductor) (ubicacion Barcelona)) !25 Tipos de Hechos Hechos ordenados: • son básicamente listas • los campos no tienen nombre asignado y pueden ser de cualquier tipo primitivo de datos, excepto el primero, que debe ser un símbolo • el orden de los campos es significativo • tipos de los campos: float, integer, symbol, string, external-address, fact-address, instance-name, instance-address Ejemplo: (Antonio 45678CLZ conductor Barcelona) !26 Tipos de Hechos Hechos estructurados: - Definen un grupo de campos o atributos en una estructura similar a un registro. No importa el orden en el que se referencia el campo y/o el orden en el que aparezcan los campos - deftemplate que define una lista de campos con nombres que se denominan slots. - Es solamente una estructura, por lo que hay que afirmar los hechos que se ajusten a esa estructura. (deftemplate <nombre> [<comentario>] <definición-slot>*) (deftemplate vehiculo (slot matricula) (slot color) (slot propietario) (slot antiguedad) (Probar el entorno) (slot cilindrada) (slot kilometraje)) (assert (vehiculo (matricula xyz) (color rojo... !27 Funciones sobre hechos assert: (assert <fact>*) inserta el hecho/s en la Base de Hechos retract: (retract <fact-index>*) elimina el hecho/s en la Base de Hechos modify: (modify <fact-index>* (slot new-value)) modifica el hecho (Probar el entorno) !28 Atributos de los Slots (facets) - Son características que ayudan en el desarrollo y mantenimiento de un SE proporcionando un fuerte tipado y comprobación de restricciones. type (type <especificación-tipo>) - Define el tipo de datos que puede tener el slot. - Los tipos válidos son: SYMBOL, STRING, LEXEME, INTEGER, FLOAT, NUMBER. - Si se especifica ?VARIABLE, significa que el slot puede tomar cualquier tipo de dato (por defecto, se supone este). - LEXEME equivale a especificar SYMBOL y STRING conjuntamente, - NUMBER equivale a INTEGER y FLOAT. (deftemplate persona (multislot nombre (type SYMBOL)) (slot edad (type INTEGER)) ) (Probar en el entorno) !29 Restricciones de los Slots allowedallowed-symbols, allowed-strings, allowed-lexemes, allowed-integers, allowed-floats, allowed-numbers y allowed-values. Los atributos allowed- no restringen el tipo del slot. En el ejemplo, allowed-symbols no restringe el tipo del slot sexo a ser un símbolo. Sólo indica que si el valor del slot es un símbolo, entonces debe ser el símbolo hombre ó el símbolo mujer. En el ejemplo, cualquier string, entero o real sería legal para el slot sexo si no se especificara (type SYMBOL). (deftemplate persona (multislot (nombre (type SYMBOL)) (slot edad (type INTEGER)) (slot sexo (type SYMBOL)( allowed-symbols hombre mujer)) ) range cardinality (range <valor-min> <valor-max>) (cardinality <valor-min> <valor-max>) !30 Valor inicial en los Slots default (default <especificación>) Permite especificar un valor por defecto para un slot cuando no se le ha dado valor en la afirmación del hecho. (deftemplate ejemplo (slot a) ;;; el tipo se supondrá SYMBOL (slot b (type INTEGER)) (slot c (allowed-values rojo verde azul)) (multislot d) ;;; por defecto contendrá el valor () (multislot e (cardinality 2 2) (type FLOAT) (range 3.5 10.0))) Al afirmar un hecho sin dar ningún valor a ninguno de sus slots, el hecho realmente contendría lo siguiente: (ejemplo (a nil) (b 0) (c rojo) (d) (e 3.5 3.5)) !31 Definición y afirmación del conocimiento inicial deffacts (deffacts <nombre-colección-hechos> <hecho>*) permite especificar un conjunto de hechos como conocimiento inicial. (deffacts estudiante "Estudiantes al inicio del curso" (estudiante (nombre Juan) (sexo varon) (fuma? no) (alojado no)) (estudiante (nombre Pepe) (sexo varon) (fuma? si) (alojado no)) (estudiante (nombre Luisa) (sexo mujer) (fuma? no) (alojado no)) (estudiante (nombre Pedro) (sexo varon) (fuma? no) (alojado no))) El comando reset afirma los hechos iniciales (initial-fact) y los definidos con deffacts !32 Variables • Variables locales ?variable permite el pattern-matching $?variable, especial para multivalores • Variables globales Permiten almacenar valores accesibles en reglas y funciones, muy útiles para resultados (defglobal ?*num* = 3 ?*suma* = (+ ?*num* 2) ?*cadena* = “hola” ?*lista* = (create$ a b c) ) Pueden aparecer en la parte izquierda de las reglas si no son utilizadas para asignar un valor y su cambio no activa las reglas, pero no pueden ser parámetros de funciones ni métodos !33 Comodines • sencillo ? • múltiple $? Ejemplos: (courses (numbers $?course_nums)) (printout t “Your courses are” $?course_nums crlf)) (list ? $? c ?) encaja con: (list a b f c e), (list a d c b) pero no con: (list c), (list c d), (list a c d b) (do picnic on Sunday) encaja con: (do ? ? Sunday) (do ? on ?) (do ? on ?when) (do $? ) (do $? Sunday) (do ?chore $?when) !34 Estructura de una regla Clips defrule (defrule <nombre-regla> [<comentario>] <elemento-condición>* ; Parte izquierda (LHS) => <acción>*) ; Parte dcha. (RHS) de la regla (defrule evaluar-hallazgos-V1 (datos-paciente (id ?paciente) (edad ?edad&:(> ?edad 65))) ?hallazgos <- (hallazgos-paciente (id-paciente ?paciente) (hallazgos $?lista-hallazgos)) => (modify ?hallazgos (hallazgos V1)) EC1 EC2 EC3 LHS A1 RHS ) Si una regla no tiene parte izquierda, entonces el hecho (initial-fact) actuará como el elemento condicional para ese tipo de reglas, y la regla se activará cada vez que se ejecute un comando reset. !35 Satisfacibilidad y ejecución de una regla Clips Se deben verificar cada una de los ECs. Para ello: 1. Para ello deben existir los hechos especificados en las ECs 2. Se deben verificar las expresiones sobre ellos. Una regla se ejecuta cuando: 1. todos sus ECs son satisfechos por la base de hechos 2. el motor de inferencia la selecciona. Ejecutar una regla supone ejecutar las acciones de la RHS (defrule regla-ejemplo "Ejemplo de regla" (frigorifico interruptor encendido) (frigorifico puerta abierta) => (assert (frigorifico comida estropeada))) !36 Elementos Concionales (ECs) Tipo pattern: Con restricciones literales. (temperatura 28 grados) Con operadores lógicos. (opcion-elegida 1|2|3) (num-pacientes ~0) Con comodines simples y multicampo. (opcion-elegida ~1&~2&~3) (temperatura ? grados) (pacientes $? Lopez $?) Con predicados o llamadas a funciones: (temperatura (maximo ?tmax) Con variables simples y multicampo. (corporal ?t &:(> ?t ?tmax))) (temperatura ?t grados) (pacientes ?primero $?resto) !37 Elementos Concionales (ECs) Tipo test: (test <llamada-a-función>) (temp-max ?tmax) (temp-corporal ?t) (test (>= ?tmax ?t) Tipo or: (or <elemento-condicional>+) (or (temperatura-corporal alta) (presion-arterial baja)) Tipo and: (and <elemento-condicional>+) (or (and (presion-arterial baja) (temperatura-corporal baja)) (and (presion ?p&:(<?p 1500) (temperatura ?t&:(< ?t 35) !38 EC que carga el índice del hecho ?<var-direccion> <- (<elemento-condicional>) (defrule elimina-pacientes-fiebre ?fiebre <- (paciente (nombre ?n) (temp-ahora ?t &: (> ?t 37))) => (printout t "El paciente: " ?n “ tiene fiebre” crlf) (retract ?fiebre) ) !39 Acciones de la RHS Acciones para modificar la base de hechos: assert: (assert <fact>*) inserta el hecho/s en la Base de Hechos retract: (retract <fact-index>*) elimina el hecho/s en la Base de Hechos modify: (modify <fact-index>* (slot new-value)) modifica el hecho (problema del modify) Acciones procedurales: Asignación a una variable (bind <variable> <expresión>*) (sólo en la RHS) Condicional: (if <expresión> then <acción>+ [else <acción>+]) (switch <expresión-test> <sentencia-case><sentencia-case>+ [(default <acción>*)]) <sentencia-case> ::= (case <comparación> then <acción>*) Iteraciones: (while <expresión> [do] <acción>*) (loop-for-count (<var> <inicio> <final>) [do] <acción>*) (break) !40 Acciones de la RHS Comandos sobre la agenda: clear, halt, run Funciones predefinidas Funciones de entorno: (load <nombre-de-fichero>) (load-facts <nombre-de-fichero>) (save <nombre-de-fichero>) (save-facts <nombre-de-fichero>) (exit) ; cierra el entorno Clips Matemáticas: abs, div, mod, round..., sin, cos.. (<op> <expresión-numérica> <expresión-numérica>+) E/S: (open <nombre-fichero> <nombre-lógico> [<modo>]) (close [<nombre-lógico>]) (read [<nombre-lógico>]) (printout <nombre-lógico> <expresión>*) Strings: (str-cat <expresión>*) (sym-cat <expresión>*) (str-index <expresión-lexema> <expresión-lexema>) (sub-string <inicio> <fin> <expresión-de-cadena>) (str-length <expresión-simbólica-o-de-cadena>) !41 Funciones para valores multicampo Funciones predefinidas Manipulación de valores multicampo: (create$ <expresión>*) (delete$ <expresión-multicampo> <posición-inicio><posición-final>) (explode$ <expresión-string>) (first$ <expresión-multicampo>) (rest$ <expresión-multicampo>) (implode$ <expresión-multicampo>) (insert$ <expr-multicampo> <expr-entera><expresión-simple-o-multicampo>+) (length$ <expresión-multicampo>) (member$ <expresión-campo-simple> <expresión-multicampo>) (nth$ <expresión-entera> <expresión-multicampo>) (replace$ <expresión-multicampo> <inicio> <final><expresión-simple-o-multicampo>) (subseq$ <expresión-multicampo> <inicio> <final>) !42 Funciones definidas por el usuario (deffunction <nombre> [<comentario>] (<parámetro>* [<parámetro-comodín>]) <acción>* ) El valor devuelto por la función es la última acción o expresión evaluada dentro de la función. Si una deffunction no tiene acciones, devolverá el símbolo FALSE. Si se produce algún error mientras se ejecuta la función, cualquier otra acción de la función aún no ejecutada se abortará, y la función devolverá el símbolo FALSE. Ejemplo: (deffunction respuesta_si_no (?pregunta) (bind ?respuesta (preguntar ?pregunta si no s n)) (if (or (eq ?respuesta si) (deffunction preguntar (?pregunta $?valores-permitidos) (eq ?respuesta s)) (printout t crlf ?pregunta) then TRUE (bind ?respuesta (read)) else FALSE)) (if (lexemep ?respuesta) then (bind ?respuesta (lowcase ?respuesta))) (while (not (member ?respuesta ?valores-permitidos)) do (printout t ?pregunta) (bind ?respuesta (read)) (if (lexemep ?respuesta) then (bind ?respuesta (lowcase ?respuesta)))) ?respuesta) !43 Otro ejemplo de entrada (bind ?carroceria 0) (while (or (< ?carroceria 1)(> ?carroceria 5)) (printout t crlf "Estado de la carroceria:") (printout t crlf "1 - Muy bueno") (printout t crlf "2 - Bueno") (printout t crlf "3 - Regular") (printout t crlf "4 - Malo") (printout t crlf "5 - Muy malo") (printout t crlf ": ") (bind ?carroceria (read)) ) (defrule pide-datos-iniciales "Pide los datos de matricula y anio de matriculacion" (initial-fact) => (printout t crlf "Datos del vehiculo") (printout t crlf "Matricula: ") (bind ?matricula (read)) (printout t crlf "Anio de matriculacion: ") (bind ?anio (read)) (assert (vehiculo (matricula ?matricula)(anio-matriculacion ?anio))) ) !44 Ejemplo de Switch Ejemplo: (defrule precio_mecanico "" ?f2 <- (estado mecanico ?mec) => (retract ?f2) (if (or (eq ?mec leves) (eq ?mec graves)) then (bind ?respuesta (preguntar_valor "Cuál es el precio de las reparaciones mecánicas suministrado por los mecánicos (Pesetas): " ))) (switch ?mec (case ninguna then (assert (estado mecanico ?mec 0))) (case leves then (assert (estado mecanico ?mec ?respuesta))) (case graves then (assert (estado mecanico ?mec ?respuesta))) (case gravisimas then (assert (tasacion nula "Las reparaciones son demasiado costosas"))))) !45 Ejemplos de funciones (deffunction CalculaPorcentajeEntero(?Num ?Porcentaje) (bind ?ParteEntera (div (* ?Num ?Porcentaje) 100)) (bind ?Resto (mod (* ?Num ?Porcentaje) 100)) (if (> ?Resto 0.5) then (bind ?Resultado (+ ?ParteEntera 1)) else (bind ?Resultado ?ParteEntera) ) ) Otro ejemplo de captura: (deffunction es-del-tipo (?respuesta ?tipo ?posibilidades) ;; Si es de tipo mutiple recorre las posibilidades y devuelve TRUE si alguna coincide. ;;;En caso contrario devuelve FALSE. (if (eq ?tipo multiple) then (progn$ (?item ?posibilidades) ; para cada elemento de la lista ?posibilidades (if (eq ?respuesta ?item) then ;si coincide con la respuesta (return TRUE))) ; devuelve TRUE (return FALSE)) ;; Si es de tipo numerico devuelve TRUE si la respuesta lo es y FALSE en ;; caso contrario. (if (eq ?tipo numerico) then (return (numberp ?respuesta))) ;; Para los demas casos devuelve TRUE si la respuesta tiene una longitud ;; mayor que 0 y FALSE en caso contrario. (return (> (str-length ?respuesta) 0))) !46 Ejemplo de llamada desde una regla (deffunction factorial (?X) (bind ?temp 1) (loop-for-count (?i 1 ?X) do (bind ?temp (* ?temp ?i)) ) (return ?temp) ) (defrule ejemplo => (printout t crlf crlf "Calcular factorial de: ") (bind ?N (read)) (printout t "El resultado es " (factorial ?N) crlf) ) !47 El mismo proceso en una regla (defrule factorial => (printout t crlf crlf "Enter a number: ") (bind ?N (read)) (bind ?temp 1) (loop-for-count (?i 1 ?N) do (bind ?temp (* ?temp ?i)) ) (printout t "Factorial=" ?temp crlf) ) !48 Un bucle implícito (deffacts numbers (number 56) (number -32) (number 7) (number 96) (number 24)) (defrule find-largest-number (number ?x) (not (number ?y &: (> ?y ?x))) => (printout t “Largest number is “ ?x crlf)) !49 (deffacts initial-information ;datos de los rectangulos de cuyas areas se obtendra la media (rectangle 10 6) (rectangle 7 5) (rectangle 6 8) (rectangle 2 5) (rectangle 9 4) (sum 0) (count 0)) Un bucle menos implícito (defrule sum-rectangles (declare (salience 30)) (rectangle ?height ?width) => (assert (add-to-sum (* ?height ?width)))) ; crea un hecho add-to-sum por cada rectangulo (defrule sum-areas (declare (salience 20)) ;;; regla que suma todas las areas ?sum-adr <- (sum ?total) ?new-area-adr <- (add-to-sum ?area) ?count-adr <- (count ?counter) => (retract ?sum-adr ?new-area-adr ?count-adr) (assert (sum (+ ?total ?area))) (assert (count (+ ?counter 1)))) (defrule average (declare (salience 10)) ;;; regla que calcula e imprime la media ?sum-adr <- (sum ?total) ?count-adr <-(count ?counter) => !50 (printout t crlf "Here is the average area" (/ ?total ?counter) crlf)) Funciones de E/S (open <nombre-fichero> <nombre-lógico> [<modo>]) Abre un fichero con el modo especificado (“r”, “w”, “r+”, “a”) asociando el nombre de fichero dado al nombre lógico especificado. Si no se especifica modo, se supone “r” (close [<nombre-lógico>]) Cierra el fichero asociado con el nombre lógico especificado. Si no se especifica el nombre lógico, se cierran todos los ficheros. (printout <nombre-lógico> <expresión>*) Evalúa e imprime como salida al nombre lógico 0 o más expresiones no formateadas. (read [<nombre-lógico>]) Lee un campo simple (single field) desde el nombre lógico especificado. Si no se especifica nombre lógico, se supondrá stdin (entrada estándar). Devuelve el elemento leído (que será siempre de un tipo primitivo) si tiene éxito, o EOF si no hay entrada disponible. Ej.: (assert (habitación (número (read)))) (readline [<nombre-lógico>]) Lee una línea completa desde el nombre lógico especificado (supondrá stdin, si no se especifica ninguno). Devuelve un string si tuvo éxito, o EOF si no había entrada disponible. (format <nombre-lógico> <string-control> <parámetros>*) Envía al dispositivo asociado con el nombre lógico especificado un string formateado. El string de control contiene unos flags de formato que indican cómo serán impresos los parámetros. El funcionamiento es similar a la función printf del lenguaje C. La función devuelve el string impreso. !51 Motor de inferencia • Ciclo Básico: 1. Si se ha alcanzado el número de ciclo de desencadenamiento expresados o no hay foco actual, entonces PARAR. • Si no, seleccionar para ejecutar (2) la regla tope de la agenda del módulo actual. • Si no hay reglas en dicha agenda, entonces eliminar el foco actual de la pila de focos y actualizar al siguiente de la pila. • Si la pila de focos está vacía, entonces PARAR, si no ejecutar 1. de nuevo. 2. Se ejecutan las acciones de la parte derecha de la regla seleccionada. Incrementar el nº de reglas desencadenadas. • Si se usa return, entonces eliminar el foco actual de la pila de focos. • Como resultado acciones se activan o desactivan nuevas reglas. • Las reglas activadas se sitúan en la agenda del módulo en el que están definidas. • La situación concreta depende de la prioridad de la regla (salience) y de la estrategia de resolución de conflictos actual. Las reglas desactivadas salen de la agenda. • Si se utiliza prioridad dinámica (dynamic salience), entonces se reevalúan los valores de prioridad de las reglas de la agenda. • Ir al paso 1. declare (salience -100) Permite al usuario asignar una prioridad a una regla, entre -10000 y +10000, por defecto 0. !52 Instancias de una regla (Agenda) • Se construye una instanciación de la regla para cada conjunto de elementos que satisfacen la LHS. <prioridad> <nombre-regla> : fact-index* fact-index := f-<número-entero> • Fases: 1: Se toman todos los elementos que satisfacen cada una de sus condiciones. 2: Se toman las combinaciones de elementos que satisfacen la restricción impuesta por las variables que relacionan condiciones (aparecen los mismos nombres de variables. •La agenda es la lista de todas estas las reglas cuyas condiciones se satisfacen y todavía no se han ejecutado. !53 Resolucíón de conflictos en la agenda • Cuando una regla se activa de nuevo, se sitúa en la agenda...: a) por encima de todas las reglas de menor prioridad y por debajo de todas las reglas de mayor prioridad y. b) entre las reglas de igual prioridad, se utiliza la estrategia de resolución de conflictos actual para determinar su situación relativa. c) Si (a) y (b) no son suficientes para determinar el orden, las reglas se colocan arbitrariamente en relación con las otras reglas. No aleatoriamente, sino que depende de la implementación de las reglas. • Estrategias: hay 7, las principales • depth (estrategia por defecto): Las nuevas reglas se sitúan sobre todas las de la misma prioridad. • breadth: Las nuevas reglas se sitúan por debajo de todas las de la misma prioridad. • random: A cada activación se le asigna un número aleatorio que se utilizará para determinar su lugar entre las activaciones de igual prioridad (este número se mantiene entre cambios de estrategia). (set-strategy <nombre-estrategia>) !54 Algoritmo RETE !55 Eficiencia de las reglas ➮ Los patrones más específicos, con más restricciones, deben de ir primero, ya que, generalmente, producirán el número más pequeño de coincidencias y tendrán un mayor número de variables asignadas. Lo que provocará una mayor restricción en los otros patrones. ➮ Los patrones temporales deben de ir los ú́ltimos. Es decir, los correspondientes a hechos que se añaden y borran frecuentemente de la lista de hechos. Esto provocará un menor número de cambios en las coincidencias parciales. ➮ Los patrones más raros deben ser los primeros. Los patrones correspondientes a hechos que se presentarán pocas veces en la lista de hechos, si se colocan al principio reducirán el número de coincidencias parciales. ➮ La función test debe ponerse lo antes posible: ¿Así, cuál es mejor de R1 y R2? (defrule R1 ?p1 <- (valor ?x) ?p2 <- (valor ?y) ?p3 <- (valor ?z) ; comprueba que ningun valor es igual a otro (test (and (neq ?p1 ?p2) (neq ?p2 ?p3) (neq ?p1 ?p3)) => ) (defrule R2 ?p1 <- (valor ?x) ?p2 <- (valor ?y) (test (neq ?p1 ?p2)) ?p3 <- (valor ?z) (test (and (neq ?p2 ?p3) (neq ?p1 ?p3)) => ) !56 ;esencialmente (deffacts myfact (loop-fact)) (defrule simple-loop ?old-fact <- (loop-fact) => (printout t “Looping!” crlf) (retract ?oldfact) (assert (loop-fact))) Errores “garrafales” ; una variante (deftemplate registro (slot anda) (slot ya)) (deffacts error (registro (anda nil) (ya nil)) ; el mismo caso (defrule anda-que (defrule sexo_usuario ?anda <- (registro (anda ?var)) ?f2 <- (vehiculo (sexo_usuario ?sexo)) => => (printout t crlf "Sexo del usario: " crlf) (modify ?anda (anda ?var) (ya bien))) (bind ?sexo (read)) (modify ?f2 (sexo_usuario ?sexo))) !57 Implementación siguiendo el modelo alarma el motor no arranca indicador de gasolina = normal reglas de dependencia de estados recubre modelo causal obtiene TASK-METHOD diagnóstico-a- través-sugiere-y-comprueba; REALIZES: diagnóstico-vehículo; hipótesis hallazgo DECOMPOSITION: predice esperado INFERENCES: recubre, predice, compara; tanque de gasolina TRANSFER-FUNCTIONS: obtiene; vacío indicador de gasolina = cero/bajo ROLES: INTERMEDIATE: modelo de efectos hipótesis: “una posible solución”; hallazgo-esperado: “un hallazgo que se debería observar si la hipótesis fuera cierta”; hallazgo-observado : “el hallazgo realmente observado”; resultado : “el resultado de la comparación”; CONTROL-STRUCTURE: WHILE NEW-SOLUTION recubre(aviso->hipótesis) DO predice(hipótesis->hallazgo-esperado); obtiene(hallazgo-esperado-> hallazgo-observado), evidencia:=evidencia ADD hallazgo-observado); compara(hallazgo-observado+ hallazgo-esperado -> resultado); IF resultado == igual THEN BREAK-LOOP END IF; ENDWHILE; IF resultado == igual THEN tipo-fallo:= hipótesis ELSE “no se ha encontrado solución” END IF; END TASK-METHOD diagnóstico-a- través-sugiere-y-comprueba; hallazgo observado compara resultado distinto !58 Control sobre las inferencias Para establecer una estructura de control de este tipo mediante reglas como las que hemos visto, podemos utilizar uno de los siguientes métodos: 1. Incluir en cada regla una premisa que determine la fase (predice, obtiene, etc.) del proceso en que podrá ser activada y la afirmación del hecho que sitúa al sistema en la siguiente fase (si ha lugar): (defrule predice-... ?fase <- (fase predice) ... => ... (retract ?fase) (assert (fase obtiene))) 2. Otra opción es secuenciar a través de los niveles de prioridad, pero esto tiene el problema de que se pueden mezclar las fases, en tanto que, si en la fase obtiene entra a la agenda una regla de las de apoyo al predice, esta se activará antes que restantes correspondientes a obtiene. El ejemplo auto.clp (en el sitio web de Clips) utiliza este sistema. !59 Más opciones 3. La tercera opción (híbrida) es definir unas reglas específicamente para secuenciar las fases, que tienen una prioridad más baja que las reglas que soportan el conocimiento experto propiamente dicho, y que cambian el hecho de define las subtarea activa. (defrule predecir-obtener (declare (salience –100)) ?subtarea <- (subtarea predecir) => (retract ?subtarea) (assert (subtarea obtener))) (defrule obtener-comparar (declare (salience –100)) (retract ?subtarea) Así, cada regla “experta” comienza con una premisa que la identifica como perteneciente al conocimiento de apoyo de una subtarea: (assert (subtarea comparar))) (defrule predice-... ?subtarea <- (subtarea obtener) => (defrule comparar-predecir (subtarea predecir) (declare (salience –100)) ; premisas que determinan la hipótesis de una avería ?subtarea <- (subtarea comparar) ... => => ... (retract ?subtarea) (assert (subtarea predecir))) ) 4. Algo muy parecido es utilizar la pila de módulos con la secuencia: (focus modulo1) (return)(focus modulo2)(return)... !60 Alternativas • Alternativamente a esta opción, podría escribirse una regla única de control que fuera lanzando las sucesivas subtareas sin tener que aparecer explícitamente en la regla, de esta forma: (defrule lanza-subtarea (declare (salience –100)) ?subtarea <- (subtarea ?subtarea-actual) (subtarea-siguiente-a ?subtarea-actual ?subtarea-siguiente) => (retract ?subtarea) (assert (subtarea ?subtarea-siguiente))) Siempre y cuando se hayan definido estas fases como hechos sucesivos de un slot fase-posterior: (deffacts secuencia-subtareas (subtarea predecir) (subtarea-siguiente-a predecir obtener) (subtarea-siguiente-a obtener comparar) (subtarea-siguiente-a comparar predecir)) • Algo totalmente equivalente sería utilizar una lista de subtareas y una regla que las secuenciara, es decir: (defrule lanza-subtarea (declare (salience –100)) ?subt <- (subtarea ?subt-actual) ?sec-subts <- (secuencia-subts ?subt-siguiente $?otras-subts) => (retract ?subt ?sec-subts) (assert (subtarea ?subt-siguiente)) (assert (secuencia-subts ?otras-subts ?subt-siguiente))) Con (deffacts estructura-subtareas (subtarea predecir) (secuencia-subts obtener comparar predecir)) !61 El mantenimiento de la verdad LOGICAL • Este EC proporciona capacidad de mantenimiento de verdad para entidades (hechos o instancias) creados por una regla que usa el EC logical. • Permite establecer una dependencia lógica entre entidades creadas en las RHS (o como resultado de las acciones realizadas en la RHS) y las entidades que matchearon los patrones contenidos en el EC logical de la LHS de las reglas. • Si una entidad que justifique a otra desaparece, esta última también se elimina. Ej. (defrule R1 (defrule R2 (defrule R3 (logical (G)) => (assert (F))) (logical (F)) => (assert (H))) (logical (H)) => (assert (I))) Afirmar F lleva a incluir F, H y I en la BH Si retiramos H con (retract H) automáticamente se retira I. •Si se crea una entidad sin el EC logical, se dice que esta entidad tiene justificación incondicional. Si se elimina una regla que apoya la justificación para una entidad, se elimina la justificación de tal entidad, pero no se elimina la entidad misma. •Si en el antecedente (LHS) de una regla aparece uno o varios EC logical, éstos deben aparecer los primeros. !62 Del control de las reglas y su tipología • En principio tenemos dos niveles de prioridad, las reglas que hemos denominado expertas y otro a las reglas de control. • Podrían introducirse dos niveles más, también para el correcto control en la evaluación de las reglas. • El mayor nivel de prioridad deberían tenerlo aquellas reglas que detectan situaciones que se han definido como ilegales del programa. • Las reglas especificas para plantear preguntas al usuario deber deberían tener un nivel intermedio de prioridad, entre las reglas de control y las reglas expertas, de tal forma que solo se pregunte al usuario cuando no haya conocimiento experto para inferir el valor que se cuestiona. • Pero no deberían utilizarse muchos más niveles de prioridad, desde luego no dentro de las reglas “expertas”, estas deben contener en sus premisas la determinación exacta y explícita de la situación que las hacen activarse. • Así, en un sistema algo grande, es preferible utilizar módulos contenedores compactos de reglas, y por tanto más sistemas de reglas en sí más reducidos, que se activan según una estructura de control procedimental. !63 Ejercicios • “Hagamos algún ejercicio con lo que ya sabemos...” Ejercicio-24: Permutaciones de los colores. Ejercicio-20: Pasar a código binario. Tratando con strings. Ejercicio-3: Dada una fecha, evaluar su corrección. Ejercicio-1: Poner notas literales desde dos exámenes y las faltas de asistencia. Diferencia con la versión procedimental. Diferentes formas de resolver el problema Ejercicio-2: Asignar habitaciones Ejercicio-15 y 16: Correo postal y viajes. Consulta de tablas. Ejercicio-13: Diagnóstico de un motor (recorrido de un árbol binario) Ejercicio-12: Fórmulas lógicas. Creando un árbol. Ejercicio-5: Diagnóstico médico. Poniendo orden. Ejercicio-10 : El mundo de bloques. También en: http://www.uco.es/~i82coory/ bloques.htm Ejercicio-19: Un problema de búsqueda. Problema de los cántaros. También solucionado en http://www.uco.es/~i82coory/jarras.htm. !64 Árboles de decisión • - Un árbol compuesto por nodos intermedios, que representan afirmaciones (“El tiempo de tromboplastina parcial activado es normal”), de los que salen enlaces, según la afirmación sea cierta o no (evaluación del nodo), hacia dos nodos descendientes (binario). • - También pueden verse los nodos intermedios como preguntas que sólo tienen dos posibles respuestas Si y No (“¿Es normal el tiempo de tromboplastina parcial activado?”) y los nodos hoja como afirmaciones concluyentes (“Secuestro leucocitario”). “test de Rumpell Leede positivo” Cierto Falso “Recuento de plaquetas bajo” ”VASCULITIS” Cierto Falso “No hay reducción o ausencia de megacariocito” Cierto Falso “APLASIA DE MÉDULA ÓSEA ” “Tamaño normal del bazo” Cierto “SECUESTRO LEUCOCITARIO” “Tiempo de tromboplastina parcial activado normal” Falso “CAUSAS INMUNOLOGICAS” Cierto Falso “Tiempo de romboplastina parcial activado bajo” “Deficiencia del FACTOR VII” Cierto “Deficiencia del FACTOR XII, XI, IX o VIII” Falso “Deficiencia del FACTOR X, V, Prothrombina o Fibrinógeno” !65 Algoritmo para el árbol binario El algoritmo de recorrido de un árbol de decisión de este tipo es muy sencillo, Comienzo nodo-actual := nodo-raiz; Mientras not(nodo-hoja(nodo-actual)) hacer respuesta:= preguntar(nodo-actual); ; Si respuesta =cierto entonces nodo-actual := descendiente-cierto(nodo-actual); Si respuesta =falso entonces nodo-actual := descendiente-falso(nodo-actual); Fin Visualizar-afirmacion(nodo-actual) Fin !66 Estructuras para el árbol binario (deftemplate nodo (slot nombre) (slot tipo (allowed-values intermedio hoja)) (slot afirmacion) (slot sig-h-cierto) (slot sig-h-falso)) ;Definimos los nodos como hechos segun esa plantilla: (deffacts arbol-diagnostico (nodo (nombre PRLP) (tipo intermedio) (afirmación "Prueba de Rumpell-Leede positiva") (sig-h-cierto VAS) (sig-h-falso RPB)) (nodo-actual PRLP)) ; el nodo raíz como nodo actual ;Así ya, el proceso de cada nodo depende de si es tipo intermedio. Si lo es hay que preguntar... (defrule afirmacion ?nodo <- (nodo-actual ?nombre)) (nodo(nombre ?nombre) (tipo intermedio) (afirmacion ?afirmacion)) (not (respuesta ?)) => (printout t "¿Es cierto lo siguiente (S/N)? " ?afirmacion) (assert (respuesta (read)))) (defrule respuesta-incorrecta ; restringe los valores de la respuesta a la anterior pregunta ?respuesta <- (respuesta ~S&~N)) => (retract ?respuesta)) ;Al eliminar el hecho se activa inmediatamente la regla afirmación. !67 Recorriendo el árbol binario Por el contrario, si la respuesta fue correcta, o bien se activa: (defrule respuesta-afirmativa ?nodo <- (nodo-actual ?nombre)) (nodo(nombre ?nombre) (tipo intermedio) (sig-h-cierto ?descendiente-cierto)) (?respuesta <- (respuesta S)) => (retract ?nodo ?respuesta) (assert (nodo-actual ?descendiente-cierto)) O bien se activa: (defrule respuesta-negativa ?nodo <- (nodo-actual ?nombre)) (nodo(nombre ?nombre) (tipo intermedio) (sig-h-falso ?descendiente-falso)) (?respuesta <- (respuesta N)) => (retract ?nodo ?respuesta) (assert (nodo-actual ?descendiente-falso)) Para los nodos hoja: (defrule nodos-hoja ?nodo <- (nodo-actual ?nombre)) (nodo(nombre ?nombre) (tipo hoja) (afirmacion ?afirmacion)) (not (respuesta ?)) => (retract ?nodo ?respuesta) (printout t "Se deduce que... " ?afirmacion crlf) (assert (nuevo-caso))) ; se afirma para determinar la repetición del proceso !68 Vuelta a empezar Se afirma el hecho nuevo-caso para determinar el lanzamiento de la siguiente regla que pregunta al usuario si desea continuar con otro caso y esto requiere además otras dos reglas: (defrule preguntar-por-nuevo-caso (nuevo-caso) (not (respuesta ?)) => (printout t "¿Desea comenzar un nuevo caso (S/N)? ") (assert (respuesta (read)))) (defrule nuevo-caso ?nuevo-caso <- (nuevo-caso) ?respuesta <- (respuesta S) => (retract ?nuevo-caso ?respuesta) (assert (nodo-actual PRLP))) (defrule terminar ?nuevo-caso <- (nuevo-caso) ?respuesta <- (respuesta N) => (retract ?nuevo-caso ?respuesta) (printout t "FIN DE LA EJECUCION" crlf)) . !69 Árboles n-arios “Tiempo de tromboplastina parcial activado?” normal “Deficiencia del FACTOR VII” bajo “Deficiencia del FACTOR XII, XI, IX o VIII” alto “Deficiencia del FACTOR X, V, Prothrombina o Fibrinógeno” Comienzo nodo-actual := nodo-raiz; Mientras not(nodo-hoja(nodo-actual)) Hacer respuesta:= preguntar(nodo-actual); i:=1; Mientras existe-descendiente(nodo-actual, i) y respuesta <> valor-descendiente(nodo-actual, i) Hacer i:= i+1; Fin Si existe-descendiente(nodo-actual, i) entonces nodo-actual := descendiente(nodo-actual, i); Fin Visualizar-afirmacion(nodo-actual) Fin !70 Módulos ¿Qué ocurre si la memoria de producción (base de reglas) es grande? • Los módulos permiten agrupar un conjunto de construcciones de modo que se mantenga un control explícito sobre la restricción del acceso de otros módulos: ámbito global estrictamente jerárquico en una sola dirección. • Agrupando las reglas en módulos es posible controlar la ejecución de éstas. (defmodule <nombre-módulo> [<comentario>] <especificación-acceso>*) <especificación-acceso> ::= (export <ítem>) | (import <nombre-módulo> <ítem>) <ítem> ::= ?ALL | ?NONE | <construcción> ?ALL | <construcción> ?NONE | <construcción> <nombreconstrucción>+ <construcción> ::= deftemplate | defclass | defglobal | deffunction | defgeneric (defmodule MAIN) (defmodule CAPTURAR-ENTRADAS) (defmodule EVALUAR-DATOS) (defmodule PRESENTAR-SOLUCIONES) Referirse a una construcción externa: <nombre-modulo>::: <nombre-construccion> Ej. CAPTURAR-ENTRADAS::datos-paciente !71 Importación y exportación • export se usa para indicar qué construcciones serán accesibles (visibles) a otros módulos • import se usa para indicar qué construcciones, que se referencián, serán de otros módulos. • Sólo se puede exportar e importar: deftemplate, defclass, defglobal, deffunction y defgeneric. • Es decir, no se pueden exportar ni importar las construcciones: deffacts, defrule y definstances. • Existen tres formas de importación/exportación (defmodule A (export ?ALL)) (defmodule B (export deftemplate ?ALL)) (defmodule CAPTURA-DATOS (export deftemplate datos-paciente)) !72 Módulos y control • Cada módulo tiene su propia agenda (y su conjunto conflicto). • La ejecución puede controlarse seleccionando una agenda. • De esta forma, se elige un conjunto determinado de reglas a ejecutar. (focus <nombre-módulo>+) • El foco actual es el valor tope de una estructura de datos similar a una pila, denominada pila de focos. •Cambiar el foco actual implica apilar el nuevo foco y abandonar el módulo (return). • Cuando se vacía la agenda de un módulo (foco actual), el foco actual se elimina de la pila de focos, y el siguiente módulo en la pila de focos se convierte en el foco actual. • La ejecución de las reglas continúa hasta que: - cambia el foco a otro módulo, - no haya reglas en la agenda, ó - se ejecute return en la RHS de una regla. !73 Ejemplos con módulos (defmodule A) (defmodule MAIN (export ?ALL)) (deftemplate A::persona (slot x)) (deftemplate MAIN::objetivo (slot nombre)(slot estado)) (defmodule B) (defrule MAIN::ejemplo-foco (defrule B::asigna => (persona (x 3)) (printout t "Disparo en el módulo MAIN."crlf) => ) (assert (objetivo (nombre principal)(estado resuelto))) -------------------------------------------------------------------- (focus A B)) (defmodule A (export deftemplate persona)) (deftemplate A::persona (defmodule A (slot x)) (export ?ALL) (defmodule B (import A deftemplate persona)) (import MAIN deftemplate initial-fact objetivo)) (defrule B::asigna (persona (x 3)) (deftemplate A::subobjetivo-A (slot nombre)(slot estado)) => ) (defrule A::regla-ejemplo ---------------------------------------------------------------------- (objetivo (nombre principal) (estado resuelto)) (defmodule A (export deftemplate ancho alto)) => (deftemplate A::ancho (slot x)) (assert (subobjetivo-A (estado resuelto))) (deftemplate A::alto (slot y)) (printout t "Disparando la regla en el módulo A."crlf)) (deffacts A::info (ancho (x 3))(alto (y 4))) (defmodule B (defmodule B (import A deftemplate ancho)) (import A deftemplate subobjetivo-A) (import MAIN deftemplate initial-fact)) (defrule B::regla-ejemplo (subobjetivo-A (estado resuelto)) => (Ejercicio 26. Uso del Teorema de Pitágoras) (printout t "Dispara la regla en el módulo B."crlf)) (Ejercicio 25. Cajas registradoras) !74 (Ejemplo en: http://www.uco.es/~i82coory/diagnostico.htm) Tratamiento de la incertidumbre en Clips Clips no incluye ningún mecanismo para el tratamiento de la incertidumbre, por tanto, si queremos emplear alguna técnica para ello, hay que codificar el soporte y los mecanismos asociados. Como ejemplo vamos a solucionar el tratamiento de la incertidumbre con factores de certeza Mycin. (deftemplate oav-fc (multislot objeto (type SYMBOL)) (multislot atributo (type SYMBOL)) (multislot valor) (slot fc (type FLOAT) (range –1.0 +1.0))) ;; rango de los factores de certeza Ejemplo: (oav-fc (objeto microorganismo) (atributo morfologia) (valor bacilo) (fc 0.7)) !75 Reglas Mycin FC(hipótesis) = max{0, FC(evidencia)} ⋅ FC(hipótesis, evidencia) -1 ≤ FC ≤ 1 !76 Un ejemplo: Sean las reglas: R1: Si h2 o h3 entonces h6 (0’4) R2: Si h6 y h7 entonces h1 (0’7) R3: Si h4 o h5 entonces h1 (0’1) FC(h2) =0,3, FC(h3)=0,6, FC(h4)=0,2, FC(h5)=0,8, FC(h7)=0,9 El atributo h1 es el atributo objetivo, empleándose encadenamiento hacia atrás. Calcular el factor de certeza que resulta para el atributo h1. Solución: El conjunto conflicto inicial {R2, R3}. R2 es la regla más prioritaria, => necesario conocer el factor de certeza para h6 y h7. Se conoce este factor para h7, a partir de la evidencia inicial, pero no para h6. Este último valor puede calcularse mediante la regla R1. En efecto, FC(h2, e’) = 0’3, FC(h3, e’) = 0’6 FC(h2 o h3, e’) = max{0’3, 0’6} = 0’6 Por tanto, a partir de R1: FC(h6, e1’) = max{0, FC(h2 o h3, e’)} . FC(h6, h2 o h3) } = 0’6 . 0’4 = 0’24 ; con e1’= (h2 o h3) Luego, FC(h6 y h7, e1’) = min{FC(h6, e1’), FC(h7, e1’)} = min{0’24, 0’9} = 0’24 FC(h1, e1’) = FC(h1, h6 y h7) ⋅ max{0, FC(h6 y h7, e1’)} = 0’7 ⋅ 0’24 = 0’168 Ahora habrá que considerar la otra regla que formaba parte del conjunto conflicto inicial: R3. Se tiene: FC(h4, e2’) = 0’2, FC(h5, e2’) = 0’8 FC(h4 o h5, e2’) = max{0’2, 0’8} = 0’8 FC(h1, e2’) = FC(h1, h4 o h5) ⋅ max{0, FC(h4 o h5, e2’)} = 0’1 ⋅ 0’8 = 0’08 Combinando las dos reglas que producen evidencia sobre h1, se obtiene finalmente: FC(h1, e1’ comb e2’) = FC(h1, e1’) + FC(h1, e2’)⋅(1 − FC(h1, e1’)) = 0’168 + 0’08 ⋅ 0’832 = 0’234 !77 Combinación de certidumbre Una característica fundamental de Mycin (de las reglas Mycin) es que pueden llegarse a los mismos hechos desde diferente reglas o inferencias (reglas) y esto afectará a su certeza. De tal forma que es preciso combinar los diferentes factores de certeza obtenidos. Así, tenemos que decirle a Clips que admita hechos duplicados: (set-fact-duplication true) La regla que combina los hechos duplicados y genera un nuevo hecho con el nuevo factor combinado, anulando los hechos previos. (sólo para FCs positivos o nulos). (defrule combina-oav-fc-positivas (declare (auto-focus true)) ;garantiza que no se va a disparar otra regla antes ?hecho1 <- (oav-fc (objeto $?obj) (atributo $?atri) (valor $?val) (FC $?fc1&: (>= ?fc1 0))) ?hecho2 <- (oav-fc (objeto $?obj) ;son hechos iguales (atributo $?atri) (valor $?val) (FC $?fc2&: (>= ?fc2 0))) (test (neq hecho1 hecho2)) ; pero no son el mismo => (retract ?hecho1) (bind ?fc3 (- (+?fc1 ?fc2) (* ?fc1 ?fc2))) (modify ?hecho2 (FC ?fc3))) !78 Transmisión de la certidumbre Las reglas de la base de conocimientos tienen que tener en cuenta un mecanismo de propagación de la certeza de la premisa sobre la certeza de la conclusión. En este ejemplo, solamente se afirmará el hecho conclusión cuando existan unos determinados hechos y con factores superiores a 0.2: (defrule combina-oav-FC-positivas (oav-fc (objeto microorganismo) (atributo coloracion) (valor gramnegativo) (fc ?fc1)) (oav-fc (objeto microorganismo) (atributo morfologia) (valor bacilo) (fc ?fc2)) (oav-fc (objeto paciente) (atributo es-un) (valor huesped-afectado) (fc ?fc3)) (test (> (min ?fc1 ?fc2 ?fc3) 0.2)) => (bind ?fc4 (* (min ?fc1 ?fc2 ?fc3) 0.6)) (assert (oav-fc (objeto microorganismo) (atributo identidad) (valor seudomonas) !79 (fc ?fc4)))) Orientación a Objetos • Objeto: Colección de información (los datos) que representa una entidad del mundo real y la forma de manipularla (el código asociado). Los objetos vienen descritos por: • Propiedades: Especificadas en términos de los atributos (slots) de la clase del objeto. • Conducta: Especificada en términos de código procedural (gestores de mensajes) asociado a la clase del objeto. •Los objetos se manipulan mediante el paso (envío) de mensajes. !80 Principios de la OOP • Abstracción Representación intuitiva de mayor nivel para un concepto complejo. Definición de nuevas clases para describir las propiedades comunes y el comportamiento de un grupo de objetos. •Encapsulación: Mecanismo que permite la ocultación de los detalles de implementación de un objeto mediante el uso de un interfaz externo bien definido. •Herencia: Proceso por el cual una clase puede ser definida en términos de otra(s) clase(s). •Polimorfismo: Capacidad de diferentes objetos para responder al mismo mensaje de una forma especializada. •Ligadura dinámica (dynamic binding): Capacidad para seleccionar en tiempo de ejecución el gestor de mensajes que corresponde a un mensaje concreto. !81 Definición de clases Construcción: (defclass <nombre> [<comentario>] (is-a <nombre-de-superclase>+) ;;; indica un orden de herencia [(role concrete | abstract)];;; puede instanciarse o no [(pattern-match reactive | non-reactive)];;; admite machting en una regla o no <slot>* ;;; definición de los atributos de la clase <documentación-handler>* ) Herencia múltiple COOL examina cada nueva clase utilizando la lista de precedencia de clases (de superclases) para establecer un orden lineal y le hace heredar slots y gestores (conducta) de cada una de las clases de esta lista en orden. Tiene prioridad las primeras clases de la lista (las más específicas) para heredar si hay conflicto (tienen el mismo nombre). (describe-class <nombre-de-clase>) En la cláusula is-a ya se establece una precedencia !82 Definición de slots (slot <nombre> <facet>*) (single-slot <nombre> <facet>*) (multislot <nombre> <facet>*) facets: son las propiedades de los atributos, las cuales son ciertas para todos los objetos que comparten dichos slots. (default ?DERIVE | ?NONE | <expresión>*) ;;; se evalúa al crear la clase (default-dynamic <expresión>*) ;;; se evalúa al instanciar (storage local | shared) ;;; el valor se almacena en la instancia o en la clase (access read-write | read-only | initialize-only) ;;; tipo de acceso permitido (propagation inherit | no-inherit) ;;; heredable o no heredable (visibility private | public) ;;; solo permite el acceso a los gestores propios (no heredados) (source exclusive | composite) ;;; hereda la facet de la clase más espcífica o de las anteriores (pattern-match reactive | non-reactive) ;;; cambios activan reglas o no (create-accessor ?NONE | read | write | read-write) ;;; crea automáticamente los gestores restricciones (type ...) (range ..) (cadinality ..) !83 pattern-matching con objetos Las modificaciones en atributos no reactivos o en instancias de clases no reactivas no tendrán efecto alguno en las reglas. (object <atributo-de-restricción>) ;;; donde <atributo-de-restricción> ::= (is-a <restricción>) | (name <restricción>) | ;;; clase a la que pertenece ;;; nombre de instancia entre [] (<nombre-atributo> <restricción>*) ;;; igual que con templates Ejemplo: "Apaga la caldera si la habitación está vacía" (defrule UNIDAD-CONTROL::UC7 (object (is-a Termostato) (temperatura ?t) (temperatura-seleccionada ?ts & :(>= ?t (- ?ts 3))) (caldera ?c) (modo calor) (habitación ?h)) ?inst <- (object (is-a Caldera) (name ?c) (estado encendida)) (object (is-a Habitacion) (name ?h) (ocupación vacía)) => (send ?inst Apagar) ) !84 Gestores de mensajes • Los objetos se manipulan mediante el envío de mensajes utilizando la función send. • La implementación de un mensaje consta de una serie de fragmentos de código procedural llamados gestores de mensajes (message-handlers). El valor devuelto por un gestor de mensajes es el resultado de la evaluación de la última acción. • La construcción defmessage-handler se utiliza para especificar la conducta de los objetos de una clase en respuesta a un mensaje particular. • Dentro de una clase, los gestores para un mensaje particular pueden ser de diferentes tipos diferentes: Primary (el proceso principal), Before, After. (defmessage-handler <nombre-clase> <nombre-mensaje> [<tipo-handler>] ;;; que identifican al mensaje [<comentario>] (<parámetro>* [<parámetro-comodín>]) <acción>*) (defmessage-handler rectángulo calcular-área () (* ?self:base ?self:altura)) ;;; Devuelve el area (base por altura). (defmessage-handler rectangulo imprimir-area () (printout t (send ?self calcular-area) crlf)) !85 Demonios y mensajes predefinidos • Demonios: Son fragmentos de código que se ejecutan implícitamente cuando se realiza alguna acción básica sobre una instancia como son la inicialización, borrado y la lectura y escritura de atributos, que han sido implementados como gestores primarios asociados a la clase de la instancia. • Gestores de mensajes predefinidos: init: inicializa una instancia con sus valores por defecto después de crearla. makeinstance) e inicializar instancias (initialize-instance) envían automáticamente el mensaje init. delete: devuelve TRUE si logra borrar con éxito la instancia; devuelve FALSE en caso contrario. print: visualiza en pantalla los atributos y sus valores de una instancia dada. ... Cuando un objeto recibe un mensaje mediante la función send, CLIPS examina la lista de precedencia de clases para determinar el conjunto de gestores de mensajes aplicables al mensaje. Un gestor de mensajes es aplicable a un mensaje, si su nombre coincide con el mensaje y el gestor está ligado (asociado) a alguna clase de la lista de precedencia a la cual pertenezca la instancia que recibe el mensaje !86 Manipulación de instancias •Los objetos se manipulan mediante el envío de mensajes de unos a otros. (send <expresión-de-objeto> <nombre-de-mensaje> <expresión>*) La función send devuelve el valor del último gestor (primary o around) ejecutado. (make-instance [<nombre-instancia>] of <nombre-clase> (<nombre-slot> <expresión>)*) (definstances <nombre-colección-instancias> [active] [<comentario>] (<definición-de-instancia>)*) get-<nombre-atributo> put-<nombre-atributo> delete !87 Consultas sobre instancias any-instancep Determina si uno o más conjuntos de instancias satisfacen una consulta. (any-instacep ((?hombre HOMBRE)) (> ?hombre:edad 30)) find-instance Devuelve el primer conjunto de instancias que satisfaga una consulta. (find-instance ((?h HOMBRE) (?m MUJER)) (= ?h:edad ?m:edad)) find-all-instances Agrupa y devuelve todos los conjuntos de instancias que satisfacen una consulta. (find-all-instances ((?h HOMBRE) (?m MUJER)) (= ?h:edad ?m:edad)) do-for-instance Realiza una acción sobre el primer conjunto de instancias que satisfaga una consulta. (do-for-instance ((?p1 PERSONA) (?p2 PERSONA) (?p3 PERSONA)) (and (= ?p1:edad ?p2:edad ?p3:edad) (neq ?p1 ?p2) (neq ?p1 ?p3) (neq ?p2 ?p3)) (printout t ?p1 " " ?p2 " " ?p3 crlf)) do-for-all-instances Realiza una acción con cada conjunto de instancias que satisface una consulta según se van encontrando. (do-for-instance ((?p1 PERSONA) (?p2 PERSONA) (?p3 PERSONA)) (and (= ?p1:edad ?p2:edad ?p3:edad) (neq ?p1 ?p2) (neq ?p1 ?p3) (neq ?p2 ?p3)) (printout t ?p1 " " ?p2 " " ?p3 crlf)) (Ejercicios 1, 8 y 11 de COOL) !88 Encadenamiento hacia atrás en Clips Es un ejercicio, más que algo práctico. Para inferir hacia atrás mejor utilizar otro tipo de lenguaje y de motor de inferencia, por ejemplo Prolog (http://www.swi-prolog.org/). Hay que definir un objetivo: (deftemplate objetivo (slot propiedad)) (deftemplate propiedad-valor (slot propiedad) (slot valor)) (deffacts objetivo-inicial (objetivo (propiedad propiedad-objetivo-inicial)) (deftemplate rule (multislot if) (multislot then)) if: <atributo-1> es <valor-1> y ... <atributo-n> es <valor-n> !89 Procedimientos (seudocódigo) Procedimiento Obtener-objetivo(objetivo) Si valor(objetivo)<> nil entonces retornar(valor(objetivo)); ; si no se conoce habra que buscar en la BC las reglas con el objetivo en la RHS Para cada regla en Base-Conocimientos / contiene-rhs(propiedad, regla) hacer Si Regla-con-exito(regla)=TRUE entonces ;se cumple la LHS valor(objetivo):= valor-rhs(regla); retornar(valor(objetivo)) Fin Fin valor(objetivo):= pedir-valor-usuario; ; si no existe esta regla, se pide al usuario retornar(valor(objetivo); Fin ;el siguiente procedimiento situa nuevos objetivos en la pila Procedimiento Regla-con-exito(regla) Para cada condición en LHS(regla) hacer Si Obtener-objetivo(propiedad(condicion)) <> valor(condicion) entonces retornar(FALSE); ;es decir, no se cumple la condicion Fin retornar(TRUE); Fin !90 Reglas que implementan los procedimientos ;;; regla que busca las rules cuya conclusión (then) incluya la asignación de un valor a ;;; diagnóstico y que afirme su antecedente (if) como nuevo objetivo, siempre y cuando no ;;; tenga ya un valor previo o ya sea un objetivo. (defrule evaluar-regla (objetivo (propiedad ?objetivo)) (rule (if ?propiedad $?) (then ?objetivo $?)) ; regla con el objetivo en el RHS (not (propiedad-valor (propiedad ?propiedad))) ;no existe valor para esa propiedad (not (objetivo (propiedad ?propiedad))) ; no se ha planteado ya como objetivo => (assert (objetivo (propiedad ?propiedad))) ) ;;; Y otra que pregunte al usuario por el valor del antecedente cuando no haya rules que lo ;;; incluyan en su consecuente. (defrule pedir-valor-propiedad ?hecho-objetivo <- (objetivo (propiedad ?objetivo)) (not (propiedad-valor (propiedad ?objetivo))) ; no existe valor para el objetivo (not (rule (then ?objetivo $?))) ; no existe regla con el objetivo en la RHS => (retract ?hecho-objetivo) (printout t "Introduzca el valor de " ?objetivo ": ") (assert (propiedad-valor (propiedad ?objetivo) (valor (read)))) ) !91 Implementando los procedimientos ;;; regla que elimina como objetivo aquél que ya se ha logrado, lo cual debe tener prioridad sobre ;;; la búsqueda de objetivos (las anteriores reglas): (defrule retractar-objetivo-logrado (declare (salience 10)) ?hecho-objetivo <- (objetivo (propiedad ?objetivo)) (propiedad-valor (propiedad ?objetivo)) => (retract ?hecho-objetivo) ) ;;; También tiene que tener prevalencia la afirmación del consecuente de una rule cuando su ;;; antecedente, como anterior objetivo, se haya logrado. Lleva asociada la eliminación de esa rule. (defrule afirmar-consecuente (declare (salience 10)) (objetivo (propiedad ?objetivo)) (propiedad-valor (propiedad ?propiedad) (valor ?valor)) ?rule <- (rule (if ?propiedad es ?valor) (then ?objetivo es ?valor-objetivo)) => (retract ?rule) (assert (propiedad-valor (propiedad ?objetivo) (valor ?valor-objetivo))) ) !92 Implementando los procedimientos ;;; Cuando se cumple la primera premisa del antecedente de una rule, esta misma premisa se ::: elimina de la rule, para no volverla a tener en cuenta: (defrule eliminar-premisa-cumplida (declare (salience 10)) (objetivo (propiedad ?objetivo)) (propiedad-valor (propiedad ?propiedad) (valor ?valor)) ?rule <- (rule (if ?propiedad es ?valor y $?resto-if) (then ?objetivo es ?valor-objetivo))) => (modify ?rule (if $?resto-if)) ) ;;; Pero si no se cumple la premisa, y por tanto, todo el antecedente, ;;; toda la rule debe ser eliminada: (defrule retractar-rule-fallida (declare (salience 10)) (objetivo (propiedad ?objetivo)) (propiedad-valor (propiedad ?propiedad) (valor ?valor)) ?rule <- (rule (if ?propiedad es ~?valor) (then ?objetivo es ?valor-objetivo))) => (retract ?rule)) !93 Con valores posibles aceptables ;;; Si deseamos que en la pregunta al usuario se especifiquen los posibles valores aceptables, ;;; una forma muy sencilla de resolverlo sería modificar la regla pedir-valor-propiedad ;;; para que quede: (defrule pedir-valor-propiedad ?hecho-objetivo <- (objetivo (propiedad ?objetivo)) (not (propiedad-valor (propiedad ?objetivo))) (not (rule (then ?objetivo $?))) (valores-posibles (propiedad ?objetivo) (valor-1 ?valor-1) (valor-2 ?valor-2)) => (retract ?hecho-objetivo) (printout t "Introduzca el valor de " ?objetivo " (" ?valor-1 "/" ?valor-2 "): ") (assert (propiedad-valor (propiedad ?objetivo) (valor (read)))) ) ;;; Para lo que es preciso definir un nuevo template: (deftemplate valores-posibles (slot propiedad) (slot valor-1) (slot valor-2)) ;;; Y los siguientes hechos complementarios: (deffacts pruebas (valores-posibles (propiedad rumpell-leede) (valor-1 positivo) (valor-2 negativo)) (valores-posibles (propiedad recuento-plaquetas) (valor-1 normal) (valor-2 bajo)) (valores-posibles (propiedad reduccion-megacariocitos) (valor-1 cierto) (valor-2 falso)) (valores-posibles (propiedad dimension-bazo) (valor-1 normal) (valor-2 anormal))) !94 Un ejemplo “test de Rumpell Leede positivo” Cierto Falso “Recuento de plaquetas bajo” ”VASCULITIS” Cierto “No hay reducción o ausencia de megacariocito” Cierto Falso “APLASIA DE MÉDULA ÓSEA ” “Tamaño normal del bazo” Cierto “SECUESTRO LEUCOCITARIO” Falso “CAUSAS INMUNOLOGICAS” deffacts reglas-diagnostico (rule (if rumpell-leede es positivo) (then diagnostico es vasculitis)) (rule (if rumpell-leede es negativo y recuento-plaquetas es normal) (then diagnostico es deficiencia-factores-coagulacion)) (rule (if rumpell-leede es negativo y recuento-plaquetas es bajo y reduccion-megacariocitos es falso) (then diagnostico es aplasia-medula-osea)) (rule (if rumpell-leede es negativo y Falso recuento-plaquetas es bajo y reduccion-megacariocitos es cierto y “Deficiencia de factores de dimension-bazo es normal) coagulación” (then diagnostico es secuestro-leucocitario)) (rule (if rumpell-leede es negativo y recuento-plaquetas es bajo y reduccion-megacariocitos es cierto y dimension-bazo es anormal) (then diagnostico es causas-inmunologicas)) ) (deffacts hechos (objetivo (propiedad diagnostico)) (propiedad-valor (propiedad rumpell-leede)) (propiedad-valor (propiedad recuento-plaquetas)) (propiedad-valor (propiedad reduccion-megacariocitos)) (propiedad-valor (propiedad dimension-bazo)) ) !95 Otro ejemplo Regla 1 INFECCION DE MENINGITIS IF El medico sabe que paciente tiene meningitis. OR Se sospecha de meningitis THEN Infección de meningitis. AND DESPLEGAR Infección ELSE DESPLEGAR No se encontró infección. Regla 2 SE SOSPECHA DE MENINGITIS POR EL TEST O SINTOMAS IF Se sospecha de meningitis por el resultado del test. OR Se sospecha de meningitis por los síntomas del paciente. THEN Se sospecha de meningitis. Regla 3 CULTIVOS PARECIDOS A LA MENINGITIS IF Donde el test esta corriendo. AND Cultivos donde se observa. AND Cultivos parecidas a la meningitis. THEN Se sospecha de meningitis por el resultado del test. Regla 4 CULTIVOS PARECIDADAS A LA MENINGITIS IF La apariencia de la cultivo es coccus. AND Las manchas de la cultivo son grampos. THEN Cultivos parecidas a la meningitis. Regla 5 SE SOSPECHA DE MENINGITIS POR LOS SÍNTOMAS IF El paciente esta sufriendo persistentes dolores de cabeza. AND El paciente esta sufriendo de vértigo. AND El paciente esta letárgico. THEN Se sospecha de meningitis por los síntomas. !96 Sitios interesantes relacionados con SBC y Clips Sitio de Clips: http://clipsrules.sourceforge.net/ Sitio de FuzzyClips: http://awesom.eu/~cygal/archives/2010/04/22/fuzzyclips_downloads/index.html Sitio de Jess: http://www.jessrules.com/ Drools - The Business Logic integration Platform. http://www.jboss.org/drools Sitio de Rusell y Norvig: Artificial Intelligence: A Modern Approach. http://aima.cs.berkeley.edu/ Un sitio con muchas cosas y ejemplos: http://www.csie.ntu.edu.tw/~sylee/courses/es/index.html#outline Departamento de Inteligencia Artificial, UNED: http://www.ia.uned.es/ Grupo SIMDA, UNED: http://simda.uned.es/ !97 Referencias • CLIPS User’s Guide: ofrece una introducción a CLIPS. Se compone de 2 vol úmenes: Volume I: Rules, introducción a la programación basada en reglas usando CLIPS. Volume II: Objects, introducción a la programación orientada a objetos usando COOL • CLIPS Reference Manual: consta de 3 volúmenes, de los cuales se han utilizado el I y II. Volume I: The Basic Programming Guide, descripción de la sintaxis de CLIPS y ejemplos de uso Volume II: Advanced Programming Guide, describe en detalle las características más sofisticadas de CLIPS para programación de aplicaciones avanzadas. • Expert Systems: Principles and Programming. Joseph Giarratano & Gary Riley. 2nd Edition. PWS Publishing Company, 1994 • Jess in Action: Java Rule-Based Systems (In Action series). Ernest Friedman-Hil.Manning Publications (July 2003) • Desarrollo de SBCs en Clips y FuzzyClips. Javier Carbó Rubiera, Jose M. Molina López, Rafael Martínez Tomás. Editorial Sanz y Torres. 2005 • Sistemas Expertos y Redes Probabilistas. E. Castillo, J.M. Gutiérrez, and A.S. Hadi. http://personales.unican.es/gutierjm/BookCGH.html. 1998. • Apuntes, bastante completos, de Aitor San Juan Sánchez (UCM): http://www.fdi.ucm.es/profesor/belend/ ISBC/clips_archivos/clips.pdf !98