Скачиваний:
53
Добавлен:
01.05.2014
Размер:
565.76 Кб
Скачать

7.1. Порядок правил

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

Порядок правил определяет порядок поиски решении.

Изменение порядка правил в процедуре приводит к перестановке ветвей в любом дереве поиска цели, использующей данную процедуру. Обход дерева поиска производится в глубину. Поэтому перестановка ветвей дерева изменяет порядок обхода дерева поиска и порядок нахождения решений. Этот эффект очевиден при использовании фактов для нахождения ответов на экзистенциальный вопрос. Если использовать нашу библейскую базу данных для ответа на такой вопрос, как отец(Х,У)?, то изменение порядка фактов изменит порядок, в котором Пролог будет находить решения. Однако решение о том, как упорядочить факты, не имеет большого значения.

Порядок, в котором находятся ответы на вопросы при работе рекурсивной программы, также определяется порядком предложений. Рассмотрим простую библейскую базу данных вместе с программой, определяющей отношение предок (программа 7.1).

родитель (фарра,авраам). родитель (авраам, исаак).

родитель (исаак, иаков). `родитель (иаков, вениамин).

предок(Х,Y)  родитель (X,Y).

предок(Х,Y)  родитель (X,Y), предок(Y,Z).

Программа 7.1 Еще один семейный пример.

При решении вопроса предок (фарра.Х)?. с использованием программы 7.1 ответы будут даны в следующем порядке: Х = авраам, Х -= исаак, Х = иаков и Х = вениамин. Если переставить два правила, определяющие отношение предок, то решения будут появляться в другом порядке: Х = вениамин. Х = иаков, Х = исаак и Х= авраам.

Изменение порядка правил, задающих отношение предок, меняет порядок поиска в неявно заданном генеалогическом дереве. При одном порядке Пролог перечисляет потомков в порядке порождения. При переставленных предложениях Пролог переходит к концу дерева и выдает решения в обратном порядке. Требуемый порядок решений определяется использованием программы, в соответствии с которым и выбирается порядок правил для отношения предок.

Изменение порядка предложений в определении предиката member (программа 3.12) также приводит к изменению порядка поиска. В представленном виде программа просматривает список до тех пор, пока не будет найден нужный элемент. Если поменять порядок предложений на обратный, то программа будет всегда начинать поиск с конца списка. Это повлияет на порядок решений. Рассмотрим, например, вопрос member(X,[1,2,3])?. При обычном порядке правил порядок решений естествен: X = 1, Х = 2, Х = 3. Если правила переставлены, то порядок решений - X = 3. Х = 2, X = I. Порядок правил в программе 3.12 основан на интуиции и поэтому предпочтительнее.

В тех случаях, когда дерево поиска данной цели содержит бесконечную ветвь, порядок правил может определять, будет ли вообще найдено хотя бы одно решение. Рассмотрим вопрос append(Xs,[c,d],Ys)?.. Из дерева поиска, приведенного на рис. 5.4, можно усмотреть, что решения найдены не будут. Если, однако, в программе, задающей отношение append, поставить факт перед правилом, то будет найдено бесконечное число пар Xs, Ys, удовлетворяющих вопросу.

Не существует общих правил выбора порядка предложений в процедурах Пролога. Ясно, что стандартная для большинства традиционных языков проверка условия остановки перед продолжением итерации или рекурсии не имеет столь важного значения в Прологе. Это заметно в программе 3.15, задающей отношение append, равно как и в других программах, приведенных в книге. Дело в том, что применимость итерационного или рекурсивного правила проверяется с помощью унификации. Эта проверка производится явно и независимо от остальных предложений в процедуре.

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

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

Упражнения к разд. 7.1

1. Проверьте порядок нахождения решений вопроса предок (авраам,Х)? с помощью программы 7.1, а также с помощью варианта программы, полученного изменением порядка правил, задающих отношение предок.

2. В каком порядке появляются ответы на вопрос предок(Х, вениамин)? при использовании программы 7.1? Что произойдет при перестановке правил?

7.2. Проблема завершения программ

Используемый в Прологе принцип обхода дерева в глубину приводит к серьезным проблемам. Если дерево поиска цели относительно некоторой программы содержит бесконечную ветвь, то вычисление не завершится. Пролог может не найти решение цели, даже если существует конечное вычисление, решающее вопрос.

Бесконечные вычисления появляются при использовании рекурсивных правил. рассмотрим добавление отношения супруги (Мужчина, Женщина) к нашей базе данных семейных отношений. Один из фактов библейской истории -супруги( авраам, capa). Для пользователя, применяющего отношение супруги, несущественно, мужчина или женщина упоминается на первом месте, так как это отношение коммутативно. “Очевидный” способ задания коммутативности состоит в добавлении рекурсивного правила супруги(Х,Y)супруги (Y,X). Если такое правило добавить к программе, то ни одно вычисление, использующее отношение супруги, никогда не закончится. В качестве примера на рис. 7.1 приведен протокол решения вопроса супруги(авраам, сара) ?

супруги(Х,Y)  супруги(Х,Y).

супруги(авраам,сара).

супруги(авраам,сара)

супруги(сара.авраам)

супруги(авраам,сара)

супруги(сара,авраам)

Рис. 7.1. Незавершающееся вычисление.

Рекурсивные правила, в которых рекурсивная цель является первой целью в теле правила, называются левыми рекурсивными правилами. Аксиома для отношения супруги является примером такого правила. Левые рекурсивные правила в Прологе причиняют немало хлопот. В случае несоответствующих аргументов использование этих правил приводит к бесконечным вычислениям.

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

быть_супругами(Х,Y)  супруги(Х,Y).

быть_супругами(Х,Y)  супруги(Y,Х).

В общем случае, к сожалению, невозможно избавиться от всех появлений левой рекурсии. Все простые минимальные рекурсивные программы, приведенные в гл. 3, содержат левую рекурсию и могут привести к бесконечным вычислениям. Однако соответствующий анализ, использующий введенные в разд. 5,2 понятия области и полной структуры, позволяет определить вопросы, решение которых относительно рекурсивных программ приводит к результату.

В качестве примера рассмотрим программу 3.15, соединяющую два списка. Программа, задающая отношение append, всюду завершается для множества целей, в которых первый или/и последний аргументы - полные списки. Вычисление любого append-вопроса, у которого первый аргумент - полный список, неизбежно завершится. То же самое справедливо для всех вопросов, у которых третий аргумент является полным списком. Вычисление программы завершается в том случае, когда первый или/и третий аргумент - основные термы, не являющиеся списками. Наконец, есть вопросы, не приводящие к завершению вычислений: это вопросы, у которых и первый, и третий аргументы - неполные списки.

Условие остановки программы 3.12, задающей отношение member, также формулируется в терминах неполных списков. Решение вопроса не завершается, если второй аргумент - неполный список. Если второй аргумент вопроса - полный список, то вычисление остановится.

Другой, не всегда замечаемый случай, который заведомо приводит к незавершающимся вычислениям, - это порочный круг в определении. Рассмотрим пару правил

родитель(Х,Y)  ребенок(Y,Х).

ребенок(Y,Х)  родитель(Х,Y).

Любое вычисление, использующее предикат родитель или ребенок (например, родитель (аран,.лот)?), не завершится. Ввиду порочного круга дерево поиска обязательно содержит бесконечную ветвь.

Упражнения к разд. 7.2

1. Рассмотрите проблему остановки программ, определяющих префикс и суффикс списков (программа 3.13).

2. Рассмотрите проблему остановки программы 3.14(с), задающей отношение sublist.

Соседние файлы в папке 1-13