# Complex edges

⚠️ Complex edges are available since version 1.2 (2019/03/26)

## Motivation

Before version 1.2, label edges were atomic and didn’t have an internal structure. This was not very convenient to deal with complex edges:

- in Deep-sequoia, the edge
`suj:obj`

means that the final function is`suj`

and the canonical function is`obj`

; - in UD, the label
`aux:pass`

is a subtype of the label`aux`

; - in SUD, the label
`compl:obl@agent`

contains both a subtype`obl`

and a deep feature`agent`

(see TLT 2019).

In all these cases, with atomic edge labels, it is not possible to deal with one part of the label independently. Since version 1.2, the implementation of label edges has changed to tackle this problem.

## Complex edges in graphs

In Grew graphs, an edge label is internally stored as a flat feature structure or, in other words, a finite set of couples `(f_1,v_1)`

… `(f_k,v_k)`

where all `f_i`

are pairwise different.
We will use the traditional notation `f=v`

for these couples.

In graph defined through CoNLL, we keep using the old syntax with symbols `:`

and `@`

with an implicit conversion:

- the sub labels, separated by
`:`

and before`@`

are transformed in numbered features following their position - the sub label after
`@`

is transformed in a`deep`

feature

In Grew output, the reverse conversion is done. If the conversion is not possible, a bracketed view of the edge is displayed

The table below shows the conversion of the 3 initial examples and a case where the conversion fails (last line). Note that it is not possible to use a bracketed notation as an input file.

Internal representation | Label used in CoNNL |
---|---|

`1=suj, 2=obj` |
`suj:obj` |

`1=aux, 2=pass` |
`aux:pass` |

`1=compl, 2=obl, deep=agent` |
`compl:obl@agent` |

`2=obl` |
`[2=obl]` |

## Complex edges in patterns

In pattern, it is possible to match edges with a standard unification mechanism, similar to the one used for feature structures in nodes. Some examples (with SUD labels) are given below.

Syntax | Description | `comp` |
`comp:obl` |
`comp:obl@agent` |
`comp:aux` |
`comp:obj@lvc` |
---|---|---|---|---|---|---|

`X -[1=comp]-> Y` |
any edge such that the feature `1` is defined with value `comp` |
YES | YES | YES | YES | YES |

`X -[1=comp, 2=obl¦aux]-> Y` * |
the feature `1` is defined with value `comp` and the feature `2` is defined with one of the two values `obl` or `aux` |
NO | YES | YES | YES | NO |

`X -[1=comp, 2<>obl¦aux]-> Y` * |
the feature `1` is defined with value `comp` and the feature `2` is defined with a value different from `obl` or `aux` |
NO | NO | NO | NO | YES |

`X -[1=comp, !deep]-> Y` |
the feature `1` is defined with value `comp` and the feature `deep` is not defined |
YES | YES | NO | YES | NO |

`X -[1=comp, 2=*]-> Y` |
the feature `1` is defined with value `comp` and the feature `2` is defined with any value |
NO | YES | YES | YES | YES |

`X -[comp]-> Y` |
the exact label `comp` and nothing else |
YES | NO | NO | NO | NO |

* replace the symbol `¦`

by the pipe `|`

symbol in Grew (the right symbol cannot be used in Markdown table!)

### ⚠️⚠️ Matching with atomic labels ⚠️⚠️

It is important to note that from the pattern point of view, the two clauses `X -[1=comp]-> Y`

(first line in the table) and `X -[comp]-> Y`

(last line in the table) are not equivalent!

### Difference with node features matching

Note that we would expect that the syntax `X -[1=comp, 2]-> Y`

should be equivalent to `X -[1=comp, 2=*]-> Y`

but it will bring a ambiguity for `X -[lab]-> Y`

that can be interpreted as the atomic label `X -[lab]-> Y`

or as `X -[lab=*]-> Y`

.
To avoid this ambiguity, the syntax `X -[1=comp, 2]-> Y`

in not allowed.

## Complex edges in commands

In commands, it is possible to manipulate subpart of edges.
If the pattern binds the identifier `e`

to some edge (with the syntax `e: X -[…]-> Y`

), the following commands can be used:

`e.2 = aux`

: update the current edge`e`

`add_edge X -[1=suj, 2=e.2]-> Z`

: add a new edge where the value of feature`2`

is copied from the value of feature`2`

of edge`e`

;`del_feat e.deep`

: remove the feature`deep`

from the edge`e`

;`add_edge e: Y -> Z`

: add a new edge with the same label as`e`

;

Note that, if the identifier `e`

is used several times in the commands of a same rule, each occurrence refers to the “current” `e`

edge eventually modified by previous commands.

## Examples

### Modify and copy an edge

Rule: `mod_copy.grs`

:

```
rule mod_copy {
pattern { e1: N -[1=X]-> M; M -> T }
commands { e1.2 = U; add_edge e1: M -> T }
}
```

Command: `grew transform -grs mod_copy.grs -strat "Onf(mod_copy)"`

Input graph: `mod_copy.gr`

Observe the difference if the two commands are swapped:

Rule: `copy_mod.grs`

:

```
rule copy_mod {
pattern { e1: N -[1=X]-> M; M -> T }
commands { add_edge e1: M -> T; e1.2 = U }
}
```

Command: `grew transform -grs copy_mod.grs -strat "Onf(copy_mod)"`

Input graph: `copy_mod.gr`

### Reverse an edge

Rule: `reverse.grs`

:

```
rule reverse {
pattern { N -[X]-> M; e: N -[Y|Z]-> M }
commands { add_edge e: M -> N; del_edge e; }
}
```

Command: `grew transform -grs complex_edges.grs -strat "Onf(reverse)"`

Input graph: `reverse.gr`

By contrast, with the rule `fail_reverse.grs`

:

```
rule fail_reverse {
pattern { N -[X]-> M; e: N -[Y|Z]-> M }
commands { del_edge e; add_edge e: M -> N }
}
```

the command `grew transform -grs complex_edges.grs -strat "Onf(fail_reverse_YZ)"`

applied to the same graph produces the error:

`[file: complex_edges.grs, line: 8] ADD_EDGE_EXPL: the edge identifier 'e' is undefined`

The `add_edge`

command cannot be executed because the edge `e`

does not exist anymore.
Note that with previous Grew versions, the rule `fail_reverse_YZ`

can be applied and hence, it may be needed to update existing rule systems.

## TODO in an upcoming release

### Copy a feature value

```
rule copy_sub {
pattern { e1: N -[1=X]-> M; e2: M -[!2]-> T }
commands { e2.2 = e1.2 }
}
```