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

实验简介

本次实验题目是《智能系统》课程实验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
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值