
- •Глава 1. Введение в пролог
- •1. Декларативные и процедурные языки программирования
- •2. Пролог и логика предикатов. Внешние цели
- •3. Управление программой. Подцели. Механизм сопоставления
- •4. Внутренние подпрограммы унификации
- •Глава 2. Внутренние цели. Механизм возврата
- •1. Структура пролог-программы
- •2. Использование внутренних целей
- •3. Встроенный предикат fail
- •4. Сокращенные варианты внутренних запросов
- •5. Использование в запросах анонимных переменных
- •6. Механизм возврата
- •Глава 3. Типы данных и арифметика Turbo Prolog
- •1. Стандартные типы данных
- •2. Структуры, простые и составные
- •3. Структурные диаграммы
- •4. Использование в запросах анонимных переменных
- •5. Использование альтернативных доменов
- •6. Арифметика в Turbo Prolog
- •Глава 4. Предикат отсечения (!). Программирование альтернатив. Правила повтора
- •1. Повторения и возвраты
- •2. Отсечение (!)
- •3. Программирование альтернатив
- •4. Правило повтора
- •Глава 5. Методы организации рекурсии
- •1. Простая рекурсия
- •2. Метод обобщенного правила рекурсии
- •3. Граничное условие рекурсии. Нисходящая и восходящая рекурсии
- •4. Программа о подсчете числа точек
- •Глава 6. Списки
- •1. Основные понятия
- •2. Списки и турбо-пролог
- •3. Атрибуты списка
- •4. Внутреннее представление списков
- •5. Применение списков в программе
- •6. Метод разделения списка на голову и хвост
- •7. Поиск элемента в списке
- •8. Присоединение списка
- •9. Добавление и удаление элемента
- •10. Подсписок
- •11. Перестановки списка
- •Глава 7. Сортировка списков
- •1. Разделение списка на два
- •2. Сортировка списков методом вставки
- •3. Быстрая сортировка
- •4. Быстрая сортировка_1
- •5. Компоновка данных в список
- •Глава 8. Программирование алгоритмов с возвратом. Представление графов в turbo prolog
- •1. Задача о весах
- •2. Представление графов в turbo prolog
- •3. Поиск пути на неориентированном графе
- •4. Поиск гамильтоновых циклов
- •5. Поиск пути минимальной стоимости
- •Глава 9. Динамическая база данных
- •1. Турбо-пролог и реляционные базы данных
- •2. Описание предикатов динамических бд
- •3. Встроенные предикаты asserta, assertz, retract, retractall, save, consult
- •4. Создание динамической базы данных
- •5. Обсуждение проекта базы данных
- •6. Создание базы данных
- •7. Написание программных модулей
- •Глава 10. Глобальные переменные в turbo prolog
- •1. Модификация базы данных
- •2. Накопление результатов с помощью вынуждаемого возврата
- •3. Подсчет членов парторганизации
- •4. Поиск пути минимальной стоимости от a до z
- •Библиографический список
- •Оглавление
3. Встроенный предикат fail
Предикат fail вызывает неудачное завершение правила, в результате чего внутренние унификационные процедуры выполняют возврат в предыдущую подцель и пытаются найти для нее другое решение.
С помощью этого предиката можно заставить систему находить все решения и для внутренней цели.
Goal
sister(ann,X),write(“Ann — сестра “,X),
nl, fail
Дойдя до предиката fail, система будет осуществлять возврат к предикату sister и будет находить для Х новое значение. В конечном итоге цель так и не будет согласована, но при попытках ее доказать будут напечатаны все, для кого ann — сестра.
Для того, чтобы заставить систему выдавать еще и обоих родителей ann, запрос нужно составить так:
Goal
(sister(ann,X), write(”Ann- сестра ”,X), nl;
pearent(X,ann), write(X,” — родитель Ann”)),
fail
Или так:
Goal
sister(ann,X), write(”Ann-сестра ”,X),nl,fail;
pearent(X,ann), fail
4. Сокращенные варианты внутренних запросов
В предыдущих примерах запросы строились из цепочек взимосвязанных предикатов. В случае, когда какой-либо запрос нужно повторить несколько раз, разумно предусмотреть возможность не задавать всякий раз одни и те же условия. В Турбо-Прологе эта задача решается конструированием правил, не содержащих в себе данных, т.е. правил нулевой арности. Задача, таким образом, сводится к написанию сокращенного варианта запроса. Пояснить только что сказанное можно на следующем примере:
Goal
who_is_the_sister ,fail
who_is_the_sister:-
sister(X,Y),
write(X,”- сестра ”,Y),nl.
Для определения всех родственников девушки составим запрос:
Goal
family,fail
И следующие правила:
family:-
write(” Tell me girl, please ”),nl,
readln(X),
family_of_girl(X).
family_of_girl(Girl):- % сестры Girl
sister(X, Girl),
write(X,”- сестра”), nl.
family_of_girl(Girl):- % мать Girl
mother(X,Girl),
write(X,”- мать”),nl.
Аналогично составляются правила для определения братьев и отца.
При разработке программы такой способ записи цели более предпочтителен, так как он упрощает процедуру запросов.
Упражнение 2.1.
Модифицируйте программу «Родственники» из примера 1.2 главы 1 так, чтобы печатались все родственники девушки по имени Бэт.
5. Использование в запросах анонимных переменных
Пусть потребовалось узнать имена всех лиц, имеющих сестер, причем имена сестер нас не интересуют.
Goal
write(”Имеют сестер: ”),nl, sister(_,X),
write(X), nl, fail.
Знак подчеркивания обозначает анонимную переменную, чье значение нас не интересует. Если в одном предикате имеется несколько знаков подчеркивания, то каждый обозначает свою анонимную переменную, то есть все они различны.
6. Механизм возврата
Турбо-Пролог пытается вычислить цель при помощи сопоставления цели с утверждениями базы данных. Сопоставление выполняется СЛЕВА НАПРАВО, причем, в процессе доказательства основной цели, Турбо-Пролог сам генерирует подцели. Некоторые сопоставления подцелей с какими-то утверждениями, вероятно, будут неуспешными.
Поэтому Турбо-Прологу требуется способ запоминания точек, в которые он может вернуться, чтобы продолжить альтернативные попытки найти решение. Прежде чем выбрать один из возможных путей доказательства подцели, Турбо-Пролог фактически помещает в программу «указатель».
Указатель определяет точку, в которую может быть выполнен возврат, если текущая попытка будет неуспешной. По мере того, как Турбо-Пролог успешно заканчивает свои попытки вычисления подцелей слева направо, указатели возврата расставляются во всех точках, которые могут привести к альтернативному решению.
Если некоторая подцель оказывается неуспешной, то Турбо-Пролог возвращается влево и останавливается у ближайшего указателя возврата. С этой точки Турбо-Пролог начинает попытку найти другое решение для неуспешной цели.
До тех пор, пока следующая цель на данном уровне не будет успешной, Турбо-Пролог будет повторять возврат к ближайшему указателю возврата. Эти попытки выполняются внутренними подпрограммами унификации и механизмом возврата. Окончательным результатом будет либо успешное, либо неуспешное вычисление цели. Рассмотрим механизм возврата на примере программы 2.1.
/* Программа 2.1 «РОДСТВЕННИКИ».
Назначение: демонстрация механизма возврата */
domains
name=symbol
predicates
pearent(name,name)
feminin(name)
male(name)
sister(name,name)
clauses
pearent(mary,bob).
(2) pearent(mary,beth).
(1) pearent(tom,beth).
(4)(5) pearent(tom,bob).
(6) pearent(tom,liz).
(7) pearent(bob,ann).
pearent(bob,pat).
pearent(pat,jim).
feminin(mary).
feminin(beth).
(3) feminin(liz).
feminin(ann).
feminin(pat).
male(tom).
male(bob).
male(jim).
sister(X,Y):-
pearent(Z,X),
pearent(Z,Y),
feminin(X),
X<>Y .
/* Конец программы */
Будем вычислять цель
Goal: sister(beth,X)
Первым правилом, сопоставимым с нашей целью, является правило sister(X,Y). Так как других утверждений для предиката sister нет, то нет и альтернативных путей. Поэтому указатель возврата не ставится, а система генерирует первую подцель pearent(Z,beth). Эта подцель успешно согласуется с фактом pearent(mary,beth). Так как для предиката pearent есть другие утверждения, то указатель возврата (1) устанавливается на факт, следующий за фактом pearent(mary,beth).
Затем система генерирует подцель pearent(mary,Y) и начинает просматривать сначала всю базу данных. Первым утверждением, согласующим данную подцель, будет pearent(mary,bob). Указатель возврата (2) при этом устанавливается на следующее за ним утверждение pearent(mary,beth). Подцели feminin(beth) и beth<>bob успешно согласуются, цель вычисляется со значением X=bob.
Так как для feminin есть другие утверждения, то указатель возврата (3) устанавливается на feminin(liz) и к нему возвращается система, пытаясь передоказать feminin(beth). Передоказать его не удается, указатель (3) снимается, а система возвращается на указатель (2). X означивается beth, успешно доказывается feminin(beth), но beth<>beth неуспешно.Так как для pearent(mary,_) больше утверждений нет, то возвращаемся на (1). Цель pearent(tom,beth) успешно согласуется, на следующее утверждение устанавливается указатель (4), система генерирует подцель pearent(tom,Y).
Эта цель успешно доказывается с Y=beth, указатель (5) устанавливается на pearent(tom,bob), и к нему мы возвращаемся, потерпев неудачу при доказательстве beth<>beth. (5) снимается, на pearent(tom,liz) устанавливается (6). Так как beth<>bob цель успешно доказывается (получаем повторно X=bob) и возвращаемся на (6). Y получает значение liz, указатель (7) устанавливается на pearent(bob,ann). Успешно получив решение X=liz, возвращаемся на (7), потерпев неудачу, возвращаемся еще на шаг назад — на (4). bob не согласуется с beth, больше указателей нет, выходим из системы.