当前位置:   article > 正文

广州大学人工智能原理-实验三-推理系统

广州大学人工智能原理-实验三-推理系统

广州大学学生实验报告

开课学院及实验室: 计算机科学与网络工程学院电子信息楼416   2023年12月21日

学院

计算机科学与网络工程学院

年级/专业/班

*****

姓名

****

学号

****

实验课程名称

人工智能原理实验

成绩

实验项目名称

推理系统

指导老师

****

实验三  推理系统

  • 实验目的

本实验课程是计算机、智能、物联网等专业学生的一门专业课程,通过实验,帮助学生更好地掌握人工智能相关概念、技术、原理、应用等;通过实验提高学生编写实验报告、总结实验结果的能力;使学生对智能程序、智能算法等有比较深入的认识。

  1. 掌握人工智能中涉及的相关概念、算法;
  2. 熟悉人工智能中的知识表示方法;
  3. 掌握问题表示、求解及编程实现;
  4. 理解谓词逻辑、子句消解的原理和应用;
  5. 理解谓词逻辑、子句消解、产生式系统的结构原理与实际应用;
  6. 掌握词逻辑、子句消解、产生式规则表示及规则库组建的实现方法;
  7. 熟悉和掌握产生式系统的运行机制,掌握基于规则推理的基本方法。

二、基本要求

  1. 实验前,复习《人工智能》课程中的有关内容。
  2. 准备好实验数据。
  3. 编程要独立完成,程序应加适当的注释。
  4. 完成实验报告。

三、实验软件

使用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要求有用户交互,如界面等输入要查询的初始事实、推理方法、推理中用到的规则和结论。

算法设计过程

规则集

正向推理过程

// 进行正向推理
    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;
                    }
                }
            }
        }

实验运行结果 :

实验选做

实验完整代码

  1. #include <iostream>
  2. #include <vector>
  3. #include <map>
  4. #include <set>
  5. #include <queue>
  6. #include <iomanip>
  7. #include <algorithm>
  8. #include <string>
  9. using namespace std;
  10. map<string, vector<string>> inDegree;
  11. map<string, vector<string>> outDegree;
  12. map<string, vector<vector<string>>> preCondition;
  13. set<string> st;
  14. map<string, int> getNum;
  15. map<int, string> getString;
  16. int maxWordLength = 0;
  17. /*
  18. * 初始化 : 入度, 出度, 前提条件(多个入度推导出下一步)
  19. */
  20. void init()
  21. {
  22.     vector<vector<string>> ver = {
  23.         {"有奶""哺乳动物"},
  24.         {"有毛发""哺乳动物"},
  25.         {"有羽毛""鸟"},
  26.         {"会飞""生蛋""鸟"},
  27.         {"哺乳动物""有爪""有犬齿""目盯前方""食肉动物"},
  28.         {"哺乳动物","吃肉","食肉动物"},
  29.         {"哺乳动物""有蹄""有蹄动物"},
  30.         {"有蹄动物""反刍食物""偶蹄动物"},
  31.         {"食肉动物""黄褐色""黑色条纹""老虎"},
  32.         {"食肉动物""黄褐色""黑色斑点","金钱豹"},
  33.         {"有蹄动物""长腿""长脖子""黄褐色""暗斑点""长颈鹿"},
  34.         {"有蹄动物""白色""黑色条纹""斑马"},
  35.         {"鸟""不会飞""长腿""长脖子""黑白色""驼鸟"},
  36.         {"鸟""不会飞""会游泳""黑白色""企鹅"},
  37.         {"鸟""善飞""不怕风浪""海燕"},
  38.         // 选做
  39.         {"有毛发""有奶""善跳跃""唇裂""兔子"},
  40.         {"有毛发""有奶""善捕鼠""脚有肉垫""猫"},
  41.         {"有毛发""有奶""鼻子上有角""褐色""皮糙肉后""皮糙肉厚""有蹄""犀牛"},
  42.         {"有毛发""有奶""黑眼圈""四肢短小""熊猫"},
  43.         {"鸟类""上嘴鹰钩""会模仿人说话""鹦鹉"},
  44.         {"鸟类""腿短""嘴扁平""善潜水游泳""鸭子"},
  45.         {"鸟类""上嘴鹰钩""有爪""吃肉""鹰"},
  46.         {"有羽毛""卵生""善游泳""嘴扁平""腿短""鸭子"},
  47.         {"有羽毛""卵生""善潜水游泳""白色或黑色""颈长""嘴大""腿长""颈部有肉只凸起""鹅"},
  48.         {"有羽毛""卵生""黑色""嘴大""鸦"},
  49.         {"有羽毛""卵生""有爪""吃肉""上嘴鹰钩""鹰"},
  50.         {"有羽毛""卵生""上嘴鹰钩""能模仿人说话""鹦鹉"},
  51.         {"卵生""生活在水中""生活在陆地""有皮肤呼吸""用肺呼吸""皮肤光滑""吃昆虫""会变色""青蛙"},
  52.         {"卵生""生活在水中""生活在陆地""有皮肤呼吸""用肺呼吸""吃昆虫""皮肤粗糙""四肢扁""背部黑色""蝾螈"},
  53.         {"卵生""生活在水中""生活在陆地""有皮肤呼吸""用肺呼吸""吃昆虫""皮肤粗糙""蟾蜍"},
  54.         {"用鳃呼吸""身体有鳍""生活在海洋中""身体扁平""两眼在头部同侧""比目鱼"},
  55.         {"用鳃呼吸""身体有鳍""生活在淡水中""身体扁平""头高尾部窄""鲫鱼"},
  56.         {"生活在陆地""用肺呼吸""胎生""身体有鳞或甲""身体圆而细长""吃小动物""蛇"},
  57.         {"生活在陆地""用肺呼吸""胎生""身体有鳞或甲""有四肢""尾巴细长易断""吃昆虫""壁虎"},
  58.         {"生活在陆地""用肺呼吸""胎生""身体有鳞或甲""身体圆而扁""有坚硬的壳""乌龟"},
  59.         {"生活在陆地""用肺呼吸""胎生""身体有鳞或甲""壳为黄褐色""皮肤光滑""有黑斑""玳瑁"},
  60.         {"生活在陆地""用肺呼吸""胎生""身体有鳞或甲""有四肢""善游泳""皮硬黑褐色""鳄鱼"}
  61.     };
  62.     int n = ver.size();
  63.     for (int i = 0; i < n; i++) {
  64.         int m = ver[i].size();
  65.         string ed = ver[i][m - 1];
  66.         vector<string> pre;
  67.         st.insert(ver[i][m - 1]);
  68.         maxWordLength = max(maxWordLength, (int)ver[i][m - 1].size());
  69.         for (int j = 0; j < m - 1; j++) {
  70.             st.insert(ver[i][j]);
  71.             inDegree[ed].push_back(ver[i][j]);
  72.             outDegree[ver[i][j]].push_back(ed);
  73.             pre.push_back(ver[i][j]);
  74.             maxWordLength = max(maxWordLength, (int)ver[i][j].size()); 
  75.         }
  76.         preCondition[ed].push_back(pre);
  77.     }
  78.     cout << "规则集合" << endl;
  79.     for (auto [s, matrix] : preCondition) {
  80.         for (auto ver : matrix) {
  81.             cout << s << ":";
  82.             for (auto s : ver) {
  83.                 cout << s << ' ';
  84.             }
  85.             cout << endl;
  86.         }
  87.     }
  88.     cout << endl;
  89.     cout << "入度" << endl;
  90.     // 输出inDegree
  91.     for (auto [s, ver] : inDegree) {
  92.         cout << s << ":";
  93.         for (auto s2 : ver) {
  94.             cout << s2 << ' ';
  95.         }
  96.         cout << endl;
  97.     }
  98.     cout << endl;
  99.     cout << "出度" << endl;
  100.     for (auto [s, ver] : inDegree) {
  101.         cout << s << ":";
  102.         for (auto s2 : ver) {
  103.             cout << s2 << ' ';
  104.         }
  105.         cout << endl;
  106.     }
  107.     // 单词与数字之间的映射
  108.     int idx = 1;
  109.     for (auto s : st) {
  110.         getNum[s] = idx;
  111.         getString[idx] = s;
  112.         idx++;
  113.     }
  114. }
  115. int main()
  116. {
  117.     // 初始化
  118.     init();
  119.     cout << endl; 
  120.     for (auto [idx, s] : getString) {
  121.         string idx2 = to_string(idx);
  122.         string s2 = idx2 + "." + s;
  123.         cout << std::left << std::setw(maxWordLength + 1) << s2<< "\t";
  124.         if (idx % 6 == 0) {
  125.             cout << endl;
  126.         }
  127.     }
  128.     cout << "\n输入初始事实, 输入0结束" << endl;
  129.     int idx;
  130.     cin >> idx;
  131.     queue<string> q;
  132.     while (idx != 0) {
  133.         q.push(getString[idx]);
  134.         cin >> idx;
  135.     }
  136.     map<string, vector<string>> currentInDegree; // 当前的入度信息, 如果入度达到一定数目, 那么可以推导出来
  137.     set<string> ans; // 出度为0的string 是答案
  138.     // 进行正向推理
  139.     while (q.size()) {
  140.         string s = q.front();
  141.         q.pop();
  142.         // 查找出度
  143.         vector<string> ver = outDegree[s];
  144.         for (auto next : ver) {
  145.             //入度的数目加1
  146.             currentInDegree[next].push_back(s);
  147.             vector<string> inDegree2 = currentInDegree[next];
  148.             for (auto ver : preCondition[next]) {
  149.                 if (inDegree2.size() >= ver.size()) {
  150.                     int equals = 0;
  151.                     // 入度可能重复出现了两次 要去重
  152.                     sort(inDegree2.begin(), inDegree2.end());
  153.                     for (int i = 0; i < (int)ver.size(); i++) {
  154.                         for (int j = 0; j < (int)inDegree2.size(); j++) {
  155.                             if (j > 0 && inDegree2[j] == inDegree2[j - 1]) continue// 跳过重复的
  156.                             if (ver[i] == inDegree2[j]) {
  157.                                 equals++;
  158.                             }
  159.                         }
  160.                     }
  161.                     // 入度足够, 能够推导出下一步
  162.                     if (equals >= (int)ver.size()) {
  163.                         q.push(next);
  164.                         // 出度为0, 是最终结果
  165.                         if (outDegree[next].size() == 0) {
  166.                             ans.insert(next);
  167.                         }
  168.                         break;
  169.                     }
  170.                 }
  171.             }
  172.         }
  173.     }
  174.     if (ans.size() == 0) {
  175.         cout << "无法推理出该动物" << endl;
  176.     }
  177.     else {
  178.         cout << "经过推理, 该动物可能是" << ":";
  179.         for (auto s : ans) {
  180.             cout << s << ", ";
  181.         }
  182.         cout << endl;
  183.     }
  184.     return 0;
  185. }
  186. // 91 92 57 18 0 =>兔子

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/354640?site
推荐阅读
相关标签
  

闽ICP备14008679号