人工智能之产生式系统

这次的人工智能实验是产生式系统——动物分类

规则:R1:动物有毛→ 哺乳类

     R2:动物产奶 → 哺乳类

     R3:动物有羽毛 → 鸟类

     R4:动物会飞 ∧会下蛋 → 鸟类

     R5:哺乳类∧动物吃肉→ 食肉类

     R6:动物有犬齿 ∧有爪 ∧眼盯前方→肉食类

     R7:哺乳类 ∧有蹄 →蹄类动物

     R8:哺乳类 ∧反刍 → 蹄类

     R9:食肉类 ∧ 黄褐色 ∧ 有斑点→ 金钱豹

     R10:食肉类 ∧ 黄褐色 ∧ 有黑色条纹→虎

     R11:蹄类 ∧ 长脖 ∧ 长腿 ∧ 有斑点→ 长颈鹿

     R12:蹄类 ∧  有黑色条纹→ 斑马

     R13:鸟类 ∧长脖 ∧ 长腿 ∧ 不会飞 →鸵鸟

     R14:鸟类 ∧会游泳 ∧黑白二色 ∧ 不会飞 →企鹅

     R15:鸟类 ∧善飞 →信天翁


这是给定的规则库,通过这个规则库,以及用户输入的已知条件,来判断所描述的动物。

产生式系统的问题求解过程即为对解空间的搜索过程,也就是推理过程。按照搜索的方向可把产生式系统分为正向推理、逆向推理和双向推理

正向推理:从一组表示事实的谓词或命题出发,使用一组产生式规则,用以证明该谓词公式或命题是否成立。

逆向推理:从表示目标的谓词或命题出发,使用一组产生式规则证明事实谓词或命题成立,即首先提出一批假设目标,然后逐一验证这些假设。

双向推理:双向推理的推理策略是同时从目标向事实推理和从事实向目标推理,并在推理过程中的某个步骤,实现事实与目标的匹配。

这里,我们采用双向推理。通俗来说,双向推理就是先采用正向推理,如果已经是无法进行下去的情况,采用逆向推理,这个时候就需要询问用户是否能观察到某

些逆向推理出来的特征,然后讲这些特征加入到已知的条件特征中,再次进行正向推理,如此反复,知道得到最后的结果。需要注意的是,上面给定的规则库中的

名词可以分为三类:1.已知类,即用户能实际观察到的动物特征,这些只会出现在每个条件的前半段;2.概念类,即对动物进行的抽象的概念概括,也算是推理的

中间产物,会出现在条件的前端或后端;3.结果类,即最后推理出来的结果,真实的动物,只会出现在条件的后端。

有了这些概念之后,下面就是具体的推理过程了,我所采用的方式是读取规则库txt文件,将所有名词编号,然后用编号来组织成一条条件,遍历这些条件,根据

用户给出的名词,进行比较,同时计算每个条件的符合程度,推理出的名词加入到已知的名词队列中,重新遍历条件,更新符合度,如果没有100%符合的条件,则

寻找符合度最高的条件,进行逆向推理,询问可能的且没有在已知名词队列中的名词,进行判断,加入名词队列,重新遍历,更新符合度,直至找到属于结果类的

名词,即是结果。

代码中,只要是按照这种格式编写的规则的txt文件,都可以进行推理,实现了更便捷的应用。

下面是实现代码:

首先是主处理流程类,Project:

import java.util.ArrayList;
import java.util.Scanner;

/**
 * 主函数,处理
 * @author 41571
 *
 */

public class Project {
	
	public static ArrayList word = new ArrayList();	//存放所有的词汇,用下标来编号
	public static ArrayList sentenceList = new ArrayList();	//存放句子
	private ArrayList now = new ArrayList();	//存放用户输入的条件
	public static ArrayList know = new ArrayList();
	
	public static void main(String args[]){
		new Project();
	}
	
	public Project(){
		new ReadFile();
		System.out.println("请输入你已知的信息(空格间隔):");
		Scanner in = new Scanner(System.in);
		dealKnow(in.nextLine());
	/*	for(int i = 0;i < word.size();i ++){
			System.out.print(i+": ");
			word.get(i).show();
		}*/
		domain();
	}
	
	private void dealKnow(String nextLine) {	//处理输入的已知信息
		// TODO Auto-generated method stub
		char[] temp = nextLine.toCharArray();
		int a = temp.length -1 ;
		for(int i = temp.length - 1;i >= 0;i --){
			if(temp[i] == ' '){
				toString(temp,i+1,a);
				a = i -1;
			}
			if(i == 0){
				toString(temp,0,a);
			}
		}
		addKnow();
	}
	
	private void toString(char[] temp, int j, int i) {	//转化为字符串,开始位置,结束位置
		// TODO Auto-generated method stub
		String str = "";
		for(int m = j;m <= i;m ++){
			str = str+temp[m];
		}
		now.add(new Condition(str));
	}

	private void addKnow() {
		// TODO Auto-generated method stub
		for(int i = 0;i < now.size();i ++){
			know.add(find(now.get(i).getStr()));
		}
		//sortKnow();
	}
	
	/*private void sortKnow(){
		int a;
		for(int i = 0;i < know.size();i ++){
			for(int j = i+1;j < know.size();j ++){
				if(know.get(i) > know.get(j)){
					a = know.get(j);
					know.set(j, know.get(i));
					know.set(i, a);
				}
			}
		}
	}*/
	
	private int find(String str) {
		// TODO Auto-generated method stub
		for(int i = 0;i < Project.word.size();i ++){
			if(str.equals(Project.word.get(i).getStr())){
				return i;
			}
		}
		return -1;
	}

	public void domain(){		//主进程
		int a,z = 0;
		boolean out = true;
		while(out){
			a = 0;z = 0;
			for(int i = 0;i < sentenceList.size();i ++){
				if(sentenceList.get(i).isLook()){		//isLook==true时,表示这个还没有完全匹配
					sentenceList.get(i).compare();
					if(sentenceList.get(i).getMay() == 1.0){
						know.add(sentenceList.get(i).getResult());
						sentenceList.get(i).setLook(false);		//不再遍历
						sentenceList.get(i).setNeglect(false);	//忽视这个语句
						a = 1;z = 1;
						if(word.get(sentenceList.get(i).getResult()).isBaceOK()){
							System.out.println("你所描述的对象是"+word.get(sentenceList.get(i).getResult())
							.getStr()+"。");
							out = false;
							break;
						}
					}
				}
			}
			/*for(int i = 0;i < sentenceList.size();i ++){
				if(!sentenceList.get(i).isNeed()){
					sentenceList.get(i).setNeglect(false);
				}
			}*/
			if(a == 0){
				/*for(int i = 0;i < know.size();i ++){
					System.out.println(word.get(know.get(i)).getStr());
				}*/
				float max = 0;int tag = 0;	//找出最有可能的句子,询问用户
				for(int i = 0;i < sentenceList.size();i ++){
					if(sentenceList.get(i).isLook()&&sentenceList.get(i).isNeglect()&&
							sentenceList.get(i).isNeed()){
						//isLook == true时,说明当前语句没有完全匹配,isNeglect == true 说明这个句子在询问查询时不能忽略
						sentenceList.get(i).compare();
						if(sentenceList.get(i).getMay()>max){
							max = sentenceList.get(i).getMay();
							tag = i;
						}
					}
				}
				for(int k = 0;k < sentenceList.get(tag).getNotExist().length;k ++){
					if(word.get(sentenceList.get(tag).getNotExist()[k]).isFrontOK()){
						System.out.println("请问你是否发现该对象有 “"+word.get(sentenceList
								.get(tag).getNotExist()[k]).getStr()
								+"” 特征吗?(是的回答“y”,否或不知道回答“n”)");
						Scanner in = new Scanner(System.in);
						String input = in.nextLine();
						char[] inputs = input.toCharArray();
						z = 1;
						if(inputs[0] == 'y'){
							know.add(sentenceList.get(tag).getNotExist()[k]);
							break;
						}else{
							sentenceList.get(tag).setNeglect(false); 	//忽略这个句子
							break;
						}
					}
					else{
						sentenceList.get(tag).setNeglect(false);
					}
				}
			}
			
			if(z == 0){
				System.out.println("抱歉!系统暂时未包含该对象!");
				out = false;
			}
			/*if(a == 0){		//如果没有匹配的了,就要询问用户可能的情况了
				int m = 0;
				while(m == 0){
					for(int j = 0;j < sentenceList.size();j ++){
						if(sentenceList.get(j).isLook()){
							if(sentenceList.get(j).getNotExist()!=null)
							for(int k = 0;k < sentenceList.get(j).getNotExist().length;k ++){
								if(word.get(sentenceList.get(j).getNotExist()[k]).getBack()&&	//即出现在前端又
								word.get(sentenceList.get(j).getNotExist()[k]).getFront());		//出现在后端
								else{
									System.out.println("请问你是否发现该对象有 “"+word.get(sentenceList
											.get(j).getNotExist()[k]).getStr()
											+"” 特征吗?(是的回答“y”,否回答“n”)");
									Scanner in = new Scanner(System.in);
									String input = in.nextLine();
									char[] inputs = input.toCharArray();
									if(inputs[0] == 'y'){
										know.add(sentenceList.get(j).getNotExist()[k]);
										m = 1;
									}else{
										if(k+1==sentenceList.get(j).getNotExist().length){
											sentenceList.get(j).setNeglect(false);
											break;
										}
									}
								}
							}
						}
					}
				}
			}*/
		}
	}
}


接下来是条件句子类Sentence:


/**
 * 经过处理的一个句子
 * 包括条件
 * 还有结果
 * @author 41571
 *
 */

public class Sentence {
	private int[] begin;
	private int result;
	private int[] notExist;
	private float may;
	private boolean isLook = true;		//是否完全匹配
	private boolean neglect = true;	//询问用户时是否忽略
	public boolean isNeglect() {
		return neglect;
	}

	public void setNeglect(boolean neglect) {
		this.neglect = neglect;
	}

	public Sentence(){
		
	}
	
	public boolean isLook() {
		return isLook;
	}

	public void setLook(boolean isLook) {
		this.isLook = isLook;
	}

	public void compare(){
		int[] temp = new int[10];
		int a,m = 0;
		for(int i = 0;i < begin.length;i ++){
			a = 0;
			for(int j = 0;j < Project.know.size();j ++){
				if(Project.know.get(j) == begin[i]){
					a = 0;
					break;
				}
				a = 1;
			}
			if(a == 1){
				temp[m++] = begin[i];
			}
		}
		notExist = new int[m];
		for(int i = 0;i < m;i ++){
			notExist[i] = temp[i];
		}
		may = ((float)(begin.length-notExist.length))/begin.length;
	}
	
	public int[] getNotExist() {
		return notExist;
	}

	public void setNotExist(int[] notExist) {
		this.notExist = notExist;
	}

	public float getMay() {
		return may;
	}

	public int[] getBegin() {
		return begin;
	}
	public void setBegin(int[] begin) {
		this.begin = sort(begin);
	}
	private int[] sort(int[] begin) {
		// TODO Auto-generated method stub
		int a;
		for(int i = 0;i < begin.length;i ++){
			for(int j = i+1;j < begin.length;j ++){
				if(begin[i] > begin[j]){
					a = begin[j];
					begin[j] = begin[i];
					begin[i] = a;
				}
			}
		}
		return begin;
	}
	public int getResult() {
		return result;
	}
	public void setResult(int result) {
		this.result = result;
	}

	public boolean isNeed() {
		// TODO Auto-generated method stub
		for(int i = 0;i < Project.know.size();i ++){
			if(this.result == Project.know.get(i)){
				return false;
			}
		}
		return true;
	}
}

名词条件类Condition:

/**
 * 名词条件类,属性包括两个boolean型变量
 * @author 41571
 *
 */


public class Condition {
	private String str;
	private boolean front;	//是前端的
	private boolean back;	//是后端的
							//如果既是前端的,也是后端的,那就是中间属性
	public Condition(String str){
		this.str = str;
	}
	
	public String getStr(){
		return this.str;
	}
	
	public void setFront(boolean front){
		this.front = front;
	}
	
	public void setBack(boolean back){
		this.back = back;
	}
	
	public boolean getFront(){
		return this.front;
	}
	
	public void show(){
		System.out.println("字符串:"+this.str+" Front:"+this.front+" Back:"+this.back);
	}
	
	public boolean getBack(){
		return this.back;
	}
	
	public boolean isFrontOK(){		//是否是前端
		if(this.front&&!this.back){
			return true;
		}
		return false;
	}
	public boolean isBaceOK(){		//是否是后端
		if(!this.front&&this.back){
			return true;
		}
		return false;
	}
}

最后是读取文件及加工的类ReadFile:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Scanner;
import java.io.OutputStreamWriter;


/**
 * 读取文件类,将文件内容加工成
 * @author 41571
 *
 */

public class ReadFile {
	private final String filePath = "file\\knowledge.txt";
	private ArrayList content = new ArrayList();	//存放读取到的所有数据
	//public ArrayList word = new ArrayList();	//存放所有的词汇,用下标来编号
	
	public ReadFile(){
		getData();
	}

	private void getData() {
		// TODO Auto-generated method stub
		/*try{		//写入文件
			File file = new File(filePath);
			OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(file),"gbk");
			BufferedWriter writer = new BufferedWriter(write);
			writer.write(content);
			writer.close();
		}catch(Exception e){
			e.printStackTrace();
		}*/
		try{		//读取文件
			File file = new File(filePath);
			if(file.isFile()&&file.exists()){
				InputStreamReader read = new InputStreamReader(new FileInputStream(file),"gbk");
				BufferedReader reader = new BufferedReader(read);
				String line;
				while((line = reader.readLine())!=null){
					content.add(line);
				}
				read.close();
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		collectWord();	//收集所有关键词
		collectSentence();	//收集所有的句子
	}

	private void collectSentence() {
		// TODO Auto-generated method stub
		for(int i = 0;i < content.size();i ++){
			char[] temp = content.get(i).toCharArray();
			for(int j = (temp.length-1);j > 0;j --){
				if(temp[j] == '>'){
					String str = toString(temp,j+1,temp.length-1);
					Sentence sen = new Sentence();
					sen.setResult(find(str));
					setBegin(temp,j,sen);
				}
			}
		}
	}

	private void setBegin(char[] temp, int j, Sentence sen) {
		// TODO Auto-generated method stub
		int a = j-1;
		int[] test = new int[10];
		int total = 0;
		int[] begin;
		for(int i = j-1;i >= 0;i --){
			if(temp[i] == '^'){
				String str = toString(temp,i+1,a);	//数组,开始位置,结束位置
				test[total++] = find(str);
				a = i-1;
			}
			if(i == 0){
				String str = toString(temp,0,a);
				test[total++] = find(str);
			}
		}
		begin = new int[total];
		for(int i = 0;i < total;i ++){
			begin[i] = test[i];
		}
		sen.setBegin(begin);
		Project.sentenceList.add(sen);
	/*	for(int i = 0;i < sen.getBegin().length;i ++){
			System.out.print(sen.getBegin()[i]+" ");
		}
		System.out.println("result:"+sen.getResult());*/
	}

	private int find(String str) {
		// TODO Auto-generated method stub
		for(int i = 0;i < Project.word.size();i ++){
			if(str.equals(Project.word.get(i).getStr())){
				return i;
			}
		}
		return 0;
	}

	private void collectWord() {
		// TODO Auto-generated method stub
		for(int i = 0;i < content.size();i ++){
			char[] temp = content.get(i).toCharArray();
			for(int j = (temp.length-1);j > 0;j --){
				if(temp[j] == '>'){
					String str = toString(temp,j+1,temp.length-1);
					addStr(str,1,1);		//position = 1表示后条件,a = 1 表示在后面遇到
					precondition(temp,j);	//前提
				}
			}
		}
	}

	private void precondition(char[] temp, int j) {
		// TODO Auto-generated method stub
		int a = j-1;
		for(int i = j-1;i >= 0;i --){
			if(temp[i] == '^'){
				String str = toString(temp,i+1,a);	//数组,开始位置,结束位置
				addStr(str,-1,-1);	//position = -1表示前条件,a = -1 表示在前面遇到
				a = i-1;
			}
			if(i == 0){
				String str = toString(temp,0,a);
				addStr(str,-1,-1);
			}
		}
	}

	private void addStr(String str,int position,int a) {
		// TODO Auto-generated method stub
		boolean is = true;
		for(int i = 0;i < Project.word.size();i ++){
			if(str.equals(Project.word.get(i).getStr())){
				is = false;
				Project.word.get(i).setFront(true);
			}
		}
		if(is){
			Condition con = new Condition(str);
			if(position == 1){
				con.setBack(true);
			}else if(position == -1){
				con.setFront(true);
			}
			Project.word.add(con);
		}
	}

	private String toString(char[] temp, int j, int i) {
		// TODO Auto-generated method stub
		String str = "";
		for(int m = j;m <= i;m ++){
			str = str+temp[m];
		}
		return str;
	}
}



你可能感兴趣的:(ML&DL,人工智能,产生式系统,动物分类)