2017-04-07 66 views
0

我是CLIPS的新手,回溯範式的確令我頭疼。如何消除CLIPS中的if-then-else以更好地優化代碼

我得到一個問題,我需要產生後續輸出。

Q: Is the patient's temperature more than 39? [yes/no]: yes 
    The patient has fever 
Q: Does the patient sick over a month? [yes/no]: yes 
    We suspect the patient has bacterial infection 
Q: How about sore throat? [yes/no]: yes 
    We believe the patient has strep throat 

因此,根據需要,我定義了一些規則來使其工作。

(defrule rule_1 
    (THE-PATIENT-HAS-A-SORE-THROAT) 
    (WE-SUSPECT-A-BACTERIAL-INFECTION) => 
    (assert(WE-BELIEVE-THE-PATIENT-HAS-STREP-THROAT)) 
    (printout t "We believe the patient has strep throat" crlf)) 

(defrule rule_2 
    (THE-PATIENT-TEMPERATURE-IS-40C) => 
    (assert(THE-PATIENT-HAS-A-FEVER))) 

(defrule rule_3 
    (THE-PATIENT-HAS-BEEN-SICK-OVER-A-MONTH) 
    (THE-PATIENT-HAS-A-FEVER) => 
    (assert(WE-SUSPECT-A-BACTERIAL-INFECTION))) 

(defrule ask-sick 
    (start-question) => 
    (printout t "Q: Is the patient's temperature more than 39? [yes/no]: ") 
    (bind ?input (readline)) 
    (if (neq ?input "no") 
    then 
     (assert (THE-PATIENT-TEMPERATURE-IS-40C)) 
     (printout t "The patient has fever" crlf) 
     (printout t "Q: Does the patient sick over a month? [yes/no]: ") 
     (bind ?input2 (readline)) 
     (if (neq ?input2 "no") 
     then 
      (assert (THE-PATIENT-HAS-BEEN-SICK-OVER-A-MONTH)) 
      (printout t "We suspect the patient has bacterial infection" crlf) 
      (printout t "Q: How about sore throat? [yes/no]: ") 
      (bind ?input3 (readline)) 
      (if (neq ?input3 "no") 
      then 
       (assert (THE-PATIENT-HAS-A-SORE-THROAT)) 
     ) 
    ) 
) 
) 

(deffacts start 
    (start-question) 
) 

最終我確實讓節目過日子。

問題是,在規則問病的時候,我必須包含一堆if-then-else以使程序工作在不太符合回溯範式的地方。

有人能告訴我,我應該如何優化它在它知道從哪裏着手,規則1 - >規則2 /規則3等

回答

1

這裏有一個辦法:

(deffunction ask-question (?question $?allowed-values) 
    (printout t "Q: " ?question " [" (implode$ ?allowed-values) "] ") 
    (bind ?answer (read)) 
    (if (lexemep ?answer) 
     then (bind ?answer (lowcase ?answer))) 
    (while (not (member ?answer ?allowed-values)) do 
     (printout t "Q: " ?question " [" (implode$ ?allowed-values) "] ") 
     (bind ?answer (read)) 
     (if (lexemep ?answer) 
      then (bind ?answer (lowcase ?answer)))) 
    ?answer) 

(deffunction yes-or-no (?question) 
    (ask-question ?question yes no)) 

(defrule ask-temperature 
    => 
    (bind ?input (yes-or-no "Is the patient's temperature more than 39?")) 
    (assert (THE-PATIENT-TEMPERATURE-IS-40C ?input))) 

(defrule ask-sick-for-over-a-month 
    (THE-PATIENT-HAS-A-FEVER yes) 
    => 
    (bind ?input (yes-or-no "Does the patient sick over a month?")) 
    (assert (THE-PATIENT-HAS-BEEN-SICK-OVER-A-MONTH ?input))) 

(defrule ask-sore-throat 
    (WE-SUSPECT-A-BACTERIAL-INFECTION yes) 
    => 
    (bind ?input (yes-or-no "How about sore throat?")) 
    (assert (THE-PATIENT-HAS-A-SORE-THROAT ?input))) 

(defrule conclude-fever 
    (THE-PATIENT-TEMPERATURE-IS-40C yes) 
    => 
    (assert (THE-PATIENT-HAS-A-FEVER yes)) 
    (printout t "The patient has fever" crlf)) 

(defrule conclude-bacterial-infection 
    (THE-PATIENT-HAS-BEEN-SICK-OVER-A-MONTH yes) 
    (THE-PATIENT-HAS-A-FEVER yes) 
    => 
    (assert (WE-SUSPECT-A-BACTERIAL-INFECTION yes)) 
    (printout t "We suspect the patient has bacterial infection" crlf)) 

(defrule conclude-strep-throat 
    (THE-PATIENT-HAS-A-SORE-THROAT yes) 
    (WE-SUSPECT-A-BACTERIAL-INFECTION yes) 
    => 
    (assert (WE-BELIEVE-THE-PATIENT-HAS-STREP-THROAT yes)) 
    (printout t "We believe the patient has strep throat" crlf)) 

而另:

(deffunction ask-question (?question $?allowed-values) 
    (printout t "Q: " ?question " [" (implode$ ?allowed-values) "] ") 
    (bind ?answer (read)) 
    (if (lexemep ?answer) 
     then (bind ?answer (lowcase ?answer))) 
    (while (not (member ?answer ?allowed-values)) do 
     (printout t "Q: " ?question " [" (implode$ ?allowed-values) "] ") 
     (bind ?answer (read)) 
     (if (lexemep ?answer) 
      then (bind ?answer (lowcase ?answer)))) 
    ?answer) 

(deffunction yes-or-no (?question) 
    (ask-question ?question yes no)) 

(deftemplate attribute 
    (slot name) 
    (slot value)) 

(deftemplate question 
    (slot text) 
    (slot attribute) 
    (multislot precursors)) 

(deftemplate conclusion 
    (slot text) 
    (slot attribute) 
    (multislot precursors)) 

(deffacts questions 
    (question 
     (text "Is the patient's temperature more than 39?") 
     (attribute THE-PATIENT-TEMPERATURE-IS-40C)) 
    (question 
     (text "Does the patient sick over a month?") 
     (attribute THE-PATIENT-HAS-BEEN-SICK-OVER-A-MONTH) 
     (precursors THE-PATIENT-HAS-A-FEVER)) 
    (question 
     (text "How about sore throat?") 
     (attribute THE-PATIENT-HAS-A-SORE-THROAT) 
     (precursors WE-SUSPECT-A-BACTERIAL-INFECTION))) 

(deffacts conclusions 
    (conclusion 
     (text "The patient has fever") 
     (attribute THE-PATIENT-HAS-A-FEVER) 
     (precursors THE-PATIENT-TEMPERATURE-IS-40C)) 
    (conclusion 
     (text "We suspect the patient has bacterial infection") 
     (attribute WE-SUSPECT-A-BACTERIAL-INFECTION) 
     (precursors THE-PATIENT-HAS-BEEN-SICK-OVER-A-MONTH THE-PATIENT-HAS-A-FEVER)) 
    (conclusion 
     (text "We believe the patient has strep throat") 
     (attribute WE-BELIEVE-THE-PATIENT-HAS-STREP-THROAT) 
     (precursors THE-PATIENT-HAS-A-SORE-THROAT WE-SUSPECT-A-BACTERIAL-INFECTION))) 

(defrule ask-question 
    (question (text ?text) 
       (attribute ?attr)) 
    (forall (question (attribute ?attr) 
         (precursors $? ?pre $?)) 
      (attribute (name ?pre) 
         (value yes))) 
    => 
    (bind ?input (yes-or-no ?text)) 
    (assert (attribute (name ?attr) (value ?input)))) 

(defrule conclude 
    (conclusion (text ?text) 
       (attribute ?attr)) 
    (forall (conclusion (attribute ?attr) 
         (precursors $? ?pre $?)) 
      (attribute (name ?pre) 
         (value yes))) 
    => 
    (assert (attribute (name ?attr) (value yes))) 
    (printout t ?text crlf)) 
+0

哇!這真的很巧妙!謝謝! –