2019.2.26
主要功能:
1. 功能完善(知识库、综合数据库、推理机)
2. 正向推理、反向推理
3. 知识库可维护(添加、删除、修改)
4. 中间结果可视化(推理中间结果可见)
这次编写代码的时候,思路很清晰,从之前的节奏中跳了出来,先def main() ,之后在main() 中定义各个模块,之后再思考各个模块怎样实现,这样编写代码看起来很合理。
当我编写一个函数的时候,特别是算法部分,如 def Topo() 最好是先想一下自己要怎么做才能完成,而不是直接上手,要想好怎么做,之后再动手
没有UI界面。。因为只是随手做的,而且也没有学PyQt5,只是为了另一件事拿这个熟悉一下专家系统。
后期会更新的, 吧??
主要说一下问题:
我觉得主要是难在了新增一条规则时候,需要进行规则的整合管理。
开始的时候,使用了拓扑排序,但是发现不行,因为同一个结论,如下面rules.txt中的哺乳动物,可以由两种方式推导出来,这样的结构其实不合适用拓扑排序(也可能是我理解不够)
对于下面这一个规则,就是很简单的 当满足哺乳动物 和 反刍动物的时候,那么就是有蹄类动物
哺乳动物 反刍动物->有蹄类动物
image.png
而对于这样两条规则:
有毛发->哺乳动物
有奶-> 哺乳动物
image.png
那么他们的逻辑图应该怎么画呢?这就很迷惑。。
这样导致了他们的图我不知道怎么画,更不用DAG谈拓扑化了。
我所使用的方法,则很简单,就是先遍历一遍所有规则,找出其中的baseAttr(也就是基础属性,基础属性意味着他不是被推导出来的,而是先天的属性,如:有毛发);
然后,不断第二次规则库,当规则满足他的前置条件都在base中,那么就加入到拓扑规则序列中,然后将他的结论也加入到baseAttr中。不断遍历规则库,知道所有的规则都被加入到了拓扑序列中。
这样就能实现规则的增加了。
代码
#使用专家系统来构建 动物识别系统
#使用:加入一条规则S,当规则库中已有的node中包含了S的前置条件,才加入到规则库中,否则先跳过
def TopulogyRules(rules):
basicAttr = set() #基础属性
midAttr = set() #这些中是被推倒出来的结论
for rule in rules:
for attr in rule:
basicAttr.add(attr)
midAttr.add(rule[-1])
basicAttr = basicAttr - midAttr #全部属性 - 中间属性 = 基础属性
rs = rules.copy()
visited = []
for i in range(len(rules)):
visited.append(0)
newRules = []
while(len(rs) != 0):
for rule in rules:
if rule in rs:
s = set(rule[:-1])
if s <= basicAttr:
newRules.append(rule)
rs.remove(rule)
visited[i] = 1
basicAttr.add(rule[-1])
print(newRules)
#不断新建base环境,不断向前搜索,不断添加
return rules
###读入rules.txt,然后拓扑化 rules,返回一个拓扑化之后的 rules
def getRules():
animalKinds = []
rules = []
f = open("./AnimalRecongnizeSystem/rules.txt", 'r', encoding='UTF-8')
#f = open("./AnimalRecongnizeSystem/data.txt", 'r').read()
for line in f:
#print(line, end='')
line = line.replace("\n","")
ls = line.split(" ")
rules.append(ls)
animalKinds = rules[-1]
rules.pop()
rules = TopulogyRules(rules)
f.close()
return rules,animalKinds
def getAnimalInfo():
info = input("请输入动物的特征(空格为分隔符): ")
basicInfo = info.split(' ')
return basicInfo
def Inference(rules, basicInfo, animalKinds):
animal = "茄子"
for rule in rules:
set1 = set(rule[:-1])
set2 = set(basicInfo)
if set1 <= set2:
set2.add(rule[-1])
basicInfo = list(set2)
if rule[-1] in animalKinds:
animal = rule[-1]
break
print(basicInfo)
return animal
def showRules():
pass
def main():
rules, animalKinds = getRules()
# print("知识库中的全部规则为:{}".format(rules))
# print("知识库能推导出的动物种类为:{}".format(animalKinds))
basicInfo = getAnimalInfo()
animal = Inference(rules, basicInfo, animalKinds)
print("你描述的动物是:{}".format(animal))
main()
# 测试用例:身上有暗斑点 黄褐色 长脖子 有长腿 有奶 有蹄
rules.txt
有毛发 哺乳动物
有奶 哺乳动物
有羽毛 鸟
会飞 会下蛋 鸟
吃肉 食肉动物
有犬齿 有爪 眼盯前方 食肉动物
哺乳动物 有蹄 有蹄类动物
哺乳动物 反刍动物 有蹄类动物
哺乳动物 食肉动物 黄褐色 身上有暗斑点 金钱豹
哺乳动物 食肉动物 黄褐色 身上有黑色条纹 虎
有蹄类动物 长脖子 有长腿 身上有暗斑点 长颈鹿
有蹄类动物 身上有黑色条纹 斑马
鸟 长脖子 有长腿 不会飞 有黑白二色 鸵鸟
鸟 会游泳 不会飞 有黑白二色 企鹅
鸟 善飞 信天翁
金钱豹 虎 长颈鹿 斑马 鸵鸟 企鹅 信天翁