
- •Предисловие
- •Глава 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. Установка контрольных точек
- •Возможные действия в контрольной точке
- •Включение и выключение режима контрольных точек
- •Необязательные параметры режима контрольных точек
- •Предикаты для работы с контрольными точками
- •Режимы, связанные с контрольными точками
- •Основные отладочные предикаты
- •Статистическая информация
7.6. Вопросы эффективности
Существует немало способов повысить эффективность программ на Прологе. Все они приведены ниже.
1) Как можно шире используйте механизм унификации. Например, вместо того, чтобы писать процедуру сопоставить:
сопоставить (X,Y) :- Х=1,Y=фред.
сопоставить () :- Х=2,Y=джо.
сопоставить () :- Х=З.Y=джим.
лучше определить факты:
сопоставить (1,фред).
сопоставить (2,джо).
сопоставить (3,джим).
Такое решение будет особенно эффективно в тех реализациях Пролога, где сопоставление по главному функтору дополнено сопоставлением по первому аргументу целевого утверждения в случае, если аргумент является простым термом (например, целым числом или атомом).
2) Сокращайте число избыточных утверждений насколько это возможно, однако не в ущерб ясности понимания программы. Покажем это на примере:
выход_целое (N) :-
получить_число(N),
write (N).
получить_число(N) :-
read(N),
integer(N).
лучше написать так:
read(N),
integer(N),
write(N).
3) Упорядочите утверждения в процедуре таким образом, чтобы сократить число неудачных обращений.
4) Убедитесь, что в процедуре определены граничные условия. Это позволит избежать ненужных обращений и возможных циклов в программе.
5) Используйте возможность отсечения (см.гл. 8) для устранения ненужных возвратов и сокращения альтернативных путей в программе, если заранее известно, что тот или иной путь не приведет к решению.
Глава 8 Отсечение
В гл. 7 мы описали, как работает механизм возврата Пролога в том случае, когда одна из целей в конъюнкции целей терпит неудачу. Иногда возникает необходимость отключить механизм возврата. В данной главе определяется целевое утверждение, позволяющее управлять работой механизма возврата.
8.1. Почему используют отсечение?
Начнем с примера, в котором следует отключить механизм возврата. Рассмотрим следующую формулировку отношения являться дедом:
Х является дедом Y, если некоторый
Z является отцом Y и Х является отцом Z.
На Прологе данное описание примет вид:
дед(Х,Y) :- Отец(Z,Y), Отец(X,Z).
Предположим, что имеются факты:
отец(м-р_a, м-р_b).
отец(м-р_c, м-р_d).
………
………
………
отец,(м-p_w, м-p_x).
отец(м-p_y, м-p_z).
Пытаясь ответить на запрос
?-дед(Х,м-р_b).
Пролог заменяет его на целевые утверждения в теле утверждения дед (так как голова утверждения связывается с выданным запросом):
отец (Z,м-p_b), отец (X,Z).
Пролог доказывает первую из целей, связывая ее с первым фактом отец и конкретизируя переменную Z значением м-р_а.
Теперь Пролог пробует доказать вторую цель при значении Z, равном м-р_а, т.е. отец(Х,м-р_а), но терпит неудачу. В этот момент начинает работать механизм возврата Пролога и предпринимается попытка повторного доказательства первой цели, отец(Z,м-р_b). Пролог пытается выбрать другое утверждение отец для м-р_b. Конечно, он терпит неудачу, но все же впустую затрачивает время на поиск.
Для того, чтобы остановить работу механизма возврата Пролога после доказательства первой цели в теле утверждения дед, поместим после нее специальное целевое утверждение !, называемое отсечением:
дед(Х,Y) :- отец(Z,Y),!,отец(X,Z).
Учитывая данное определение, при доказательстве запроса
?-дед(Х,м-р_b).
Пролог связывает его с головой утверждения и затем пытается доказать цели в теле утверждения
отец (Z,м-p_b),!,отец (X,Z).
Как и раньше, первая из целей доказывается при
Z=м-р_а
Далее становится доказанным утверждение, осуществляющее управление механизмом возврата, - отсечение; оно всегда доказуемо. Теперь Пролог пробует доказать цель
отец(Х,м-р_а).
терпит неудачу и пытается осуществить возврат, но наталкивается на отсечение, которое прекращает работу механизма возврата.
Итак, доказательство цели-отсечения всегда заканчивается успешно, и после этого не могут быть передоказаны цели, стоящие в утверждении до отсечения, включая и головную цель.
Таким образом, в последовательности утверждений:
a :- !,b.
a :- c.
второе утверждение излишне, поскольку любой запрос:
?- a.
сопоставится с первым утверждением, после чего будет доказано отсечение и, если попытка доказать утверждение b окончится неудачей, то работа Пролога прекратится без перехода ко второму утверждению.