File: electrnc.clp

package info (click to toggle)
clips 6.21-6.2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 7,956 kB
  • ctags: 8,731
  • sloc: ansic: 97,932; makefile: 1,406; sh: 189
file content (393 lines) | stat: -rw-r--r-- 13,319 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
;;;======================================================
;;;   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 6.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))