Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Отсечение




Предикат! (без параметров) задает отсечением. Предикат отсечения удовлетворяется всегда, однако обладает побочным эффектом, который состоит в том, что повторное удовлетворение всех ранее удовлетворенных (т. е. находящихся левее) целей становятся невозможным. На последующие цели (т. е. находящиеся правее) цели отсечение влияния не оказывает. Одним из следствий отсечения является то, что значения всех переменных, связанных к моменту отсечения «фиксируются» и не могут быть в последующем изменены. Рассмотри примеры:

?- member(X, [1, 2, 3]). % X = 1; X = 2; X = 3.

?- member(X, [1, 2, 3]),!. % X = 1.

?-!, member(X, [1, 2, 3]). % X = 1; X = 2; X = 3.

?- member(X, [a, b]), member(Y, [c, d]). % X = a, Y = c; X = a, Y = d; X = b, Y = c; X = b, Y = d.

?- member(X, [a, b]),!, member(Y, [c, d]). % X = a, Y = c; X = a, Y = d.

?- member(X, [a, b]), member(Y, [c, d]),!. % X = a, Y = c.

?- member(X, [2, 1, 3]), member(Y, [2, 1, 3]), X > Y. % X = 2, Y = 1; X = 3, Y = 2; X = 3, Y = 1; false.

?- member(X, [2, 1, 3]), member(Y, [2, 1, 3]),!, X > Y. % false.

?- member(X, [2, 1, 3]),!, member(Y, [2, 1, 3]), X > Y. % X = 2, Y = 1; false.

likes(alice, john).

likes(mary, john).

likes(john, mary).

?- likes(X, Y), likes(Y, X). % X = mary, Y = john; X = john, Y = mary.

?- likes(X, Y), likes(Y, X),!. % X = mary, Y = john.

?- likes(X, Y),!, likes(Y, X). % false.

Областью действия отсечения является запрос (конъюнкция целей); поэтому отсечение, встретившееся в правой части правила не воздействует на цели, предшествовавшие запуску этого правила. Однако если предикат имеет несколько предложений, то отсечение воздействует на все предложения. Например:

gcd(A, 0, C):-!, C = A.

gcd(A, B, C):- D is A mod B, gcd(B, D, C).

?- gcd(4, 6, 2). % true.

?- gcd(4, 6, 1). % false.

?- gcd(4, 6, N). % N = 2.

?- N = [4, 6, 3, 9], member(X, N), member(Y, N), gcd(X, Y, 1).

N = [4, 6, 3, 9], X = 4, Y = 3; N = [4, 6, 3, 9], X = 4, Y = 9;

N = [4, 6, 3, 9], X = 3, Y = 4; N = [4, 6, 3, 9], X = 9, Y = 4; false.

?- N = [4, 6, 3, 9], member(X, N), member(Y, N), gcd(X, Y, 1),!.

N = [4, 6, 3, 9], X = 4, Y = 3.

Правильное положение отсечения важно.

gcd1(A, 0, C):- A = C,!.

gcd1(A, B, C):- D is A mod B, gcd1(B, D, C).

?- gcd1(4, 6, 1). % ERROR: mod/2: Arithmetic: evaluation error: `zero_divisor'

Можно выделить три наиболее частых случая использования отсечения:

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

contains(X, [X | _]):-!.

contains(X, [_ | T]):- contains(X, T).

?- contains(b, [a, b, c]). % true.

?- contains(b, [a, b, b, b, c]). % true.

?- contains(b, [a, c]). % false.

?- contains(X, [a, b, c]). % X = a.

?- contains(X, [a, b, c]), X = b. % false.

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

unique([]).

unique([H | T]):- contains(H, T),!, fail.

unique([_ | T]):- unique(T).

?- unique([a, b, c]). % true.

?- unique([a, b, b]). % false.

?- unique([a, b, X]). % false.

Если отсечение опустить, то результат будет неверным:

unique1([]).

unique1([H | T]):- contains(H, T), fail.

unique1([_ | T]):- unique1(T).

?- unique1([a, b, b]). % true.

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

count(_, [], 0).

count(X, [X | T], N):-!, count(X, T, M), succ(M, N).

count(X, [_ | T], N):- count(X, T, N).

?- count(b, [a, b, c], N). % N = 1; false.

?- count(b, [a, b, b, c, b], N). % N = 3; false.

?- count(b, [a, c], N). % N = 0; false.

Если отсечение опустить, то результат будет неверным:

count1(_, [], 0).

count1(X, [X | T], N):- count1(X, T, M), succ(M, N).

count1(X, [_ | T], N):- count1(X, T, N).

?- count1(b, [a, b, b, c], N). % N = 2; N = 1; N = 1; N = 0; false.

Разное





Поделиться с друзьями:


Дата добавления: 2015-10-01; Мы поможем в написании ваших работ!; просмотров: 402 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Победа - это еще не все, все - это постоянное желание побеждать. © Винс Ломбарди
==> читать все изречения...

2213 - | 2048 -


© 2015-2024 lektsii.org - Контакты - Последнее добавление

Ген: 0.011 с.