home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / clips_2 / CLIPS / Examples / Electronic < prev    next >
Encoding:
Text File  |  1993-06-02  |  13.4 KB  |  394 lines

  1. ;;;======================================================
  2. ;;;   Circuit Input/Output Simplification Expert System
  3. ;;;
  4. ;;;     This program simplifies the boolean decision 
  5. ;;;     table for a circuit consisting of inputs (SOURCES) 
  6. ;;;     and outputs (LEDs). 
  7. ;;;
  8. ;;;     The simplification procedure works as follows:
  9. ;;;     1) The connections between components of the
  10. ;;;        circuit are initialized.
  11. ;;;     2) The response of the circuit when all SOURCEs
  12. ;;;        are set to zero is determined.
  13. ;;;     3) Source input values are changed one at a time
  14. ;;;        and the response of the circuit is determined.
  15. ;;;        All possible input combinations are iterated
  16. ;;;        through using a gray code (a number representation
  17. ;;;        system using binary digits in which successive
  18. ;;;        integers differ by exactly one binary digit).
  19. ;;;        For example, the gray code for the numbers 0 to 7
  20. ;;;        is 0 = 000, 1 = 001, 2 = 011, 3 = 010, 4 = 110,
  21. ;;;        5 = 111, 6 = 101, 7 = 100. By using a gray code,
  22. ;;;        only one SOURCE has to be changed at a time to
  23. ;;;        determine the next response in the decision 
  24. ;;;        table (minimizing execution time).
  25. ;;;     4) As responses are determined, a rule checks to
  26. ;;;        see if any two sets of inputs with the same
  27. ;;;        response differ if a single input. If so, then
  28. ;;;        the single input can be replaced with a * 
  29. ;;;        (indicating that it does not matter what the
  30. ;;;        value of the input is given the other inputs).
  31. ;;;        For example,  if the input 0 1 0 gave a response
  32. ;;;        of 1 0 and the input 0 0 0 gave the same response,
  33. ;;;        then the decision table can be simplified by
  34. ;;;        indicating that 0 * 0 gives a response of 1 0.
  35. ;;;     5) Once all responses and simplifications have been
  36. ;;;        determined, the decision table for the circuit is
  37. ;;;        printed.
  38. ;;;        
  39. ;;;     This example illustrates the use of most of the
  40. ;;;     constructs available in CLIPS 6.0 and also shows how
  41. ;;;     COOL can be effectively integrated with rules.
  42. ;;;     Generic functions are used to connect the components
  43. ;;;     of the circuit during initialization. Classes,
  44. ;;;     message-handlers, and deffunctions are used to
  45. ;;;     determine the response of the circuit to a set of
  46. ;;;     inputs. Rules, deffunctions, and global variables
  47. ;;;     are used to control execution, iterate through all
  48. ;;;     possible input combinations, simplify the boolean
  49. ;;;     decision tree, and print out the simplified decision
  50. ;;;     tree.
  51. ;;;
  52. ;;;     CLIPS Version 6.0 Example
  53. ;;; 
  54. ;;;     To execute, load this file, load one of the circuit
  55. ;;;     files (circuit1.clp, circuit2.clp, or circuit3.clp), 
  56. ;;;     reset, and run.
  57. ;;;======================================================
  58.  
  59.  
  60. ;;;***********
  61. ;;; DEFCLASSES
  62. ;;;***********
  63.  
  64. (defclass COMPONENT
  65.   (is-a USER)
  66.   (slot ID# (create-accessor write)))
  67.  
  68. (defclass NO-OUTPUT
  69.   (is-a USER)
  70.   (slot number-of-outputs (access read-only) 
  71.                           (default 0)
  72.                           (create-accessor read)))
  73.  
  74. (defmessage-handler NO-OUTPUT compute-output ())
  75.  
  76. (defclass ONE-OUTPUT
  77.   (is-a NO-OUTPUT)
  78.   (slot number-of-outputs (access read-only) 
  79.                           (default 1)
  80.                           (create-accessor read))
  81.   (slot output-1 (default UNDEFINED) (create-accessor write))
  82.   (slot output-1-link (default GROUND) (create-accessor write))
  83.   (slot output-1-link-pin (default 1) (create-accessor write)))
  84.  
  85. (defmessage-handler ONE-OUTPUT put-output-1 after (?value)
  86.    (send ?self:output-1-link 
  87.          (sym-cat put-input- ?self:output-1-link-pin)
  88.          ?value))
  89.  
  90. (defclass TWO-OUTPUT
  91.   (is-a ONE-OUTPUT)
  92.   (slot number-of-outputs (access read-only) 
  93.                           (default 2)
  94.                           (create-accessor read))
  95.   (slot output-2 (default UNDEFINED) (create-accessor write))
  96.   (slot output-2-link (default GROUND) (create-accessor write))
  97.   (slot output-2-link-pin (default 1) (create-accessor write)))
  98.  
  99. (defmessage-handler TWO-OUTPUT put-output-1 after (?value)
  100.    (send ?self:output-2-link 
  101.          (sym-cat put-input- ?self:output-2-link-pin)
  102.          ?value))
  103.  
  104. (defclass NO-INPUT
  105.   (is-a USER)
  106.   (slot number-of-inputs (access read-only) 
  107.                          (default 0)
  108.                          (create-accessor read)))
  109.  
  110. (defclass ONE-INPUT
  111.   (is-a NO-INPUT)
  112.   (slot number-of-inputs (access read-only) 
  113.                          (default 1)
  114.                          (create-accessor read))
  115.   (slot input-1 (default UNDEFINED) 
  116.                 (visibility public)
  117.                 (create-accessor read-write))
  118.   (slot input-1-link (default GROUND) (create-accessor write))
  119.   (slot input-1-link-pin (default 1) (create-accessor write)))
  120.  
  121. (defmessage-handler ONE-INPUT put-input-1 after (?value)
  122.    (send ?self compute-output))
  123.  
  124. (defclass TWO-INPUT
  125.   (is-a ONE-INPUT)
  126.   (slot number-of-inputs (access read-only) 
  127.                          (default 2)
  128.                          (create-accessor read))
  129.   (slot input-2 (default UNDEFINED) 
  130.                 (visibility public)
  131.                 (create-accessor write))
  132.   (slot input-2-link (default GROUND) (create-accessor write))
  133.   (slot input-2-link-pin (default 1) (create-accessor write)))
  134.  
  135. (defmessage-handler TWO-INPUT put-input-2 after (?value)
  136.    (send ?self compute-output))
  137.  
  138. (defclass SOURCE
  139.   (is-a NO-INPUT ONE-OUTPUT COMPONENT)
  140.   (role concrete)
  141.   (slot output-1 (default UNDEFINED) (create-accessor write)))
  142.  
  143. (defclass SINK
  144.   (is-a ONE-INPUT NO-OUTPUT COMPONENT)
  145.   (role concrete)
  146.   (slot input-1 (default UNDEFINED) (create-accessor read-write)))
  147.  
  148. ;;;*******************
  149. ;;; NOT GATE COMPONENT
  150. ;;;*******************
  151.  
  152. (defclass NOT-GATE
  153.   (is-a ONE-INPUT ONE-OUTPUT COMPONENT)
  154.   (role concrete))
  155.  
  156. (deffunction not# (?x) (- 1 ?x))
  157.  
  158. (defmessage-handler NOT-GATE compute-output ()
  159.    (if (integerp ?self:input-1) then
  160.        (send ?self put-output-1 (not# ?self:input-1))))
  161.  
  162. ;;;*******************
  163. ;;; AND GATE COMPONENT
  164. ;;;*******************
  165.  
  166. (defclass AND-GATE
  167.   (is-a TWO-INPUT ONE-OUTPUT COMPONENT)
  168.   (role concrete))
  169.  
  170. (deffunction and# (?x ?y) 
  171.   (if (and (!= ?x 0) (!= ?y 0)) then 1 else 0))
  172.  
  173. (defmessage-handler AND-GATE compute-output ()
  174.    (if (and (integerp ?self:input-1) 
  175.             (integerp ?self:input-2)) then
  176.        (send ?self put-output-1 (and# ?self:input-1 ?self:input-2))))
  177.  
  178. ;;;******************
  179. ;;; OR GATE COMPONENT
  180. ;;;******************
  181.  
  182. (defclass OR-GATE
  183.   (is-a TWO-INPUT ONE-OUTPUT COMPONENT)
  184.   (role concrete))
  185.  
  186. (deffunction or# (?x ?y) 
  187.   (if (or (!= ?x 0) (!= ?y 0)) then 1 else 0))
  188.  
  189. (defmessage-handler OR-GATE compute-output ()
  190.    (if (and (integerp ?self:input-1) 
  191.             (integerp ?self:input-2)) then
  192.        (send ?self put-output-1 (or# ?self:input-1 ?self:input-2))))
  193.  
  194. ;;;********************
  195. ;;; NAND GATE COMPONENT
  196. ;;;********************
  197.  
  198. (defclass NAND-GATE
  199.   (is-a TWO-INPUT ONE-OUTPUT COMPONENT)
  200.   (role concrete))
  201.  
  202. (deffunction nand# (?x ?y) 
  203.   (if (not (and (!= ?x 0) (!= ?y 0))) then 1 else 0))
  204.  
  205. (defmessage-handler NAND-GATE compute-output ()
  206.    (if (and (integerp ?self:input-1) 
  207.             (integerp ?self:input-2)) then
  208.        (send ?self put-output-1 (nand# ?self:input-1 ?self:input-2))))
  209.  
  210. ;;;*******************
  211. ;;; XOR GATE COMPONENT
  212. ;;;*******************
  213.  
  214. (defclass XOR-GATE
  215.   (is-a TWO-INPUT ONE-OUTPUT COMPONENT)
  216.   (role concrete))
  217.  
  218. (deffunction xor# (?x ?y) 
  219.   (if (or (and (= ?x 1) (= ?y 0))
  220.           (and (= ?x 0) (= ?y 1))) then 1 else 0))
  221.  
  222. (defmessage-handler XOR-GATE compute-output ()
  223.    (if (and (integerp ?self:input-1) 
  224.             (integerp ?self:input-2)) then
  225.        (send ?self put-output-1 (xor# ?self:input-1 ?self:input-2))))
  226.  
  227. ;;;*******************
  228. ;;; SPLITTER COMPONENT
  229. ;;;*******************
  230.  
  231. (defclass SPLITTER
  232.   (is-a ONE-INPUT TWO-OUTPUT COMPONENT)
  233.   (role concrete))
  234.  
  235. (defmessage-handler SPLITTER compute-output ()
  236.    (if (integerp ?self:input-1) then
  237.        (send ?self put-output-1 ?self:input-1)
  238.        (send ?self put-output-2 ?self:input-1)))
  239.  
  240. ;;;**************
  241. ;;; LED COMPONENT
  242. ;;;**************
  243.  
  244. (defclass LED
  245.   (is-a ONE-INPUT NO-OUTPUT COMPONENT)
  246.   (role concrete))
  247.  
  248. ;;; Returns the current value of each LED 
  249. ;;; instance in a multifield value.
  250. (deffunction LED-response ()
  251.    (bind ?response (create$))
  252.    (do-for-all-instances ((?led LED)) TRUE
  253.       (bind ?response (create$ ?response (send ?led get-input-1))))
  254.    ?response)
  255.  
  256. ;;;***************************
  257. ;;; DEFGENERICS AND DEFMETHODS
  258. ;;;***************************
  259.  
  260. (defgeneric connect)
  261.  
  262. ;;; Connects a one output component to a one input component.
  263. (defmethod connect ((?out ONE-OUTPUT) (?in ONE-INPUT)) 
  264.    (send ?out put-output-1-link ?in) 
  265.    (send ?out put-output-1-link-pin 1)
  266.    (send ?in  put-input-1-link ?out)
  267.    (send ?in  put-input-1-link-pin 1))
  268.  
  269. ;;; Connects a one output component to one pin of a two input component.
  270. (defmethod connect ((?out ONE-OUTPUT) (?in TWO-INPUT) (?in-pin INTEGER)) 
  271.    (send ?out put-output-1-link ?in)
  272.    (send ?out put-output-1-link-pin ?in-pin)
  273.    (send ?in  (sym-cat put-input- ?in-pin -link) ?out)
  274.    (send ?in  (sym-cat put-input- ?in-pin -link-pin) 1))
  275.  
  276. ;;; Connects one pin of a two output component to a one input component.
  277. (defmethod connect ((?out TWO-OUTPUT) (?out-pin INTEGER) (?in ONE-INPUT)) 
  278.    (send ?out (sym-cat put-output- ?out-pin -link) ?in)
  279.    (send ?out (sym-cat put-output- ?out-pin -link-pin) 1)
  280.    (send ?in put-input-1-link ?out)
  281.    (send ?in put-input-1-link-pin ?out-pin))
  282.  
  283. ;;; Connects one pin of a two output component 
  284. ;;; to one pin of a two input component.
  285. (defmethod connect ((?out TWO-OUTPUT) (?out-pin INTEGER)
  286.                     (?in TWO-INPUT) (?in-pin INTEGER)) 
  287.    (send ?out (sym-cat put-output- ?out-pin -link) ?in)
  288.    (send ?out (sym-cat put-output- ?out-pin -link-pin) ?in-pin)
  289.    (send ?in  (sym-cat put-input- ?in-pin -link) ?out)
  290.    (send ?in  (sym-cat put-input- ?in-pin -link-pin) ?out-pin))
  291.  
  292. ;;;****************************
  293. ;;; DEFGLOBALS AND DEFFUNCTIONS 
  294. ;;;****************************
  295.  
  296. (defglobal ?*gray-code* = (create$)
  297.            ?*sources* = (create$)
  298.            ?*max-iterations* = 0)
  299.  
  300. ;;; Given the current iteration, determines the next 
  301. ;;; bit in the gray code to change. 
  302. ;;; Algorithm courtesy of John R. Kennedy (The BitMan).
  303. (deffunction change-which-bit (?x)
  304.    (bind ?i 1)
  305.    (while (and (evenp ?x) (!= ?x 0)) do 
  306.       (bind ?x (div ?x 2))
  307.       (bind ?i (+ ?i 1)))
  308.    ?i)
  309.  
  310. ;;; Forward declaration since the initial configuration
  311. ;;; is stored in a separate file.
  312. (deffunction connect-circuit ())
  313.  
  314. ;;;*********
  315. ;;; DEFRULES
  316. ;;;*********
  317.  
  318. (defrule startup
  319.   =>
  320.   ;; Initialize the circuit by connecting the components
  321.   (connect-circuit) 
  322.   ;; Setup the globals. 
  323.   (bind ?*sources* (find-all-instances ((?x SOURCE)) TRUE))
  324.   (do-for-all-instances ((?x SOURCE)) TRUE
  325.      (bind ?*gray-code* (create$ ?*gray-code* 0)))
  326.   (bind ?*max-iterations* (round (** 2 (length ?*sources*))))
  327.   ;; Do the first response.
  328.   (assert (current-iteration 0)))
  329.  
  330. (defrule compute-response-1st-time
  331.    ?f <- (current-iteration 0)
  332.    =>
  333.    ;; Set all of the sources to zero.
  334.    (do-for-all-instances ((?source SOURCE)) TRUE (send ?source put-output-1 0))
  335.    ;; Determine the initial LED response.
  336.    (assert (result ?*gray-code* =(str-implode (LED-response))))
  337.    ;; Begin the iteration process of looping through the gray code combinations.
  338.    (retract ?f)
  339.    (assert (current-iteration 1)))
  340.  
  341. (defrule compute-response-other-times
  342.    ?f <- (current-iteration ?n&~0&:(< ?n ?*max-iterations*))
  343.    =>
  344.    ;; Change the gray code, saving the changed bit value.
  345.    (bind ?pos (change-which-bit ?n))
  346.    (bind ?nv (- 1 (nth ?pos ?*gray-code*)))
  347.    (bind ?*gray-code* (replace$ ?*gray-code* ?pos ?pos ?nv))
  348.    ;; Change the single changed source
  349.    (send (nth ?pos ?*sources*) put-output-1 ?nv)   
  350.    ;; Determine the LED response to the input.
  351.    (assert (result ?*gray-code* =(str-implode (LED-response))))
  352.    ;; Assert the new iteration fact
  353.    (retract ?f)
  354.    (assert (current-iteration =(+ ?n 1))))
  355.  
  356. (defrule merge-responses
  357.    (declare (salience 10))
  358.    ?f1 <- (result $?b  ?x $?e ?response)
  359.    ?f2 <- (result $?b ~?x $?e ?response)
  360.    =>
  361.    (retract ?f1 ?f2)
  362.    (assert (result $?b * $?e ?response)))
  363.  
  364. (defrule print-header
  365.    (declare (salience -10))
  366.    =>
  367.    (assert (print-results))
  368.    (do-for-all-instances ((?x SOURCE)) TRUE (format t " %3s " (sym-cat ?x)))
  369.    (printout t " | ")
  370.    (do-for-all-instances ((?x LED)) TRUE (format t " %3s " (sym-cat ?x)))
  371.    (format t "%n")
  372.    (do-for-all-instances ((?x SOURCE)) TRUE (printout t "-----"))
  373.    (printout t "-+-")
  374.    (do-for-all-instances ((?x LED)) TRUE (printout t "-----"))
  375.    (format t "%n"))
  376.       
  377. (defrule print-result
  378.    (print-results)
  379.    ?f <- (result $?input ?response)
  380.    (not (result $?input-2 ?response-2&:(< (str-compare ?response-2 ?response) 0)))
  381.    =>
  382.    (retract ?f)
  383.    ;; Print the input from the sources.
  384.    (while (neq ?input (create$)) do
  385.       (printout t "  " (nth 1 ?input) "  ")
  386.       (bind ?input (rest$ ?input)))
  387.    ;; Print the output from the LEDs.
  388.    (printout t " | ")
  389.    (bind ?response (str-explode ?response))
  390.    (while (neq ?response (create$)) do
  391.       (printout t "  " (nth 1 ?response) "  ")
  392.       (bind ?response (rest$ ?response)))
  393.    (printout t crlf))
  394.