赞
踩
本次实验题目是《智能系统》课程实验2-产生式系统推理。仅供学习和参考,希望能对你思路有所启发。实验算法仅是个人理解,不保证正确,请勿抄袭。
产生式系统推理
1 熟悉和掌握产生式系统的构成和运行机制;
2 掌握基于规则推理的基本方法和技术,掌握正确的正向推理和逆向推理方法;
3 熟悉在具体问题中如何实现正向推理和逆向推理的求解流程 。
1 以产生式推理模式为基础,实现小型动物分类系统,推理方法可以采用正向推理或反向推理;
2 要求表示规则的语言必须能体现出规则前提和结论的对应关系,必须能体现出前提和结论中的逻辑关系;
3 要求能对规则库进行动态地增加、删除和修改操作;
4 要求用界面显示要查询的初始事实、推理方法、推理中用到的规则和结论。
用Python字典数据类型存储规则库数据rules。
用Python列表数据类型存储动物特征选项。
算法中的facts,conclusions用Python集合数据类型。
初始化facts,conclusions为空集合;
选择特征,选择的特征同时加到facts集合和conclusions集合里;
循环:
遍历规则库rules每个规则rule:
如果rule前提是facts的子集且rule没被用过:
使用规则rule进行推导并输出
移除conclusions在rule前提里有的特征
将rule结论放入facts和conclusions
如果本次循环没有使用到任何规则,就跳出循环
输出事实集合facts
输出结论结合conclusions
初始化facts,conclusions为空集合;
选择目标特征,加到facts集合里;
循环:
遍历规则库rules每个规则rule:
如果rule结论属于facts且rule没被用过:
使用规则rule进行反向推导并输出
将rule前提放入facts和conclusions
如果本次循环没有使用到任何规则,就跳出循环
输出事实集合facts
输出结论结合conclusions
增加、删除、修改规则较简单,直接在rules集合增加、删除、修改即可。
初始选择操作界面如下。
因为“修改规则”可由“增加规则”和“删除规则”组合操作得到,所以略去了“修改规则”选项,以简化项目,更专注于算法的设计。
我们先测试“正向推理”,输入1,回车,进入正向推理界面,输入编号选择动物特征。
输入2 10 14 15(有毛发,吃肉,黄褐色,有黑色条纹)q,正向推理输出结果如下。显然,根据推理规则得出,输入的特征完全符合老虎的特征,输出的结论是老虎。
输入2 10 14 15 4(有毛发,吃肉,黄褐色,有黑色条纹,会飞)q,正向推理输出结果如下。输入的这几个特征,比老虎多了一个“会飞”,但规则数据里又没有完美符合这些特征的选项,于是推出了两个结论“老虎”和“会飞”,可以解释为拥有这个特征的动物是“会飞的老虎”。由于没有更好的结论,只能输出这样的组合结论。
输入2 10 14(有毛发,吃肉,黄褐色)q,正向推理输出结果如下。输入的这几个特征,比老虎少了一个“有黑色条纹”,我们无法断定它是老虎,推理得到两个结论“黄褐色”和“食肉动物”,可以解释为拥有这个特征的动物是“黄褐色的食肉动物”。由于没有更好的结论,只能输出这样的组合结论。
接下来我们尝试一下反向推理。
我们选择特征时界面和正向推理一样。我们输入86(鹰)试试。得到的结论有“鸟”、“吃肉”、“会飞”、“上嘴鹰钩”、“卵生”、“有羽毛”、“生蛋”、“有爪”。反向推理比较简单,输入其它的特征进行反向推理的情况也类似。
接下来我们来增加规则。输入“中分 背带裤 打篮球”,再输入结论“坤”。显示规则添加成功。
再看看现有规则,可以看到尾部增加了“(‘中分’, ‘背带裤’, ‘打篮球’): ‘坤’”这么一个规则,说明添加成功。
我们来尝试删除它。
显示删除成功,再看一次现有规则,可以看到结尾已经没有“坤”的判定规则。
实验结果显示,程序能够顺利地进行正向推理、反向推理、增加规则、删除规则,以及由增加删除操作可以组合出修改规则操作。
本算法的时间复杂度主要取决于两个循环:选择动物特征的循环和推理的循环。
选择动物特征的循环:这个循环的时间复杂度取决于用户的输入次数,我们可以将其表示为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()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。