- •Пролог тіліне жалпы шолу
- •Бағдарлама мысалы: туыстық қатынастар
- •1.2. Ережелер көмегімен мысал – бағдарламаны кеңейту
- •1.3. Ереженің рекурсивті анықтамасы
- •2. Пролог – бағдарламаның синтаксисі және семантикасы
- •2.1. Айнымалылар
- •2.2. Құрылымдар
- •2.3. Салыстырулар
- •2.5. Фактілер мен ережелер
- •2.6. Бағдарламаның орындалуы алгоритмі
- •2.7. Пролог – бағдарламаның декларативті мағынасы (мәні)
- •2.8. Пролог – бағдарламаның құрылымы
- •Рекурсивті есептеулер. Арифметикалық өрнектер
- •3.1. Есептеулерді басқару
- •Рекурсивті есептеулер
- •Арифметикалық өрнектер
- •Тізімдер. Стандартты предикаттар
- •4.1. Тізімдер
- •4.2. Тізімдермен операциялар жүргізу
- •1. Операция: тізімге қатыстылығы (мүшелігі).
- •Операция: жалғастыру (конкатенация).
- •4.3. Стандартты предикаттар
- •Тапсырма 2
- •Қорытынды
- •Әдебиеттер
- •3. Язык Пролог в задачах и примрах
- •3.1. Программирование с помощью фактов и правил
- •3.1.2. Первая формулировка задачи поиска в пространстве состояний 51 ад
- •3.1.3. Реализация на Прологе простой вопросно-ответной системы
- •3.2. Рекурсии
- •Упражнения
- •3.3. Программирование циклических процессов
- •3.4. Работа со списками
- •3.4.1. Описание списков в программе
- •3.4.11. Примеры использования списков
- •Упражнения
- •3.5. Виды рекурсии
- •3.6. Поиск в пространстве состояний
- •Упражнения
- •3.6.0 Использование структур
- •Упражнения
- •3.7. Динамическая база данных
- •3.7.1. Использование стандартных предикатов динамической базы данных
- •Упражнения
- •3.8. Средства управления
- •3.9. Представление множеств двоичными деревьями
- •3.9. Программы классификации
- •3.9.1. Программа классификации с обратной цепочкой рассуждений
- •3.9.2. Программы классификации с прямой цепочкой рассуждений.
- •3.9. Обработка текстов
- •Упражнения
- •3.10. Примеры
3.2. Рекурсии
В
Прологе заложено мощное средство,
позволяющее определять некоторые
отношения, используя эти же отношения,
и называемое рекурсией.
Без рекурсии невозможно решать задачи
сколько-нибудь ощутимой сложности.
Рекурсия в Прологе используется для
определения как структур данных (списков,
деревьев, графов), так и процедур.
Сочетание рекурсивных структур данных
с рекурсивными же алгоритмами вычислений
позволяет компактно и красиво описывать
задачу поиска в пространстве состояний.
Описание рекурсивных структур увидим
позже, сейчас остановимся на рекурсивных
правилах. Подробнее, правило
является рекурсивным,
если оно вызывает само себя в виде
подцели, содержащейся в теле по
крайней мере одного из ее утверждений.
Вспомним принципы программирования
рекурсивной процедуры: рекурсия содержит
рекурсивный вызов и обязательно проверку
условия, обеспечивающего выход из
рекурсии. Последовательность рекурсивных
вызовов продолжается до тех пор, пока
не встретится ограничение вычислений.
Эта часть процесса называется прямым
прохождением рекурсии, при этом параметры
процедуры заносятся в стек. После
достижения граничного условия начинается
обратное прохождение рекурсии, параметры
извлекаются из стека.
Рассмотрим
простой п
ример
рекурсивных вычислений. Пусть имеется
пирамида, построенная из блоков.
Последовательность расположения блоков
можно задать предикатом on («на»):
on( c,
b ).
on( b, a ).
Определим
отношение above («выше»),
проверяющее, например, истинно ли то,
что блок с выше
блока а.
Поскольку мы хотим задать универсальное
отношение, рассчитанное на пирамиду
блоков любой высоты, это отношение будет
уже правилом, т.е. содержать переменные.
Все отношение можно выразить с помощью
двух правил. Первое правило будет верно
для блоков, расположенных непосредственно
один на другом (отношение on)
и его можно сформулировать так:
Для
всех X и Y X будет
выше Y,
если X находится
на Y.
Второе
правило сложнее, поскольку рассчитано
на пирамиду блоков:
Для
всех X и YX будет
выше Y,
если существует такой промежуточный
блок Z,
что X находится
на Z и Z выше Y.
В
синтаксисе Пролога эти два правила
определят рекурсивный предикат:
above( X,
Y ) :- on( X, Y ).
% Нерекурсивное правило
above( X,
Y ) :- on( X, Z ), above( Z, Y ). % Правило с
рекурсией
Ключевым моментом в данной
формулировке было использование самого
отношения above в его
определении.
Любое
рекурсивное определение содержит, по
крайней мере, одно нерекурсивное правило
и одно или несколько правил с рекурсией.
В большинстве случаев имеется по одному
правилу каждого типа. Нерекурсивное
правило обеспечивает выход из вычислений
и таким образом, предотвращает
зацикливание. В нашем примере прежде
всего проверятся, найдется ли такой
блок X,
что он расположен непосредственно
на Y (нерекурсивное
правило). Если найдется, вычисления
заканчиваются.
Проследим выполнение
рекурсивной процедуры. Соберем все
факты и правила вместе и для удобства
пронумеруем их. Таким образом, полное
пространство поиска следующее:
on( c,
b ).
(1)
on( b, a
). (2)
above(
X, Y ) :- on( X, Y ).
(3)
above(
X, Y ) :- on( X, Z ),
(4)
above(
Z, Y ).
Goal
above( c,
a ).
Вычисление начинается от
цели above(c,
a).
Из всех четырех правил этой цели можно
сопоставить только правила (3) и (4), из
которых подойдет только последнее,
поскольку в базе фактов нет факта on(c,
a).
Используя правило (4), получаем конкретизации
переменных X=a, Y=c. Таким
образом, вместо прежней цели возникает
конъюнкция новых целей: on(a,
Z),above(Z, c). Эти
подцели удовлетворяются последовательно.
Сначала выполняется первая цель: on(a,
Z).Эта
цель сопоставляется с одним из фактов,
в результате переменная Z унифицируется
константой: Z=b.
Дальше выполняется вторая подцель above(Z,
c),
но поскольку к этому моменту переменная Z уже
конкретизирована, цель
переписывается: above(b,
c).
Опять среди предложений программы
(1)-(4) отыскивается подходящее сопоставление,
выполняется унификация переменных.
Процесс продолжается до сопоставления
идентичных фактов. Полное дерево вывода
приведено на рис.
Рис.
Дерево вывода для цели above(c,a).
Другим примером рекурсивных вычислений является известный алгоритм вычисления факториала. Факториал числа N определяется согласно алгоритму:
1!=1
N!=N*(N-1)!
Hа Прологе эта программа может иметь такой вид: Domains N, F = real % Вещественный тип имеет больший диапазон Predicates factorial( N, F ) Clauses factorial( 1, 1 ). % База рекурсии, ограничение вычислений factorial( N, R ):– N > 0, % Правило с рекурсией N1 = N - 1, factorial( N1, R1 ), R = R1 * N. Goal factorial( 8, F), write( F ). % Пример вычисления 8! При каждом вызове дизъюнкта factorial генерируются новые переменные, которые действуют всегда только на своем уровне вложенности, пока не встретится условие прекращения вычислений (базовое правило). Только после этого на обратном пути прохождения рекурсии определяются результаты, которые передаются наверх. Считается, что используется хвостовая рекурсия, если последнее условие в последнем правиле является рекурсивным. Такая рекурсия имеет преимущество перед нехвостовой рекурсией, так как позволяет ограничить рост стека и строго контролировать процесс возврата. По сути, хвостовая рекурсия - это итеративный процесс. В приведенном примере вычисления факториала рекурсия нехвостовая, а отношения above - хвостовая.
