人工智能之产生式系统

来源:互联网 发布:河北网络干部学院 编辑:程序博客网 时间:2024/06/04 18:24

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

规则: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<Condition> word = new ArrayList<Condition>();//存放所有的词汇,用下标来编号public static ArrayList<Sentence> sentenceList = new ArrayList<Sentence>();//存放句子private ArrayList<Condition> now = new ArrayList<Condition>();//存放用户输入的条件public static ArrayList<Integer> know = new ArrayList<Integer>();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 stubchar[] 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 stubString str = "";for(int m = j;m <= i;m ++){str = str+temp[m];}now.add(new Condition(str));}private void addKnow() {// TODO Auto-generated method stubfor(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 stubfor(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 stubint 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 stubfor(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<String> content = new ArrayList<String>();//存放读取到的所有数据//public ArrayList<String> word = new ArrayList<String>();//存放所有的词汇,用下标来编号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 stubfor(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 stubint 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 stubfor(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 stubfor(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 stubint 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 stubboolean 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 stubString str = "";for(int m = j;m <= i;m ++){str = str+temp[m];}return str;}}



原创粉丝点击