Процедура "вып". Единственным аргументом процедуры "вып" (сокращение от слова "выполнить") является запрос, который эта процедура выполняет. Если выполнение запроса окажется успешным, то процедура "вып" напечатает запрос с конкретизированными переменными, а затем спросит пользователя, не желает ли он посмотреть путь доказательства или получить иной ответ. Если ответов на запрос больше не существует, то процедура "вып" потерпит неудачу.
Использование процедуры "вып". Посмотрите, как процедура "вып" отвечает на запрос к нижеследующей базе данных "разновидность", содержащей сведения о разновидностях собраний, которые включают в себя другие вспомогательные собрания:
разновидность (собрание_38, собрание_381).
разновидность (собрание_381, собрание_382).
разновидность (собрание_39, собрание_391).
?- вып (разновидность (собрание_38, X)).
разновидность (собрание_38, собрание_381)
введите символ h для просмотри пути доказательства или символ ; для получения другого ответа.
Поскольку данный запрос может быть успешно выполнен, процедура "вып" печатает его, причем переменная Х унифицирована с константой «собрание_381». Теперь, если пользователь введет символ "h", процедура "вып" пояснит, как она выполнила запрос:
h
разновидность (собрание_38, собрание_381) содержится в программе.
Объяснение. Объяснение вырабатывается следующим образом. Если запрос унифицируется с фактом, содержащимся в текущей программе, то на печать выдаются текст запроса и слова «содержится в программе». Если запрос унифицируется с правилом, входящим в текущую программу, то печатаются запрос и вопросительный знак. Далее по этой же схеме печатаются подцели данного правила. Подцели выделяются при печати с помощью отступа.
Ниже приводится пример сеанса работы с процедурой "вып", который иллюстрирует выдачу объяснений этой процедурой. Обратите внимание на то, что форма объяснений отражает форму фраз, которые используются при выполнении запроса. Транзитивное отношение "имеет_отношение_к" основывается на приведенной выше базе данных "разновидность". Отношение "имеет_отношение_к" выражает то обстоятельство, что тема одного собрания может косвенно затрагивать тему другого, т.е через тему промежуточного собрания.
имеет_отношение_к (X,Y) :-
разновидность (X,Y).
имеет_отношение_к (X,Y) :-
разновидность (X,Z),
имеет_отношение_к (Z,Y).
?- вып (имеет_отношение_к (собрание_38, X)).
имеет_отношение_к (собрание_38, собрание_381) % первый ответ
введите символ h для просмотра пути доказательства или символ ; для получения другого ответа.
h
имеет_отношение_к (собрание_38, собрание_381) ?
разновидность (собрание_38, собрание_381) содержится в программе.
имеет_отношение_к (собрание_38, собрание_381)
введите символ h для просмотра пути доказательства или символ ; для получения другого ответа.
;
имеет_отношение_к (собрание_38, собрание_382) % второй ответ
введите символ h для просмотра пути доказательства или символ ; для получения другого ответа.
h
имеет_отношение_к (собрание_38, собрание_382) ?
разновидность (собрание_38, собрание_381) содержится в программе.
имеет_отношение_к (собрание_381, собрание_382) ?
разновидность (собрание_381, собрание_382) содержится в программе.
имеет_отношение_к (собрание_38, собрание_382)
введите символ h для просмотра пути доказательства или символ ; для получения другого ответа.
;
нет
Заметьте, что процедура "вып" повторно печатает запрос после ввода пользователем символа h.
Как работает процедура "вып". Единственным аргументом процедуры "вып" является запрос, который она далее передает процедуре "вып()". Процедура "вып()" возвращает структуру вида:
п (Запрос, ПутьДоказательства)
через свой второй аргумент. Здесь «Запрос» - это исходный запрос, а «ПутьДоказательства» - это структура, описывающая шаги, необходимые для доказательства запроса. В простейшем случае, когда запрос можно доказать по единственному факту, переменная «ПутьДоказательства» унифицируется со словами «есть_в_программе». Если запрос доказывается при помощи правила, то переменная «ПугьДоказательства» унифицируется с рекурсивной структурой "п", содержащей все подцели правила.
После конкретизации переменная «ПутьДоказательства» передается процедуре "спросить_у_пользователя". Эта процедура спрашивает пользователя, желает ли он просмотреть путь доказательства. В случае утвердительного ответа вызывается процедура "отобразить_путь", а в противном случае процедура "спросить_у_пользователя" терпит неудачу и процедура "вып()" возвращается назад для поиска другого ответа.
Реализация программы "вып"
% выполнить запрос.
вьп(Х) :-
вып() (Х,Р),
спросить_у_пользователя (X, Р).
спросить_у_пюльзователя (X, Р) :-
write (X), nl,
write (' введите символ h для просмотра пути доказательства '),
write (' или символ ; '),nl,
write (' для получения другого ответа.'),
nl,
get() (A),get0 (_), % ввод символа + перевод строки
А = 104, % ascii-код символа 'h'
отобразить_путь ('', Р), % "означает отсутствие отступа
!,
спросить_у_пользователя (X, Р).
% исходный случай: последняя фраза была фактом.
% + -
% Запрос Путь
вып()(true, есть_в_программе) :- !.
% составной запрос; вернуть Р1, соединенную с Р2 запятой
вып()(А, Б), (Р1, Р2)) :-
!,
вып()(А, Р1),
вып()(Б, Р2).
% простой запрос; вернуть структуру п( )
вып()(А,п (А,Р1)):-
clause (А, Тело),
вып() (Тело,Р1).
% отобразить путь выполнения:
% + +
отобразить_путь (Отступ, п (Фраза, есть_в_программе)) :-
write (Отступ), write (Фраза),
write ( содержится в программе.'), nl, !.
% первая подцель составного запроса
отобразить_путь (Отступ, п (Фраза, (Подцель, Подцели)) ) :-
сцепить (Отступ,' ', НовыйОтступ),
отобразить_путь (НовыйОтступ, Подцель),
!,
отобразить_путь (НовыйОтступ, Подцели).
% остальные подцели составного запроса
отобразить_путь (Отступ, (Подцель, Путь)) :-
отобразить_путь (Отступ, Подцель),
!,
отобразить_путь (Отступ, Путь).
отобразить_путь (Отступ, п (Фраза, Путь)) :-
write (Отступ), write (Фраза),
write (' ? '), nl,
сцепить (Отступ,' ', НовыйОтступ),
!,
отобразить_путь (НовыйОтступ, Путь).
% + + -
сцепить (X, Y, Z) :- % сцепить два атома
name (X, Хсписок),
name (У, Усписок),
присоединить (Хсписок, Усписок, Z список),
name (Z, Zсписок),!.
Доказательство факта. Лучше всего можно будет понять работу процедуры "вып", если рассмотреть входную и выходную информацию ее подцелей. Посмотрите, что получится, если на вход процедуры "вып()" поступит запрос, который является доказуемым по факту:
?- вып() (разновидность (собрание_38, X), ПутьДоказательства).
Процедура "вып()" вызовет подцель "clause", которая унифицирует переменную Х с константой «собрание_381», а переменную «Тело» - с «true», так как «разновидность (собрание_38, собрание_381)» — это факт.
Следующий вызов процедуры "вып()" будет эквивалентен такому
запросу:
?- вып() (true, P1).
Р1 = есть_-в_программе
Ответ на этот запрос получен по первому правилу "вып()". Значение переменной Р1 передается далее и становится частью структуры "п", которая '''возвращается через предыдущий вызов "вып()":
ПутьДоказательства = п (разновидность (собрание_38, собрание_381), есть_в_программе)
Доказательство правила. Предположим, что на вход процедуры "вып()" поступает запрос, который можно доказать только при помощи правила:
?- вып() (имеет_отношение_к (собрание_38, X), Путь). %(1)
Этот вызов согласуется с третьим правилом процедуры "вып()". Подцель "clause" этого правила эквивалентна запросу:
?- clause (имеет_отношение_к (собрание_38, X), Тело1). %(2)
Тело1 =" разновидность (собрание_38, X).
Подцель "вып()" данного правила эквивалентна:
?- вып() (разновидность (собрание_38, Х), Р1). %(3)
P1 =n(разновидность (собрание_38, собрание_381), есть_в_программе)
А этот запрос - точно такой же, как и проанализированный ранее. Теперь запрос (1) к процедуре "вып()"даст следующий результат:
Путь = п (имеет_отношение_к (собрание_38, собрание_381), п (разновидность (собрание_38, собрание_381),
есть_в_программе))
Показ цепочки выводов. Требование просмотреть путь доказательства вызовет серию обращений к процедуре "отобразить, путь", что эквивалентно следующим запросам:
?- отобразить_путь (' ' ,п (имеет_отношение_к (собрание_38. собрание_381),
п (разновидность (собрание_38, собрание_381), есть_в_программе))).
имеет_отношение_к (собрание_38, собрание_381) ?
?- отобразить_путь (‘ ‘, п (разновидность (собрание_38, собрание_381), есть_в_ программе)).
разновидность (собрание_38, собрание_381) содержится в программе.
Ограничения программы "вып". В приведенной версии программы "вып," не моделируется действие предиката "сократить". Если на вход программы "вып" подать запрос к процедуре, содержащий предикат "сократить", то этот предикат будет трактоваться как всегда истинная подцель. Предикат "сократить" не остановит процесс поиска с возвратом, выполняемый этой процедурой |