Состав рекурсивной процедуры

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

1) Нерекурсивную фразу, определяющую исходный вид процедуры, т. е. вид процедуры в момент прекращения рекурсии.

2) Рекурсивное правило. Первая подцель, располагающаяся в теле этого правила, вырабатывает новые значения аргументов. Далее размещается рекурсивная подцель, в которой используются новые значения аргументов.

Фраза (1) процедуры "предок" определяет исходный вид этой процедуры. Как только данная фраза станет истинной, дальнейшая рекурсия прекратится. Фраза (2) — это рекурсивное правило. При каждом вызове данное правило поднимается на одно поколение вверх. Подцель «родитель (В, Б)», входящая в тело этого правила, вырабатывает значение переменной В. Затем располагается рекурсивная подцель «предок (А, В)», в которой используется этот новый аргумент.

Неработоспособная версия процедуры "предок"

Ниже приводится версия процедуры "предок", которая не будет работать при использовании большинства интерпретаторов языка Пролог. Эта процедура, названная "нпредок", отличается от процедуры "предок" только порядком следования подцелей в теле фразы (2)

нпредок (А, Б): - % (1)

родитель (А, Б).

нпредок (А, Б) :- % (2)

нпредок (А, В),

родитель (В, Б).

С декларативных позиций смысл этой процедуры идентичен смыслу процедуры "предок". Но при процедурной трактовке смысл процедур "предок" и "нпредок" существенно различается. В процедуре "предок" подцель « родитель (В, Б)» рекурсивного правила вырабатывает новое значение переменной В, которое затем используется в рекурсивной подцели «предок (А, В)». С другой стороны, в процедуре "нпредок" переменная В не конкретизирована в момент обработки рекурсивной подцели «нпредок (А, В)». На практике это означает, что когда интерпретатор будет пытаться выполнить запрос к процедуре "нпредок", то вначале он отыщет правильные ответы, а затем будет выполнять рекурсивные действия вплоть до исчерпания доступного объема памяти:

|?— нпредок (жб, П),

П =лц;

П=гг;

П = вм;

предупреждение: исчерпана стековая память.

Действия интерпретатора, пытающегося отыскать четвертый ответ на данный запрос, иллюстрируются деревом доказательства, представленным на рис. 1. 3.

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

Рекурсивная версия процедуры "можно_путешествовать"

Метод рекурсии, использованный при составлении процедуры "предок", можно с успехом применить и для написания процедуры "можно_путешествовать". В процедуре "можно_путешествовать4", текст которой приведен ниже, определяется отношение между двумя городами. Это отношение будет соблюдаться в том случае, если можно совершить путешествие из одного города в другой через любое количество промежуточных пунктов. Процедура "можно_путешествовать4" является рекурсивной. Она очень похожа на процедуру "предок". Предположим, что существует упомянутая ранее база данных "путешествие/4". Тогда отношение, определяемое процедурой "можно_путешествовать4", будет соблюдаться в тех же случаях, что и для процедуры "можно_путешествовать2", а также и в ряде других ситуаций (скажем, для поездки между Бирлингтоном и Портлендом через Нью-Йорк и Бостон).

можно_путешествовать4 (ГородА, ГородБ): - % (1)

путешествие (_, ГородА, ГородБ, _).

можно_путешествовать4 (ГородА, ГородБ): - % (2)

путешествие (_, ГородА, ГородВ, _),

можно_путешествовать4 (ГородВ, ГородБ).

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

Соседние файлы в папке Гл.0,1,2,3,4,5,Предисловие