Descargar

CLIPS – Programación Basada en Reglas (página 3)

Enviado por Pablo Turmero


Partes: 1, 2, 3
edu.red

Reglas Es posible no definir ningún elemento condicional en el antecedente de una regla, situación en la que se usa automáticamente (initial-fact), el hecho que se añade de forma automática tras ejecutar el comando (reset), como elemento condicional.

También puede no haber ninguna acción en el consecuente, con lo que la ejecución de la regla no tiene en ese caso ninguna consecuencia.

En CLIPS pueden realizarse comentarios colocándolos detrás de un punto y coma (;). Todos los caracteres desde el punto y coma hasta el siguiente salto de línea serán considerados comentarios.

edu.red

Reglas La condición o antecedente de una regla puede ser múltiple:

(defrule cielo (color azul) (estamos-en exterior) => (assert (cielo-es despejado)))

Al igual que la acción resultante, p.e. para mostrar un mensaje por la salida estándar con printout:

(defrule cielo (color azul) (estamos-en exterior) => (assert (cielo-es despejado)) (printout t “cielo despejado" crlf) )

Recuerda utilizar reset para limpiar la base de hechos antes de volver a ejecutar o de lo contrario las reglas no se activarán

edu.red

Reglas Como probablemente habrás pensado, no es buena política teclear cada vez todas tus reglas, puedes tenerlas grabadas y cargarlas utilizando File->Load para cargar un fichero clp

Desde la consola se carga un fichero clp por medio del comando load, por ejemplo:

(load “nombre-fichero.clp”)

Se puede almacenar la información actual de los constructores con save, o hacer uso de la interfaz para ello, por ejemplo:

(save “nombre-fichero.clp”)

edu.red

Reglas Ejercicios:

Define una regla Lista las reglas existentes Define una nueva regla con el mismo nombre. ¿Qué ocurre? Define otra regla Lista las reglas existentes Muestra el contenido de una regla Elimina una regla

edu.red

Primeros ejemplos: Hechos iniciales Es frecuente tener que utilizar el mismo conjunto de hechos en cada ejecución del programa, equivalente a variables iniciales en un esquema de programación imperativo. El constructor deffacts permite añadir conocimiento en forma de hechos iniciales, tanto ordenados como no ordenados. Los hechos iniciales definidos, se incluyen en la base de hechos tras un reset de similar forma al hecho por defecto initial-fact.

Por ejemplo:

(deffacts arranque (color azul) (color rojo))

(deffacts gente (datospersona (nombre Samuel) (edad 20) (peso 80) (altura 188) (presion-arterial 130 80)) (datos-persona (nombre Mar) (edad 63) (peso 70) (altura 167) (presion-arterial 180 90)))

edu.red

Primeros ejemplos: Hechos iniciales Los hechos así añadidos se tratan como cualquier otro.

Pueden definirse varios grupos de hechos iniciales, recibiendo cada uno de ellos un identificador al declararse.

El identificador agrupa conceptualmente diferentes hechos sobre el mismo objeto:

(deffacts coche “información del coche” (marca Seat) (modelo Ibiza) (puertas 5) )

edu.red

Primeros ejemplos: Hechos iniciales Como con otros constructores, (list-deffacts) muestra los grupos de hechos iniciales definidos con deffacts, (ppdeffacts ) nos permitirá mostrar el contenido de uno de ellos, y (undeffacts ) suprime los hechos insertados por una orden (deffacts).

CLIPS> (list-deffacts) initial-fact arranque For a total of 2 deffacts.

CLIPS> (ppdeffacts arranque) (deffacts MAIN:: arranque (color azul) (color rojo))

edu.red

Reglas: Hechos iniciales Ejercicios:

Define unos hechos iniciales Define alguna regla que haga uso no sólo de estos hechos iniciales Añade los hechos necesarios para activar la regla Prueba a ejecutar varias veces Lista las definiciones de hechos iniciales Muestra el contenido de una de ellas

edu.red

Primeros ejemplos: Comodines Los hechos utilizados hasta ahora en las reglas eran muy simples, al estar referidos a hechos específicos. Los comodines permiten especificar reglas que encajen para distintos hechos. Definamos los hechos iniciales y regla siguientes:

CLIPS> (deffacts arranque (animal perro) (animal gato) (animal pato)) CLIPS> (defrule animal (animal ?) => (printout t "animal encontrado" crlf) )

CLIPS> (run) animal encontrado animal encontrado animal encontrado

? es un comodín que encaja con cualquier símbolo de un hecho, en este caso el segundo. Nunca puede colocarse en el primer lugar, es por ello válido (padre_de ? ?) pero no (? Juan ?)

edu.red

Primeros ejemplos: Variables Las variables permiten ofrecer aún mayor flexibilidad, ya que ofrecen la posibilidad de ser reutilizadas en la propia regla. Para ello utilizamos ?nombre-var. Un ejemplo es la siguiente regla:

(defrule lista-animales (animal ?nombre) => (printout t ?nombre “ encontrado" crlf))

CLIPS> (reset) CLIPS> (run) animal encontrado pato encontrado animal encontrado gato encontrado animal encontrado perro encontrado

Observa que también se activa la regla anterior, animal, porque no la hemos eliminado

edu.red

Primeros ejemplos: Variables Pueden combinarse el uso de una variable en varias de las condiciones o patrones de una regla. Para ver un ejemplo redefinimos los hechos por defecto con deffacts y tras eliminar todas las reglas, con (clear), introducimos una nueva:

CLIPS> (deffacts arranque (animal perro) (animal gato) (animal pato) (animal tortuga) (sangre-caliente perro) (sangre-caliente gato) (sangre-caliente pato) (pone-huevos pato) (pone-huevos tortuga))

CLIPS> (defrule mamifero (animal ?nombre) (sangre-caliente ?nombre) (not (pone-huevos ?nombre)) => (assert (mamifero ?nombre)) (printout t ?nombre " es un mamífero" crlf))

CLIPS> (run) gato es un mamífero perro es un mamífero

edu.red

Primeros ejemplos: Variables Pueden aparecer varias variables en la condición:

(deffacts arranque (animal perro) (animal gato) (animal pato) (animal tortuga) (sangre-caliente perro) (sangre-caliente gato) (sangre-caliente pato) (pone-huevos pato) (pone-huevos tortuga) (hijo-de perro perrito) (hijo-de gato gatito) (hijo-de pato patito))

(defrule mamifero2 (mamifero ?nombre) (hijo-de ?nombre ?joven) => (assert (mamifero ?joven)) (printout t ?joven " es un mamífero " crlf))

CLIPS> (run) gatito es un mamífero perrito es un mamífero

edu.red

Primeros ejemplos: Variables Sabemos que podemos eliminar un hecho por su índice con retract. Es posible hacerlo en una acción tras conectarlo en una regla con una variable

(defrule elimina ?hecho <- (mamifero ?nombre) => (printout t "eliminando “ ?hecho crlf) (retract ?hecho))

El operador <- almacena la referencia o índice al hecho en la variable ?hecho y la acción recoge esa variable para realizar el retract

CLIPS> (run) gato es un mamífero eliminando perro es un mamífero eliminando

edu.red

Primeros ejemplos: Variables Las variables también pueden emplearse en el consecuente de una regla por medio de la función bind que asigna un valor a una variable, sirviendo ésta como variable temporal:

(defrule suma (num ?x) (num ?y) => (bind ?total (+ ?x ?y)) (printout t ?x " + " ?y " = “ ?total crlf) (assert (total ?total)))

En este caso es una variable temporal que sólo tiene validez dentro de esa regla.

edu.red

Primeros ejemplos: Variables Si se necesitan variables globales, es decir para usar en más de una regla, empleamos defglobal, estas variables deben nombrarse delimitadas por *:

(defglobal ?*var1* = 17 ?*naranjas* = “siete" )

Tras realizar un reset retoman su valor original. (get-defglobal-list) permite obtener la lista, (show-defglobals) también su contenido, (undefglobal var1) elimina la variable var1.

Como el resto de variables, pueden modificar su valor mediante la función bind

(defrule prueba (dato ?) => (bind ?*var1* 3))

edu.red

Primeros ejemplos: Condiciones test permite establecer condiciones que van más allá de los hechos al permitir hacer uso de variables y valores numéricos

(defrule nonecesario (test (> 6 5)) => (printout t “Seis es mayor que cinco" crlf) )

(defrule positivo (valor ?val) (test (> ?val 0)) => (printout t ?val “es positivo" crlf) )

edu.red

Primeros ejemplos: Variables y Condiciones Ejercicios:

Escriba una regla que se active ante hechos del tipo (valor a b) Escriba una regla que se active con hechos del tipo (valor a b), siempre que b sea mayor que a, circunstancia en la que se escribirán los valores de a y b en pantalla. Comprueba el funcionamiento con la siguiente base de hechos:

(valor 6 12) (valor 6 7) (valor 15 30) (valor 14 7)

edu.red

Primeros ejemplos: Entrada y salida La función read permite a CLIPS leer información proporcionada por el usuario. El programa se detiene cuando, a la espera de que el usuario teclee el dato.

Puedes probar con (assert (milectura (read))) que tras leer el dato añade un hecho. Puedes comprobarlo con (facts).

La siguiente regla pregunta por un dato si no está ya disponible en la base de hechos:

(defrule estan-luces-funcionando (not (luces-funcionando ?)) => (printout t "¿Están las luces del coche funcionando (S o N)?") (assert (luces-funcionando (read))))

Si no existe ya un hecho con el símbolo luces-funcionando, el sistema preguntará al usuario por el dato.

edu.red

Primeros ejemplos: Entrada y salida Podemos controlar que la respuesta no siga el formato esperado haciendo

(defrule r3 ?hecho <- (luces-funcionando ?) (not (luces-funcionando S)) (not (luces-funcionando N)) => (printout t “Formato de respuesta incorrecto") (retract ?hecho))

edu.red

Primeros ejemplos: Entrada y salida La función read lee sólo hasta el primer espacio en blanco. Si queremos introducir una serie de elementos, separados por espacios, debemos utilizar readline

(defrule obtener-nombre => (printout t "Su nombre: ") (assert (nombre (readline))))

La función readline retorna una cadena. Evitamos que sea una cadena y se considere un conjunto de símbolos con explode$

(defrule obtener-nombre2 => (printout t "Su nombre: ") (assert (nombre (explode$(readline)))))

edu.red

Primeros ejemplos: Entrada y salida Ejercicios:

Escribir una base de conocimiento CLIPS que lea la respuesta (positiva o negativa a una pregunta) y posteriormente escriba si la respuesta ha sido positiva o negativa.

Escriba una base de conocimiento CLIPS que tras leer una secuencia de tres números enteros, escriba la secuencia si el tercer número es la suma de los dos primeros.

Nota: Se recomienda usar la función (readline) para leer una cadena de entrada, y seguidamente convertirla en un multivalor mediante la función (explode$)

edu.red

Primeros ejemplos: Entrada y salida El comando printout permite realizar operaciones tanto de escritura por pantalla como a fichero

(printout )

stdout Nombre lógico de la salida por pantalla, suele sustituirse por t

CLIPS> (printout t “¡Hola!!" crlf) ¡Hola!

crlf al final establece un fin de línea

edu.red

Primeros ejemplos: Entrada y salida La escritura a fichero con el comando printout, modifica el nombre lógico. Previamente debe abrirse el fichero (modo escritura w, lectura r, lectura y escritura r+, y apéndice a). Recuerda indicar la ruta correctamente

(open "mifichero.txt" F1 "w“) ;abre en modo escritura indicando w

(printout F1 “dato 23") ; escribe datos en fichero

(close F1) ; cierra el fichero

edu.red

Primeros ejemplos: Entrada y salida El comando read lee del fichero indicado un solo campo. Para leer una línea empleamos readline

(open "mifichero.txt" F1) ; indicando r o nada abre en modo lectura

(read F1) ; lee hasta primer espacio

(read F1) ; lee hasta siguiente espacio

(close F1) ; cierra fichero

stdin Nombre lógico de la entrada por defecto empleada por read y readline. Existen también comandos como rename y remove que permiten respectivamente renombrar y eliminar un fichero

edu.red

Primeros ejemplos: Entrada y salida Un ejemplo de lectura y escritura

CLIPS> (open "data.txt" misdatos "w") TRUE CLIPS> (printout misdatos “lunes martes") CLIPS> (close) TRUE CLIPS> (open "data.txt" misdatos) TRUE CLIPS> (readline misdatos) "lunes martes" CLIPS> (readline misdatos) EOF CLIPS> (close) TRUE

edu.red

Primeros ejemplos: Estructuras de control Sentencia condicional

( if () then () [else ()] )

Sentencia repetitiva o bucle

(loop-for-count ( ) [do] )

(while () [do] () )

Los elementos entre corchetes son opcionales

edu.red

Primeros ejemplos: Estructuras de control (defrule continua-bucle ?bucle <- (bucle) => (printout t “¿Continuar?” crlf) (bind ?resp (read)) (if (or (eq ?resp si)(eq ?resp s)) then (retract ?bucle) ; Ante una respuesta positiva quitamos y (assert (bucle)) ; añadimos el hecho else (retract ?bucle) ; No continuamos, simplemente eliminamos (halt) ) )

edu.red

Primeros ejemplos: Estructuras de control Prueba los bucles con:

(loop-for-count 2 (printout t "Hola mundo" crlf))

(loop-for-count (?i 0 2) do (loop-for-count (?j 1 3) do (printout t ?i " " ?j crlf)))

(defrule rwhile => (bind ? 4) (while (> ?v 0) ; antes ?v debe tener un valor (printout t “v es " ?v “ " crlf) (bind ?v (- ?v 1))) )

edu.red

Primeros ejemplos: Estructuras de control Ejercicios

Realizar un programa CLIPS que tras leer un número indique si es positivo o negativo empleando la estructura condicional Realizar un programa en CLIPS que tras leer un número entero escriba todos los valores enteros entre 0 y ese número Tras almacenar un número en una variable global, se pide realizar un programa en CLIPS que permita al usuario introducir números enteros entre 1 y 100 hasta que adivine el número que el sistema tiene almacenado. La entrada de números se hará mediante la sentencia read. El programa indicará por pantalla si el número buscado es mayor o menor que el introducido. La condición de parada se produce cuando el usuario acierte el número en cuestión.

Nota: Para generar números aleatorios usa: (random [ ]) (seed (round (time))) ;modifica la semilla

edu.red

Primeros ejemplos: Operadores lógicos y matemáticos Dos patrones en una regla se conectan de forma automática con un and, ya que requiere que ambos se cumplan para que la regla se dispare. Este ejemplo, visto anteriormente, incluye el uso del not

(defrule mamifero (animal ?nombre) (sangre-caliente ?name) (not (pone-huevos ?nombre)) => (assert (mamifero ?nombre)) (printout t ?nombre " es un mamífero" crlf))

Nos faltaría ver un ejemplo de uso de or:

(defrule coge-paraguas (or (tiempo lloviendo) (tiempo nevando)) => (assert (paraguas necesario)))

Que traducimos por “Si está lloviendo o nevando, coge el paraguas”, haciendo uso de sólo una regla ya que también podrían utilizarse dos independientes con el mismo efecto.

edu.red

Primeros ejemplos: Operadores lógicos y matemáticos Observa que el operador or está colocado antes de los argumentos y no entre ellos, es la denominada notación prefijo (prefix notation) y la utilizan todos los operadores en CLIPS. Para por ejemplo realizar una suma, la mayoría de los lenguajes, usarían 5 + 7 (infix notation), mientras que CLIPS requiere (+ 5 7).

Algunos ejemplos:

CLIPS>(+ 5 7) 12 CLIPS>(- 5 7) -2 CLIPS>(* 5 7) 35 CLIPS>(/ 5 7) 0.7142857142857143

Expresiones más complicadas como 10+4*19-35/12:

CLIPS> (+ 10 (- (* 4 19) (/ 35 12)))

edu.red

Primeros ejemplos: Funciones Una función es un algoritmo identificado con un nombre que puede o no devolver valores (uni o multicampo). Se definen con el constructor deffunction, existiendo dos tipos:

Funciones internas: Definidas en CLIPS Funciones externas: Escritas en un lenguaje distinto a CLIPS

(deffunction signo (?num) (if (> ?num 0) then (return 1)) (if (< ?num 0) then (return -1)) 0)

Las funciones se llaman usando la notación prefija entre paréntesis como ya hemos visto con los operadores aritméticos y lógicos:

CLIPS> (signo 3) 1 El comando list-deffunctions permite listar las funciones definidas

edu.red

Primeros ejemplos: Funciones Cuando una función se llama a sí misma hablaremos de recursividad:

(deffunction sumatorio (?num) ( if (> ?num 0) then (return (+ ?num (sumatorio (- ?num 1)))) else 0) )

CLIPS> (sumatorio 5) 15

edu.red

Elementos básicos: Funciones Ejercicios

Escribe una función que calcule el factorial de un número

Escribe función en CLIPS para calcular y mostrar por pantalla el máximo común divisor (mcd) de dos números obtenidos a través del teclado, asumiendo que son positivos. El mcd de estos números se calcula teniendo en cuenta:

Si a = b mcd( a, a ) = a Si a > b mcd( a, b ) = mcd( a-b, b ) Si a < b mcd( a, b ) = mcd( a, b-a )

edu.red

Elementos básicos: Funciones Ejercicios

El mínimo común múltiplo (mcm) de dos números enteros a y b se puede calcular a partir del máximo común divisor (mcd) de dichos números tal que mcm(a,b)=a*b /(mcd(a,b)). Escribe una función en CLIPS para calcular el mcm de dos números enteros que siga los siguientes pasos:

Inicialmente se leen dos números a y b del teclado Seguidamente se calcula el mcd de estos números Finalmente calcula el mcm y se muestra el resultado en pantalla

Partes: 1, 2, 3
 Página anterior Volver al principio del trabajoPágina siguiente