📄 electrnc.clp
字号:
;;;======================================================;;; Circuit Input/Output Simplification Expert System;;;;;; This program simplifies the boolean decision ;;; table for a circuit consisting of inputs (SOURCES) ;;; and outputs (LEDs). ;;;;;; The simplification procedure works as follows:;;; 1) The connections between components of the;;; circuit are initialized.;;; 2) The response of the circuit when all SOURCEs;;; are set to zero is determined.;;; 3) Source input values are changed one at a time;;; and the response of the circuit is determined.;;; All possible input combinations are iterated;;; through using a gray code (a number representation;;; system using binary digits in which successive;;; integers differ by exactly one binary digit).;;; For example, the gray code for the numbers 0 to 7;;; is 0 = 000, 1 = 001, 2 = 011, 3 = 010, 4 = 110,;;; 5 = 111, 6 = 101, 7 = 100. By using a gray code,;;; only one SOURCE has to be changed at a time to;;; determine the next response in the decision ;;; table (minimizing execution time).;;; 4) As responses are determined, a rule checks to;;; see if any two sets of inputs with the same;;; response differ if a single input. If so, then;;; the single input can be replaced with a * ;;; (indicating that it does not matter what the;;; value of the input is given the other inputs).;;; For example, if the input 0 1 0 gave a response;;; of 1 0 and the input 0 0 0 gave the same response,;;; then the decision table can be simplified by;;; indicating that 0 * 0 gives a response of 1 0.;;; 5) Once all responses and simplifications have been;;; determined, the decision table for the circuit is;;; printed.;;; ;;; This example illustrates the use of most of the;;; constructs available in CLIPS 5.0 and also shows how;;; COOL can be effectively integrated with rules.;;; Generic functions are used to connect the components;;; of the circuit during initialization. Classes,;;; message-handlers, and deffunctions are used to;;; determine the response of the circuit to a set of;;; inputs. Rules, deffunctions, and global variables;;; are used to control execution, iterate through all;;; possible input combinations, simplify the boolean;;; decision tree, and print out the simplified decision;;; tree.;;;;;; CLIPS Version 6.0 Example;;; ;;; To execute, load this file, load one of the circuit;;; files (circuit1.clp, circuit2.clp, or circuit3.clp), ;;; reset, and run.;;;======================================================;;;***********;;; DEFCLASSES;;;***********(defclass COMPONENT (is-a USER) (slot ID# (create-accessor write)))(defclass NO-OUTPUT (is-a USER) (slot number-of-outputs (access read-only) (default 0) (create-accessor read)))(defmessage-handler NO-OUTPUT compute-output ())(defclass ONE-OUTPUT (is-a NO-OUTPUT) (slot number-of-outputs (access read-only) (default 1) (create-accessor read)) (slot output-1 (default UNDEFINED) (create-accessor write)) (slot output-1-link (default GROUND) (create-accessor write)) (slot output-1-link-pin (default 1) (create-accessor write)))(defmessage-handler ONE-OUTPUT put-output-1 after (?value) (send ?self:output-1-link (sym-cat put-input- ?self:output-1-link-pin) ?value))(defclass TWO-OUTPUT (is-a ONE-OUTPUT) (slot number-of-outputs (access read-only) (default 2) (create-accessor read)) (slot output-2 (default UNDEFINED) (create-accessor write)) (slot output-2-link (default GROUND) (create-accessor write)) (slot output-2-link-pin (default 1) (create-accessor write)))(defmessage-handler TWO-OUTPUT put-output-1 after (?value) (send ?self:output-2-link (sym-cat put-input- ?self:output-2-link-pin) ?value))(defclass NO-INPUT (is-a USER) (slot number-of-inputs (access read-only) (default 0) (create-accessor read)))(defclass ONE-INPUT (is-a NO-INPUT) (slot number-of-inputs (access read-only) (default 1) (create-accessor read)) (slot input-1 (default UNDEFINED) (visibility public) (create-accessor read-write)) (slot input-1-link (default GROUND) (create-accessor write)) (slot input-1-link-pin (default 1) (create-accessor write)))(defmessage-handler ONE-INPUT put-input-1 after (?value) (send ?self compute-output))(defclass TWO-INPUT (is-a ONE-INPUT) (slot number-of-inputs (access read-only) (default 2) (create-accessor read)) (slot input-2 (default UNDEFINED) (visibility public) (create-accessor write)) (slot input-2-link (default GROUND) (create-accessor write)) (slot input-2-link-pin (default 1) (create-accessor write)))(defmessage-handler TWO-INPUT put-input-2 after (?value) (send ?self compute-output)) (defclass SOURCE (is-a NO-INPUT ONE-OUTPUT COMPONENT) (role concrete) (slot output-1 (default UNDEFINED) (create-accessor write)))(defclass SINK (is-a ONE-INPUT NO-OUTPUT COMPONENT) (role concrete) (slot input-1 (default UNDEFINED) (create-accessor read-write)));;;*******************;;; NOT GATE COMPONENT;;;*******************(defclass NOT-GATE (is-a ONE-INPUT ONE-OUTPUT COMPONENT) (role concrete))(deffunction not# (?x) (- 1 ?x))(defmessage-handler NOT-GATE compute-output () (if (integerp ?self:input-1) then (send ?self put-output-1 (not# ?self:input-1))));;;*******************;;; AND GATE COMPONENT;;;*******************(defclass AND-GATE (is-a TWO-INPUT ONE-OUTPUT COMPONENT) (role concrete))(deffunction and# (?x ?y) (if (and (!= ?x 0) (!= ?y 0)) then 1 else 0))(defmessage-handler AND-GATE compute-output () (if (and (integerp ?self:input-1) (integerp ?self:input-2)) then (send ?self put-output-1 (and# ?self:input-1 ?self:input-2))));;;******************;;; OR GATE COMPONENT;;;******************(defclass OR-GATE (is-a TWO-INPUT ONE-OUTPUT COMPONENT) (role concrete))(deffunction or# (?x ?y) (if (or (!= ?x 0) (!= ?y 0)) then 1 else 0))(defmessage-handler OR-GATE compute-output () (if (and (integerp ?self:input-1) (integerp ?self:input-2)) then (send ?self put-output-1 (or# ?self:input-1 ?self:input-2))));;;********************;;; NAND GATE COMPONENT;;;********************(defclass NAND-GATE (is-a TWO-INPUT ONE-OUTPUT COMPONENT) (role concrete))(deffunction nand# (?x ?y) (if (not (and (!= ?x 0) (!= ?y 0))) then 1 else 0))(defmessage-handler NAND-GATE compute-output () (if (and (integerp ?self:input-1) (integerp ?self:input-2)) then (send ?self put-output-1 (nand# ?self:input-1 ?self:input-2))));;;*******************;;; XOR GATE COMPONENT;;;*******************(defclass XOR-GATE (is-a TWO-INPUT ONE-OUTPUT COMPONENT) (role concrete))(deffunction xor# (?x ?y) (if (or (and (= ?x 1) (= ?y 0)) (and (= ?x 0) (= ?y 1))) then 1 else 0))(defmessage-handler XOR-GATE compute-output () (if (and (integerp ?self:input-1) (integerp ?self:input-2)) then (send ?self put-output-1 (xor# ?self:input-1 ?self:input-2))));;;*******************;;; SPLITTER COMPONENT;;;*******************(defclass SPLITTER (is-a ONE-INPUT TWO-OUTPUT COMPONENT) (role concrete))(defmessage-handler SPLITTER compute-output () (if (integerp ?self:input-1) then (send ?self put-output-1 ?self:input-1) (send ?self put-output-2 ?self:input-1)));;;**************;;; LED COMPONENT;;;**************(defclass LED (is-a ONE-INPUT NO-OUTPUT COMPONENT) (role concrete));;; Returns the current value of each LED ;;; instance in a multifield value.(deffunction LED-response () (bind ?response (create$)) (do-for-all-instances ((?led LED)) TRUE (bind ?response (create$ ?response (send ?led get-input-1)))) ?response);;;***************************;;; DEFGENERICS AND DEFMETHODS;;;***************************(defgeneric connect);;; Connects a one output component to a one input component.(defmethod connect ((?out ONE-OUTPUT) (?in ONE-INPUT)) (send ?out put-output-1-link ?in) (send ?out put-output-1-link-pin 1) (send ?in put-input-1-link ?out) (send ?in put-input-1-link-pin 1));;; Connects a one output component to one pin of a two input component.(defmethod connect ((?out ONE-OUTPUT) (?in TWO-INPUT) (?in-pin INTEGER)) (send ?out put-output-1-link ?in) (send ?out put-output-1-link-pin ?in-pin) (send ?in (sym-cat put-input- ?in-pin -link) ?out) (send ?in (sym-cat put-input- ?in-pin -link-pin) 1));;; Connects one pin of a two output component to a one input component.(defmethod connect ((?out TWO-OUTPUT) (?out-pin INTEGER) (?in ONE-INPUT)) (send ?out (sym-cat put-output- ?out-pin -link) ?in) (send ?out (sym-cat put-output- ?out-pin -link-pin) 1) (send ?in put-input-1-link ?out) (send ?in put-input-1-link-pin ?out-pin));;; Connects one pin of a two output component ;;; to one pin of a two input component.(defmethod connect ((?out TWO-OUTPUT) (?out-pin INTEGER) (?in TWO-INPUT) (?in-pin INTEGER)) (send ?out (sym-cat put-output- ?out-pin -link) ?in) (send ?out (sym-cat put-output- ?out-pin -link-pin) ?in-pin) (send ?in (sym-cat put-input- ?in-pin -link) ?out) (send ?in (sym-cat put-input- ?in-pin -link-pin) ?out-pin));;;****************************;;; DEFGLOBALS AND DEFFUNCTIONS ;;;****************************(defglobal ?*gray-code* = (create$) ?*sources* = (create$) ?*max-iterations* = 0);;; Given the current iteration, determines the next ;;; bit in the gray code to change. ;;; Algorithm courtesy of John R. Kennedy (The BitMan).(deffunction change-which-bit (?x) (bind ?i 1) (while (and (evenp ?x) (!= ?x 0)) do (bind ?x (div ?x 2)) (bind ?i (+ ?i 1))) ?i);;; Forward declaration since the initial configuration;;; is stored in a separate file.(deffunction connect-circuit ());;;*********;;; DEFRULES;;;*********(defrule startup => ;; Initialize the circuit by connecting the components (connect-circuit) ;; Setup the globals. (bind ?*sources* (find-all-instances ((?x SOURCE)) TRUE)) (do-for-all-instances ((?x SOURCE)) TRUE (bind ?*gray-code* (create$ ?*gray-code* 0))) (bind ?*max-iterations* (round (** 2 (length ?*sources*)))) ;; Do the first response. (assert (current-iteration 0)))(defrule compute-response-1st-time ?f <- (current-iteration 0) => ;; Set all of the sources to zero. (do-for-all-instances ((?source SOURCE)) TRUE (send ?source put-output-1 0)) ;; Determine the initial LED response. (assert (result ?*gray-code* =(str-implode (LED-response)))) ;; Begin the iteration process of looping through the gray code combinations. (retract ?f) (assert (current-iteration 1)))(defrule compute-response-other-times ?f <- (current-iteration ?n&~0&:(< ?n ?*max-iterations*)) => ;; Change the gray code, saving the changed bit value. (bind ?pos (change-which-bit ?n)) (bind ?nv (- 1 (nth ?pos ?*gray-code*))) (bind ?*gray-code* (replace$ ?*gray-code* ?pos ?pos ?nv)) ;; Change the single changed source (send (nth ?pos ?*sources*) put-output-1 ?nv) ;; Determine the LED response to the input. (assert (result ?*gray-code* =(str-implode (LED-response)))) ;; Assert the new iteration fact (retract ?f) (assert (current-iteration =(+ ?n 1))))(defrule merge-responses (declare (salience 10)) ?f1 <- (result $?b ?x $?e ?response) ?f2 <- (result $?b ~?x $?e ?response) => (retract ?f1 ?f2) (assert (result $?b * $?e ?response)))(defrule print-header (declare (salience -10)) => (assert (print-results)) (do-for-all-instances ((?x SOURCE)) TRUE (format t " %3s " (sym-cat ?x))) (printout t " | ") (do-for-all-instances ((?x LED)) TRUE (format t " %3s " (sym-cat ?x))) (format t "%n") (do-for-all-instances ((?x SOURCE)) TRUE (printout t "-----")) (printout t "-+-") (do-for-all-instances ((?x LED)) TRUE (printout t "-----")) (format t "%n")) (defrule print-result (print-results) ?f <- (result $?input ?response) (not (result $?input-2 ?response-2&:(< (str-compare ?response-2 ?response) 0))) => (retract ?f) ;; Print the input from the sources. (while (neq ?input (create$)) do (printout t " " (nth 1 ?input) " ") (bind ?input (rest$ ?input))) ;; Print the output from the LEDs. (printout t " | ") (bind ?response (str-explode ?response)) (while (neq ?response (create$)) do (printout t " " (nth 1 ?response) " ") (bind ?response (rest$ ?response))) (printout t crlf))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -