Fix bug in sentence starts for non-projective parses

The set_children_from_heads function assumed parse trees were
projective. However, non-projective parses may be passed in during
deserialization, or after deprojectivising. This caused incorrect
sentence boundaries to be set for non-projective parses. Close #2772.
This commit is contained in:
Matthew Honnibal 2018-09-19 14:50:06 +02:00
parent 48fd36bf05
commit 1759abf1e5
2 changed files with 22 additions and 20 deletions

View File

@ -2,7 +2,6 @@
import pytest import pytest
from ..util import get_doc from ..util import get_doc
@pytest.mark.xfail
def test_issue2772(en_vocab): def test_issue2772(en_vocab):
words = 'When we write or communicate virtually , we can hide our true feelings .'.split() words = 'When we write or communicate virtually , we can hide our true feelings .'.split()
# A tree with a non-projective (i.e. crossing) arc # A tree with a non-projective (i.e. crossing) arc

View File

@ -993,25 +993,28 @@ cdef int set_children_from_heads(TokenC* tokens, int length) except -1:
tokens[i].r_kids = 0 tokens[i].r_kids = 0
tokens[i].l_edge = i tokens[i].l_edge = i
tokens[i].r_edge = i tokens[i].r_edge = i
# Set left edges # Twice, for non-projectivity
for i in range(length): for _ in range(2):
child = &tokens[i] # Set left edges
head = &tokens[i + child.head] for i in range(length):
if child < head: child = &tokens[i]
head.l_kids += 1 head = &tokens[i + child.head]
if child.l_edge < head.l_edge: if child < head:
head.l_edge = child.l_edge head.l_kids += 1
if child.l_edge < head.l_edge:
# Set right edges --- same as above, but iterate in reverse head.l_edge = child.l_edge
for i in range(length-1, -1, -1): if child.r_edge > head.r_edge:
child = &tokens[i] head.r_edge = child.r_edge
head = &tokens[i + child.head] # Set right edges --- same as above, but iterate in reverse
if child > head: for i in range(length-1, -1, -1):
head.r_kids += 1 child = &tokens[i]
if child.r_edge > head.r_edge: head = &tokens[i + child.head]
head.r_edge = child.r_edge if child > head:
head.r_kids += 1
if child.r_edge > head.r_edge:
head.r_edge = child.r_edge
if child.l_edge < head.l_edge:
head.l_edge = child.l_edge
# Set sentence starts # Set sentence starts
for i in range(length): for i in range(length):
if tokens[i].head == 0 and tokens[i].dep != 0: if tokens[i].head == 0 and tokens[i].dep != 0: