CLIPS技术咨询:如何创建规则检查输入事实列表与已有事实的匹配性并输出对应关联事实
解决CLIPS规则匹配输入问题列表的方案
我来帮你捋清楚这个CLIPS规则的实现问题,先给你修正后的可运行代码,再详细解释怎么搞定输入列表和已有事实的匹配逻辑。
修正后的完整代码
(deftemplate rule (multislot problem) (slot cause)) (deffacts info (rule (problem one) (cause one1)) (rule (problem two) (cause two2)) (rule (problem three) (cause three3))) ; 补上你漏掉的闭合括号,不然编译会报错 (defrule reading-input => (printout t "Enter your problems: ") ; 读取整行输入并拆成符号列表,这样能一次性接收多个问题 (assert (problem $? (explode$ (readline))))) (defrule checking-input ; 用通配符定位输入列表里的单个问题 (problem $?prefix ?single-problem $?suffix) ; 匹配对应问题的已有规则事实 (rule (problem ?single-problem) (cause ?cause)) => (printout t "cause: " ?cause crlf))
关键调整说明
- 修复语法错误:你原来的
deffacts块末尾少了个),这会直接导致CLIPS编译失败,先补上这个小疏漏。 - 优化输入读取:原来的
(read)只能读单个符号,没法处理one two这种多问题输入。用(explode$ (readline))可以把用户输入的整行文本拆成符号列表,这样断言的problem事实就包含了所有输入的问题。 - 调整匹配逻辑:
checking-input规则里用$?prefix ?single-problem $?suffix这种通配符写法,能精准定位到输入列表里的每一个单独问题,然后直接和已有rule事实的problem槽匹配,CLIPS会自动找出所有符合条件的条目并输出对应的原因。
关于“检查输入事实列表与已有事实匹配”的实现思路
这里的核心是利用CLIPS的多槽通配符匹配和成员检查能力,分两种场景:
场景1:找出所有匹配的条目(就是你要的输出对应原因)
刚才的checking-input规则已经实现了这个逻辑——通过通配符遍历输入列表里的每个问题,逐个和已有rule事实匹配,只要有匹配就输出原因。
场景2:检查输入的所有问题是否都能匹配到已有事实
如果需要确认输入的问题有没有未匹配的,可以加个辅助规则来统计匹配数量:
(defrule check-all-matched (problem $?input-problems) ; 用accumulate统计所有匹配到的问题数量 (accumulate (bind ?matched-count 0) (bind ?matched-count (+ ?matched-count 1)) ?matched-count (rule (problem ?p) (cause ?c) (test (member$ ?p ?input-problems)))) => (bind ?input-length (length$ ?input-problems)) (if (eq ?matched-count ?input-length) then (printout t "All input problems have matching causes." crlf) else (printout t "Some input problems have no matching causes." crlf)))
这个规则会先收集所有能匹配到的问题数量,再和输入的问题总数对比,就能知道是不是所有输入都有对应的事实了。
实际运行效果
CLIPS> (reset) CLIPS> (run) Enter your problems: one two cause: one1 cause: two2 All input problems have matching causes. CLIPS>
内容的提问来源于stack exchange,提问作者Nikolay G
相关产品推荐
相关产品推荐

