Prolog
Шрифт:
решение( [X/Y | Остальные] ) :-
решение( Остальные),
принадлежит( Y, [1, 2, 3, 4, 5, 6, 7, 8] ),
not бьет( X/Y, Остальные).
бьет( X/Y, Остальные) :-
принадлежит( X1/Y1, Остальные),
( Y1 = Y;
Y1 is Y + X1 - X;
Y1 is Y - X1 + X ).
принадлежит( А, [В | L] ) :-
принадлежит( А, L).
% Шаблон решения
шаблон( [1/Y1, 2/Y2, 3/Y3, 4/Y4, 5/Y5, 6/Y6, 7/Y7, 8/Y8]).
Рис. 5. 3. Еще одна программа для решения задачи о восьми ферзях.
разность( Множ1, Множ2, Разность)
где все три множества представлены в виде списков. Например,
разность( [a, b, c, d], [b, d, e, f], [a, c] )
Посмотреть ответ
5. 6. Определите предикат
унифицируемые( Спис1, Терм, Спис2)
где Спис2– список всех элементов Спис1, которые сопоставимы с Терм'ом, но не конкретизируются таким сопоставлением. Например:
?- унифицируемые( [X, b, t( Y)], t( a), Спис).
Спис = [ X, t( Y)]
Заметьте, что и Х и Y должны остаться неконкретизированными, хотя сопоставление с t( a) вызывает их конкретизацию. Указание: используйте not ( Терм1 = Терм2). Если цель Терм1 = Терм2 будет успешна, то not( Терм1 = Tepм2) потерпит неудачу и получившаяся конкретизация будет отменена!
Посмотреть ответ
Назад | Содержание | Вперёд
Назад | Содержание | Вперёд
5. 4. Трудности с отсечением и отрицанием
Используя отсечение, мы кое-что выиграли, но не совсем даром. Преимущества и недостатки применения отсечения были показаны на примерах из предыдущих разделов. Давайте подытожим сначала преимущества:
(1) При помощи отсечения часто можно повысить эффективность программы. Идея состоит в том, чтобы прямо сказать пролог-системе: не пробуй остальные альтернативы, так как они все равно обречены на неудачу.
(2) Применяя отсечение, можно описать взаимоисключающие правила, поэтому есть возможность запрограммировать утверждение:
если условие Р, то решение Q,
иначе решение R
Выразительность языка при этом повышается.
Ограничения на использование отсечения проистекают из того, что есть опасность потерять такое важное
р :- а, b.
р :- с.
Декларативный смысл программы: р истинно тогда и только тогда, когда истинны одновременно и а, и b или истинно с. Это можно записать в виде такой логической формулы:
р <===> (а & b) U с
Можно поменять порядок этих двух предложений, но декларативный смысл останется прежним. Введем теперь отсечение
p :- а, !, b.
р :- с.
Декларативный смысл станет теперь таким:
р <===> (а & b) U ( ~а & с)
Если предложения поменять местами
р :- с.
р :- а, !, b.
декларативный смысл станет таким:
р <===> с U ( а & b)
Важным моментом здесь является то, что при использовании отсечения требуется уделять больше внимания процедурным аспектам. К несчастью, эта дополнительная трудность повышает вероятность ошибок программирования.
В наших примерах из предыдущего раздела мы видели, что удаление отсечений из программы может привести к изменению ее декларативного смысла. Но были также в такие случаи, когда отсечение на него не влияло. Использование отсечений последнего типа требует меньшей осторожности, и поэтому такие отсечения иногда называют "зелеными отсечениями". С точки зрения наглядности программы такие отсечения "невинны" и их использование вполне приемлемо. При чтении программы их можно просто игнорировать.
Напротив, отсечения, влияющие на декларативный смысл, называются "красными". Красные отсечения -это такие отсечения, которые делают программу трудной для понимания, и их нужно применять с особой осторожностью.
Отсечение часто используется в комбинации со специальной целью fail. В частности, мы определили отрицание какой-либо цели (not), как ее неуспех. Определенное таким образом отрицание представляет собой просто особый (более ограниченный) вид отсечения. Из соображений ясности программ мы предпочтем пользоваться not вместо комбинации отсечение - неуспех (всюду, где возможно), поскольку отрицание является понятием более высокого уровня, чем отсечение - неуспех.