- •Глава 7 экспертные консультации
- •7.1. Системы экспертных консультаций
- •Два определения понятия "экспертная система"
- •Составные части системы экспертных консультаций
- •Интерфейс с пользователем
- •Стратегия решения задач
- •7.2, Запоминание пути вывода Процедура "вып"
- •Как работает процедура "вып"
- •Доказательство факта
- •Доказательство правила
- •Показ цепочки выводов
- •Ограничения программы "вып"
- •7.3. Видимый пролог
- •Переход от программы "вып" к программе "вид"
- •7.4. Интерпретатор, обнаруживающий циклы Процедуры, которые зацикливаются.
- •Робастный решатель задач
- •Программа "иоц" как предикат метаязыка
- •7.5. Заключение: стиль программирования на прологе Суть компьютерной программы
- •Два правила хорошего стиля программирования на Прологе. Декларативная граница
- •Примеры декларативной границы
- •Другие примеры
- •Пролог как эффективный вычислительный формализм
- •Библиографические заметки
- •Упражнения
Переход от программы "вып" к программе "вид"
Реализация программы "вид" очень похожа на реализацию программы "вып". Первым аргументом процедуры "вид0" (эквивалент процедуры "вып0") в отличие от "вып0" является количество пробелов, на которое следует сделать отступ. Однако главное различие между процедурами "вид" и "вып" заключается в форме третьего правила процедуры "вид0". Вместо простого вызова встроенного предиката "clause", при котором первым аргументом служил бы запрос (как это было сделано в процедуре "вып0"), процедура "вид0" создает копию запроса. Все аргументы этого нового запроса являются переменными. Новый запрос передается процедуре "найти фразу", которая возвращает тело фразы, унифицирующейся с этим запросом. К примеру, если исходным является запрос «owns(ибм, _0)», то новым запросом будет «owns(_l,_2)». Процедура "найти_фразу" может конкретизировать переменные нового запроса. После вызова процедуры "найти_фразу" печатаются исходный запрос и запрос, выработанный данной процедурой, а затем предпринимается попытка унификации этих двух фраз. Если унификация окажется успешной, то будет напечатана буква "У" и процедура "вып0" будет вызвана рекурсивно вместе с телом фразы, выработанным процедурой "найти_фразу". В противном случае процедура "найти_фразу" возвратится назад для поиска другой фразы в текущей программе.
Реализация программы "вид"
вид(Х):-
вид0 (",Q,Путь).
спросить_у_пользователя (Q, Путь).
спросить_у_пользователя (Q, Путь) :
write (Q),nl,
write (' введите символ h для просмотра пути доказательства '),
write ('или символ ; доя '),n1,
write (' получения другого ответа '),
n1,
get0 (А), get0 (_ ) - % ввести символ + перевод строки
А = 104, % asii - код символа 'R'
отобразить—путь("', Путь),
спросить_у_пользователя (Q, Путь),
!.
% исходный случай для факта
% +Отступ +Запрос -Путь
вид0( , true, есть_в_программе) : -!.
% составной запрос
вид0 (Oтступ, (Q1, Q2), (Путь1,Путь,2))
!,
вид0 (Отступ, Ql,путь1).
вид0 (Отступ, Q2, Путь2) .
% простой запрос
вид0 (Отступ, Q1, п(Q1. Путь)) :
% построить Q2:
% (Q2 - это копия 01, но все его аргументы являются
% переменными)
Q1 = . . [Предикат ; Аргументы1],
length (Аргументы1, Длина),
построить_список (Длина, Аргументы2),
Q2 = . . [Предикат | Аргументы2],
!,
найти_фразу (Отступ, Q2, Тело, Предикат),
write (Отступ), write (' подцель= '), write (Q1),
write ('элементбд='), write (Q2),write(' '),
( % успех, если Q1 унифицируется с Q2:
Q1 =Q2, write ('Y'),nl
;
% неудача, если они не унифицируются:
not (Q1 = Q2), write (' H '), n1, fail ),
сцепить (Отступ,' ', НовыйОтступ), % отступ для подцелей
вид0(НовыйОтступ, Тело, Путь).
% найти следующую фразу или напечатать сообщение о конце
% базы данных.
% + - - +
найти-фразу (_, Q, Тело, - ) :
clause (Предикат, Тело).
найти_фразу (Отступ,_,_, Предикат) :
write (Отступ),
write (': Конец базы данных '), write (Предикат),
write ('. '),n1,
!,fail.
построить_список (0, [ ]) :— !.
построить_список (N, [X | R]) :-
NN is N – 1,
построить_список (NN, R), !.
Процедуры "отобразить путь" и "сцепить" будут такими же, как и в приведенной ранее программе "вып".
