Назад | Содержание| Вперёд Глава 5 УПРАВЛЕНИЕ ПЕРЕБ...

Назад | Содержание| Вперёд

Глава 5

УПРАВЛЕНИЕ ПЕРЕБОРОМ

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

5. 1.    Ограничение перебора

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

Рис. 5. 2.  Вточке, помеченной словом "ОТСЕЧЕНИЕ",уже известно,

что правила  2  и  3  должныпотерпеть неудачу.

При вычислении первой цели  f( l, Y)  Y конкретизируется нулем. Поэтому вторая цельстановится такой:

        2 < 0

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

Три правила, входящие в отношение f,являются взаимоисключающими, поэтому успехвозможен самое большее в одном из них.Следовательно, мы (но не пролог-система) знаем,что, как только успех наступил в одном из них, нетсмысла проверять остальные, поскольку они всеравно обречены на неудачу. В примере, приведенномна рис. 5.2, о том, что в правиле 1 наступил успех,становится известно в точке, обозначенной словом"ОТСЕЧЕНИЕ". Для предотвращениябессмысленного перебора мы должны явно указатьпролог-системе, что не нужно осуществлять возврат из этой точки. Мы можем сделатьэто при помощи конструкции отсечения. "Отсечение"записывается в виде символа '!',который вставляется между целями и играет рольнекоторой псевдоцели. Вот наша программа,переписанная с использованием отсечения:

        f( X, 0) :- X < 3,  !.

        f( X, 2) :- 3 =< X,  X <6,  !.

        f( X, 4) :- 6 =< X.

Символ  '!'  предотвращает возврат из техточек программы, в которых он поставлен. Если мытеперь спросим

        ?-  f( 1, Y),  2 < Y.

то пролог-система породит левую ветвь дерева,изображенного на рис. 5.2. Эта ветвь потерпитнеудачу на цели  2  <  0.  Система попытается сделать возврат, но вернутьсяона сможет не далее точки, помеченной в программесимволом   '!' .  Альтернативные ветви,соответствующие правилу 2 и правилу 3, порожденыне будут.

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

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

5. 1. 2.    Эксперимент 2

Проделаем теперь еще один эксперимент совторой версией нашей программы. Предположим, мызадаем вопрос:

        ?-  f( 7, Y).

        Y = 4

Проанализируем, что произошло. Перед тем, какбыл получен ответ, система пробовала применитьвсе три правила. Эти попытки породили следующуюпоследовательность целей:

Попытка применить правило 1:

    7  <  3  терпит неудачу,происходит возврат, и попытка применить правило 2(точка отсечения достигнута не была)

Попытка применить правило 2:

    3  <=  7  успех, но  7  <  6  терпит неудачу; возврат и попыткаприменить правило 3 (точка отсечения снова недостигнута)

Попытка применить правило 3:

    6  <=  7  - успех

Приведенные этапы вычисления обнаруживают ещеодин источник неэффективности. В началевыясняется, что  X  <  3  неявляется истиной  (7  <  3  терпитнеудачу). Следующая цель -   3 =< Х   (3  <=  7- успех).  Но нам известно, что, еслипервая проверка неуспешна, то вторая обязательнобудет успешной, так как второе целевоеутверждение является отрицанием первого.Следовательно, вторая проверка лишняя исоответствующую цель можно опустить. То же самоеверно и для цели  6 =< Х  в правиле 3.Все эти соображения приводят к следующей, болееэкономной формулировке наших трех правил:

        если  Х < 3,  то  Y= 0

        иначе, если  3 <= X  и  Х < 6,  то  Y = 2,

        иначе  Y = 4.

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

        f( X, 0) :- X < 3,  !.

        f( X, 2) :- X < 6,  !.

        f( X, 4).

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

        f( X, 0) :- X < 3.

        f( X, 2) :- X < 6.

        f( X, 4).

Она может порождать различные решения, часть изкоторых неверны. Например:

        ?-  f( 1, Y).

        Y = 0;

        Y = 2;

        Y = 4;

        nо            (нет)

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

Более точный смысл механизма отсеченийможно сформулировать следующим образом:

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

Чтобы прояснить смысл этого определения,рассмотрим предложение вида

        Н :- В1, В2, ..., Вm, !, ...,Вn.

Будем считать, что это предложениеактивизировалось, когда некоторая цель  G  сопоставилась с  Н.  Тогда  G   являетсяцелью-родителем. В момент, когда встретилосьотсечение, успех уже наступил в целях  В1, ...,  Вm.  При выполнении отсечения это(текущее) решение  В1,   ...,  Вm "замораживается" и все возможные оставшиесяальтернативы больше не рассматриваются. Далее,цель  G  связывается теперь с этимпредложением: любая попытка сопоставить  G с головой какого-либо другого предложенияпресекается.

Применим эти правила к следующему примеру:

        С :- Р, Q, R, !, S, Т, U.

        С :- V.

        А :- В, С, D.

        ?-  А.

Здесь  А,  В,  С,  D,  Р  и т.д. имеютсинтаксис термов. Отсечение повлияет навычисление цели  С  следующим образом.Перебор будет возможен в списке целей  Р,   Q,  R;  однако, как только точкаотсечения будет достигнута, все альтернативныерешения для этого списка изымаются израссмотрения. Альтернативное предложение,входящее в  С:

        С :- V.

также не будет учитываться. Тем не менее,перебор будет возможен в списке целей  S,  Т,  U.  "Цель-родитель" предложения,содержащего отсечения, -это цель  С  впредложении

        А :- В, С, D.

Поэтому отсечение повлияет только на цель  С.  С другой стороны, оно будет "невидимо" изцели  А.  Таким образом, автоматическийперебор все равно будет происходить в спискецелей  В,  С,  D,  вне зависимости отналичия отсечения в предложении, котороеиспользуется для достижения  С.

Назад | Содержание| Вперёд









Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх