Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Spec_Mov_3k_4k_Lect.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
1.46 Mб
Скачать

Управление формированием вывода Отсечение

Турбо-Пролог в случае, когда есть больше одного факта или правила для текущей цели, отмечает текущее состояние построения вывода точкой решения, чтобы можно было впоследствии вернуться и продолжить поиск других вариантов формирования вывода. Отсечение ! (cut) является встроенным предикатом. Его действие заключается в том, что для всех целей между головой правила и предикатом ! точка решения не сохраняется.

Пример

Рассмотрим пример общего вида.

primer:- a, b, c, !, d, e, f.

primer.

В данном примере предикаты primer, a, b, c, d, e, f – предикаты с переменными.

Если b согласовано по ходу построения вывода, а c нет, то возможен возврат к другому варианту выбора решений для a, b или primer. Но как только с согласовано, и, таким образом, был согласован и предикат !, то дальнейший возврат к выбору других вариантов решений для c, b, a или primer невозможен. Если цель d не может быть согласована в дальнейшем, то вся задача заканчивается отказом. (not).

Пример

Определение целой части от деления некоторого числа из последовательности 0, 1, 2, … на заданное число. Результатом должно быть наименьшее целое большее, чем некоторое заданное пороговое значение. Оба числа,- делитель и верхняя граница указываются в диалоге.

domains

num = integer

predicates

razdelit(num, num,num)

celoje(num)

clauses

celoje(0). /* генерация чисел */

celoje(X):- celoje(Y), X = Y + 1.

razdelit(_, 0, _):- !, write(“нельзя делить на 0!”), exit.

razdelit(N1, N2, Rez):- celoje(Rez), Prod = (Rez + 1)*N2, Prod > N1,

Prod2 = Rez * N2, Prod2 <= N1, !.

goal

write(“Введите делитель:”), readint(Mod), nl,

write(“Введите верхнюю границу:”), readint(Gr), nl

celoje(N), /* формирование последовательности */

razdelit(N, Mod, X),

X > Gr, write(“ответ:”, X).

Если бы отсечение не располагалось в конце определения предиката razdelit, то в случае ложности условия X > Gr произошел бы возврат к цели celoje(Rez) в определении, что повлекло бы зацикливание программы. Отсечка обеспечивает возврат к цели celoje(N) в конъюнктивном вопросе и генерацию следующего целого из последовательности чисел.

«Зеленые» и «Красные» отсечения

Аккуратное, правильное использование отсечений повышает эффективность программ без нарушения их ясности и изменения смысла. Различать «красные» и «зеленые» отсечения предложил ван Эмден (van Emden M. Red and green cuts. “Logic Programming Newsletter. N2, 1982”). Отсечения, влияющие на декларативный смысл пронраммы, называются «красными», а не влияющие – «зелеными».

Примеры

p:- a, b, c.

p:- d, e.

Декларативный смысл этой программы p  (a & b & c) v (d & e). Если правила поменять местами, то смысл программы не изменится.

p:- a, b, !, c.

p:- d, e.

Декларативный смысл этой программы p  (a & b & c) v (Øa & d & e) v (a & Øb & d & e) v (Øa & Øb & d & e). Если правила поменять местами, то программа будет иметь другой декларативный смысл: p  (d & e) v (a & b & c). Т.о., при использовании отсечений в ряде случаев смысл программы изменяется.

«Зеленые» отсечения. Размещение или удаление отсечения не влияет на смысл программы. Основное назначение – удаление ненужных ветвей вывода, а это означает сокращение времени выполнения программы (сокращается и объем программы, поскольку во время выполнения точки решений не создаются).

Пример

Вычисления минимума.

predicates

minim(real, real, real)

clauses

minim(X, Y, X):- X <= Y, !.

minim(X, Y, Y):- X > Y, !.

Ясно, что если выполняется X <= Y, то альтернативная проверка не X > Y требуется. Значит точка возврата не нужна и можно применить отсечение.

Пример

Слияние упорядоченных списков целых чисел Xs и Ys, и получениеупорядоченного списка Zs: merge(Xs, Ys, Zs).

damains

lst = integer*

predicates

merge(lst, lst, lst)

clauses

merge([], Ys, Ys):- !.

merge(Xs, [], Xs):- !.

merge([X | Xs], [Y | Ys], [X | Zs]):- X < Y, !, merge(Xs, [Y | Ys], Zs).

merge([X | Xs], [Y | Ys], [X | Zs]):- X = Y, !, merge(Xs, Ys, Zs).

merge([X | Xs], [Y | Ys], [X | Zs]):- X > Y, !, merge([X | Xs], Ys, Zs).

Программа будет правильной и без отсечений.

«Красные» отсечения. Удаление отсечения изменяет декларативный смысл программы, т.е. множество выводимых целей.

Пример

predicates

minim(real, real, real)

clauses

minim(X, Y, Z):- X <= Y, !, Z = X.

minim(X, Y, Y).

Если удалить отсечение, то выполнима будет цель minim(2, 5, 5). Если отсечение присутствует, то эта цель не выполнима, т.к. отсечение отменяет точку возврата для minim и альтернатива не рассматривается.

Обычное применение «красных» отсечений – удаление явных условий, как в вышеприведенном примере. Условие X > Y не требуется.

Пример

Удаление всех вхождений элемента X в список Xs: delete(X, Xs, Ys). Результат в Ys.

domains

sm = symbol

lst = sm*

predicates

delete(sm, lst, lst)

clauses

delete(X, [], []).

delete(X, [X | Ys], Zs):- !, delete(X, Ys, Zs).

delete(X, [Y | Ys], [Y | Zs]):- delete(X, Ys, Zs).

Удаление отсечения дает возможность для реализации, напрмер, следующего целевого утверждения: delete(1, [2, 1], [2, 1]), и других утверждений подобного типа, т.е. приведет к получению некорректной программы.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]