Главная > Java > Простая экспертная система на Java

Простая экспертная система на Java

2 Февраль 2010 Vitaliy Juravskiy 234

В прошлой моем примере на тему экспертных систем, я рассказывал о созданной “ЭС поиска неисправностей ПК”. ЭС была выполнена с использованиям языка Prolog и C++. В данном примере я расскажу, как этаже ЭС с тем же набором правил в базе знаний, была реализована на языке Java.

База знаний представлена рекурсивной структурой данных типа бинарное дерево (binary tree). Для реализации более сложных правил можно использовать N-арное дерево, в узлах которых не только хранить правила, но и например какие-нибудь коэффициенты, или статистику. Приведу класс BinaryTree:

public class BinaryTree {
    private BinaryTree parent;
    private BinaryTree yes;
    private BinaryTree no;
    private String question;
    private String answer;

    private boolean isEnd;

    public BinaryTree(BinaryTree parent) {
        this.parent = parent;
    }

    public BinaryTree setQuestion(String question) {
        this.question = question;
        return this;
    }

    public String getQuestion() {
        return question;
    }

    public BinaryTree getParent() {
        return parent;
    }

    public BinaryTree setAnswer(String answer) {
        this.answer = answer;
        setEnd();
        return this;
    }

    public String getAnswer() {
        return answer;
    }

    public BinaryTree getYes() {
        if (isEnd) return null;
        if (yes == null) {
            yes = new BinaryTree(this);
        }
        return yes;
    }

    public BinaryTree getNo() {
        if (isEnd) return null;
        if (no == null) {
            no = new BinaryTree(this);
        }
        return no;
    }

    public boolean isEnd() {
        return isEnd;
    }

    private void setEnd() {
        this.isEnd = true;
    }

    public void setNo(BinaryTree no) {
        this.no = no;
    }

    public void setYes(BinaryTree yes) {
        this.yes = yes;
    }

}

Ядро экспертной системы, находиться в классе ExpertSysyem, в которой реализована рекурсивная функция обхода бинарного дерева:

public static void start(BinaryTree db)
                    throws IOException {
    if(db.isEnd()) {
        System.out.println(db.getAnswer());
        System.out.println("Объяснить почему ЭС пришла к такому выводу?");
        if(readBoolean()) {
            stack.clear();
            why(db);
            for (String el : stack) {
                System.out.println(el);
            }
        }
	return;
    }

    System.out.println(db.getQuestion());
    if(readBoolean()) start(db.getYes());
    else start(db.getNo());
}

Данный метод производит проход в глубину, и идет от корневого узла, до конечного листа. В узлах находатся вопросы, метод выводит вопрос и в зависимости от ответа пользователя производиться переход к следующему узлу, и так происходит до тех пор, пока не дойдет до листа, в котором хранится вывод. Также существует метод why (почему) это обратный рекрсивный метод, который идет от узла или листа, к корню дерева, и выводит на экран то, как ЭС, работала с пользователем. База знаний статическая, времени на реализацию денмаческой БД не было, но при желании вы можете добавить класс отвчеающий за загрузку/выгрузку ЭС, и добавление новых правил и выводов в ее структуру. База зананй представленна следующим образом:

BinaryTree db = new  BinaryTree(null);
db.setQuestion("Работает ПК?");
db.getYes().setAnswer("Вам не нужны услуги экспертной системы");
db.getNo().setQuestion("ПК включается?");
db.getNo().getNo().setQuestion("Свет есть?");
db.getNo().getNo().getYes().setAnswer("Поломался блок питания");
db.getNo().getNo().getNo().setAnswer("Включите свет");
db.getNo().getYes().setQuestion("Изображение есть на мониторе?");
db.getNo().getYes().getNo().setQuestion("Монитор подключен к сети?");
db.getNo().getYes().getNo().getNo().setAnswer("Подключите монитор");
db.getNo().getYes().getNo().getYes()
    .setQuestion("Индикатор горит на мониторе");
db.getNo().getYes().getNo().getYes().getNo()
    .setAnswer("Не работает монитор");
db.getNo().getYes().getNo().getYes().getYes()
    .setAnswer("Не работает видеокарта");
db.getNo().getYes().getYes().setQuestion("Писк есть?");
db.getNo().getYes().getYes().getYes()
    .setAnswer("Используйте руководство по пискам BIOS");
db.getNo().getYes().getYes().getNo().setQuestion("Загружаеться ОС?");
db.getNo().getYes().getYes().getNo().getNo()
    .setQuestion("Есть сообщения об ошибках?");
db.getNo().getYes().getYes().getNo().getNo().getYes()
    .setAnswer("Следуйте сообщениям об ошибках");
db.getNo().getYes().getYes().getNo().getNo().getNo()
    .setAnswer("Не знаю");
db.getNo().getYes().getYes().getNo().getYes()
    .setQuestion("При входе в ОС есть звук?");
db.getNo().getYes().getYes().getNo().getYes().getYes()
    .setQuestion("Система загрузилась без ошибок");
db.getNo().getYes().getYes().getNo().getYes().getYes().getYes()
    .setAnswer("Следуйте рекомендациям ОС");
db.getNo().getYes().getYes().getNo().getYes().getYes().getNo()
    .setAnswer("Приятной работы");
db.getNo().getYes().getYes().getNo().getYes().getNo()
    .setQuestion("У вас есть звуковая карта?");
db.getNo().getYes().getYes().getNo().getYes().getNo().getYes()
    .setAnswer("Не работает звуковая карта");
db.getNo().getYes().getYes().getNo().getYes().getNo()
    .setNo(db.getNo().getYes().getYes().getNo().getYes().getYes());

Прилогаю к примеру исходный код проекта (Eclipse проект), где вы можете рассмотреть все подробней, и собраный jar архив, который можно запустить при наличии jvm.
Исходный коды ЭС поиска неисправностей ПК (java) (96)
Скомпилированный пример ЭС (jar файл) (102)

Комментирование отключено.
blog comments powered by Disqus