⬆️ Top
Compute span of nodes in a dependency tree
This example illustrates the usage of non-injective matching introduced in version 1.11 (January 2023).
The objective is to add to each node, two new outgoing edges (labeled span=left
and span=right
) from the given node to its leftmost projection and rightmost projection respectively.
The main idea of the GRS is:
- add to each node two looping links
span=left
andspan=right
(ruleinit
above) - iteratively enlarge the span of one node either on the left or on the right (package
enlarge
above): “if one of my daughter node has a left [resp. right] span which is more on the left [resp. right] than mine, it become my new left [resp. right] span”. When this last rule cannot be applied further, the spans are correcly computed.
The second item (for the left case) can be formulated in the Grew rule below, with nodes:
N
: the current node where the span will be enlargeLN
: the left span ofN
before the application of the ruleX
: the daughter ofN
having a left spanLX
which is more on the left thanLN
LX
: the left span ofX
rule left {
pattern { e: N -[span=left]-> LN; N -> X; X -[span=left]-> LX; LX << LN }
commands {
del_edge e;
add_edge N -[span=left]-> LX;
}
}
The main difficulty is that we have to take into account some superposition subcases (NB: the other superposition cases cannot arise, the proof is left as an exercise!) Possible cases are:
- all nodes are different
N
andLN
refers to the same nodeX
andLX
refers to the same node- (
N
andLN
refers to the same node) and (X
andLX
refers to the same node) LN
andX
refers to the same node
When using only injective matching, we then have to design 10 rules (5 on the left and 5 on the right) for the enlarge
package (see below).
With non-injective matching (introduced in version 1.11), the same package can be written with only two rules.
Solution with non-injective matching
With the grs file non_injective.grs:
rule init {
pattern { N [upos] }
without { N -[span=left]-> * }
without { N -[span=right]-> * }
commands {
add_edge N -[span=left]-> N;
add_edge N -[span=right]-> N;
}
}
package enlarge {
rule left {
pattern { e: N -[span=left]-> LN$; N -> X; X -[span=left]-> LX$; LX$ << LN$ }
commands {
del_edge e;
add_edge N -[span=left]-> LX$;
}
}
rule right {
pattern { e: N -[span=right]-> RN$; N -> X; X -[span=right]-> RX$; RN$ << RX$ }
commands {
del_edge e;
add_edge N -[span=right]-> RX$;
}
}
}
strat main { Seq (Onf (init), Onf (enlarge)) }
⚠️ In Grew-web, dependency graphs are drawn with dep2pict and loops can not be displayed directly. Loops are replaced by special features with a green background and with double brackets. See for instance, the final graph computed with the example above:
Solution with only injective matching
With the grs file injective.grs:
rule init {
pattern { N [upos] }
without { N -[span=left]-> * }
without { N -[span=right]-> * }
commands {
add_edge N -[span=left]-> N;
add_edge N -[span=right]-> N;
}
}
package enlarge {
% 4 different nodes
rule left_1 {
pattern { e: N -[span=left]-> LN; N -> X; X -[span=left]-> LX; LX << LN }
commands {
del_edge e;
add_edge N -[span=left]-> LX;
}
}
% LN = N
rule left_2 {
pattern { e: N -[span=left]-> N; N -> X; X -[span=left]-> LX; LX << N }
commands {
del_edge e;
add_edge N -[span=left]-> LX;
}
}
% LX = X
rule left_3 {
pattern { e: N -[span=left]-> LN; N -> X; X -[span=left]-> X; X << LN }
commands {
del_edge e;
add_edge N -[span=left]-> X;
}
}
% LN = N & LX = X
rule left_4 {
pattern { e: N -[span=left]-> N; N -> X; X -[span=left]-> X; X << N }
commands {
del_edge e;
add_edge N -[span=left]-> X;
}
}
% LN = X
rule left_5 {
pattern { e: N -[span=left]-> X; N -> X; X -[span=left]-> LX; LX << X }
commands {
del_edge e;
add_edge N -[span=left]-> LX;
}
}
% 4 different nodes
rule right_1 {
pattern { e: N -[span=right]-> RN; N -> X; X -[span=right]-> RX; RX >> RN }
commands {
del_edge e;
add_edge N -[span=right]-> RX;
}
}
% RN = N
rule right_2 {
pattern { e: N -[span=right]-> N; N -> X; X -[span=right]-> RX; RX >> N }
commands {
del_edge e;
add_edge N -[span=right]-> RX;
}
}
% RX = X
rule right_3 {
pattern { e: N -[span=right]-> RN; N -> X; X -[span=right]-> X; X >> RN }
commands {
del_edge e;
add_edge N -[span=right]-> X;
}
}
% RN = N & RX = X
rule right_4 {
pattern { e: N -[span=right]-> N; N -> X; X -[span=right]-> X; X >> N }
commands {
del_edge e;
add_edge N -[span=right]-> X;
}
}
% RN = X
rule right_5 {
pattern { e: N -[span=right]-> X; N -> X; X -[span=right]-> RX; RX >> X }
commands {
del_edge e;
add_edge N -[span=right]-> RX;
}
}
}
strat main { Seq (Onf (init), Onf (enlarge)) }