printЛогическое программирование

printПредикаты для работы с утверждениями

Пролог позволяет программисту анализировать и изменять программу во время выполнения.
Предикат consult/1 предназначен для добавления утверждений из некоторого файла к утверждениям, уже имеющимся в БД. Аргумент предиката должен быть атомом, содержащим имя файла, например, 'w:/flp/lab1.pl', или списком имен файлов. Вводимые утверждения заменяют все имеющиеся утверждения для того же самого предиката.
Предикат listing позволяет вывести утверждения из БД в текущий выходной файл. Цель listing выводит все утверждения из БД, цель listing(N/A) – все утверждения для предиката с именем N и арностью A, а цель listing(N) – утверждения для всех предикатов с именем N любой арности. Используя предикат listing, можно сохранять состояние БД перед завершением работы программы, а в начале работы загружать информацию с помощью предиката consult.
Предикат clause/2 полезен при создании программ, анализирующих или обрабатывающих другие программы. Цель clause(X,Y) сопоставляет термы X и Y с головой и телом некоторого имеющегося в БД утверждения. Терм X должен быть конкретизирован до такой степени, чтобы стал известен функтор структуры. Если утверждение является фактом, то Y сопоставляется с true. Если имеется несколько утверждений, соответствующих термам X и Y, то Пролог выбирает первое из них. В случае возврата будет выбрано следующее утверждение и так далее. Предикат в GNU Prolog должен быть объявлен в программе с помощью команд :-public(N/A) или :-dynamic(N/A).
Предикаты asserta/1 и assertz/1 используются для добавления новых утверждений в БД. Предикат asserta(X) добавляет утверждение X в начало БД, а assertz(X) – в конец. При добавлении правил аргумент предиката нужно ставить в дополнительные скобки: assertz((a:-b,c)). Предикат asserta можно использовать для повышения эффективности программы, запоминая результаты предыдущих вычислений, чтобы не вычислять предикат повторно для тех же самых аргументов.
Предикат retract(X) удаляет из БД первое утверждение, сопоставимое с термом X. При возврате выполняется поиск и удаление следующего утверждения, сопоставимого с X. Если таких утверждений нет, то согласование цели завершается неудачей. Так как при удалении происходит сопоставление терма и утверждения, то имеется возможность получить точное представление об удаляемом утверждении. Можно определить предикат, удаляющий все утверждения с заданной головой.
retractall(X):-retract(X),fail.
retractall(X):-retract((X:-Y)),fail.
retractall(X).
В этом определении предикат fail обеспечивает обработку всех утверждений предикатом retract.
Предикаты assertz и retract позволяют создать аналог глобальных переменных.
:-dynamic(mem/2). % mem изменяется во время выполнения
set(X,V):-(retract(mem(X,_));true),assertz(mem(X,V)),!.
?-set(a,10).
?-mem(a,X).
X=10
Но использование таких побочных эффектов влияет на логическую обоснованность программы, так как отношения, выполнявшиеся в некоторый момент времени, могут оказаться неверными в другой. Обычно предикаты asserta/z и retract используются для изменения БД в соответствии с информацией, полученной от пользователя, а затем на основе этих знаний выполняется логический вывод.
Упражнения
1. Пусть имеется набор фактов вида:
словарь(like,нравится).
словарь(fish,рыба).
Определите предикат, выполняющий перевод предложений с английского языка на русский. В случае неизвестного слова необходимо делать запрос его значения у пользователя и добавлять новое определение в словарь.
?-перевод([cat,like,fish],R).
Введите перевод для слова cat: кот.
R=[кот,нравится,рыба]
2. Используя сохранение промежуточных результатов в специальном факте, определите предикат дети(X,L) для получения списка детей X для БД о родственных связях из главы 1.
?-дети(адам,R).
R=[каин,авель]
3. Определите предикат := для вычисления арифметических вычислений, запоминающий значения вычисленных переменных (обозначаемых атомом Пролога) и печатающий результат.
?-a:=1.
a=1
?-b:=a*3+5.
b=8
4. Определите предикат листинг(P,A), работающий аналогично встроенному предикату listing(P/A).
loading