Documentos de Académico
Documentos de Profesional
Documentos de Cultura
En todos los capítulos se presentan ejemplos para cada tema tratado y se proponen
ejercicios para que el estudiante compruebe el nivel de apropiación alcanzado.
En los albores del nuevo siglo, el desarrollo de software debe responder a los
requerimientos crecientes de usuarios inmersos en una sociedad que cada día se apoya
más en herramientas tecnológicas, especialmente en el campo de las TICS. Un aspecto
relevante es la incorporación de funcionalidades “inteligentes” en las soluciones
informáticas, repercutiendo en el crecimiento acelerado de la demanda por productos de
software diseñados para responder a tal expectativa. Los cursos de Inteligencia Artificial e
Ingeniería del Conocimiento, abordan el reto mencionado ofreciendo a los Ingenieros de
Sistemas de la UCC las herramientas necesarias para incursionar con éxito en un campo de
acción que ofrece inmejorables oportunidades de desarrollo profesional.
Durante los últimos diez años los autores han orientado los cursos mencionados
anteriormente, identificando dificultades de los estudiantes para alcanzar un adecuado
desempeño, siendo las más significativas la carencia de material de apoyo que responda
gradualmente a la complejidad de los temas abordados y la confusión que se puede
generar, si no se tienen bases sólidas en el írea de programació, al enfrentar un paradigma
de construcción de software diferente a los enfoques convencionales.
Este capítulo describe algunos aspectos fundamentales que facilitan una primera
aproximación a CLIPS, procurando evidenciar las similitudes y diferencias con respecto a
otros lenguajes de programación, aclarando que para entender y usar correctamente
CLIPS no es indispensable tener conocimientos previos de otras herramientas de
programación.
Al igual que cualquier otro lenguaje, CLIPS tiene como componentes primarios los
símbolos que forman su alfabeto o juego de caracteres: las letras del alfabeto inglés
(mayúsculas y minúsculas), los dígitos decimales (del 0 al 9) y los caracteres especiales
(también llamados símbolos de espaciado y puntuación), formados por los demás
símbolos gráficos del código ASCII. Es importante resaltar que CLIPS establece diferencia
entre letras minúsculas y mayúsculas.
A partir de los símbolos del alfabeto se forman identificadores o palabras que pueden ser
reservadas, si tienen un significado concreto dentro del lenguaje, o del usuario, si se crean
para responder a necesidades específicas dentro de un programa, como por ejemplo:
darle nombre a una variable, a una regla o a una función. Una diferencia radical de CLIPS
con respecto a otros lenguajes consiste en que los identificadores no necesariamente
deben iniciar con una letra y pueden incluir algunos caracteres especiales; a manera de
ejemplo y como se verá posteriormente, el símbolo + se puede utilizar como el nombre de
una función.
En principio existen dos tipos de valores: números y símbolos; los números pueden ser
enteros o de punto flotante (reales) y los símbolos pueden ser símbolos propiamente
dichos o cadenas de caracteres (símbolos encerrados entre comillas dobles).
A continuación se presenta una lista de los tipos de datos primitivos de CLIPS, note que las
palabras reservadas que los identifican se escriben con mayúsculas.
1.5 Funciones.
(nombre-de-función lista-de-argumentos)
Los valores de los argumentos se separan por uno o más espacios en blanco.
1.6 Constructores.
Los constructores son sentencias que sirven para crear elementos tales como: objetos,
reglas, bloques de hechos, funciones entre otros. El nombre de los constructores inicia
con el prefijo def, algunos ejemplos son: deftemplate, deffacts y defrule.
CLIPS>
La sintaxis de CLIPS exige que todas las sentencias se encierren entre paréntesis.
Por ejemplo, para salir de CLIPS se puede utilizar la sentencia (exit).
CLIPS>(exit)
Un comentario inicia con el carácter punto y coma (;) y se extiende hasta el final de la
línea.
1.9 Ejercicios.
Este capítulo presenta una relación de las principales funciones provistas por CLIPS. Se
destaca como diferencia sustancial con otros lenguajes, especialmente con sus ancestros
C/C++, el hecho de contar con pocos operadores; la mayoría de ellos se remplazan por
llamados a funciones.
Se utilizan funciones para efectuar las operaciones aritméticas, sin ningún tipo de
jerarquía entre ellas.
Se deben llamar en notación prefija, utilizando paréntesis para agrupar las operaciones en
el caso de expresiones complejas.
Ejemplo 1.
CLIPS> (- 5 70)
-65
CLIPS> (* 4 8)
32
CLIPS> (/ 4 8)
0.5
CLIPS> (+ -1 3)
2
CLIPS> (/ (+ 2 3) (* 4 2))
0.625
CLIPS> (/ 15 5)
3.0
Ejemplo 2.
CLIPS> (+ 1 5 -2 4)
8
CLIPS> (- 5 2 3 7 -1)
-6
CLIPS> (* 2 5 -2)
-20
CLIPS> (/ 8 3 5 8)
0.0666666666666667
Observe que en todos los casos el resultado de la función / es un valor de punto flotante.
CLIPS> (div 5 2)
2
CLIPS> (div 5 8)
0
CLIPS> (div 8 3 5 8)
0
CLIPS> (max 1 7 -8 4)
7
CLIPS> (min 1 7 -8 4)
-8
2.2.5 **, devuelve el valor del primer argumento elevado a la potencia indicada por el
segundo argumento.
CLIPS> (** 4 2)
16.0
CLIPS> (** 2 0.5)
1.4142135623731
CLIPS> (** 27 (/ 1 3))
3.0
CLIPS> (** 4 -0.5)
0.5
CLIPS> (sqrt 4)
2.0
2.2.7 mod, devuelve el residuo de la división del primer argumento entre el segundo.
CLIPS> (mod 17 3)
2
CLIPS> (mod -9 4)
-1
CLIPS> (mod 9 -4)
1
CLIPS> (exp 1)
2.71828182845905
CLIPS> (pi)
3.14159265358979
CLIPS> (random)
41
CLIPS> (random)
18467
2.2.15 time, devuelve un valor real que representa el número de segundos transcurridos
desde un tiempo de referencia del sistema.
CLIPS> (time)
494.851
CLIPS> (time)
524.323
CLIPS> (time)
543.351
Al igual que en el caso de los expresiones aritméticas, se utilizan funciones que permiten
obtener el efecto de los operadores relacionales; no existen niveles de jerarquía por
defecto y se requieren paréntesis para agrupar las operaciones en expresiones complejas.
Ejemplo 3.
CLIPS> (= 2 (+ 1 1))
TRUE
CLIPS> (> 2 9)
FALSE
CLIPS> (<> 5 3)
TRUE
CLIPS> (<= (* 2 3) (/ (+ 4 16) 2))
TRUE
Como se mencionó anteriormente, en realidad <, <=, >, >=, = y <> no son operadores sino
funciones que se pueden llamar con dos o más argumentos. Su aplicación más
generalizada se ilustra a continuación:
Ejemplo 4.
CLIPS> (< 1 5 4 2)
FALSE
CLIPS> (< 2 6 7 10)
TRUE
CLIPS> (<= 5 7 5 (* 2 3))
FALSE
CLIPS> (> 2 (/ (+ 4 2) 4) 0)
TRUE
CLIPS> (>= 5 1 3)
FALSE
CLIPS> ( = (+ 4 2) 6 (* 2 3))
TRUE
CLIPS> (<> 1 2 0)
TRUE
CLIPS> (<> 1 2 (+ 2 -1))
FALSE
Como se observa en cada caso, la relación se aplica de manera continua sobre los
argumentos formando parejas de la forma (an, an+1).
2.4.12 eq, devuelve verdadero si su primer argumento es igual en tipo y valor a todos los
argumentos subsecuentes, falso en caso contrario.
2.4.13 neq, devuelve verdadero si su primer argumento no es igual en tipo y valor a todos
los argumentos subsecuentes, falso en caso contrario.
2.5.1 str-cat, devuelve todos sus argumentos concatenados como una cadena.
2.5.2 str-compare, compara en forma lexicográfica sus dos argumentos, devuelve 0 si son
iguales, 1 si el primero es mayor que el segundo o -1 si el primero es menor que el
segundo.
Observe que str-compare permite comparar cadenas con símbolos, sin establecer
diferencia entre los dos tipos de datos.
2.6.3 lowcase, devuelve su argumento (cadena o símbolo) después de convertir todas las
letras mayúsculas en minúsculas.
2.6.4 upcase, devuelve su argumento (cadena o símbolo) después de convertir todas las
letras minúsculas en mayúsculas.
Todas las funciones que se describen a continuación utilizan radianes como unidad de
medida para su argumento.
CLIPS> (cos 0)
1.0
CLIPS> (cos 3.1416)
-0.999999999973015
CLIPS> (acos 0)
1.5707963267949
CLIPS> (acos 1)
0.0
2.8 Ejercicios.
1. Utilice CLIPS para determinar el valor de cada una de las siguientes expresiones:
a) 20+(4*12-100/45)
b) (log(54)-ln(22))*e4
c) 63 < 92—11*3
2. ¿Qué resultado se obtiene al dividir por cero?
3. ¿Qué resultado se obtiene en CLIPS al calcular la raíz cuadrada de un número
negativo?
4. La función integer, ¿trunca o redondea el valor de su argumento?
5. Utilice la función sub-string para determinar:
a) ¿Qué sucede si el tercer argumento es un símbolo?
b) ¿Qué ocurre si el primer argumento es mayor que el segundo?
c) ¿Qué ocurre si el primer argumento es menor o igual que cero?
d) ¿Qué ocurre si el segundo argumento es mayor que la longitud del tercer
argumento?
6. Construya una expresión para calcular el factorial de un entero determinado.
7. ¿Cuál es el dominio de los argumentos para funciones como acos y acosh?
Capítulo 3: HECHOS ORDENADOS.
Este capítulo aborda el concepto de hecho resaltando su importancia para los Sistemas
Basados en Conocimiento, describe las funciones básicas para su manipulación y permite
observar la gestión que realiza CLIPS sobre la memoria de trabajo (lista de hechos).
Un hecho se define como el conjunto de valores que describe de la forma más detallada
posible un aspecto específico de un problema relacionado con un dominio particular de
conocimiento. Para un Sistema Basado en Conocimiento (SBC), la lista de hechos
corresponde al conjunto de datos e información que describe el estado actual del sistema
sobre el cual se aplica el conocimiento.
El primer paso para trabajar con hechos consiste en agregarlos (afirmarlos) al
componente llamado lista de hechos. A cada hecho se le asigna dinámicamente una
dirección en la lista, cuyo valor es único e irrepetible.
Es importante tener en cuenta que, por defecto, no se admiten hechos duplicados.
Ejemplo 1.
<Fact-3>
En primer lugar se agrega un hecho ordenado de la relación Cifra cuyo valor es 1, posteriormente
se agregan dos hechos más de la mima relación, con valores 2 y 3 respectivamente, y un hecho de
la relación Monto cuyo valor corresponde al símbolo Tres. Siempre se muestra la dirección del
último hecho agregado a la lista, note que la dirección del primer hecho es 0.
Ejemplo 2.
En este caso, el mensaje FALSE permite comprobar que, por defecto, CLIPS no acepta el intento
de agregar un hecho que ya existe.
El tipo de datos correspondiente a los valores de un hecho ordenado se establece por CLIPS en
tiempo de ejecución según el contexto; en el ejemplo anterior, los valores asociados con la
relación Cifra son enteros y el asociado con la relación Monto es un símbolo.
Ejemplo 3.
CLIPS> (facts)
f-0 (Cifra 1)
f-1 (Cifra 2)
f-2 (Cifra 3)
f-3 (Monto Tres)
For a total of 4 facts.
(facts entero), muestra el contenido de la lista a partir de la posición indicada por el entero
especificado.
Ejemplo 4.
CLIPS> (facts 2)
f-2 (Cifra 3)
f-3 (Monto Tres)
For a total of 2 facts.
(facts entero1 entero2), muestra los hechos comprendidos entre entero1 y entero2.
Ejemplo 5.
CLIPS> (facts 0 2)
f-0 (Cifra 1)
f-1 (Cifra 2)
f-2 (Cifra 3)
For a total of 3 facts.
CLIPS> (facts 2 2)
f-2 (Cifra 3)
For a total of 1 fact.
Este formato permite mostrar únicamente el(los) hecho(s) seleccionado(s). El primer argumento
indica el hecho inicial y el segundo el final.
(facts entero1 entero2 entero3), muestra como máximo entero3 hechos comprendidos entre las
posiciones entero1 y entero2.
Ejemplo 6.
CLIPS>
(facts 0 3 2)
f-0 (Cifra 1)
f-1 (Cifra 2)
For a total of 2 facts.
Ejemplo 7.
CLIPS> (retract 3)
CLIPS> (facts)
f-0 (Cifra 1)
f-1 (Cifra 2)
f-2 (Cifra 3)
For a total of 3 facts
Ejemplo 8.
CLIPS> (retract 0 2)
CLIPS> (facts)
f-1 (Cifra 2)
For a total of 1 fact.
Elimina los hechos ubicados en las direcciones 0 y 2; observe que se elimina realmente la dirección
correspondiente; es decir, los hechos restantes no se desplazan.
Para eliminar todos los hechos se utiliza (retract *).
Ejemplo 9.
CLIPS> (clear)
CLIPS> (facts)
CLIPS> (assert (Resultado (+ 4 3 7)))
<Fact-0>
CLIPS> (facts)
f-0 (Resultado 14)
For a total of 1 fact.
Note que el resultado del primer comando facts es nulo porque inmediatamente antes se ejecutó
el comando clear para dejar vacía la lista de hechos. Posteriormente se agrega un hecho ordenado
de la relación Resultado cuyo valor se obtiene de un cálculo aritmético.
A continuación se muestra un ejemplo que agrega un hecho ordenado cuyo valor se obtiene del
resultado de una expresión lógica.
Ejemplo 10.
En los ejemplos anteriores, cada hecho está formado por un solo valor; resulta importante
destacar que por definición, cualquier hecho ordenado tiene asociada una lista donde se pueden
colocar cero o más valores.
Analice cuidadosamente el siguiente ejemplo.
Ejemplo 11.
CLIPS> (clear)
CLIPS> (assert (Nulo)
(Sencillo uno)
(Multiple uno dos tres))
<Fact-2>
CLIPS> (facts)
f-0 (Nulo)
f-1 (Sencillo uno)
f-2 (Multiple uno dos tres)
For a total of 3 facts.
En primer lugar se deja vacía la lista de hechos (comando clear), a continuación se utiliza el
comando assert para agregar tres hechos ordenados, el primero corresponde a la relación Nulo
(no se asocia ningún valor), el segundo corresponde a la relación Simple (se le asocia un solo valor)
y el tercero corresponde a la relación Multiple (tiene asociados tres valores); por último, el
comando facts permite visualizar el contenido de la lista de hechos.
Posteriormente se explicará la forma de acceder y manipular los valore de una lista.
3.6 Ejercicios.
La definición de una plantilla puede establecer características específicas para los campos
(ranuras) que forman una relación.
Ejemplo 1.
El ejemplo define la plantilla Relacion formada por tres campos. Los campos pueden ser de tipo
spot, si van a contener un solo valor, o multislot, si van a contener cero o más valores. Como se ha
mencionado anteriormente, a los hechos ordenados se les asocia un campo de tipo multislot sin
nombre, propiedad que hace posible definir hechos ordenados con cero o más valores como se
muestra a continuación.
Ejemplo 2.
Se pueden definir todas las plantillas que sean necesarias y cada una de ellas puede contener
cualquier cantidad de campos slot (campos sencillos) y multislot (multicampos).
Sobre los hechos de plantilla aplican las mismas funciones y comandos utilizados para los
hechos ordenados.
Ejemplo 3.
El comando assert afirma el hecho ordenado Ordenado1 que no tiene asociado ningún valor (su
campo multislot se encuentra vació), posteriormente agrega dos hechos de la plantilla Relacion y
por último agrega el hecho ordenado Ordenado2 con varios valores en su campo multislot. El
comando facts muestra los hechos cargados en la lista de hechos.
Como se puede apreciar en el comando assert, el orden en que se incluyen los campos de una
plantilla es irrelevante.
El tipo de datos correspondiente a cada campo se establece en tiempo de ejecución si no se
especifica de manera explicita al definir la plantilla, característica que puede dar lugar a
ambigüedades.
Ejemplo 4.
CLIPS> (retract *)
CLIPS> (assert (Relacion (Campo1 4.0125))
(Relacion (Campo1 "Confusion")))
<Fact-5>
CLIPS> (facts)
f-4 (Relacion (Campo1 4.0125) (Campo2) (Campo3 nil))
f-5 (Relacion (Campo1 "Confusion") (Campo2) (Campo3 nil))
For a total of 2 facts.
Primero se eliminan todos los hechos de la lista y después se agregan dos hechos de la plantilla
Relacion. Recuerde que las direcciones de los hechos son únicas e irrepetibles; los nuevos hechos
se encuentran en las direcciones 4 y 5 respectivamente.
Observe que el valor de Campo1 en el hecho de la dirección 4 es de punto flotante mientras que
ese mismo campo en el hecho de la dirección 5 es una cadena de caracteres; situación que puede
dar lugar a interpretaciones ambiguas e incluso generar errores al procesar los valores.
El ejemplo anterior permite evidenciar que el orden de los campos no solo es irrelevante sino que
además, no es obligatorio incluirlos todos. Si se omite un campo multislot como Campo2, se
asume por defecto como una lista vacía; por el contrario, los campos de tipo slot se asumen como
símbolos y por defecto se les asigna el valor nil (nulo).
Para evitar ambigüedades y hacer precisas las definiciones de las plantillas, se pueden incluir
restricciones en el constructor deftemplete.
4.3.1 type, permite especificar el tipo de datos para los valores de un campo.
4.3.2 range, permite establecer los límites inferior y superior para los valores de un campo
numérico. La construcción ?VARIABLE se refiere al valor más grande o más pequeño según se
utilice como límite superior o inferior, los valores específicos dependen del tipo de datos y del
hardware que se esté utilizando.
4.3.3 cardinality, solamente aplica para campos multislot y permite establecer la cantidad mínima
y máxima de valores para campos de este tipo. Si se usa ?VARIABLE como cantidad mínima se
asume como cero.
4.3.4 allowed-symbols, permite establecer la lista de posibles valores para un campo de tipo
símbolo. Análogamente se pueden utilizar allowed-strings, allowed-lexemes, allowed-numbers,
allowed-integers, allowed-floats y allowed-values entre otras; las últimas cuatro formas no se
pueden utilizar si se incluye la restricción range.
Ninguna restricción es obligatoria pero su uso es de gran importancia para la validación de datos.
Después de establecer una restricción cualquier intento de afirmar hechos que la contradigan
generará error.
Ejemplo 5.
CLIPS> (clear)
CLIPS> (deftemplate Estudiante (slot Codigo (type INTEGER)
(range 0 ?VARIABLE))
(multislot Nombre (type STRING)
(cardinality 1 2))
(slot Promedio (type FLOAT)(range 0.0 5.0))
(slot Sexo (type SYMBOL)
(allowed-symbols F M)))
CLIPS> (assert (Estudiante (Codigo 240)
(Nombre "Adriana Marcela")
(Sexo F)))
<Fact-0>
CLIPS> (facts)
f-0 (Estudiante (Codigo 240) (Nombre "Adriana Marcela") (Promedio 0.0) (sexo F))
For a total of 1 fact.
Ejemplo 6.
Si la definición de un campo numérico incluye la restricción range y el valor del campo es omitido,
por defecto se toma el límite inferior, pero si este límite se ha especificado con ?VARIABLE se
toma el límite superior (campo C1).
Por otra parte, el campo C2 es un multislot que no incluye la restricción type y por lo tanto se
asume, en principio, que sus componentes son de tipo SYMBOL; la restricción cardinality indica
que C2 debe tener como mínimo tres componentes, al ser omitido en el comando assert, se
incluyen tres valores nil por defecto.
Por último, resulta importante observar que es posible asociar varias restricciones de tipo allowed
a un campo, como ocurre con C3 en R1. El valor de C3 puede ser un símbolo o un entero tomado
de la respectiva lista.
Ejemplo 7.
Ejemplo 8.
El siguiente ejemplo muestra una variante de la restricción default que puede resultar útil.
Ejemplo 9.
CLIPS> (clear)
CLIPS> (deftemplate Estudiante (multislot Nombre (cardinality 2 4)
(default ?NONE))
(slot Asignatura (type STRING)
Capítulo 5: CONSTRUCCIÓN Y EJECUCIÓN DE REGLAS
Las reglas constituyen la forma básica de representación del conocimiento en CLIPS, interactúan
con los hechos e instancias a través del mecanismo de inferencia para generar acciones
conducentes a la solución de problemas utilizando el método conocido como encadenamiento
hacia delante.
Este capítulo aborda algunas consideraciones para la construcción de reglas y describe los
comandos para su utilización.
Las reglas son construcciones análogas a la sentencia if de otros lenguajes y por lo tanto se
ajustan al formato:
SI (condición)
ENTONCES (acción)
Es importante tener en cuenta que, para el mismo conjunto de hechos y objetos, cada regla se
comprueba una sola vez siendo posible que se causen varias activaciones, cualquier modificación
de los hechos provocará una nueva comprobación de todas las reglas; el mecanismo de inferencia
se encarga de efectuar y controlar esta operación.
5.2.1 defrule, es el constructor que sirve para definir una regla siguiendo el formato:
Ejemplo 1.
El mecanismo de inferencia busca en la lista de hechos ocurrencias de la relación Prueba con valor
igual a cero para activar la regla.
Ejemplo 2.
CLIPS>(defrule Regla2
=> (clear)
)
5.3.1 agenda, comando para visualizar las reglas que se encuentran activas. El comando indica la
prioridad de la regla (cero por defecto) y los hechos que causaron la activación.
Ejemplo 3.
Ejemplo 4.
Como se puede apreciar, la acción causada por el consecuente de la regla se ha ejecutado (los
hechos se han modificado).
Ejemplo 5.
El resultado del comandó agenda indica que las dos reglas se activan por el hecho de la dirección
1.
Opcionalmente, el comando run permite especificar el número máximo de reglas activas que
serán ejecutadas.
Ejemplo 6.
5.5.1 watch activations, permite visualizar el orden en que se van activando las reglas.
5.5.2 watch rules, permite visualizar el orden en que se ejecutan (disparan) las reglas.
5.5.3 unwatach all, permite desactivar el efecto del comando watch para todos los elementos
activos. Alternativamente se pueden utilizar unwatch activations y unwatch rules.
Ejemplo 7.
Observe que el proceso de verificación de antecedentes para determinar que reglas se activan,
solo se inicia después de ejecutar el comando reset (es necesario que los hechos estén
disponibles). Aunque este aspecto se trata en detalle posteriormente, se destaca que el orden de
las activaciones no coincide con el orden de aparición de las reglas en el programa, como ocurre
en los lenguajes convencionales; en este caso el orden de activación depende de la estrategia de
resolución de conflictos en uso.
5.5.3 printout <nombre-dispositivo>, permite dirigir la salida del programa hacia el dispositivo
especificado (t para referirse a la salida estándar (stdout) que normalmente es la pantalla).
Ejemplo 8.
Ejemplo 9.
CLIPS> (defrule Regla1 => (printout t "Existen hechos" crlf "Se ejecuta la
Regla1" ))
CLIPS> (run)
Ejemplo 10.
CLIPS> (defrule Regla1 =>(printout t "Existen hechos" crlf "Se ejecuta la
regla1" crlf ))
CLIPS> (reset)
CLIPS> (run)
Existen hechos
Se ejecuta la regla1
CLIPS> (facts)
f-0 (initial-fact)
For a total of 1 fact.
Cuando no existe ningún constructor de hechos iniciales, el comando reset carga el hecho inicial
cuya existencia se comprueba si el antecedente de una regla es vacío. Es decir, si el antecedente
de una regla no contiene condiciones se evaluará como verdadero solamente si existe el hecho
inicial.
5.5.4 list-defrules, produce un listado de las reglas definidas actualmente en el ambiente de CLIPS.
Ejemplo 11.
Ejemplo 12.
Ejemplo 13.
Ejemplo 14.
Al ejecutar matches por primera vez, se observa que el antecedente de R2 se relaciona con el
hecho de la dirección 1 y se produce una activación. Como las reglas solo se activan una vez para
el mismo conjunto de hechos, la segunda ejecución de matches muestra el hecho relacionado con
el antecedente de R2 pero la regla no se activa.
Ejemplo 15.
En este caso el antecedente se relaciona con hechos de la plantilla FIGURA, específicamente con
un valor determinado del campo CLASE
.
5.5.8 refresh, permite que la regla especificada se vuelva a activar para el mismo conjunto de
hechos.
Ejemplo 16.
5.6 Ejercicios.
1. Complete el ejercicio 4.4, agregando una regla que muestre un mensaje por cada persona
que cumplan con un determinado parentesco.
2. Utilice como base el ejercicio 4.5 para agregar un hecho ordenado de la relación
ENCONTRADO ppor cada rectángulo cuya área sea igual a un valor especifico.
3. ¿Cuantas veces se ejecuta la regla R1 del siguiente programa?
¿Por qué?
(reset)
(defrule R1 => (printout t "Se ejecuto la rela" crlf)
(reset))
(run)
5. A partir del ejercicio 4.9 construya una regla para borrar un hecho específico de la lista.
Capítulo 6: ELEMENTO CONDICIONAL PATRON
En este capítulo se explica la construcción de reglas más flexibles y complejas. Se abordarán los
conceptos de comodín y variable, la entrada de datos y las restricciones conectivas.
Cada una de las partes que constituyen el antecedente de una regla se denomina elemento
condicional (EC). Para que una regla se active todos los elementos condicionales que forman el
antecedente deben ser satisfechos por la existencia de hechos u objetos apropiados. Si no existe
ningún EC explicito, la activación estará sujeta a la presencia del patrón (inicial-fact) o (inicial-
object).
6.2 EC patrón.
Se compone de restricciones de campo, comodines y/o variables que sirven para determinar las
entidades patrón (hechos u objetos) que lo satisfacen.
Todo EC patrón debe iniciar con un símbolo utilizado por CLIPS para determinar si el patrón se
aplica sobre hechos ordenados, hechos de plantilla o instancias.
Una restricción de campo puede estar formada por una o más constantes (restricción literal),
comodines, variables o por varias restricciones conectadas entre si.
Ejemplo 1.
La regla se activa cada vez que un hecho satisface el patrón. El antecedente esta formado por un
EC patrón muy sencillo, el símbolo PATRON (identifica hechos ordenados) y una restricción de
campo literal (la constante 5).
6.2.1 Comodines.
Sirven para indicar que un campo simple o un grupo de campos serán confrontados
satisfactoriamente por cualquier valor.
El carácter comodín para un campo simple es ? y para un campo múltiple es $?. Los campos de
tipo slot y multislot que no se especifiquen en un EC patrón, serán confrontados de manera
implícita por ? y $? respectivamente.
Ejemplo 2.
CLIPS> (deffacts I
(C ROJO VERDE AZUL)
(C ROJO AZUL VERDE)
(C VERDE ROJO AZUL)
(C VERDE AZUL ROJO)
(C AZUL ROJO VERDE)
(C AZUL VERDE ROJO))
CLIPS> (reset)
CLIPS> (defrule R1
(C ? AZUL ?)=>)
CLIPS> (defrule R2
(C ? ? AZUL)=>)
CLIPS> (matches R1)
Matches for Pattern 1
f-2
f-4
Activations
f-4
f-2
CLIPS> (matches R2)
Matches for Pattern 1
f-1
f-3
Activations
f-3
f-1
Utilizando el comodín para campos simples (?), la regla R1 busca el símbolo AZUL en la segunda
posición de la lista C, la regla R2 busca AZUL en la tercera posición de la lista.
Ejemplo 3.
CLIPS> (deffacts I
(C ROJO NARANJA VERDE AZUL)
(C ROJO AZUL VERDE)
(C VERDE AZUL)
(C VERDE AZUL ROJO)
(C AZUL)
(C AZUL VERDE ROJO))
CLIPS> (reset)
CLIPS> (defrule R1
(C $? AZUL )=>)
CLIPS> (matches R1)
Matches for Pattern 1
f-1
f-3
f-5
Activations
f-5
f-3
f-1
Con la ayuda del comodín para campos múltiples ($?), la regla R1 busca el símbolo AZUL en la
última posición de la lista C, observe que la búsqueda es exitosa para ocurrencias de C con
cualquier longitud.
6.2.2 Variables.
Sirven para almacenar valores que serán utilizados posteriormente. CLIPS permite la utilización de
variables asociadas con reglas, teniendo en cuenta los siguientes aspectos:
Ejemplo 4.
Ejemplo 5.
CLIPS> (deffacts Inicio (Prueba Primer Valor)(Prueba Segundo Valor)(Prueba Tercer Valor))
CLIPS> (defrule R1 (Prueba $?valor)
=> (printout t "El valor es = " ?valor crlf))
CLIPS> (reset)
CLIPS> (run)
El valor es = (Tercer Valor)
El valor es = (Segundo Valor)
El valor es = (Primer Valor)
Ejemplo 6.
Ejemplo 7.
A continuación se definen reglas para consultar los hechos según los campos Tipo y Genero. En
cada regla el antecedente está formado por dos EC patrón: el primero busca un hecho ordenado
que se relaciona con el tipo de consulta, guardando el valor correspondiente en la variable ?cual;
el segundo causa la búsqueda de todos los hechos de la relación ARTISTAS en los que el campo
Tipo o Genero (según la consulta) coincida con el valor de la variable ?cual.
Hasta el momento ninguna de las reglas se activa pues no existen hechos ordenados que indiquen
el tipo de consulta. Al introducir:
Nombre (SHAKIRA)
Pais COLOMBIA
Genero POP
Al agregar:
CLIPS> (assert (Consulta-genero ROCK))
<Fact-9>
CLIPS> (run)
Se obtiene:
Son muy frecuentes las situaciones que requieren la posibilidad de almacenar la dirección de un
hecho para su posterior manipulación.
Ejemplo 8.
El propósito del hecho ordenado Total es acumular los valores de las áreas.
La regla Muestra-area permite visualizar la sumatoria de las áreas, la primera condición verifica qie
no existan hechos de la relación Rectangulo (garantizando la acumulación de todas las áreas).
CLIPS> (agenda)
0 Suma-areas: f-4,f-3
0 Suma-areas: f-4,f-2
0 Suma-areas: f-4,f-1
For a total of 3 activations.
El comando agenda permite observar que la regla Suma-areas se active tres veces (existen tres
hechos de la relación Rectangulo). La regla Muestra-area no se activa mientras existan hechos de
tipo Rectangulo.
Al ejecutar las reglas, se obtiene:
CLIPS> (run)
Area total= 306
En los ejemplos anteriores se le asignó valor a las variables por su primera aparición en el
antecedente de las reglas, ahora se mostrará la forma de hacerlo en el consecuente.
6.2.4.1 bind, sirve para asignarle a una variable el resultado de una expresión o del llamado a otra
función.
6.2.4.2 read, permite leer un valor sencillo desde un dispositivo, si no se especifica ninguno se
asume la entrada estándar (stdin), que normalmente es el teclado.
6.2.4.3 readline, permite leer los caracteres que forman una línea de texto desde un dispositivo,
si no se especifica ninguno se asume stdin.
Ejemplo 9.
CLIPS> (reset)
CLIPS> (defrule Leer => (printout t "Digite el primer número: ")
(bind ?n1 (read))
(printout t "Digite el segundo número: ")
(bind ?n2 (read))
(bind ?r (** ?n1 ?n2))
(printout t "El resultado es: " ?r))
CLIPS> (run)
Digite el primer número: 5
Digite el segundo número: 3
El resultado es: 125.0
Como el antecedente de la regla Leer es vació (no contiene ningún EC), se hace necesario ejecutar
el comando reset para cargar el hecho inicial que permite activar la regla.
Ejemplo 10.
AMARILLO OSCURO
VERDE OSCURO
AZUL OSCURO
La conectiva ~ permite excluir todos los hechos de la plantilla Color cuyo campo Valor contenga el
símbolo ROJO (direcciones 1 y 2), la conectiva | permite incluir los hechos que contengan los
símbolos OSCURO o claro en el campo Tono (direcciones 5, 6, 9 y 11).
Permiten restringir un campo dependiendo del resultado obtenido al llamar una función, si el valor
devuelto es diferente de FALSE la restricción se satisface.
Ejemplo 11.
CLIPS> (reset)
CLIPS> (defrule Leer (not (A))
=> (printout t crlf "Digite tono a consultar-->" (assert (A (read)))))
CLIPS> (defrule TONOCONSULTADO
(A ?t)
(Color (Valor ?c1)(Tono ?t1&?t|:(eq ?t1 (upcase ?t))))
=> (printout t crlf ?c1 " " ?t1 crlf))
CLIPS> (run)
Se obtiene:
VERDE CLARO
AZUL CLARO
ROJO CLARO
Resultados que corresponden a los hechos ubicados en las direcciones 1, 3, 8 y 11. La restricción
predicado permite que el usuario introduzca el tono en mayúsculas o minúsculas.
Ejemplo 12.
CLIPS> (defrule ENTEROPAR (Dato ?x&:(integerp ?x)&:(evenp ?x)) => (printout t ?x crlf))
CLIPS> (deffacts I
(Dato 20.14)
(Dato 8)
(Dato Rojo)
(Dato 1))
CLIPS> (reset)
CLIPS> (run)
8
Permiten incorporar como parte de un patrón el valor que retorna una función, incorporándolo
como una restricción literal. El valor retornado por la función debe corresponder a uno de los tipos
de datos primitivos de CLIPS.
Ejemplo 13.
CLIPS> (reset)
CLIPS> (defrule TODOCOLORMEDIO
(Color (Valor ?c1)(Tono = (upcase MedIo)))
=> (printout t crlf ?c1 crlf))
CLIPS> (run)
Se obtiene:
AMARILLO
VERDE
AZUL
Note que el antecedente de la regla Leer es vació, por lo tanto se verifica la existencia del hecho
inicial afirmado por el comando reset. El comando bind y la función read se utilizan para
establecer los límites del intervalo.
El antecedente de la regla Suma verifica que el límite inferior sea menor o igual que el límite
superior mediante el comando test. El consecuente modifica el límite inferior (incrementándolo de
uno en uno), acumula el valor actual del límite inferior y actualiza los hechos.
La siguiente regla es Resultado y solamente se ejecuta si el límite inferior es mayor que el superior.
Sumatoria=33
De manera similar a los lenguajes convencionales CLIPS proporciona los comandos if y while. Su
uso se explica a través de dos ejemplos sencillos.
Verificar la existencia de hechos de la relación A formados ppor un solo valor; si el valor es de tipo
entero se debe eliminar el hecho correspondiente.
Para cada hecho de la relación A formado por un valor entero positivo obtener como resultado la
suma de todos los enteros entre 1 y el valor leído.
6.4 Ejercicios.
La posibilidad de definir variables que se puedan utilizar en cualquier punto del programa se
conoce como variable global. En este capítulo se muestra la forma de utilizar este tipo de variables
relacionándolas con funciones que aplican sobre campos de tipo multislot.
El símbolo que representa el nombre de la variable debe ir precedido del comodín ? y encerrado
entre asteriscos.
7.1.1 defglobal, permite definir variables que se pueden utilizar en cualquier punto del programa.
Se pueden utilizar varios constructores defglobal y cada uno de ellos puede contener cualquier
número de variables. Si aparece el mismo nombre de variable en varios constructores, el valor que
prevalece es el de la última aparición.
Las variables globales no se pueden utilizar para capturar el valor de un campo al verificar
patrones de reglas, por lo tanto la siguiente construcción es ilegal.
Salvo la restricción señalada anteriormente, las variables globales se pueden utilizar en cualquier
otro contexto como se muestra a continuación.
Note que las expresiones a concatenar pueden ser de diferentes tipos de datos y que los valores
se muestran encerrados entre paréntesis por tratarse de un valor múltiple.
Es importante resaltar que los valores se eliminan del campo múltiple que la función devuelve
pero la variable conserva su valor.
CLIPS> ?*q*
(Uno Dos Tres Cuatro Cinco)
rest$, devuelve un valor de campo múltiple formado por los valores de su argumento sin
incluir el primer campo.
explode$, devuelve un valor de campo múltiple formado por los elementos de una cadena.
implode$, devuelve una cadena formada por los valores de los campos de su argumento.
insert$, inserta un valor sencillo o múltiple antes del campo especificado para su primer
argumento.
CLIPS> ?*q*
(Uno Dos Tres Cuatro Cinco)
replace$, remplaza en su primer argumento los campos especificados por un valor sencillo
o múltiple.
CLIPS> (replace$ ?*q* 3 4 *)
(Uno Dos * Cinco)
CLIPS> (replace$ ?*q* 3 4 (create$ Seis Siete))
(Uno Dos Seis Siete Cinco)
CLIPS> ?*q*
(Uno Dos Tres Cuatro Cinco)
De manera similar a los lenguajes convencionales CLIPS permite que el usuario defina y utilice sus
propias funciones. Este aspecto se ilustra a continuación.
La función Mensaje se define sin parámetros y por lo tanto se llama sin argumentos.
La función implementa una solución recursiva para obtener el enésimo término de la secuencia de
FIBONACCI.
7.4 Ejercicios.
Referencias:
• Enrique Castillo, José Manuel Gutiérrez, y Ali S. Hadi Sistemas Expertos y Modelos de
Redes Probabilísticas