;; circuit2.clp: Jess code to represent a logic circuit ;; ;; Note: this is demonstration code, but IT IS AN OUTLINE OF CODE THAT ;; WOULD ACTUALLY WORK. ;; ;; Modified from circuit1.clp, based on the observation from ;; circuit3.clp that what we really want to do is to check when an ;; input to an element has changed its value. When that occurs, we ;; update the element; otherwise, there's no need. This should work ;; with feedback. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Circuit structure ;; ;; Each circuit element has a name, connectivity information, current ;; input value(s), and a current output value. Note also that we need ;; to initialize circuit elements to have input and output values that ;; are either TRUE or FALSE, and those values should "make sense", ;; according to the function of the given circuit element. ;; ;; a NOT gate (deftemplate not-gate "Logical not" (slot name) (slot input) (slot input-value (default FALSE)) (multislot output) (slot output-value (default TRUE))) ;; Input port (deftemplate input-port "Circuit input" (slot name) (multislot output) (slot output-value (default FALSE))) ;; Output port (deftemplate output-port "Circuit output" (slot name) (slot input) (slot input-value (default FALSE)) (slot output-value (default FALSE))) ;; Connector (deftemplate connector "Connects one input to one or more outputs" (slot name) (slot input) (slot input-value (default FALSE)) (multislot output) (slot output-value (default FALSE))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; A simple circuit ;; ;; It would be best to put this in a separate file, so different ;; circuits could be loaded independently of the expert system. (deffacts simple "A simple circuit" (input-port (name in1) (output conn1) (output-value TRUE)) (connector (name conn1) (input in1) (output not1)) (not-gate (name not1) (input conn1) (output conn2)) (connector (name conn2) (input not1) (output out1)) (output-port (name out1) (input conn2))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Gate rules ;; What we need is to compare the output-value of an element's input ;; to its input-value (for that input) and update both its input-value ;; and its output-value if they differ. Since the modify on the RHS ;; changes the element fact so that the CE on the LHS will no longer ;; match it, there is no infinite loop. (defrule propagate-input "Copy value from input port to connector" (input-port (output ?c) (output-value ?v)) ?cf <- (connector (name ?c) (input-value ~?v)) => (modify ?cf (input-value ?v) (output-value ?v))) (defrule compute-not "Compute output of a NOT gate when its input has changed" ?nf <- (not-gate (input ?c) (input-value ?nv)) (connector (name ?c) (output-value ?v&~?nv)) => (modify ?nf (input-value ?v) (output-value (not ?v)))) (defrule propagate-not "Copy NOT output to connector" (not-gate (output ?c) (output-value ?v)) ?cf <- (connector (name ?c) (input-value ~?v)) => (modify ?cf (input-value ?v) (output-value ?v))) (defrule propagate-outport "Copy connector value to output port" ?of <- (output-port (name ?n) (input ?c) (input-value ?ov)) (connector (name ?c) (output-value ?v&~?ov)) => (modify ?of (input-value ?v) (output-value ?v)) (printout t "Output " ?n " changes to " ?v crlf))