⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expertsystem.cpp

📁 用vc编写的专家系统的源代码,对初学者很有帮助
💻 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 + -