
- •Предисловие
- •Глава 1 Введение в Пролог
- •Глава 2 Синтаксис и унификация
- •2.1. Синтаксис термы
- •Константы
- •Переменные
- •Область действия переменных
- •Сложные термы, или структуры
- •Синтаксис операторов
- •Синтаксис списков
- •Синтаксис строк
- •Утверждения
- •Запросы
- •Ввод программ
- •2.2 Унификация
- •Глава 3 Арифметические выражения
- •3.1. Введение
- •3.2. Арифметические выражения
- •3.3. Арифметические операторы
- •3.4. Вычисление арифметических выражений
- •3.5. Сравнение результатов арифметических выражений
- •Глава 4 Рекурсия
- •4.1. Стратегия «разделяй и властвуй»
- •Пример 4.1.1
- •Фаза разбиения
- •Фаза решения задачи
- •4.2. Восходящая стратегия
- •4.3. Рекурсия и эффективность
- •Пример 4.3.2
- •Глава 5 Структуры данных
- •5.1. Списки списковая форма записи
- •А на запрос
- •Некоторые стандартные целевые утверждения для обработки списков
- •5.2. Бинарные деревья представление бинарных деревьев
- •Бинарное дерево на рис.5.2.1 имеет левое поддерево
- •Представление множеств с помощью бинарных деревьев
- •Будем называть линейным представление такого вида, как на рис.5.2.3, и сбалансированным - такое, как на рис.5.2.2.
- •Левому поддереву соответствует отсортированный список
- •Глава 6 Операторы
- •6.1. Операторы и структуры синтаксис операторов
- •Свойства операторов
- •6.2. Позиция операторов
- •6.3. Приоритет операторов
- •6.4. Ассоциативность операторов
- •6.5. Спецификаторы
- •6.6. Операторы объявления
- •6.7. Пример: вычисление многочленов
- •6.8. Системные операторы
- •Глава 7 Механизм возврата и процедурная семантика
- •7.1. Механизм возврата
- •7.2. Пример: задача поиска пути в лабиринте
- •Целевое утверждение не удается согласовать с первым утверждением
- •Если мы введем
- •Если затем мы введем
- •7.3. Обработка фактов с помощью механизма возврата
- •7.4. Предикат repeat
- •7.5. Декларативная и процедурная семантики
- •Характеристики процедуры
- •7.6. Вопросы эффективности
- •Глава 8 Отсечение
- •8.1. Почему используют отсечение?
- •8.2. Использование отсечения
- •Выдав запрос
- •Обратившись к системе с запросом
- •8.3. Ловушки отсечения
- •Глава 9 Встроенные предикаты
- •9.1. Встроенные предикаты
- •9.2. Обновление базы данных Пролога
- •Добавление и удаление утверждений
- •Считывание утверждений в базу данных
- •Предикаты сохранения и восстановления
- •9.3. Особенности ввода и вывода чтение символов
- •Запись символов
- •Считывание термов Предикаты
- •Запись термов
- •9.4. Обработка файлов
- •Редактирование программ на прологе
- •Распечатка предикатов
- •Глава 10 Модули. Пример разработки системы
- •10.1. Модули
- •Пример 10.1.1
- •10.2. Пример разработки системы: деревья решений
- •Описание дерева решений
- •Разработка системы
- •Целевое утверждение
- •Глава 11 Отладка
- •11.1. Трассировка
- •Включение и выключение механизма трассировки
- •Необязательные параметры трассировки
- •Предикаты трассировки
- •Режимы трассировки
- •11.2. Установка контрольных точек
- •Возможные действия в контрольной точке
- •Включение и выключение режима контрольных точек
- •Необязательные параметры режима контрольных точек
- •Предикаты для работы с контрольными точками
- •Режимы, связанные с контрольными точками
- •Основные отладочные предикаты
- •Статистическая информация
Пример 4.1.1
Рассмотрим способы определения n-го терма в последовательности:
1, 1, 2, 6, 24, 120, 720,...
Первый вариант описания таков: нулевой терм равен 1, первый терм получается при умножении 1*1, второй терм - при умножении 1*1*2, третий - при умножении 1*1*2*3, и в общем случае, n-й терм получается при умножении 1*1*2*3*... *n.
С другой стороны, нулевой терм есть 1, а n-й терм есть (n - 1)-й терм, умноженный на n. Данное определение является рекурсивным, поскольку разбивает задачу нахождения n-го терма на задачи нахождения сначала (n-1)-го терма и умножения его затем на n.
Ясно, что оба определения эквивалентны, ибо, например, задача вычисления третьего терма с помощью рекурсивного определения сводится к задаче вычисления второго терма и умножения его на 3. Задача вычисления второго терма сводится к задаче вычисления нулевого терма и умножения его на 1. Поскольку нулевой терм равен 1, вычислим первый терм - он будет равен 1. Это в свою очередь позволяет нам вычислить второй терм - он равняется 2, а затем - третий терм, равный 6.
Для обозначения факта, что N-й член последовательности равен V, воспользуемся предикатом посл(N,V). Рекурсивное определение выражается следующими утверждениями Пролога:
/* ГРАНИЧНОЕ УСЛОВИЕ - нулевой терм равен 1
посл(0,1).
/* РЕКУРСИВНОЕ УСЛОВИЕ - если (N-1)-й терм равен U, то
/* N-й терм равен U * N
посл(N,V) :-
M is N-1,
посл(М,U),
V is U * N.
Ответом на вопрос
?-посл(3,Z).
будет
Z=6
другие решения (да/нет) ? нет
Заметим, что если на вопрос Пролог-системы мы ответим «да» вместо «нет», то система попадает в бесконечный цикл. В гл. 8 мы покажем, как избежать такой ситуации.
Для того чтобы представить, каким образом Пролог находит ответ, рассмотрим вопрос
?-посл(3,Х).
и опишем работу Пролога на двух этапах: разбиения и решения задачи.
Фаза разбиения
Первое обращение. Пролог пытается удовлетворить запрос посл(3,Х), используя первое утверждение процедуры описания последовательности посл(0,1). Поскольку первая компонента терма (0) не сопоставляется с первой компонентой запроса (3), попытка заканчивается неудачей.
Теперь Пролог пытается использовать второе утверждение, описывающее последовательность. На этот раз голова второго утверждения посл(N,V) сопоставляется с запросом посл(3,Х), при этом N получает значение 3, а V связывается с X. Пролог переходит к доказательству целей в теле утверждения:
/*N=3
/*V=X
M is 3 - 1,
посл(М,U),
X is U * 3. /* откладывается
Первое целевое утверждение согласуется при М = 2. Второе целевое утверждение посл(2,U) приводит ко второму рекурсивному обращению. Пролог пытается согласовать третье целевое утверждение только при условии, что согласовано второе. Поэтому третье целевое утверждение откладывается.
Второе обращение. Для того чтобы согласовать посл(2,U), Пролог пытается сопоставить посл(2,U) с первым утверждением процедуры посл(0,1), но неудачно, поскольку первые компоненты термов не сопоставляются.
Однако удается сопоставить посл(2,U) с головой второго утверждения посл(N2,V2) при N2, равной 2, и V2, равной U. Теперь Пролог пытается согласовать тело утверждения:
/* N2=2
/* V2=U
M2 is 2 - 1,
посл(М2,U2),
U is U2 * 2. /* откладывается
Мы использовали то же утверждение, что и в первом обращении, но с меньшим аргументом N2.
Чтобы отличить второе обращение к утверждению от первого, присвоим переменным индекс 2. В общем случае индекс n у переменной показывает, что она применяется при n-м обращении. Переменные при первом обращении записаны без индексов.
Первое из целевых утверждений согласуется при M2, равной 1. Второе целевое утверждение приводит к третьему обращению, а третье целевое утверждение откладывается.
Третье обращение. Чтобы согласовать посл(1,U2), Пролог пытается сопоставить его с первым утверждением определения посл(0,1), но неудачно. Однако удается сопоставить посл(1,U2) с головой второго утверждения, причем N3 получает значение 1, а V3 связывается с U2. Следовательно, теперь надо согласовать цели:
/* N3=1
/* V3=U2
M3 is 1 - 1,
посл(МЗ,UЗ),
U2 is U3 * 1. /* откладывается
Первое целевое утверждение согласуется при МЗ, равной 0.
Второе целевое утверждение посл(0,U3) Пролог пытается согласовать, сопоставляя его с первым утверждением определения. На этот раз два терма успешно сопоставляются при U3, равной 1.
Редукция задачи завершена, и граничные условия позволили решить последнюю задачу. Теперь Пролог возвращается к отложенным целевым утверждениям и пытается согласовать самое последнее из них. Если удается это сделать, Пролог переходит к согласованию предпоследнего отложенного целевого утверждения и так далее, пока не будет согласовано первое. В данной главе мы предполагаем, что все отложенные целевые утверждения успешно согласуются. В гл.7 показано, что происходит, если Пролог не может согласовать целевое утверждение.