Está en la página 1de 13

CLIPS aplicado a la representación de un problema basado en

estados y transiciones (hechos y reglas) sin búsqueda


Ricardo Aler Mur

Índice
1. El problema 2

2. Representación de los estados 2

3. Creación del estado inicial 2

4. Especificación de las transiciones 3


4.1. Definición de las reglas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
4.2. Equiparación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

5. Modificación de la base de hechos (o memoria de trabajo) 5

6. Condición de fin 5

7. Ejecución del programa 6

8. Prioridad para las reglas 10

9. Otras cuestiones importantes (refracción y activación múltiple de la misma regla) 11

10. Conclusión 12

11. Ejercicio 13

1
1. El problema
Vamos a intentar representar por medio de un sistema de producción el siguiente problema: Queremos
poner 3 litros en una jarra.

Partimos de un estado inicial: la jarra está vacı́a.

Queremos llegar a un estado final: la jarra contiene tres litros.

A partir del estado inicial, los únicos cambios que le podemos hacer a la jarra son:

• Añadirle un litro, o
• Añadirle dos litros.

Como vemos, nuestro problema involucra:

Estados (en este caso, el número de litros en la jarra). Los estados de un problema se pueden representar
por medio de hechos.

Transiciones entre estados (se puede pasar de un estado a otro, bien añadiendo 1 litro, bien añadiendo 2
litros). Las transiciones entre estados de un problema se pueden representar por medio de reglas.

Ahora veremos como se representarı́a en CLIPS este problema.

2. Representación de los estados


Primero veremos como representar los estados del problema (una jarra que contenga un cierto número de
litros). Para ello, podemos usar una plantilla (o template), como la siguiente:

(deftemplate jarra
(slot litros
(type INTEGER)
(default 0)))
Una plantilla, es una estructura compuesta de varios campos (o slots). En nuestro caso hemos definido la
plantilla jarra. Esta plantilla consta de un solo slot (o campo): litros. Este slot es de tipo entero (INTEGER) y
tiene un valor por omisión de 0 (default0). Esto quiere decir que si creamos un hecho de jarra y no especificamos
el número de litros que contiene, el valor que se le dará será 0.
Una deftemplate solo define la plantilla (la estructura) de los hechos de tipo jarra, pero por si sola no crea
ningún hecho en la memoria del ordenador 1 . Por tanto es necesario crear el hecho que representa el estado
inicial (la jarra vacı́a) de alguna manera.

3. Creación del estado inicial


Podemos crear el estado inicial con la siguiente declaración de regla:

(defrule estado-inicial

=>
(assert (jarra)))

Esta regla añade un hecho de jarra a la memoria de hechos. Pero veamos antes que es una regla en CLIPS.
Una regla CLIPS consta de dos partes:
1
La parte de un sistema de producción que contiene los hechos se denomina base de hechos o memoria de trabajo

2
La parte izquierda, o condición (o LHS, “Left hand side”), que va antes del =>.
La parte derecha, o acción (o RHS, “Right hand side”), que va después del =>.

La parte izquierda de una regla comprueba si ciertos hechos están en la base de hechos. En este caso
particular, nuestra regla no comprueba nada (la parte anterior a => está vacı́a), por lo que su condición se
cumple siempre. Caso de que se cumpla la parte izquierda de la regla, se ejecuta la parte derecha de la regla.
Genéricamente, la parte derecha de una regla puede:

Añadir hechos a la memoria de trabajo.


Quitar hechos de la memoria de trabajo.
Modificar hechos de la memoria de trabajo.

En nuestro caso particular, esta regla añade un hecho a la memoria de trabajo por medio de:

(assert (jarra))

Obsérvese que no hemos especificado el número de litros que va a tener el hecho de jarra recién creada.
Antes veı́amos que la plantilla de jarra tenı́a un valor por omisión de 0 para el slot litros, por tanto ese es el
valor que se le asignará. Hubiéramos podido decir explı́citamente el número de litros del hecho inicial de jarra
con:

(assert (jarra (litros 0)))

Y si hubiéramos querido crear una jarra inicial con 5 litros, hubiéramos escrito:

(assert (jarra (litros 5)))

Bien, ya tenemos la regla que crea el estado inicial: un hecho de jarra con 0 litros, pero todavı́a no tenemos
dicho hecho en la memoria de trabajo: hasta que el sistema no se ejecute y la regla se dispare, el hecho no
pasará a existir.
Veamos ahora como especificar las transiciones entre estados para nuestro problema. Recordemos que habı́a
que hacerlo con reglas.

4. Especificación de las transiciones


4.1. Definición de las reglas
Nuestro problema podı́a experimentar dos tipos de transiciones: añadir 1 litro a la jarra, o añadir 2 litros.
Estas transiciones se pueden representar de una manera muy sencilla con reglas:

Si tenemos una jarra con x litros, entonces añadir 1 litro.


Si tenemos una jarra con x litros, entonces añadir 2 litros.

Y en la sintaxis de CLIPS:
(defrule un-litro-mas
?jarra <- (jarra (litros ?litros))
=>
(modify ?jarra (litros (+ ?litros 1))))

(defrule dos-litros-mas
?jarra <- (jarra (litros ?litros))
=>
(modify ?jarra (litros (+ ?litros 2))))

3
Ambas reglas son muy similares, ası́ que solo analizaremos la primera. En la parte izquierda de la regla
un-litro-mas hemos especificado la condición:

(jarra (litros ?litros))

Cuando CLIPS se encuentra condiciones de ese tipo, lo que hace es intentar equipararlas con los hechos
de la memoria de trabajo.

4.2. Equiparación
En este apartado veremos de manera genérica la idea de equiparación con un ejemplo relacionado: los
nombres de fichero del sistema operativo DOS (o UNIX). Por ejemplo, cuando escribimos algo como:

DIR pp*.txt

lo que le estamos pidiendo a DOS es que nos muestre todos los ficheros que empiezan por pp y tienen de tipo
txt (usamos a * como comodı́n) . Todos los nombres de fichero del directorio que cumplan esas caracterı́sticas
se dice que equiparan con el patrón pp*.txt. Por ejemplo, si en el directorio tuviéramos estos ficheros:
ppuno.txt
ppdos.txt
pptres.txt

fich1.c
ppfich.c
Solo los tres primeros equipararı́an, pero no los dos últimos.
De la misma manera, si tuvieramos el patrón CLIPS

(jarra (litros ?))

y en la memoria de trabajo tuviéramos los hechos:


(jarra (litros 1))
(jarra (litros 101))

(jarra (peso 50))


(mesa (peso 30))
solo los dos primeros equipararı́an, pero no ası́ los dos últimos (nota: el comodı́n ? en CLIPS equipara con
cualquier cosa: un número, un carácter, una cadena, a diferencia de DOS en el que el comodı́n ? equipara solo
con un carácter).
Pero el elemento de condición que estábamos analizando no era (jarra (litros ?)), sino:

(jarra (litros ?litros))

Este elemento de condición es similar, excepto que en lugar de ? hemos puesto ?litros. ?litros actúa también
como comodı́n, pero además es una variable CLIPS. Esta variable tomará el valor de lo que hubiera equiparado
con el comodı́n. Por ejemplo, si en la memoria de trabajo tuviéramos los hechos vistos anteriormente, nuestro
elemento de condición equipararı́a con:
(jarra (litros 1))
(jarra (litros 101))
En el primer caso, la variable ?litros contendrı́a 1, y en el segundo caso contendrı́a 101. El contenido de
dichas variables solo tiene sentido dentro de la regla en que se equiparan. En el siguiente apartado veremos
como podemos usar el valor de dicha variable dentro de la regla.

4
5. Modificación de la base de hechos (o memoria de trabajo)
Estábamos analizando la regla:

(defrule un-litro-mas
?jarra <- (jarra (litros ?litros))
=>
(modify ?jarra (litros (+ ?litros 1))))

que, recordemos, querı́amos que representara la transición desde un estado en el que la jarra contenı́a un
número ?litros de litros a un estado en el que contendrı́a ?litros + 1 litros. Ahora podemos ver con mas detalle
el significado de la regla anterior:

1. Equiparamos la parte izquierda de la regla con la jarra que hay en la memoria de trabajo

2. Modificamos esa jarra para que el valor de su slot litros contenga un litro mas.

El segundo paso, la modificación, lo hacemos en la parte derecha de la regla con:

(modify ?jarra (litros (+ ?litros 1)))

Pero para modificar un hecho de jarra que hemos equiparado en la parte izquierda, tendrı́amos que haberle
dado un nombre previamente en esa misma parte izquierda. Eso lo hacemos con ?jarra <- en:

?jarra <- (jarra (litros ?litros))

?jarra es también una variable CLIPS, pero a diferencia de ?litros que contenı́a un valor, esta contiene un
hecho entero, precisamente el que hemos equiparado con (jarra (litros ?litros)). Ese es el que modificamos en
la parte derecha con (modify ?jarra (litros (+ ?litros 1))).
En resumen, si hubiéramos partido de la base de hechos:

(jarra (litros 0))

(que es la que construı́a la regla estado-inicial), y se hubiera disparado la regla un-litro-mas, nos resultarı́a
en la base de hechos:

(jarra (litros 1))

6. Condición de fin
Además, podemos añadir una regla a la base de reglas que nos indique cuando el sistema de producción ha
alcanzado el estado deseado (en nuestro caso, que la jarra contenga 3 litros). Esa regla se escribirı́a como:

(defrule acabar
(jarra (litros 3))
=>
(printout t "Lo he conseguido" crlf))

Esta regla equipararı́a solo cuando en la base de hechos haya un hecho como (jarra (litros 3)). Además
vemos algo nuevo en la parte derecha: printout, que es una función CLIPS que sirve para imprimir por pantalla.
crlf significa que al final se imprime un retorno de carro. En general, en la parte derecha de una regla, además
de poder modificar la base de hechos (con assert, retract o modify, podemos llamar a cualquier función del
lenguaje CLIPS.

5
7. Ejecución del programa
Nuestro programa CLIPS completo es:

; Define la plantilla para la jarra


(deftemplate jarra
(slot litros
(type INTEGER)
(default 0)))

;; Inicializa la base de hechos


(defrule estado-inicial

=>
(assert (jarra)))

;; Añade un litro
(defrule un-litro-mas
?jarra <- (jarra (litros ?litros))
=>
(modify ?jarra (litros (+ ?litros 1))))

;; Añade dos litros


(defrule dos-litros-mas
?jarra <- (jarra (litros ?litros))
=>
(modify ?jarra (litros (+ ?litros 2))))

;; Comprueba terminación
(defrule acabar
(jarra (litros 3))
=>
(printout t "Lo he conseguido" crlf))

Para ejecutarlo, realicemos los siguientes pasos:

Carguemos el programa:

CLIPS> (load "ejemplo_jarra.clp")


Defining deftemplate: jarra
Defining defrule: estado-inicial +j
Defining defrule: un-litro-mas +j
Defining defrule: dos-litros-mas +j
Defining defrule: acabar +j
TRUE

Digámosle a CLIPS que queremos ver que reglas se disparan (watch rules) y que hechos se ponen y se
quitan de la memoria de trabajo (watch facts). Escribamos también (unwatch compilations) para no ver
mensajes relativos a la compilación de las reglas2 .
2
(watch activations) permite ver que reglas se van activando. Para mas información, consultar el manual de referencia.

6
Hagamos (reset) para limpiar el sistema y para que se añada el hecho (initial-fact) a la memoria de
trabajo, que es necesario para que las reglas que no tienen nada en la parte izquierda se puedan disparar
(por ejemplo, nuestra primera regla).

CLIPS> (reset)
==> f-0 (initial-fact)

La flecha ==> quiere decir que se ha añadido el hecho inicial (initial-fact).

Ejecutémoslo. Vamos a permitir que se disparen las reglas solo 5 veces ((run 5)).

CLIPS> (run 5)
FIRE 1 estado-inicial: f-0
==> f-1 (jarra (litros 0))
FIRE 2 un-litro-mas: f-1
<== f-1 (jarra (litros 0))
==> f-2 (jarra (litros 1))
FIRE 3 un-litro-mas: f-2
<== f-2 (jarra (litros 1))
==> f-3 (jarra (litros 2))
FIRE 4 un-litro-mas: f-3
<== f-3 (jarra (litros 2))
==> f-4 (jarra (litros 3))
FIRE 5 un-litro-mas: f-4
<== f-4 (jarra (litros 3))
==> f-5 (jarra (litros 4))

En la traza podemos ver varias cosas:

1. Que la regla estado-inicial equipara con el hecho f-0, se dispara y añade el hecho f-1 ((jarra (litros
0))).
2. Que la regla un-litro-mas equipara con el hecho f-1, la cual se dispara, quita el hecho (jarra (litros
0)) y añade el hecho (jarra (litros 1)) (observar que para CLIPS, modificar un hecho equivale a
quitar el hecho antiguo y a añadir el modificado).
3. Que se vuelve a disparar la regla un-litro-mas
4. Y ası́ sucesivamente. La regla que comprueba si hemos llegado al hecho deseado (acabar ) no se
dispara nunca.

Algo ha ido mal: se ha disparado siempre la misma regla y la jarra se ha llenado demasiado. Vayamos paso
por paso para ver que ocurre:

Primero reset. Después veamos que reglas están activas (una regla está activa si podrı́a dispararse. El
conjunto de reglas activas se denomina agenda. Solo una regla puede dispararse en cada ciclo) con
(agenda)

CLIPS> (reset)
CLIPS> (agenda)
0 estado-inicial: f-0
For a total of 1 activation.

7
Cuadro 1: resumen de la traza
ciclo Hechos Reglas en la agenda Regla que se dispara
1 initial-fact estado-inicial estado-inicial
2 (jarra (litros 0)) un-litro-mas
(initial-fact) dos-litros-mas un-litro-mas
3 (jarra (litros 1)) un-litro-mas
(initial-fact) dos-litros-mas un-litro-mas
4 ... ... un-litro-mas
5 (jarra (litros 3)) un-litro-mas
(initial-fact) dos-litros-mas
acabar un-litro-mas
6 ... ... un-litro-mas

Vemos que solo hay una regla activada, la estado-inicial.

Demos otro paso ((run 1)):

CLIPS> (run 1)
FIRE 1 estado-inicial: f-0
==> f-1 (jarra (litros 0))
CLIPS> (agenda)
0 un-litro-mas: f-1
0 dos-litros-mas: f-1
For a total of 2 activations.

Tras dispararse estado-inicial, hay dos reglas activas: un-litro-mas y dos-litros-mas (ambas equiparan
con el mismo hecho: f-1 ).

Demos otro paso:

CLIPS> (run 1)
FIRE 1 un-litro-mas: f-1
<== f-1 (jarra (litros 0))
==> f-2 (jarra (litros 1))
CLIPS> (agenda)
0 un-litro-mas: f-2
0 dos-litros-mas: f-2
For a total of 2 activations.

Vemos que se ha disparado un-litro-mas y que un-litro-mas y dos-litros-mas vuelven a estar disponibles
para dispararse (ahora equiparan con f-2, la jarra resultante de añadir 1 litro a la jarra vacı́a).

Un par de pasos mas:

8
CLIPS> (run 1)
FIRE 1 un-litro-mas: f-2
<== f-2 (jarra (litros 1))
==> f-3 (jarra (litros 2))
CLIPS> (agenda)
0 un-litro-mas: f-3
0 dos-litros-mas: f-3
For a total of 2 activations.

CLIPS> (run 1)
FIRE 1 un-litro-mas: f-3
<== f-3 (jarra (litros 2))
==> f-4 (jarra (litros 3))
CLIPS> (agenda)
0 un-litro-mas: f-4
0 dos-litros-mas: f-4
0 acabar: f-4
For a total of 3 activations.

CLIPS> (run 1)
FIRE 1 un-litro-mas: f-4
<== f-4 (jarra (litros 3))
==> f-5 (jarra (litros 4))
CLIPS> (agenda)
0 un-litro-mas: f-5
0 dos-litros-mas: f-5
For a total of 2 activations.

Ya vemos cual es el problema: de todas las reglas activas, en cada ciclo se dispara siempre la primera
de la agenda. A la manera en la que un sistema de producción ordena las activaciones se la denomina
estrategia de control o estrategia de resolución de conflictos. En el caso de CLIPS, las reglas de la
agenda se ordenan de la siguiente manera:

• Una regla recien activada se coloca sobre todas las reglas de menor prioridad y debajo de las reglas
de mayor prioridad. Después se verá que es la prioridad de una regla, pero por el momento será su-
ficiente saber que es un número que se asigna a una regla y que determina el orden en el que se
colocan esas reglas en la agenda.
• Se usa alguna estrategia de resolución de conflictos para ordenar las reglas con la misma prioridad.
Por omisión, la estrategia de resolución de conflictos es profundidad.
• Si dos (o mas) reglas se activan a la vez por la misma aserción o borrado de un hecho, y los
pasos anteriores no bastan para ordenarlas, entonces esas reglas se ordenan de manera arbitraria.
Aunque esta ordenación arbitraria depende del orden en el que se escribieron las reglas, no se
deberı́a depender de esa ordenación.

La estrategia de control por omisión es profundidad. Esta estrategia consiste en que las reglas recien ac-
tivadas se colocan encima de las reglas con la misma prioridad. Si dos reglas se activan al mismo tiempo
con los mismos hechos y tienen la misma prioridad, su ordenación será arbitraria, como se comentaba
antes. Por contra la estrategia anchura coloca (en la agenda) las reglas recien activadas debajo de las acti-
vadas anteriormente, si tienen la misma prioridad. Existen otras estrategias de control, como simplicidad,
complejidad, LEX, MEA y random (ver manual de referencia pp 27-29). Para poner una estrategia de
control distinta a la de profundidad, usar el comando set-strategy. Ej: (set-strategy random).

9
Veiamos antes que, de todas las reglas activas, siempre se disparaba la primera de la agenda: un-litro-mas.
¿Por qué?. Pues porque al añadirse el hecho f5, ambas reglas un-litro-mas y dos-litros-mas se activan
al mismo tiempo. A falta de otros criterios de ordenación, el sistema pone antes la regla que primero
encontró en el código. De esa manera jamás se llega a disparar dos-litros-mas ni acabar. Una manera
sencilla de determinar el orden en el que se deben ordenar las activaciones de reglas en la agenda es la
prioridad, como se verá a continuación.

8. Prioridad para las reglas

Para solucionar el problema anterior (que la regla que comprueba el final jamás se dispara), lo ideal serı́a
poderle decirle a CLIPS que la regla acabar deberı́a dispararse siempre antes que ninguna otra. Esto se
puede hacer dándoles una prioridad (o en la terminologı́a de CLIPS, una “salience”) a las reglas. Por
ejemplo, la siguiente declaración le da una prioridad de 1000 (por omisión es 0) a la regla acabar:

;; Comprueba terminación con salience


(defrule acabar
(declare (salience 1000))
(jarra (litros 3))
=>
(printout t "Lo he conseguido" crlf))

Si lo hacemos, veremos que al ejecutar el sistema, la traza es correcta y termina bien:

CLIPS> (reset)
<== f-0 (initial-fact)
<== f-5 (jarra (litros 4))
==> f-0 (initial-fact)
CLIPS> (run 5)
FIRE 1 estado-inicial: f-0
==> f-1 (jarra (litros 0))
FIRE 2 un-litro-mas: f-1
<== f-1 (jarra (litros 0))
==> f-2 (jarra (litros 1))
FIRE 3 un-litro-mas: f-2
<== f-2 (jarra (litros 1))
==> f-3 (jarra (litros 2))
FIRE 4 un-litro-mas: f-3
<== f-3 (jarra (litros 2))
==> f-4 (jarra (litros 3))
FIRE 5 acabar: f-4
Lo he conseguido

Desgraciadamente, esto no acaba con nuestros problemas, porque si lo ejecutamos un paso mas:

CLIPS> (run 1)
FIRE 1 un-litro-mas: f-4
<== f-4 (jarra (litros 3))
==> f-5 (jarra (litros 4))

vemos que el sistema sigue ejecutandose. Esto es ası́ porque aunque la regla acabar se ha ejecutado, todavı́a
quedan dos reglas activas en la agenda: un-litro-mas y dos-litros-mas. Podemos comprobarlo:

10
CLIPS> (agenda)
0 un-litro-mas: f-5
0 dos-litros-mas: f-5
For a total of 2 activations.
Y están activas porque hay un hecho de jarra en la memoria. Por tanto, para que el sistema termine real-
mente, será necesario borrar el hecho de jarra de la memoria de trabajo. Para conseguirlo, la regla de acabar
tendrá que retirar también el hecho de jarra que haya en la memoria. Nuestra nueva regla acabar será:
; Quita la jarra
(defrule acabar
(declare (salience 1000))
?jarra <- (jarra (litros 3))
=>
(printout t "Lo he conseguido" crlf)
(retract ?jarra))
Lo único nuevo que hemos añadido es (retract ?jarra), que sirve para quitar de la memoria de trabajo, el
hecho contenido en la variable ?jarra. Notar que hemos usado <- para asignar a ?jarra el hecho que equipara
con (jarra (litros 3)), para poder borrarla después.
Todavı́a queda otro problema por resolver: la regla dos-litros-mas no se dispara nunca. Podemos intentar
resolver el problema como antes, dándole una prioridad mas alta a dos-litros-mas (hacerlo), pero en ese caso
descubriremos que dos-litros-mas se disparará siempre y un-litro-mas no se disparará nunca. Lo que es peor,
ahora el contenido de la jarra seguirá la secuencia 0, 2, 4, 6, . . . , con lo que la regla acabar no tendrá oportunidad
de dispararse nunca. Esto nos lleva a un par de conclusiones importantes:
El que un problema representado por medio de un sistema de producción encuentre solu-
ción o no, depende en gran medida de la estrategia de control.

Un problema representado por medio de un sistema de producción no tiene por qué encon-
trar una solución.

9. Otras cuestiones importantes (refracción y activación múltiple de la misma


regla)
Antes de concluir vamos a examinar dos cuestiones sobre la ejecución de las fases de CLIPS.

Refracción: Por omisión, CLIPS nunca ejecuta la misma regla dos ciclos seguidos usando el mismo
hecho. Esto se puede ver en el ejemplo anterior. El hecho (initial-fact) permanece en la memoria de
trabajo durante toda la ejecución del sistema. Sin embargo, la regla estado-inicial solo se activa en el
ciclo número 1. Una vez que la regla se ha activado y disparado, ya no se volverá a ejecutar con el mismo
hecho nunca más, a menos que el hecho sea modificado por una orden modify. Esto es ası́ para evitar que
una regla se dispare continuamente y el sistema entre en un ciclo infinito.

Activación múltiple de la misma regla con distintos hechos: Hasta ahora, en la memoria de trabajo
nunca ha habido más de un hecho de tipo jarra en todo momento. Por tanto, la parte izquierda de una
regla solo se podı́a emparejar con un solo hecho en la memoria de trabajo. Sin embargo, si existieran
varios hechos de tipo jarra en la memoria de trabajo, una misma regla se activarı́a tantas veces como
hechos equipararan con su parte izquierda. Más concretamente, si la memoria de trabajo contuviera los
hechos:

CLIPS> (facts)
f-0 (jarra (litros 1))
f-1 (jarra (litros 2))

11
f-2 (jarra (litros 0))
For a total of 3 facts.

darı́a lugar a la siguiente agenda, en la que cada una de las dos reglas está emparejada con cada uno de
los tres hechos (f0, f1 y f2), resultando en 3 activaciones por regla y 6 activaciones en total. Por tanto, la
estrategia de control deberı́a elegir una de entre esas 6 activaciones para dispararla en la siguiente fase.
A continuación se muestra dicha agenda:

CLIPS> (agenda)
0 un-litro-mas: f-2
0 dos-litros-mas: f-2
0 un-litro-mas: f-1
0 dos-litros-mas: f-1
0 un-litro-mas: f-0
0 dos-litros-mas: f-0
For a total of 6 activations.

10. Conclusión
Hemos visto como podemos representar un problema que consta de estados y transiciones entre estados por
medio de hechos y de reglas, es decir, por medio de un sistema de producción. Para representar un problema de
este tipo en un sistema de producción, hay que especificar:
La representación de los estados del problema (por medio de los deftemplates adecuados).
El estado inicial (hechos iniciales).
Las transiciones entre estados (las reglas que representan las transiciones entre estados).
El estado final (regla que detecta cuando se ha alcanzado una solución).
El sistema de producción funciona en ciclos sucesivos, que se ejecutan hasta que no haya mas reglas activas.
Un ciclo consta de:
Determinar que reglas están activas (equiparando sus partes izquierdas con la base de hechos). Las reglas
activas constituyen la agenda.
Determinar que regla se debe disparar en ese ciclo (por medio de la estrategia de control, que puede ser
tan simple como elegir la regla que tenga prioridad máxima).
Disparar la regla elegida ejecutando su parte derecha. Esto normalmente cambiará la base de hechos
(borrando hechos, añadiendo hechos o modificando hechos).
Una misma regla puede equiparar con varios hechos de la memoria de trabajo, por lo que lo que hay en
la agenda no son exactamente las reglas activas, sino parejas (regla, hecho(s) que equipara(n) con esa regla),
aunque por resumir se habla de reglas solamente.
Dicho de otra manera, los componentes básicos de un sistema de producción son:
Base de hechos (o memoria de trabajo).
Base de reglas.
Estrategia de control.
Por último, un sistema de producción con una estrategia de control determinista, puede no encontrar la solu-
ción al problema representado con ese sistema. Eso es debido a que la estrategia de control se haya equivocado
al elegir una regla en lugar de otra en algún momento. La única manera de solucionar ese problema es utilizar
búsqueda en el espacio de estados, la cuál se verá mas adelante.

12
11. Ejercicio
1. Representar el siguiente problema por medio de un sistema de producción. Tenemos dos jarras, una de 4
litros y otra de 3 litros. Ninguna de ellas tienen marcas que permitan identificar cuanta agua hay en ellas.
Hay un grifo que permite llenar las jarras. El problema consiste en acabar teniendo exactamente 2 litros
de agua en la jarra de 4 litros.
En concreto, especificar:

La representación del estado.


La regla que pone los hechos iniciales.
Las reglas que especifican las posibles transiciones.
La regla que detecta el estado final.

Nota: Además de lo ya visto, será necesario usar las siguientes construcciones:

(test (neq ?jarra1 ?jarra2)). En la parte izquierda, además de poner patrones para que equiparen con
la base de hechos, se pueden poner condiciones que deben cumplir las variables. Esta por ejemplo
comprueba que dos variables no son iguales.
(test (<= (+ ?litros1 ?litros2) ?capacidad2)). Esta otra comprueba que la suma de dos variables
?litros1 y ?litros2 es menor o igual que otra variable llamada capacidad

13

También podría gustarte