Práctica: Representación del Conocimiento Basada en reglas

      1. Objetivo de la práctica

      El objetivo de esta práctica es escribir un programa CLIPS que resuelva el problema de las fichas. Primero estudia el siguiente código para resolver el problema del ocho puzzle en CLIPS. A continuación implementa de forma similar el problema de las fichas.
       

      2. El problema del 8-puzzle resuelto en CLIPS

Estado Inicial
 
2 8 3
1 6 4
7   5
Estado Final
 
1 2 3
8   4
7 6 5
    (deftemplate MAIN::nodo
   (multislot estado)
   (multislot camino)
   (slot heuristica)
   (slot clase (default abierto)))

(defglobal MAIN
   ?*estado-inicial* = (create$ 2 8 3 1 6 4 7 H 5)
   ?*estado-final* = (create$ 1 2 3 8 H 4 7 6 5))

(deffunction MAIN::heuristica ($?estado)
   (bind ?res 0)
   (loop-for-count (?i 1 9)
    (if (neq (nth ?i $?estado)
             (nth ?i ?*estado-final*))
         then (bind ?res (+ ?res 1))
     )
    )
   ?res)

(defrule MAIN::inicial
   =>
   (assert (nodo (estado ?*estado-inicial*)
                  (camino)
                  (heuristica (heuristica ?*estado-inicial*))
                  (clase cerrado))))

(defrule MAIN::arriba
   (nodo (estado $?a ?b ?c ?d H $?e)
          (camino $?movimientos)
          (clase cerrado))
=>
   (bind $?nuevo-estado (create$  $?a H ?c ?d ?b $?e))
   (assert (nodo (estado $?nuevo-estado)
                 (camino $?movimientos ^)
                 (heuristica (heuristica $?nuevo-estado)))))

(defrule MAIN::abajo
   (nodo (estado $?a H ?b ?c ?d  $?e)
          (camino $?movimientos)
          (clase cerrado))
=>
   (bind $?nuevo-estado (create$ $?a ?d ?b ?c H $?e))
   (assert (nodo (estado $?nuevo-estado)
                 (camino $?movimientos v)
                 (heuristica (heuristica $?nuevo-estado)))))

(defrule MAIN::izquierda
   (nodo (estado $?a&:(neq (mod (length $?a) 3) 2)
                   ?b H $?c)
          (camino $?movimientos)
          (clase cerrado))
=>
   (bind $?nuevo-estado (create$ $?a H ?b $?c))
   (assert (nodo (estado $?nuevo-estado)
                 (camino $?movimientos <)
                 (heuristica (heuristica $?nuevo-estado)))))

(defrule MAIN::derecha
   (nodo (estado $?a H ?b
                 $?c&:(neq (mod (length $?c) 3) 2))
          (camino $?movimientos)
          (clase cerrado))
 =>
   (bind $?nuevo-estado (create$ $?a ?b H $?c))
   (assert (nodo (estado $?nuevo-estado)
                 (camino $?movimientos >)
                 (heuristica (heuristica $?nuevo-estado)))))

(defrule MAIN::pasa-el-mejor-a-cerrado
   (declare (salience -10))
   ?nodo <- (nodo (clase abierto)
                  (heuristica ?h1))
   (not (nodo (clase abierto)
              (heuristica ?h2&:(< ?h2 ?h1))))
=>
   (modify ?nodo (clase cerrado)))

;;; Modulo restricciones
 

(defrule MAIN::repeticiones-de-nodo
   (declare (auto-focus TRUE))
   (nodo (estado $?actual)
         (camino $?movimientos-1))
   ?nodo <- (nodo (estado $?actual)
                  (camino $?movimientos-1 ? $?))
 =>
   (retract ?nodo))

;;; Modulo solucion
 

(defrule MAIN::reconoce-solucion
   (declare (auto-focus TRUE))
   ?nodo <- (nodo (heuristica 0)
               (camino $?movimientos))
 =>
   (retract ?nodo)
   (assert (solucion $?movimientos)))

(defrule MAIN::escribe-solucion
   (solucion $?movimientos)
  =>
   (printout t "Solucion:" $?movimientos crlf)
   (halt))
 
 

 

      3. El problema de las fichas

La situación inicial es  
B
B
B
 
V
V
V
  La situación final es  
V
V
V
 
B
B
B
 

 

Los movimientos permitidos consisten en desplazar una ficha al hueco, saltando como máximo, sobre otras dos.     Ejemplo: La heurística del siguiente estado es 1+2+2= 5.  
B
V
B
 
V
V
B
  CLIPS (watch statistics)
CLIPS> (reset)
CLIPS> (run)
La solución de longitud 15 es:
BBBHVVV
BBBVVVH
...
VVVHBBB
93 rules fired Run time is 1.83 seconds.
50.7272727270043 rules per second.
26 mean number of facts (49 maximum).
1 mean number of instances (1 maximum).
5 mean number of activations (12 maximum).
 
 
Puedes utilizar la siguiente representación:

 

(defmodule MAIN export deftemplate nodo))
(deftemplate MAIN::nodo
 (multislot estado)
 (multislot camino)
 (slot heuristica)
 (slot coste)
 (slot clase (default abierto)))

(defglobal MAIN
 ?*estado-inicial* = (create$ B B B H V V V))
 

 
Funciones que pueden ser útiles: implode$, explode$, create$, duplicate, loop-for-count ... Puedes acceder a los manuales de CLIPS en http://diana.cps.unizar.es/banares/IC/IC.html, son ficheros pdf que se pueden leer con acroread que esta disponible en merlin. Para poder ejecutar acroread incluye en tu path /opt/acroread/bin.