Операции с базой данных

Ваза данных, в соответствии с реляционной моделью баз данных, представляет собой спецификацию набора отношений. Любая программа Prolog может рассматри­ваться как подобная база данных; в ней спецификация отношений частично являет­ся явной (факты), а частично неявной (правила). Некоторые встроенные предикаты позволяют модифицировать эту базу данных во время выполнения программы. Такое обновление осуществляется путем добавления новых предложений в программу или удаления существующих предложений (причем эти операции осуществляются во время выполнения программы). Для этого предназначены предикаты assert, asserts, assertz и retract. Цель asserttС)

всегда достигается и в качестве побочного эффекта вызывает подтверждение (assertion) предложения С, т.е. внесение его в базу данных. Цель

retract< С)

выполняет противоположное действие: удаляет предложение, которое согласуется с предложением С. Выполнение этих операций можно продемонстрировать на примере следующего диалога с системой Prolog:

?- crisis.

no

?- assert С crisis) .

yes

?- crisis,

yes

?- retractf crisis).

?- crises,

Таким образом, внесенные в базу данных предложения действуют точно так же, как часть "первоначальной" программы. Приведенный ниже пример показывает один из способов использования предикатов assert и retract для учета изменений ситуации. Предположим, что имеется следующая программа, в которой регистриру­ется состояние погоды:


Глава 7. Дополнительные встроенные предикаты



nice :-

sunshine, not raining.

funny :-

sunshine, raining.

disgusting :-

raining, fog.

raining. fog.

Ниже приведендиалог с этой программой, который показывает, как постепенно , изменяются содержимое базы данных и реакция программы.

?- nice.

по

?- disgusting.

yes

?- retract [ fog) .

yes

?- disgusting.

no

?- assert! sunshine).

yes

?- funny.

У- retract ( raining).

yes

?- nice.

yes

Вносить или извлекать из базы данных можно предложения любой формы. Но в за­висимости от реализации Prolog может потребоваться, чтобы предикаты, добавляемые и извлекаемые с помощью предикатов assert/retract, были объявлены как динами­ческие. ДЛЯ ЭТОГО используется директива dynamic( Predicatelndicator). Преди­каты, внесенные в базу данных с помощью предиката assert, а не consult, автома­тически рассматриваются как динамические.

Следующий пример показывает, что предикат retract также является недетер­минированным: с помощью единственной цели retract может быть удален целый набор предложений путем перебора с возвратами. Предположим, что в программе, применяемой для "консультации", имеется следующий набор фактов:

fast ( aims .

slow! torn).

pat) .

К этой программе можно добавить некоторое правило следующим образом:

?- assert! (faster[X,¥> :-

fastcxb slow(Y) ) ) .

yes

?- faster! a, B) .

A - ann

E = torn

?- retract ( sio>;(x) ) .

X = torn;

X - pat;

no

?- faster! ann, _).

no

Обратите вниманиена то, что при внесении в базу данных это правило (как пара­метр предиката assert) в соответствии с синтаксисом было заключено в круглые скобки.

162 Часть I. Язык Prolog


 


При внесении предложения в базу данных может потребоваться указать позицию, в которой это новое предложение должно быть вставлено в базу данных. Предикаты asserta и assertz предоставляют возможность управлять позицией вставки. Цель asserta(С) добавляет предложение С в начале базы данных, а цель

assertz(С)

вставляет предложение С в конце базы данных. Предполагается, что предикат assert эквивалентен assertz, как обычно предусмотрено в реализациях Prolog. В следующем примере демонстрируется, какое влияние на базу данных оказывают эти предикаты:

?- assert p(b>), aseertzl р(О), assert: p(d)), asserta ( p [an .

yes

?- P{X) X - a; X = b ; X = c,-

X = d

Предикаты consult и assertz связаны между собой определенной зависимо­стью. Получение консультации из файла с помощью предиката consult можно оп­ределить в терминах предиката asser z следующим образом: для получения кон­сультации из файла прочитать каждый терм (предложение) файла и внести его в ко­нец базы данных.

Одна из типичных областей применения предиката asserta состоит в сохранении уже вычисленных ответов на вопросы. Например, предположим, что в программе оп­ределен следующий предикат: solve.' Problem, solution)

Теперь системе можно задать некоторый вопрос и потребовать, чтобы она запом­
нила ответ, для того, чтобы он мог использоваться в будущих вопросах:
?- solve) prob[ Solution),

eiS SCI l a solve f problem!. Solution)).

Если первая из приведенных целей достигается, то ответ (Solution) запоминает­ся и используется наряду с любыми другими предложениями при формировании от­ветов на дальнейшие вопросы. Преимуществом такого "запоминания" ответом явля­ется то, что на дальнейшие вопросы, соответствующие подтвержденным фактам, сис­тема обычно находит ответ намного быстрее, чем на первый вопрос. После этого результат может быть просто выбран из базы данных как факт, не требуя вычисле­ния в процессе, который, возможно, занимает много времени. Такой метод сохране­ния ранее полученных решений называют также кэшированием.

В одном из вариантов реализации этой идеи операция внесения в базу данных ис­пользуется для выработки всех решений в форме таблицы фактов. Например, имеет­ся возможность сформировать таблицу произведений всех пар целых чисел от О до 9 следующим образом: сформировать пару целых чисел X и V, вычислить выражение Z is л внести в базу данных три числа в виде одной строки таблицы произведе­ний, а затем вызвать ситуацию недостижения цели. Эта ситуация приведет к тому, что в результате перебора с возвратами будет сформирована еще одна пара целых чи­сел и в таблицу будет введена еще одна строка и т.д. Эта идея реализована в приве­денной ниже процедуре maketable.

maketable :-

L = [0,1,2, 3,4, 5, 6,7, В, 9],

member( X, L) , * Выооать первый коэффициент

member( Y, L) , ■ Выбрать второй коэффициент Z isX'Y, assert! product(X,Y,Z) >,

fail .

Глава 7. Дополнительные встроенные предикаты 163


Безусловно, что вопрос ?- maketable.

окончится неудачей, но в качестве побочного эффекта позволит ввести в базу данных всю таблицу умножения. После этого системе можно задать вопрос, например, какая пара чисел дает произведение 8:

?- product! к, В, 8). А = 1 В =8; А =2 В =4;

На данном этапе необходимо сделать одно замечание в отношении такого стиля программирования. Приведенные выше примеры показывали некоторые, безусловно, удобные способы применения предикатов assert и retract. Но при использовании этих предикатов необходимо соблюдать особую осторожность. Излишнее и непроду­манное применение этих средств нельзя рекомендовать в качестве хорошего стиля программирования. Использование операций подтверждения и извлечения фактов и правил по сути приводит к модификации программы. Поэтому отношения, которые в какой-то момент были действительными, в другое время могут оказаться недействи­тельными. В разное время на одни и те же вопросы система будет давать разные от­веты. Поэтому применение значительного количества операций подтверждения и из­влечения может затемнить смысл программы. В конечном итоге может оказаться, что поведение программы трудно понять, нелегко объяснить, и поэтому ей нельзя до­верять.

Упражнения

7.6. Выполните указанные ниже действия после проведения упражнений с табли­
цей product.

а) Составьте вопрос к системе Prolog для удаления всей таблицы product из базы данных.

6} Измените вопрос таким образом, чтобы он удалял только те записи, в кото­рых произведение равно нулю.

7.7. Определите отношение

copy_tem{ Tern, Copy)

создающее такую копию Сору терма Terra, в которой переименованы все пере­менные. Программу решения" данной задачи легко сформировать с использова­нием предикатов asserta и retract. В некоторых реализациях Prolog уже предусмотрен такой встроенный предикат, copy_term.