基于规则系统的表示与推理的动物专家系统(使用正向推理和反向推理两种方法)

4 篇文章 0 订阅
4 篇文章 0 订阅

基于规则系统的表示与推理的动物专家系统(使用正向推理和反向推理两种方法)

解题思路

  • 正向推理:
    从用户提供的初始已知事实出发,从规则集中选出一条可适用的规则进行推理,并将推理到的结论加入事实库,重复上述过程,直到求得了所要的解或者规则集无法在扩展为止。算法描述如下:
    (1) DATA<-初始数据库
    (2) Util DATA 满足结束条件以前,do
    (3) Begin
    a) 在规则集中选择一条适用于DATA的规则
    b) 将该规则得到结果加入DATA中
    End
  • 反向推理:
    假设一个目标,通过规则找到推出该目标的证据,若所需的这些证据都在用户给事实库中,就说明假设成立,若无论如何都找不到支持假设的证据,说明原假设不成立,此时需要另做假设。算法描述如下:
    (1)做出假设G
    (2)检查G是否在事实数据库中,若在则假设成功返回该假设匹配成功。若不在,则进行下一步。
    (3)从规则库中寻找能推出该假设的规则。对找到的每一条规则的证据(即规则的左部)分别作为假设递归调用该函数。
    (4)上述调用中若有结果为匹配成功则说明该假设是可以成功推出的,返回匹配成功。
    其实是一个深度搜索的过程

    代码

Inference.java

package com.xiao;

import jdk.nashorn.internal.codegen.ObjectClassGenerator;

import java.awt.*;
import java.util.*;
import java.util.List;


public class Inference {
    //数据库
    String[] FACTS = new String[]{/*1*/"反刍动物",/*2*/"蹄类动物",/*3*/"哺乳动物",
            /*4*/"目视前方",/*5*/"有爪子",/*6*/"有犬齿",/*7*/"吃肉"
            ,/*8*/"下蛋",/* 9*/"会飞",/*10*/"有羽毛",
            /*1l*/"有蹄",/*12*/"肉食动物",/*13*/"鸟类",/*14*/"产奶",/*l5*/"有毛发", /*16*/"善飞",/* 17*/"黑白色",/*18*/"会游泳",
            /*19*/"长腿",/*20*/"长脖子",/*21*/"有黑色条纹",/*22*/"有暗斑点",/*23*/"黄褐色",/*24*/"信天翁",
            /*25*/"企鹅",/*26*/"鸵鸟",/*27*/"斑马",/*28 */"长颈鹿",/* 29 */"老虎",/*30*/"金钱豹"};

    public int[][] RULE_pre = {{15}, {14}, {10}, {9, 8}, {7}, {6, 5, 4}, {3, 2}, {3, 1},
            {23, 22, 12, 3}, {23, 21, 12, 3}, {22, 20, 19, 11},
            {21, 11}, {20, 19, 17, 13, -9}, {18, 17, 13, -9}, {16, 13},
    };

    public int[] RULE_after = {3, 3, 13, 13, 12, 12, 2, 2, 30, 29, 28, 27, 26, 25, 24};
    public HashSet<Integer> curFacts;
    public HashSet<Integer> use_rules;
    public HashSet<Integer> post_use_rules;
    private TextArea t1;
    private TextArea t2;
    private StringBuffer forPanel;
    private StringBuffer process;

    Inference(TextArea t1,TextArea t2) {
        this.t1 = t1;
        this.t2 = t2;
        forPanel = new StringBuffer();
        process = new StringBuffer();
        printFacts_Rules();
        //System.out.println("请输入特征数字以,隔开");
        forPanel.append("请输入特征数字以,隔开\n");
        show();
    }
    public void show(){
        t1.setText(forPanel.toString());
        t2.setText(process.toString());
    }
    public void in(String input){
        String[] sp = input.split(",");
        int[] in = new int[sp.length];
        for(int i = 0;i<in.length;i++)
            in[i] = Integer.parseInt(sp[i]);

        use_rules = new HashSet<>();
        post_use_rules = new HashSet<>();
        curFacts = new HashSet<>();
        for(int i:in){
            curFacts.add(i);
            if(i>0){forPanel.append(FACTS[i-1]+" ");}
            else{forPanel.append("不"+FACTS[Math.abs(i)-1]+" ");}
        }//System.out.print(FACTS[i-1]+" ");}
        forPanel.append("\n");//System.out.println();
        show();
    }
    void printFacts_Rules(){
        for(int i=0;i<FACTS.length;i++){
            if(i%10==0) forPanel.append("\n");//System.out.println();
            forPanel.append((i+1)+" "+FACTS[i]+"  ");//System.out.print(i+1+" "+FACTS[i]+"  ");
        }
        forPanel.append("\n");//System.out.println();

        for(int i=0;i<RULE_pre.length;i++){
            forPanel.append("rule"+(i+1)+": ");//System.out.print("rule"+(i+1)+": ");
            for(int j:RULE_pre[i]){
                if(j>0)
                    forPanel.append(FACTS[Math.abs(j)-1]+" ");//System.out.print(FACTS[Math.abs(j)-1]+" ");
                else
                    forPanel.append("不"+FACTS[Math.abs(j)-1]+" ");
            }
            forPanel.append("----->"+FACTS[RULE_after[i]-1]+"    ");//System.out.print("----->"+FACTS[RULE_after[i]-1]+"    ");
            if(i%3==0) forPanel.append("\n");//System.out.println();
        }
        forPanel.append("\n");//System.out.println();
    }
    private void printCurFacts(){
        process.append("当前事实库");//System.out.print("当前事实库");
        int j = 0;
        for(int i:curFacts){
            if(j%5==0) process.append("\n");//System.out.println();
            j++;
            if(i>0)
            process.append(FACTS[i-1]+ " ");//System.out.print(FACTS[i-1]+ " ");
            else process.append("不"+FACTS[Math.abs(i)-1]+ " ");
        }
        process.append("\n");//System.out.println();
    }

    private void printCurUseRules(){
        for(int i:use_rules){
            if(!post_use_rules.contains(i)){
                process.append("rule"+(i+1)+":");//System.out.print("rule"+(i+1)+":");
                for(int j:RULE_pre[i])
                    if(j>0)
                    process.append(FACTS[Math.abs(j)-1]+" ");//System.out.print(FACTS[Math.abs(j)-1]+" ");
                    else process.append("不"+FACTS[Math.abs(j)-1]+" ");
                process.append("----->"+FACTS[RULE_after[i]-1]+"    ");//System.out.print("----->"+FACTS[RULE_after[i]-1]+"    ");
                post_use_rules.add(i);
            }
        }
        process.append("\n");//System.out.println();
    }
    /**
     * 正向推理
     * */
    public void forword(){
        printCurFacts();
        HashSet<Integer> indexs;
        while (true){
            indexs = find(curFacts);
            printCurUseRules();
            int size = curFacts.size();
            for(int i:indexs)
                curFacts.add(i);

            if(curFacts.size() > size){
                printCurFacts();
                show();
            }
            if(curFacts.size() == size){ break;}
        }
        StringBuffer res = new StringBuffer();
        boolean flags = false;
        process.append("最终结果如下:\n");//System.out.println("最终结果如下:");
        for(int i=24;i<=30;i++){
            if(curFacts.contains(i)){ res.append(FACTS[i-1]+" "); flags=true;}
        }
        if(flags) process.append("推理成功,该可能动物为:"+res.toString()+"\n");
        else process.append("推理不成功\n");//System.out.println("推理不成功"); //System.out.println("推理成功,该可能动物为:"+res);
        show();
    }
    /**
     * 传入curFacts,返回可推出结论的下标集合
     * curFacts是否包含规则左侧的证据
     * */
    private HashSet<Integer> find(HashSet<Integer> input) {

        HashSet<Integer> res = new HashSet<>();

        HashSet<Integer> hashset = new HashSet<>();
        for(Object i:input.toArray()){
            hashset.add(Integer.parseInt(i.toString()));
        }

        for (int i = 0; i < RULE_pre.length; i++) {
            int j = 0;
            for(j = 0; j < RULE_pre[i].length; j++)
            {
                if(!hashset.contains(RULE_pre[i][j]))
                    break;
            }
            if(j == RULE_pre[i].length){ res.add(RULE_after[i]);use_rules.add(i);}
        }
        return res;
    }
    /**
     * 反向推理
     * */
    public void backword(){
        for(int i=24;i<=30;i++){
            if(dfs(i)){
                process.append("推理成功,该动物可能为:"+FACTS[i-1]+"\n");//System.out.println("推理成功,该动物可能为:"+FACTS[i-1]);
                break;
            }else{
                process.append("推理不成功,该动物不为:"+FACTS[i-1]+"\n");//System.out.println("推理不成功,该动物不为:"+FACTS[i-1]);
            }
        }
        show();
    }
    /**
     * 寻找num在规则右部出现的规则
     * */
    private List<Integer> InRULE_after(int num){
        List<Integer> res = new ArrayList<>();
        for(int i=0;i<RULE_after.length;i++){
            if(RULE_after[i] == num)  res.add(i);
        }
        return res;
    }
    /**
     * 深度遍历
     * */
    private boolean dfs(int num){
        String temp = num>0?"":"不";
        process.append("假设为"+temp+FACTS[Math.abs(num)-1]+"\n");

        if(curFacts.contains(num)) return true;
        else{
            List<Integer> indexs = InRULE_after(num);
            if(indexs.size()==0){ return false;}
            else {
                for(int i:indexs){
                    boolean flag = true;
                    for(int j:RULE_pre[i]){
                        String a = j>0?"":"不";
                        if(!dfs(j)){ flag = false; process.append(a+FACTS[Math.abs(j)-1]+ "假设失败\n");}
                        else process.append(a+FACTS[Math.abs(j)-1]+ "假设成功\n");
                    }
                    if(flag){return true;}
                }
                return false;
            }
        }
    }


}

Main.java

package com.xiao;


import javax.swing.*;
import java.awt.Dimension;
import java.awt.TextArea;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class Main extends JFrame {
    private JTextField textField;
    private Inference inference ;
    private TextArea textArea_1;
    private TextArea textArea;
    private JButton button;
    private JButton button_1;
    private boolean isNew = true;
    public Main() {
        setSize(new Dimension(931, 654));
        setResizable(false);
        getContentPane().setLayout(null);

        textArea = new TextArea();
        textArea.setEditable(false);
        textArea.setRows(50);
        textArea.setBounds(50, 29, 830, 204);
        getContentPane().add(textArea);

        textField = new JTextField();
        textField.setBounds(165, 256, 489, 21);
        getContentPane().add(textField);
        textField.setColumns(10);

        button = new JButton("\u6B63\u5411\u63A8\u7406");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(!isNew) inference = new Inference(textArea,textArea_1);
                String input = textField.getText().toString();
                if(input.equals("")) textArea_1.setText("请输入特征");
                else{ inference.in(input); inference.forword(); isNew=false;}
            }
        });
        button.setBounds(219, 287, 93, 23);
        getContentPane().add(button);

        button_1 = new JButton("\u9006\u5411\u63A8\u7406");
        button_1.setBounds(477, 287, 93, 23);
        button_1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(!isNew) inference = new Inference(textArea,textArea_1);
                String input = textField.getText().toString();
                if(input.equals("")) textArea_1.setText("请输入特征");
                else{ inference.in(input); inference.backword(); isNew=false;}
            }
        });
        getContentPane().add(button_1);

        textArea_1 = new TextArea();
        textArea_1.setRows(50);
        textArea_1.setEditable(false);
        textArea_1.setBounds(50, 334, 820, 280);
        getContentPane().add(textArea_1);
        setVisible(true);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        inference = new Inference(textArea,textArea_1);
    }

    public static void main(String[] args) {
        Main m = new Main();
    }
}


运行结果

输入特征4,5,6,14,22,23 点击正向推理
在这里插入图片描述
输入17,18,10,-9点击逆向推理
在这里插入图片描述
输入1,2,4,5,6
点击正向推理

在这里插入图片描述

点击逆向推理
在这里插入图片描述

  • 9
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值