《智能系统》课程实验-产生式系统推理

实验简介

本次实验题目是《智能系统》课程实验2-产生式系统推理。仅供学习和参考,希望能对你思路有所启发。实验算法仅是个人理解,不保证正确,请勿抄袭。

一 实验题目

产生式系统推理

二 实验目的

1 熟悉和掌握产生式系统的构成和运行机制;
2 掌握基于规则推理的基本方法和技术,掌握正确的正向推理和逆向推理方法;
3 熟悉在具体问题中如何实现正向推理和逆向推理的求解流程 。

三 实验要求

1 以产生式推理模式为基础,实现小型动物分类系统,推理方法可以采用正向推理或反向推理;
2 要求表示规则的语言必须能体现出规则前提和结论的对应关系,必须能体现出前提和结论中的逻辑关系;
3 要求能对规则库进行动态地增加、删除和修改操作;
4 要求用界面显示要查询的初始事实、推理方法、推理中用到的规则和结论。

四 数据结构

用Python字典数据类型存储规则库数据rules。
在这里插入图片描述
用Python列表数据类型存储动物特征选项。在这里插入图片描述
算法中的facts,conclusions用Python集合数据类型。

五 实验算法

1 正向推理

初始化facts,conclusions为空集合;
选择特征,选择的特征同时加到facts集合和conclusions集合里;
循环:
	遍历规则库rules每个规则rule:
		如果rule前提是facts的子集且rule没被用过:
			使用规则rule进行推导并输出
			移除conclusions在rule前提里有的特征
			将rule结论放入facts和conclusions
	如果本次循环没有使用到任何规则,就跳出循环
输出事实集合facts
输出结论结合conclusions

2 反向推理

初始化facts,conclusions为空集合;
选择目标特征,加到facts集合里;
循环:
	遍历规则库rules每个规则rule:
		如果rule结论属于facts且rule没被用过:
			使用规则rule进行反向推导并输出
			将rule前提放入facts和conclusions
	如果本次循环没有使用到任何规则,就跳出循环
输出事实集合facts
输出结论结合conclusions

增加、删除、修改规则较简单,直接在rules集合增加、删除、修改即可。

六 实验结果

1 运行测试

初始选择操作界面如下。

因为“修改规则”可由“增加规则”和“删除规则”组合操作得到,所以略去了“修改规则”选项,以简化项目,更专注于算法的设计。

在这里插入图片描述
我们先测试“正向推理”,输入1,回车,进入正向推理界面,输入编号选择动物特征。
在这里插入图片描述
输入2 10 14 15(有毛发,吃肉,黄褐色,有黑色条纹)q,正向推理输出结果如下。显然,根据推理规则得出,输入的特征完全符合老虎的特征,输出的结论是老虎。
在这里插入图片描述
输入2 10 14 15 4(有毛发,吃肉,黄褐色,有黑色条纹,会飞)q,正向推理输出结果如下。输入的这几个特征,比老虎多了一个“会飞”,但规则数据里又没有完美符合这些特征的选项,于是推出了两个结论“老虎”和“会飞”,可以解释为拥有这个特征的动物是“会飞的老虎”。由于没有更好的结论,只能输出这样的组合结论。
在这里插入图片描述
输入2 10 14(有毛发,吃肉,黄褐色)q,正向推理输出结果如下。输入的这几个特征,比老虎少了一个“有黑色条纹”,我们无法断定它是老虎,推理得到两个结论“黄褐色”和“食肉动物”,可以解释为拥有这个特征的动物是“黄褐色的食肉动物”。由于没有更好的结论,只能输出这样的组合结论。
在这里插入图片描述
接下来我们尝试一下反向推理。
我们选择特征时界面和正向推理一样。我们输入86(鹰)试试。得到的结论有“鸟”、“吃肉”、“会飞”、“上嘴鹰钩”、“卵生”、“有羽毛”、“生蛋”、“有爪”。反向推理比较简单,输入其它的特征进行反向推理的情况也类似。
在这里插入图片描述
接下来我们来增加规则。输入“中分 背带裤 打篮球”,再输入结论“坤”。显示规则添加成功。
在这里插入图片描述
再看看现有规则,可以看到尾部增加了“(‘中分’, ‘背带裤’, ‘打篮球’): ‘坤’”这么一个规则,说明添加成功。
我们来尝试删除它。
在这里插入图片描述
显示删除成功,再看一次现有规则,可以看到结尾已经没有“坤”的判定规则。

实验结果显示,程序能够顺利地进行正向推理、反向推理、增加规则、删除规则,以及由增加删除操作可以组合出修改规则操作。

2 性能分析

本算法的时间复杂度主要取决于两个循环:选择动物特征的循环和推理的循环。

选择动物特征的循环:这个循环的时间复杂度取决于用户的输入次数,我们可以将其表示为O(n),其中n是用户输入的次数。

正向推理和反向推理的循环:这两个循环都遍历所有的规则,对于每个规则,它检查该规则是否满足特定条件,这个操作的时间复杂度是O(m),其中m是规则的数量。然后,它可能会从结论集中删除元素,这个操作的时间复杂度是O(k),其中k是结论集的大小。因此,这两个循环的总时间复杂度是O(m*k)。

因此,整个代码的时间复杂度是O(n + m*k)。这是一个粗略的估计,实际的时间复杂度可能会因为Python内部的优化和数据结构的特性而有所不同。

七 实验总结及体会

正向推理是最复杂的,因为它可能会出现自相矛盾的事实。比如在老虎的特征之上再加上“会飞”,出现了一个规则库中不存在的生物体,对此,我们只能输出组合结论“会飞的老虎”。

写完代码后,我给助教老师检查了两次。反向推理以及规则的增删改没有什么问题,就只有正向推理出问题。

第一次在老虎的特征基础上加上“会飞”特征,我的程序推导出“老虎”,但现实中显然不存在有“会飞”特征的“老虎”,我的算法需要修改。

第二次给助教老师检查,我使用了“概率”或“特征符合率”来描述推导出最优结论与特征的符合率。如果完全符合“老虎”的特征,结论是“老虎”,特征符合率是1.0。在老虎的特征基础上加上“会飞”特征,结论是“老虎”,“特征符合率”是0.875,可以解释为拥有这个特征的动物最接近“老虎”,符合87.5%“老虎”的特征。但助教老师又指出这个方法有缺点。输入特征“有毛发”、“吃肉”、“黄褐色”,推出结论是0.8特征符合率的“食肉动物”结论,而显然符合这个特征的动物必定是“食肉动物”。这时候特征符合率就并不能很好地进行推理了。

下课后,我决定再换一种算法,推导出组合结论,让“会飞”和“老虎”的结论同时存在,而不只给出最优结论,因为根本无法推导出一个正确的最优结论。将结论解释为“会飞的老虎”或者“黄褐色的食肉动物”之类的组合结论,从而弥补规则库的局限。实验证明效果确实不错,我决定将它作为最终算法。

本次实验共设计了三种算法,既锻炼了我的算法设计能力,也让我更深刻地理解了产生式系统推理的过程。

实验代码

# 创建规则库
rules = {
    ("有奶",): "哺乳动物",
    ("有毛发",): "哺乳动物",
    ("有羽毛",): "鸟",
    ("会飞", "生蛋"): "鸟",
    ("哺乳动物", "有爪", "有犬齿", "目盯前方"): "食肉动物",
    ("哺乳动物", "吃肉"): "食肉动物",
    ("哺乳动物", "有蹄"): "有蹄动物",
    ("有蹄动物", "反刍食物"): "偶蹄动物",
    ("食肉动物", "黄褐色", "有黑色条纹"): "老虎",
    ("食肉动物", "黄褐色", "有黑色斑点"): "金钱豹",
    ("有蹄动物", "长腿", "长脖子", "黄褐色", "有暗斑点"): "长颈鹿",
    ("有蹄动物", "白色", "有黑色条纹"): "斑马",
    ("鸟", "不会飞", "长腿", "长脖子", "黑白色"): "驼鸟",
    ("鸟", "不会飞", "会游泳", "黑白色"): "企鹅",
    ("鸟", "善飞", "不怕风浪"): "海燕",

# 扩充规则库
    ("有毛发", "有奶", "善跳跃", "唇裂"): "兔子",
    ("有毛发", "有奶", "善捕鼠", "脚有肉垫"): "猫",
    ("有毛发", "有奶", "鼻子上有角", "褐色", "皮糙肉后", "皮糙肉厚", "有蹄"): "犀牛",
    ("有毛发", "有奶", "黑眼圈", "四肢短小"): "熊猫",
    ("鸟", "上嘴鹰钩", "会模仿人说话"): "鹦鹉",
    ("鸟", "腿短", "嘴扁平", "善潜水游泳"): "鸭子",
    ("鸟", "上嘴鹰钩", "有爪", "吃肉"): "鹰",
    ("有羽毛", "卵生", "善游泳", "嘴扁平", "腿短"): "鸭子",
    ("有羽毛", "卵生", "善潜水游泳", "白色或黑色", "颈长", "嘴大", "腿长", "颈部有肉只凸起"): "鹅",
    ("有羽毛", "卵生", "黑色", "嘴大"): "鸦",
    ("有羽毛", "卵生", "有爪", "吃肉", "上嘴鹰钩"): "鹰",
    ("有羽毛", "卵生", "上嘴鹰钩", "能模仿人说话"): "鹦鹉",
    ("卵生", "生活在水中", "生活在陆地", "有皮肤呼吸", "用肺呼吸", "皮肤光滑", "吃昆虫", "会变色"): "青蛙",
    ("卵生", "生活在水中", "生活在陆地", "有皮肤呼吸", "用肺呼吸", "吃昆虫", "皮肤粗糙", "四肢扁", "背部黑色"): "蝾螈",
    ("卵生", "生活在水中", "生活在陆地", "有皮肤呼吸", "用肺呼吸", "吃昆虫", "皮肤粗糙"): "蟾蜍",
    ("用鳃呼吸", "身体有鳍", "生活在海洋中", "身体扁平", "两眼在头部同侧"): "比目鱼",
    ("用鳃呼吸", "身体有鳍", "生活在淡水中", "身体扁平", "头高尾部窄"): "鲫鱼",
    ("生活在陆地", "用肺呼吸", "胎生", "身体有鳞或甲", "身体圆而细长", "吃小动物"): "蛇",
    ("生活在陆地", "用肺呼吸", "胎生", "身体有鳞或甲", "有四肢", "尾巴细长易断", "吃昆虫"): "壁虎",
    ("生活在陆地", "用肺呼吸", "胎生", "身体有鳞或甲", "身体圆而扁", "有坚硬的壳"): "乌龟",
    ("生活在陆地", "用肺呼吸", "胎生", "身体有鳞或甲", "壳为黄褐色", "皮肤光滑", "有黑斑"): "玳瑁",
    ("生活在陆地", "用肺呼吸", "胎生", "身体有鳞或甲", "有四肢", "善游泳", "皮硬黑褐色"): "鳄鱼",
}


# 动物特征选择列表
choices = ["有奶","有毛发","有羽毛","会飞","生蛋","哺乳动物", "有爪", "有犬齿", "目盯前方",
"吃肉", "有蹄", "反刍食物", "有蹄动物", "黄褐色", "有黑色条纹", "有黑色斑点", "长腿", "长脖子", "有暗斑点",
"白色", "鸟", "不会飞", "黑白色", "善飞", "不怕风浪", "有奶", "善跳跃", "唇裂", "善捕鼠", "脚有肉垫",
"鼻子上有角", "皮糙肉后", "皮糙肉厚", "有蹄", "黑眼圈", "四肢短小", "上嘴鹰钩", "会模仿人说话", "腿短",
"嘴扁平", "善潜水游泳", "有爪", "吃肉", "卵生", "生活在水中", "生活在陆地", "有皮肤呼吸", "用肺呼吸",
"皮肤光滑", "吃昆虫", "会变色", "皮肤粗糙", "四肢扁", "背部黑色", "身体有鳍", "生活在海洋中", "身体扁平",
"两眼在头部同侧", "生活在淡水中", "头高尾部窄", "身体有鳞或甲", "身体圆而细长", "吃小动物", "有四肢",
"尾巴细长易断", "吃昆虫", "身体圆而扁", "有坚硬的壳", "壳为黄褐色", "皮肤光滑", "有黑斑", "皮硬黑褐色",
"生活在陆地", "用肺呼吸", "胎生", "有鳞或甲", "有四肢", "善游泳", "鳄鱼", "兔子", "猫", "犀牛", "熊猫",
"鹦鹉", "鸭子", "鹰", "鹅", "鸦", "青蛙", "蝾螈", "蟾蜍", "比目鱼", "鲫鱼", "蛇", "壁虎", "乌龟", "玳瑁"
]


# 选择动物特征
def select():
    print("请选择动物特征:")
    for i in range(len(choices)):
        print("%d. %s" % (i + 1, choices[i]), end=", ")
    print("q. 退出")
    choice = input("请输入编号:")
    if choice.isdigit() and 0 < int(choice) <= len(choices):
        return choices[int(choice) - 1]
    elif choice == "q":
        return choice
    else:
        print("输入错误,请重新输入!")
        return select()


# 正向推理
def forward():
    # 初始事实
    facts = set()
    # 选择动物特征
    while True:
        choice = select()
        if choice == "q":
            break
        facts.add(choice)
    # 推理
    used_rules = set()
    conclusions = set()
    for fact in facts:
        conclusions.add(fact)
    while True:
        flag = False
        for rule in rules:
            if set(rule).issubset(facts) and rule not in used_rules:
                print("使用规则:%s -> %s" % (rule, rules[rule]))
                for feature in rule:
                    if feature in conclusions:
                        conclusions.remove(feature)
                facts.add(rules[rule])
                conclusions.add(rules[rule])
                used_rules.add(rule)
                flag = True
        if not flag:
            break
    # 显示最终的事实
    print("推理过程中得到的事实:", facts)
    print("推理过程中得到的结论:", conclusions)


# 反向推理
def backward():
    # 目标条件
    facts = set()
    # 选择动物特征
    while True:
        choice = select()
        if choice == "q":
            break
        facts.add(choice)
    # 推理
    used_rules = set()
    conclusions = set()
    while True:
        flag = False
        for rule in rules:
            if rules[rule] in facts and rule not in used_rules:
                print("使用规则:%s -> %s" % (rule, rules[rule]))
                for feature in rule:
                    facts.add(feature)
                    conclusions.add(feature)
                used_rules.add(rule)
                flag = True
        if not flag:
            break
    # 显示最终的事实
    print("推理过程中得到的事实:", facts)
    print("推理过程中得到的结论:", conclusions)


# 增加规则
def insert():
    # 显示现有规则
    print("现有规则:")
    print(rules)
    # 增加规则
    while True:
        print("请输入规则(例:“哺乳动物 有蹄”),输入q退出:")
        rule = input()
        if rule == "q":
            break
        rule = tuple(rule.split())
        if rule in rules:
            print("规则已存在!")
        else:
            print("请输入结论:")
            result = input()
            rules[rule] = result
            print("规则添加成功!")
            # 自动添加之前不存在的选项
            for choice in rule:
                if choice not in choices:
                    choices.append(choice)


# 删除规则
def remove():
    # 显示现有规则
    print("现有规则:")
    print(rules)
    # 删除规则
    while True:
        print("请输入要删除的规则(例:“哺乳动物 有蹄”),输入q退出:")
        rule = input()
        if rule == "q":
            break
        rule = tuple(rule.split())
        print(rule)
        if rule not in rules:
            print("规则不存在!")
        else:
            del rules[rule]
            print("规则删除成功!")

# 主函数
def main():
    while True:
        print("请选择推理方式:")
        print("1. 正向推理")
        print("2. 反向推理")
        print("3. 增加规则")
        print("4. 删除规则")
        print("5. 退出")
        choice = input("请输入编号:")
        if choice == "1":
            forward()
        elif choice == "2":
            backward()
        elif choice == "3":
            insert()
        elif choice == "4":
            remove()
        elif choice == "5":
            break
        else:
            print("输入错误,请重新输入!")


if __name__ == "__main__":
    main()
  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
人工智能课程上的实验 分别使用lisp语言和prolog语言实现了一个专家系统 并且有详细的实验报告 附带画的二级推理树 (1) 领域背景简介 为了更好地阐明专家系统的基本工作原理 ,我们用 PROLOG语言实现一个简单的动物识别专家系统。该系统可以识别老虎、金钱豹、斑马、长颈鹿、鸵鸟、企鹅、信天翁这 7 种动物。 (2) 求解问题的范围(如植物分类涉及哪些大类,哪些子类) 首先 ,将动物粗略地分为哺乳动物、鸟、肉食动物 3 大类 ,然后逐步缩小分类范围,再将动物分为老虎、金钱豹、斑马、长颈鹿、鸵鸟、企鹅、信天翁 在知识库中 ,并非简单地给每一种动物一条规则。首先 ,将动物粗略地分为哺乳动物、鸟、肉食动物 3 大类 , 然后逐步缩小分类范围 ,最后给出识别 7 种动物的规则。如图给出了识别长颈鹿和斑马的推理网络。 (1) 规则的前提和结论的表示方法 在本系统当中 ,知识库中的知识用产生式规则来表示。本系统能够识别 7 种动物 ,知识库中共有以下 15 条 规则。 R1 IF 该动物有毛发 THEN 该动物是哺乳动物 R2 IF 该动物有奶 THEN 该动物是哺乳动物 R3 IF 该动物有羽毛 THEN 该动物是鸟 R4 IF 该动物会飞 AND 会下蛋 THEN 该动物是鸟 (2) 规则的结论为中间结论时,规则的格式 R5 IF 该动物吃肉 THEN 该动物是肉食动物 R6 IF 该动物有犬齿 AND 有爪 AND 眼盯前方 THEN 该动物是肉食动物 R7 IF 该动物是哺乳动物 AND 有蹄 THEN 该动物是有蹄类动物 R8 IF 该动物是哺乳动物 AND 是嚼反刍动物 THEN 该动物是有蹄类动物 (3) 规则的结论为最终结论时,规则的格式 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 不会飞 THEN 该动物是鸵鸟 R14 IF 该动物是鸟 AND 会游泳 AND 不会飞 AND 有黑白二色 THEN 该动物是企鹅 R15 IF 该动物是鸟 AND 善飞 THEN 该动物是信天翁

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值