
- •Глава 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
- •Библиографический список
- •Оглавление
Глава 9. Динамическая база данных
1. Турбо-пролог и реляционные базы данных
Турбо-Пролог ориентирован на работу с реляционными БД. Можно указать следующее соответствие понятий:
База данных Турбо-Пролога |
Реляционная база данных |
предикат БД |
Отношение |
объект(аргумент) |
Атрибут |
отдельное утверждение |
Элемент отношения |
количество утверждений |
Мощность |
Пусть в разделе clauses имеется следующий факт:
member_party(”Вольфович”,50,100,”n”).
Предикат member_party имеет четыре аргумента: партийное имя, возраст, членский взнос (в рублях), отметка об уплате.
Поскольку введенная ранее терминология Турбо-Пролога прилагается к реляционным базам данных, то все понятия приобретают новое значение:
набор атрибутов Name,Age,Pay и Payment называется реляционной схемой отношения member_party, где арность отношения равна четырем и мощность отношения равна одному.
Совокупность утверждений предиката member_party составляет СТАТИЧЕСКУЮ БД, так как эти утверждения являются частью программного кода и не могут быть изменены во время выполнения программы. Также в Турбо-Прологе имеются специальные средства и для организации динамических баз данных, и для работы с внешними базами данных, расположенными на жестком диске. Рассмотрим подробно способы организации динамических БД.
2. Описание предикатов динамических бд
Раздел database в Турбо-Прологе предназначен для описания предикатов базы данных. Все различные утверждения этих предикатов составляют динамическую базу данных Турбо-Пролога.
database
dmember_party(name,age,pay,payment)
Такая база данных располагается в оперативной памяти, и во время работы программы из нее можно удалять любые содержащиеся в ней утверждения и добавлять новые. В этом состоит ее отличие от статической базы данных, где утверждения вписаны в программный код раз и навсегда, и не могут быть изменены. Если БД состоит из статической и динамической части, то предикаты динамической БД имеют другое имя, но ту же самую форму представления данных.
Все отличие предиката dmember_party по сравнению с member_party заключается лишь в одной лишней букве терма. Добавление латинской буквы d — обычный способ различать предикаты динамической и статической баз данных.
domains
name,payment=symbol
age,rubel=integer
pay=integer
database
dmember_party(name,age,pay,payment)
predicates
member_party(name,age,pay,payment)
В ДИНАМИЧЕСКОЙ БАЗЕ ДАННЫХ МОГУТ СОДЕРЖАТЬСЯ ТОЛЬКО ФАКТЫ (НЕ ПРАВИЛА).
В этом состоит отличие Турбо-Пролога от других реализаций языка Пролог.
Утверждения статической БД могут быть считаны в динамическую БД сразу после активизации программы (для этой цели используются предикаты asserta и assertz, которые будут рассмотрены ниже).
Другая важная особенность динамической базы данных состоит в том, что такая база может быть записана на диск, а также считана с диска в оперативную память (встроенные предикаты save и consult).
3. Встроенные предикаты asserta, assertz, retract, retractall, save, consult
В Турбо-Прологе имеются специальные встроенные предикаты для работы с динамической базой данных. Таковыми являются asserta, assertz, retract, retracrall, save, consult.
Предикаты asserta, assertz и retract позволяют занести факт в заданное место динамической БД и удалить из нее уже имеющийся факт.
Предикат asserta заносит новый факт в базу данных, располагающуюся в оперативной памяти компьютера (резидентная БД). Новый факт помещается перед всеми уже внесенными утверждениями данного предиката. Этот предикат имеет такой синтаксис:
asserta(Clause)
Таким образом, чтобы поместить в БД утверждение о новом члене партии перед уже имеющимся там утверждением (стоящим в настоящий момент в базе данных на первом месте), необходимо следующее предикатное выражение:
asserta(member_party(”Кузьмич”,65,10,”y”))
Предикат assertz так же, как и asserta, заносит новые утверждения в базу данных. Однако он помещает новое утверждение за всеми уже имеющимися в базе утверждениями того же предиката. Синтаксис предиката столь же прост:
assertz(Clause)
Предикат retract удаляет утверждение из динамической БД. Его синтаксис таков:
retract(Existing_clause)
Если в базе данных НЕТ УТВЕРЖДЕНИЯ, которое вы пытаетесь удалить, то retract ОКОНЧИТСЯ НЕУДАЧЕЙ.
Предположим, что вы хотите удалить из базы данных второе утверждение. Для этого необходимо написать выражение:
retract(member_party(”Кузьмич”, 65,10,”y”))
Если вы хотите удалить из БД всех членов, не уплативших взносы, то можно воспользоваться предикатом:
retractall(member_party(_,_,_,”n”))
Предикат retractall ВСЕГДА УСПЕШЕН, даже при попытке удалить что-то из абсолютно пустой БД.
Предикат retract имеет важную особенность — он ПЕРЕДОКАЗЫВАЕТСЯ ПРИ ВОЗВРАТАХ (в отличие от asserta, assertz и retractall). Поэтому при применении предиката retract существует опасность непредсказуемого изменения программы. В дальнейшем будут рассмотрены приемы, позволяющие решить эту проблему.
Для модификации базы данных можно использовать комбинацию выражений с предикатами asserta, assertz и retract. Например, для того, чтобы отредактировать содержащееся в БД утверждение, ваша программа должна получить данные от пользователя, составить новое утверждение, удалить старое и занести новое.
Процедурой занесения в динамическую БД информации из статической БД, представляющей собой утверждения предиката member_party служит:
assert_database :-
member_party(Name,Age,Pay,Payment),
assertz(dmember_party(Name,Age,Pay,Payment)),
fail.
assert_database :- !.
Первое правило с помощью возврата после неудачи перебирает все утверждения предиката member_party, второе обеспечивает успешное завершение цели.
Процедура очистки динамической БД перед выходом из программы:
clear_database:-
retractall(dmember_party(_,_,_,_)).
Содержимое динамической БД можно и сохранить в файле на диске, и загрузить из файла.
Предикат save сохраняет находящуюся в оперативной памяти базу данных в текстовом файле. Синтаксис этого предиката:
save(DOS_file_name)
Здесь DOS_file_name есть произвольное допустимое в MS DOS имя файла.
Для того чтобы сохранить содержимое БД в файле текущего каталога с именем party.dba, требуется предикат:
save("party.dba")
Если файл с таким именем уже имелся на диске, то этот старый файл будет затерт, если такого файла не было, будет образован новый.
Файл с динамической БД представляет собой обычный текстовый файл, в котором утверждения сгруппированы по шаблону (если в БД имеется несколько разных предикатов), и каждое утверждение находится на отдельной строчке.
Файл БД может быть считан в память при помощи предиката consult, систаксис которого таков:
consult(DOS_file_name)
Для загрузки файла партийной БД требуется выражение consult("party.dba").
Следует помнить, что предикат consult неуспешен, если файл с указанным именем отсутствует на диске, или этот файл содержит ошибки, как, например, в случае несоответствия синтаксиса предиката из файла описаниям из раздела программы database, или если содержимое файла невозможно разместить в памяти ввиду отсутствия места.
Кроме того, при указании пути для любых предикатов, работающих с файлами обратный слэш \ следует заменять его кодом \92:
save(”a:\92dbs\92party.dba”)
Предикат findall позволяет собрать все имеющиеся в базе данные в список, который может быть полезен при дальнейшей работе. (Предикат findall был описан в гл. 7.) Так, findall можно использовать для получения списка имен всех членов партии. После того, как успешным будет предикат
findall(Name,dmember_party(Name,_,_,_),Name_list)
переменная Name_list будет содержать список всех имен.