goodmami / penman

PENMAN notation (e.g. AMR) in Python
https://penman.readthedocs.io/
MIT License
139 stars 27 forks source link

Best Way To Connect Two AMR Graphs #114

Closed JosephGatto closed 1 year ago

JosephGatto commented 1 year ago

Suppose I wanted to take two different AMR graphs and connect them to either a new node or some given node in one of the two graphs. What is the best way to do this?

goodmami commented 1 year ago

So, if I understand correctly, you want to do something like the following?

(a / A)  +  (b / B)  -->  (c / C :ARG0 (a / A) :ARG1 (b / B))

or

(a / A :ARG0 (b / B))  +  (b / B :ARG0 (c / C))  -->  (a / A :ARG0 (b / B :ARG0 (c / C)))

Penman has no graph manipulation functions that will do what you ask, but you can construct a new graph by concatenating lists of triples. E.g., for the first, you can do something like the following:

>>> import penman
>>> g = penman.Graph(
...     penman.decode('(c / C)').triples
...     + penman.decode('(a / A)').triples
...     + penman.decode('(b / B)').triples
...     + [('c', ':ARG0', 'a'), ('c', ':ARG1', 'b')]
... )
>>> print(penman.encode(g))
(c / C
   :ARG0 (a / A)
   :ARG1 (b / B))

For the second, you can do this:

>>> g = penman.Graph(
...     set(
...         penman.decode('(a / A :ARG0 (b / B))').triples
...         + penman.decode('(b / B :ARG0 (c / C))').triples
...     )
... )
>>> print(penman.encode(g))
(a / A
   :ARG0 (b / B
            :ARG0 (c / C)))

I convert the concatenated lists of triples to a set to ensure ('b', ':instance', 'B') doesn't appear twice.

If you are combining two graphs that use the same variable for different nodes (e.g., one has (d / dog) and the other (d / door)), you'll need to take care to ensure they don't get unintentionally merged.

JosephGatto commented 1 year ago

This is very helpful. Thank you!