Пример процедуры, поведение которой соответствует предположению об открытости мира

Рассмотрим простой пример процедуры, поведение которой соответствует предположению об открытости мира. Запрос может обладать одним из трех истинностных значений: истина, ложь или неизвестно. Ложные утверждения должны быть представлены в текущей программе в явном виде в качестве фактов, имеющих форму «false (X)», где Х сам является фактом. Если нельзя доказать, что утверждение истинно или ложно, то оно считается неизвестным.

доказать (Р):—

P, write ('** истинно'), n1,!.

доказать (Р): -

false (P), write('** ложно '), n1,!.

доказать (Р):—

not (P),

not (false (P)),

write ('** неизвестно '), n1.

Предположим, что в программу введены факты:

отец (филип, чарльз). % позитивный факт

false (отец (чарльз, Х)). % негативный факт

На примере следующих запросов проиллюстрируем работу процедуры "доказать":

|? - доказать (отец (филип, энн)).

••неизвестно

да

|? - доказать (отец (филип, X)).

••истинно

Х = чарльз

Как Вы считаете, какой ответ будет дан на запрос:

|?— доказать (отец (чарльз, мери)).?

3. 4. Встроенные предикаты, предназначенные для обеспечения ввода-вывода Побочные эффекты ввода-вывода

В языке Пролог есть ряд встроенных предикатов, обеспечивающих ввод и вывод. Каждый из таких предикатов обладает побочным эффектом ввода-вывода. Это означает, что когда обрабатывается запрос к одному из предикатов ввода-вывода, то это оказывает некоторое перманентное воздействие на вычислительную среду, такое, скажем, как вывод сообщения на экран терминала или считывание слова из файла.

Каждый предикат ввода-вывода обладает четким процедурным смыслом. Однако, как и у предиката "сократить", у данных предикатов отсутствует декларативный смысл. Каждый из них является детерминированным в том смысле, что запрос к такому предикату будет успешным только один раз.

put (X) X — целое, значением которого является некоторый ascii-код. Предикат "put" выводит в текущий выходной поток символ, код которого соответствует значению X.

write (X) Предикат "write" выводит терм в текущий выходной поток.

n1 Предикат "n1" записывает в выходной поток признак возврата каретки/перевода строки.

get0 (X) Предикат "get0" унифицирует Х с ascii-кодом следующего символа из текущего входного потока.

read (X) Предикат "read" унифицирует Х со следующим термом из текущего входного потока. Ограничителем терма является точка, за которой следует пробел или начало новой строки.

Пример:

|? -read (X).

привет.

X=привет

Заметьте, что точка, введенная пользователем, не включается в значение переменной X.

Пример запроса, в котором используется предикат "read"

Рассмотрим сложный составной запрос, в котором употребляется предикат "read". Предположим, что существует база данных с названиями языков и пользователь, говорящий на французском языке, отвечает на вопросы, которые задает представленный ниже составной запрос.

язык (итальянский).

язык (немецкий).

язык (японский).

язык (французский).

язык (английский).

|?—язык (L),

write ('Знаете ли Вы'),

write (L), write ('язык?'), n1,

read (A),

А=да,

!,

write ('Ага! Так Вы знаете '),

write (L), write ('язык! '), n1,

Знаете ли Вы итальянский язык?

нет.

Знаете ли Вы немецкий язык?

нет.

Знаете ли Вы японский язык?

нет.

Знаете ли Вы французский язык?

да.

Ага ! Так Вы знаете французский язык !

L = французский

А=да

Алгоритм поиска с возвратом

Составной запрос задает пользователю вопрос о том, знает ли он итальянский язык, а затем "считывает" ответ пользователя и запоминает его в переменной А. Если пользователь отвечает нет, то подцель «А=да» терпит неудачу, и интерпретатор возвращается назад и рассматривает следующий язык. В конце концов пользователь отвечает да на вопрос о французском языке, после этого интерпретатор проходит через предикат "сократить" и печатает некоторые дополнительные сообщения. Предикат "сократить" дает гарантию того, что запрос закончится после первого ответа да. Поэтому перед пользователем не был поставлен вопрос о знании им английского языка.

Данный составной запрос основывается на алгоритме поиска с возвратом, который получил это название из-за того, что интерпретатор возвращается назад при просмотре базы данных "язык". Вначале интерпретатор действует циклически. Он перемещается назад и вперед между рассмотрением нового языка и вопросом пользователю о том, знает ли он этот язык.

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

Соседние файлы в папке Гл.0,1,2,3,4,5,Предисловие