📄 expertsystem.cpp
字号:
// ExpertSystem.cpp : Defines the entry point for the console application.
//模拟一个专家系统,由外提供规则库,自行生成事实库(文件)和解释系统(输出);
//人机交互方式
#include "stdafx.h"
#include "Stack.h"
#include <string>
#include <cmath>
#include<iostream>
#include<iomanip>
#include<cstdlib>
#include<fstream>
#include<vector>
using namespace std;
double reason(char conclusion[],vector<string> &rules,
Stack<int> &rulenumber,Stack<char> &jielun,double gailv[],ofstream &fact,vector<string> &xuliehao,int &size);
double combination(double orarray[],int c);//求并集
double min(double andarr[],int size);//求交集
void charToDouble(vector<string> &rules,double gailv[]);//将读到的字符串转化为DOUBLE型
void interpretation(char outfile[]);//解释系统
void main()
{
int i;
int j;
int k,p;
int findnumber;//用于保存查找的位置
bool mark;
int goalnumber=0;
/////////////////读取规则库(前提是规则文件是正确的)////////////////////////
vector<string> rules;//引入容器类模板
vector<string> xuliehao;
Stack<int> rulenumber;//存放压入规则栈的规则号
Stack<char> jielun;//存放压入规则栈的结论
rulenumber.MakeEmpty();
jielun.MakeEmpty();
//////////////////////////////////////////////////////////////////
//打开文件读取
char outfile[20]="shishiku.txt";
char filename[20];
cout<<"请输入规则库文件名:";
cin>>filename;
ifstream ku(filename,ios::in);
if(!ku){
cerr<<"file can not open"<<endl;
exit(1);
}
string rule;//用于读取文件中的字符串
while(ku>>rule){
rules.push_back(rule);//将文件中的字符串压入容器类中
xuliehao.push_back(rule);
}
int size=rules.size();//规则类的长度
double *gailv=new double[size/2];//用于存放规则的概率
///////////////////////////////////////////////////////////////
//建立事实数据库
ofstream fact(outfile,ios::out);
if(!fact){
cerr<<"file can not open"<<endl;
exit(1);
}
fact<<setw(10)<<"事实"<<setw(20)<<"y/n值"<<setw(20)<<"规则号"<<setw(20)<<"可信度"<<endl;
/////////////////////////////////////////////////////////////////
//test
//for(i=0;i<rules.size();i++)
//cout<<rules[i]<<endl;//end
char* conclusion=new char[size/2];//存放结论的动态数组
char* ptr;//指针
bool in;//用于判断
int * number=new int [size/2];//用于判断最终目标即结论
int *finalGoalNumber=new int [size/2];//总目标对应的规则号
double *result=new double[size/2];
int jishu;
double finalResult;
int *pass=new int [size/2];
if(rules.empty()||(size%2!=0))
cout<<"规则库不完备"<<endl;
else{
for(i=0;i<size/2;i++)
number[i]=0;//初始化数组
for(i=0,j=0;i<size;i=i+2,j++){//将结论存入新的数组且精简规则数组
ptr=rules[i].begin();//字符串的起始指针
findnumber=rules[i].find("→");//用于查找结论在字符串里的位置
conclusion[j]=*(ptr+findnumber+2);//将结论存入数组里
rules[i].erase(findnumber);//将“→”和结论从数组中删去
findnumber=rules[i].find("∧");
while(findnumber!=string::npos){
rules[i].replace(findnumber,2,"");//将“∧”从数组中删去
findnumber=rules[i].find("∧");
}
findnumber=rules[i].find(":");
while(findnumber!=string::npos){
rules[i].replace(0,findnumber+1,"");//将规则序列号从数组中删去
findnumber=rules[i].find(":");
}
findnumber=rules[i+1].find("CF");
while(findnumber!=string::npos){
rules[i+1].replace(findnumber,2,"");//将CF从数组中删去
findnumber=rules[i+1].find("CF");
}
findnumber=rules[i+1].find("(");
while(findnumber!=string::npos){
rules[i+1].replace(findnumber,1,"");//将"("从数组中删去
findnumber=rules[i+1].find("(");
}
findnumber=rules[i+1].find(")");
rules[i+1].erase(findnumber);//将“)”从数组中删去
findnumber=xuliehao[i].find(":");
xuliehao[i].erase(findnumber);//将“:”后面的从数组中删去
}
/////test//////////
/*for(i=0;i<size/2;i++)
cout<<conclusion[i]<<endl;
for(i=0;i<rules.size();i++)
cout<<rules[i]<<endl;
for(i=0;i<size;i++)
cout<<xuliehao[i]<<endl;*/
//////end/////////
charToDouble(rules,gailv);
//test
//for(i=0;i<size/2;i++)
//cout<<gailv[i]<<endl;//end
//寻找结论
for(i=0;i<size/2;i++){
for(j=0;j<size;j=j+2){
if((j/2)==i)
continue;
else{
in=false;
ptr=rules[j].begin();
for(k=0;k<rules[j].length();k++){
if(conclusion[i]==(*(ptr+k))){
in=true;
break;
}
else
continue;
}
}
if(in)
break;
if(k==rules[j].length()){
++number[i];
continue;
}
}
}
//for(i=0;i<rules.size()/2;i++)
//cout<<number[i]<<endl;
string yconnect("");
string nconnect("");
jishu=0;
for(i=0;i<size/2;i++){
if(number[i]!=(size/2-1))
continue;
else{//找到某个结论,进行逆向推理
if((jishu==0)||(conclusion[i]==conclusion[finalGoalNumber[jishu-1]])){
mark=true;
goalnumber++;
finalGoalNumber[jishu]=i;
//test
//cout<<"finalGoalNumber:"<<finalGoalNumber[jishu]<<endl;
//end
jielun.Push(conclusion[finalGoalNumber[jishu]]);//把总目标G压入栈
rulenumber.Push(finalGoalNumber[jishu]*2);//将总目标对应的规则号0压入栈
result[jishu]=reason(conclusion,rules,rulenumber,jielun,gailv,fact,xuliehao,size);
if(result[jishu]>=0.2){
pass[jishu]=1;
//fact<<setprecision(2)<<right<<setw(8)<<conclusion[finalGoalNumber[jishu]]
//<<setw(20)<<'y'<<setw(20)<<xuliehao[finalGoalNumber[jishu]*2]<<setw(20)<<result<<endl;
//fact<<setprecision(2)<<right<<setw(8)<<jielun.Pop()
//<<setw(20)<<'y'<<setw(20)<<xuliehao[rulenumber.Pop()]<<setw(20)<<result<<endl;
}
else{
pass[jishu]=0;
//fact<<setprecision(2)<<right<<setw(8)<<conclusion[finalGoalNumber[jishu]]
// <<setw(20)<<'n'<<setw(20)<<xuliehao[finalGoalNumber[jishu]*2]<<setw(20)<<result<<endl;
//fact<<setprecision(2)<<right<<setw(8)<<jielun.Pop()
//<<setw(20)<<'n'<<setw(20)<<xuliehao[rulenumber.Pop()]<<setw(20)<<result<<endl;
}
jishu++;
}
else{
mark=false;
break;
}
}
}
if(mark==true&&goalnumber>0){
for(p=0;p<jishu;p++){
if(pass[p]==1)
yconnect+=xuliehao[finalGoalNumber[p]];
else
continue;
}
for(p=0;p<jishu;p++)
nconnect+=xuliehao[finalGoalNumber[p]];
finalResult=combination(result,jishu);
if(finalResult>=0.2){
fact<<setprecision(2)<<right<<setw(8)<<jielun.Pop()<<setw(20)<<'y'
<<setw(20)<<yconnect<<setw(20)<<finalResult<<endl;
}
else{
//nodecertainty=0;
fact<<setprecision(2)<<right<<setw(8)<<jielun.Pop()<<setw(20)<<'n'
<<setw(20)<<nconnect<<setw(20)<<finalResult<<endl;
}
}
}
//解释
if(mark==true&&goalnumber>0)
interpretation(outfile);//
else if(mark==false)
cout<<"无法处理多目标的推理"<<endl;
else if(goalnumber==0)
cout<<"无法处理无目标的推理"<<endl;
else
cout<<"无法处理异常情况的推理"<<endl;
delete []gailv;
delete []conclusion;
delete []number;
delete []pass;
delete []finalGoalNumber;
delete []result;
}
double reason(char conclusion[],vector<string> &rules,Stack<int> &rulenumber,
Stack<char> &jielun,double gailv[],ofstream &fact,vector<string> &xuliehao,int &size)
{
int i,j,k;
int count;
char *ptr;
//for(i=0;i<rules.size();i++)
//cout<<rules[i]<<endl;
char reply;
//double leafcertainty;
double nodecertainty;//规则树的结点(不含叶结点)的不确定度
cout<<endl;
int number=rulenumber.GetTop();//结论的规则号
//cout<<"number:"<<number<<endl;
double arrsize=rules[number].length();
//cout<<rules[number]<<endl;
//cout<<"arrsize:"<<arrsize<<endl;
//cout<<endl;
double *andarr=new double [arrsize];//存放与的几个字符的概率
for(i=0,ptr=rules[number].begin();i<arrsize;i++,ptr++){//and
count=0;
//cout<<"*ptr:"<<(*ptr)<<endl;
jielun.Push(*ptr);//将结论对应的前提之一压入栈
for(j=0;j<size;j++){//or
if(conclusion[j]==(*ptr)){
count++;
//cout<<"count:"<<count<<endl;
//cout<<"j:"<<j<<endl;
rulenumber.Push(j*2);
}
else
continue;
}
double *orarr=new double[count];//OR的不确定度数组
int *rulearr=new int[count];//组成OR的规则号数组
int *pass=new int[count];
if(count==0){
cout<<"请输入"<<(*ptr)<<"的y/n值:";
cin>>reply;
cout<<"请输入"<<(*ptr)<<"的可信度:";
cin>>nodecertainty;
cout<<endl;
fact<<setprecision(2)<<right<<setw(8)<<jielun.Pop()<<setw(20)<<reply
<<setw(20)<<'0'<<setw(20)<<nodecertainty<<endl;
}
else if(count==1){
nodecertainty=reason(conclusion,rules,rulenumber,jielun,gailv,fact,xuliehao,size);
if(nodecertainty>=0.2){
fact<<setprecision(2)<<right<<setw(8)<<jielun.Pop()<<setw(20)<<'y'
<<setw(20)<<xuliehao[rulenumber.Pop()]<<setw(20)<<nodecertainty<<endl;
}
else{
//nodecertainty=0;
fact<<setprecision(2)<<right<<setw(8)<<jielun.Pop()<<setw(20)<<'n'
<<setw(20)<<xuliehao[rulenumber.Pop()]<<setw(20)<<nodecertainty<<endl;
}
}
else{
for(k=0;k<count;k++){
orarr[k]=reason(conclusion,rules,rulenumber,jielun,gailv,fact,xuliehao,size);
rulearr[k]=rulenumber.Pop();
if(orarr[k]<0.2)
pass[k]=0;
else
pass[k]=1;
}
string connect("");
nodecertainty=combination(orarr,count);
if(nodecertainty>=0.2){
for(k=0;k<count;k++){
if(pass[k]==1)
connect+=xuliehao[rulearr[k]];
else
continue;
}
fact<<setprecision(2)<<right<<setw(8)<<jielun.Pop()<<setw(20)<<'y'
<<setw(20)<<connect<<setw(20)<<nodecertainty<<endl;
}
else{
for(k=0;k<count;k++)
connect+=xuliehao[rulearr[k]];
//nodecertainty=0;
fact<<setprecision(2)<<right<<setw(8)<<jielun.Pop()<<setw(20)<<'n'
<<setw(20)<<connect<<setw(20)<<nodecertainty<<endl;
}
}
andarr[i]=nodecertainty;
}
return min(andarr,arrsize)*gailv[number/2];
/*delete []andarr;
delete []orarr;
delete []rulearr;
delete []pass;*/
}
double min(double andarr[],int size)
{
int i;
double m=andarr[0];
for(i=1;i<size;i++){
if(andarr[i]<m)
m=andarr[i];
}
return m;
}
double combination(double orarray[],int c)
{
int i;
double com=orarray[0];
for(i=1;i<c;i++)
com=com+orarray[i]-com*orarray[i];
return com;
}
void charToDouble(vector<string> &rules,double gailv[])
{
int i,j,k;
double a;
char *ptr;
for(j=1,k=0;j<rules.size();j=j+2,k++){
a=0.0;
for(i=0,ptr=rules[j].begin();i<rules[j].length();i++,ptr++){
if(i==0){
if(*ptr=='1')
a=static_cast<double>(*ptr);
}
else{
if((*ptr)=='.')
continue;
else
a+=(static_cast<int>(*ptr)-48)*pow(10,-(i-1));
}
}
gailv[k]=a;
}
}
void interpretation(char outfile[])
{
string headline;
char shishi;
char answer;
string guizehao;
double kexindu;
cout<<"路径解释:"<<endl;
ifstream interpret(outfile,ios::in);
if(!interpret){
cerr<<"file can not open"<<endl;
exit(1);
}
getline(interpret,headline);
while(interpret>>shishi>>answer>>guizehao>>kexindu){
cout<<endl;
if(answer=='y'){
if(guizehao=="0")
cout<<setw(5)<<right<<shishi<<"成立的可信度为"<<kexindu<<","<<"用户回答的事实"<<endl;
else
cout<<setw(5)<<right<<shishi<<"成立的可信度为"<<kexindu<<","<<"由规则"<<guizehao<<"推出"<<endl;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -