Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Voprosy_k_ekzamenu_po_FLP_SP21_22.doc
Скачиваний:
13
Добавлен:
15.03.2015
Размер:
330.75 Кб
Скачать

Листинг 5.9. Бесконечная рекурсия (хвостовая рекурсия)

predicates

count(real)

clauses

count(N):-

write(N),nl,

NewN=N+1,

count(NewN).

Эта процедура count(N) –является хвостовой рекурсией, которая вызывает себя без резервирования нового стекового фрейма, и потому не истощает запас памяти, в конечном итоге произойдет целочисленное переполнение, но остановки из-за нехватки памяти не будет.

Введение условия, ограничивающего бесконечную рекурсию:

Листинг 5.10.Ограничение бесконечной рекурсии

predicates

count(integer)

check(integerl)

clauses

count(N):-

write(N),nl,

NewN=N+1,

сheck(NewN),

count(NewN).

check(Z):-Z<5.

goal

clearwindow,

write(“result:”),nl,

count(1).

Замечание:

В Прологе мы не можем изменить значение переменной, поэтому создаем новую переменную NewN.

  1. Отрицание как недостижение цели. Предикат not. Предположения о замкнутости и открытости мира.

  1. Влияние предиката cut на составную цель и процедуру. Подтвердить конкретными примерами

Влияние предиката cut на составную цель

Пусть cut является одной из подцелей составной цели.

После того как компилятор пройдет предикат cut, он больше не сможет вернуться назад к подцелям, стоящим перед этим предикатом. И все значения переменных, расположенных слева от предиката cut, которые они получили в процессе унификации будут заморожены.

Пример:

Goal: a(X), b(y), !, c(X,y,z).

При выполнении этой цели компилятор пройдет через предикат cut только в том случае, если и подцель a(X), и подцель b(Y) окажутся уже успешными.

После того как предикат cut окажется обработан, компилятор не сможет вернуться назад для повторного рассмотрения подцелей “a” и “b”, если подцель”c” потерпит неудачу при текущем значении переменных X и Y.

Эта составная цель не обладает декларативным смыслом. Но с процедурной точки зрения ее можно прочесть так:

взять значение переменной X из подцели “a” и значение переменной Y из подцели “b” а затем выполнить подцель c(X,Y,Z).

5.2.2.Влияние предиката cut на процедуру

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

Листинг 5.2. Программа, в которой нет предиката cut

predicates

a(symbol)

d(symbol)

clauses

a(“1”):-

write(“один”).

a(X):-

d(X),

write(“два”).

a(“3”):-

write(“три”).

d(“2a”).

d(“2b”).

Возьмем цель goal: a(N).

В соответствии с представленной схемой получаем все четыре решения:

1) один, N=1;

2) два, N=2a;

3) два, N=2b;

4) три,N=3.

Изменим программу, вставим предикат cut между двумя подцелями правила a(X) и проанализируем, что произойдет в результате выполнения программы, которая будет запущена той же самой целью goal:a{N).

Листинг 5.3.Программа с предикатом cut

predicates

a(symbol)

d(symbol)

clauses

a(“1”):-

write(“один”).

a(X):-

d(X),

!,

write(“два”).

a(“3”):-

write(“три”).

d(“2a”).

d(“2b”).

В результате получим только два ответа:

1) один, N=1;

2) два, N=2.

3) система ‘заморозила’ все альтернативы, стоящие до cut,и лишила тем самым возможности вернуться к подцели d(X),чтобы воспользоваться веткой d(“2b”).

4) отбросила все утверждения процедуры a , стоящие после утверждения с предикатом cut.(то есть перейти к утверждению a(“3”) –невозможно)

Использование предиката cut позволило отбросить части пространства поиска.

Рассмотрим еще один пример.

  1. Составные объекты и альтернативные домены. Предикатная и доменная структурные диаграммы.

  2. Компоновка данных в список