任务描述
本关任务:编写一个能进行动物识别的程序。
相关知识
为了完成本关任务,你需要掌握产生式系统。
产生式系统
把一组产生式放在一起,让它们相互配合,协同作用,一个产生式生成的结论可以供另一个产生式作为已知事实使用,以求得问题的解,这样的系统称为产生式系统。一般来说,一个产生式系统由规则库、控制系统(推理机)、综合数据库三个部分组成。它们之间的关系如下图:
粗略的说,推理机主要做以下几项工作:
1、从规则库中选择与综合数据库中的已知事实进行匹配。
2、匹配成功的规则可能不止一条,这称为发生了冲突,需要进行冲突消解。
3、执行某一规则时,如果其右部是一个或多个结论,则把这些结论加入到综合数据库中:如果其右部是一个或多个操作,则执行这些操作。对于不确定性知识,在执行每一条规则时还要按一定的算法计算结论的不确定性。
4、检查综合数据库中是否包含了最终结论,决定是否停止系统的运行。
动物识别系统
下面我们以动物识别系统为例,介绍产生式系统求解问题的过程。这个动物识别系统是识别虎、金钱豹、斑马、长颈鹿、企鹅、鸵鸟、信天翁等七种动物的产生式系统。首先根据这些动物识别的专家知识,建立如下规则库:
r1: IF 该动物有毛发 THEN 该动物是哺乳动物
r2: IF 该动物有奶 THEN 该动物是哺乳动物
r3: IF 该动物有羽毛 THEN 该动物是鸟
r4: IF 该动物会飞 AND 会下蛋
THEN 该动物是鸟
r5: IF 该动物吃肉 THEN 该动物是食肉动物
r6: IF 该动物有犬齿 AND 有爪
AND 眼盯前方
THEN 该动物是食肉动物
r7: IF 该动物是哺乳动物 AND 有蹄
THEN 该动物是有蹄类动物
r8: IF 该动物是哺乳动物 AND 是反刍动物
THEN 该动物是有蹄类动物
r9: IF 该动物是哺乳动物 AND 是食肉动物
AND 是黄褐色
AND 身上有暗斑点
THEN 该动物是金钱豹
r10:IF 该动物是哺乳动物 AND 是食肉动物
AND 是黄褐色
AND 身上有黑色条纹
THEN 该动物是虎
r11:IF 该动物有蹄类动物 AND 有长脖子
AND 有长腿
AND 身上有暗斑点
THEN 该动物是长颈鹿
r12:IF 该动物有蹄类动物 AND 黑色条纹
THEN 该动物是斑马
r13:IF 该动物是鸟 AND 有长脖子
AND 有长腿
AND 不会飞
AND 有黑白二色
THEN 该动物是鸵鸟
r14:IF 该动物是鸟 AND 会游泳
AND 不会飞
AND 有黑白二色
THEN 该动物是企鹅
r15:IF 该动物是鸟 AND 善飞
THEN 该动物是信天翁
由上述产生式规则可以看出,虽然系统是用来识别七种动物的,但它并不是简单地设计7条规则,而是设计15条。其基本的想法是先根据一些比较简答的条件,如“有毛发”、“有羽毛”、“会飞”等对动物进行比较粗的分类。如“哺乳动物”、“鸟”等,然后随着条件的不断增加,逐步缩小分类范围,最后给出识别其中动物的规则。
举个例子,在综合数据库中,现在有如下已知事实:该动物的特征是有斑点,长脖子,长腿,奶,蹄。假设该综合数据库中的已知事实与规则库中的知识是从第一条(即r1)开始逐条进行匹配的,则当推理开始时,推理机构的工作过程是:
1.从规则库中取r1,检查其前提是否可以与综合数据库中已知事实匹配成功。由于综合数据库中没有“该动物有毛发”这一事实,所以匹配不成功,r1不能用于推理。然后取第二条规则r2,发现与“该动物有奶”相匹配。然后再检查r3至r15,均不匹配。所以将“该动物是哺乳动物”加入到综合数据库中。并将r2标记为使用过的记号,避免下次再被匹配。
此时综合数据库的内容变为:该动物的特征是有斑点,长脖子,长腿,奶,蹄,哺乳动物。
2.分别用r1、r3、r4、r5、r6与综合数据库中的已知事实进行匹配,均不成功。直至匹配到r7匹配时,匹配成功。然后检查r8至r15均不匹配。所以将“该动物是有蹄动物”加入到综合数据库中。并将r7标记为使用过的记号,避免下次再被匹配。此时综合数据库的内容变为:该动物的特征是有斑点,长脖子,长腿,奶,蹄,哺乳动物,有蹄类动物。
检查数据库,没有发现要识别的任何一种动物,所以还要继续推理。
3.在此之后,除匹配过的r2,r7外,只有r11可以与综合数据库中的已知数据库中的事实,匹配。所以将r11的结论加入综合数据库,此时综合数据库的内容变为:该动物的特征是有斑点,长脖子,长腿,奶,蹄,哺乳动物,有蹄类动物,长颈鹿。
检查综合数据库中的内容,发现要识别的动物长颈鹿包含在综合数据库中,所以推出了“该动物是长颈鹿”,这一最终结论。
上述过程的求解过程,就是不断地从规则库中选择可用规则与综合数据库中的已知事实进行匹配的过程。我们可以用普通编程语言的 if 语句来实现产生式系统。
编程要求
根据提示完成识别鸵鸟的程序片段,最终程序根据输入会输出根据提前条件、推导过程以及所识别的动物。
提示:为了方便编程,我们将条件进行编号:
前提条件
| 序号 | 前提 | 序号 | 前提 | 序号 | 前提 | 序号 | 前提 |
|---|---|---|---|---|---|---|---|
| 1 | 有毛发 | 6 | 吃肉 | 11 | 反刍 | 16 | 长腿 |
| 2 | 产奶 | 7 | 有犬齿 | 12 | 黄褐色 | 17 | 不会飞 |
| 3 | 有羽毛 | 8 | 有爪 | 13 | 有斑点 | 18 | 会游泳 |
| 4 | 不会飞 | 9 | 眼盯前方 | 14 | 有黑色条纹 | 19 | 黑白两色 |
| 5 | 会下蛋 | 10 | 有蹄 | 15 | 长脖 | 20 | 善飞 |
中间结论
| 编号 | 中间结论 | 编号 | 中间结论 |
|---|---|---|---|
| 21 | 哺乳类 | 23 | 食肉类 |
| 22 | 鸟类 | 24 | 蹄类 |
结论
| 编号 | 结论 | 编号 | 结论 | 编号 | 结论 | 编号 | 结论 |
|---|---|---|---|---|---|---|---|
| 25 | 金钱豹 | 27 | 长颈鹿 | 29 | 鸵鸟 | 31 | 信天翁 |
| 26 | 虎 | 28 | 斑马 | 30 | 企鹅 |
推导规则
| 推导规则 | 推导规则 | 推导规则 | 推导规则 |
|---|---|---|---|
| 1→21 | 2→21 | 3→22 | 4,5→22 |
| 21,6→23 | 7,8,9→23 | 21,10→23 | 21,11→24 |
| 21,23,12,13→25 | 21,23,12,14→26 | 24,15,16,13→27 | 24,14→28 |
| 22,15,16,4→29 | 22,18,19,4→30 | 22,20→31 |
测试说明
对你编写的代码进行测试:其中输入以0为结束符。
测试输入:
0
预期输出:
前提条件为:
推理过程如下:
根据所给条件无法判断为何种动物
测试输入:
22
20
0
预期输出:
前提条件为:
鸟类 善飞
推理过程如下:
善飞,鸟类->信天翁
所识别的动物为信天翁
测试输入:
1
11
14
0
预期输出:
前提条件为:
有毛发 反刍 有黑色条纹
推理过程如下:
有毛发->哺乳类
反刍,哺乳类->哺乳类
有黑色条纹,蹄类->斑马
所识别的动物为斑马
代码文件
animal.py
# 动物识别系统
# 自定义函数,判断有无重复元素
def judge_repeat(value, list=[]):
for i in range(0, len(list)):
if (list[i] == value):
return 1
else:
if (i != len(list) - 1):
continue
else:
return 0
# 自定义函数,对已经整理好的综合数据库real_list进行最终的结果判断
def judge_last(list):
for i in list:
if (i == '23'):
for i in list:
if (i == '12'):
for i in list:
if (i == '21'):
for i in list:
if (i == '13'):
print("黄褐色,有斑点,哺乳类,食肉类->金钱豹\n")
print("所识别的动物为金钱豹")
return 0
elif (i == '14'):
print("黄褐色,有黑色条纹,哺乳类,食肉类->虎\n")
print("所识别的动物为虎")
return 0
elif (i == '14'):
for i in list:
if (i == '24'):
print("有黑色条纹,蹄类->斑马\n")
print("所识别的动物为斑马")
return 0
elif (i == '24'):
for i in list:
if (i == '13'):
for i in list:
if (i == '15'):
for i in list:
if (i == '16'):
print("有斑点,有黑色条纹,长脖,蹄类->长颈鹿\n")
print("所识别的动物为长颈鹿")
return 0
elif (i == '20'):
for i in list:
if (i == '22'):
print("善飞,鸟类->信天翁\n")
print("所识别的动物为信天翁")
return 0
#********* Begin *********#
# ********* End *********#
elif (i == '4'):
for i in list:
if (i == '22'):
for i in list:
if (i == '18'):
for i in list:
if (i == '19'):
print("不会飞,会游泳,黑白二色,鸟类->企鹅\n")
print("所识别的动物企鹅")
return 0
else:
if (list.index(i) != len(list) - 1):
continue
else:
print("\n根据所给条件无法判断为何种动物")
main.py
from animal import judge_last,judge_repeat
dict_before = {'1': '有毛发', '2': '产奶', '3': '有羽毛', '4': '不会飞', '5': '会下蛋', '6': '吃肉', '7': '有犬齿',
'8': '有爪', '9': '眼盯前方', '10': '有蹄', '11': '反刍', '12': '黄褐色', '13': '有斑点', '14': '有黑色条纹',
'15': '长脖', '16': '长腿', '17': '不会飞', '18': '会游泳', '19': '黑白二色', '20': '善飞', '21': '哺乳类',
'22': '鸟类', '23': '食肉类', '24': '蹄类', '25': '金钱豹', '26': '虎', '27': '长颈鹿', '28': '斑马',
'29': '鸵鸟', '30': '企鹅', '31': '信天翁'}
# 综合数据库
list_real = []
while (1):
# 循环输入前提条件所对应的字典中的键
num_real = input()
list_real.append(num_real)
if (num_real == '0'):
break
#print("\n")
print("前提条件为:")
# 输出前提条件
for i in range(0, len(list_real) - 1):
print(dict_before[list_real[i]], end=" ")
print("\n")
print("推理过程如下:")
# 遍历综合数据库list_real中的前提条件
for i in list_real:
if (i == '1'):
if (judge_repeat('21', list_real) == 0):
list_real.append('21')
print("有毛发->哺乳类")
elif (i == '2'):
if (judge_repeat('21', list_real) == 0):
list_real.append('21')
print("产奶->哺乳类")
elif (i == '3'):
if (judge_repeat('22', list_real) == 0):
list_real.append('22')
print("有羽毛->鸟类")
else:
if (list_real.index(i) != len(list_real) - 1):
continue
else:
break
for i in list_real:
if (i == '4'):
for i in list_real:
if (i == '5'):
if (judge_repeat('22', list_real) == 0):
list_real.append('22')
print("不会飞,会下蛋->鸟类")
elif (i == '6'):
for i in list_real:
if (i == '21'):
if (judge_repeat('21', list_real) == 0):
list_real.append('21')
print("食肉->哺乳类")
elif (i == '7'):
for i in list_real:
if (i == '8'):
for i in list_real:
if (i == '9'):
if (judge_repeat('23', list_real) == 0):
list_real.append('23')
print("有犬齿,有爪,眼盯前方->食肉类")
elif (i == '10'):
for i in list_real:
if (i == '21'):
if (judge_repeat('24', list_real) == 0):
list_real.append('24')
print("有蹄,哺乳类->蹄类")
elif (i == '11'):
for i in list_real:
if (i == '21'):
if (judge_repeat('24', list_real) == 0):
list_real.append('24')
print("反刍,哺乳类->哺乳类")
else:
if (i != len(list_real) - 1):
continue
else:
break
judge_last(list_real)