使用pytholog定义带症状列表的知识库查询失败,求解决方法
问题
想用pytholog构建一个疾病对应症状列表的知识库,写了如下代码:
import pytholog as pl diseases_kb = pl.KnowledgeBase() diseases_kb([ "disease(diabetes, [frequent_urination, extreme_thirst])", "disease(pneumonia, [cough, fever, shortness_of_breath])", ])
但执行查询print(diseases_kb.query(pl.Expr("disease(diabetes, Symptoms)")))时,返回结果是['No']。试过用()、list()替换列表语法都没用,怀疑是pytholog解析时会移除括号并按逗号拆分参数,有没有可行的解决办法?
解决办法
pytholog基于Prolog实现,而Prolog的事实参数并不支持Python风格的列表直接解析,得换用符合Prolog规范的方式来处理,这里有几种可行方案:
方案1:拆分疾病-症状为独立事实(推荐)
这是Prolog中存储一对多关系的标准做法,避免列表参数的解析问题,同时更灵活:
import pytholog as pl diseases_kb = pl.KnowledgeBase() # 添加疾病-症状对应事实 diseases_kb([ "disease_symptom(diabetes, frequent_urination)", "disease_symptom(diabetes, extreme_thirst)", "disease_symptom(pneumonia, cough)", "disease_symptom(pneumonia, fever)", "disease_symptom(pneumonia, shortness_of_breath)", # 定义规则,用findall收集某疾病的所有症状 "get_disease_symptoms(Disease, Symptoms) :- findall(S, disease_symptom(Disease, S), Symptoms)" ]) # 查询糖尿病的症状 print(diseases_kb.query(pl.Expr("get_disease_symptoms(diabetes, Symptoms)")))
执行后会返回[{'Symptoms': ['frequent_urination', 'extreme_thirst']}],完全符合需求。
方案2:使用Prolog兼容的列表语法直接定义
如果坚持要保留列表形式,确保定义和查询都使用Prolog的列表语法,同时用pl.Expr构造事实:
import pytholog as pl diseases_kb = pl.KnowledgeBase() # 用pl.Expr包装每个事实,确保列表被正确解析 diseases_kb([ pl.Expr("disease(diabetes, [frequent_urination, extreme_thirst])"), pl.Expr("disease(pneumonia, [cough, fever, shortness_of_breath])") ]) # 查询 result = diseases_kb.query(pl.Expr("disease(diabetes, Symptoms)")) print(result)
这种方式能让pytholog正确识别列表参数,返回预期的症状列表。
方案3:手动构造列表参数(调试用)
如果上述方法仍有问题,可以尝试将列表作为原子字符串传递,再通过Prolog规则转换:
import pytholog as pl diseases_kb = pl.KnowledgeBase() diseases_kb([ "disease(diabetes, 'frequent_urination,extreme_thirst')", "disease(pneumonia, 'cough,fever,shortness_of_breath')", # 定义规则拆分字符串为列表 "split_symptoms(Str, List) :- split_string(Str, ',', '', List)", "get_disease_symptoms(Disease, Symptoms) :- disease(Disease, SymStr), split_symptoms(SymStr, Symptoms)" ]) # 查询 print(diseases_kb.query(pl.Expr("get_disease_symptoms(diabetes, Symptoms)")))
不过这种方式需要依赖Prolog的字符串处理能力,通用性不如前两种方案。
内容的提问来源于stack exchange,提问作者Elissa
相关产品推荐
相关产品推荐

