7.2, Запоминание пути вывода Процедура "вып"

Единственным аргументом процедуры "вып" (сокращение от слова "выполнить") является запрос, который эта процедура выполняет. Если выполнение запроса окажется успешным, то процедура "вып" напечатает запрос с конкретизированными переменными, а затем спросит пользователя, не желает ли он посмотреть путь доказательства или получить иной ответ. Если ответов на запрос больше не существует, то процедура "вып" потерпит неудачу.

Использование процедуры "вып"

Посмотрите, как процедура "вып" отвечает на запрос к нижеследующей базе данных "owns", содержащей сведения о корпорациях, которые владеют другими корпорациями:

owns (ибм,ролм).

owns (ролм, дейтапойнт).

owns (атт, телетайп).

| ? - вып (owns (ибм, X))-

owns (ибм, ролм)

введите символ h для просмотри пути доказательства или символ ; для

получения другого ответа.

Поскольку данный запрос может быть успешно выполнен, процедура "вып" печатает его, причем переменная Х унифицирована с константой « ролм ». Теперь, если пользователь введет символ "h", процедура "вып" пояснит, как она выполнила запрос:

H

owns (ибм, ролм) содержится в программе.

Объяснение

Объяснение вырабатывается следующим образом. Если запрос унифицируется с фактом, содержащимся в текущей программе, то на печать выдаются текст запроса и слова «содержится в программе». Если запрос унифицируется с правилом, входящим в текущую программу, то печатаются запрос и вопросительный знак. Далее по этой же схеме печатаются подцели данного правила. Подцели выделяются при печати с помощью отступа.

Ниже приводится пример сеанса работы с процедурой "вып", который иллюстрирует выдачу объяснений этой процедурой. Обратите внимание на то, что форма объяснений отражает форму фраз, которые используются при выполнении запроса. Транзитивное отношение "holds" ("владеть непосредственно или через посредника") основывается на приведенной выше базе данных "owns" ("владеть непосредственно"). Отношение "holds"

выражает то обстоятельство, что одна компания может владеть другой косвенно, т.е. через промежуточную компанию.

holds (X, Y) :-

owns (X, Y).

holds (X, Y) :-

owns (X, Z),

holds (Z, Y).

| ?- вып (holds (ибм, X)).

holds (ибм, ролм) % первый ответ

введите символ h для просмотра пути доказательства или символ ;

для получения другого ответа. h

holds (ибм, ролм) ?

owns (ибм, ролм) содержится в программе.

holds (ибм, ролм)

введите символ h для просмотра путч доказательства или символ ;

для получения другого ответа.

;

holds (ибм, дейтапойнт) % второй ответ

введите символ h для просмотра пути доказательства или символ ;

для получения другого ответа.

h

holds (ибм, дейтапойнт) ?

owns (ибм, ролм) содержится в программе.

holds (ролм, дейтапойнт) ?

owns (ролм, дейтапойнт) содержится в программе.

holds (ибм, дейтапойнт)

введите символ h для просмотра пути доказательства или символ ;

для получения другого ответа.

;

нет

Заметьте, что процедура "вып" повторно печатает запрос после ввода пользователем символа h.

Как работает процедура "вып"

Единственным аргументом процедуры "вып" является запрос, который она далее передает процедуре "вып0. Процедура "вып0 возвращает структуру вида:

п (Запрос, ПутьДоказательства)

через свой второй аргумент. Здесь «Запрос» — это исходный запрос, а «ПутьДоказательства» - это структура, описывающая шаги, необходимые для доказательства запроса. В простейшем случае, когда запрос можно доказать по единственному факту, переменная «ПутьДоказательства» унифицируется со словами «есть_в_программе». Если запрос доказывается при помощи правила, то переменная «ПутьДоказательства» унифицируется с рекурсивной структурой "п", содержащей все подцели правила.

После конкретизации переменная «ПутьДоказательства» передается процедуре "спросить_у_пользователя". Эта процедура спрашивает пользователя, желает ли он просмотреть путь доказательства. В случае утвердительного ответа вызывается процедура "отобразить_путь", а в противном случае процедура "спросить_у_пользователя" терпит неудачу и процедура "вып0" возвращается назад для поиска другого ответа.

Реализация программы "вып "

% выполнить запрос. вып(Х):-

вып0 (Х,Р),

спросить_у_пользователя (X, Р).

спросить_у_пользователя (X, Р) :—

write (X),nl,

write ('введите символ h для просмотра пути доказательства '),

write (' или символ ; '),n1,

write (' для получения другого ответа.'),

nl,

get0 (А), get0 (_), % ввод символа + перевод строки

А = 104, % ascii-код символа 'h'

отобразить—путь ('', Р), % " означает отсутствие отступа

!,

спросить_у_пользователя (X, Р).

% исходный случай: последняя фраза была фактом.

% +

% Запрос Путь

вып(true, есть_в_программе):- !.

% составной запрос; вернуть Р1, соединенную с Р2 запятой

!,

вып0(А.Б), (Р1,Р2)):-!,

вып0(А,Р1), вып0(Б,Р2).

% простой запрос; вернуть структуру п( )

вып0(А,п(А,Р1)):-

clause (А, Тело),

вып0 (Тело, Р1).

% отобразить путь выполнения:

% + + отобразить-путь (Отступ, п (Фраза, есть_в_программе)):-

write (Отступ), write (Фраза),

write (' содержится в программе.'), n1, !,

% первая подцель составного запроса

отобразить-путь (Отступ, п (Фраза, (Подцель, Подцели)) ):"-

сцепить (Отступ,' ', НовыйОтступ),

отобразить_путь (НовыйОтступ, Подцель),

!,

отобразить_путь (НовыйОтступ, Подцели).

% остальные подцели составного запроса

отобразить_путь (Отступ, (Подцель, Путь)) :-

отобразить_путь (Отступ, Подцель),

!,

отобразить_путь (Отступ, Путь).

отобразить_путь (Отступ, п (Фраза, Путь)) :-

write (Отступ), write (Фраза),

write(' ? '),nl,

сцепить (Отступ,' ', НовыйОтступ),

!,

отобразить_путь (НовыйОтступ, Путь).

% + + -сцепить (X,Y,Z):- % сцепить два атома

name (X, Хсписок),

name (Y,Yсписок),

присоединить (Хсписок, Yсписок, Z список),

name (Z, Zсписок), !.

Соседние файлы в папке Гл.6,7,Прилож.,Допол