Está en la página 1de 57

Perfil de los autores

Juniel Almeida, Magister en Didáctica, docente investigador de tiempo completo del


Programa de Ingeniería de Sistemas, Universidad Cooperativa de Colombia, sede Bogotá.
Correo-e: juniel.almeida@campusucc.edu.co

Julio Ferrer, Especialista en Gestión y Desarrollo Comunitario, docente investigador de


tiempo completo del Programa de Ingeniería de Sistemas, Universidad Cooperativa de
Colombia, sede Bogotá. Correo-e: julio.ferrer@campusucc.edu.co

Título del documento. Fundamentos de Programación en Clips

Resumen: Este documento describe los elementos básicos de programación para


estudiantes interesados en el diseño y construcción de prototipos sencillos de Sistemas
Basados en Conocimiento (SBC) utilizando lenguaje CLIPS. Comienza con una breve
reseña histórica seguida de las instrucciones para una interacción adecuada con el
entorno de desarrollo provisto por CLIPS, en el capítulo 2 se presenta un conjunto de
funciones provistas por el lenguaje agrupadas de acuerdo con su funcionalidad; los
capítulos 3 y 4 describen los conceptos y comandos relacionados con la manipulación de
la base de hechos; el capítulo 5 introduce la noción de regla como mecanismo de
inferencia en CLIPS explicando su construcción y ejecución además de resaltar la
diferencia entre base de hechos y base de conocimiento, el capítulo 6 explica aspectos
relacionados con la construcción de elementos condicionales. Finalmente el capítulo 7 se
enfoca en el uso de variables globales, comandos para el control de flujo y funciones del
usuario.

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.

Palabras clave. CLIPS, SBC, Inteligencia Artificial, Conocimiento, Sistemas Expertos.


Tabla de contenidos
• Introducción 3
• Capítulo 1: Conceptos Básicos. 4
• Capítulo 2: Funciones provistas por CLIPS. 8
• Capítulo 3: HECHOS ORDENADOS. 19
• Capítulo 4: HECHOS NO ORDENADOS. 24
• Capítulo 5: CONSTRUCCIÓN Y EJECUCIÓN DE REGLAS 30
• Capítulo 6: ELEMENTO CONDICIONAL PATRON 38
• Capítulo 7: VARIABLES GLOBALES Y FUNCIONES DEL USUARIO 51
Introducción

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.

Un elemento fundamental para logar las competencias indispensables para el diseño y


construcción de productos de software inteligente, es el conocimiento de herramientas
de desarrollo propias de este campo. El lenguaje CLIPS responde a esta necesidad con la
ventaja de no requerir licencias para su utilización.

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 documento se elaboró a partir de la experiencia de los autores, basándose en un


criterio teórico práctico que estimula la capacidad creativa del lector y le ofrece el soporte
necesario para construir prototipos simples pero eficientes de Sistemas Basados en
Conocimiento.
Capítulo 1: Conceptos Básicos.

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.

1.1 Origen de CLIPS.

Se desarrolló en la Sección de Inteligencia Artificial del Centro Espacial Johnson de la NASA


(Matinés 2008), con el propósito de crear una herramienta transportable, económica y de
fácil integración para el desarrollo de sistemas basados en conocimiento. El prototipo
inicial se construyó en 1985 pero la primera versión disponible para grupos de
investigación externos solo se liberó en 1986 (versión 3.0).

En la actualidad se encuentran disponibles versiones de CLIPS para diferentes sistemas


operativos; su aceptación ha venido aumentando en los últimos años y actualmente se
utiliza en diferentes entornos de desarrollo (gobierno, industria y educación entre otros;
especialmente en los Estados Unidos de Norteamérica). El incremento de su popularidad
está relacionado con algunas características que orientaron su diseño:

o Facilidad para ser llamado desde otros lenguajes de programación, con la


posibilidad de retornar tanto valores como el control de la ejecución al programa que
efectuó el llamado.

o Facilidad para ejecutar funciones externas retornando el resultado y el control a


CLIPS.

o Excelente funcionalidad a bajo costo.

o Disminución considerable del tiempo requerido para desarrollar sistemas basados


en conocimiento.

o Elevado nivel de portabilidad.

CLIPS es la sigla de C Language Integrated Production System, Sistema Integrado de


Producción en Lenguaje C. La primera versión se escribió en lenguaje C y solo soportaba la
representación del conocimiento por medio de reglas, las versiones más recientes
permiten otras formas de representación.
1.2 Paradigmas de programación soportados por CLIPS.

A continuación se presenta una breve descripción de los diferentes enfoques de


programación que actualmente soporta CLIPS, como una clara evidencia de su evolución.

o Reglas de producción, se construyen a partir del conocimiento heurístico basado


en la experiencia. Como se mencionó anteriormente, es el paradigma original de CLIPS.

o Orientado a objetos, se basa en conocimiento de tipo declarativo formulado en


términos de las características básicas de la programación orientada a objetos: clases,
abstracción, encapsulamiento, herencia, paso de mensajes y polimorfismo.

o Por procedimientos, consiste en la representación del conocimiento mediante


funciones generalizadas.

1.3 Alfabeto e identificadores.

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.

1.4 Tipos de datos.

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.

o INTEGER, números enteros formados por un signo (+ o -) opcional, seguido de una


secuencia de dígitos; los valores enteros se almacenan como los de tipo long integer de C.

Algunos ejemplos de enteros:


4047229
+404
-58368

o FLOAT, números de punto flotante (reales) formados por un signo (+ o -) opcional,


seguido por una secuencia de dígitos, un punto y otra secuencia de dígitos; opcionalmente
se puede utilizar la notación exponencial. Los valores reales se almacenan como los de
tipo double float de C.

Algunos ejemplos de reales:


157.23
-157.23
+157.23e+1
157.23E-2

o SYMBOL, un símbolo es cualquier secuencia de caracteres que no corresponde


exactamente con el formato de un número.

Algunos ejemplos de símbolos:


OLIMPO
Olimpo
12mas
mAs12Z
xxx-mn
?valor

o STRING, una cadena de caracteres es un caso particular de símbolo encerrado


entre comillas dobles.

Algunos ejemplos de cadenas:


“OLIMPO”
“+1256”

o EXTERNAL-ADDRESS, una dirección externa es la dirección de una estructura de


datos externa devuelta por una función escrita en C o ADA. Los valores de este tipo solo
son creados con la llamada a la función.
El formato general de una dirección externa es <Pointer-XXX>.

o FACT-ADDRESS, la dirección de un hecho, el formato general es <Fact-


XXX>.

o INSTANCE, una instancia es un símbolo encerrado entre paréntesis rectangulares.


Una instancia es un caso particular de un objeto que puede pertenecer a alguno de los
tipos de datos primitivos o a una clase construida por el usuario.
Algunos ejemplos:
[OLIMPO]
[12345]
[++]

o INSTANCE-ADDRESS, dirección de una instancia, el formato general es <Instance-


XXX>.

o NUMBER, hace referencia a cualquier valor numérico.

o LEXEME, hace referencia a cualquier valor no numérico.

1.5 Funciones.

Una función es un segmento de código identificado con un nombre (nombre de función)


que implementa un algoritmo. Las funciones pueden recibir valores de entrada
(argumentos) y devolver un valor al punto del programa desde el cual son llamadas.
En CLIPS se utilizan funciones estándar y funciones construidas por el usuario; en
cualquier caso, el llamado a una función se debe hacer en notación prefija de acuerdo con
el siguiente formato:

(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.

1.7 Instalación y ejecución.

CLIPS es un software de dominio público que se puede descargar gratuitamente a través


de Internet.
Para ejecutar CLIPS bajo Windows solo se requiere tener disponible el archivo
CLIPSWin.exe. Al ejecutarlo se tiene acceso al nivel superior de desarrollo que funciona
como un intérprete de comandos identificado por el prompt:

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)

Desarrollar programas en el nivel superior de CLIPS es factible pero absolutamente


incómodo. Si se cometen errores al escribir una sentencia y se presiona la tecla Enter, no
es posible corregirlos y será necesario escribir nuevamente toda la sentencia; para evitar
este inconveniente, es preferible utilizar cualquier editor de texto para escribir el
programa y posteriormente ejecutarlo mediante la opción File – Load Batch de la barra de
tareas de CLIPS. La versión 6.23 incorpora un editor de texto sencillo pero bastante
práctico.

1.8 Líneas de comentario.

Un comentario inicia con el carácter punto y coma (;) y se extiende hasta el final de la
línea.

1.9 Ejercicios.

1. Instale CLIPS en su computador e ingrese al nivel superior de desarrollo.


2. ¿A que punto se devuelve el control después de ejecutar el comando exit?
3. Identifique cada una de las opciones de la barra de tareas de CLIPS e investigue su
funcionalidad.
4. Determine experimentalmente los valores máximos y mínimos para los tipos de
datos numéricos.
5. ¿Qué sucede si no se utilizan paréntesis al tratar de ejecutar el comando exit?
Capítulo 2: Funciones provistas por CLIPS.

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.

2.1 Expresiones aritméticas.

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

Como se mencionó anteriormente, en realidad +, -, * y / no son operadores sino funciones


aritméticas que se pueden llamar con dos o más argumentos. Su aplicación más
generalizada se ilustra a continuación.

Ejemplo 2.

CLIPS> (+ 1 5 -2 4)
8

El resultado es la suma de los argumentos: 1+5+(-2)+4.

CLIPS> (- 5 2 3 7 -1)
-6

El resultado es la resta entre el primer argumento y la suma de los siguientes:


5 – (2+3+7+(-1)).

CLIPS> (* 2 5 -2)
-20

El resultado es el producto de los argumentos: 2*5*(-2)

CLIPS> (/ 8 3 5 8)
0.0666666666666667

El resultado es el cociente de las divisiones sucesivas entre sus argumentos: 8/3/5/8.

Observe que en todos los casos el resultado de la función / es un valor de punto flotante.

2.2 Funciones matemáticas.

CLIPS ofrece la posibilidad de utilizar un amplio conjunto de funciones matemáticas, a


continuación se describen algunas de ellas.

2.2.1 abs, permite obtener el valor absoluto de su argumento.

CLIPS> (abs 151)


151
CLIPS> (abs -151)
151

2.2.2 div, funciona de manera similar a / pero utilizando aritmética entera.

CLIPS> (div 5 2)
2
CLIPS> (div 5 8)
0
CLIPS> (div 8 3 5 8)
0

2.2.3 max, devuelve el argumento de mayor valor.

CLIPS> (max 1 7 -8 4)
7

2.2.4 min, devuelve el argumento de menor valor.

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

2.2.6 sqrt, devuelve la raíz cuadrada de su argumento.

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

2.2.8 round, redondea su argumento al entero más cercano.

CLIPS> (round 1.5)


1
CLIPS> (round 1.51)
2

2.2.9 exp, devuelve el valor de la constante e elevado a la potencia indicada por el


argumento.

CLIPS> (exp 1)
2.71828182845905

2.2.10 log, devuelve el logaritmo en base e de su argumento.

CLIPS> (log 10)


2.30258509299405
2.2.11 log10, devuelve el logaritmo en base 10 de su argumento.

CLIPS> (log10 10)


1.0

2.2.12 pi, devuelve el valor de la constante Π.

CLIPS> (pi)
3.14159265358979

2.2.13 random, permite generar un entero aleatorio.

CLIPS> (random)
41
CLIPS> (random)
18467

2.2.14 seed, permite establecer la semilla para la generación de números aleatorios a


partir de un valor entero.

CLIPS> (seed 20)


CLIPS> (random)
103
CLIPS> (random)
26079

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

2.3 Expresiones de relación.

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 Funciones lógicas y de comprobación.

2.4.1 and, devuelve verdadero si todos sus argumentos son verdaderos.

CLIPS> (and (> 5 3) (= 5 (+ 4 1)) (<> 1 0))


TRUE
2.4.2 or, devuelve verdadero si por lo menos uno de sus argumentos es verdadero.

CLIPS> (or (> 8 9) (<= 5 (+ 4 2)))


TRUE

2.4.3 not, devuelve verdadero si su argumento es falso o falso si el argumento es


verdadero.

CLIPS> (not (= 4 3))


TRUE

2.4.4 numberp, devuelve verdadero si el argumento tiene un valor numérico o falso en


caso contrario.

CLIPS> (numberp 4.12)


TRUE
CLIPS> (numberp casa)
FALSE

2.4.5 evenp, devuelve verdadero si el argumento es un entero par o falso en caso


contrario.

CLIPS> (evenp 21)


FALSE

2.4.6 oddp, devuelve verdadero si el argumento es un entero impar o falso en caso


contrario.

CLIPS> (oddp 21)


TRUE

2.4.7 integerp, devuelve verdadero si el argumento es un entero o falso en caso contrario.

CLIPS> (integerp (/ 4 2))


FALSE

2.4.8 floatp, devuelve verdadero si el argumento es un valor de punto flotante o falso en


caso contrario.

CLIPS> (floatp (/ 4 2))


TRUE

2.4.9 lexemep, devuelve verdadero si el argumento es una cadena o un símbolo, falso en


caso contrario.
CLIPS> (lexemep Carnaval)
TRUE
CLIPS> (lexemep "Carnaval")
TRUE

2.4.10 stringp, devuelve verdadero si el argumento es una cadena o falso en caso


contrario.

CLIPS> (stringp "Carnaval")


TRUE
CLIPS> (stringp 12)
FALSE

2.4.11 symbolp, devuelve verdadero si el argumento es un símbolo o falso en caso


contrario.

CLIPS> (stringp 12)


FALSE
CLIPS> (symbolp Carnaval)
TRUE
CLIPS> (symbolp "Carnaval")
FALSE

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.

CLIPS> (eq (+ 9 1) (* 5 2) (- 14 4))


TRUE
CLIPS> (eq 10 (/ 20 2))
FALSE
CLIPS> (eq CARNAVAL "CARNAVAL")
FALSE

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.

CLIPS> (neq CARNAVAL "CARNAVL")


TRUE
CLIPS> (neq 10 (/ 20 2) (- 12 2))
FALSE

Observe que las funciones eq y neq permiten comparar valores no numéricos.


2.5 Funciones de cadenas y símbolos.

2.5.1 str-cat, devuelve todos sus argumentos concatenados como una cadena.

CLIPS> (str-cat 123 SOL "Frio")


"123SOLFrio"

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.

CLIPS> (str-compare "Milagro" "Milagro")


0
CLIPS> (str-compare "Milagro" Milagro)
0
CLIPS> (str-compare Milagro Milagro)
0
CLIPS> (str-compare Uno Tres)
1
CLIPS> (str-compare Tres Uno)
-1

Observe que str-compare permite comparar cadenas con símbolos, sin establecer
diferencia entre los dos tipos de datos.

2.5.3 str-index, devuelve el entero correspondiente a la posición en la que el primer


argumento inicia en el segundo, o falso si no esta contenido.

CLIPS> (str-index Cama Camarote)


1
CLIPS> (str-index Camarote Cama)
FALSE
CLIPS> (str-index "eric" America)
3

Observe que se pueden mezclar cadenas con símbolos.

2.5.4 str-length, devuelve la longitud de una cadena o de un símbolo.

CLIPS> (str-length "America")


7
CLIPS> (str-length America)
7
2.5.5 sub-string, devuelve la subcadena comprendida en el intervalo establecido por los
dos primeros argumentos.

CLIPS> (sub-string 1 5 "Los mejores tiempos")


"Los m"

2.5.6 sym-cat, devuelve todos sus argumentos concatenados como un símbolo.

CLIPS> (sym-cat Los 123 "America")


Los123America

2.6 Funciones de conversión.

2.6.1 float, convierte su argumento en un valor de punto flotante.

CLIPS> (float 25)


25.0
CLIPS> (float (div 4 2))
2.0
CLIPS> (float (div 1 2))
0.0

2.6.2 integer, convierte su argumento en un valor entero.

CLIPS> (integer 1.255)


1
CLIPS> (integer (/ 5 3))
1

2.6.3 lowcase, devuelve su argumento (cadena o símbolo) después de convertir todas las
letras mayúsculas en minúsculas.

CLIPS> (lowcase AMERICA)


america
CLIPS> (lowcase Junior)
junior

2.6.4 upcase, devuelve su argumento (cadena o símbolo) después de convertir todas las
letras minúsculas en mayúsculas.

CLIPS> (upcase "america")


"AMERICA"
CLIPS> (upcase "juNior")
"JUNIOR"
2.6.5 deg-grad, convierte un valor expresado en grados a unidades de gradiente.

CLIPS> (deg-grad 45)


50.0

2.6.6 deg-rad, convierte un valor expresado en grados a radianes.

CLIPS> (deg-rad 45)


0.785398163397448

2.6.7 grad-deg, convierte un valor expresado en unidades de gradiente a grados.

CLIPS> (grad-deg 50.0)


45.0

2.6.8 rad-deg, convierte un valor de radianes a grados.

CLIPS> (rad-deg 3.1416)


180.000420918299

2.7 Funciones trigonométricas.

Todas las funciones que se describen a continuación utilizan radianes como unidad de
medida para su argumento.

2.7.1 cos, devuelve el coseno del valor indicado por su argumento.

CLIPS> (cos 0)
1.0
CLIPS> (cos 3.1416)
-0.999999999973015

2.7.2 acos, devuelve el coseno del arco indicado por su argumento.

CLIPS> (acos 0)
1.5707963267949
CLIPS> (acos 1)
0.0

2.7.3 cot, devuelve la cotangente del valor indicado por su argumento.

2.7.4 acot, devuelve la cotangente del arco indicado por su argumento.


2.7.5 csc, devuelve la cosecante del valor indicado por su argumento.

2.7.6 acsc, devuelve la cosecante del arco indicado por su argumento.

2.7.7 sec, devuelve la secante del valor indicado por su argumento.

2.7.8 asec, devuelve la secante del arco indicado por su argumento.

2.7.9 sin, devuelve el seno del valor indicado por su argumento.

2.7.10 asin, devuelve el seno del arco indicado por su argumento.

2.7.11 tan, devuelve la tangente del valor indicado por su argumento.

2.7.12 atan, devuelve la tangente del arco indicado por su argumento.

Si se agrega la letra h a cualquiera de las funciones anteriores, se obtiene el resultado


hiperbólico correspondiente.

CLIPS> (sinh 0.72)


0.783840477341958
CLIPS> (atanh 0)
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).

3.1 Consideraciones iniciales.

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.

3.2 Definición de hecho ordenado.

Un hecho ordenado es un conjunto de cero o más valores cuyo significado depende


estrictamente de la posición de cada valor. Son especialmente útiles para implementar
redes semánticas. En CLIPS la definición de un hecho ordenado se efectúa mediante un
símbolo al que se le puede asociar un conjunto de valores (cero o más) dispuestos en una
relación de orden. Es decir, los valores se referencia según su posición.

3.3 Afirmación de hechos.

3.3.1 assert, permite agregar uno o varios hechos a la lista de hechos.

Ejemplo 1.

CLIPS> (assert (Cifra 1))


<Fact-0>
CLIPS> (assert (Cifra 2)
(Cifra 3)
(Monto Tres))

<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.

CLIPS> (assert (Cifra 1))


FALSE

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.

3.4 Visualización de hechos.

3.4.1 facts, permite visualizar total o parcialmente el contenido de la lista de hechos.

Ejemplo 3.

Para ver la lista completa:

CLIPS> (facts)
f-0 (Cifra 1)
f-1 (Cifra 2)
f-2 (Cifra 3)
f-3 (Monto Tres)
For a total of 4 facts.

Para ver la lista de manera parcial:

(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.

3.5 Eliminación de hechos.

3.5.1 retract, permite eliminar uno o más hechos de la lista.

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

Como se puede observar, se ha eliminado el hecho de la dirección 3 correspondiente a la relación


Monto.

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 *).

3.5.2 clear, deja vacía la lista de hechos.

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.

CLIPS> (assert (Mayor (> 3 1)))


<Fact-1>
CLIPS> (facts)
f-0 (Resultado 14)
f-1 (Mayor TRUE)
For a total of 2 facts.

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.

Para cada caso sustente la respuesta con ejemplos.

1. ¿Un hecho ordenado puede tener asociada varias cadenas de caracteres?


2. ¿Si un hecho ordenado esta formado por varios valores, todos deben ser del mismo tipo?
3. ¿El nombre de relación correspondiente a un hecho ordenado puede ser un número?
4. ¿El nombre de relación correspondiente a un hecho ordenado puede ser un carácter
especial (como +, -, *) ?
5. ¿Existe alguna diferencia entre los comandos (retract *) y (clear)?
Capítulo 4: HECHOS NO ORDENADOS.

A continuación se introduce el concepto de hecho no ordenado también conocido como hecho de


plantilla; se establece la diferencia con los hechos ordenados y se describen algunos comandos
complementarios.
Conviene reiterar que los términos hechos de plantilla y hechos no ordenados hacen referencia al
mismo concepto.

4.1 Definición de hecho no ordenado.

Un hecho no ordenado es un conjunto de datos relacionados que representan información de una


entidad. Constituyen una buena alternativa para la implementación de los marcos como técnica
de representación del conocimiento.

4.2 El concepto de plantilla.

Una plantilla es un conjunto de campos agrupados bajo un nombre de relación, el concepto es


similar al de registro en lenguaje PASCAL o al de estructura en C/C++.

La definición de una plantilla puede establecer características específicas para los campos
(ranuras) que forman una relación.

4.2.1 deftemplete, es el constructor que permite definir plantillas.

Ejemplo 1.

CLIPS> (deftemplate Relacion (slot Campo1)


(multislot Campo2)
(slot Campo3))

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.

CLIPS> (assert (Ordenado)


(Ordenado 1)
(Ordenado 1 uno 2))
<Fact-2>
CLIPS> (facts)
f-0 (Ordenado)
f-1 (Ordenado 1)
f-2 (Ordenado 1 uno 2)
For a total of 3 facts.

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.

CLIPS> (assert (Ordenado1)


(Relacion (Campo1 20)
(Campo2 Somos los mejores)
(Campo3 4.5))
(Relacion (Campo2 No importa el orden)
(Campo3 4.8)
(Campo1 10))
(Ordenado2 0 1 2 3))
<Fact-3>
CLIPS> (facts)
f-0 (Ordenado1)
f-1 (Relacion (Campo1 20) (Campo2 Somos los mejores) (Campo3 4.5))
f-2 (Relacion (Campo1 10) (Campo2 No importa el orden) (Campo3 4.8))
f-3 (Ordenado2 0 1 2 3)
For a total of 4 facts.

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 Restricciones para la definición de campos.

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.

Después de reiniciar la lista de hechos se define la relación Estudiante, la plantilla de definición


incluye restricciones.

Note que cada tipo de restricción se encierra entre paréntesis.


El comando assert omite el campo Promedio, al que por defecto se le asigna ahora el valor 0.0 en
lugar de nil, porque la definición del campo incluye la restricción type FLOAT.

Ejemplo 6.

CLIPS>(deftemplate R1 (slot C1 (type INTEGER)(range ?VARIABLE 100))


(multislot C2 (cardinality 3 5))
(slot C3 (allowed-symbols S1 S2 S3)
(allowed-integers 0 8 1)))
CLIPS> (assert (R1 (C3 8)))
<Fact-0>
CLIPS> (facts)
f-0 (R1 (C1 100) (C2 nil nil nil) (C3 8))
For a total of 1 fact.

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.

CLIPS>(deftemplate R2 (slot C1 (allowed-values S1 S2 1 2)))


CLIPS> (assert (R2 (C1 S2)))
<Fact-0>
CLIPS> (facts)
f-0 (R2 (C1 S2))
For a total of 1 fact.

El tratamiento del campo C1 de la relación R2 comprueba que la restricción allowed-values ofrece


la posibilidad de incluir una lista con valores de diferentes tipos de datos.

4.3.5 default, permite establecer la obligatoriedad de un campo.

Ejemplo 8.

CLIPS> (deftemplate R3 (slot C1 (default ?DERIVE))


(slot C2 (default ?NONE))
(slot C3))
CLIPS> (assert (R3 (C2 Obligatorio)))
<Fact-0>
CLIPS> (facts)
f-0 (R3 (C1 nil) (C2 Obligatorio) (C3 nil))
For a total of 1 fact.

La relación R3 ilustra la manera de utilizar la restricción default, el campo C1 incluye la opción


?DERIVE que asigna el valor por defecto, según el tipo de datos, en caso de omisión del campo.
Como la definición de C1 no específica el tipo de datos se asume SYMBOL por defecto y como el
comando assert omite el valor de C1, se asigna nil como se ha explicado anteriormente. Observe
que utilizar default ?DERIVE es lo mismo que omitir la restricción default como se hace en la
definición de C3. La definición de C2 incluye la restricción default ?NONE para indicar que se trata
de un campo obligatorio, si por alguna razón se omite el valor de C2, no se aceptará el hecho.

El siguiente ejemplo muestra una variante de la restricción default que puede resultar útil.

Ejemplo 9.

CLIPS> (deftemplate R3 (slot C1 (default SIEMPRE))


(slot C2 (default ?NONE))
(slot C3))
CLIPSc> (assert (R3 (C2 Obligatorio)))
<Fact-0>
CLIPS> (facts)
f-0 (R3 (C1 SIEMPREc) (C2 Obligatorio) (C3 nil))
For a total of 1 fact.

Ahora la definición de C1 incluye la restricción default seguida de un valor específico ( el símbolo


SIEMPRE), por lo tanto si se omite el valor de C1 se asignará por defecto el valor indicado.

4.4 Manipulación de hechos no ordenados.


Ejemplo 10.

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.

5.1 Aspectos generales.

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)

El mecanismo de inferencia evalúa la(s) condición(es) (elementos condicionales), si todas las


condiciones son verdaderas la regla se activa. Si varias reglas se cumplen para el mismo conjunto
de hechos y objetos, el mecanismo de inferencia utiliza la estrategia de resolución de conflictos
que se encuentre activa para determinar el orden de activación. A diferencia de lo que ocurre en
los lenguajes convencionales, el orden de activación (y por lo tanto el de ejecución) no coincide
necesariamente con el orden de aparición de las reglas en el programa.

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 Construcción de reglas.

5.2.1 defrule, es el constructor que sirve para definir una regla siguiendo el formato:

(defrule nombre-regla antecedente


=>
consecuente)

El antecedente (parte izquierda de la regla) esta formado por un conjunto de elementos


condicionales unidos implícitamente por conjunciones lógicas (and), el consecuente (parte
derecha de la regla) contiene las acciones que se llevarán a cabo, de manera secuencial, si todos
los elementos condicionales del antecedente son verdaderos. El símbolo => (entonces) separa la
parte izquierda de la derecha.

Ejemplo 1.

CLIPS> (defrule Regla1 (Prueba 0)


=> (retract 0)
(assert (Prueba 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)
)

Como el antecedente no contiene ningún elemento condicional explicito, el mecanismo de


inferencia verificará la existencia del patrón (inicial-fact) o (inicial-object) para activar la regla.

5.3 Reglas activas.

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.

CLIPS> (assert (Prueba 0))


<Fact-0>
CLIPS> (defrule Regla1 (Prueba 0)
=> (retract 0)
(assert (Prueba 1)))
CLIPS> (agenda)
0 Regla1: f-0
For a total of 1 activation.
CLIPS> (facts)
f-0 (Prueba 0)
For a total of 1 fact

Observe que el consecuente no se ejecuta automáticamente como resultado de la activación y


por lo tanto no se lleva a cabo ninguna acción (los hechos no se modifican).

5.4 Ejecución de reglas.

5.4.1 run, comando que permite ejecutar las reglas activas.

Ejemplo 4.

CLIPS> (assert (Prueba 0))


<Fact-0>
CLIPS> (defrule Regla1 (Prueba 0)
=> (retract 0)
(assert (Prueba 1)))
CLIPS> (agenda)
0 Regla1: f-0
For a total of 1 activation.
CLIPS> (run)
CLIPS> (facts)
f-1 (Prueba 1)
For a total of 1 fact.

Como se puede apreciar, la acción causada por el consecuente de la regla se ha ejecutado (los
hechos se han modificado).

Ejemplo 5.

CLIPS> (deffacts I (Prueba 0))


CLIPS> (defrule Regla1 (Prueba 0)
=> (assert (Prueba 1)))
CLIPS> (defrule Regla2 (Prueba 0)
=> (assert (Prueba 2)))
CLIPS> (reset)
CLIPS> (agenda)
0 Regla1: f-1
0 Regla2: f-1
For a total of 2 activations.
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (Prueba 0)
f-2 (Prueba 1)
f-3 (Prueba 2)
For a total of 4 facts.

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.

CLIPS> (deffacts I (Prueba 0))


CLIPS> (defrule Regla1 (Prueba 0)
=> (assert (Prueba 1)))
CLIPS> (defrule Regla2 (Prueba 0)
=> (assert (Prueba 2)))
CLIPS> (defrule Regla3 (Prueba 0)
=> (assert (Prueba 3)))
CLIPS> (reset)
CLIPS> (agenda)
0 Regla1: f-1
0 Regla2: f-1
0 Regla3: f-1
For a total of 3 activations.
CLIPS> (run 1)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (Prueba 0)
f-2 Prueba 1)
For a total of 3 facts.

Se activan las tres reglas pero solo se ejecuta una.

5.5 Comandos complementarios.

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.

CLIPS> (deffacts I (Prueba 0))


CLIPS> (defrule Regla1 (Prueba 0)
=> (assert (Prueba 1)))
CLIPS> (defrule Regla2 (Prueba 0)
=> (assert (Prueba 2)))
CLIPS> (defrule Regla3 (Prueba 0)
=> (assert (Prueba 3)))
CLIPS> (watch activations)
CLIPS> (watch rules)
CLIPS> (reset)
==> Activation 0 Regla3: f-1
==> Activation 0 Regla2: f-1
==> Activation 0 Regla1: f-1
CLIPS> (agenda)
0 Regla1: f-1
0 Regla2: f-1
0 Regla3: f-1
For a total of 3 activations.
CLIPS> (run 1)
FIRE 1 Regla1: f-1
CLIPS> (facts)
f-0 (initial-fact)
f-1 (Prueba 0)
f-2 (Prueba 1)
For a total of 3 facts.
CLIPS> (unwatch all)

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.

CLIPS> (deffacts I (Prueba 0))


CLIPS> (defrule Regla1 (Prueba 0)
=> (printout t "Se ejecuta la Regla1" crlf)
(assert (Prueba 1)))
CLIPS> (defrule Regla2 (Prueba 0)
=> (printout t "Se ejecuta la Regla2" crlf)
(assert (Prueba 2)))
CLIPS> (defrule Regla3 (Prueba 0)
=> (printout t "Se ejecuta la Regla3" crlf)
(assert (Prueba 3)))
CLIPS> (reset)
CLIPS> (run)
Se ejecuta la Regla1
Se ejecuta la Regla2
Se ejecuta la Regla3

La opción crlf sirve para indicar un cambio de línea.

Ejemplo 9.

CLIPS> (defrule Regla1 => (printout t "Existen hechos" crlf "Se ejecuta la
Regla1" ))
CLIPS> (run)

Recuerde que la existencia de hechos es indispensable para la activación y posterior ejecución de


las reglas. El programa no causa ningún efecto porque no existen hechos.

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.

CLIPS> (defrule R1 (Prueba 0)


=> (retract *))
CLIPS> (defrule R2 (Prueba 1)
=> (assert (Verdadero)))
CLIPS> (list-defrules)
R1
R2
For a total of 2 defrules.

5.5.5 ppdefrule, muestra el detalle de la regla especificada.

Ejemplo 12.

CLIPS> (ppdefrule R2)


(defrule MAIN::R2
(Prueba 1)
=>
(assert (Verdadero)))

5.5.6 undefrule, elimina la regla especificada.

Ejemplo 13.

CLIPS> (undefrule R1)


5.5.7 matches, muestra los hechos que se relacionan con el antecedente de la regla especificada y
las activaciones causadas por ellos.

Ejemplo 14.

CLIPS> (defrule R2 (Prueba 1)


=> (assert (Verdadero)))
CLIPS> (assert (Prueba 0)
(Prueba 1))
<Fact-1>
CLIPS> (matches R2)
Matches for Pattern 1
f-1
Activations
f-1
CLIPS> (run)
CLIPS> (facts)
f-0 (Prueba 0)
f-1 (Prueba 1)
f-2 (Verdadero)
For a total of 3 facts.
CLIPS> (matches R2)
Matches for Pattern 1
f-1
Activations
None

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.

CLIPS> (deftemplate Figura


(slot Tipo)(slot Clase)(multislot Significado))
CLIPS> (deffacts I
(Figura (Tipo Rombo)(Clase Preventiva)(Significado Glorieta))
(Figura (Tipo Rombo)(Clase Preventiva)(Significado Tubel))(Figura (Tipo Circulo)(Clase
Reglamentaria)(Significado Via cerrada))(Figura (Tipo Circulo)(Clase Reglamentaria)(Significado
Reten))(Figura (Tipo Circulo)(Clase Reglamentaria)(Significado Desvio))(Figura (Tipo
Cuadradoo)(Clase Informativa)(Significado Iglesia)))
CLIPS> (reset)
CLIPS> (defrule F
(Figura (Clase Reglamentaria))
=> (printout t "Se encontro una señal preventiva" crlf))
CLIPS> (agenda)
0 F: f-5
0 F: f-4
0 F: f-3
For a total of 3 activations.
CLIPS> (run)
Se encontro una señal preventiva
Se encontro una señal preventiva
Se encontro una señal preventiva

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.

CLIPS> (refresh R2)


CLIPS> (matches R2)
Matches for Pattern 1
f-1
Activations
f-1

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é?

(assert (Valor 1))


(defrule R1 (Valor 1)
=> (printout t "Se ejecuto la regla" crlf)
(assert (Valor 1)))
(run)
4. ¿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.

6.1 Concepto de elemento condicional.

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.

CLIPS> (set-fact-duplication TRUE)


FALSE
CLIPS> (watch facts)
CLIPS> (watch activations)
CLIPS> (defrule R1
(PATRON 5) =>)
CLIPS> (assert (PATRON 5)
(PATRON 5)
(PATRON 5))
==> f-0 (PATRON 5)
==> Activation 0 R1: f-0
==> f-1 (PATRON 5)
==> Activation 0 R1: f-1
==> f-2 (PATRON 5)
==> Activation 0 R1: f-2
<Fact-2>

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:

o El ámbito de una variable se limita a la regla donde se define, comportándose como


variables locales.
o El nombre de una variable debe ir precedido por ? si almacena un valor sencillo, o por $?
Si almacena varios valores (variables de tipo lista). El primer carácter del nombre de una variable
debe ser alfabético.
o La primera aparición de la variable sirve para asignarle valor.
o Las apariciones posteriores sustituyen la variable por el valor asignado.

Ejemplo 4.

CLIPS> (deffacts Inicio (Prueba 0)(Prueba 1)(Prueba 2))


CLIPS> (defrule R1 (Prueba ?valor)
=> (printout t "El valor es = " ?valor crlf))
CLIPS> (reset)
CLIPS> (run)
El valor es = 2
El valor es = 1
El valor es = 0

El antecedente de R1 verifica la existencia de hechos de la relación Prueba; la regla se activa para


cada uno de estos hechos guardando el valor correspondiente en instancias diferentes de la
variable ?valor.

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)

Note que en el consecuente la variable se referencia cómo ?valor en lugar de $?valor.

Ejemplo 6.

CLIPS> (deftemplate Rectangulo (slot base)(slot altura))


CLIPS> (deffacts Varios
(Rectangulo (base 5)(altura 10))
(Rectangulo (base 12)(altura 20))
(Rectangulo (base 2)(altura 8)))
CLIPS> (reset)
CLIPS> (defrule Calculo
(Rectangulo (base ?b)(altura ?h))
=> (printout t crlf "Base= " ?b " Altura= " ?h " Area= " (* ?b ?h)
" Perimetro= " (+ ?b ?b ?h ?h)))
CLIPS> (agenda)
0 Calculo: f-3
0 Calculo: f-2
0 Calculo: f-1
For a total of 3 activations.
CLIPS> (run)

Base= 2 Altura= 8 Area= 16 Perimetro= 20


Base= 12 Altura= 20 Area= 240 Perimetro= 64
Base= 5 Altura= 10 Area= 50 Perimetro= 30

Se afirma un conjunto de hechos iniciales que corresponden a la información necesaria para


definir varios rectángulos (base y altura), para cada uno de ellos se calcula y muestra el valor del
área y del perímetro mediante la regla Calculo. La regla se activa tantas veces como hechos de la
relación Rectangulo se encuentren en la lista de hechos.

Ejemplo 7.

Dadas las definiciones:

CLIPS> (deftemplate ARTISTAS (multislot Nombre)(slot Pais)


(slot Tipo)(slot Genero))
CLIPS> (deffacts DESTACADOS
(ARTISTAS (Nombre RICARDO ARJOMA)(Pais GUATEMALA)
(Tipo SOLISTA)(Genero BALADA))
(ARTISTAS (Nombre SHAKIRA)(Pais COLOMBIA)
(Tipo SOLISTA)(Genero POP))
(ARTISTAS (Nombre LOS TRIO)(Pais COLOMBIA)
(Tipo GRUPO)(Genero BOLERO))
(ARTISTAS (Nombre JUAN FERNANDO VELASCO)(Pais ECUADOR)
(Tipo SOLISTA)(Genero BALADA))
(ARTISTAS (Nombre THE BEATLES)(Pais INGLATERRA)
(Tipo GRUPO)(Genero ROCK))
(ARTISTAS (Nombre SODA STEREO)(Pais ARGENTINA)
(Tipo GRUPO)(Genero ROCK))
(ARTISTAS (Nombre SILVIO RODRIGUEZ)(Pais CUBA)
(Tipo SOLISTA)(Genero PROTESTA)))
CLIPS> (reset)

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.

CLIPS> (defrule Tipo


(Consulta-tipo ?cual) (ARTISTAS (Tipo ?cual)(Nombre $?n)(Pais ?p)(Genero
?g))
=> (printout t crlf "Nombre " ?n crlf "Pais " ?p crlf "Genero " ?g crlf))
CLIPS> (defrule Genero (Consulta-genero ?cual)
(ARTISTAS (Genero ?cual)(Nombre $?n)(Pais ?p)(Tipo ?t))
=> (printout t crlf "Nombre " ?n crlf "Pais " ?p crlf "Tipo " ?t crlf))

Hasta el momento ninguna de las reglas se activa pues no existen hechos ordenados que indiquen
el tipo de consulta. Al introducir:

CLIPS> (assert (Consulta-tipo SOLISTA))


<Fact-8>
CLIPS> (run)

Se obtienen los siguientes resultados:

Nombre (SILVIO RODRIGUEZ)


Pais CUBA
Genero PROTESTA

Nombre (JUAN FERNANDO VELASCO)


Pais ECUADOR
Genero BALADA

Nombre (SHAKIRA)
Pais COLOMBIA
Genero POP

Nombre (RICARDO ARJOMA)


Pais GUATEMALA
Genero BALADA

Al agregar:
CLIPS> (assert (Consulta-genero ROCK))
<Fact-9>
CLIPS> (run)

Se obtiene:

Nombre (SODA STEREO)


Pais ARGENTINA
Tipo GRUPO

Nombre (THE BEATLES)


Pais INGLATERRA
Tipo GRUPO

6.2.3 Dirección de un hecho (operador <-).

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 siguiente programa calcula el área total de un conjunto de rectángulos.

CLIPS> (deftemplate Rectangulo (slot Base)(slot Altura))


CLIPS> (deffacts Varios (Rectangulo (Base 5)(Altura 10)) (Rectangulo (Base
12)(Altura 20)) (Rectangulo (Base 2)(Altura 8)) (Total 0))
CLIPS> (reset)

El propósito del hecho ordenado Total es acumular los valores de las áreas.

CLIPS> (defrule Suma-areas


?dt <- (Total ?at)
?dr <- (Rectangulo (Base ?b)(Altura ?h))
=> (retract ?dt ?dr)
(assert (Total (+ ?at (* ?b ?h)))))

La regla Suma-areas permite calcular y acumular el área de cada rectángulo. El primer EC


comprueba la existencia del hecho ordenado Total guardando en la variable ?at el valor asociado
con este hecho (inicialmente cero) y en la variable ?dt la dirección asignada al hecho. El segundo
EC comprueba la existencia de hechos de la relación Rectangulo, creando para cada uno de ellos
una instancia de las variables ?b, ?h y ?dr; ?b almacena la base, ?h la altura y ?dr la dirección de
cada rectángulo.
El consecuente elimina la ocurrencia actual del hecho Total así como la del rectángulo que causó la
activación de la regla, finalmente se afirma una nueva ocurrencias del hecho Total acumulando el
área del rectángulo procesado. Observe que las variables se utilizan incluso después de haber
eliminado los hechos que permitieron asignarles valor.

CLIPS> (defrule Muestra-area


(not (Rectangulo))
(Total ?at)
=> (printout t "Area total= " ?at crlf))

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

6.2.4 Asignación y lectura de valores en el consecuente de una regla.

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.

6.2.5 Restricciones conectivas.

Existen tres restricciones de este tipo: ~ (no), & (y) y | (o).


Permiten enlazar restricciones sencillas para formar patrones complejos; al confrontar los
patrones la evaluación se realiza teniendo en cuenta la precedencia (~, &, |) y si existen
restricciones del mismo nivel la evaluación se realiza de izquierda a derecha.
La restricción ~ se satisface si la restricción que le sigue es falsa, & se satisface si las dos
restricciones enlazadas son verdaderas y | se satisface si por lo menos una de las restricciones
enlazadas es verdadera.

Ejemplo 10.

CLIPS> (deftemplate Color


(slot Valor)(slot Tono))
CLIPS> (deffacts I
(Color (Valor ROJO)(Tono CLARO)
)
(Color (Valor ROJO)(Tono OSCURO))
(Color (Valor AZUL)(Tono CLARO)
)
(Color (Valor AZUL)(Tono MEDIO)
)
(Color (Valor AZUL)(Tono OSCURO))
(Color (Valor VERDE)(Tono OSCURO))
(Color (Valor VERDE)(Tono MEDIO))
(Color (Valor VERDE)(Tono CLARO))
(Color (Valor AMARILLO)(Tono OSCURO))
(Color (Valor AMARILLO)(Tono MEDIO))
(Color (Valor GRIS)(Tono claro)))
CLIPS> (reset)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (Color (Valor ROJO) (Tono CLARO))
f-2 (Color (Valor ROJO) (Tono OSCURO))
f-3 (Color (Valor AZUL) (Tono CLARO))
f-4 (Color (Valor AZUL) (Tono MEDIO))
f-5 (Color (Valor AZUL) (Tono OSCURO))
f-6 (Color (Valor VERDE) (Tono OSCURO))
f-7 (Color (Valor VERDE) (Tono MEDIO))
f-8 (Color (Valor VERDE) (Tono CLARO))
f-9 (Color (Valor AMARILLO) (Tono OSCURO))
f-10 (Color (Valor AMARILLO) (Tono MEDIO))
f-11 (Color (Valor GRIS) (Tono claro))
For a total of 12 facts.
CLIPS> (defrule Leer (not (A))
=> (printout t "Digite color a excluir-->" (assert (A (read))))
(printout t crlf "Digite tono a consultar-->" (assert (T (read)))))
CLIPS> (defrule NOCOLORYTONO
(A ?c)
(T ?t)
(Color (Valor ~?c)(Tono ?t|claro))
=> (printout t crlf ?c " " ?t crlf))
CLIPS> (run)
Digite color a excluir-->ROJO
<Fact-12>
Digite tono a consultar-->OSCURO
<Fact-13>
GRIS OSCURO

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).

6.2.4 Restricciones predicado.

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.

Utilizando las definiciones del Ejemplo 10, si se introduce:

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:

Digite tono a consultar-->claro


<Fact-12>
GRIS claro

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

6.2.5 Restricciones de valor de retorno.

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.

Utilizando las definiciones del Ejemplo 10, si se introduce:

CLIPS> (reset)
CLIPS> (defrule TODOCOLORMEDIO
(Color (Valor ?c1)(Tono = (upcase MedIo)))
=> (printout t crlf ?c1 crlf))
CLIPS> (run)

Se obtiene:

AMARILLO
VERDE

AZUL

Resultados que corresponden a los hechos ubicados en las direcciones 4, 7 y 10.


test, comprueba el resultado (verdadero o falso) de una relación que forma parte del
antecedente de una regla.

El siguiente programa obtiene la sumatoria de los enteros comprendidos en un intervalo


determinado.

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.

CLIPS> (deffacts Prueba (Total 0))


CLIPS> (reset)
CLIPS> (defrule Leer => (printout t crlf "Digite limite inferior " )
(bind ?li (read))
(printout t "Digite limite superior ")
(bind ?ls (read))
(assert (Inferior ?li)
(Superior ?ls)))

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.

CLIPS> (defrule Sumar


?di <- (Inferior ?li)
?ds<- (Total ?st)
(Superior ?ls)
(test (<= ?li ?ls))
=> (retract ?di ?ds)
(assert (Inferior (+ ?li 1)))
(bind ?st (+ ?st ?li))
(assert (Total ?st)))

La siguiente regla es Resultado y solamente se ejecuta si el límite inferior es mayor que el superior.

CLIPS> (defrule Resultado (Inferior ?li)


(Superior ?ls)
(test (> ?li ?ls))
(Total ?st)
=> (printout t crlf "Sumatoria=" ?st crlf))
CLIPS> (run)

Digite límite inferior 10


Digite límite superior 12

Sumatoria=33

6.3 Comandos de control de flujo

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.

CLIPS> (defrule BORRA.ENTEROS


?d <- (A ?valor)
(if (integerp ?valor) then (retract ?d)))
Tener en cuenta que el uso de la palabra then es obligatorio.

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.

CLIPS> (defrule SUMA-ENTEROS


(A ?valor)
(if (and (integerp ?valor) (> ?valor 0)) then
(bind ?suma ?valor)
(while (> ?valor 0)
(bind ?valor (- ?valor 1))
(bind ?suma (+ ?suma ?valor))
)
(printout t ?suma crlf)
else (printout t “EL VALOR NO ES ENTERO POSITIVO” crlf) ) )

6.4 Ejercicios.

Para cada caso escriba el programa correspondiente validando la entrada de datos.

1. Leer diez números enteros y obtenga como resultado su sumatoria.


2. Simular el funcionamiento del ciclo for de C/C++, el valor inicial, el valor final y el valor
correspondiente al incremento de la variable de control los proporciona el usuario en tiempo de
ejecución. Se debe mostrar un mensaje que identifique cada iteración.
3. Calcular el factorial de cualquier entero.
4. Obtener los primeros N términos de la serie de Fibonacci.
5. Leer un entero positivo y determine si es o no perfecto.
6. Dados dos conjuntos A y B determinar si uno de ellos es subconjunto del otro.
7. Determinar si un valor específico existe como elemento de un conjunto previamente
definido.
8. Tomando como base el ejercicio 4.8 borrar de la lista un conjunto de hechos especificado
por el usuario.
9. Tomando como base el ejercicio 4.5 leer los datos de N rectángulos, calcular el área
promedio y el número de rectángulos cuya área es inferior al promedio. Si se introducen datos
errados se debe mostrar un mensaje de error y continuar el proceso.
10. Para un conjunto de polígonos de los que se conoce el valor del perímetro y el número de
lados, determinar cuáles son regulares con lados de valor entero.
11. Escriba un programa que despliegue un menú de opciones y valide la selección del usuario.
Capítulo 7: VARIABLES GLOBALES Y FUNCIONES DEL USUARIO

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.

7.1 Variables globales.

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.

CLIPS> (defglobal ?*V1* = 51


?*V2* = 4.021
?*V3* = "Cadena")
CLIPS> ?*V1*
51
CLIPS> ?*V2*
4.021
CLIPS> ?*V3*
"Cadena"

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.

CLIPS> (assert (Prueba 20))


<Fact-0>
CLIPS> (defrule R (Prueba ?*V1*)
=> (printout "El valor es " ?*V1* crlf))

Salvo la restricción señalada anteriormente, las variables globales se pueden utilizar en cualquier
otro contexto como se muestra a continuación.

CLIPS> (assert (Valor (* ?*V1* 5)))


<Fact-1>
CLIPS> (facts)
f-0 (Prueba 20)
f-1 (Valor 255)
For a total of 2 facts.
CLIPS> (bind ?*V2* (+ ?*V2* 5.5))
9.521

7.2 Funciones de campo múltiple.


create$, concatena cero o más expresiones para formar un valor de campo múltiple.

CLIPS> (defglobal ?*q* = (create$ Nas 12 "Solo"))


CLIPS> ?*q*
(Nas 12 "Solo")

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.

multifieldp, devuelve verdadero si su argumento es un valor múltiple o falso en caso


contrario.

CLIPS> (defglobal ?*q* = (create$ Nas 12 "Solo")


?*p* = 7)
CLIPS> (multifieldp ?*q*)
TRUE
CLIPS> (multifieldp ?*p*)
FALSE

delete$, elimina los campos correspondientes al rango especificado.

CLIPS> (defglobal ?*q* = (create$ Uno Dos Tres Cuatro Cinco))


CLIPS> ?*q*
(Uno Dos Tres Cuatro Cinco)
CLIPS> (delete$ ?*q* 2 3)
(Uno Cuatro Cinco)

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)

subset$, extrae los campos correspondientes al rango especificado devolviéndolos como


un valor de campo múltiple.

CLIPS> (subset$ ?*q* 1 2)


(Uno Dos)

rest$, devuelve un valor de campo múltiple formado por los valores de su argumento sin
incluir el primer campo.

CLIPS> (rest$ ?*q*)


(Dos Tres Cuatro Cinco)

nth$, devuelve el valor del enésimo campo de su argumento.


CLIPS> (nth$ 3 ?*q*)
Tres

explode$, devuelve un valor de campo múltiple formado por los elementos de una cadena.

CLIPS> (explode$ "Esta es una cadena")


(Esta es una cadena)

length$, devuelve la cantidad de campos que forman un valor múltiple.

CLIPS> (length$ ?*q*)


5

Se obtiene el mismo resultado si se utiliza length.

first$, devuelve el valor correspondiente al primer campo de su argumento.

CLIPS> (first$ ?*q*)


(Uno)

implode$, devuelve una cadena formada por los valores de los campos de su argumento.

CLIPS> (implode$ ?*q*)


"Uno Dos Tres Cuatro Cinco"

insert$, inserta un valor sencillo o múltiple antes del campo especificado para su primer
argumento.

CLIPS> (insert$ ?*q* 1 Cero)


(Cero Uno Dos Tres Cuatro Cinco)
CLIPS> (insert$ ?*q* 3 (create$ 1 2))
(Uno Dos 1 2 Tres Cuatro Cinco)

El efecto se causa sobre el resultado pero la variable conserva su valor.

CLIPS> ?*q*
(Uno Dos Tres Cuatro Cinco)

member$, devuelve la posición de la primera ocurrencia de un valor sencillo en un valor


múltiple o falso si no se encuentra.

CLIPS> (member$ Dos ?*q*)


2
CLIPS> (member$ Seis ?*q*)
FALSE

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)

El efecto se causa sobre el resultado pero la variable conserva su valor.

CLIPS> ?*q*
(Uno Dos Tres Cuatro Cinco)

subsetp, devuelve verdadero si su primer argumento es un subconjunto del segundo o


falso en caso contrario.

CLIPS> (defglobal ?*p* = (create$ Tres Cuatro)


?*r* = (create$ Tres Cinco)
?*s* = (create$ Dos Ocho))
CLIPS> (subsetp ?*p* ?*q*)
TRUE
CLIPS> (subsetp ?*r* ?*q*)
TRUE
CLIPS> (subsetp ?*s* ?*q*)
FALSE
CLIPS> (subsetp ?*q* ?*p*)
FALSE

7.3 Funciones del usuario.

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.

CLIPS> (deffunction Mensaje ()


(printout t “ESTE ES EL MENSAJE”))
CLIPS> (Mensaje)
ESTE ES EL MENSAJE

La función Mensaje se define sin parámetros y por lo tanto se llama sin argumentos.

CLIPS> (deffunction Perfecto (?n)


(bind ?suma 1)
(bind ?maxdiv (div ?n 2))
(while (> ?maxdiv 1)
(if (= (mod ?n ?maxdiv) 0) then
(bind ?suma (+ ?suma ?maxdiv))
)
(bind ?maxdiv (- ?maxdiv 1))
)
(if (= ?n ?suma) then (return 1)
else (return 0))
)
CLIPS> (Perfecto 6)
1
CLIPS> (Perfecto 10)
0

La función retorna 1 si su argumento es un número perfecto o 0 en caso contrario.


CLIPS> (deffunction F (?n)
(if (= ?n 1) then (return 0)
else
(if (< ?n 4) then (return 1)
else
(return (+ (F (- ?n 1)) (F (- ?n 2))))
)))
CLIPS> (F 4)
2

La función implementa una solución recursiva para obtener el enésimo término de la secuencia de
FIBONACCI.

7.4 Ejercicios.

1. ¿Qué sucede si la función create$ se llama sin argumentos?


2. ¿Qué ocurre si al llamar funciones como delete$ el tercer argumento es mayor que
el número de campos del primer argumento?
3. En el mismo sentido del ejercicio anterior, ¿Qué ocurre si el primer argumento es menor o
igual que cero?
4. Escriba una función que determine la cantidad de veces que un valor está contenido en un
campo múltiple.
5. ¿Es posible utilizar las funciones de campo múltiple con variables locales? Sustente la respuesta
con de ejemplos.
6. Simule el funcionamiento de un ciclo while utilizando variables globales.
7. Un campo múltiple puede estar formado por cualquier cantidad de valores numéricos,
escriba una función que obtenga como resultado la suma de dichos valores.
8. Escriba una función iterativa para encontrar el enésimo término de la secuencia de FIBONACCI.
Se espera que este texto sea de gran ayuda a los estudiantes que intentan construir sus primeros
SBC.

Referencias:

• Enrique Castillo, José Manuel Gutiérrez, y Ali S. Hadi Sistemas Expertos y Modelos de
Redes Probabilísticas

• Giarratano y Riley, Sistemas Expertos: Principios y Programación (3ra Edición)

• Carlos Martínez García, Programación en lenguaje clips, editorial universitaria Ramón


Areces, 2008

• clipsrules.sourceforge.net/, Página oficial de CLIPS

También podría gustarte