产生式系统的设计及代码实现(植物识别系统)

产生式系统的设计及代码实现(植物识别系统)一 研究背景和目的 1 研究背景 1 产生式概念产生式系统简称产生式 它是指形如 gt 或 IFTHEN 或其等价形式的一条规则 其中箭头左边称为产生式的左部或前件 箭头右边称为产生式的右部或后件 如果前件和后见分别代表需要注视的一组条件及其成立时需要采取的行动 那么称为条件 行动型产生式 如果前件和后见分别代表前提及其相应的结论 那么称为前提 结论型产生式 2 产生式特点产生式是系统的

一、研究背景和目的

1.研究背景

2.研究目的

本次研究的目的为熟悉产生式构成的三个部分:综合数据库、规则库、策略控制,通过实际操作,完成一个简单的产生式系统的设计,从设计数据库、规则库、处理规则、运用算法实现推理几个过程,完成对产生式系统的认识加深与运用。并在研究中锻炼自己自主学习、思考问题的习惯,去分析、解决算法逻辑、功能实现等方面的问题,培养自己的研究能力。

二、系统总体设计

1.系统功能

实现一个植物识别系统的创建,数据库部分包括植物特征,规则库内容,实现根据输入特征判断库中是否存在该植物,并输出查找结果。

2.设计原理:

3.设计步骤

三、详细设计

1.系统实现方法——双向推理

2.创建植物数据库

3.设计算法

4.屏幕显示设置

#include<iostream> #include<iomanip> #include<string> #include<stdlib.h> #include<algorithm> #include<vector> using namespace std; //记录数据库内植物名 string plant[] = { 
    "玫瑰", "荷花", "仙人球", "水棉", "苹果树", "油菜", "海带", "松树" }; //记录数据库植物特征 string feature[] = { 
    "有刺", "水生", "喜阳", "药用", "木本", "可食用", "有白色粉末", "叶片针状", "结果实", "黄色花",//区别个体的特征 //0 1 2 3 4 5 6 7 8 9 "种子有果皮", "种子无果皮", "无茎叶", "无根", "有托叶", "吸引菜粉蝶", "十字形花冠", "缺水环境",//区别种类的特征 // 10 11 12 13 14 15 16 17 "被子植物", "裸子植物", "藻类植物", "蔷薇科", "十字花科", "仙人掌科", //种类 // 18 19 20 21 22 23  "玫瑰", "荷花", "仙人球", "水棉", "苹果树", "油菜", "海带", "松树" };//个体 //24 25 26 27 28 29 30 31 //存放规则的结构体  typedef struct { 
    int relation[7]; //关系  int name; //推理结果  }Rule;// 存放可能的植物  typedef struct { 
    int plant; // name  double confidence; //置信度 = 满足的特性数 / 所含特征数; int site; // 在rule中的位置 int num; // 满足的特征数  int size; // 此animal的所含总特征数  }Result; vector<Result> result; //规则库 //输入规则时最后输入-1则代表规则结束  Rule rule[15] = { 
    { 
    { 
    10, -1 }, 18 }, // R1:种子有果皮 -> 被子植物 { 
    { 
    11, -1 }, 19 }, // R2:种子无果皮 -> 裸子植物 { 
    { 
    12, 13, -1 }, 20 }, // R3:无茎叶 & 无根 -> 藻类植物 { 
    { 
    18, 14, -1 }, 21 }, // R4:被子植物 & 有托叶 -> 蔷薇科 { 
    { 
    18, 15, -1 }, 22 }, // R5:被子植物 & 吸引菜粉蝶 -> 十字花科 { 
    { 
    18, 16, -1 }, 22 }, // R6:被子植物 & 十字形花冠 -> 十字花科 { 
    { 
    18, 17, -1 }, 23 }, // R7:被子植物 & 缺水环境 -> 仙人掌科 { 
    { 
    18, 21, 0, -1 }, 24 }, // R8:被子植物 & 蔷薇科 & 有刺 -> 玫瑰 { 
    { 
    18, 1, 5, 8, -1 }, 25 }, // R9:被子植物 & 水生 & 可食用 & 结果实 -> 荷花 { 
    { 
    18, 2, -1, 0}, 26 }, // R10:被子植物 & 仙人掌科 & 喜阳 & 有刺 -> 仙人球 { 
    { 
    20, 1, 3, -1 }, 27 }, // R11:藻类植物 & 水生 & 药用 -> 水棉 { 
    { 
    18, 21, 4, 5, 8, -1 }, 28 }, // R12:被子植物 & 蔷薇科 & 木本 & 可食用 & 结果实 -> 苹果 { 
    { 
    18, 22, 9, 8, 5, -1 }, 29 }, // R13:被子植物 & 十字花科 & 黄色花 & 可食用 & 结果实 -> 油菜 { 
    { 
    20, 1, 5, 6, -1 }, 30 }, //R14:藻类植物 & 水生 & 可食用 & 有白色粉末 -> 海带 { 
    { 
    19, 4, 7, 8, -1 }, 31 } //R15:裸子植物 & 木本 & 叶片针状 & 结果实 -> 松树 }; int flag[23] = { 
    0 }; //标记各个特征是否选择 int IsPlant(int a); int change_speices(); //将可以推理出植物类的规则进行  int fnum(); //获取flag标记的数目  int z_inference(); //正向推理  int category(); //输出植物类别  void cal_confi(); //计算置信度  void r_inference(); //反向推理  void input(); //输入  void menu(); //菜单  //判断置信度大小 bool Compare(const Result& a, const Result& b) { 
    return a.confidence > b.confidence; } //排序并返回排序结果 void Rsort(vector<Result>& r) { 
    //调用数组容器的排序函数 sort(r.begin(), r.end(), Compare); return; } //选择特征菜单  void menu() { 
    //输出知识库中特征数组除植物名的成员,每输出4个换行 for (int i = 0; i < sizeof(feature) / sizeof(feature[0]) - sizeof(plant) / sizeof(plant[0]); i++) { 
    if (i % 4 == 0 && i != 0) { 
    cout << endl; } cout << setiosflags(ios::left) << setw(2) << i << "."; cout << setiosflags(ios::left) << setw(15) << feature[i]; } memset(flag, 0, sizeof(flag));//初始化标记数组为0 } //特征输入值选择数字  void input() { 
    for (int i = 0; i < sizeof(feature) / sizeof(feature[0]) - sizeof(plant) / sizeof(plant[0]); i++) { 
    flag[i] = 0; } int key = 0; cout << endl << "输入所选植物特征:"; while (key != -1)//当输入-1时停止特征输入 { 
    cin >> key; if (key >= 0 && key <= 23) { 
    flag[key] = 1; } else if (key != -1) { 
    cout << "输入错误,请输入一个特征:" << endl; cin.clear(); //清除流错误错误标记 cin.sync(); //清空输入缓冲区 cout << "请继续输入:"; } } } //是某植物而不是某种物种  int IsPlant(int a) { 
    if (a >= sizeof(feature) / sizeof(feature[0]) - sizeof(plant) / sizeof(plant[0]) && a <= sizeof(feature) / sizeof(feature[0])) { 
    return 1; } return 0; } //判断是否某一物种类  int IsPlant_speices(int a) { 
    if (a >= 18 && a <= 23) { 
    return 1; } return 0; } //返回flag数组中标记的总数  int fnum() { 
    int fum = 0; for (int i = 0; i < 24; i++) if (flag[i] == 1) { 
    fum++; } return fum; } //输出打印物种类别 int category() { 
    bool k; int count = 0; for (int i = 18; i < 24; i++) { 
    k = false; if (flag[i] == 1) { 
    k = true; count++; if (count == 1) { 
    cout << "无法识别植物! 所属类为:"; } cout << setiosflags(ios::left) << setw(10) << feature[i]; } } cout << endl; if (!k) { 
    cout << "系统无该植物" << endl; } return 1; } //改变特征值,变化flag,推理是否有物种种类,并将用到的事实清空,改flag为0 int change_speices() { 
    int i, j, key; bool t; int temp[23] = { 
    0 }; //临时存储,方便修改 int f[23] = { 
    0 }; // 标记使用过的flag  for (i = 0; i < 7; i++) { 
    //前7个规则 t = true; j = 0; key = rule[i].relation[j]; while (key != -1)//遍历该条关系 { 
    if (flag[key] == 1) { 
    temp[key] = 1; } else { 
    memset(temp, 0, sizeof(temp)); t = false; break; } j++; key = rule[i].relation[j]; } if (t) { 
    for (int k = 0; k <= 17; k++) { 
    if (temp[k] == 1) { 
    f[k] = 1; } } flag[rule[i].name] = 1; } memset(temp, 0, sizeof(temp)); } //删除推理过的事实,保留结果  for (i = 0; i <= 17; i++) { 
    if (f[i] == 1) { 
    flag[i] = 0; } } return 1; } //重新计算置信度  void cal_confi() { 
    for (int i = 0; i < result.size(); i++) { 
    for (int j = 7; j < 15; j++) { 
    if (result[i].plant == rule[j].name) { 
    result[i].confidence = 1.0 * result[i].num / result[i].size; break; } } } } //双向推理,正向推理不下去,事实不够,采用逆向推理 int z_inference() { 
    int key, num; int i, j; int fum = fnum(); cout << endl; for (i = 7; i < 15; i++) { 
    //检查规则库 Result temp; j = 0; num = 0; key = rule[i].relation[j]; while (key != -1) { 
    if (flag[key] == 1) { 
    num++; } j++; key = rule[i].relation[j]; } //此时j保存则rule[i]所含有的特征数  if (num != 0 && fum <= j) { 
    //给定特征数小于等于的情况,即flag数组中标记位数目大于此植物的特征数则不放入result if (IsPlant(rule[i].name)) { 
    // 是具体的植物  temp.plant = rule[i].name; int size = j; //rule[i]所含有的特征数 temp.size = size; temp.confidence = 1.0 * num / size; temp.site = i; temp.num = num; result.push_back(temp); } } } if (!result.empty()) { 
    Rsort(result); //对置信度从高到低排序  } //正向推理后  if (result.empty()) { 
    //给定特征数无法用任何一规则推理,可能没有这种植物,可能是一种类别  category(); } else if (result.front().confidence == 1.0) { 
    //可能给的特征刚好推理出,可能特征还没用完 cout << "植物为:" << feature[result.front().plant] << endl; result.clear();//清空 return 1; } else//逆向推理,询问特征 { 
    r_inference(); } } //特征不足,进入反向推理  void r_inference() { 
    vector<Result>::iterator it = result.begin(); int enquire[23]; //用来标记询问过的特征数组(0代表没有此特征,1代表有,2代表不请楚、 不知道)  memset(enquire, -1, sizeof(enquire)); for (int i = 0; i< result.size();) { 
    //从置信度最高开始询问 bool in_i = true; // i ++ 的标记  int nu = result[i].size; for (int j = 0; j < nu; j++) { 
    //询问特征  if (flag[rule[result[i].site].relation[j]] == 0) { 
    int en = rule[result[i].site].relation[j]; char c; if (enquire[en] == -1) { 
    //此特征未被询问过,则输出询问语句,否则直接判断处理  cout << "是否有以下特征:" << feature[rule[result[i].site].relation[j]] << endl; cout << "Y(y) or N(n) or D(don't know) : "; cin >> c; while (c != 'Y' && c != 'y' && c != 'N' && c != 'n' && c != 'D' && c != 'd') { 
    cout << "输出选择:Y(y) N(n) D(d)!" << endl; cin >> c; } } if (enquire[en] == 1 || c == 'Y' || c == 'y') { 
    //有此特征 改变置信度 result[i].num++; enquire[en] = 1; } else if (enquire[en] == 0 || c == 'N' || c == 'n') { 
    // 没有此特征 直接去掉 enquire[en] = 0; result.erase(it + i); //erase删除后i不自增,就能删除最后的元素,迭代器指向删除之前元素后的第一个元素 in_i = false; //如果擦除了元素,则i不自增  if (result.empty())//result为空,输出类别后退出  { 
    category(); } break; } else if (enquire[en] == 2 || c == 'D' || c == 'd') { 
    enquire[en] = 2; // 不确定、不知道,则置信度不改变  } } } if (in_i) { 
    ++i; } } if (!result.empty()) { 
    // 改变置信度  cal_confi(); if (result.size() > 1) //重新排序 { 
    Rsort(result); } //判断询问后进行双向推理 if (result.front().confidence == 1.0) { 
    cout << "植物是:" << feature[result.front().plant] << endl; } else { 
    cout << "植物可能为(置信度从高到低):"; for (vector<Result>::iterator it = result.begin(); it != result.end(); ++it) { 
    cout << setiosflags(ios::left) << setw(10) << feature[(*it).plant] << " "; } cout << endl; } result.clear(); // 清空  } } int main() { 
    char q; cout << "是否进入系统:Y(y) N(n)"; cin >> q; while (q != 'N' && q != 'n') { 
    menu(); input(); change_speices(); z_inference(); cout << endl << "继续?(Y/N)" << endl; cin >> q; system("cls");//清屏进行新的操作 } return 0; } 

五、结果展示

1.当输入特征完全匹配系统规则时,正向推理,直接输出结果:(如下图所示)

2.当输入特征不完全匹配系统规则,缺少特征时,从置信度最高的开始进行逆向推理,获得新特征,以此更新置信度:(如下图所示)

3.当输入特征不完全匹配系统规则,缺少特征时,从置信度最高的开始进行逆向推理,若不更新特征,直至最后按照置信度高低输出可能的植物:(如下图所示)

4.当输入特征不完全匹配系统规则,缺少特征时,从置信度最高的开始进行逆向推理,获得新特征,若新特征与系统数据相矛盾,则输出无该植物:(如下图所示)

六、总结

1.系统完成情况分析

2.系统不足

本系统的规则库是静态的,不能很好的进行增删改操作,这使得在实际运用是不便于系统数据库的修改和维护,对于系统功能更方便地实现增加了一定难度。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/228442.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午7:00
下一篇 2026年3月16日 下午7:01


相关推荐

  • 利用Regsvr32绕过Applocker的限制策略

    利用Regsvr32绕过Applocker的限制策略

    2022年4月2日
    57
  • VOIP技术架构

    VOIP技术架构H 323 协议存在一些问题 不支持群播 只有有限的 MCU 其 IP 电话网络在接入端仍需经过当地 PSTN 电路交换网 之后定制了 MGCP 目的在于将 H 323 在功能上进行分解 划分成负责媒体处理的媒体网关 MG 掌控呼叫建立与控制的媒体网关控制器 MGC 两部分 VoIP 架构 4 元素 媒体网关 媒体网关控制器 语音服务器 信号网关器 在交换过程中进行相关控制 以决定通话建立与否 及相关增值

    2026年3月18日
    2
  • Python写的我的世界源码+现成

    文章目录不想阅读代码者跳过正派活于话少今天第一次讲Python不要问我为什么之前不讲,就不讲~(假装自己学过python但是不讲)瞧,标题是什么,敢多说吗(我也不敢多说啊)效果图:源码(903行)from__future__importdivisionimportsysimportmathimportrandomimporttimefromcollectionsimportdequefrompygletimportimagefrompyglet.g

    2022年4月14日
    163
  • @ApiModelProperty注解中的属性

    @ApiModelProperty注解中的属性https blog csdn net weixin article details

    2026年3月17日
    3
  • torch.nn.Conv1d及一维卷积详解[通俗易懂]

    近日在搞wavenet,期间遇到了一维卷积,在这里对一维卷积以及其pytorch中的API进行总结,方便下次使用之前对二维卷积是比较熟悉的,在初次接触一维卷积的时候,我以为是一个一维的卷积核在一条线上做卷积,但是这种理解是错的,一维卷积不代表卷积核只有一维,也不代表被卷积的feature也是一维。一维的意思是说卷积的方向是一维的。下边首先看一个简单的一维卷积的例子(batchsize是1,也只…

    2022年4月13日
    496
  • 创建UFT对象

    创建UFT对象小船UFT总结:VBS创建UFT对象: SetqtApp=CreateObject(“QuickTest.Application”)    ‘创建COM对象qtApp.Launch                                                                     ‘启动UFTqtApp.New

    2022年5月28日
    37

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号