system: [SYSTEM]

user: 4. 树模式匹配算法 本节以XML数据流处理为例，介绍XML数据流的树模式匹配方法。 4.1. 流数据处理流程 如图3所示，XML数据流的树模式匹配流程由三个阶段组成。在预处理阶段，系统根据给定的树模式分析输入的XML数据流，过滤掉与树模式无关的XML元素；然后通过边缘节点的开始结束标签驱动边缘分枝匹配算法，其中，startElem()针对边缘分枝节点的开始标签进行处理，endElem()针对边缘分枝节点的结束标签进行处理。这两个函数共同确定存在边缘分枝的非边缘实例树节点是否满足边缘分枝并为其做标记，为模式匹配阶段的筛选做准备，并且将非边缘节点的开始标签和结束标签交给模式匹配阶段处理。在模式匹配阶段，调用toStack()函数处理非边缘节点的开始标签，toList()函数处理非边缘节点的结束标签。他们共同完成树模式的模式匹配，采用实例树保存匹配结果。在第三阶段，系统从实例树中逐个枚举出检测出的每个查询结果。 4.2. 边缘分枝数据模型 每条边缘分枝由边缘节点和边缘节点的最近非边缘祖先节点组成。对于边缘分枝上的每个节点K，设置一个stackK。 如果K是边缘节点，则stackK中的元素是一个三元组enode=(level，point，flagB)。其中，level保存了该元素所在层次，point是指向父亲查询节点V的栈stackV中满足轴约束关系的最近祖先节点的指针，flagB标识该节点是否满足该节点所在的边缘分枝。B是K所在边缘分枝上距离K最远的边缘节点，标识该边缘分枝。 如果K是边缘节点的最近非边缘祖先节点，则stackK中的元素是一个一元组enode = (flags)。其中，flags是n(n是边缘分枝的个数)元索引数组。对于子节点K i (0 < I < n + 1)，若Ki是边缘节点，则数组元素flagK i 标识该元素是否满足以K i 为最近边缘后代的边缘分枝。 4.3. 实例树数据模型 本节介绍保存树模式匹配结果的实例树模型。实例树模型采用与树模式相同的树结构。对于每个非边缘节点K，设置一个实例树节点列表L K ，这里假设K有n个非边缘子节点。 L K 的表元素是四元组node=(elem，starts，ends，brother)，表示一个实例树节点qq。其中，elem是标记为K的XML元素，starts、ends都是n元索引数组。对于节点K i (0 i) = (K，AD)，则列表L ki 中从starts[i]到ends[i]所指向的每个L Ki 表元素包含了elem的所有K i 子孙元素；若axis(K i ) = (K，PC)，则从starts[i]到ends[i]分别指向的Ki表元素按照brother指针组成一个兄弟链表，包含了elem的所有K i 子元素。 图4是XML流数据处理引擎针对图2(b)所示的XML文档树执行图2(a)所示的树模式查询得到的实例树。A、C、D节点均为边缘分枝上的节点，故分别为其建立栈S A 、S C 、S D 。L A 、L B 分别是A、B查询节点对应的List。List中存放的元素均满足以该元素为根的树模式子树。L A 中每个元素指向L D 的starts D ，ends D 指针之间的B元素均为其后代。L B 中a2指向L B 的starts B ，ends B 指针之间的元素均为a2的后代。 图3. 基于树模式的XML流数据处理流程 图4. 实例树 4.4. 边缘分枝过滤算法 在预处理阶段，边缘分枝过滤算法的输入是边缘节点的XML标签和其所在层次。使用到的数据结构是边缘分枝上的节点对应的栈Stack。算法如下： 算法1：startElem(label，level) 1. w的树模式节点->W 2. W的父亲查询节点->V 3. W所在分枝上距离W最远的边缘节点->B 4. if S V .empty()或者S V .top.flagB=true 5. return； 6. if axis(W)=(PC，V)并且(S V .top().level+1)!=level 7. return； 8. 建立节点w， 9. level->w.level，S V .top()->w.point，false->w.flagB； 10. S W .push(w)； 11. if W 是叶子节点 then 12. setEdgeFlag(w，W) 算法2：setEdgeFlag(w，W) 输入：边缘分枝上的节点w和节点类型W 1. if W是边缘节点 then 2. W的父查询节点->V； 3. w指向S V 中的元素w.point->cur； 4. if axis(W)=(V，AD) 5. while cur存在并且cur.flagB=false do 6. true->cur.flagB； 7. setEdgeFlag(cur，V)； 8. S V 中cur的下一个节点->cur； 9. else 10. true ->cur.FlagB； 11. setEdgeFlag(cur，V)； 算法3：endEBranch(label，level) 1. label的树模式节点->W 2. if S W 不空&&S W .top().level=level 3. S W .pop()； 算法1用于响应边缘节点开始标签的处理，当w的开始标签到来的时候，如果w与其对应的查询节点W的父亲节点V的栈顶元素stackV.top()满足轴约束关系，并且stackV.top()还不满足边缘分枝时，则执行入栈操作。同时，如果w是叶子节点，会递归调用setEdgeFlag()函数为此分枝上的满足边缘分枝的所有元素设置标识这些元素满足边缘分枝的布尔值。算法3用来响应边缘节点的结束标签。 4.5. 模式匹配算法 如上所述，树模式的模式匹配的输入是非边缘节点的XML标签，输出是保存匹配结果的实例树模型。模式匹配过程中使用了几个数据结构：正规树模式Q、栈STK、存在边缘子节点的非边缘节点对应的Stack以及非边缘节点对应的List。两个核心算法如下： 算法4：toStack(label) 1. 为label构造实例树节点v； 2. v对应的查询节点àV； 3. 构造标识边缘分枝的栈元素->flags 4. for each child W of V do 5. if W 是边缘节点 then 6. flags.add(flagsW = false) 7. else 8. v.starts W = length(L W )+1; 9. if flags.size!=0then 10. S V .push(flags) 11. STK.push(v); 注释：v.starts W 表示实例树节点v中starts数组中子节点W所对应的元素。 算法5：结束标签的处理算法toList(label) 1. v = STK.pop(); 2. v对应的查询节点àV 3. if check(v， V)=false then 4. return; 5. 将v添加到列表Lv； 算法6：check(v，V) 输入：XML元素v、其对应的查询节点V 输出：布尔值 1. if V 存在边缘分枝 2. S V .pop->flags 3. if flags中存在值不等于true的元素 4. return false 5. for each child W of V do 6. if W是非边缘节点 then 7. v.ends W = length(L W ); 8. if v.ends W W then 9. return false; 10. if axis(W)=(V，PC) then 11. 在v.starts W 和v.ends W 之间构造兄弟链表; 12. if 兄弟链表为空then 13. returnfalse; 14. return true; 算法5所示的toList函数用于响应非边缘节点结束标签的处理；从栈中弹出当前标签对应的XML元素v后，得到对应的查询节点V，调用check检查以v为根的子树中是否存在以V为根的查询子树的查询结果。当节点v通过上述检查时，则作为中间结果保存到实例树节点列表L V 中。 在check函数的处理过程中，对边缘节点和非边缘节点分别进行的检查。前者检查是否满足边缘分枝，后者则检查V子女的实例树节点列表是否存在相应的元素。 图5展示了图2(a)的树模式对图2(b)的XML文档树匹配过程的片段。图中的T、F分别表示true和false。初始时，STK初始化为空，S A 、S C 、S D 、L A 、L B 也初始化为空。当a1的开始标签到来时，创建a1表元素，设置a1.starts B 为length(L B )+1并将其入栈STK，同时，创建a1栈元素，设置a1.flagB = F并将其入栈S A 。当a2的开始标签到来时，执行的操作与a1相同。当b1的开始标签到来时，创建b1表元素，并入栈STK。如图5(a)所示。当b1的结束标签到来的时候，b1出栈STK，并加入到L B 。当c1的开始标签到来时，由于c1和S A 的栈顶元素a1满足轴约束关系，故创建c1栈元素，设置c1.point指向a2，c1.level为c1的层次，flagC为F。当d1的开始标签到来时，同样设置d1.point指向c1，d1.flagC为F。由于d1是叶子节点，依次设置b1.flagC、c1.flagC、a2.flagC、a1.flagC为true。如图5(b)所示。当d1、c1的结束标签到来时，d1、c1分别从S D 、S C 出栈。当a2的结束标签到来时，设置a2.ends B 为length(L B )，由于a2.ends B >= a2.starts B 并且栈元素a2.flagC = T，所以a2存在B类的后代，并且满足以C为最近后代的边缘分枝。故将a2加入L A 的后代，由于streamB中的b1是a1的孩子，故a1满足树模式约束被加入到L A ，如图5(c)所示。 4.6. 算法分析 在复杂事件检测方法的开销集涉及边缘分支的处理和非边缘节点的处理。 在时间复杂度方面，非边缘节点的check匹配算法，仅涉及XML子树的一遍扫描，且没有针对XML元素的循环处理，可以在线性时间内完成。边缘节点的匹配算法中，时间开销主要集中在setEdgeFlag，为O(d*n)。其中，d是分支个数，n是边缘分支的元素个数。因此计算复杂度与元素个数成正比。在最坏的情况下，对于XML文档D，树模式的时间复杂度可以达到O(m|D|)，其中，m是最大分枝度数。因此，树模式匹配可以在线性时间内完成。 在空间复杂度方面，边缘分枝栈中的元素所占内存空间为O(N1)，其中N1是XML数据流中边缘分枝的深度，并且对于非边缘节点元素来说，占用内存空间为O(b*N2)，其中b为分枝节点的个数，N2是XML数据流中非边缘节点元素的个数。因此，空间复杂度为O(N1 + b*N2)。鉴于分支节点的数量有限，流数据匹配过程中将随时释放已经枚举的结果，算法的空间开销主要取决于正规节点匹配结果的需求， 图5. 匹配过程的状态变化 与匹配元素序列的长度和匹配结果的数量成正比。