write( Прав), write( ', что'),
write( Цель),
выд_трассу( Трасса).
конкретный( Терм) :-
нумпер( Терм, 0, 0). % Нет переменных в Терм'е
% конкретизация( Т1, Т2) означает, что Т2 - конкретизация Т1,
% т.е. терм Т1 - более общий, чем Т2, или той же степени
% общности, что и Т2
конкретизация( Терм, Терм1) :-
% Терм1 - частный случай Терм'а
копия( Терм1, Терм2),
% Копия Терм1 с новыми переменными
нумпер( Терм2, 0, _), !,
Терм = Терм2. % Успех, если Терм1 - частный случай Терм2
копия( Терм, НовТерм) :-
% Копия Терм' а с новыми переменными
asserta( copy( Терм) ),
retract( сору( НовТерм) ), !.
посл_индекс( 0). % Начальный индекс для "сказано"
след_индекс( Инд) :- % Следующий индекс для "сказано"
retract( посл_индекс( ПослИнд) ), !,
Инд is ПослИнд + 1,
assert( посл_индекс( Инд) ).
Рис. 14.11. Оболочка экспертной системы: Вопросы к пользователю и ответы на вопросы "почему".
Отношение, подобное нумпер
, часто входит в состав пролог-системы в качестве встроенной процедуры. Если это не так, то его можно реализовать программно следующим способом:
нумпер( Терм, N, Nплюс1) :-
var( Терм), !, % Переменная?
Терм = пер/N,
Nплюс1 is N + 1.
нумпер( Терм, N, М) :-
Терм =.. [Функтор | Аргументы], % Структура или атом
нумарг( Аргументы, N, M).
% Пронумеровать переменные в аргументах
нумарг( [], N, N) :- !.
нумарг( [X | Спис], N, M) :-
нумпер( X, N, N1),
нумарг( Спис, N1, М).
14.5.4. Процедура выдать
Процедура
выдать( Ответ)
приведенная на рис. 14.12, показывает пользователю окончательный результат консультационного сеанса и дает объяснения типа "как". Ответ
включает в себя как ответ на вопрос пользователя, так и дерево вывода, демонстрирующее выдать
представляет пользователю свое заключение. Затем, если пользователь пожелает узнать,
14.5.5. Драйвер верхнего уровня
И наконец, для того, чтобы иметь удобный доступ к оболочке из интерпретатора Пролога, нам необходима процедура, выполняющая функцию "драйвера". На рис. 14.13 показано, как могла бы выглядеть предназначенная для этой цели процедура эксперт
. Драйвер эксперт
производит запуск трех основных модулей оболочки (рис. 14.10–14.12) и координирует их работу. Например:
?- эксперт.
X это животное и голиаф это X. % Вопрос пользователя
...
% Выдача заключения консультационного сеанса и
% объяснения типа "как"
выдать( Ответ) :-
nl, заключение( Ответ),
nl, write( 'Хотите узнать, как?'),
принять( Ответ1),
( Ответ1 = да, !, отобр( Ответ);
true). % Показ решающего дерева
заключение( Ответ1 и Ответ2) :- !,
заключение( Ответ1), write( 'и'),
заключение( Ответ2).
заключение( Заключение было Найдено) :-
write( Заключение).
% "отобр" отображает полное решающее дерево
отобр( Решение) :-
nl, отобр( Решение, 0), !. % Отступ 0
отобр( Ответ1 и Ответ2, H) :- !, % Отступ H
отобр( Ответ1, H),