Sei sulla pagina 1di 62

Se plantea el problema clsico de rutas entre ciudades: Un agente desea desplazarse por carretera desde la ciudad en la que se encuentra

actualmente a una ciudad destino. La accin bsica que puede emprender es ir(x,y), que lo lleva de la ciudad X a la ciudad Y, siempre y cuando exista una ruta directa entre ambas. Este ltimo hecho se expresa mediante hechos (rutaDirecta x y). Se supone que existen los siguientes hechos en la memoria de trabajo para representar estas rutas: (deffacts mapa_ciudades (rutaDirecta Zeind Oradea 71) (rutaDirecta Oradea Sibiu 151) (rutaDirecta Zerind Arad 75) (rutaDirecta Arad Sibiu 140) (rutaDirecta Arad Timisoara 118) (rutaDirecta Timisoara Lugoj 111) (rutaDirecta Lugoj Mehadia 70) (rutaDirecta Mehadia Dobreta 75) (rutaDirecta Dobreta Caiova 120) (rutaDirecta Caiova Rimnicu 146) (rutaDirecta Caiova Pitesti 138) (rutaDirecta Rimnicu Sibiu 80) (rutaDirecta Rimnicu Pitesti 97) (rutaDirecta Pitesti Bucarest 101) (rutaDirecta Sibiu Fagaras 99) (rutaDirecta Fagaras Bucarest 211) (rutaDirecta Bucarest Giurgiu 90) (rutaDirecta Bucarest Urziceni 85) (rutaDirecta Urziceni Hirsova 98) (rutaDirecta Hirsova Eforie 86) (rutaDirecta Urziceni Vaslui 142) (rutaDirecta Vaslui Iasi 92) (rutaDirecta Iasi Neamt 87) ) Se pide que responda a las siguientes cuestiones: a) Elaborar una Base de Conocimiento de reglas para este problema que sea capaz de responder a la consulta (ir X Y) al menos con una ruta factible entre las ciudades X e Y. La ruta contendr todas las rutas directas exploradas para llegar de X a Y. No se solicita calcular la ruta ptima, slo una ruta factible en la que ninguna ciudad en la ruta est repetida i) Debe tenerse en cuenta que, aunque en la base de hechos inicial nicamente se describen las rutas directas en una direccin, estas rutas son simtricas, ej. (rutaDirecta Oradea Sibiu 151) -> (rutaDirecta Sibiu Oradea 151). ii) Dentro de la solucin al problema deber incluirse, al menos, todas las ciudades recorridas (en su orden correcto desde el origen al destino). La solucin no tiene que repetir una ciudad (utilizar la funcin booleana que comprueba si un elemento es miembro de una lista (member$ ?elemento $?lista-elementos)). Se pide tambin justificar brevemente el diseo del hecho o de los hechos de la solucin al problema. iii) Una vez encontrada la solucin, se pide que esta se imprima en la salida estndar, utilizando (printout t <cadena> crlf) b) Supngase ahora que el vehculo utilizado tiene un depsito de combustible y consume 5 litros cada 100 kilmetros. Se pide ampliar la representacin de manera que estos nuevos factores queden reflejados y las consultas anteriores sigan funcionando y produciendo planes factibles. i) En el inicio de cada ruta, se supone que el depsito est lleno de combustible. ii) La capacidad del depsito de combustible estar definida por un hecho que deber ser especificado en la base de hechos. iii) Un plan se considera factible si el vehculo tiene combustible suficiente para llegar al destino. iv) nicamente se pide especificar las reglas y hechos que cambian respecto al apartado anterior. Solucin: (defglobal ?*preferencia-maxima* = 10000) ;------------------------------------------;- Inserta todas las rutas directas con el ;- origen y destino invertidos ;-------------------------------------------

(defrule simetrica (declare (salience ?*preferencia-maxima*)) (rutaDirecta ?orig ?dest $?resto) => (assert (rutaDirecta ?dest ?orig $?resto)) ) ;------------------------------------------;- Detecta la consulta "ir a" y comienza a ;- construir la ruta ;------------------------------------------(defrule ir_desde_origen (ir ?origen ?destino) (rutaDirecta ?origen ?dest ?) => (assert (ruta ?origen ?dest)) ) ;------------------------------------------;- Expande todas las rutas con los destinos ;- directos accesibles ;------------------------------------------(defrule expande_ruta_sin_duplicar (ruta $?previo ?final) (rutaDirecta ?final ?dest ?) (test (not (member$ ?dest $?previo))) => (assert (ruta $?previo ?final ?dest)) ) ;------------------------------------------;- Cuando existe un ruta en el que la ;- ltima ciudad sea el destino de la ;- consulta, se crea un nuevo hecho solucin ;- para marcar esta ruta como solucin ;------------------------------------------(defrule solucion ?nruta <- (ruta $?lista ?destino) (ir ?origen ?destino) => (retract ?nruta) (assert (solucion $?lista ?destino)) ) ;------------------------------------------;- Imprime la ruta con la solucin ;------------------------------------------(defrule imprime_solucion (solucion $?lista) => (printout t "-> Solucion: " $?lista crlf) ) b) Slo se muestran las reglas que cambian: ;------------------------------------------;- Hechos iniciales para el depsito de ;- combustible ;------------------------------------------(deffacts combustible (capacidad_deposito 35) (consumo 0.05) ) ;-------------------------------------------

;- Detecta la consulta "ir" y cominenza a ;- construir la ruta ;- Descuenta el consumo del trayecto al ;- depsito, que es el ltimo valor en la ;- ruta. ;------------------------------------------(defrule ir_desde_origen (ir ?origen ?destino) (rutaDirecta ?origen ?dest ?dist) (capacidad_deposito ?cap) (consumo ?cons) (test (>= ?cap (* ?dist ?cons))) => (assert (ruta ?origen ?dest (- ?cap (* ?dist ?cons)))) ) ;------------------------------------------;- Expande todas las rutas con los destinos ;- directos accesibles. Recalcula ;- el consumo de combustible ;------------------------------------------(defrule expande_ruta_sin_duplicar (ruta $?previo ?final ?deposito) (rutaDirecta ?final ?dest ?dist) (consumo ?cons) (test (not (member$ ?dest $?previo))) (test (>= ?deposito (* ?dist ?cons))) => (assert (ruta $?previo ?final ?dest (- ?deposito (* ?dist ?cons)))) ) ;------------------------------------------;- Cuando existe un ruta en el que la ;- ltima ciudad sea el destino de la ;- consulta, se crea un nuevo hecho solucin ;- para marcar esta ruta como solucin ;------------------------------------------(defrule solucion ?nruta <- (ruta $?lista ?destino ?deposito) (ir ?origen ?destino) => (retract ?nruta) (assert (solucion $?lista ?destino ?deposito)) ) ;------------------------------------------;- Imprime la ruta con la solucin ;------------------------------------------(defrule imprime_solucion (solucion $?lista ?deposito) => (printout t "-> Solucion: " $?lista crlf) (printout t "-> Deposito: " ?deposito crlf) )

- A continuacin presentamos un ejemplo de tarea propia de la audiologa clnica. El perfil de un paciente se caracteriza por un conjunto de hallazgos V1V8 que se obtiene a partir de observaciones de los pacientes (desde la observacin de la edad de paciente de 65 aos se obtiene el hallazgo V1:edad>60): hallzs. Descripcin V1 edad>60 V2 air = mild V3 history = noise V4 speech = poor V5 tympan = a V6 acoustic_ref_c = elevated V7 acoustic_ref_u = elevated V8 o_acoustic_ref_c = elevated Los diferentes diagnsticos posibles son los expresados en la siguiente tabla: Diags. SA1 SA2 SA3 SA4 SA5 SA6 SA7 SA8 SA9 SA10 SA11 Descripcin age-induced cochlear with otitis media age and noise-induced cochlear noise-induced cochlear age-induced cochlear normal ear ( norm) acoustic neuroma cochlear mixed otitis media possible menieres bells palsy

Los hallazgos sugieren diferentes posibles diagnsticos (V sugiere SA), como se observa en la siguiente tabla: hallzs V1 V2 V3 V4 V5 V6 V7 V8 Diags. SA1, SA2, SA4, SA9 SA6, SA7, SA9 SA2, SA3 SA7, SA8 SA5, SA7 SA8, SA10 SA4, SA9 SA7, SA8, SA11

Aqu se reduce pues el conjunto de diagnsticos posibles, pero solamente con esta tabla no se designa un nico diagnstico como solucin. Para conseguir un diagnstico ms preciso, en primer lugar, se suman todas las ocurrencias de cada SA en la tabla de equiparaciones (por ejemplo cochlear SA7 tiene 4 ocurrencias). A continuacin, cada SA como subcategora hereda adems los puntos de las categoras genricas a que pertenece, (por ejemplo, age-induced cochlear hereda de cochlear, age-induced cochlear with otitis media hereda de otitis media). Por ejemplo, si se da V1 entonces se sugiere SA1, SA2, SA4 y SA9. Como SA4 y SA9 refuerzan SA1, sta queda con 3 puntos. Mientras que SA2 queda con 2 puntos. As, la solucin puntuada en primer lugar sera age-induced cochlear with otitis media. Esta fase del diagnstico, por tanto, concluira con las hiptesis ms valoradas (o la ms valorada) como solucin. Se pide una implementacin en Clips para este diagnstico.

Solucin: ; Se puede hacer de una forma mas ortodoxa, sin variable global y sin modificacin de los hechos tabla-refuerzos-diagnosticos, por ejemplo, pero esta solucin es bastante sencilla. (defglobal ?*contador-diagnosticos* = 0) (deftemplate datos-paciente (slot id-paciente (type INTEGER)) (slot edad (type INTEGER)) ) (deftemplate datos-pruebas-paciente (slot id-paciente (type INTEGER)) (slot variable (type SYMBOL)) (slot valor (type STRING)) ) (deftemplate hallazgo (slot id-hallazgo (type SYMBOL)) (slot variable (type SYMBOL)) (slot operador (type STRING)) (slot valor (type STRING)) ) (deftemplate diagnostico (slot id-diagnostico (type SYMBOL)) (slot descripcion (type STRING)) ) (deftemplate refuerza (slot diagnostico-G (type SYMBOL)) (slot diagnostico-E (type SYMBOL)) (slot hecho (type SYMBOL) (allowed-values NO SI) (default NO)) ) (deftemplate hallazgo-paciente (slot id-paciente (type INTEGER)) (slot hallazgo (type SYMBOL)) ) (deftemplate hallazgo-diagnostico (slot id-hallazgo (type SYMBOL)) (slot diagnostico (type SYMBOL)) ) (deftemplate diagnostico-paciente (slot id-paciente (type INTEGER)) (slot diagnostico (type SYMBOL)) (slot contador (type INTEGER) (default 1)) ) (deftemplate lista-aux-diagnosticos (multislot diagnosticos (type SYMBOL)) ) ; afirmamos los hallazgos como hechos (deffacts tabla-hallazgos

(hallazgo (hallazgo (hallazgo (hallazgo (hallazgo (hallazgo (hallazgo (hallazgo )

(id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo

V1) V2) V3) V4) V5) V6) V7) V8)

(variable (variable (variable (variable (variable (variable (variable (variable

edad) (operador ">") (valor "65")) air) (operador "=") (valor "mild")) history) (operador "=") (valor "noise")) speech) (operador "=") (valor "poor")) tympan) (operador "=") (valor "a")) acoustic_ref_c) (operador "=") (valor "elevated")) acoustic_ref_u) (operador "=") (valor "elevated")) o_acoustic_ref_c) (operador "=") (valor "elevated"))

(deffacts tabla-diagnosticos (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (id-diagnostico (id-diagnostico (id-diagnostico (id-diagnostico (id-diagnostico (id-diagnostico (id-diagnostico (id-diagnostico (id-diagnostico (id-diagnostico (id-diagnostico SA1) (descripcion "age-induced cochlear with otitis media")) SA2) (descripcion "age and noise-induced cochlear")) SA3) (descripcion "noise-induced cochlear")) SA4) (descripcion "age-induced cochlear")) SA5) (descripcion "normal ear")) SA6) (descripcion "acoustic neuroma")) SA7) (descripcion "cochlear")) SA8) (descripcion "mixed")) SA9) (descripcion "otitis media") ) SA10) (descripcion "possible menieres") ) SA11) (descripcion "bells palsy"))

(deffacts tabla-hallazgos-diagnosticos (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (hallazgo-diagnostico (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo (id-hallazgo V1) V1) V1) V1) V2) V2) V2) V3) V3) V4) V4) V5) V5) V6) V6) V7) V7) V8) V8) V8) (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico (diagnostico SA1)) SA2)) SA4)) SA9)) SA6)) SA7)) SA9)) SA2)) SA3)) SA7)) SA8)) SA5)) SA7)) SA8)) SA10)) SA4)) SA9)) SA7)) SA8)) SA11))

(deffacts tabla-refuerzos-diagnosticos (refuerza (refuerza (refuerza (refuerza (refuerza (refuerza (diagnostico-G (diagnostico-G (diagnostico-G (diagnostico-G (diagnostico-G (diagnostico-G SA3) SA4) SA4) SA7) SA7) SA9) (diagnostico-E (diagnostico-E (diagnostico-E (diagnostico-E (diagnostico-E (diagnostico-E SA2)) SA1)) SA2)) SA3)) SA4)) SA1))

; los resultados de la exploracin podran introducirse por teclado, preguntando al usuario por ejemplo, o desde una ; base de datos. Asumimos que los tenemos disponibles como hechos segn la definicin de los anteriores templates (deffacts datos-del-paciente (datos-paciente (id-paciente 23) (edad 66)) ; por simplificacin, los datos del paciente entran en este hecho. ; Logicamente, al menos, habra que aadir una regla para introducirlos por teclado. (datos-pruebas-paciente (datos-pruebas-paciente (datos-pruebas-paciente (datos-pruebas-paciente (datos-pruebas-paciente (id-paciente (id-paciente (id-paciente (id-paciente (id-paciente 23) 23) 23) 23) 23) (variable (variable (variable (variable (variable air) (valor "other")) history) (valor "other")) peech) (valor "other")) tympan) (valor "other")) acoustic_ref_c) (valor "other"))

(datos-pruebas-paciente (id-paciente 23) (variable acoustic_ref_u) (valor "other")) (datos-pruebas-paciente (id-paciente 23) (variable o_acoustic_ref_c) (valor "other")) (contador-diagnosticos 0) ) (deffacts datos-inferidos (lista-aux-diagnosticos (diagnosticos)) ) ; reglas para abstraer los hallazgos desde los datos introducidos sobre los pacientes (defrule abstraer-hallazgos-V1 (declare (salience 1000)) (datos-paciente (id-paciente ?paciente) (edad ?edad&:(> ?edad 65))) => (assert (hallazgo-paciente (id-paciente ?paciente) (hallazgo V1))) ) (defrule abstraer-hallazgos-resto (declare (salience 1000)) (datos-paciente (id-paciente ?id-paciente)) (hallazgo (id-hallazgo ?hallazgo) (variable ?variable) (valor ?valor)) ?datos-pruebas-paciente <- (datos-pruebas-paciente (id-paciente ?paciente) (variable ? variable) (valor ?valor)) => (assert (hallazgo-paciente (id-paciente ?id-paciente) (hallazgo ?hallazgo))) ) ;reglas para emparejar los hallazgos con las soluciones (defrule emparejar-hallazgos-soluciones (declare (salience 900)) (datos-paciente (id-paciente ?id-paciente)) (hallazgo-paciente (id-paciente ?id-paciente) (hallazgo ?id-hallazgo)) (hallazgo-diagnostico (id-hallazgo ?id-hallazgo) (diagnostico ?diagnostico)) => (assert (diagnostico-paciente (id-paciente ?id-paciente) (diagnostico ?diagnostico))) (bind ?*contador-diagnosticos* (+ ?*contador-diagnosticos* 1)) ) ; regla para contabilizar los refuerzos de unos diagnosticos sobre otros (defrule refuerzos-soluciones (declare (salience 700)) (datos-paciente (id-paciente ?id-paciente))

(diagnostico-paciente (id-paciente ?id-paciente) (diagnostico ?diagnostico)) ?refuerza <- (refuerza (diagnostico-G ?diagnostico) (diagnostico-E ?diagnostico-E) (hecho NO)) ?reforzado <- (diagnostico-paciente (id-paciente ?id-paciente) (diagnostico ?diagnostico-E) (contador ?contador)) => (modify ?reforzado (contador (+ ?contador 1))) (bind ?*contador-diagnosticos* (+ ?*contador-diagnosticos* 1)) (modify ?refuerza (hecho SI)) ) ; regla imprimir los resultados como tabla de probabilidades de los diagnosticos, para esto se utiliza la variable global (defrule imprime-soluciones (declare (salience 400)) (datos-paciente (id-paciente ?id-paciente)) (diagnostico-paciente (id-paciente ?id-paciente) (diagnostico ?diagnostico) (contador ? contador)) => (printout t crlf "El paciente " ?id-paciente " sufre " ?diagnostico " con probabilidad: " (* 100 (/ ?contador ?*contador-diagnosticos*)) " %" crlf) )

- Se plantea un sistema experto para la ayuda a la composicin de programas musicales en emisoras de radio. El programa de radio tiene una duracin determinada que se pretende cubrir con canciones cuya duracin se acerque lo ms posible a la duracin prevista para el programa. Las canciones adems de una duracin tienen un identificador y una intensidad (de 1 a 5). Se pide llevar a cabo las siguientes acciones: a) Definir los templates y reglas necesarias para dado un programa musical de una duracin determinada completarlo con las canciones disponibles sin repetir ninguna (utilizar la funcin booleana que comprueba si un elemento es miembro de una lista (member$ ?elemento $?listaelementos)) y sin que entre una y la siguiente haya un salto de intensidad superior a 1. Escribir una regla primera-cancion que seleccione inicie el programa y otra regla programar que vaya aadiendo canciones hasta llegar al lmite de tiempo. b) Disee una regla equivalente a primera_cancin tal que seleccione como primera cancin del programa la cancin con ms intensidad de las disponibles en la base de hechos de canciones. c) Disee una regla ultima_cancin tal que site como ltima cancin en la programacin la cancin que ms se acerque a la duracin restante del programa y que no est incluida con anterioridad en la programacin. Esta regla deber ejecutarse tras la regla programar. Solucin: ; respuesta a) (deftemplate cancion (slot id (type INTEGER)) (slot intensidad (type INTEGER) (range 1 5)) (slot duracion (type INTEGER)) ) (deftemplate programa (slot nombre (type STRING)) (slot duracion (type INTEGER)) (multislot canciones (type INTEGER)) (slot duracion_completa (type INTEGER) (default 0)) ) (deffacts programa-y-canciones (programa (nombre "matinal") (duracion 60)) (cancion (id 1) (intensidad 3) (duracion 7)) (cancion (id 2) (intensidad 1) (duracion 3)) (cancion (id 3) (intensidad 2) (duracion 2)) (cancion (id 4) (intensidad 5) (duracion 6)) (cancion (id 5) (intensidad 2) (duracion 5)) (cancion (id 6) (intensidad 1) (duracion 4)) (cancion (id 7) (intensidad 3) (duracion 4)) (cancion (id 8) (intensidad 4) (duracion 2)) (cancion (id 9) (intensidad 2) (duracion 8)) (cancion (id 10) (intensidad 3) (duracion 4)) (cancion (id 11) (intensidad 1) (duracion 3)) (cancion (id 12) (intensidad 1) (duracion 3)) (cancion (id 13) (intensidad 5) (duracion 4)) (cancion (id 14) (intensidad 4) (duracion 5)) (cancion (id 15) (intensidad 4) (duracion 6)) (cancion (id 16) (intensidad 3) (duracion 2)) (cancion (id 17) (intensidad 1) (duracion 3)) (cancion (id 18) (intensidad 1) (duracion 4)) (cancion (id 19) (intensidad 5) (duracion 5)) (cancion (id 20) (intensidad 2) (duracion 3)) (cancion (id 21) (intensidad 2) (duracion 4))

(cancion (cancion (cancion (cancion (cancion (cancion

(id (id (id (id (id (id

22) 23) 24) 25) 26) 27)

(intensidad (intensidad (intensidad (intensidad (intensidad (intensidad

3) 4) 3) 5) 1) 1)

(duracion (duracion (duracion (duracion (duracion (duracion

5)) 6)) 7)) 2)) 4)) 5))

;(defrule primera_cancion ; ?p <- (programa (duracion ?dur_prog) (duracion_completa 0)) ; (cancion (id ?id_cancion) (duracion ?dur_cancion)) ; => ; (modify ?p (canciones ?id_cancion) (duracion_completa ?dur_cancion)) ;) (defrule programar ?p <- (programa (duracion ?dur_prog) (canciones $?canciones ?ultima_cancion) (duracion_completa ?dur_compl)) (cancion (id ?id_cancion) (intensidad ?int_cancion) (duracion ?dur_cancion)) (cancion (id ?ultima_cancion) (intensidad ?int_ultima_cancion)) (test (neq ?id_cancion ?ultima_cancion)) (test (not (member$ ?id_cancion $?canciones))) (test (<= (+ ?dur_compl ?dur_cancion) ?dur_prog)) (test (<= (abs (- ?int_cancion ?int_ultima_cancion)) 1 )) => (modify ?p (canciones $?canciones ?ultima_cancion ?id_cancion) (duracion_completa (+ ?dur_compl ?dur_cancion))) ) ; respuesta b) (defrule primera_cancion_max_intensidad ?p <- (programa (duracion ?dur_prog) (duracion_completa 0)) (cancion (id ?id_cancion) (intensidad ?int_cancion) (duracion ?dur_cancion)) (not (cancion (intensidad ?int&:(> ?int ?int_cancion)))) => (modify ?p (canciones ?id_cancion) (duracion_completa ?dur_cancion)) ) ; respuesta c) (defrule ultima_cancion ?p <- (programa (duracion ?dur_prog) (canciones $?canciones) (duracion_completa ? dur_compl&:(< ?dur_compl ?dur_prog))) (cancion (id ?id_cancion) (duracion ?dur_cancion)) (test (not (member$ ?id_cancion $?canciones))) (not (cancion (duracion ?dur&:(< ?dur (- ?dur_prog ?dur_compl))))) (not (cancion (id ?id&:(not (member$ ?id $?canciones))) (duracion ?dur&:(< ?dur ? dur_cancion)))) => (modify ?p (canciones $?canciones ?id_cancion) (duracion_completa (+ ?dur_compl ? dur_cancion))) )

- Realizar un sistema en Clips que permita introducir los datos de entrada y llegar a una clasificacin de peces de acuerdo al siguiente texto: Si un pez tiene la boca pequea y con dientes puntiagudos y vive en ros de muchas partes del mundo, entonces estamos hablando de un ejemplar del orden de los ciprinodontiformes. Si tenemos un individuo de esta orden que vive en los ros de Amrica del Sur y que en el caso de ser macho posee Gonopodio, entonces el pez es de la familia de los Poccilidos y la hembra es 3 cm. ms grande que el macho. Si es hembra tambin es, claro, de los Poccilidos y el macho ser 3 cms. ms pequeo. Si tenemos un individuo de la familia de los Poccilidos que tiene manchas a lo largo del cuerpo, estamos ante un pez de la raza Gambusia Affinis. Pero si tiene color gris y rayas verdes a lo largo del cuero entonces es de la raza Gambusia Punetata. Si es un pez de tamao medio, tiene dientes puntiagudos, vive en ros de todo el mundo y posee canales labernticos para respirar fuera del agua, entonces pertenece al orden de los anabtidos. Si un pez de esta orden es de color azul, tiene rayas royas y vive en ros de Asia, estamos ante un pez de la raza Luchadores de Sian. Pero si mide 25 cms. y no tiene rayas entonces es una perca trepadora. Si es un pez de boca pequea, vive en ros de todo el mundo y tiene la cola redondeada es que es un ejemplar de la orden de los Cclidos. Si un pez de esta orden vive en ros de frica y es de color rojo con manchas negras, es un pez joya.

- Un cajero automtico guarda 10 billetes de 10 euros, cinco billetes de 20, dos billetes de 50 y un billete de 100. Se trata de implementar en CLIPS un programa que pregunte al usuario la cantidad de dinero que quiere sacar y que le devuelva por pantalla una combinacin de billetes que suman la cantidad total pedida, de manera que el nmero total de billetes sea mnimo (o bien un mensaje diciendo que no es posible reunir la cantidad exacta). El problema puede ser planteado como un problema de espacio de estados, de manera que los nodos sean definidos por una plantilla con campos para almacenar el nmero utilizado de cada tipo de billete, el nmero total de billetes (coste) y la suma total de euros. En el nodo inicial hay 0 billetes de cada tipo. Existe un operador por cada tipo de billete, de manera que al aplicarlo a un nodo incrementa el nmero de billetes de ese tipo en uno. En el nodo final (o solucin) la suma total de euros es igual a la solicitada por el usuario. El problema debe ser resuelto mediante una bsqueda que minimice el nmero total de billetes. A continuacin aparecen varios ejemplos de sesin. NOTA: en los ejemplos, el usuario teclea la cantidad que est a continuacin de "Reintegro:". El resto es salida del programa. CLIPS> (reset) CLIPS> (run) Reintegro: 230 Billetes de 10 :1 Billetes de 20 :1 Billetes de 50 :2 Billetes de 100 :1 CLIPS> (reset) CLIPS> (run) Reintegro: 410 NO ES POSIBLE. CLIPS> (reset) CLIPS> (run) Reintegro: 125 Cantidad errnea, debe ser entero mltiplo de 10!! Reintegro: 270 Billetes de 10 : 1 Billetes de 20 : 3 Billetes de 50 : 2 Billetes de 100 : 1 - Definir las reglas Clips que lleven a cabo la peticin al usuario de la cantidad que desea como reintegro. En el caso de que el usuario introduzca una cantidad que no sea un entero mltiplo de 10, entonces el programa debe dar un mensaje de error, repitiendo la pregunta. En el caso de que el dato sea un mltiplo de 10, se aplicarn los operadores. INDICACION: Usar un hecho de la forma (total ...) para almacenar la peticin del usuario. - Definir una plantilla Clips para los nodos que incluya informacin sobre: numero de billetes de mil, de dos mil, de cinco mil, de diez mil, nmero total de billetes, suma total de euros y si el nodo est abierto o cerrado (es decir, ha sido, o est siendo, expandido). Incluir un "deffacts" para que inicialmente se cree el nodo inicial. - Definir una regla Clips por cada operador, otra regla que pasa el nodo de menor coste a cerrado y una ltima regla que se dispara solamente si ya no es posible encontrar solucin. NOTA: controlar mediante restricciones que no se creen nodos que tengan un nmero superior al permitido de billetes de cada tipo.

- Definir una nica regla Clips que elimine los nodos cuya suma total de euros sea superior a la cantidad que pide el usuario. - Definir una regla Clips que detecte nodos que son solucin. La regla debe mostrar en pantalla la solucin encontrada.

Solucin: ;;; Plantillas (deftemplate nodo (slot bill-100 (type INTEGER) (default 0)) (slot bill-50 (type INTEGER) (default 0)) (slot bill-20 (type INTEGER) (default 0)) (slot bill-10 (type INTEGER) (default 0)) (slot num-bill (type INTEGER) (default 0)) (slot importe-bill (type INTEGER) (default 0)) (slot estado (type SYMBOL) (allowed-values cerrado abierto) (default abierto)) ) (deftemplate cajero (slot bill-100 (type INTEGER) (default 1)) (slot bill-50 (type INTEGER) (default 2)) (slot bill-20 (type INTEGER) (default 5)) (slot bill-10 (type INTEGER) (default 10)) ) (deffacts iniciales (cajero) (inicio) ) ;;; Regla de peticin del importe del reintegro (se puede hacer con dos reglas en lugar de una) (defrule Pedir-importe ?estado <- (inicio) => (retract ?estado) (printout t crlf "Teclee el importe del reintegro (multiplo de 10) (0 para salir): " crlf) (bind ?in (read)) (if (= ?in 0) then (halt)) (if (= (mod ?in 10) 0) then (assert (reintegro ?in)) (assert (nodo)) else (assert (inicio)) ) ) ;;; Reglas de los operadores (defrule operador-100 ?nodo <- (nodo (bill-100 ?bill-100) (bill-50 ?bill-50) (bill-20 ?bill-20) (bill-10 ?bill-10) (num-bill ?num-bill) (importe-bill ?importe-bill) (estado cerrado)) (cajero (bill-100 ?caj-bill-100&:(> ?caj-bill-100 ?bill-100))) => (assert (nodo (bill-100 (+ ?bill-100 1)) (bill-50 ?bill-50) (bill-20 ?bill-20) (bill-10 ?bill-10) (num-bill (+ ?num-bill 1)) (importe-bill (+ ?importe-bill 100)))) )

(defrule operador-50 ?nodo <- (nodo (bill-100 ?bill-100) (bill-50 ?bill-50) (bill-20 ?bill-20) (bill-10 ?bill-10) (num-bill ?num-bill) (importe-bill ?importe-bill) (estado cerrado)) (cajero (bill-50 ?caj-bill-50&:(> ?caj-bill-50 ?bill-50))) => (assert (nodo (bill-100 ?bill-100) (bill-50 (+ ?bill-50 1)) (bill-20 ?bill-20) (bill-10 ?bill-10) (num-bill (+ ?num-bill 1)) (importe-bill (+ ?importe-bill 50)))) ) (defrule operador-20 ?nodo <- (nodo (bill-100 ?bill-100) (bill-50 ?bill-50) (bill-20 ?bill-20) (bill-10 ?bill-10) (num-bill ?num-bill) (importe-bill ?importe-bill) (estado cerrado)) (cajero (bill-20 ?caj-bill-20&:(> ?caj-bill-20 ?bill-20))) => (assert (nodo (bill-100 ?bill-100) (bill-50 ?bill-50) (bill-20 (+ ?bill-20 1)) (bill-10 ?bill-10) (num-bill (+ ?num-bill 1)) (importe-bill (+ ?importe-bill 20)))) ) (defrule operador-10 ?nodo <- (nodo (bill-100 ?bill-100) (bill-50 ?bill-50) (bill-20 ?bill-20) (bill-10 ?bill-10) (num-bill ?num-bill) (importe-bill ?importe-bill) (estado cerrado)) (cajero (bill-10 ?caj-bill-10&:(> ?caj-bill-10 ?bill-10))) => (assert (nodo (bill-100 ?bill-100) (bill-50 ?bill-50) (bill-20 ?bill-20) (bill-10 (+ ?bill-10 1)) (num-bill (+ ?num-bill 1)) (importe-bill (+ ?importe-bill 10)))) ) ;;; Regla de seleccin del nodo de menor coste. (defrule cierra-nodo-menor-costo (declare (salience -10)) ?nodo-1 <- (nodo (importe-bill ?importe-bill) (num-bill ?num-bill1) (estado abierto)) (not (exists (nodo (num-bill ?num-bill2&:(< ?num-bill2 ?num-bill1)) (estado abierto)))) => (modify ?nodo-1 (estado cerrado)) ) ;;; Regla que se dispara solamente si ya no es posible encontrar la solucin (defrule sin-solucion (declare (salience -100)) (not (solucion-encontrada)) => (printout t crlf "Actualmente no hay suficientes billetes para ese reintegro " crlf) ) ;;; Regla que se dispara solamente si ya no es posible encontrar la solucin (defrule elimina-nodos-excesivo-importe (declare (salience 100)) (reintegro ?reintegro) ?nodo <- (nodo (importe-bill ?importe-bill&: (> ?importe-bill ?reintegro))) => (retract ?nodo) ) ;;; Regla que identifica un nodo solucin

(defrule identifica-solucion (declare (salience 100)) (reintegro ?reintegro) (nodo (importe-bill ?importe-bill&: (= ?importe-bill ?reintegro)) (bill-100 ?bill-100) (bill-50 ?bill-50) (bill-20 ?bill-20) (bill-10 ?bill-10)) => (printout t crlf "Se reintegra con los siguientes billetes: " crlf) (printout t crlf ?bill-100 " Billetes de 100" crlf) (printout t crlf ?bill-50 " Billetes de 50" crlf) (printout t crlf ?bill-20 " Billetes de 20" crlf) (printout t crlf ?bill-10 " Billetes de 10" crlf) (assert (solucion-encontrada)) (halt) )

Se trata de simular el comportamiento de una colonia de clulas cuya vida o muerte a lo largo de generaciones viene determinada por una serie de reglas. Las clulas estn dispuestas en forma de grafo, es decir, existe una relacin de "vecindad" entre ellas. En cada generacin, cada clula puede estar viva o muerta (OJO, es posible que una clula este muerta en una generacin y viva en la siguiente). La regla que marcan la vida o muerte de las clulas es la siguiente: SI UNA CELULA EN LA GENERACION N TIENE AL MENOS DOS VECINAS VIVAS Y AL MENOS UNA MUERTA, ENTONCES VIVE EN LA GENERACION N+1. EN CASO CONTRARIO, MUERE. Supongamos el siguiente ejemplo, una colonia de nueve clulas de nombres a1, a2, a3, b1, b2, b3, c1, c2 y c3. La relacin de vecindad viene determinada por el siguiente grafo (por ejemplo, a1 y a3 son vecinas, pero a1 y a2 no lo son). Las clulas vivas son las marcadas con la x. Inicialmente (en la primera generacin), las que estn vivas son a1, a2, b1 y b2. x a1 x a2 \ / a3 / \ b3-----c3 / \ / \ x b1 x b2 c1 c2 Siguiendo la regla anteriormente expuesta, la situacin de la colonia en la generacin 2 es la siguiente: a1 a2 \ / x a3 / \ x b3----c3 /\ / \ b1 b2 c1 c2 Decimos que una colonia de clulas queda estancada en la generacin N si la generacin N+1 es igual (exactamente las mismas clulas vivas y muertas) a la generacin N. En nuestro ejemplo, en la cuarta generacin, la colonia queda estancada: todas las clulas estn muertas. Se trata de hacer un programa CLIPS que simule el comportamiento de una colonia de clulas cuya vida o muerte a lo largo de las generaciones se rige por la regla anterior y aplicarlo al ejemplo anterior para detectar en qu generacin se estanca y cmo queda la colonia una vez estancada. 1.1- Definir una plantilla Clips que represente el estado de cada clula en una generacin determinada, incluyendo informacin sobre el nombre de la clula, la generacin en la que se encuentra y el estado en el que se encuentra (viva o muerta). Escribir los hechos iniciales (deffacts), que describan el estado de la colonia de clulas en la generacin 1. Incluir adems dos hechos sin plantilla para almacenar la generacin actual y la anterior (inicialmente 1 y 0, respectivamente). La siguiente definicin inicial de hechos informa de la relacin de vecindad en el grafo. (deffacts vecinas (vecina a1 a3) ) 1.2. Definir reglas Clips que obtengan la generacin actual a partir de la generacin anterior. Una regla para obtener las clulas que quedan vivas y otra, u otras, para obtener las clulas que quedan muertas. Debe borrarse la informacin sobre generaciones anteriores.

1.3. Describir las reglas Clips para que en cada generacin se compruebe si se ha producido estancamiento y parar en tal caso devolviendo los mensajes pertinentes. Para esto ltimo seran precisas tres reglas, la primera de ellas debe actuar antes que las otras: 1) que escriba un mensaje que indique que la colonia se ha estancado y en qu generacin, 2) Otra regla para escribir las clulas que quedan vivas, 3) Otra para escribir las clulas que quedan muertas Ntese que existe estancamiento si no hay clulas tal que en la generacin anterior tengan distinto estado que en la actual. (deftemplate celula "estructura de celula" (slot nombre) (slot estado) (slot generacion) ) (deftemplate vecina (slot nombre1) (slot nombre2) ) (deftemplate generacion (slot numero) ) (deftemplate estancamiento (slot valor) ) (deffacts colonia (celula (nombre a1) (estado viva) (generacion 0)) (celula (nombre a2) (estado viva) (generacion 0)) (celula (nombre a3) (estado muerta) (generacion 0)) (celula (nombre b1) (estado viva) (generacion 0)) (celula (nombre b2) (estado viva) (generacion 0)) (celula (nombre b3) (estado muerta) (generacion 0)) (celula (nombre c1) (estado muerta) (generacion 0)) (celula (nombre c2) (estado muerta) (generacion 0)) (celula (nombre c3) (estado muerta) (generacion 0)) (vecina (nombre1 a1) (nombre2 a3)) (vecina (nombre1 a2) (nombre2 a3)) (vecina (nombre1 a3) (nombre2 b3)) (vecina (nombre1 a3) (nombre2 c3)) (vecina (nombre1 b3) (nombre2 b1)) (vecina (nombre1 b3) (nombre2 b2)) (vecina (nombre1 b3) (nombre2 c3)) (vecina (nombre1 c3) (nombre2 c1)) (vecina (nombre1 c3) (nombre2 c2)) (vecina (nombre1 a3) (nombre2 a1)) (vecina (nombre1 a3) (nombre2 a2)) (vecina (nombre1 b3) (nombre2 a3)) (vecina (nombre1 c3) (nombre2 a3)) (vecina (nombre1 b1) (nombre2 b3)) (vecina (nombre1 b2) (nombre2 b3)) (vecina (nombre1 c3) (nombre2 b3)) (vecina (nombre1 c1) (nombre2 c3)) (vecina (nombre1 c2) (nombre2 c3)) (estancamiento (valor true)) (generacion (numero 0)) )

(defrule obtener-celulas-vivas "Obtiene la generacion siguiente a partir de la anterior" (declare (salience 550)) ?celula1 <- (celula (nombre ?nombre1) (estado ?estado1) (generacion ?generacion1)) (celula (nombre ?nombre2&~?nombre1) (estado ?estado2) (generacion ?generacion2)) (celula (nombre ?nombre3&~?nombre2&~?nombre1) (estado ?estado3) (generacion ? generacion3)) (celula (nombre ?nombre4&~?nombre3&~?nombre2&~?nombre1) (estado ?estado4) (generacion ?generacion4)) (vecina (nombre1 ?nombre1) (nombre2 ?nombre2)) (vecina (nombre1 ?nombre1) (nombre2 ?nombre3)) (vecina (nombre1 ?nombre1) (nombre2 ?nombre4)) (vecina (nombre1 ?nombre1) (nombre2 ?nombre5)) (generacion (numero ?generacion-actual)) (test (and (eq ?generacion1 ?generacion-actual) (eq ?generacion2 ?generacion-actual) (eq ?generacion3 ?generacion-actual) (eq ?generacion4 ?generacion-actual))) (test (or (and (eq ?estado2 viva) (eq ?estado3 viva)) (and (eq ?estado2 viva) (eq ? estado4 viva)) (and (eq ?estado3 viva) (eq ?estado4 viva)))) ?estancamiento <- (estancamiento (valor ?valor)) => (bind ?siguiente-generacion (+ ?generacion1 1)) (modify ?celula1 (estado viva) (generacion ?siguiente-generacion)) (modify ?estancamiento (valor false)) ) (defrule obtener-celulas-muertas "todas las que queden deben cambiar a muertas" (declare (salience 500)) ?celula1 <- (celula (nombre ?nombre) (estado ?estado) (generacion ?generacion1)) (generacion (numero ?generacion-actual)) (test (eq ?generacion1 ?generacion-actual)) => (bind ?siguiente-generacion (+ ?generacion-actual 1)) (modify ?celula1 (estado muerta) (generacion ?siguiente-generacion)) ) (defrule cambiar-generacion (declare (salience 150)) ?generacion <- (generacion (numero ?numero)) ?estancamiento <- (estancamiento (valor false)) => (bind ?siguiente-generacion (+ ?numero 1)) (modify ?generacion (numero ?siguiente-generacion)) (modify ?estancamiento (valor true)) ) (defrule imprimir-celulas-vivas "Imprime al final las celulas vivas" (celula (nombre ?nombre) (estado viva) ) => (printout t "La celula " ?nombre " vive. " crlf) ) (defrule imprimir-celulas-muertas "Imprime al final las celulas muertas" (celula (nombre ?nombre) (estado muerta) ) => (printout t "La celula " ?nombre " ha muerto. " crlf) ) (defrule imprimir-estancamiento (declare (salience 10)) (estancamiento (valor true)) (generacion (numero ?numero))

=> (bind ?numero (+ ?numero 1)) (printout t "Se ha producido estancamiento y por lo tanto finalizamos en la generacin " ?numero crlf) )

Implementar en el lenguaje CLIPS el conjunto de los operadores del mundo de los bloques. La solucin debe, mediante reglas de inferencia, identificar la trayectoria de los estados alcanzados, partiendo de un estado inicial, y los operadores aplicados, que reflejen los movimientos efectuados por el robot hasta alcanzar el estado meta (u objetivo). Los operadores vlidos son: Operador Coger (x) Dejar (x) Montar (x en y) Desmontar (x, y) Precondicin/Resultado Precondicin: Sobre mesa (x), libre (x), mano robot vaca Resultado: Cogido (x) Precondicin: Cogido (x) Resultado: Sobre mesa (x), libre (x), mano robot vaca Precondicin: Cogido (x), Libre (y) Resultado: Sobre (y, x), mano robot vaca, libre (x) Precondicin: Mano robot vaca, sobre (y, x), libre (x) Resultado: Cogido (x), libre (y)

Solucin: (deftemplate apilado (slot encima (type SYMBOL)) (slot debajo (type SYMBOL)) ) (deftemplate objetivo (slot encima (type SYMBOL)) (slot debajo (type SYMBOL)) ) (deffacts bloques ; Estado de partida ; nada encima de B encima de A encima de mesa ; nada encima de C encima de D encima de mesa (apilado (apilado (apilado (apilado (apilado (apilado (encima (encima (encima (encima (encima (encima B) (debajo A)) nada) (debajo B)) C) (debajo D)) nada) (debajo C)) D) (debajo mesa)) A) (debajo mesa))

; Estado final u objetivo (objetivo (encima A) (debajo D)) ; Reglas

(defrule Objetivo-logrado (declare (salience 110)) ?obj <- (objetivo (encima ?a) (debajo ?b)) ?x <- (apilado (encima nada) (debajo ?a)) ?y <- (apilado (encima nada) (debajo ?b)) ?z <- (apilado (encima ?a) (debajo ?c)) => (modify ?z (debajo ?b)) (retract ?obj ?y) (printout t crlf "Objetivo conseguido" crlf) ) (defrule Objetivo-arriba-la-mesa ?obj <- (objetivo (encima ?a) (debajo ?b)) ?x <- (apilado (encima ?algo&:(neq ?algo nada)) (debajo ?a)) => (assert (objetivo (encima ?algo) (debajo mesa))) (printout t "Objetivo: encima " ?algo " debajo: mesa" crlf) ) (defrule Objetivo-abajo-a-la-mesa ?obj <- (objetivo (encima ?a) (debajo ?b)) ?x <- (apilado (encima ?algo&:(neq ?algo nada)) (debajo ?b)) => (assert (objetivo (encima ?algo) (debajo mesa))) (printout t "Objetivo: encima " ?algo " debajo: mesa" crlf) ) (defrule Objetivo-cumplido (declare (salience 100)) ?obj <- (objetivo (encima ?a) (debajo mesa)) (apilado (encima ?a) (debajo mesa)) => (retract ?obj) ) (defrule mover-a-la-mesa ?obj <- (objetivo (encima ?a) (debajo mesa)) (apilado (encima nada) (debajo ?a)) ?y <- (apilado (encima ?a) (debajo ?b)) => (retract ?obj) (modify ?y (debajo mesa)) (assert (apilado (encima nada) (debajo ?b))) (printout t "muevo " ?a " a la mesa" crlf) )

Dado un mapa que representa la situacin de distintas ciudades, se quiere construir un sistema en Clips que permita contestar preguntas sobre la posicin relativa de dos ciudades, con las siguientes caractersticas: a) Se introducirn exclusivamente hechos correspondientes a las relaciones estar al norte de y estar al oeste de y slo entre las ciudades ms prximas entre s. Por ejemplo, si suponemos 9 ciudades distribuidas en una cuadrcula: ABC DEF GHI slo se establecern como hechos: A est al norte de D, A est al oeste de B, etc. b) El sistema de representacin ser capaz de inferir todas las relaciones inversas de las dadas directamente, es decir, las relaciones estar al sur de y estar al este de. c) Se inferirn nuevas relaciones por transitividad. Por ejemplo, sabiendo que A est al norte de D y que D est al norte de G se inferir que A est al norte de G. d) Se inferirn las relaciones noroeste, noreste, suroeste y sureste a partir de los hechos iniciales. Por ejemplo, se podr inferir que C est al noreste de G. e) El hecho que se utilizar para consultar al sistema ser ( situacin <ciudad_1> <ciudad_2> ). Cuando este hecho se inserta en el sistema, el mismo debe responder mostrando por pantalla la situacin de la ciudad 1 con respecto a la ciudad 2. Solucin: Desde luego, la forma ms simple de hacer es: (deffacts ciudades (ubicada (ubicada (ubicada (ubicada (ubicada (ubicada (ubicada (ubicada (ubicada (ubicada (ubicada (ubicada A B D E G H A D B E C F al-oeste-de al-oeste-de al-oeste-de al-oeste-de al-oeste-de al-oeste-de al-norte-de al-norte-de al-norte-de al-norte-de al-norte-de al-norte-de B) C) E) F) H) I) D) G) E) H) F) I)

(situacion B F) ) ; Reglas para inferir relaciones inversas (defrule al-sur-de

(ubicada ?a al-norte-de ?b) => (assert (ubicada ?a al-sur-de ?a))

(defrule al-este-de (ubicada al-oeste-de ?a ?b) => (assert (ubicada ?b al-este-de ?a)) ) ; Reglas para inferir relaciones transitivas (defrule transitiva (ubicada ?a ?rel ?b) (ubicada ?b ?rel ?c) => (assert (ubicada ?a ?rel ?c)) ) ; Reglas para inferir relaciones combinadas (defrule noreste (ubicada ?a al-norte-de ?b) (ubicada ?b al-este-de ?c) => (assert (ubicada ?a al-noreste-de ?c)) ) (defrule noroeste (ubicada ?a al-norte-de ?b) (ubicada ?b al-oeste-de ?c) => (assert (ubicada ?a al-noroeste-de ?c)) ) (defrule sureste (ubicada ?a al-sur-de ?b) (ubicada ?b al-este-de ?c) => (assert (ubicada ?a al-sureste-de ?c)) ) (defrule suroeste (ubicada ?a al-sur-de ?b) (ubicada ?b al-oeste-de ?c) => (assert (ubicada ?a al-suroeste-de ?c))

;Respuesta de la pregunta (defrule relacion-entre-ciudades (declare (salience -10)) (situacion ?a ?b) (ubicada ?a ?rel ?b)

=> (printout t ?a " est " ?rel " " ?b crlf) )

Consideremos frmulas de la lgica proposicional construidas con las conectivas: negacin (-), disyuncin (|), conjuncin (&), implicacin (->) y equivalencia (<->). Por ejemplo: (p&q)->r Para la representacin en clips de este tipo de frmulas se propone el siguiente template. (deftemplate formula (slot id) (slot tipo) (multislot componentes) ) Id almacena un identificador asociado a la frmula. Tipo almacena la conectiva entre (siguiente campo) los identificadores de las frmulas componentes. Por ejemplo, la frmula anterior quedara en los siguientes hechos: (formula (id id-1) (tipo ->) (componentes id2 id3)) (formula (id id-2) (tipo &) (componentes id4 id5)) (formula (id id-3) (tipo var) (componentes)) (formula (id id-4) (tipo var) (componentes)) (formula (id id-5) (tipo var) (componentes)) a) Con qu hechos se representara la frmula ((-q)| (-r)) <> (-(q&r)) Toda frmula proposicional se puede transformar a forma normal negativa aplicando una serie de reglas de transformacin, de las cuales las siguientes son una parte: (-(-p)) se transforma en p (p->q) se transforma en (-p)|q (-(p&q)) se transforma en (-p)|(-q) (p<->q) se transforma en (p->q)&(q->p) b) Construir un conjunto de reglas Clips que sirvan para realizar estas transformaciones. Para ello ser necesario utilizar la funcin gensym que genera un identificador nico para asignrselo a una frmula. Por ejemplo, (assert (formula (id (genysim)))) No se permite la utilizacin de condicionales en el consecuente de las reglas. c) Cmo se podra imprimir mediante reglas Clips una frmula as representada conocido el identificador raz?

Solucin: Solucin: 1. (deffacts hechos (formula (formula (formula (formula (formula (formula (formula (formula (id (id (id (id (id (id (id (id q) (tipo "var") (componentes)) r) (tipo "var") (componentes)) id-1) (tipo "-") (componentes q)) id-2) (tipo "-") (componentes r)) id-3) (tipo "|") (componentes id-1 id-2)) id-4) (tipo "-") (componentes id-5)) id-5) (tipo "&") (componentes q r)) raiz) (tipo "<->") (componentes id-3 id-5))

(transformar) )

2. ; transformacion de la doble negacin (defrule doble-negacion (declare (salience 550)) (transformar) ?f1 <- (formula (id ?id-1) (tipo "-") (componentes ?id-2)) ?f2 <- (formula (id ?id-2) (tipo "-") (componentes ?id-3)) ?f3 <- (formula (id ?id-3) ) => (retract ?f1 ?f2) (modify ?f3 (id ?id-1)) ) ;transformacin de la implicacin (defrule implicacion (declare (salience 550)) (transformar) ?f1 <- (formula (id ?id-1) (tipo "->") (componentes ?id-2 ?id-3)) => (bind ?nuevo-id (gensym)) (modify ?f1 (tipo "|") (componentes ?nuevo-id ?id-3)) (assert (formula (id ?nuevo-id) (tipo "-") (componentes ?id-2))) ) ;transformacin negacin de la conjuncin (defrule negacion-conjuncion (declare (salience 550)) (transformar) ?f1 <- (formula (id ?id-1) (tipo "-") (componentes ?id-2)) ?f2 <- (formula (id ?id-2) (tipo "&") (componentes ?id-3 ?id-4)) => (bind ?id-2a (gensym)) (bind ?id-2b (gensym)) (modify ?f1 (id ?id-1) (tipo "|") (componentes ?id-2a ?id-2b)) (modify ?f2 (id ?id-2a) (tipo "-") (componentes ?id-3))

(assert (formula (id ?id-2b) (tipo "-") (componentes

?id-4)))

; transformacion doble implicacin (defrule doble-implicacion (declare (salience 550)) (transformar) ?f1 <- (formula (id ?id-1) (tipo "<->") (componentes ?id-2 ?id-3)) => (bind ?id-4a (gensym)) (bind ?id-4b (gensym)) (modify ?f1 (id ?id-1) (tipo "&") (componentes ?id-4a ?id-4b)) (assert (formula (id ?id-4a) (tipo "->") (componentes ?id-2 ?id-3))) (assert (formula (id ?id-4b) (tipo "->") (componentes ?id-3 ?id-2))) ) ; cierra la transformacion y define hecho raiz para la impresin (defrule cierra-transformacion (declare (salience 100)) ?t <- (transformar) => (retract ?t) (assert (imprimir raiz)) )

3. (defrule imprimir-dupla ?f <- (imprimir ?id-1) (formula (id ?id-1) (tipo ?tipo&"&"|"|"|"->"|"<->") (componentes ?id-2 ?id3)) => (retract ?f) (printout t ?tipo " ") (assert (imprimir ?id-3)) (assert (imprimir ?id-2)) ) (defrule imprimir-negacion ?f <- (imprimir ?id-1) (formula (id ?id-1) (tipo "-") (componentes ?id-2)) => (retract ?f) (printout t "- ") (assert (imprimir ?id-2)) ) (defrule imprimir-var ?f <- (imprimir ?id-1) (formula (id ?id-1) (tipo "var")) => (retract ?f) (printout t ?id-1 " ") ) (defrule imprimir-fin (not (imprimir ?)) => (printout t crlf) )

El siguiente rbol de decisin presenta una pequea seccin de un diagnstico de fallos en el sistema de encendido de coches. Cada caja redondeada es una recomendacin. Cada caja rectangular implica la recogida de evidencias. Implemente en Clips un sistema que solucione este problema. Hay diversas posibilidades en cuanto al diseo de la implementacin? Razone las opciones y sus ventajas o inconvenientes. Puede implementar el sistema de acuerdo a cada una de esas posibilidades? No importa si no entiende alguna palabra de la figura, son preguntas de respuestas booleanas y las recomendaciones correspondientes a las secuencias de evidencias.

;Definicin de la estructuras de datos (deftemplate nodo-binario "estructura del nodo del arbol binario" (slot nodo-id (type INTEGER)) (slot pregunta (type STRING)) (slot nodo-yes (type INTEGER)) (slot nodo-not (type INTEGER)) ) (deftemplate nodo-terminal "estructura del nodo terminal del arbol" (slot nodo-id (type INTEGER)) (slot indicacion (type STRING)) ) (deffacts arbol-binario "contenidos de los nodos que componen en arbol" (nodo-binario (nodo-id 1) (pregunta "Starter turning") (nodo-yes 2) (nodonot 3)) (nodo-binario (nodo-id 2) (pregunta "Got any petrol") (nodo-yes 4) (nodonot 5)) (nodo-binario (nodo-id 3) (pregunta "Lights working") (nodo-yes 6) (nodonot 7)) (nodo-binario (nodo-id 6) (pregunta "Solenoid clik") (nodo-yes 8) (nodo-not 9)) (nodo-binario (nodo-id 8) (pregunta "Terminals clean") (nodo-yes 10) (nodonot 11)) (nodo-binario (nodo-id 9) (pregunta "Solenoid fuse OK") (nodo-yes 12) (nodo-not 13)) (nodo-terminal (nodo-terminal (nodo-terminal (nodo-terminal (nodo-terminal (nodo-terminal (nodo-terminal (nodo-activo 1) ) ;************************************* ;DEFINICIN DE REGLAS ;******************************************** (defrule pide-datos "Presenta la pregunta del nodo y navega por el arbol" ?n <- (nodo-activo ?nodo) (nodo-binario (nodo-id ?nodo) (pregunta ?pregunta) (nodo-yes ?ny) (nodo-not ?nn)) => (retract ?n) (printout t crlf ?pregunta " (Y/-)?: " crlf) (if (eq (read) Y) then (assert (nodo-activo ?ny)) else (assert (nodoactivo ?nn)) ) ) (defrule presenta-conclusiones "Presenta la indicacion correspondiente" ?n <- (nodo-activo ?nodo) (nodo-terminal (nodo-id ?nodo) (indicacion ?indicacion)) => (nodo-id (nodo-id (nodo-id (nodo-id (nodo-id (nodo-id (nodo-id 4) (indicacion "Call de A.A.")) 5) (indicacion "Buy same")) 7) (indicacion "Charge battery")) 10) (indicacion "Replace starter")) 11) (indicacion "Clean terminals")) 12) (indicacion "Replace solenoid")) 13) (indicacion "Replace fuse"))

(retract ?n) (printout t crlf ?indicacion "!" crlf crlf) )

Ejercicio de Clips: Se dispone de un registro con los siguientes datos de personas: DNI, Nombre, Apellidos, ao-nacimiento, profesin, DNI-padre, DNI-madre y DNI-cnyuge. 1.1 Disear las estructuras Clips para almacenar estos datos en la base de hechos. Implementar las reglas Clips que permitan alcanzar los siguientes objetivos: 1.2 Se desea obtener un listado de los nombres de los ascendientes de cada persona. 1.3 Se desea determinar si hubo matrimonios entre primos hermanos. 1.4 Se desea determinar si hubo matrimonios entre un cnyuge que tuviese una determinada profesin y que el padre del otro cnyuge tuviese esa misma profesin. 1.5 Se desea un listado de todas las personas ordenadas por ao de nacimiento. 1.6 Se desea un listado de todas las personas ordenadas por apellidos. Para comparar strings se dispone de la funcin str-compare que tiene como argumentos los dos strings a comparar. Devuelve 0 si son iguales, un valor positivo si el primero es mayor que el segundo, y devuelve un valor negativo en el caso inverso. ;Se dispone de un registro con los siguientes datos de personas: DNI, Nombre y apellidos, ao-nacimiento, profesin, DNI-padre, ;DNI-madre y DNI-cnyuge. ;Definicin de la estructuras de datos (deftemplate persona "Tipo de entidad persona" (slot posicion (type INTEGER)); campo para la ordenacin de los registros segun diferentes criterios (slot dni) (slot nombre) (multislot apellidos) (slot nacimiento (type INTEGER));Ao nacimiento (slot profesion) (slot padre) ;Contendr el DNI del padre (slot madre) ;Contendr el DNI de la madre (slot conyuge); contendr el DNI del conyuge ) (deffacts personas (persona (posicion 1) (dni 156688068A) (nombre Pedro) (apellidos "Ponce Sala") (nacimiento 1941) (profesion "cartero")) (persona (posicion 2) (dni 080245678A) (nombre Francisco) (apellidos "Ponce Suarez") (nacimiento 1960) (profesion "Informatico") (padre 156688068A) (madre 112244069A) (conyuge 663355046A)) (persona (posicion 3) (dni 856678098A) (nombre Zeus) (apellidos "Ponce Suarez") (nacimiento 1961) (profesion "Agricultor") (padre 156688068A)(madre 112244069A) (conyuge 333344059A)) (persona (posicion 4) (dni 356688068A) (nombre Pepe) (apellidos "Ponce Saez") (nacimiento 1980) (profesion "Lechero") (padre 080245678A) (madre 663355046A)) (persona (posicion 5) (dni 556688068A) (nombre Luis) (apellidos "Ponce Lopez") (nacimiento 1972) (profesion "cartero") (padre 856678098A) (madre 333344059A) (conyuge 552299078A)) (persona (posicion 6) (dni 456688068A) (nombre Juan) (apellidos "Ponce Lopez") (nacimiento 1981) (profesion "elect") (padre 856678098A) (madre 663355046A) ) (persona (posicion 7) (dni 552299078A) (nombre Carol) (apellidos "Ponce Saez") (nacimiento 1973) (profesion "azafata") (padre 080245678A) (madre 663355046A)(conyuge 556688068A))

(persona (posicion 8) (dni 663355046A) (nombre Petra) (apellidos "Saez Diaz") (nacimiento 1963) (profesion "ama casa") (conyuge 080245678A)) (persona (posicion 9) (dni 333344059A) (nombre Manuela) (apellidos "Lopez Perez") (nacimiento 1962) (profesion "cartero") (conyuge 856678098A)) (persona (posicion 10) (dni 112244069A) (nombre Felisa) (apellidos "Suarez Garcia") (nacimiento 1948) (profesion "ama casa") (conyuge 156688068A)) (inicio) ) ;******************************************** ;DEFINICIN DE REGLAS ;******************************************** ;Regla que plantea de forma muy simple el men de acciones que se desean realizar: (defrule presenta-menu "Presenta el menu de acciones al usuario" ?inicio <- (inicio) => (printout t crlf "Seleccione accin (1-5)" crlf " 1- Listar por apellidos" crlf " 2- Listar por ao de nacimiento" crlf " 3- Obtener los ascendientes de una persona" crlf " 4- Determinar si hubo matrimonios entre primos" crlf " 5- Determinar si un conyuge con la profesion del suegro" crlf " Accin: ") (bind ?accion (read)) (if (= ?accion 1) then (assert (listar-apellidos))) (if (= ?accion 2) then (assert (listar-anhos))) (if (= ?accion 3) then (assert (listar-ascendientes))) (if (= ?accion 4) then (assert (determinar-matri-primos))) (if (= ?accion 5) then (assert (determinar-matri-suegro))) (retract ?inicio) ) ;************************************** ;Reglas que ordenan las posiciones por apellidos (defrule ordenar-apellidos "ordena por apellidos" (declare (salience 550)) (listar-apellidos) ?x1 <- (persona (posicion ?i) (apellidos $?ap1) ) ?x2 <- (persona (posicion ?j)(apellidos $?ap2) ) (test (= ?j (+ ?i 1))) ;Pasamos la variable multicampo a una cadena simple y se compara (test (> (str-compare (implode$ $?ap1) (implode$ $?ap2)) 0)) ;Ordenadas alfabeticamente => (modify ?x1 (posicion ?j)) (modify ?x2 (posicion ?i)) )

; regla para preparar el proceso de impresin (defrule inicia-indice-apellidos "Inicia el indice para la ordenacin" (declare (salience 520)) ?l <- (listar-apellidos) => (retract ?l) (assert (indice-ap 1)) ) ; Regla imprime ordenadamente por apellidos (defrule imprime-apellidos "Imprime por apellidos" (declare (salience 500)) ?x <- (indice-ap ?i) (persona (posicion ?i) (nombre ?nombre) (apellidos $?ap) => (printout t $?ap ", " ?nombre crlf) (retract ?x) (assert (indice-ap (+ ?i 1))) ) ;************************************** ;Regla que ordena las posiciones por anho de la misma forma que la anterior (defrule ordenar-anhos "ordena por anhos" (declare (salience 550)) (listar-anhos) ?x1 <- (persona (posicion ?i) (nacimiento ?anho-1) ) ?x2 <- (persona (posicion ?j) (nacimiento ?anho-2) ) ;se comparan solo las posiciones adyacentes (test (= ?j (+ ?i 1))) (test (< ?anho-1 ?anho-2)) => (modify ?x1 (posicion ?j)) (modify ?x2 (posicion ?i)) ) (defrule inicia-indice-anhos "Inicia el indice para la ordenacin" (declare (salience 520)) ?l <- (listar-anhos) => (retract ?l) (assert (indice-an 1)) ) (defrule imprime-anhos "imprime por anhos" (declare (salience 450)) ?x <- (indice-an ?i) (persona (posicion ?i) (nombre ?nombre) (nacimiento ?a) ) => (printout t ?a ", " ?nombre crlf) (retract ?x) (assert (indice-an (+ ?i 1))) ) ;************************************** ; Reglas para el listado de los ancestros de una persona

(defrule obtener-dni-ascendientes "Pide el dni de la persona cuyos ascendientes se buscan" (declare (salience 550)) ?fase <- (listar-ascendientes) => (printout t crlf "introduzca el dni de la persona: " crlf) (assert (objetivo (read))) (retract ?fase) ) (defrule obtener-ascendentes "Obtiene los ascendientes de una persona dada" (declare (salience 500)) ?ob <- (objetivo ?dni-ob) (persona (dni ?dni-ob) (nombre ?nombre) (apellidos $?ap-h) (padre ?dnipadre) (madre ?dni-madre) ) (persona (dni ?dni-padre) (nombre ?nombre-p) (apellidos $?ap-p) ) (persona (dni ?dni-madre) (nombre ?nombre-m) (apellidos $?ap-m) ) => (printout t ?nombre " " $?ap-h " es hijo de " ?nombre-p " " $?ap-p " y de " ?nombre-m " " $?ap-m crlf) (retract ?ob) (assert (objetivo ?dni-padre)) (assert (objetivo ?dni-madre)) ) ;************************************** ;Regla que comprueba si hay matrimonios entre primos. Para simplificar supondremos que hay un nico matrimonio ;para cada miembro de una pareja. As, podemos dejar las abuelas tranquilas, por ejemplo (defrule comprueba-matrimonios-primos "Determina si ha habido matrimonios entre primos" ?mp <- (determinar-matri-primos) (persona (dni ?dni) (nombre ?nombre) (padre ?padre) (madre ?madre) (conyuge ?d-conyuge) ) (persona (dni ?d-conyuge) (nombre ?conyuge) (padre ?c-padre) (madre ?cmadre) ) (persona (dni ?padre) (padre ?abuelo-p)) ; abuelo paterno (persona (dni ?madre) (padre ?abuelo-m)) ; abuelo materno (persona (dni ?c-padre) (padre ?c-abuelo-p) ) ; abuelo paterno del conyuge (persona (dni ?c-madre) (padre ?c-abuelo-m) ) ; abuelo materno del conyuge (test ( or (eq ?abuelo-p ?c-abuelo-p ) (eq ?abuelo-p ?c-abuelo-m ) (eq ?abuelo-m ?c-abuelo-p ) (eq ?abuelo-m ?c-abuelo-m ) )) => (retract ?mp) (printout t "Se ha encontrado un matrimonio entre primos: " ?nombre " y " ?conyuge " " crlf) ) ;**************************************

;Regla que comprueba si hay un matrimonio con un conyuge con la misma profesin que el padre del otro conyuge (defrule comprueba-profesion-suegro "Determina si una persona con la profesin de su suegro" ?mp <- (determinar-matri-suegro) (persona (dni ?dni) (nombre ?nombre) (profesion ?prof ) (conyuge ? conyuge)) (persona (dni ?conyuge) (padre ?suegro) ); obtenemos el dni del suegro (persona (dni ?suegro) (nombre ?n-suegro) (profesion ?prof)) ; coincide la profesion del suegro => (retract ?mp) (printout t "Se ha encontrado que " ?nombre " y su suegro " ?n-suegro " tienen la misma profesin " crlf) )

Supngase una empresa de mensajera que transporta paquetes y cartas. La siguiente tabla presenta los costes de enviar cartas y paquetes menores de 2 Kgs. entre la ciudad origen y la ciudad destino siempre que la entrega sea al da siguiente. COSTE (euros) ORIGEN Madrid Madrid Madrid Barcelon a Barcelon a Barcelon a DESTINO Barcelon a Toledo Badajoz Cdiz Gerona Badajoz CARTA 4 2 3 6 2 4 PAQUETE 7 6 7 8 4 9

Si la entrega es para el mismo da que la recogida existe un suplemento tanto para las cartas como para los paquetes de 60 euros. Al margen de esto, si el paquete pesa ms de 2 kilos, hay un suplemento de 6 euros por cada 100 grs. de ms. Se pide, utilizando Clips, 4.1. Definir la base de hechos . 4.2. Construir la base de reglas que formalice dichos conocimientos utilizando el menor nmero de reglas posible. 4.3. Construir las reglas para la introduccin de los datos del paquete a enviar y muestren el importe correspondiente. 4.4. Supngase que cada fila de la tabla representa los costes de enviar cartas entre dos ciudades determinadas, con independencia de cul sea el origen y cul el destino. Es decir, vale lo mismo enviar una carta de Madrid a Barcelona que de Barcelona a Madrid. Construir la o las reglas para formalizar tal conocimiento.

;Definicin de la estructuras de datos (deftemplate ruta "Ruta y tipo de envos" (slot origen) (slot destino) (slot tipo) (slot importe (type INTEGER)) ) (deftemplate envio "Datos del envio" (slot origen) (slot destino) (slot tipo (type SYMBOL)) (slot urgente? (type SYMBOL)) (slot peso (type INTEGER)) (slot importe (type INTEGER)) ) (deftemplate suplementos "suplemento que se paga por entrega rpida" (slot entrega-rapida (type INTEGER)) (slot exceso-peso-minimo (type INTEGER)) (slot importe-peso-minimo (type INTEGER)) (slot exceso-peso-margen (type INTEGER)) (slot importe-margen (type INTEGER)) ) (deffacts tarifas (ruta (origen Madrid) (destino Barcelona) (tipo C) (importe 4)) (ruta (origen Madrid) (destino Barcelona) (tipo P) (importe 7)) (ruta (origen Madrid) (destino Toledo ) (tipo C) (importe 2)) (ruta (origen Madrid) (destino Toledo ) (tipo P) (importe 6)) (ruta (origen Madrid) (destino Badajoz) (tipo C) (importe 3)) (ruta (origen Madrid) (destino Badajoz) (tipo P) (importe 7)) (ruta (origen Barcelona) (destino Cadiz) (tipo C) (importe 6)) (ruta (origen Barcelona) (destino Cadiz) (tipo P) (importe 8)) (ruta (origen Barcelona) (destino Gerona) (tipo C) (importe 2)) (ruta (origen Barcelona) (destino Gerona) (tipo P) (importe 4)) (ruta (origen Barcelona) (destino Badajoz) (tipo C) (importe 4)) (ruta (origen Barcelona) (destino Badajoz) (tipo C) (importe 9)) (suplementos (entrega-rapida 60) (exceso-peso-minimo 2000) (exceso-pesomargen 100) (importe-margen 6)) ) ;************************************* ;DEFINICIN DE REGLAS ;******************************************** ;Regla que plantea de forma muy simple el men de acciones que se desean realizar: ;origen, destino, y tipo de paquete ;pregunta la urgencia del envo (urgente o no) ;si es paquete pide el peso (defrule pide-datos "Pide los datos del envio" (initial-fact) => (printout t crlf "Datos del envo" crlf) (printout t crlf "Origen: " ) (bind ?origen (read)) (printout t crlf "Destino: ") (bind ?destino (read)) (printout t crlf "Es una carta (C) o un paquete (P): ") (bind ?tipo (read)) (printout t crlf "Es urgente? (S/N): ") (bind ?urgente (read)) (assert (envio (origen ?origen) (destino ?destino) (tipo ?tipo) (urgente? ?urgente) (peso 0) (importe 0))) )

(defrule calcula-importe "calcula el importe en funcin del origen, destino, urgencia y tipo" ?e <- (envio (origen ?origen) (destino ?destino) (tipo ?tipo) (urgente? ? urgente) (peso 0) (importe 0)) (ruta (origen ?origen) (destino ?destino) (tipo ?tipo) (importe ?importe)) (suplementos (entrega-rapida ?entrega-rapida)) => (if (eq ?urgente S) then (bind ?importe (+ ?importe ?entrega-rapida))) (modify ?e (importe ?importe)) ) (defrule suma-importe-exceso-peso "acumula el importe del peso extra" ?e <- (envio (tipo P) (peso 0) (importe ?importe&:(> ?importe 0))) (suplementos (exceso-peso-minimo ?peso-minimo) (importe-peso-minimo ? importe-peso-minimo) (exceso-peso-margen ?margen) (importe-margen ?importe-margen)) => (printout t crlf "Peso?: ") (bind ?peso (read)) (if (> ?peso ?peso-minimo) then (bind ?importe (+ ?importe ?importe-peso-minimo)) (bind ?exceso (div (- ?peso ?peso-minimo) ?margen)) (if (> ?exceso 0) then (bind ?importe (+ ?importe (* ?exceso ? importe-margen)))) ) (modify ?e (peso ?peso) (importe ?importe)) ) ; Regla final que termina presentando el coste del envio. (defrule presenta-importe "presenta el coste del envio" (declare (salience -10)) ?e <- (envio (importe ?importe)) => (printout t crlf "El coste del envo es: " ?importe crlf) )

Supngase una agencia de viajes que ofrece viajes de trenes a sus clientes. Los viajes tienen unos atributos como son: el lugar de origen y el lugar de destino y una tarifa inicial que se utilizar para calcular el precio final del viaje. Los viajes en tren se caracterizan por el tipo de tren (AVE o TALGO), por la clase (turista o preferente), por el perodo de salida (blanco, rojo o azul) y el tipo de cliente (asiduo o espordico). Sin descuentos ni incrementos, los precios de un viaje en clase turista, entre dos ciudades, son los siguientes y dependen del tipo de tren. COSTE (euros) ORIGEN Madrid Madrid Barcelon a DESTINO Crdoba Sevilla Madrid AVE 70 80 --TALGO 60 70 80

El precio sera el mismo para el viaje Barcelona-Madrid que para el viaje Madrid-Barcelona. Se utilizan las siguientes reglas para calcular el precio final: o Si el viaje es en clase preferente, los precios de la tabla se ven incrementados en un 30% o Si la fecha de salida es azul, el precio del billete se reduce en un 10% y si es roja se incrementa en un 10%. o Si el cliente es asiduo, el precio se reduce en un 10% o o o Si el viajero es menor de 22 aos (tarifa joven), se le aplica un 20% de reduccin. Si el viajero es mayor de 65 aos (tarifa dorada), se le aplica un 50% de reduccin. Los descuentos y suplementos se aplican en el orden establecido en el enunciado.

Usando Clips: 5.1. Definir la base de hechos 5.2. Construir la base de reglas que formalice dichos conocimientos utilizando el menor nmero de reglas posible. Esto debe realizarse de tal forma que sea fcil aadir y borrar reglas en el sistema, y modificar los incrementos y descuentos sin modificar la base de reglas. 5.3. Construir las reglas para la introduccin de los datos del viaje y muestren el importe correspondiente.

;Definicin de la estructuras de datos (deftemplate trayecto "Trayecto y tipo" (slot origen) (slot destino) (slot tipo-transporte) (slot importe (type INTEGER)) ) (deftemplate billete "Datos billete" (slot origen) (slot destino) (slot tipo-transporte (type SYMBOL)) (slot preferente? (type SYMBOL)) (slot edad-viajero (type INTEGER)) (slot tipo-dia (type SYMBOL)) (slot asiduo? (type SYMBOL)) (slot tarifa-edad (type SYMBOL)) (slot importe (type INTEGER)) ) (deftemplate suplementos "suplemento que se paga por entrega rpida" (slot preferente (type FLOAT)) (slot dia-azul (type FLOAT)) (slot dia-rojo (type FLOAT)) (slot viajero-asiduo (type FLOAT)) (slot tarifa-joven (type FLOAT)) (slot tarifa-dorada (type FLOAT)) (slot exceso-peso-margen (type INTEGER)) (slot importe-margen (type INTEGER)) ) (deffacts tarifas (trayecto (origen Madrid) (destino Cordoba) (tipo-transporte A) (importe 70)) (trayecto (origen Madrid) (destino Cordoba) (tipo-transporte T) (importe 60)) (trayecto (origen Madrid) (destino Sevilla) (tipo-transporte A) (importe 80)) (trayecto (origen Madrid) (destino Sevilla) (tipo-transporte T) (importe 70)) (trayecto (origen Barcelona) (destino Madrid) (tipo-transporte T) (importe 80)) (suplementos (preferente 0.3) (dia-azul -0.1) (dia-rojo 0.1) (viajeroasiduo -0.1) (tarifa-joven -0.1) (tarifa-dorada -0.5 )) ; desglose de edades (edad-joven 22) (edad-mayor 65) ) ;************************************* ;DEFINICIN DE REGLAS ;******************************************** ;Regla que plantea de forma muy simple el men de acciones que se desean FLOATizar: ;origen, destino, y tipo de paquete ;pregunta la urgencia del envo (urgente o no)

;si es paquete pide el peso (defrule pide-datos "Pide los datos del envio" ?i <- (initial-fact) (edad-joven ?joven) (edad-mayor ?mayor) => (printout t crlf "Datos del billete" crlf) (printout t crlf "Origen: " ) (bind ?origen (read)) (printout t crlf "Destino: ") (bind ?destino (read)) (printout t crlf "Tipo de tren, AVE (A) o Talgo (T): ") (bind ?tipo-transporte (read)) (printout t crlf "Viaja en preferente (S/N): ") (bind ?preferente? (read)) (printout t crlf "La fecha del viaje es dia Normal (N), Azul (A) o Rojo (R): ") (bind ?tipo-dia (read)) (printout t crlf "Es viajero asiduo (S/N): ") (bind ?asiduo? (read)) (printout t crlf "Edad del viajero (aos): ") (bind ?edad (read)) (if (< ?edad ?joven) then (assert (billete (origen ?origen) (destino ?destino) (tipo-transporte ? tipo-transporte) (preferente? ?preferente?) (tipo-dia ?tipo-dia) (asiduo? ? asiduo?) (tarifa-edad J) (importe 0))) else (if (> ?edad ?mayor) then (assert (billete (origen ?origen) (destino ?destino) (tipotransporte ?tipo-transporte) (preferente? ?preferente?) (tipo-dia ?tipodia) (asiduo? ?asiduo?) (tarifa-edad D) (importe 0))) else (assert (billete (origen ?origen) (destino ?destino) (tipotransporte ?tipo-transporte) (preferente? ?preferente?) (tipo-dia ?tipodia) (asiduo? ?asiduo?) (tarifa-edad N) (importe 0))) ) ) (retract ?i) (assert (trayecto-tipo)) ) (defrule calcula-importe-trayecto-tipo-tren "calcula el importe en funcin del origen, destino y tipo de transporte" ?i <- (trayecto-tipo) ?e <- (billete (origen ?origen) (destino ?destino) (tipo-transporte ? tipo) ) (trayecto (origen ?origen) (destino ?destino) (tipo-transporte ?tipo) (importe ?importe)) => (modify ?e (importe ?importe)) (retract ?i) (assert (clase)) ) (defrule suma-clase "acumula el importe de clase preferente, si lo es" ?i <- (clase) ?e <- (billete (preferente? S) (importe ?importe)) (suplementos (preferente ?preferente)) =>

(modify ?e (importe (* ?importe (+ 1 ?preferente)))) (retract ?i) (assert (tipo-dia))

(defrule suma-tipo-dia "acumula el importe en funcion del tipo de dia" ?i <- (tipo-dia) ?e <- (billete (tipo-dia ?tipo-dia) (importe ?importe)) (suplementos (dia-rojo ?dia-rojo) (dia-azul ?dia-azul)) => (if (eq ?tipo-dia A) then (modify ?e (importe (* ?importe (+ 1 ?diaazul))))) (if (eq ?tipo-dia R) then (modify ?e (importe (* ?importe (+ 1 ?diarojo))))) (retract ?i) (assert (tipo-viajero)) ) (defrule suma-tipo-viajero "acumula el importe segun si es asiduo o no lo es" ?i <- (tipo-viajero) ?e <- (billete (origen ?origen) (destino ?destino) (asiduo? S) (importe ? importe)) (suplementos (viajero-asiduo ?viajero-asiduo)) => (modify ?e (importe (* ?importe (+ 1 ?viajero-asiduo)))) (retract ?i) (assert (tipo-edad)) ) (defrule suma-edad-viajero "acumula el importe segun la tarifa aplicable segun la edad" ?i <- (tipo-edad) ?e <- (billete (tarifa-edad ?tarifa-edad) (importe ?importe)) (suplementos (tarifa-joven ?tarifa-joven) (tarifa-dorada ?tarifa-dorada)) => (if (eq ?tarifa-edad J) then (modify ?e (importe (* ?importe (+ 1 ?tarifajoven))))) (if (eq ?tarifa-edad D) then (modify ?e (importe (* ?importe (+ 1 ?tarifadorada))))) (retract ?i) (assert (calcula-total)) ) ; Regla final que termina presentando el coste del envio. (defrule presenta-importe "presenta el precio final del billete" ?i <- (calcula-total) (billete (importe ?importe)) => (printout t crlf "El precio del billete es: " ?importe crlf) (retract ?i) )

Se pretende construir un sistema que aconseje a un usuario la compaa (de entre dos contratadas) ms barata para cada llamada. El sistema debera preguntar si la llamada es local o interprovincial, la duracin estimada, y el da y la hora de comienzo. Los precios de la compaa AAT son: Las llamadas locales tienen una tarifa mnima de 0,1 euros, e incluye los dos primeros minutos. Los siguientes minutos son: de lunes a viernes, de 8 a 18 hs, a 0,02 euros y de 18 a 8 hs. de 0,01 euros. Los sbados y domingos, todo el da a 0,01 euros. Las llamadas interprovinciales tienen una tarifa mnima de 0,25 euros que tambin incluye solamente el primer minuto. Cada uno de los siguientes minutos cuesta: de lunes a viernes, de 8 a 22 hs, a 0,3 euros y de 22 a 8 hs. de 0,2 euros. Los sbados y domingos, todo el da a 0,2 euros el minuto. Los precios de la compaa BBT son: Las llamadas locales tienen una tarifa mnima de 0,04 euros, pero no incluye ningn minuto. Cada minuto de lunes a viernes cuesta, de 8 a 20 hs, a 0,03 euros y de 20 a 8 hs. de 0,01 euros. Los sbados y domingos, todo el da a 0,01 euros. Las llamadas interprovinciales tienen una tarifa mnima de 0,1 euros, que tampoco incluye ningn minuto. Cada minutos cuesta: de lunes a viernes, de 8 a 20 hs, a 0,3 euros y de 20 a 8 hs. de 0,1 euros. Los sbados y domingos, todo el da a 0,1 euros el minuto. Se pide construir el sistema en Clips. 3.1. Construir la base de hechos y la base de reglas que formalice dichos conocimientos utilizando el menor nmero de reglas posible. 3.2. Construir las reglas para la introduccin de los datos de la llamada y muestren al usuario el nmero de la compaa por la cual efectuar la llamada. 1era. Versin: ;La solucin ms adecuada a este tipo de problemas normalmente es la definicin de una tabla, y este se podra resolver as, ; como en los anteriores ejercicios. Pero en este, dada la variabilidad de los tipos de datos, vamos a resolverlo de otra forma, ; con reglas que contienen todos los variables, datos y rangos que se utilizan para el calculo de la tarifa (deftemplate llamada "Datos de la llamada tipo" (slot tipo-llamada (type SYMBOL)) (slot dia (type INTEGER)) (slot hora (type INTEGER)) (slot duracion (type INTEGER)) ) ;************************************* ;DEFINICIN DE REGLAS ;******************************************** ;Regla que plantea de forma muy simple el men de acciones que se desean FLOATizar: ;origen, destino, y tipo de paquete ;pregunta la urgencia del envo (urgente o no) ;si es paquete pide el peso

(defrule pide-datos "Pide los datos de la llamada" => (printout t crlf "Datos de la llamada tipo" crlf) (printout t crlf "Llamada Local (L) o Interprovincial (I)?: ") (bind ?tipo-llamada (read)) (printout t crlf "El dia habitual de la llamada (1 a 7)?: ") (bind ?dia (read)) (printout t crlf "La hora habitual de la llamada (1 a 24)?: ") (bind ?hora (read)) (printout t crlf "Duracion de la llamada: ") (bind ?duracion (read)) (assert (llamada (tipo-llamada ?tipo-llamada) (dia ?dia) (hora ?hora) (duracion ?duracion))) ) (defrule calcula-importe-segun-la-telefonica-AAT "calcula el importe en funcin del tipo de llamada, duracin y dia y hora de AAT" ?e <- (llamada (tipo-llamada ?tipo) (dia ?dia) (hora ?hora) (duracion ? duracion)) => (if (eq ?tipo L) then (bind ?importe 0.1) (if (> ?duracion 2) then (bind ?duracion (- ?duracion 2)) (if (and (>= ?dia 1) (<= ?dia 5) (>= ?hora 8) (< ?hora 18)) then (bind ? importe (+ ?importe (* ?duracion 0.02)))) (if (and (>= ?dia 1) (<= ?dia 5) (or (>= ?hora 18) (< ?hora 8))) then (bind ?importe (+ ?importe (* ?duracion 0.01)))) (if (and (>= ?dia 6) (<= ?dia 7)) then (bind ?importe (+ ?importe (* ? duracion 0.01)))) ) ) (if (eq ?tipo I) then (bind ?importe 0.25) (if (> ?duracion 1) then (bind ?duracion (- ?duracion 1)) (if (and (>= ?dia 1) (<= ?dia 5) (>= ?hora 8) (< ?hora 22)) then (bind ? importe (+ ?importe (* ?duracion 0.03)))) (if (and (>= ?dia 1) (<= ?dia 5) (or (>= ?hora 22) (< ?hora 8))) then (bind ?importe (+ ?importe (* ?duracion 0.02)))) (if (and (>= ?dia 6) (<= ?dia 7)) then (bind ?importe (+ ?importe (* ? duracion 0.02)))) ) ) (printout t crlf "El importe de la llamada tipo en AAT es: " ?importe crlf crlf) ) (defrule calcula-importe-segun-la-telefonica-BBT "calcula el importe en funcin del tipo de llamada, duracin y dia y hora de BBT" ?e <- (llamada (tipo-llamada ?tipo) (dia ?dia) (hora ?hora) (duracion ? duracion)) => (if (eq ?tipo L) then (bind ?importe 0.04) (if (and (>= ?dia 1) (<= ?dia 5) (>= ?hora 8) (< ?hora 20)) then (bind ? importe (+ ?importe (* ?duracion 0.03)))) (if (and (>= ?dia 1) (<= ?dia 5) (or (>= ?hora 20) (< ?hora 8))) then (bind ?importe (+ ?importe (* ?duracion 0.01)))) (if (and (>= ?dia 6) (<= ?dia 7)) then (bind ?importe (+ ?importe (* ? duracion 0.01)))) )

(if (eq ?tipo I) then (bind ?importe 0.1) (if (and (>= ?dia 1) (<= ?dia 5) (>= ?hora 8) (< ?hora 22)) then (bind ? importe (+ ?importe (* ?duracion 0.03)))) (if (and (>= ?dia 1) (<= ?dia 5) (or (>= ?hora 22) (< ?hora 8))) then (bind ?importe (+ ?importe (* ?duracion 0.01)))) (if (and (>= ?dia 6) (<= ?dia 7)) then (bind ?importe (+ ?importe (* ? duracion 0.01)))) ) (printout t crlf "El importe de la llamada tipo en BBT es: " ?importe crlf crlf)

2da. Versin: ; Antes hemos resuelto este mismo problema con una reglas para cada telefonica que incluyen todas sus tarifas ; Ahora lo resolveremos mediante una tabla sencilla. Se puede hacer ms complejo, de forma que admita todas las ; posibilidades de tarifas (es un recomendable ejercicio). Pero esta es una solucin intermedia. (deftemplate llamada "Datos de la llamada tipo" (slot tipo-llamada (type SYMBOL)) (slot dia (type INTEGER)) (slot hora (type INTEGER)) (slot duracion (type INTEGER)) ) (deftemplate tarifa "datos de cada telefonica" (slot telefonica (type SYMBOL)) (slot tipo-llamada (type SYMBOL)) (slot establecimiento-llamada (type FLOAT)) (slot franquicia (type INTEGER)) (slot inicio-noche-laborable (type INTEGER)) (slot minuto-laborable-noche (type FLOAT)) (slot inicio-dia-laborable (type INTEGER)) (slot minuto-laborable-dia (type FLOAT)) (slot minuto-festivo (type FLOAT)) ) (deffacts tarifas-telefonicas "datos de las tarifas de las diferentes telefonicas" (tarifa (telefonica AAT) (tipo-llamada L) (establecimiento-llamada 0.1) (franquicia 2) (inicio-noche-laborable 18) (minuto-laborable-noche 0.01) (inicio-dia-laborable 8) (minuto-laborable-dia 0.02) (minuto-festivo 0.01)) (tarifa (telefonica AAT) (tipo-llamada I) (establecimiento-llamada 0.25) (franquicia 1) (inicio-noche-laborable 22) (minuto-laborable-noche 0.2) (inicio-dia-laborable 8) (minuto-laborable-dia 0.3) (minuto-festivo 0.2)) (tarifa (telefonica BBT) (tipo-llamada L) (establecimiento-llamada 0.04) (franquicia 0) (inicio-noche-laborable 20) (minuto-laborable-noche 0.03) (inicio-dia-laborable 8) (minuto-laborable-dia 0.01)

(minuto-festivo 0.01)) (tarifa (telefonica BBT) (tipo-llamada I) (establecimiento-llamada 0.1) (franquicia 0) (inicio-noche-laborable 20) (minuto-laborable-noche 0.3) (inicio-dia-laborable 8) (minuto-laborable-dia 0.1) (minuto-festivo 0.1))

;************************************* ;DEFINICIN DE REGLAS ;******************************************** ;Regla que plantea de forma muy simple el men de acciones que se desean FLOATizar: ;origen, destino, y tipo de paquete ;pregunta la urgencia del envo (urgente o no) ;si es paquete pide el peso (defrule pide-datos "Pide los datos de la llamada" => (printout t crlf "Datos de la llamada tipo" crlf) (printout t crlf "Llamada Local (L) o Interprovincial (I)?: ") (bind ?tipo-llamada (read)) (printout t crlf "El dia habitual de la llamada (1 a 7)?: ") (bind ?dia (read)) (printout t crlf "La hora habitual de la llamada (1 a 24)?: ") (bind ?hora (read)) (printout t crlf "Duracion de la llamada: ") (bind ?duracion (read)) (assert (llamada (tipo-llamada ?tipo-llamada) (dia ?dia) (hora ?hora) (duracion ?duracion))) ) (defrule calcula-importe-segun-la-telefonica "calcula el importe en funcin del tipo de llamada, duracin y dia y hora" ?e <- (llamada (tipo-llamada ?tipo) (dia ?dia) (hora ?hora) (duracion ? duracion)) (tarifa (telefonica ?telefonica) (tipo-llamada ?tipo) (establecimientollamada ?est) (franquicia ?franquicia) (inicio-noche-laborable ?inicio-noche-laborable) (minuto-laborable-noche ? minuto-laborable-noche) (inicio-dia-laborable ?inicio-dia-laborable) (minuto-laborable-dia ? minuto-laborable-dia) (minuto-festivo ?minuto-festivo)) => (bind ?importe ?est) (if (> ?duracion ?franquicia) then (bind ?duracion (- ?duracion ?franquicia)) (if (and (>= ?dia 1) (<= ?dia 5) (>= ?hora ?inicio-dia-laborable) (< ? hora ?inicio-noche-laborable)) then (bind ?importe (+ ?importe (* ?duracion 0.02)))) (if (and (>= ?dia 1) (<= ?dia 5) (or (>= ?hora ?inicio-noche-laborable) (< ?hora ?inicio-dia-laborable))) then (bind ?importe (+ ?importe (* ? duracion ?minuto-laborable-noche)))) (if (and (>= ?dia 6) (<= ?dia 7)) then (bind ?importe (+ ?importe (* ? duracion ?minuto-festivo)))) )

(printout t crlf "El importe de la llamada tipo en " ?telefonica " es: " ?importe crlf crlf)

Dentro del problema global de un juego de ajedrez: 1 Definir una plantilla "ficha" que sirva para almacenar los datos relativos a las diferentes piezas de ajedrez que se encuentran sobre el tablero: tipo de pieza, color y posicin que ocupa. 2 Definir las reglas que sean necesarias para la generacion de todas las casillas del tablero, almacenndolas en hechos de la forma (casilla <i> <j>). 3 Definir las reglas que sean necesarias para eliminar las casillas que estn ocupadas. Asmase para ello que se han generado los hechos del 3.1. 4 Definir las reglas que sean necesarias para eliminar las casillas que son amenazadas por alguna de las piezas blancas colocadas. Para simplificar, considerar nicamente amenazas procedentes de reyes, peones y torres. 5 Defina la regla/s para visualizar las casillas libres y no amenazadas. Resolucin del ejercicio 1 (deftemplate ficha (slot tipo (type SYMBOL) (allowed-values peon torre alfil caballo rey reina)) (slot color (type SYMBOL) (allowed-values blanca negra)) (slot posicion_h (type INTEGER) (range 1 8)) (slot posicion_v (type INTEGER) (range 1 8))) 2 (defrule inicio (initial-fact) => (bind ?i 1) (while (< ?i 9) (bind ?j 1) (while (< ?j 9) (assert (casilla ?i ?j)) (bind ?j (+ ?j 1)) ) (bind ?i (+ ?i 1)) ) ) 3 (defrule eliminar_ocupadas (ficha (posicion_h ?i) (posicion_v ?j)) ?ocupada <- (casilla ?i ?j) => (retract ?ocupada) ) 4 ;el enunciado no diferencia, para eliminar las casillas amenazadas, ;de si trata de una amenaza blanca o negra sobre el contrario, ;asumamos que las blancas avanzan en sentido creciente del indice del tablero (defrule eliminar_amenazadas_peon (ficha (tipo peon)(color blanca) (posicion_h ?i) (posicion_v ?j)) ?amenazada <- (casilla ?k ?l)

(or

(and (test(= ?l (+ ?i 1))) (test(= ?k (+ ?j 1)))) (and (test(= ?l (- ?- 1))) (test(= ?k (+ ?j 1))))

) => (retract ?amenazada) ) ;la siguiente regla podra haberse diferenciado en 8 (defrule eliminar_amenazadas_rey (ficha (tipo rey)(color blanca) (posicion_h ?i) (posicion_v ?j)) ?amenazada <- (casilla ?k ?l) (or (and (test(= ?l (+ ?j 1))) (test (= ?k ?i))) (and (test(= ?l (- ?j 1))) (test (= ?k ?i))) (and (test(= ?l ?j)) (test (= ?k (+ ?i 1)))) (and (test(= ?l ?j)) (test (= ?k (- ?i 1)))) (and (test(= ?l (+ ?j 1))) (test(= ?k (+ ?i 1)))) (and (test(= ?l (+ ?j 1))) (test(= ?k (- ?i 1)))) (and (test(= ?l (- ?j 1))) (test(= ?k (+ ?i 1)))) (and (test(= ?l (- ?j 1))) (test(= ?k (- ?i 1)))) ) => (retract ?amenazada) ) ; para eliminar las celdas amenazadas por la torre (defrule eliminar_amenazadas_torre_1 (ficha (tipo torre)(color blanca) (posicion_h ?i) (posicion_v ?j)) ?amenazada <- (casilla ?i ?k) (test (> ?k ?j)) => (retract ?amenazada) ) ;Esta solucin pasa por alto la posibilidad de que alguna ficha, ;en la misma columna que la torre "amenazante", impida que la torre ;amenace el resto posterior de la columna. Para solucionar esto, lo ms prctico ;sera diferencia entre celda ocupada y celda simplemente amenazada. 5 (defrule mensaje (declare (salience -10)) => (printout t "Han quedado libres las siguientes casillas" crlf)) (defrule casillas (declare (salience -20)) (casilla ?i ?j) => (printout t "(" ?i " , " ?j ") (defrule terminacion (declare (salience -30)) => (printout t crlf)) "))

Se dispone de dos cntaros de agua, uno de 4 litros y otro de 3 litros de capacidad, siendo sta la nica informacin que se tiene de los mismos. Existe una bomba de agua con la que se pueden llenar los cntaros. Se desea que el cntaro de 4 ls. de capacidad quede lleno por la mitad y el de 3 ls. vaco. Este es un ejemplo planteable como problema de bsqueda en un espacio de estados. Este espacio consistira del conjunto de pares de enteros (x, y), tal que x = 0, 1, 2, 3 o 4 e y = 0, 1, 2 o 3, donde x e y representan el nmero de litros de agua que hay en los cntaros de 4 y 3 litros respectivamente. Se considerar que el estado inicial es (0, 0) y el estado meta (2, 0). En cuanto a los operadores que se pueden aplicar a los estados descritos con anterioridad, pueden definirse los siguientes: a. Llenar el cntaro de 4 ls.: Si (x, y) and x < 4 entonces (4, y) b. Llenar el cntaro de 3 ls.: Si (x, y) and y < 3 entonces (x, 3) c. Vaciar en el suelo el cntaro de 4 l.: Si (x, y) and x > 0 entonces (0, y) d. Vaciar en el suelo el cntaro de 3 ls.: Si (x, y) and y > 0 (x, 0) e. Verter agua del cntaro de 3 ls. al de 4 hasta llenarlo: Si (x, y) and x + y 4 and y > 0 and x < 4 entonces (4, y (4 x)) f. Verter agua del cntaro de 4 ls. al de 3 hasta llenarlo: Si (x, y) and si x + y 3 and x > 0 and y < 3 entonces (x (3 y), 3) g. Verter todo el agua del cntaro de 3 ls. al de 4: Si (x, y) and x + y 4 and y > 0 entonces (x + y, 0) h. Verter todo el agua del cntaro de 4 ls. al de 3: Si (x, y) and x + y 3 and x > 0 entonces (0, x + y) Cmo llevaras a un programa Clips la resolucin de este problema, considerada la solucin del mismo como la obtencin de un hecho que represente la distribucin de litros planteada como objetivo desde el hecho que representa la distribucin inicial? 1. Cmo representara el contenido y capacidad de las jarras? 2. Y de los operadores? 3. Cmo determinaras el final del proceso? 4. Podra (y cmo) generalizarse la resolucin para una jarra A de capacidad A1 y otra jarra B con capacidad B1 y obtener A2 litros en la primera y B2 litros en la segunda? podra plantearse algn dificultad en la resolucin? 5. La verdadera resolucin de este tipo de problemas es encontrar y mostrar (imprimir, por ejemplo) la secuencia de operadores que conducen al objetivo. Cmo podra hacerse aqu? Resolucin del ejercicio. (deftemplate cantaros (slot profundidad (slot padre (type (slot contenido_4 (slot contenido_3 (ultimo_mov (type )

(type INTEGER) (range 1 ?VARIABLE)) FACT-ADDRESS SYMBOL) (allowed-symbols sin-padre)) (type INTEGER)) (type INTEGER) STRING))

(deffacts cantaros_inicio (cantaros (contenido_4 0) (contenido_3 0)) ) (defrule llena_4 (declare (salience 510))

?h <- (cantaros (profundidad ?pf) (padre ?p) (contenido_4 ?c4&:(< ?c4 4)) (contenido_3 ?c3)) => (assert (cantaros (profundidad (+ 1 ?pf)) (padre ?h) (contenido_4 4) (contenido_3 ?c3) (ultimo_mov "llena 4))) (printout t "llena_4" crlf) ) (defrule llena_3 (declare (salience 510)) ?h <- (cantaros (profundidad ?pf) (padre ?p) (contenido_4 ?c4) (contenido_3 ? c3&:(< ?c3 3))) => (assert (cantaros (profundidad (+ 1 ?pf)) (padre ?h) (contenido_4 ?c4) (contenido_3 3))) (printout t "llena_3" crlf) ) (defrule vacia_4 (declare (salience 500)) ?h <- (cantaros (profundidad ?pf) (padre ?p) (contenido_4 ?c4&:(> ?c4 0)) (contenido_3 ?c3)) => (assert (cantaros (profundidad (+ 1 ?pf)) (padre ?h) (contenido_4 0) (contenido_3 ?c3))) (printout t "vacia_4" crlf) ) (defrule vacia_3 (declare (salience 500)) ?h <- (cantaros (profundidad ?pf) (padre ?p) (contenido_4 ?c4)(contenido_3 ? c3&:(> ?c3 0))) => (assert (cantaros (profundidad (+ 1 ?pf)) (padre ?h) (contenido_4 ?c4) (contenido_3 0))) (printout t "vacia_3" crlf) ) (defrule llenar_3_con_4 (declare (salience 515)) ?h <- (cantaros (profundidad ?pf) (padre ?p) (contenido_4 ?c4&:(> (contenido_3 ?c3&:(< ?c3 3))) (test (>= (+ ?c3 ?c4) 3)) => (assert (cantaros (profundidad (+ 1 ?pf)) (padre ?h) (contenido_4 3 ?c3))) (contenido_3 3))) (printout t "llenar_3_con_4" crlf) ) (defrule llenar_4_con_3 (declare (salience 515)) ?h <- (cantaros (profundidad ?pf) (padre ?p) (contenido_4 ?c4&:(< (contenido_3 ?c3&:(> ?c3 0))) (test (>= (+ ?c3 ?c4) 4)) => (assert (cantaros (profundidad (+ 1 ?pf)) (padre ?h) (contenido_4 (contenido_3 (- ?c3 (- 4 ?c4))))) (printout t "llenar_4_con_3" crlf) ) (defrule verter_3_en_4

?c4 0))

(- ?c4 (-

?c4 4))

4)

(declare (salience 515)) ?h <- (cantaros (profundidad ?pf) (contenido_3 ?c3&:(> ?c3 0))) (test (< (+ ?c3 ?c4) 4)) => (assert (cantaros (profundidad (+ (contenido_3 0))) (printout t "verter_3_en_4" crlf) ) (defrule verter_4_en_3 (declare (salience 515)) ?h <- (cantaros (profundidad ?pf) (contenido_3 ?c3&:(< ?c3 3))) (test (< (+ ?c3 ?c4) 4)) (printout t "verter_4_en_3" crlf) => (assert (cantaros (profundidad (+ (contenido_3 (+ ?c4 ?c3)))) )

(padre ?p) (contenido_4 ?c4&:(< ?c4 4))

1 ?pf)) (padre ?h) (contenido_4 (+ ?c4 ?c3))

(padre ?p) (contenido_4 ?c4&:(> ?c4 0))

1 ?pf)) (padre ?h) (contenido_4 0)

(defrule elimina-circularidad (declare (salience 520)) (cantaros (profundidad ?pf1) (contenido_4 ?c4) (contenido_3 ?c3)) ?h <-(cantaros (profundidad ?pf2&:(< ?pf1 ?pf2)) (contenido_4 ?c4) (contenido_3 ?c3)) => (retract ?h) ) (defrule finaliza (declare (salience 520)) (cantaros (contenido_4 2) (contenido_3 0)) => (printout t "Conseguido" crlf) (halt) )

Las siguientes reglas de sustitucin de smbolos pueden usarse para reemplazar la cifra de la izquierda por la tira de cifras a su derecha: 2 11 3 21 4 31 5 32 Codificar en Clips un sistema que permita la traduccin de un nmero compuesto de varias cifras (del 1 al 5) segn las reglas anteriores. Para ello podran ser tiles las siguientes funciones: (str-index <strig-expression> <string-expression>): devuelve la posicin del primer string dentro del segundo. (sub-string <integer-1-expression> <integer-2-expression> <string-expression>): devuelve la porcin del string que comienza en la posicin integer-1 y termina en la posicin integer-1 + integer-2. (str-cat <string-expression>*) : Concatena los strings argumento

Resolucin del ejercicio. (deffacts datos-a-traducir (vector 3 2 1) (tabla 2 1 1) (tabla 3 2 1) (tabla 4 3 1) ) (defrule traduce ?cadena <- (vector $?ini ?x $?fin) (tabla ?x ?y1 ?y2) => (retract ?cadena) (assert (vector $?ini ?y1 ?y2 $?fin)) ) (defrule imprime-cadenas (vector $?datos) => (printout t "una salida es: "$?datos crlf)) Una solucin alternativa: (deftemplate traduccion (slot numero (type STRING)) ) (deftemplate cifra (slot entrada) (slot salida) ) (deffacts entrada_salida (traduccion (numero "0")) ) (deffacts tabla-traduccion (cifra (entrada "2") (salida "11")) (cifra (entrada "3") (salida "21")) (cifra (entrada "4") (salida "31"))

) (defrule pide_valor ?f1 <- (traduccion (numero "0")) => (printout t "Introduzca numero: " crlf) (modify ?f1 ( numero (read)))) (defrule traduce_i (cifra (entrada ?i)(salida ?o)) ?f1 <- (traduccion (numero ?numero)) (test (neq (str-index ?i ?numero) FALSE )) => (bind ?long (str-length ?numero)) (bind ?posicion (str-index ?i ?numero)) (bind ?numero (str-cat (sub-string 1 (- ?posicion 1) ?numero) ?o (substring (+ ?posicion 1) ?long ?numero))) (printout t "una salida es: " ?numero crlf) (modify ?f1 (numero ?numero)) )

Dados los datos del siguiente esquema,

J uan Rodriguez
casados

Ana Lopez

hijos

J ose Perez

Elena Rodriguez
casados

J avier Rodriguez
casados

Eva Garcia

J aim Perez e

hijos

hijos

Rut Rodriguez

codificar en Clips un sistema que permita inferir: Si una persona tiene un cnyuge que est vivo, entre sus herederos se incluir al cnyuge. Si una persona tiene hijos que estn vivos, estos se incluirn entre sus herederos. Si una persona tiene un descendiente (hijo) que tiene hijos, los hijos del descendiente sern sus herederos siempre que el cnyuge y sus hijos hayan fallecido. Si una persona no tiene hijos ni cnyuge ni padres vivos, sus herederos sern los herederos de sus padres.

Resolucin del ejercicio. (deftemplate persona (slot id (type SYMBOL)) (slot nombre (type STRING)) (slot apellidos (type STRING)) (slot conyuge (type SYMBOL)) ; Id del cnyuge (multislot padres (type SYMBOL) (cardinality 2 2)) ; Ids de los padres (multislot hijos (type SYMBOL)) ; Ids de los hijos (slot vivo (allowed-values SI NO) (default SI))) Se han insertado como vivas a las siguientes personas: (deffacts arbol-genealogico (persona (id juan) (nombre "Juan") (apellidos "Rodrguez") (conyuge ana) (hijos elena javier) (vivo NO)) (persona (id ana) (nombre "Ana") (apellidos "Lpez") (conyuge juan) (hijos elena javier)

(vivo NO)) (persona (id jose) (nombre "Jos") (apellidos "Prez") (conyuge elena) (hijos jaime belen alba) (vivo NO)) (persona (id elena) (nombre "Elena") (apellidos "Rodrguez") (conyuge jose) (padres juan ana) (hijos jaime belen alba) (vivo NO)) (persona (id javier) (nombre "Javier") (apellidos "Rodrguez") (conyuge eva) (padres juan ana) (hijos rut mar) (vivo NO)) (persona (id eva) (nombre "Eva") (apellidos "Garca") (conyuge javier) (hijos rut mar)) (persona (id jaime) (nombre "Jaime") (apellidos "Prez") (padres jose elena) (vivo NO)) (persona (id belen) (nombre "Beln") (apellidos "Prez") (padres jose elena)) (persona (id alba) (nombre "Alba") (apellidos "Prez") (padres jose elena)) (persona (id rut) (nombre "Rut") (apellidos "Rodrguez") (padres javier eva)) (persona (id mar) (nombre "Mar") (apellidos "Rodrguez") (padres javier eva) (vivo NO))) ; Secuenciacin de tareas de bsqueda de herederos (deffacts secuencia-tareas (siguiente buscar-conyuge buscar-hijo)

(siguiente (siguiente (siguiente (siguiente

buscar-hijo buscar-nieto) buscar-nieto buscar-padre) buscar-padre buscar-herederos-padres) buscar-herederos-padres sin-herederos))

; ; REGLAS "EXPERTAS" ; ; Inicializacin. Calcularemos los herederos para cada persona fallecida (defrule inicializar (persona (id ?id) (vivo NO)) => (assert (tarea buscar-conyuge ?id))) ; Si el conyuge est vivo, formar parte de sus herederos (defrule buscar-conyuge (tarea buscar-conyuge ?id) (persona (id ?id) (conyuge ?id-conyuge)) (persona (id ?id-conyuge) (vivo SI)) => (assert (heredero ?id ?id-conyuge))) ; Los hijos vivos, formarn parte de sus herederos (defrule buscar-hijo (tarea buscar-hijo ?id) (persona (id ?id) (hijos $?hijos)) (persona (id ?id-hijo&: (member$ ?id-hijo $?hijos)) (vivo SI)) => (assert (heredero ?id ?id-hijo))) ; Si el cnyuge y todos los hijos han muerto, heredarn sus nietos (defrule buscar-nieto (tarea buscar-nieto ?id) (persona (id ?id) (conyuge ?id-conyuge) (hijos $?hijos)) (persona (id ?id-conyuge) (vivo NO)) (forall (persona (id ?id-hijo&: (member$ ?id-hijo $?hijos))) (persona (id ?id-hijo) (vivo NO))) (persona (id ?id-hijo) (hijos $?nietos)) (persona (id ?id-nieto&: (member$ ?id-nieto $?nietos)) (vivo SI)) => (assert (heredero ?id ?id-nieto))) ; Si no tiene cnyuge ni hijos, heredarn sus padres vivos (defrule buscar-padre (tarea buscar-padre ?id) (persona (id ?id) (conyuge nil) (hijos) (padres $?padres)) (persona (id ?id-padre&: (member$ ?id-padre $?padres)) (vivo SI)) => (assert (heredero ?id ?id-padre))) ; Lo mismo si el cnyuge, todos los hijos y nietos han muerto (defrule buscar-padre2 (tarea buscar-padre ?id) (persona (id ?id) (conyuge ?id-conyuge) (hijos $?hijos) (padres $?padres)) (not (heredero ?id ?)) (persona (id ?id-padre&: (member$ ?id-padre $?padres)) (vivo SI)) => (assert (heredero ?id ?id-padre)))

; Finalmente, si no tiene cnyuge, ni hijos, y sus padres se conocen pero han muerto, ; heredarn los herederos de sus padres (defrule buscar-herederos-padres (tarea buscar-herederos-padres ?id) (persona (id ?id) (conyuge nil) (hijos) (padres $?padres)) (forall (persona (id ?id-padre&: (member$ ?id-padre $?padres))) (persona (id ?id-padre) (vivo NO))) (heredero ?id-padre&: (member$ ?id-padre $?padres) ?heredero-padre& ~Estado) => (assert (heredero ?id ?heredero-padre))) ; Lo mismo si el cnyuge, todos los hijos, nietos y padres han muerto (defrule buscar-herederos-padres2 (tarea buscar-herederos-padres ?id) (persona (id ?id) (conyuge ?id-conyuge) (hijos $?hijos) (padres $?padres)) (not (heredero ?id ?)) (forall (persona (id ?id-padre&: (member$ ?id-padre $?padres))) (persona (id ?id-padre) (vivo NO))) (heredero ?id-padre&: (member$ ?id-padre $?padres) ?heredero-padre& ~Estado) => (assert (heredero ?id ?heredero-padre))) ; Para las personas sin herederos, el Estado se queda con la herencia (defrule sin-herederos (tarea sin-herederos ?id) (not (heredero ?id ?)) => (assert (heredero ?id Estado))) ; ; REGLAS DE CONTROL ; ; Regla con prioridad baja para cambiar de tarea segn la secuenciacin establecida ; en la base de hechos (defrule siguiente-tarea (declare (salience -100)) ?t <- (tarea ?tarea ?id) (siguiente ?tarea ?siguiente) => (retract ?t) (assert (tarea ?siguiente ?id))) ; Elimina la ltima tarea de la base de hechos cuando finaliza (defrule ultima-tarea (declare (salience -100)) ?t <- (tarea ?tarea ?id) (not (siguiente ?tarea ?siguiente)) => (retract ?t))

Se desea desarrollar un sistema basado en conocimiento en Clips para la determinacin de la terapia adecuada a los sntomas encontrados en el paciente. Para ello se dispone del conocimiento recogido en la siguiente tabla. En ella tenemos una columna para las infecciones, que tienen asociada una terapia genrica (por ejemplo paperas tiene asociada una "terapia de paperas genrica") que en algunos casos se particulariza con alguna otra indicacin (por ejemplo para las paperas de adultos). Infeccin Rubeola Paperas Sarampin Sarampin alemn Varicela Escarlatina Sntomas Fiebre de 3 das, glndulas inflamadas y salpullido Fiebre, sudor, glndulas inflamadas y sin salpullido Fiebre, ojos llorosos, manchas de Koplik, tos y salpullido. Fiebre, ojos llorosos, manchas rosadas, tos, glndulas inflamadas en la nuca e inflamacin de odo. Fiebre, costras y picazn. Fiebre, dolor de cabeza, vmitos, salpullido rojo y dolor al tragar. Penicilina para no alrgicos Suero inmunolgico solo para adultos Ganmaglobulina para adultos no mayores de 65 aos Ganmaglobulina si la paciente esta embarazada. Terapia especfica

Resolucin del ejercicio. Desde luego hay otras formas de resolver el problema e incluso con algo ms de estructura en el cdigo, o incluso ahorrando cdigo, pero esta propuesta puede ser aceptable. Los datos iniciales del paciente se introducen como hechos iniciales y se pregunta al usuario por datos complementarios cuando estos son necesarios. (deftemplate paciente (slot adulto (type SYMBOL) (allowed-values SI NO NONE) (default NONE) ) (slot adulto_mayor (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot sexo (type SYMBOL) (allowed-values MASCULINO FEMENINO NONE) (default NONE)) (slot sudor (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot embarazada (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot fiebre (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot fiebre_mas_3_dias (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot glandulas_inflamadas (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot salpullido (type SYMBOL) (allowed-values SI NO) (default NO)) (slot ojos_llorosos (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot manchas_Koplik (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot tos (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot manchas_rosadas (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot glandulas_inflamadas_nuca (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot inflamacion_oido (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot costras (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot picazon (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot dolor_cabeza (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot vomitos (type SYMBOL) (allowed-values SI NO NONE) (default NONE))

(slot salpullido_rojo (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot dolor_tragar (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot alergico_penicilina (type SYMBOL) (allowed-values SI NO NONE) (default NONE)) (slot tipo_infeccion (type SYMBOL)(default NONE)) (slot terapia_especifica (type SYMBOL)(default NONE)) ) (deffacts datos_paciente (paciente (adulto SI) (sexo FEMENINO) (fiebre SI) (ojos_llorosos SI) (manchas_rosadas SI) (tos SI) (glandulas_inflamadas_nuca SI) (inflamacion_oido SI) ) ) (defrule dias_fiebre ?paciente <-(paciente (fiebre SI) (glandulas_inflamadas SI) (salpullido SI) (fiebre_mas_3_dias NONE)

=>

) (printout t crlf "Mas de 3 dias de fiebre? ") (modify ?paciente (fiebre_mas_3_dias (read)))

) (defrule pide_salpullido ?salpullido <(paciente (salpullido SI) (dolor_cabeza SI) (vomitos SI) (dolor_tragar SI) (salpullido_rojo NONE) ) => (printout t "El salpullido es rojo? ") (modify ?salpullido (salpullido_rojo (read))) (printout t crlf) ) (defrule adulto_mayor ?adulto <-(paciente (adulto SI) (tipo_infeccion sarampion) (adulto_mayor NONE) ) => (printout t crlf "Mas de 65 aos? ") (modify ?adulto (adulto_mayor (read))) ) (defrule embarazada ?sexo <-(paciente ) => (sexo FEMENINO) (tipo_infeccion sarampion_aleman) (embarazada NONE)

(printout t crlf "Se encuentra embarazada? ") (modify ?sexo (embarazada (read))) ) (defrule rubeola ?paciente <-(paciente (fiebre_mas_3_dias SI ) (glandulas_inflamadas SI) (salpullido SI) (tipo_infeccion NONE)

=>

) (modify ?paciente (tipo_infeccion rubeola)) (printout t crlf "tiene rubeola")

) (defrule paperas ?paciente <-(paciente

) =>

(fiebre SI ) (sudor SI) (glandulas_inflamadas SI) (salpullido NO) (tipo_infeccion NONE)

) (defrule sarampion ?paciente <-(paciente

(modify ?paciente (tipo_infeccion paperas)) (printout t crlf "tiene paperas") (fiebre SI ) (ojos_llorosos SI) (manchas_Koplik SI) (tos SI) (salpullido SI) (tipo_infeccion NONE)

) =>

) (defrule sarampion_aleman ?paciente <-(paciente

(modify ?paciente (tipo_infeccion sarampion)) (printout t crlf "tiene sarampion") (fiebre SI ) (ojos_llorosos SI) (manchas_rosadas SI) (glandulas_inflamadas_nuca SI) (inflamacion_oido SI) (tipo_infeccion NONE)

) =>

) (defrule varicela ?paciente <-(paciente

(modify ?paciente (tipo_infeccion sarampion_aleman)) (printout t crlf "tiene sarampion aleman") (fiebre SI ) (costras SI) (picazon SI) (tos SI) (tipo_infeccion NONE)

=>

) (modify ?paciente (tipo_infeccion varicela)) (printout t crlf "tiene varicela" crlf)

) (defrule escarlatina ?paciente <-(paciente

(fiebre SI )

) =>

(dolor_cabeza SI) (vomitos SI) (salpullido_rojo SI) (dolor_tragar SI) (tipo_infeccion NONE)

) (defrule suero_paperas_adultos ?paciente <-(paciente (tipo_infeccion paperas ) (adulto SI) (terapia_especifica NONE) ) => (modify ?paciente (terapia_especifica suero_inmunologico)) (printout t crlf "terapia especifica: suero_inmunologico" crlf) ) (defrule ganma_sarampion_menores ?paciente <-(paciente (tipo_infeccion sarampion) (adulto_mayor NO) (terapia_especifica NONE) ) => (modify ?paciente (terapia_especifica ganmaglobulina)) (printout t crlf "terapia especifica: ganmaglobulina" crlf) ) (defrule ganma_sarampion_aleman_embarazada ?paciente <-(paciente (tipo_infeccion sarampion_aleman) (embarazada SI) (terapia_especifica NONE) ) => (modify ?paciente (terapia_especifica ganmaglobulina)) (printout t crlf "terapia especifica: ganmaglobulina" crlf) ) (defrule penicilina_escarlatina_no_alergicos ?paciente <-(paciente (tipo_infeccion escarlatina) (alergico_penicilina NO) (terapia_especifica NONE) ) => (modify ?paciente (terapia_especifica penicilina)) (printout t crlf "terapia especifica: penicilina" crlf) )

(modify ?paciente (tipo_infeccion escarlatina)) (printout t crlf "tiene escarlatina" crlf)

Potrebbero piacerti anche