- •Глава 11 Отсечения и отрицание
- •11.1. Зеленые отсечения: выражение детерминизма
- •11.2. Оптимизация остатка рекурсии
- •11.3. Отрицание
- •11.4. Красные отсечения: устранение явных условий
- •11.5. Правила по умолчанию
- •1) «На бобах» остались Макдаф и, что уж совсем обидно, Макдональд. - прим.Ред.
- •11.6. Дополнительные сведения
- •Глава 12 Внелогические предикаты
- •12.1. Ввод-вывод
- •12.2. Доступ к программам и обработка программ
- •12.3. Запоминающие функции
- •12.4. Интерактивные программы
- •12.5. Циклы, управляемые отказом
- •12.6. Дополнительные сведения
11.4. Красные отсечения: устранение явных условий
Последовательный перебор правил в Прологе и способ его реализации при использовании отсечения является основой, необходимой для построения программы not. Программист может принимать во внимание, что при определенных условиях Пролог будет выполнять только часть процедуры. Это наводит на мысль о новом (вводящем в заблуждение) стиле программирования на Прологе с устранением явных условий, регламентирующих применение правила.
Исходным (плохим) примером в литературе является модификация программы 11.3, задающей отношение minimum. Можно отбросить сравнение во втором предложении программы, что приводит к программе
minimum(X,Y,X)XY,!. minimum(X,Y,Y).
Законность этой программы объясняют так: “Если Х не больше Y, то минимум -X. В противном случае минимум равен Y и сравнение Х с Y не требуется”. Однако в программе 11.3 такое сравнение выполняется.
Эти доводы имеют серьезный изъян. Значение модифицированной программы отличается от значения стандартной программы minimum, В модифицированной программе выполняется цель minimum (2,5,5). Модифицированная программа является ложной логической программой.
Можно избавиться от ложных целей, выводимых из модифицированной программы. Для этого необходимо неявную унификацию первого и третьего аргумента в первом правиле сделать явной. Измененное правило -
minimum(X,Y,Z) Х Y,!,Z = X.
Такой способ использования отсечения для фиксации правила после частичного выполнения унификации является достаточно обычным приемом. Но в случае программы minimum в результате получается слишком мудреный текст. Гораздо лучше просто записать корректную логическую программу, добавив для эффективности отсечение, как это сделано в программе 11.3.
Использование отсечения в операционной среде Пролога весьма проблематично. Оно приводит к появлению Пролог - программ, которые неверны, если их рассматривать как логические программы, т.е. из таких программ выводимы ложные утверждения. Однако они же работают правильно, поскольку в Прологе невозможно доказать эти ложные утверждения. Например, если в цели вида minimum (X,Y,Z) аргументам Х и Y сопоставлены значения, а аргументу Z-нет, то модифицированная программа работает правильно.
Единственным следствием применения зеленых отсечений в разд. 11.1 является отбрасывание заведомо бесполезных ветвей в дереве поиска. Отсечения в программе, которые приводят к изменению ее значения, называются красными отсечениями . Удаление красного отсечения изменяет значение программы, т. е. множество выводимых целей.
Обычный способ использования красных отсечений в Прологе - это устранение явных условий. Знание метода вычислений в Прологе и порядка использования правил в программе позволяет опускать заведомо выполнимые условия. В практическом программировании это иногда существенно, так как явные условия, особенно использующие отрицание, затрудняют описание и снижают эффективность выполнения программ. Однако такое устранение чревато ошибками.
Устранение явного условия возможно, если безуспешное применение предыдущих правил влечет выполнение этого условия. Например, из безуспешности сравнения ХY в программе minimum следует, что Х больше Y Следовательно, проверка Х > Y может быть опущена. Обычно такое явное условие эквивалентно отрицанию предыдущих условий. Использование красных отсечений для устранения условий позволяет задавать отрицание неявно.
Рассмотрим программу 11.5 - программу сортировки перестановками. Первое (рекурсивное) правило применимо всегда, когда в списке имеется пара неупорядоченных соседних элементов. Когда применяется второе правило sort, такие пары в списке отсутствуют и он должен быть упорядочен. Следовательно, условие ordered(Xs) может быть опущено, что превращает второе правило в факт sort(Xs, Xs). Как и в случае программы minimum, данное предложение логически некорректно.
Как только из программы удалено условие Ordered, цвет отсечения меняется с зеленого на красный. Удаление отсечений из варианта программы, не содержащего условия ordered, приводит к программе, дающей ложные решения.
Обратимся к другому примеру устранения явного условия. Рассмотрим программу 3.18, удаляющую элементы из списка. В двух рекурсивных предложениях рассматриваются различные случаи, зависящие от того, совпадает ли голова списка с удаляемым элементом. Взаимоисключащий характер этих случаев может быть выражен с помощью отсечений, как это сделано в программе 11.8а.
Ввиду того что безуспешное выполнение первого предложения означает несовпадение удаляемого элемента с головой списка, явную проверку на неравенство во втором предложении можно опустить. Программа 11.8б содержит соответствующие изменения. Все отсечения программы 1 l.8a зеленые в отличие от красного отсечения в первом предложении программы 11,8б.
delete (Xs.X.Ys)
список Ys получен в результате удаления всех вхождений элемента Х из списка Xs.
delete([X|Ys],X,Zs)!,delete(Ys,X,Zs) delete([Y|Ys],X,[YZs])YX,!,delete(Ys,X,Zs).
deleted: ],X,[ ]).
Программа 11.8a. Удаление всех вхождений элемента из списка.
delete (Х s,X,Ys)
список Ys получен в результате удаления всех вхождений элемента Х из списка Xs.
delete([X |Ys], X, Zs)!, delete (Ys, X., Zs).
delete([Y | Ys],X,[Y) Zs])!, delete (Ys, X, Zs).
delete([ ],X,[ ]).
Программа 11.8б. Удаление всех вхождений элемента из списка.
В общем случае удалять простые проверки, как это сделано в программе 11,86, нецелесообразно. Выигрыш в эффективности, который дает такое удаление, ничтожен по сравнению с потерями удобочитаемости текста программы и его модифицируемости.
Рассмотрим использование отсечения при задании управляющей конструкции if_then_else. Программа 11.9 определяет отношение if_.then_else(P,Q,R). Декларативное понимание предиката: предикат выполнен, если Р и Q истинны или не Р и R истинны. Операционное понимание: мы пытаемся доказать Р, в случае успеха доказываем Q, в противном случае доказываем R.
If_ then_ else (P,Q,R)-
Или Р и Q, или не Р и R.
if_Jhen_else(P,Q,R) Р,!, Q. if_then_else(P,Q,R)R.
Программа 11.9. Конструкция if_then_else.
Очевидно, что использование красного отсечения в данном случае разумно. Альтернатива к использованию отсечения состоит в явном указании условия, при котором доказывается R. В этом случае второе предложение будет иметь вид
if_then_else(P,Q,R) not Р, R.
С вычислительной точки зрения это может привести к большим затратам. При вычислении предиката not придется полностью повторить вычисление цели Р.
До сих пор мы встречались с двумя вариантами использования красных отсечений, В первом красное отсечение было встроено в программу, как в определениях отношений not и . Во втором красное отсечение возникало из зеленого при удалении условий из программы. Однако имеется и третий вариант красного отсечения. Отсечение, вводимое в программу в качестве зеленого, предназначенного лишь для повышения эффективности, может оказаться красным, меняющим значение программы.
В качестве примера рассмотрим попытку создания эффективного варианта программы member, который при неоднократном вхождении элемента в список допускал бы лишь одно успешное вычисление. Применяя процедурный подход, для устранения возврата при обнаружении вхождения элемента в список, будем использовать отсечение. Текст соответствующей программы:
member(X,[X | Xs])!.
member(X,[Y | Ys]) member(X,Ys).
Добавление отсечения действительно изменило функционирование программы. Однако полученная программа некорректна, так как решение, например, цели member(Х,[1,2.3])? дает лишь одно значение Х = 1. Эта программа является вариантом программы member_check (программа 7.3), в которой опущено явное условие X Y, и, следовательно, отсечение является красным.
Упражнения к разд. 11.4
1. Рассмотрите возможность добавления отсечений в программу 9.3, задающую отношение Substitute. Полезно ли использовать комбинацию «отсечение-fail» и имеет ли смысл исключать явные условия?
2. Исследуйте связь между программой Select (программа 3.19) и программой, полученной добавлением одного отсечения:
select(X,[X |Xs],Xs)!.
select (X,[Y | Ys],[Y | Zs])select(X, Ys, Zs).
(Указание: Рассмотрите варианты программы select.)