赞
踩
广州大学学生实验报告
开课学院及实验室: 计算机科学与网络工程学院电子信息楼416 2023年12月21日
学院 | 计算机科学与网络工程学院 | 年级/专业/班 | ***** | 姓名 | **** | 学号 | **** |
实验课程名称 | 人工智能原理实验 | 成绩 | |||||
实验项目名称 | 推理系统 | 指导老师 | **** |
实验三 推理系统
本实验课程是计算机、智能、物联网等专业学生的一门专业课程,通过实验,帮助学生更好地掌握人工智能相关概念、技术、原理、应用等;通过实验提高学生编写实验报告、总结实验结果的能力;使学生对智能程序、智能算法等有比较深入的认识。
二、基本要求
三、实验软件
使用C或C++(Visual studio或其它开发环境)(不限制语言使用)。
四、实验内容:
【产生式推理系统的算法原理】
以动物识别系统为例,用选定的编程语言建造规则库和综合数据库,开发能进行正确的正向推理,即从已知事实出发,通过规则库求得结论。推理过程是:
1 动物分类规则集
(1)若某动物有奶,则它是哺乳动物。
(2)若某动物有毛发,则它是哺乳动物。
(3)若某动物有羽毛,则它是鸟。
(4)若某动物会飞且生蛋,则它是鸟。
(5)若某动物是哺乳动物且有爪且有犬齿且目盯前方,则它是食肉动物。
(6)若某动物是哺乳动物且吃肉,则它是食肉动物。
(7)若某动物是哺乳动物且有蹄,则它是有蹄动物。
(8)若某动物是有蹄动物且反刍食物,则它是偶蹄动物。
(9)若某动物是食肉动物且黄褐色且有黑色条纹,则它是老虎。
(10)若某动物是食肉动物且黄褐色且有黑色斑点,则它是金钱豹。
(11)若某动物是有蹄动物且长腿且长脖子且黄褐色且有暗斑点,则它是长颈鹿。
(12)若某动物是有蹄动物且白色且有黑色条纹,则它是斑马。
(13)若某动物是鸟且不会飞且长腿且长脖子且黑白色,则它是驼鸟。
(14)若某动物是鸟且不会飞且会游泳且黑白色,则它是企鹅。
(15)若某动物是鸟且善飞且不怕风浪,则它是海燕。
下面是该规则集所形成的(部分)推理网络:
图1 动物识别系统部分推理网络
2 问题描述
由上述动物识别规则组成规则库,推理机采用正向推理算法或反向推理算法,实现对动物的查询。
如给出初始事实:
F1:某动物有毛发
F2:吃肉
F3:黄褐色
F4:有黑色条纹
目标条件为:该动物是什么?
3 规则库扩充 (选做)
在上述规则集(Ⅰ)基础上增加以下规则集(Ⅱ):
(1)兔子:有毛发,有奶,善跳跃,唇裂;
(2)猫:有毛发,有奶,善捕鼠,脚有肉垫;
(3)犀牛:有毛发,有奶,鼻子上有角,褐色,皮糙肉后,皮糙肉厚,有蹄;
(4)熊猫:有毛发,有奶,黑眼圈,四肢短小;
(5)鹦鹉:鸟类,上嘴鹰钩,会模仿人说话;
(6)鸭子:鸟类,腿短,嘴扁平,善潜水游泳;
(7)鹰:鸟类,上嘴鹰钩,有爪,吃肉;
(8)鸭子:有羽毛,卵生,善游泳,嘴扁平,腿短;
(9)鹅:有羽毛,卵生,善潜水游泳,白色或黑色,颈长,嘴大,腿长,颈部有肉只凸起;
(10)鸦:有羽毛,卵生,黑色,嘴大;
(11)鹰:有羽毛,卵生,有爪,吃肉,上嘴鹰钩;
(12)鹦鹉:有羽毛,卵生,上嘴鹰钩,能模仿人说话;
(13)青蛙:卵生,生活在水中,生活在陆地,有皮肤呼吸,用肺呼吸,皮肤光滑,吃昆虫,会变色;
(14)蝾螈:卵生,生活在水中,生活在陆地,有皮肤呼吸,用肺呼吸,吃昆虫,皮肤粗糙,四肢扁,背部黑色;
(15)蟾蜍:卵生,生活在水中,生活在陆地,有皮肤呼吸,用肺呼吸,吃昆虫,皮肤粗糙;
(16)比目鱼:用鳃呼吸,身体有鳍,生活在海洋中,身体扁平,两眼在头部同侧;
(17)鲫鱼:用鳃呼吸,身体有鳍,生活在淡水中,身体扁平,头高尾部窄;
(18)蛇:生活在陆地,用肺呼吸,胎生,身体有鳞或甲,身体圆而细长,吃小动物;
(19)壁虎:生活在陆地,用肺呼吸,胎生,身体有鳞或甲,有四肢,尾巴细长易断,吃昆虫;
(20)乌龟:生活在陆地,用肺呼吸,胎生,身体有鳞或甲,身体圆而扁,有坚硬的壳;
(21)玳瑁:生活在陆地,用肺呼吸,胎生,身体有鳞或甲,壳为黄褐色,皮肤光滑,有黑斑;
(22)鳄鱼:生活在陆地,用肺呼吸,胎生,身体有鳞或甲,有四肢,善游泳,皮硬黑褐色。
要求在动物分类规则集(Ⅰ)的基础上添加上述22条知识,共构成29种动物的知识库系统,对原有动物分类系统进行扩充和修改。
五、学生实验报告要求
1 以产生式推理模式为基础,实现动物分类系统,推理方法采用正向推理或反向推理;
2 要求表示规则的语言必须能体现出规则前提和结论的对应关系,必须能体现出前提和结论中的逻辑关系;
3 要求能对规则库进行动态地增加、删除和修改操作(选做);
4要求有用户交互,如界面等输入要查询的初始事实、推理方法、推理中用到的规则和结论。
// 进行正向推理 |
- #include <iostream>
- #include <vector>
- #include <map>
- #include <set>
- #include <queue>
- #include <iomanip>
- #include <algorithm>
- #include <string>
- using namespace std;
- map<string, vector<string>> inDegree;
- map<string, vector<string>> outDegree;
- map<string, vector<vector<string>>> preCondition;
- set<string> st;
- map<string, int> getNum;
- map<int, string> getString;
- int maxWordLength = 0;
-
- /*
- * 初始化 : 入度, 出度, 前提条件(多个入度推导出下一步)
- */
- void init()
- {
-
- vector<vector<string>> ver = {
- {"有奶", "哺乳动物"},
- {"有毛发", "哺乳动物"},
- {"有羽毛", "鸟"},
- {"会飞", "生蛋", "鸟"},
- {"哺乳动物", "有爪", "有犬齿", "目盯前方", "食肉动物"},
- {"哺乳动物","吃肉","食肉动物"},
- {"哺乳动物", "有蹄", "有蹄动物"},
- {"有蹄动物", "反刍食物", "偶蹄动物"},
- {"食肉动物", "黄褐色", "黑色条纹", "老虎"},
- {"食肉动物", "黄褐色", "黑色斑点","金钱豹"},
- {"有蹄动物", "长腿", "长脖子", "黄褐色", "暗斑点", "长颈鹿"},
- {"有蹄动物", "白色", "黑色条纹", "斑马"},
- {"鸟", "不会飞", "长腿", "长脖子", "黑白色", "驼鸟"},
- {"鸟", "不会飞", "会游泳", "黑白色", "企鹅"},
- {"鸟", "善飞", "不怕风浪", "海燕"},
-
- // 选做
- {"有毛发", "有奶", "善跳跃", "唇裂", "兔子"},
- {"有毛发", "有奶", "善捕鼠", "脚有肉垫", "猫"},
- {"有毛发", "有奶", "鼻子上有角", "褐色", "皮糙肉后", "皮糙肉厚", "有蹄", "犀牛"},
- {"有毛发", "有奶", "黑眼圈", "四肢短小", "熊猫"},
- {"鸟类", "上嘴鹰钩", "会模仿人说话", "鹦鹉"},
- {"鸟类", "腿短", "嘴扁平", "善潜水游泳", "鸭子"},
- {"鸟类", "上嘴鹰钩", "有爪", "吃肉", "鹰"},
- {"有羽毛", "卵生", "善游泳", "嘴扁平", "腿短", "鸭子"},
- {"有羽毛", "卵生", "善潜水游泳", "白色或黑色", "颈长", "嘴大", "腿长", "颈部有肉只凸起", "鹅"},
- {"有羽毛", "卵生", "黑色", "嘴大", "鸦"},
- {"有羽毛", "卵生", "有爪", "吃肉", "上嘴鹰钩", "鹰"},
- {"有羽毛", "卵生", "上嘴鹰钩", "能模仿人说话", "鹦鹉"},
- {"卵生", "生活在水中", "生活在陆地", "有皮肤呼吸", "用肺呼吸", "皮肤光滑", "吃昆虫", "会变色", "青蛙"},
- {"卵生", "生活在水中", "生活在陆地", "有皮肤呼吸", "用肺呼吸", "吃昆虫", "皮肤粗糙", "四肢扁", "背部黑色", "蝾螈"},
- {"卵生", "生活在水中", "生活在陆地", "有皮肤呼吸", "用肺呼吸", "吃昆虫", "皮肤粗糙", "蟾蜍"},
- {"用鳃呼吸", "身体有鳍", "生活在海洋中", "身体扁平", "两眼在头部同侧", "比目鱼"},
- {"用鳃呼吸", "身体有鳍", "生活在淡水中", "身体扁平", "头高尾部窄", "鲫鱼"},
- {"生活在陆地", "用肺呼吸", "胎生", "身体有鳞或甲", "身体圆而细长", "吃小动物", "蛇"},
- {"生活在陆地", "用肺呼吸", "胎生", "身体有鳞或甲", "有四肢", "尾巴细长易断", "吃昆虫", "壁虎"},
- {"生活在陆地", "用肺呼吸", "胎生", "身体有鳞或甲", "身体圆而扁", "有坚硬的壳", "乌龟"},
- {"生活在陆地", "用肺呼吸", "胎生", "身体有鳞或甲", "壳为黄褐色", "皮肤光滑", "有黑斑", "玳瑁"},
- {"生活在陆地", "用肺呼吸", "胎生", "身体有鳞或甲", "有四肢", "善游泳", "皮硬黑褐色", "鳄鱼"}
-
- };
-
- int n = ver.size();
- for (int i = 0; i < n; i++) {
- int m = ver[i].size();
- string ed = ver[i][m - 1];
- vector<string> pre;
- st.insert(ver[i][m - 1]);
- maxWordLength = max(maxWordLength, (int)ver[i][m - 1].size());
- for (int j = 0; j < m - 1; j++) {
- st.insert(ver[i][j]);
- inDegree[ed].push_back(ver[i][j]);
- outDegree[ver[i][j]].push_back(ed);
- pre.push_back(ver[i][j]);
- maxWordLength = max(maxWordLength, (int)ver[i][j].size());
- }
-
- preCondition[ed].push_back(pre);
- }
-
- cout << "规则集合" << endl;
- for (auto [s, matrix] : preCondition) {
- for (auto ver : matrix) {
- cout << s << ":";
- for (auto s : ver) {
- cout << s << ' ';
- }
- cout << endl;
- }
- }
- cout << endl;
- cout << "入度" << endl;
- // 输出inDegree
- for (auto [s, ver] : inDegree) {
- cout << s << ":";
- for (auto s2 : ver) {
- cout << s2 << ' ';
- }
- cout << endl;
- }
- cout << endl;
- cout << "出度" << endl;
- for (auto [s, ver] : inDegree) {
- cout << s << ":";
- for (auto s2 : ver) {
- cout << s2 << ' ';
- }
- cout << endl;
- }
-
- // 单词与数字之间的映射
- int idx = 1;
- for (auto s : st) {
- getNum[s] = idx;
- getString[idx] = s;
- idx++;
- }
- }
- int main()
- {
- // 初始化
- init();
-
- cout << endl;
- for (auto [idx, s] : getString) {
- string idx2 = to_string(idx);
- string s2 = idx2 + "." + s;
- cout << std::left << std::setw(maxWordLength + 1) << s2<< "\t";
- if (idx % 6 == 0) {
- cout << endl;
- }
- }
- cout << "\n输入初始事实, 输入0结束" << endl;
- int idx;
- cin >> idx;
- queue<string> q;
- while (idx != 0) {
- q.push(getString[idx]);
- cin >> idx;
- }
-
- map<string, vector<string>> currentInDegree; // 当前的入度信息, 如果入度达到一定数目, 那么可以推导出来
- set<string> ans; // 出度为0的string 是答案
- // 进行正向推理
- while (q.size()) {
- string s = q.front();
- q.pop();
-
- // 查找出度
- vector<string> ver = outDegree[s];
- for (auto next : ver) {
- //入度的数目加1
- currentInDegree[next].push_back(s);
- vector<string> inDegree2 = currentInDegree[next];
- for (auto ver : preCondition[next]) {
- if (inDegree2.size() >= ver.size()) {
- int equals = 0;
-
- // 入度可能重复出现了两次 要去重
- sort(inDegree2.begin(), inDegree2.end());
- for (int i = 0; i < (int)ver.size(); i++) {
- for (int j = 0; j < (int)inDegree2.size(); j++) {
- if (j > 0 && inDegree2[j] == inDegree2[j - 1]) continue; // 跳过重复的
- if (ver[i] == inDegree2[j]) {
- equals++;
- }
- }
- }
- // 入度足够, 能够推导出下一步
- if (equals >= (int)ver.size()) {
- q.push(next);
- // 出度为0, 是最终结果
- if (outDegree[next].size() == 0) {
- ans.insert(next);
- }
- break;
- }
- }
- }
- }
-
- }
-
- if (ans.size() == 0) {
- cout << "无法推理出该动物" << endl;
- }
- else {
- cout << "经过推理, 该动物可能是" << ":";
- for (auto s : ans) {
- cout << s << ", ";
- }
- cout << endl;
- }
-
- return 0;
- }
-
-
- // 91 92 57 18 0 =>兔子
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。