Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Логическое программирование. Учебно-методическое пособие к лабораторным работам
.pdf
71
save(Имя_Файла).
Другой встроенный служебный предикат позволяет добавлять в безы-
мянную динамическую базу данных факты из заданного файла, в котором
эти факты были ранее каким-либо образом накоплены:
consult(Имя_Файла).
Аналогичные предикаты имеются и для работы с именованными базами
данных. Только вместо одного аргумента эти предикаты имеют два аргумента, так как второй аргумент содержит заданное имя динамической базы данных. Предикаты для именованных динамических баз данных таковы:
assert(Факт, Имя_базы_данных) — добавить Факт в произвольное ме-
сто динамической базы данных, имеющей Имя_базы_данных;
asserta(Факт, Имя_базы_данных) — добавить Факт в начало динами-
ческой базы данных, имеющей Имя_базы_данных;
assertz(Факт, Имя_базы_данных) — добавить Факт в конец динамиче-
ской базы данных, имеющей Имя_базы_данных
;
retract(Факт, Имя_базы_данных) — удалить одно вхождение клаузы
Факт из динамической базы данных, имеющей Имя_базы_данных;
retractall(Факт, Имя_базы_данных) — удалить все вхождения клаузы
Факт из динамической базы данных, имеющей Имя_базы_данных;
save(Имя_Файла, Имя_базы_данных) — сохранить в файле, имеющем
Имя_Файла, факты, накопленные в динамической базе данных, имеющей
Имя_базы_данных;
consult(Имя_Файла, Имя_базы_данных) — добавить все факты из фай-
ла, имеющего Имя_Файла, в динамическую базу данных, имеющую
Имя_базы_данных.
Как было сказано выше, предикаты, используемые в именованной внут-
ренней динамической базе данных, должны быть объявлены в соответству-
ющем разделе логической программы:
database - <Имя_базы_данных>
для Турбо-ПРОЛОГа

72
и facts -
<
Имя_базы_данных>
для языка Visual Prolog (название database для Visual Prolog тоже допускается).
Так как при поиске решения алгоритм резолюции может работать со
всеми предикатами логической программы, не делая различия между предикатами, объявленными в разделе predicates, и предикатами, объявленными в одном из разделов database (или facts), то использование любого из
предикатов consult фактически изменяет набор фактов логической программы, что напоминает использование предикатов группы assert.
Использование нескольких именованных динамических баз данных бывает необходимым, как правило, только тогда, когда требуется сохранять
различные наборы накопленных фактов в различных файлах.
Ниже приведены несколько примеров, содержащих фрагменты логиче-
ских программ, в которых использованы встроенные предикаты динамиче-
ских баз данных.
1) Программа с повторами, осуществляющая создание динамической ба-
зы данных путём копирования всех фактов с предикатом p(X,Y) в факты с
предикатом dp(X,Y) из безымянной динамической базы данных:
assert_database :- p(X, Y), assertz( dp(X, Y)), fail.
assert_database :- !.
Наличие предиката fail заставляет механизм резолюции продолжать по-
иск решения, пока не будут просмотрены все факты типа p(X,Y). Успешный
выход из повторов после просмотра всех заданных фактов осуществляется
с помощью отсечения.
2) Сохранение безымянной динамической базы данных в файле с име-
нем dbs_file.txt непосредственно из раздела goal:
goal save(dbs_file.txt).
3) Программа с повторами, осуществляющая удаление всех фактов вида
dp(X,Y) из динамической базы данных:
clear_database :- retract(dp(_,_)), fail.
clear_database :- !.

73
Механизм функционирования программы clear_database аналогичен механизму программы assert_database. Для удаления здесь используется не-
детерминированный предикат однократного удаления retract(...), используе-
мый многократно. Возможно аналогичное по результату однократное ис-
пользование предиката retractall(...), например, в разделе goal:
goal retractall(dp(_,_)).
Возможны и другие случаи использования retractall.
4) Подключение фактов из файла dbs_file.txt к динамической базе данных
db1 непосредственно из раздела goal:
goal consult(dbs_file.txt, db1).
5) Запрос к базе данных из 1-й лабораторной работы, состоящей из фак-
тов типа mother(X,Y). Использование динамической базы данных и предиката not() исключает паразитное повторение ответов:
goal
mother(X,_), % Обращение к фактам mother(X,_).
not(d_mother(X)), % Есть ли соответствующий факт в динамической базе?
assert(d_mother(X)), % Добавить, если такого факта не существует.
write(X), % Распечатать значение аргумента предиката.
fail; true. % Продолжить просмотр.
Комментарии показывают, как функционирует механизм динамических
баз данных. Фактически таким способом можно осуществлять накопление
информации, полученной в процессе работы программы. В императивных
языках программирования эти действия выполняются с помощью оператора
присваивания, отсутствующего в логическом программировании.
6) Предикаты динамической базы данных позволяют ещё одним спосо-
бом «оптимизировать» рекурсивные программы. Так в приведённом ниже
Примере №8 использование предикатов группы assert помогает резко со-
кратить используемый объём стека и вычислительные затраты. Для удоб-
ства соответствующих сравнений используется рассмотренная ранее (в 5-й
и 6-й лабораторных работах) задача вычисления чисел Фибоначчи.

74
Кроме текста программы в Примере_8 приведён текст диалога с
ПРОЛОГ-машиной, иллюстрирующий изменения, происходящие в опера-
тивной памяти компьютера в процессе работы программы. Видно, что
ПРОЛОГ-машина в этом случае функционирует как самопрограммирующаяся информационная система.
В конце текста диалога приведён пример успешного считывания инфор-
мации из созданного в процессе функционирования программы файла
«C:fibd.txt». Это считывание проводится с помощью конъюнкции встроенных
предикатов openread, readdevice и readterm.
Предикат openread(f, "C:fibd.txt") связывает файловую переменную f
c именем файла «C:fibd.txt». Предикат readdevice(f) объявляет эту перемен-
ную устройством ввода. Комбинация предикатов для чтения структуриро-
ванных данных readterm(fbd, _) позволяет пропустить несколько строк (несколько фактов) в файле, прочитав затем значения переменных в очередном факте.
Рассмотренные шесть неравнозначных примеров не исчерпывают всех
возможностей по использованию предикатов динамических баз данных, а
лишь показывает их разнообразие.
Методические указания
«Самопрограммирование» с помощью предикатов assert и retract изучено
в гл. 7 [10], подробнее динамические базы данных рассмотрены в гл. 9 [7] и
в гл. 15 [8], полный набор встроенных предикатов Турбо-ПРОЛОГа имеется
в [12].
Содержание отчёта:
1) заголовок и цель лабораторной работы;
2) индивидуальное задание;
3) тексты логических программ с предикатами динамических баз дан-
ных;
4) результаты работы логических программ;
5) выводы.

75
% Пример 8. Использование предикатов внутренней динамической базы данных
domains
file = f % f - это файловая переменная (символическое имя файла)
fbd = fibd(integer, integer) % fbd - структурный тип с функтором fibd
/* Этот тип повторяет описание предиката динамической базы данных. */
% Эти типы данных созданы для прямого чтения термов из файла fibd.txt,
% в котором сохранены вычисленные факты, использующие предикаты fibd.
predicates fib(integer, integer) % Предикат для вычисления чисел Фибоначчи
database % Раздел предикатов безымянной динамической базы данных
fibd(integer, integer) % Предикат безымянной динамической базы данных
clauses
fib(N,F):- fibd(N,F),!. % Извлечение информации из динамической базы данных
fib(1,1):- asserta(fibd(1,1)),!. % Добавить 1-е число Фибоначчи.
fib(2,1):- assertz(fibd(2,1)),!. % Добавить 2-е число Фибоначчи.
fib(N,F):-N1=N-1,fib(N1,F1), % Предыдущее число Фибоначчи.
N2=N-2,fib(N2,F2), % Число Фибоначчи, предшествующее
% предыдущему.
F=F1+F2, % Вычисление искомого числа Фибоначчи.
assertz(fibd(N,F)). % Добавление нового числа в динамическую
% базу данных
/* Диалог с ПРОЛОГ-машиной. */
Goal: fibd (N, Fib). % Запрос информации из динамической базы данных
No Solution
Goal: consult (“C:fibd.txt”). %Подключение фактов из файла fibd.txt в дин-ю базу
Yes
Goal: fibd (N, Fib). % Повторный запрос из динамической базы данных.
N=1, Fib=1
N=2, Fib=1
N=3, Fib=2
N=4, Fib=3
N=5, Fib=5
5 Solution
Goal: fibd (7, Fib). % Вычисление 7-го числа Фибоначчи.
Fib=13
1 Solution
Goal: save(“C: fibd.txt”). % Сохранение вычисленных фактов в файле fibd.txt.
Yes
Goal: openread(f, “C: fibd.txt”), readdevice(f), readterm(fbd,_), readterm(fbd,_),
readterm(fbd,_), readterm(fbd,_), readterm(fbd,_), readterm(fbd, fibd(N,F)).
N=6, F=8
1 Solution
% Был открыт для чтения fibd.txt и прочитана информация в 6-й строке

76
Задания для лабораторной работы №8
Часть 1
Используя материалы 1-й, 2-й и 3-й лабораторных работ в соответствии
с вариантами заданий к ним, выполнить следующее:
а) создать внутреннюю динамическую базу данных,
б) сохранить созданную внутреннюю базу данных в файле,
в) изучить текст созданного в пункте б) файла,
г) подключить факты, хранимые в созданном файле, к новой логической
программе.
Эти действия следует выполнить как с обычной, неструктурированной
информацией (лабораторная работа №1), так и со структурно организованной информацией (лабораторные работы №2 и №3), аналогично примерам
1–4 настоящей лабораторной работы.
Часть 2
Используя предикаты динамических баз данных и текст 1-й лаборатор-
ной работы, создать такие запросы, ответы на которые не будут содержать
паразитных повторов, как это сделано в примере (5) настоящей работы. В
этом примере показано, как наличие и использование динамического преди-
ката позволяет изменить последовательность работы алгоритма резолюции
и устранить лишние повторы в решениях.
Часть 3
На основе материалов 5-й и 6-й лабораторных работ и в соответствии
с вариантами задания на эти работы, оптимизировать рекурсивные про-
граммы. Для этого использовать встроенные предикаты внутренних дина-
мических баз данных, как это показано в примере (6) этой работы.

77
Р а б о т а №9. ТИПОВЫЕ МЕТАЛОГИЧЕСКИЕ ПРЕДИКАТЫ
Цель работы — изучение особенностей использования встроенных пре-
дикатов ПРОЛОГа, предназначенных для определения типов аргументов
предикатов. Освоение принципов разработки универсальных с позиции вхо-
да-выхода логических программ с помощью таких металогических предика-
тов.
Общие сведения
Аргументы предикатов в логических программах делятся на два основ-
ных типа: входные (input) и выходные (output).
Входные аргументы при обращении к предикату бывают означены, то
есть принимают конкретные заданные значения. Такие аргументы называют
связанными.
Выходные аргументы в момент обращения к предикату неозначены, то
есть являются неконкретизированными свободными переменными. В мо-
мент успешного выполнения предиката (когда предикат возвращает значе-
ние true) выходные аргументы конкретизируются и принимают итоговые вычисленные значения.
Предикаты, создаваемые пользователем (также как и встроенные преди-
каты ПРОЛОГа), могут иметь как входные, так и выходные аргументы. Су-
ществует множество программ, в которых одни и те же аргументы предика-
тов выступают как в роли входных, так и в роли выходных аргументов. Так
предикат, задающий отношение «X является матерью Y» (mother(X,Y)) может вызываться семью возможными способами:
1) mother(X, Y).
o o
"Кто кому приходится матерью?"
2) mother("Мария", Y).
i o
"Кому приходится матерью Мария?"

78
3) mother(X, "Иван").
o i
"Кто приходится матерью Ивану?"
4) mother("Мария", "Иван").
i i
"Мария — мать Ивана?"
5) mother("Мария", _).
i i
"Является ли Мария кому-либо матерью?"
6) mother(_, "Иван").
i i
"Указана ли мать Ивана в нашей программе?"
7) mother(_, _).
i i
"Есть ли положительная информация о матерях в нашей программе?"
Видно, что аргументы предиката выступают как в роли входных, так и в
роли выходных. Такие предикаты можно условно назвать универсальными.
Наряду с этими универсальными предикатами существует множество ло-
гических программ, в которых используются предикаты со строго заданными
с позиции входа и выхода типами аргументов. То есть в таких предикатах
одни аргументы могут быть только входными (и должны быть обязательно
означены или связаны), а другие — только выходными (и должны быть обя-
зательно свободны). Таковы, например, программа вычисления суммы эле-
ментов списка:
sum_list(List, Sum_of_list),
input output

79
или программа вычисления чисел Фибоначчи:
fib(Number, Fiboncchi_number).
input output
Возможны ситуации, когда необходимо определить тип аргументов с
точки зрения их означенности. Определение типов аргументов как означенных и неозначенных называется металогическим для того, чтобы отличить
типы означенности от типов данных (встроенных или задаваемых пользова-
телем). Определение типов означенности происходит с помощью особых
типовых металогических предикатов, которыми в языках Турбо-ПРОЛОГ
и Visual Prolog являются предикаты:
free(V) — выполнен, если переменная V неозначена или свободна;
bound(V) — выполнен, если переменная V означена (связана).
В приведённом ниже Примере_9 представлены программы с использо-
ванием этих встроенных предикатов. Показано, как с их помощью можно со-
здать универсальные предикаты plus(A,B,C) и mult(A,B,C), переделав специальные программы:
plus(A, B, C) :- C=A+B.
i i o
mult(A, B, C) :- C=A*B.
i i o
Важно заметить, что в других версиях языка ПРОЛОГ (не фирмы Borland)
также имеются предикаты, выполняющие эти металогические функции. Од-
нако названия этих предикатов могут быть другие [11].
Создание универсальных предикатов — простой и очевидный способ использования bound(.) и free(.), но не единственный. Другие случаи использования типовых металогических предикатов можно видеть в программах так
называемого искусственного интеллекта [10].

80
Пример_9. Использование типовых металогических предикатов
predicates
plus(real, real, real)
mult(real, real, real)
clauses
plus(A,B,C):- bound(A), bound(B), C=A+B.
plus(A,B,C):- bound(A), bound(C), B=C-A.
plus(A,B,C):- bound(B), bound(C), A=C-B.
mult(A,B,C):- bound(A), bound(B), C=A*B.
mult(A,B,C):- bound(A), bound(C), A<>0, B=C/A.
mult(A,B,C):- bound(B), bound(C), B<>0, A=C/B.
mult(A,_,C):- bound(A), bound(C), A=0, write("Деление на ноль!").
mult(_,B,C):- bound(B), bound(C), B=0, write("Деление на ноль!").
% Аргументы в этих предикатах можно задавать произвольно:
Goal: plus(2,3,C).
C=5
Goal: plus(1,B,5).
B=4
Goal: plus(A,5,7).
A=2
Goal: plus(7,3,10).
Yes
Goal: mult(2,5,10).
Yes
Goal: mult(A,4,12).
A=3
Goal: mult(3,B,15).
B=5
Goal: mult(7,8,C). C=56
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
