Skip to content

Commit

Permalink
Add edge reification transform
Browse files Browse the repository at this point in the history
Also make it and transform.canonicalize_roles() return a new graph
instead of modify one in-place.
  • Loading branch information
goodmami committed Nov 14, 2019
1 parent 91cea28 commit ce402f0
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 23 deletions.
9 changes: 8 additions & 1 deletion penman/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ def _process(t):
"""Encode tree *t* and return the string."""
# tree transformations
if transform_options['canonicalize_roles']:
transform.canonicalize_roles(t, model)
t = transform.canonicalize_roles(t, model)

g = layout.interpret(t, model)

# graph transformations
if transform_options['reify_edges']:
g = transform.reify_edges(g, model)

return codec.encode(g, **format_options)

Expand Down Expand Up @@ -71,6 +74,9 @@ def main():
norm.add_argument(
'--canonicalize-roles', action='store_true',
help='canonicalize role forms')
norm.add_argument(
'--reify-edges', action='store_true',
help='reify all eligible edges')

args = parser.parse_args()

Expand All @@ -96,6 +102,7 @@ def main():

transform_options = {
'canonicalize_roles': args.canonicalize_roles,
'reify_edges': args.reify_edges,
}
format_options = {
'indent': indent,
Expand Down
46 changes: 38 additions & 8 deletions penman/transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
Tree and graph transformations.
"""

from typing import List

from penman.types import BasicTriple
from penman.tree import (Tree, Node, is_atomic)
from penman.graph import Graph
from penman.model import Model
from penman.layout import (LayoutMarker, Push, POP)


def canonicalize_roles(t: Tree, model: Model) -> None:
def canonicalize_roles(t: Tree, model: Model) -> Tree:
"""
Normalize roles in *t* so they are canonical according to *model*.
Expand All @@ -18,29 +22,55 @@ def canonicalize_roles(t: Tree, model: Model) -> None:
"""
if model is None:
model = Model()
_canonicalize_node(t.node, model)
return Tree(_canonicalize_node(t.node, model), metadata=t.metadata)


def _canonicalize_node(node: Node, model: Model) -> None:
_, edges = node
def _canonicalize_node(node: Node, model: Model) -> Node:
id, edges = node
canonical_edges = []
for i, edge in enumerate(edges):
role, tgt, epidata = edge
if not is_atomic(tgt):
_canonicalize_node(tgt, model)
edges[i] = (model.canonicalize_role(role), tgt, epidata)
tgt = _canonicalize_node(tgt, model)
canonical_edges.append(
(model.canonicalize_role(role), tgt, list(epidata)))
return (id, canonical_edges)


def reify_edges(g: Graph, model: Model) -> None:
def reify_edges(g: Graph, model: Model) -> Graph:
"""
Reify all edges in *g* that have reifications in *model*.
"""
pass
vars = g.variables()
if model is None:
model = Model()
new_epidata = dict(g.epidata)
new_triples: List[BasicTriple] = []
for triple in g.triples:
if model.is_reifiable(triple):
in_triple, node_triple, out_triple = model.reify(triple, vars)
new_triples.extend((in_triple, node_triple, out_triple))
var = node_triple[0]
vars.add(var)
# manage epigraphical markers
new_epidata[in_triple] = [Push(var)]
new_epidata[node_triple] = [
epi for epi in new_epidata.pop(triple)
if not isinstance(epi, LayoutMarker)]
new_epidata[out_triple] = [POP]
else:
new_triples.append(triple)
return Graph(new_triples,
epidata=new_epidata,
metadata=g.metadata)


def contract_edges(g: Graph, model: Model) -> None:
"""
Contract all edges in *g* that have reifications in *model*.
"""
if model is None:
model = Model()
pass


Expand Down
49 changes: 35 additions & 14 deletions tests/test_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,40 +18,61 @@

def test_canonicalize_roles_default_codec():
parse = def_codec.parse
norm = lambda t: canonicalize_roles(t, def_model)
format = lambda t: def_codec.format(t, indent=None)

t = parse('(a / alpha :ARG1 (b / beta))')
canonicalize_roles(t, def_model)
t = norm(parse('(a / alpha :ARG1 (b / beta))'))
assert format(t) == '(a / alpha :ARG1 (b / beta))'

t = parse('(a / alpha :ARG1-of-of (b / beta))')
canonicalize_roles(t, def_model)
t = norm(parse('(a / alpha :ARG1-of-of (b / beta))'))
assert format(t) == '(a / alpha :ARG1 (b / beta))'

t = parse('(a / alpha :mod-of (b / beta))')
canonicalize_roles(t, def_model)
t = norm(parse('(a / alpha :mod-of (b / beta))'))
assert format(t) == '(a / alpha :mod-of (b / beta))'


def test_canonicalize_roles_amr_codec():
parse = amr_codec.parse
norm = lambda t: canonicalize_roles(t, amr_model)
format = lambda t: amr_codec.format(t, indent=None)

t = parse('(a / alpha :ARG1 (b / beta))')
canonicalize_roles(t, amr_model)
t = norm(parse('(a / alpha :ARG1 (b / beta))'))
assert format(t) == '(a / alpha :ARG1 (b / beta))'

t = parse('(a / alpha :ARG1-of-of (b / beta))')
canonicalize_roles(t, amr_model)
t = norm(parse('(a / alpha :ARG1-of-of (b / beta))'))
assert format(t) == '(a / alpha :ARG1 (b / beta))'

t = parse('(a / alpha :mod-of (b / beta))')
canonicalize_roles(t, amr_model)
t = norm(parse('(a / alpha :mod-of (b / beta))'))
assert format(t) == '(a / alpha :domain (b / beta))'


def reify_edges():
pass
def reify_edges_default_codec():
decode = def_codec.parse
norm = lambda g: reify_edges(g, def_model)
encode = lambda g: def_codec.encode(g, indent=None)

g = norm(decode('(a / alpha :mod 5)'))
assert encode(g) == '(a / alpha :mod 5)'

g = norm(decode('(a / alpha :mod-of (b / beta))'))
assert encode(g) == '(a / alpha :mod-of (b / beta))'


def reify_edges_amr_codec():
decode = amr_codec.parse
norm = lambda g: reify_edges(g, amr_model)
encode = lambda g: amr_codec.encode(g, indent=None)

g = norm(decode('(a / alpha :mod 5)'))
assert encode(g) == '(a / alpha :ARG0-of (_ / have-mod-91 :ARG1 5))'

g = norm(decode('(a / alpha :mod-of (b / beta))'))
assert encode(g) == '(a / alpha :ARG1-of (_ / have-mod-91 :ARG0 (b / beta))'

g = norm(decode('(a / alpha :mod-of (b / beta :polarity -))'))
assert encode(g) == (
'(a / alpha :ARG1-of (_ / have-mod-91 '
':ARG0 (b / beta :ARG0-of (_2 / have-polarity-91 :ARG1 -))))')


def contract_edges():
Expand Down

0 comments on commit ce402f0

Please sign in to comment.