📄 shwrnoui.clp
字号:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Global definitions used in the simulation
;;
(defglobal
?*coldValvePos* = 0.0
?*hotValvePos* = 0.0
?*coldTemp* = 0.0
?*hotTemp* = 0.0
?*coldPress* = 0.0
?*hotPress* = 0.0
?*optimalTempMin* = 34.0
?*optimalTempMax* = 38.0
?*optimalFlowMin* = 11.0
?*optimalFlowMax* = 13.0
?*atmosphericPress* = 30.0
?*iterationFactor* = 1.0
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Deftemplates below define the fuzzy variables being used
;;
;;
;; Outputs of the shower
;;
;; outTemp -- output temperature
;;
;; outFlow -- flow out of the shower
(deftemplate outTemp
5 65 Celcius
((none (5 1) (5.1 0))
(cold (z 10 35))
(OK (pi 2 36))
(hot (s 37 60)) )
())
(deftemplate outFlow
0 100 liters/minute
((none (0 1) (0.05 0))
(low (z 3 11.5))
(OK (pi 1 12))
(strong (s 12.5 25)) )
() )
;; controls for hot and cold valve positions
;;
(deftemplate change_vc
-1 1
((NB (-0.5 1) (-.25 0))
(NM (-.35 0) (-.3 1) (-.15 0))
(NS (-.25 0) (-.15 1) (0 0))
(Z (-.05 0) (0 1) (.05 0))
(PS (0 0) (.15 1) (.25 0))
(PM (.15 0) (.3 1) (.35 0))
(PB (.25 0)(0.5 1)) )
( ; modifier definitions
; (very sqr)
; (less sqrt)
)
)
(deftemplate change_vh
-1 1
((NB (-0.5 1) (-.25 0))
(NM (-.35 0) (-.3 1) (-.15 0))
(NS (-.25 0) (-.15 1) (0 0))
(Z (-.05 0) (0 1) (.05 0))
(PS (0 0) (.15 1) (.25 0))
(PM (.15 0) (.3 1) (.35 0))
(PB (.25 0)(0.5 1)) )
( ; modifier definitions
; (very sqr)
; (less sqrt)
)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Some supporting functions
;;
;; getNumber - requests a number in a given range
;;
;; ask-question - asks a question and gets answer from provided
;; allowed responses
;;
;; yes-or-no-p - requests a yes or no answer to given question
;; (uses ask-question)
;;
;; initShower - initializes certain global values and requests some
;; initial values from the user and calls simulate to
;; calc the out flow and temp and assert these as
;; fuzzy facts to start the fuzzy rules going
;;
;; Simulate - calculates the new outFlow and outTemp when changes
;; to valve positions are made -- also asserts the
;; fuzzified facts representing these new values --
;; also checks for finished state (temp and flow in range
;; or for certain error conditions
;;
(deffunction getNumber (?question ?from ?to)
(printout t ?question " [" ?from " to " ?to "]: ")
(bind ?answer (read))
(while (not (and (numberp ?answer)
(>= ?answer ?from)
(<= ?answer ?to)
)
)
do
(printout t "Please enter a numeric answer within the specified range" crlf
?question " [" ?from " to " ?to "]: ")
(bind ?answer (read))
)
?answer
)
(deffunction ask-question (?question $?allowed-values)
(printout t ?question)
(bind ?answer (read))
(if (lexemep ?answer)
then (bind ?answer (lowcase ?answer)))
(while (not (member ?answer ?allowed-values)) do
(printout t ?question)
(bind ?answer (read))
(if (lexemep ?answer)
then (bind ?answer (lowcase ?answer))))
?answer)
(deffunction yes-or-no-p (?question)
(bind ?response (ask-question ?question yes no y n))
(if (or (eq ?response yes) (eq ?response y))
then TRUE
else FALSE))
(deffunction Simulate (?coldValveChange ?hotValveChange)
;; Check for some rather bad situations where control is lost
;;
(if (and (= ?*coldValvePos* 1.0) (> ?coldValveChange 0.0) (>= ?hotValveChange 0.0))
then
(printout t crlf "*** Cold Water Problem -- Cold valve full open and trying to open more ***" crlf
"Stopping simulation" crlf)
(bind ?*iterationFactor* 1.0) ;; reset iteration Factor
(halt)
)
(if (and (= ?*hotValvePos* 1.0) (> ?hotValveChange 0.0) (>= ?coldValveChange 0.0))
then
(printout t crlf "*** Hot Water Problem -- Hot valve full open and trying to open more ***" crlf
"Stopping simulation" crlf)
(bind ?*iterationFactor* 1.0) ;; reset iteration Factor
(halt)
)
(if (and (= ?*coldValvePos* 0.0) (< ?coldValveChange 0.0) (< (abs ?hotValveChange) 0.000001))
then
(printout t crlf "*** HOT TEMPERATURE PROBLEM ***" crlf
"Shutting down - cannot get temperature high enough" crlf )
(bind ?*iterationFactor* 1.0) ;; reset iteration Factor
(halt)
)
(if (and (= ?*hotValvePos* 0.0) (< ?hotValveChange 0.0) (< (abs ?coldValveChange) 0.000001))
then
(printout t crlf "*** HOT TEMPERATURE PROBLEM ***" crlf
"Shutting down - cannot get temperature low enough" crlf )
(bind ?*iterationFactor* 1.0) ;; reset iteration Factor
(halt)
)
;; calc new hot and cold valve positions based on the recommendations
;; for change provided
;; NOTE: we perform a scaling factor on the recommendations making the assumption
;; that at high valve settings a change will produce less effect than
;; if we are operating at a low valve setting; this is due to the effect
;; of pressures -- low pressures will tend to put us at higher valve
;; positions; of course in a REAL situation the actual operating conditions
;; of the system would likely be known and we couuld adjust accordingly;
;; One problem that can occur is that the adjustments cause the system
;; to be too course in its adjustment and it makes a change to go up and then
;; a symmetric change to go down -- it will then endlessly flip flop between
;; a too high and a too low condition -- this is solved by reducing the scale
;; factor after each iteration so the adjustments get smaller and smaller.
;; Also note that we could also tune the fuzzy sets to reduce the range
;; of changes recommended.
;; REMEMBER the conditions of the problem -- we do not know the temps or
;; pressures of hot and cold supplies
(if (or (<> ?coldValveChange 0.0) (<> ?hotValveChange 0.0))
then
(bind ?*coldValvePos*
(max 0.0
(min 1.0
(+ ?*coldValvePos*
(* (* (max 0.1 ?*coldValvePos*) ?*iterationFactor*)
?coldValveChange
)
)
)
)
)
(bind ?*hotValvePos*
(max 0.0
(min 1.0
(+ ?*hotValvePos*
(* (* (max 0.1 ?*hotValvePos*) ?*iterationFactor*)
?hotValveChange
)
)
)
)
)
(format t "Cold Valve Position = %5.3f, Hot Valve Position = %5.3f %n"
?*coldValvePos* ?*hotValvePos*
)
)
(bind ?hotFlow (* ?*hotValvePos* (- ?*hotPress* ?*atmosphericPress*)))
(bind ?coldFlow (* ?*coldValvePos* (- ?*coldPress* ?*atmosphericPress*)))
(bind ?outFlow (+ ?hotFlow ?coldFlow))
(if (= ?outFlow 0.0)
then
(bind ?outTemp 5.0)
else
(bind ?outTemp (/ (+ (* ?coldFlow ?*coldTemp*)
(* ?hotFlow ?*hotTemp*))
?outFlow)
)
)
(format t "Output Flow is %6.3f litres/sec%n" ?outFlow)
(format t "Output Temp is %6.3f degrees C%n" ?outTemp)
;; if both output flow and temp are within correct range control is
;; completed -- pause to ask for changes to input temps or pressures
;; or to quit
;;
(if (and (and (> ?outFlow ?*optimalFlowMin*) (< ?outFlow ?*optimalFlowMax*))
(and (> ?outTemp ?*optimalTempMin*) (< ?outTemp ?*optimalTempMax*))
)
then
(printout t "Shower is under control!" crlf)
(bind ?*iterationFactor* 1.0) ;; reset iteration Factor
(if (yes-or-no-p "Would you like to change some parameters? ")
then
(bind ?*coldTemp* (getNumber "New Temperature (Celcius) of cold water input?" 5 65))
(bind ?*hotTemp* (getNumber "New Temperature (Celcius) of hot water input?" 5 65))
(bind ?*coldPress* (getNumber "New Pressure (kPa) of cold water input?" 42 100))
(bind ?*hotPress* (getNumber "New Pressure (kPa) of hot water input?" 42 100))
;; need to recalc Fow and Temp since things changed
(bind ?hotFlow (* ?*hotValvePos* (- ?*hotPress* ?*atmosphericPress*)))
(bind ?coldFlow (* ?*coldValvePos* (- ?*coldPress* ?*atmosphericPress*)))
(bind ?outFlow (+ ?hotFlow ?coldFlow))
(if (= ?outFlow 0.0)
then
(bind ?outTemp 5.0)
else
(bind ?outTemp (/ (+ (* ?coldFlow ?*coldTemp*)
(* ?hotFlow ?*hotTemp*))
?outFlow)
)
)
(format t "Output Flow is %6.3f litres/sec%n" ?outFlow)
(format t "Output Temp is %6.3f degrees C%n" ?outTemp)
else
(bind ?*iterationFactor* 1.0) ;; reset iteration Factor
(halt)
)
)
;; iterationFactor reduces each cycle through
(if (> ?*iterationFactor* 0.1)
then
(bind ?*iterationFactor* (* ?*iterationFactor* .96))
)
;; now assert the fuzzified values of the Flow and Temp of Output
(if (= ?outFlow 0.0)
then
(assert (outFlow (0.0 1.0) (0.5 0.0)))
else
(if (= ?outFlow 100.0)
then
(assert (outFlow (99.5 0.0) (100.0 1.0)))
else
(assert (outFlow ((max 0.0 (- ?outFlow 0.5)) 0.0) (?outFlow 1.0)
((min 100.0 (+ ?outFlow 0.5)) 0.0) ))
)
)
(if (= ?outTemp 5.0)
then
(assert (outTemp (5.0 1.0) (5.1 0.0)))
else
(if (= ?outTemp 65.0)
then
(assert (outTemp (64.9 0.0) (65.0 1.0)))
else
(assert (outTemp ((max 5.0 (- ?outTemp 0.1)) 0.0) (?outTemp 1.0)
((min 65.0 (+ ?outTemp 0.1)) 0.0) ))
)
)
)
(deffunction initShower ()
(bind ?*coldValvePos* (getNumber "Initial Cold Valve Position?" 0.0 1.0))
(bind ?*hotValvePos* (getNumber "Initial Hot Valve Position?" 0.0 1.0))
(bind ?*coldTemp* (getNumber "Initial Temperature (Celcius) of cold water input?" 5 65))
(bind ?*hotTemp* (getNumber "Initial Temperature (Celcius) of hot water input?" 5 65))
(bind ?*coldPress* (getNumber "Initial Pressure (kPa) of cold water input?" 42 100))
(bind ?*hotPress* (getNumber "Initial Pressure (kPa) of hot water input?" 42 100))
(Simulate 0.0 0.0)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Initializing rule
;;
(defrule start
=>
(initShower)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Rules that control the shower with fuzzy inferencing
;;
(defrule none_none "will jump start an off system"
(outTemp none)
(outFlow none)
=>
(assert (change_vh PS))
(assert (change_vc PM))
)
(defrule cold_low
(outTemp cold)
(outFlow low)
=>
(assert (change_vh PB))
(assert (change_vc Z))
)
(defrule cold_OK
(outTemp cold)
(outFlow OK)
=>
(assert (change_vh PM))
(assert (change_vc Z))
)
(defrule cold_strong
(outTemp cold)
(outFlow strong)
=>
(assert (change_vh Z))
(assert (change_vc NB))
)
(defrule OK_low
(outTemp OK)
(outFlow low)
=>
(assert (change_vh PS))
(assert (change_vc PS))
)
(defrule OK_strong
(outTemp OK)
(outFlow strong)
=>
(assert (change_vh NS))
(assert (change_vc NS))
)
(defrule hot_low
(outTemp hot)
(outFlow low)
=>
(assert (change_vh Z))
(assert (change_vc PB))
)
(defrule hot_OK
(outTemp hot)
(outFlow OK)
=>
(assert (change_vh NM))
(assert (change_vc Z))
)
(defrule hot_strong
(outTemp hot)
(outFlow strong)
=>
(assert (change_vh NB))
(assert (change_vc Z))
)
;; when all rules have fired and contributed to determination of the
;; control changes to be made then defuzzify the change values and
;; pass these new values to the simulate function
(defrule defuzzification-and-control
(declare (salience -1))
?f1 <- (change_vc ?)
?f2 <- (change_vh ?)
?f3 <- (outTemp ?)
?f4 <- (outFlow ?)
=>
(bind ?coldChange (moment-defuzzify ?f1))
(bind ?hotChange (moment-defuzzify ?f2))
(retract ?f1 ?f2 ?f3 ?f4)
(Simulate ?coldChange ?hotChange)
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -