Опубликован: 12.02.2014 | Уровень: для всех | Доступ: платный
Лекция 15:

Экспертная система. Логическая задача. Фейерверк

< Лекция 14 || Лекция 15: 123 || Лекция 16 >
Аннотация: Рассматриваются примеры решения задач на языке Visual Prolog. Создается небольшая экспертная система. Она применяется для определения мифологических животных. Приводится решение так называемой "головоломки Эйнштейна" (задачи, авторство которой приписывается Эйнштейну). Моделируется фейерверк.

Настоящая глава посвящена примерам решения задач на языке Visual Prolog. Создается небольшая экспертная система. Приводится пример ее использования для определения мифологических животных. Рассматривается так называемая "головоломка Эйнштейна" (задача, авторство которой приписывается Эйнштейну). Последний параграф посвящен моделированию фейерверка.

15.1. Экспертная система

Рассмотрим экспертную систему о мифологических животных. Система распознает следующих животных: грифон, дракон, единорог, сатир и сфинкс (для того чтобы она распознавала и других животных, достаточно внести сведения о них в базу данных). Они определяются по следующим признакам:

  • по наличию крыльев или рогов;
  • по форме крыльев, если они имеются;
  • по форме и количеству рогов, в случае их наличия;
  • по форме головы;
  • по форме туловища.

Программа вычисляет животное следующим образом. Она перебирает животных из базы данных (об этом пользователю не сообщается) и проверяет в диалоге с пользователем, имеются ли у них в наличии необходимые признаки. Если выяснилось, что признак имеется, то впоследствии повторно вопрос о нем не задается. Полученные сведения могут быть противоречивыми. В этом случае программа сообщает, что для ответа ей недостает сведений. Если оказалось, что все признаки некоторого животного имеются в наличии, и что признаки, которыми он не обладает, действительно отсутствуют, то делается заключение, что животное распознано. Пользователю задаются вопросы, на которые он отвечает "да", "нет" или "?". Например, "Верно ли что, форма крыльев — орлиные?". Если пользователь вводит знак вопроса "?", то программа объясняет, почему задается такой вопрос, например: "Идет проверка гипотезы, что чудовище — грифон <далее перечисляются признаки>. Известно, что чудовище — крылатое".

Все сведения о животных хранятся в двух видах фактов — rule/4 и cond/3. Отношение rule описывает виды животных, в нем указывается список номеров необходимых признаков. Отношение cond описывает сами признаки. Идея реализации экспертной системы взята из примера GENI системы Visual Prolog 5.2. Ниже приводится более простой вариант экспертной системы.

В директории Exe проекта следует создать файл monsters.txt и поместить в него приведенные ниже факты.

clauses
    rule(1, "чудовище", "грифон", [1, 6, 12, 18]).
    rule(2, "чудовище", "дракон", [1, 4, 15, 19]).
    rule(3, "чудовище", "единорог", [1, 5, 2, 7, 9, 11, 16]).
    rule(4, "чудовище", "сатир", [2, 8, 10, 14, 17]).
    rule(5, "чудовище", "сфинкс", [3, 13, 18]).

    cond(1, "чудовище", "крылатое").
    cond(2, "чудовище", "рогатое").
    cond(3, "чудовище", "без крыльев и рогов").
    cond(4, "форма крыльев", "летучей мыши").
    cond(5, "форма крыльев", "лебединые").
    cond(6, "форма крыльев", "орлиные").
    cond(7, "форма рогов", "прямые").
    cond(8, "форма рогов", "изогнутые").
    cond(9, "количество рогов", "1").
    cond(10, "количество рогов", "2").
    cond(11, "голова", "лошадиная").
    cond(12, "голова", "орлиная").
    cond(13, "голова", "человечья").
    cond(14, "голова", "обезьянья").
    cond(15, "голова", "крокодилья").
    cond(16, "туловище", "лошадиное").
    cond(17, "туловище", "козлиное").
    cond(18, "туловище", "львиное").
    cond(19, "туловище", "змеиное").
    
    topic("чудовище").
Пример 15.1. Файл monsters.txt

Реализация экспертной системы приведена в листинге 15.2.

    open core, console, string, list

class facts - db
    rule: (positive, string, string, positive*).
    cond: (positive, string, string).
    topic: (string).

class facts
    answer: (positive, integer).

class predicates
    expert: (string).
    ask: (positive, positive*) determ.
    ask: (integer, positive, positive*) determ.
    explanation: (positive).
    getAnswer: () -> integer.
    getAnswer: (char) -> integer determ.
    correct: (positive*) determ.
clauses
    expert(Topic):-
        rule(K, Topic, Goal, QList),
        ask(K, QList),
        correct(QList),
        !,
        writef("Заключение: % - %.", Topic, Goal).
    expert(Topic):-
        writef("Не хватает сведений, чтобы определить %.", Topic).

    ask(_, [N | _]):-
        answer(N, 0),     % если признак отсутствует,
        !,     % то это животное не подходит
        fail.
    ask(K, [N | QList]):-
        answer(N, 1),    % если признак присутствует,
        !,      % то следующий вопрос
        ask(K, QList).
    ask(K, [N | QList]):-
        cond(N, X, Y),     % задается вопрос о признаке
        writef("Верно ли, что % - %? (да/нет/?): > ", X, Y),
        A = getAnswer(),    % ответ от пользователя
        !,
        ask(A, K, [N | QList]).   % реакция на ответ
    ask(_, []).

    ask(2, K, QList):- !,    % если введен знак ?, то
        explanation(K),     % выдается объяснение,
        ask(K, QList).     % опрос продолжается
    ask(A, _, [N | _]):-
        assert(answer(N, A)),   % ответ запоминается в БД
        fail.
    ask(1, K, [_ | QList]):-     % если ответ положительный,
        ask(K, QList).     % то опрос продолжается

    explanation(K):-
        rule(K, Topic, Goal, QList),
        writef("Проверяется гипотеза, что % - %. Это так, если\n",
            Topic, Goal),
        F = {(I):- cond(I, X, Y), !, writef("\t% - %\n", X, Y); succeed},
        forAll(QList, F),
        L = [N || answer(N, 1), isMember(N, QList)],
        L <> [],
        !,
        write("Известно, что\n"),
        forAll(L, F).
    explanation(_).

    correct(QList):-
        answer(N, 1),      % если есть признак, 
        not(isMember(N, QList)),     % которого не должно быть,
        !,      % то животное не подходит
        fail;
        succeed().

    getAnswer() = R:-
        S = frontChar(toLowerCase(trim(readLine()))),
        R = getAnswer(S),
        !.
    getAnswer() = 0.

    getAnswer(S) = 1:-       % положительный ответ
        (S = 'д'; S = 'y'; S = 'l'),     % не зависит от раскладки
        !.
    getAnswer('?') = 2.

    run():-
        file::consult("monsters.txt", db),
        topic(Topic),
        expert(Topic),
        !,
        _ = readLine();
        succeed().
Пример 15.2. Экспертная система
< Лекция 14 || Лекция 15: 123 || Лекция 16 >
Жаныл Айкын
Жаныл Айкын
Rustam Inatov
Rustam Inatov

Доброго времени суток, подскажите пожалуйста, visual prolog examples, pie, vip7.5 - это все, где я могу скачать? (в смысле) может быть на сайте есть какой-то архив? Увы я не нашел его.

Подскажите, пожалуйста.

С уважением, Рустам.

Айдана Ахметова
Айдана Ахметова
Россия
Дмитрий Куянов
Дмитрий Куянов
Россия, Омск, ОмГТУ