Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Логическое программирование. Учебно-методическое пособие к лабораторным работам

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
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
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]