You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

饮食营养专家系统CLIPS代码无结果输出问题求助

饮食营养专家系统CLIPS代码修正方案

问题分析

原代码无法输出结果的核心问题如下:

  • 输入规则触发混乱:多个输入规则(read-age、read-height等)触发条件相同,导致同时执行,输入顺序失控,甚至重复输入。
  • 事实名称不匹配:计算规则断言的事实(如daily-calories)与输出规则匹配的事实(如calories-needed)名称不一致,输出规则无法触发。
  • 身体状态值大小写不统一:计算规则断言的是"Underweight"(首字母大写),但输出规则匹配的是underweight(全小写),导致规则不匹配。
  • 缺少纤维计算逻辑:系统承诺输出每日纤维需求,但未实现对应计算规则。
  • BMI计算公式错误:未将厘米单位的身高转换为米,导致BMI计算值严重偏离实际。
  • 输出规则触发条件缺失:输出规则没有等待所有计算完成的逻辑,部分规则因依赖事实未完全生成而无法触发。

修正后的完整代码

(defrule read-gender
  (initial-fact)
  =>
  (printout t crlf crlf "欢迎使用饮食营养专家系统" crlf)
  (printout t "******************************************" crlf)
  (printout t "本系统将为您生成以下结果:" crlf)
  (printout t "1. 您的BMI指数及身体状态" crlf)
  (printout t "2. 基于身体状态的每日推荐卡路里摄入量" crlf)
  (printout t "3. 基于体重的每日蛋白质需求量" crlf)
  (printout t "4. 基于年龄的每日钙需求量" crlf)
  (printout t "5. 基于卡路里需求的每日纤维需求量" crlf)
  (printout t "6. 基于体重的每日碳水化合物需求量" crlf)
  (printout t "******************************************" crlf crlf)
  (printout t "请输入您的性别(Female/Male,区分大小写):") 
  (assert (gender (read))))

(defrule read-age
  (gender ?)
  (not (age ?))
  =>
  (printout t "请输入您的年龄:")
  (assert (age (read))))

(defrule read-height
  (age ?)
  (not (height ?))
  =>
  (printout t "请输入您的身高(单位:厘米):")
  (assert (height (read))))

(defrule read-weight
  (height ?)
  (not (weight ?))
  =>
  (printout t "请输入您的体重(单位:千克):")
  (assert (weight (read))))

(defrule read-activity-days
  (weight ?)
  (not (activity-days ?))
  =>
  (printout t "请输入您每周锻炼的天数:")
  (assert (activity-days (read))))

(defrule set-activity-rate-sedentary
  (activity-days ?days)
  (test (< ?days 2))
  =>
  (assert (activity-rate "Sedentary"))
  (assert (activity-factor 1.2)))

(defrule set-activity-rate-moderate
  (activity-days ?days)
  (test (and (>= ?days 2) (< ?days 5)))
  =>
  (assert (activity-rate "Moderate"))
  (assert (activity-factor 1.55)))

(defrule set-activity-rate-hard
  (activity-days ?days)
  (test (>= ?days 5))
  =>
  (assert (activity-rate "Hard"))
  (assert (activity-factor 1.75)))

(defrule calculate-bmi
  (weight ?weight)
  (height ?height)
  =>
  (bind ?height-m (/ ?height 100)) ; 将厘米转换为米
  (bind ?bmi (/ ?weight (* ?height-m ?height-m)))
  (assert (bmi ?bmi)))

(defrule set-body-status-underweight
  (bmi ?bmi)
  (test (< ?bmi 18.5))
  =>
  (assert (body-status "underweight"))) ; 统一为小写

(defrule set-body-status-normal-weight
  (bmi ?bmi)
  (test (and (>= ?bmi 18.5) (< ?bmi 24.9)))
  =>
  (assert (body-status "normal-weight"))) ; 统一为小写

(defrule set-body-status-overweight
  (bmi ?bmi)
  (test (and (>= ?bmi 24.9) (< ?bmi 29.9)))
  =>
  (assert (body-status "overweight"))) ; 统一为小写

(defrule set-body-status-obesity
  (bmi ?bmi)
  (test (>= ?bmi 29.9))
  =>
  (assert (body-status "obesity"))) ; 新增肥胖状态规则

(defrule calculate-daily-calories-female
  (gender "Female")
  (activity-factor ?activity-factor)
  (weight ?weight)
  (age ?age)
  (height ?height)
  =>
  (bind ?height-m (/ ?height 100))
  (bind ?bmr (+ 655.1 (+ (* 9.563 ?weight) (* 1.85 ?height-m) (* -4.676 ?age)))) ; BMR公式修正:年龄项为负
  (bind ?daily-calories (* ?bmr ?activity-factor))
  (assert (calories-needed ?daily-calories)) ; 统一事实名称
  (assert (daily-calories ?daily-calories)))

(defrule calculate-daily-calories-male
  (gender "Male")
  (activity-factor ?activity-factor)
  (weight ?weight)
  (age ?age)
  (height ?height)
  =>
  (bind ?height-m (/ ?height 100))
  (bind ?bmr (+ 66.5 (+ (* 13.75 ?weight) (* 5.003 ?height-m) (* -6.755 ?age)))) ; BMR公式修正:年龄项为负
  (bind ?daily-calories (* ?bmr ?activity-factor))
  (assert (calories-needed ?daily-calories)) ; 统一事实名称
  (assert (daily-calories ?daily-calories)))

(defrule set-daily-calcium-baby
  (age ?age)
  (test (< ?age 4))
  =>
  (assert (calcium-needed "210-270mg")) ; 统一事实名称
  (assert (daily-calcium "210-270mg")))

(defrule set-daily-calcium-child
  (age ?age)
  (test (and (>= ?age 4) (< ?age 9)))
  =>
  (assert (calcium-needed "350-450mg")) ; 统一事实名称
  (assert (daily-calcium "350-450mg")))

(defrule set-daily-calcium-teen
  (age ?age)
  (test (and (>= ?age 9) (< ?age 19)))
  =>
  (assert (calcium-needed "800mg")) ; 统一事实名称
  (assert (daily-calcium "800mg")))

(defrule set-daily-calcium-adult
  (age ?age)
  (test (and (>= ?age 19) (< ?age 51)))
  =>
  (assert (calcium-needed "1000mg")) ; 统一事实名称
  (assert (daily-calcium "1000mg")))

(defrule set-daily-calcium-old
  (age ?age)
  (test (>= ?age 51))
  =>
  (assert (calcium-needed "1200mg")) ; 统一事实名称
  (assert (daily-calcium "1200mg")))

(defrule calculate-daily-protein-sedentary
  (weight ?weight)
  (activity-rate "Sedentary")
  =>
  (bind ?daily-protein (* ?weight 0.8))
  (assert (protein-needed ?daily-protein)) ; 统一事实名称
  (assert (daily-protein ?daily-protein)))

(defrule calculate-daily-protein-moderate
  (weight ?weight)
  (activity-rate "Moderate")
  =>
  (bind ?daily-protein (* ?weight 1))
  (assert (protein-needed ?daily-protein)) ; 统一事实名称
  (assert (daily-protein ?daily-protein)))

(defrule calculate-daily-protein-hard
  (weight ?weight)
  (activity-rate "Hard")
  =>
  (bind ?daily-protein (* ?weight 1.2))
  (assert (protein-needed ?daily-protein)) ; 统一事实名称
  (assert (daily-protein ?daily-protein)))

(defrule calculate-daily-carbohydrates
  (weight ?weight)
  =>
  (bind ?daily-carbohydrates (* ?weight 2.5))
  (assert (carbohydrate-needed ?daily-carbohydrates)) ; 统一事实名称
  (assert (daily-carbohydrates ?daily-carbohydrates)))

(defrule calculate-daily-fiber
  (calories-needed ?calories)
  =>
  (bind ?fiber (round (/ ?calories 100))) ; 每100卡路里对应1克纤维
  (assert (fiber-needed ?fiber)) ; 新增纤维计算规则
  (assert (daily-fiber ?fiber)))

(defrule print-all-results
  (bmi ?bm)
  (body-status ?b)
  (calories-needed ?c)
  (protein-needed ?p)
  (calcium-needed ?ca)
  (fiber-needed ?f)
  (carbohydrate-needed ?carbo)
  =>
  (printout t crlf crlf "      ########   计算结果  ######## " crlf)
  (printout t "1. 您的BMI指数为:" ?bm ",身体状态:" ?b crlf)
  (printout t "2. 每日推荐卡路里摄入量:" ?c "千卡" crlf)
  (printout t "3. 每日蛋白质需求量:" ?p "克" crlf)
  (printout t "4. 每日钙需求量:" ?ca crlf)
  (printout t "5. 每日纤维需求量:" ?f "克" crlf)
  (printout t "6. 每日碳水化合物需求量:" ?carbo "克" crlf)
  
  ; 根据身体状态输出额外建议
  (if (eq ?b "underweight")
      then (printout t crlf "专家建议:您可每日额外摄入300卡路里(总计" (+ ?c 300) "千卡),每周可增重约0.25千克。" crlf)
      else (if (eq ?b "normal-weight")
              then (printout t crlf "专家建议:保持当前卡路里摄入,维持健康体重。" crlf)
              else (if (eq ?b "overweight")
                      then (printout t crlf "专家建议:每日减少300卡路里摄入(总计" (- ?c 300) "千卡),逐步控制体重。" crlf)
                      else (printout t crlf "专家建议:每日减少500卡路里摄入(总计" (- ?c 500) "千卡),每周可减重约0.5千克。" crlf)))))

关键修正点说明

  1. 输入规则顺序化:修改输入规则的触发条件,确保只有前一个输入完成后才触发下一个(如read-age需(not (age ?))),避免输入混乱。
  2. 统一事实名称:将计算规则断言的事实名称与输出规则匹配的名称统一(如daily-calories改为calories-needed,同时保留原事实兼容其他规则)。
  3. 统一身体状态值大小写:将身体状态的断言值改为全小写,与输出规则的匹配条件一致。
  4. 修正BMI计算逻辑:加入身高单位转换(厘米转米),确保BMI计算结果正确。
  5. 修正BMR公式:原公式中年龄项符号错误(应为减法),修正后保证卡路里计算准确。
  6. 新增纤维计算规则:根据每日卡路里需求计算纤维摄入量(每100卡路里对应1克纤维)。
  7. 统一输出规则:新增print-all-results规则,等待所有必要事实生成后一次性输出结果,避免分散输出的问题,并加入不同身体状态的建议。

内容的提问来源于stack exchange,提问作者Zeek G

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 02:06:03