Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Методы и средства интеграции независимых баз данных в распределенных телекоммуникационных сетях. Монография
.pdf
Данный алгоритм позволяет успешно унифицировать
предикаты runtime:p(?z,?z) и runtime:p(?x,f(?x)), на выходе получится
множества S ={(z_2, z_2%),(x_1,z_2%),(z_2%, z_2%%),(f(z_2%),z_2%%)},
и Q={(f(z_2%%)=z_2%%)}. Множество S содержит подстановки вида
x=f(Y), x=y и x=c (где x,y — переменные, c - константа, Y - множество
аргументов функции f, такое что ), множество Q содержит
условия вида x=f(X) и f(X)=g(Y) (где где x - переменная, X и Y множества аргументов функций f и g соответственно, ). В
дальнейшем данные условия используются при генерации
выражения РА.
3.2. Алгоритмы генерации выражений РА
В данном параграфе рассматриваются алгоритмы генерации
выражений РА и
программ РИ по графу MCIG, соответствующему
запросу пользователя.
3.2.1. Алгоритм генерации выражений РА для не
рекурсивных программ
Предлагаемый
нами алгоритм перевода не рекурсивных
запросов в выражения РА [2] состоит в следующем. Прежде всего,
проверяется, есть ли в графе MCIG, соответствующем запросу
пользователя, циклы. Если они есть, то программа рекурсивная,
происходит проверка, может ли система обработать рекурсивный
запрос данного типа. Если его обработка возможна, рекурсивно
определенные предикаты считаются в дальнейшем явными и
обрабатываются специальным образом (алгоритмы обработки
рекурсивно определенных предикатов описываются далее). Затем
вызывается функция перевода в выражение РА нулевого правила
графа, то есть правила, соответствующего основной части программы.
Функция перевода нулевого правила графа вызывает рекурсивную
функцию перевода translRule и проверяет, что после ее выполнения
91

не осталось необработанных условий (в противном случае
диагностируется ошибочная ситуация).
Функция translRule генерирует выражение РА по телу правила
(для каждого предиката вызывается функция обработки предикатов
processNode, полученные выражения соединяются операциями
натурального соединения JOIN) и дополняет полученное выражение
операциями PROJECT и ADD, генерируемыми по голове правила.
Функция processNode для явных предикатов генерирует выражения
РА, состоящие из отношений, соответствующих этим предикатам,
операций WHERE и RENAME (при обработке аргументов
предикатов), и проверяет, что аргументы используемых функций
известны. В зависимости от этого она либо заменяет функцию на
новую переменную и передает условие на обработку на предыдущий
уровень рекурсии, либо явно добавляет условие равенства атрибутов
отношений значениям функций в выражение WHERE.
Обработка неявных предикатов происходит в функции
processIDBPred, просматривающей все дуги, исходящие из вершины,
соответствующей обрабатываемому предикату. Для каждого правила,
соединенного с данным дугой, генерируется выражение РА. Пока не
пусто для обрабатываемой дуги, происходит циклическая обработка
этого множества. (Здесь S обозначает множество подстановок, которое
нужно выполнить, чтобы осуществить переход по обрабатываемой
дуге графа, а Q - множество условий, которые при этом должны
выполняться). Это приводит к генерации условий WHERE, операций
RENAME и ADD. По ходу обработки условий часть из них может
быть передана для дальнейшей обработки на предыдущий уровень
рекурсии в связи с неизвестностью некоторых имен переменных,
встречающихся в условиях. После завершения обработки всех
правил, соединенных с обрабатываемым дугой, получившиеся
выражения РА объединяются операцией UNION.
Отложенные на обработку условия обрабатываются в тех
местах, где могут стать известными некоторые имена переменных: в
92

функциях processNode после получения выражения JOIN, в конце
цикла по дугам в функции processIDBPred и в функции translRule
при обработке заголовков правил.
Отложенные на обработку условия необходимы для обработки
переменных, имена которых не известны на текущем, но становяися
известными на последующем этапе обработки. Например, без них
алгоритм не сможет обработать запрос, содержащий основную часть
вида
scholarship(round(?avgMark),?amount),student(?name,?surname,?avgM
ark), поскольку при обработке первого предиката имя переменной
avgMark будет неизвестно.
Рассмотрим следующий пример обработки достаточно часто
упоминаемого запроса. Считая, что нам известны отношения между
родителями и потомками (предикат parent отображается на
отношение структуры parent[VARCHAR parent,VARCHAR child]),
выбрать дедушек и бабушек Василия Иванова. Данный запрос будет
выглядеть следующим образом (см. рис. 3.4).
Preamble {
schema="http://www.sfedu.ru/~alp/family-sample#";
must ?a;
runtime:grandparent(?x,?y):-parent(?x,?z),parent(?z,?y);
} runtime:grandparent(?a,?b) ,?b="Василий Иванов"
Рис 3.4 Запрос, выбирающий прародителей Василия Иванова
При обработке по данному запросу будет построен следующий
граф взаимосвязанности выражений (см. рис. 3.5).
Рис 3.5 Граф взаимосвязанности выражений
93

Данный граф состоит из 5 вершин и 2 правил. На рисунке
вершины, соответствующие литералам одного правила, здесь и далее
изображаются в виде смежных прямоугольников. У нулевого правила
отсутствует головная часть (что отмечено пустым прямоугольником
на рисунке). Выражению ?b="Василий Иванов" в графе соответствует
вспомогательный предикат comppreds:eq(?b,"Василий Иванов"). Дуга,
соединяющая правила, помечена множеством подстановок
переменных S, состоящим из подстановок {(?y_2,?b_1%),(?b_1,?b_1%),
(?x_2,?a_1%),(a_1,?a_1%)} и множеством условий Q, при которых
возможен переход (в данном случае пустом).
Обработка данного графа происходит рекурсивно, слева
направо снизу вверх. Вначале вызывается функция transRule для
нулевого правила графа (на рисунке показано вверху). Данная
функция вызывает функцию processNode для каждой вершины,
входящей в правило и соответствующей предикату в хвосте правила
программы. Обработка вершины, помеченной как
runtime:grandparent(?a,?b), приведет к вызову процедуры transRule
для первого правила графа, которая в свою очередь вызовет функции
processNode для обработки отдельных вершин правила. После
окончания работы второй функции transRule вызвавшая ее функция
processNode произведет обработку правил S и Q, что приведет к
генерации выражения RENAME. По аргументам первого предиката
в хвосте нулевого правила произойдет выборка нужных атрибутов с
помощью операции проекции. Затем произойдет обработка
оставшихся вершин нулевого правила (в результате чего появится
условие для обработки ?b="Василий Иванов") и функция transRule
произведет окончательную обработку запроса, создав операцию РА
WHERE с данным условием и осуществив проекцию выбираемых
пользователем атрибутов согласно выражению "must" запроса. В
результате получится изображенное на рис. 3.6 выражение РА,
соответствующее данному запросу.
94

(parent[parent,child] RENAME child AS z,parent AS x)
JOIN (parent[parent,child] RENAME child AS y,parent AS z)
{x,y} RENAME y AS b,x AS a{a,b} WHERE (b = "Василий Иванов"){a}
Рис. 3.6. Выражение РА, соответствующее запросу 3.5
3.2.2. Алгоритм генерации выражений РА для
рекурсивных программ
Алгоритм обработки рекурсивных программ принимает на вход
граф MCIG и цикл, который нужно обработать, а на выходе получает
программу РИ, которая «материализует» цикл (то есть явно создает в
БД отношение, соответствующее рекурсивно определенному
предикату) [23]. Алгоритм работает при некоторых условиях,
налагаемых на циклы в графе. Согласно этим условиям выделяется
рекурсия первого и второго рода.
Будем говорить, что вершина a, соответствующая предикату,
принадлежащему правилу , принадлежит циклу, если существует
путь, ведущий из вершины а в вершину, соответствующую голове
правила . Назовем входом цикла A вершину графа b,
принадлежащую циклу A, если существует дуга E(a,b): a не
принадлежит циклу A. Назовем выходом из цикла A вершину графа
с, если c принадлежит циклу A, и существуют дуги E(c,d), E(c,f),
причем вершина d принадлежит циклу A, а вершина f не
принадлежит циклу A.
Назовем рекурсию, при которой циклы в графе не
пересекаются, имеют только один вход и не менее одного выхода,
простейшей рекурсией или рекурсией первого рода.
Приведем пример программы DISGO QL c простейшей
рекурсией (считаем, что предикат directChiefOf известен системе) (см.
рис. 3.7).
95

Preamble {
schema="http://www.sfedu.ru/~alp/employees#";
must ?a,?b;
runtime:chief(?x,?y):-directChief(?x,?y);
runtime:chief(?x,?y):-runtime:chief(?x,?z),directChief(?z,?y);
} runtime:chief(?a,?b)
Рис. 3.7. Программа с рекурсией первого рода
Граф MCIG, соответствующий программе, будет выглядеть
следующим образом (рис 3.8). Дуги 1 и 2 помечены подстановками
{y_2=b_1%,b_1=b_1%,x_2=a_1%,a_1=a_1%}, дуги 3 и 4 - подстановками
{y_2=z_1%,z_1=z_1%,x_2=x_1%,x_1=x_1%}. Все дуги помечены
множеством условий Q, пустым в данном случае.
Если материализовать цикл в рассматриваемом примере, а
результирующее отношение назвать chief%0, то выражение РА,
приведенное на рис. 3.9, будет соответствовать вышеприведенной
программе.
Программа РИ для материализации подобного цикла показана
на рис. 3.10. Данная итеративная программа использует переменную
chief%0 для накопления результата (отношение chief%0 соответствует
рекурсивно определенному предикату) и вспомогательную
переменную _A1. Вначале _A1 инициализируется выражением РА,
которое получается следующим образом:
1.
в графе взаимосвязанности выражений удаляется дуга,
выходящая из последнего выхода цикла и принадлежащую
циклу;
2.
по получившемуся графу строится выражение РА путем
перевода правила, голове которого соответствует вершина,
служащая входом в цикл (цикл уже разорван, поэтому данное
выражение может быть построено).
96

Рис. 3.8. Граф взаимосвязанности выражений для программы 3.7
(directChief[manager,subordinate] RENAME manager AS y,subordinate AS
x{x,y} RENAME y AS b,x AS a{a,b}) UNION (chief%0[x,y] RENAME y AS y,x AS
x{x,y} RENAME y AS b,x AS a{a,b}){a,b}
Рис. 3.9. Выражение РА для программы 3.7
/*Инициализация _A1*/
_A1=(directChief[manager,subordinate] RENAME subordinate AS y,manager AS
x{x,y} RENAME y AS z,x AS x{x,z}) NATURAL JOIN
(directChief[manager,subordinate] RENAME manager AS y,subordiante AS
z){x,y}
chief%0=_A1 WHERE false
INTEGER i=0
while(i<N AND _A1 MINUS chief%0 IS NOT NULL) /*Здесь N – некоторая
константа*/
begin
i=i+1;
chief%0=_A1
/*Используется выражения перехода и результат предыдущей итерации*/
97

_A1=((chief%0[x,y] RENAME y AS z,x AS x) NATURAL JOIN
(directChief[manager,subordinate] RENAME subordinate AS y,manager AS
z){x,y}) UNION chief%0
end
Рис. 3.10. Программа РИ для программы 3.7
Выражение перехода для _A1 получается следующим образом:
1) в CIG удаляется последняя дуга цикла и каждое из
обращений к предикату, голове которого соответствует вершина,
служащая входом в цикл, заменяется на обращение к предикату с
той же структурой, но с именем отношения, которое будет
соответствовать рекурсивно определенному предикату;
2) по получившемуся графу строится выражение РА путем
перевода правила, голове которого соответствует вершина, служащая
входом в цикл (цикл опять разорван, поэтому данное выражение
может быть построено).
В цикле значение переменной _A1 обновляется - к результату
предыдущего шага цикла добавляются кортежи, получаемые в
результате выполнения выражения перехода.
Заметим, что вышеприведенный алгоритм накладывает
слишком большие ограничения на преобразуемые программы.
Например, следующий запрос (рис. 3.11), эквивалентный
рассмотренному ранее запросу, он не может обработать.
Preamble {
schema="http://www.sfedu.ru/~alp/employees#";
must ?a,?b;
runtime:chief(?x,?y):-directChief(?x,?y);
runtime:chief(?x,?y):-runtime:chief(?x,?z),runtime:chief(?z,?y);
} runtime:chief(?a,?b)
Рис. 3.11. Программа, эквивалентная программе на Рис. 3.7
Причина этого состоит в том, что здесь два цикла пересекаются
в одной точке. Граф MCIG, соответствующий данной программе,
выглядит следующим образом (рис. 3.12).
98

Из-за пересечения этих циклов первый алгоритм не
срабатывает. Введем понятие группы циклов. Будем говорить, что
некоторое множество циклов графа относится к одной группе, если
вершины, в которых эти циклы начинаются, принадлежат одному
правилу, и больше они не содержат общих точек.
Рис. 3.12. Граф MCIG для программы на рис. 3.11
В примере, рассмотренном выше, два цикла, каждый из
которых состоит из одной дуги (дуги 3 и 4 соответственно), образуют
группу. Назовем несколько циклов группы циклами-близнецами,
если у них совпадают вершины, в которых эти циклы начинаются.
Пример программы с циклами-близнецами показан на рис. 3.13.
Граф MCIG этой программы приведен на рис. 3.14.
Preamble {
schema="http://www.sfedu.ru/~alp/twinLoops-sample#";
must ?b;
runtime:a(?x,7):-b(?x,7);
runtime:a(?x,6):-runtime:a(?x,?z),c(?z,6);
runtime:a(?x,5):-runtime:a(?x,6);
} runtime:a(?b,6)
Рис. 3.13. Программа, содержащая циклы-близнецы
99

Рис. 3.14. Граф взаимосвязанности выражений для программы на
рис. 3.13
Необходимым условием обработки группы циклов является
наличие выхода из каждого множества циклов близнецов,
начинающихся в одной вершине. В этом случае для каждого
рекурсивно определенного предиката программы возможно
построить выражение инициализации. Генерация программ РИ для
таких рекурсивных программ на DISGO QL происходит следующим
образом. Вначале разрываются все циклы группы путем удаления
дуги, выходящей из последнего выхода каждого цикла и
принадлежащей данному циклу. Если из цикла нет выхода (что
возможно в случае существования циклов-близнецов), то такой цикл
полностью исключается из рассмотрения в процессе построения
выражения инициализации путем удаления первой дуги цикла. По
такому графу, не содержащему циклов, строится выражение
инициализации. Далее строится выражение перехода путем замена
дуг, ведущих обратно в цикл, на дуги, ведущие к материализуемому
предикату. Полученные таким образом программы имеют такой же
вид, как и программа, представленная на рис. 3.9, разница
заключается в сложности построения начального условия и шага
перехода.
В результате обработки запроса, приведенного на рис. 3.13,
получится следующие программа РИ (рис. 3.15) и выражение РА
(рис. 3.16).
100
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
