Пример #1
0
    def fixRanges(self):
        rangeFuncList = [
            lambda n: (isPreposition(n) and n.prepType == "from" and len(
                self.gr.neighbors(n)) == 1), lambda n:
            ((isTime(n) or isLocation(n)) and len(self.gr.neighbors(n)) == 2),
            lambda n: (isPreposition(n) and n.prepType == "to" and len(
                self.gr.neighbors(n)) == 1), lambda n:
            ((isTime(n) or isLocation(n)) and len(self.gr.neighbors(n)) == 1)
        ]
        ls = findChain(self.gr, rangeFuncList)
        if not ls:
            return False

        [fromNode, start, toNode, end] = ls
        startNode = [
            n for n in self.gr.neighbors(start) if not isPreposition(n)
        ][0]
        endNode = self.gr.neighbors(end)[0]
        if isTime(start):
            rangeNode = TimeNode.init(features={"Range": True})
        elif isLocation(start):
            rangeNode = LocationNode.init(features={"Range": True})

        self.gr.add_node(rangeNode)
        if isTime(start):
            sonNode = Node(isPredicate=False,
                           text=startNode.text +
                           [Word(index=toNode.text[0].index, word="to")] +
                           endNode.text,
                           features={
                               'Time Value':
                               "-".join([
                                   startNode.features['Time Value'],
                                   endNode.features['Time Value']
                               ])
                           },
                           valid=True)
        elif isLocation(start):
            sonNode = Node(isPredicate=False,
                           text=startNode.text +
                           [Word(index=toNode.text[0].index, word="to")] +
                           endNode.text,
                           features={},
                           valid=True)
        self.gr.add_node(sonNode)
        self.gr.add_edge((rangeNode, sonNode))
        for curFather in self.gr.incidents(fromNode):
            duplicateEdge(graph=self.gr,
                          orig=(curFather, fromNode),
                          new=(curFather, rangeNode))

        delete_component(graph=self.gr, node=fromNode)
        self.types.add(APPENDIX_RANGE)
        return True
Пример #2
0
 def propogateFeatures(self):
     """
     handle propagating features between nodes of the graph
     
     @rtype  bool
     @return True iff this function has changed the graph in some way 
     """
     ret = False
     for curNode in self.gr.nodes():
         # for each node in the graph
         curNodeNeigbours = self.gr.neighbors(curNode)
         for curPropogateNode in curNode.propagateTo:
             # for each of its propgated nodes
             curPropogateNodeNeigboursIds = [
                 cpn.uid for cpn in self.gr.neighbors(curPropogateNode)
             ]
             for curNeigbour in curNodeNeigbours:
                 if isProp(curNeigbour) or isTime(curNeigbour):
                     # for each *prop* neigbour
                     if curNeigbour.uid not in curPropogateNodeNeigboursIds:
                         # if its not a neigbour of propogated node - add it
                         self.gr.add_edge(edge=(curPropogateNode,
                                                curNeigbour),
                                          label=self.gr.edge_label(
                                              (curNode, curNeigbour)))
                         # mark that a change was made to the graph
                         ret = True
     return ret
Пример #3
0
 def fixRanges(self):
     rangeFuncList = [lambda n:(isPreposition(n) and n.prepType == "from" and len(self.gr.neighbors(n))==1),
                      lambda n:((isTime(n) or isLocation(n)) and len(self.gr.neighbors(n))==2),
                      lambda n:(isPreposition(n) and n.prepType == "to" and len(self.gr.neighbors(n))==1),
                      lambda n:((isTime(n) or isLocation(n)) and len(self.gr.neighbors(n))==1)]
     ls = findChain(self.gr, rangeFuncList)
     if not ls:
         return False
     
     [fromNode,start,toNode,end] = ls
     startNode = [n for n in self.gr.neighbors(start) if not isPreposition(n)][0]
     endNode = self.gr.neighbors(end)[0]
     if isTime(start):
         rangeNode = TimeNode.init(features={"Range":True})
     elif isLocation(start):
         rangeNode = LocationNode.init(features={"Range":True})
         
     self.gr.add_node(rangeNode)
     if isTime(start):
         sonNode = Node(isPredicate=False,
                        text = startNode.text + [Word(index=toNode.text[0].index,word="to")]+ endNode.text,
                        features = {'Time Value':"-".join([startNode.features['Time Value'],
                                                           endNode.features['Time Value']])},
                        valid=True)
     elif isLocation(start):
         sonNode = Node(isPredicate=False,
                        text = startNode.text + [Word(index=toNode.text[0].index,word="to")]+ endNode.text,
                        features = {},
                        valid=True)
     self.gr.add_node(sonNode)
     self.gr.add_edge((rangeNode,sonNode))
     for curFather in self.gr.incidents(fromNode):
         duplicateEdge(graph=self.gr, 
                       orig=(curFather,fromNode), 
                       new=(curFather,rangeNode))
     
     delete_component(graph=self.gr, node=fromNode)
     self.types.add(APPENDIX_RANGE)
     return True
Пример #4
0
 def propogateFeatures(self):
     """
     handle propagating features between nodes of the graph
     
     @rtype  bool
     @return True iff this function has changed the graph in some way 
     """
     ret = False
     for curNode in self.gr.nodes():
         # for each node in the graph
         curNodeNeigbours = self.gr.neighbors(curNode)
         for curPropogateNode in curNode.propagateTo:
             # for each of its propgated nodes
             curPropogateNodeNeigboursIds = [cpn.uid for cpn in self.gr.neighbors(curPropogateNode)]
             for curNeigbour in curNodeNeigbours:
                 if isProp(curNeigbour) or isTime(curNeigbour):
                     # for each *prop* neigbour
                     if curNeigbour.uid not in curPropogateNodeNeigboursIds:
                         # if its not a neigbour of propogated node - add it
                         self.gr.add_edge(edge=(curPropogateNode,curNeigbour), 
                                          label=self.gr.edge_label((curNode,curNeigbour)))
                         # mark that a change was made to the graph
                         ret = True
     return ret
Пример #5
0
 def parsePossessive(self,possessor,possessed,possessive):
     """
     add a possessive subgraph to the graph
     
     @type  index: int
     @param index: the index of the possessive in the sentence
     
     @type  possessor: DepTree
     @param possessor: the syntax tree of the possessor
     
     @type  possessed: DepTree
     @param possessed: the syntax tree of the possessed
     
     @type  possessive: DepTree
     @param possessive: the syntax tree of the possessive - e.g - 's
     
     @rtype: Node
     @return: the top node of the possessive subgraph
     """
     
     if not possessive:
         index = graph_representation.word.NO_INDEX
     else:
         index = possessive.id
     
     # generate nodes
     possessorNode = self.parse(possessor)
     possessedNode = self.parse(possessed)
     
     if isTime(possessorNode) or isLocation(possessorNode):
         #possessive construction to indicate time
         self.gr.add_edge((possessedNode,possessorNode))
         return possessedNode
     
     #otherwise - proper possessive:
     hasNode = PossessiveNode.init(index=index,
                              features={}, 
                              valid=True)
     self.gr.add_node(hasNode)
     
     # add edges to graph
     self.gr.add_edge(edge=(hasNode,possessorNode), 
                      label=POSSESSOR_LABEL)
     self.gr.add_edge(edge=(hasNode,possessedNode), 
                      label=POSSESSED_LABEL)
     
     # create top node
     # get list of all relevant nodes
     nodeLs = [possessorNode,possessedNode]
     
     if possessive: # in some cases there's no possessive marker (e.g., "their woman")
         possessiveNode = graph_representation.node.Node(isPredicate=False,
                                                         text = [Word(possessive.id,
                                                                     possessive.get_original_sentence(root=False))],
                                                         features = {},
                                                         valid=True)
         nodeLs.append(possessiveNode)
     
     
     # create possessive top node, add to graph, and return it
     topNode = graph_utils.generate_possessive_top_node(graph=self.gr, nodeLs=nodeLs)
     self.gr.add_node(topNode)
     
     #mark that features and neighbours should propagate from the top node to the possessed
     # John's results were low -> features should propogate between (John's results) and (results)
     graph_representation.node.addSymmetricPropogation(topNode, possessedNode)
     
     return topNode 
Пример #6
0
 def parsePossessive(self,possessor,possessed,possessive):
     """
     add a possessive subgraph to the graph
     
     @type  index: int
     @param index: the index of the possessive in the sentence
     
     @type  possessor: DepTree
     @param possessor: the syntax tree of the possessor
     
     @type  possessed: DepTree
     @param possessed: the syntax tree of the possessed
     
     @type  possessive: DepTree
     @param possessive: the syntax tree of the possessive - e.g - 's
     
     @rtype: Node
     @return: the top node of the possessive subgraph
     """
     
     if not possessive:
         index = graph_representation.word.NO_INDEX
     else:
         index = possessive.id
     
     # generate nodes
     possessorNode = self.parse(possessor)
     possessedNode = self.parse(possessed)
     
     if isTime(possessorNode) or isLocation(possessorNode):
         #possessive construction to indicate time
         self.gr.add_edge((possessedNode,possessorNode))
         return possessedNode
     
     #otherwise - proper possessive:
     hasNode = PossessiveNode.init(index=index,
                              features={}, 
                              valid=True)
     self.gr.add_node(hasNode)
     
     # add edges to graph
     self.gr.add_edge(edge=(hasNode,possessorNode), 
                      label=POSSESSOR_LABEL)
     self.gr.add_edge(edge=(hasNode,possessedNode), 
                      label=POSSESSED_LABEL)
     
     # create top node
     # get list of all relevant nodes
     nodeLs = [possessorNode,possessedNode]
     
     if possessive: # in some cases there's no possessive marker (e.g., "their woman")
         possessiveNode = graph_representation.node.Node(isPredicate=False,
                                                         text = [Word(possessive.id,
                                                                     possessive.get_original_sentence(root=False))],
                                                         features = {},
                                                         valid=True)
         nodeLs.append(possessiveNode)
     
     
     # create possessive top node, add to graph, and return it
     topNode = graph_utils.generate_possessive_top_node(graph=self.gr, nodeLs=nodeLs)
     self.gr.add_node(topNode)
     
     #mark that features and neighbours should propagate from the top node to the possessed
     # John's results were low -> features should propogate between (John's results) and (results)
     graph_representation.node.addSymmetricPropogation(topNode, possessedNode)
     
     return topNode 
Пример #7
0
        def inner():
            change = False
            # 1,2
            nodes = find_nodes(self.gr, isCondition)
            nodes.extend(find_nodes(self.gr, isPreposition))
            for curNode in nodes:
                sisterNodes = sister_nodes(graph=self.gr, node=curNode)
                for sisterNode in sisterNodes:
                    if isProp(sisterNode) and is_following(graph=self.gr,
                                                           node1=sisterNode,
                                                           node2=curNode):
                        reattch(graph=self.gr, 
                                node=curNode, 
                                new_father=sisterNode)
                        return True
                        break
            # 3
            nodes = find_nodes(self.gr, isAdverb)
            for curNode in nodes:
                sisterNodes = sister_nodes(graph=self.gr, node=curNode)
                for sisterNode in sisterNodes:
                    if isProp(sisterNode) and is_following(graph=self.gr,
                                                           node1=curNode,
                                                           node2=sisterNode):
                        reattch(graph=self.gr, 
                                node=curNode, 
                                new_father=sisterNode)
                        return True
                        break
                    
            #4
            nodes = find_nodes(self.gr,
                               lambda n:isCondition(n) and n.text[0].word == "{0}-{1}".format(COND,'that'))
            for curNode in nodes:
                curFathers = self.gr.incidents(curNode)
                curChildren = self.gr.neighbors(curNode)
                for curFather in curFathers:
                    for curChild in curChildren:
                        self.gr.add_edge(edge = (curFather,curChild),
                                         label = "that")
                self.gr.del_node(curNode)
                change = True
            
            #5
            filterFunc = lambda n:isConjunction(n) and len(self.gr.incidents(n)) == 1 and isConjunction(self.gr.incidents(n)[0]) and (n.conjType  == self.gr.incidents(n)[0].conjType) #TODO: efficiency - multiple calls to incidents and a lot of deref
            nodes = find_nodes(self.gr,filterFunc)
                               
            for curNode in nodes:
                curFather = self.gr.incidents(curNode)[0]
                for curChild in self.gr.neighbors(curNode):
                    self.gr.add_edge((curFather,curChild))
                self.gr.del_node(curNode)
                change = True 
                
            #6
            nodes = find_nodes(self.gr,
                               lambda n:len(n.text)==1 and n.text[0].word == "able")
            for curNode in nodes:
                curFathers = self.gr.incidents(curNode)
                if len(curFathers)==1:
                    curChildren = self.gr.neighbors(curNode)
                    if len(curChildren) ==1:
                        child = curChildren[0]
                        if child.isPredicate and (self.gr.edge_label((curNode,child))=="xcomp"):
                            father = curFathers[0]
                            self.gr.add_edge(edge=(father,child),
                                             label=self.gr.edge_label((father,curNode)))
                            child.features["Modal"]={"Value":['able']} #TODO: is this maybe overrun previous modals?
                            self.gr.del_node(curNode)
                            change=True
            #7
            edges = find_edges(self.gr,
                               lambda (u,v):isTime(u)and isTime(v) and len(self.gr.neighbors(u))==1)
            for curFather,curSon in edges:
                for curNode in self.gr.neighbors(curSon):
                    self.gr.add_edge(edge=(curFather,curNode),
                                     label = self.gr.edge_label((curSon,curNode)))
                self.gr.del_node(curSon)
                return True
            
            #8
            edges = find_edges(self.gr,
                               lambda (u,v):(isTime(v) or isLocation(v)) and isPreposition(u) and u.is_time_prep())
            
            for prepNode,timeNode in edges:
                if (len(self.gr.neighbors(prepNode))==1):
                    # time node is only son - attach time to all of prep incidents
                    for curFather in self.gr.incidents(prepNode):
                        self.gr.add_edge(edge=(curFather,timeNode),
                                         label = self.gr.edge_label((curFather,prepNode)))
                    self.gr.del_node(prepNode)
                    change=True
                    
            #9
            conjNodes = find_nodes(self.gr, lambda n: isConjunction(n) and n.conjType.lower() == "and")
            for conjNode in conjNodes:
                curParents = []
                curChildren = self.gr.neighbors(conjNode)
                for curChild in curChildren:
                    curParents.extend([parent for parent in self.gr.incidents(curChild) if parent != conjNode])
                
                if len(curParents)==1:
                    parent = curParents[0]
                    if isProp(parent):
                        # found a prop->conj construction 
                        # connect all prop to parent of conj and remove the conj node
                        for child in curChildren:
                            if not (parent,child) in self.gr.edges():
                                self.gr.add_edge(edge = (parent,child))
                        self.gr.del_node(conjNode)
                        change = True
                        
                    
            
            #10
            change = change or self.fixRanges()
            
            #11
            edges = find_edges(self.gr,
                               lambda (u,v):self.gr.edge_label((u,v))=="loc" and len(self.gr.neighbors(u))>1)
            
            for topNode,loc in edges:
                for curNeigbor in self.gr.neighbors(topNode):
                    if curNeigbor != loc:
                        duplicateEdge(graph=self.gr, orig=(topNode,curNeigbor), new=(loc,curNeigbor))
                for curFather in self.gr.incidents(topNode):
                    duplicateEdge(graph=self.gr, orig=(curFather,topNode), new=(curFather,loc))
                self.gr.del_node(topNode)
                self.types.remove(APPENDIX_LOCATION)
                change=True
                    
            
            #12
            edges = find_edges(graph=self.gr, 
                               filterFunc = lambda (u,v): isProp(u) and isLocation(v))
            
            for _,locNode in edges:
                for curFather in self.gr.incidents(locNode):
                    for curNeighbour in self.gr.neighbors(locNode):
                        duplicateEdge(graph=self.gr, orig=(locNode,curNeighbour), new=(curFather,curNeighbour))
                self.gr.del_node(locNode)
                self.types.remove(APPENDIX_LOCATION)
                change=True
                
            #13
            edges = find_edges(graph=self.gr, 
                               filterFunc = lambda (u,v): isProp(u) and v.isPredicate and (len(self.gr.neighbors(v)) ==0) and (len(self.gr.incidents(u)) ==1) and (len(self.gr.neighbors(u)) ==1))
            
            for propNode,predNode in edges:
                change = True
                curFather = self.gr.incidents(propNode)[0]
                if not isApposition(curFather):
                    jointNode = node.join(node1=curFather, 
                                          node2=predNode, 
                                          gr=self.gr)
                    curFather.text = jointNode.text
                    self.gr.del_nodes([propNode,predNode])
                else:
                    self.gr.del_node(propNode)
                    self.gr.add_edge((predNode,curFather))
                    for curIncident in self.gr.incidents(curFather):
                        duplicateEdge(graph=self.gr, 
                                      orig=(curIncident,curFather), 
                                      new=(curIncident,predNode))
                        self.gr.del_edge((curIncident,curFather))
                        
                        
            #14
            propNodes = find_nodes(self.gr, lambda n:isProp(n) and len(self.gr.incidents(n))==1)
            for propNode in propNodes:
                curFather = self.gr.incidents(propNode)[0]
                if ((len(curFather.str)==1) and (not isCopular(curFather)) and (curFather.str[0].word == "be" or curFather.str[0].word in contractions)) or ((isProp(curFather) or isRcmodProp(curFather)) and len(self.gr.neighbors(curFather))==1):
                    if len(self.gr.incidents(curFather))==1:                    
                        curAncestor = self.gr.incidents(curFather)[0]
                        duplicateEdge(graph=self.gr,
                                      orig=(curAncestor,curFather), 
                                      new=(curAncestor,propNode))
                        self.gr.del_node(curFather)
                        # this node no longer describes the "be" relation
                        propNode.parent_relation = ''
                        return True
            
            #15
            edges = find_edges(graph=self.gr, 
                               filterFunc = lambda (u,v): isProp(v) and (v.parent_relation == "acomp") and len(self.gr.neighbors(v))==1 and u.isPredicate)
            
            for pred, prop in edges:
                acompNode = self.gr.neighbors(prop)[0]
                duplicateEdge(graph=self.gr, orig=(pred,prop), new=(pred,acompNode),
                              newLabel = "modifier")
                self.gr.del_node(prop) # TODO: could there be others connected to it?
                newPred = node.join(pred,acompNode,self.gr)
                newPred.isPredicate =True
                self.gr.add_node(newPred)
                for neigbour in self.gr.neighbors(pred):
                    duplicateEdge(graph=self.gr, orig=(pred,neigbour), new=(newPred,neigbour))
                
                for curFather in self.gr.incidents(pred):
                    duplicateEdge(graph=self.gr, orig=(curFather,pred), new=(curFather,newPred))
                
                if len(self.gr.neighbors(acompNode))==0:
                    self.gr.del_node(acompNode)
                    
                self.gr.del_node(pred)
#                 newPred.features["debug"] =True #TODO: remove this
                self.types.add("ACOMP")
                return True
            
            #16
            edges = find_edges(graph=self.gr,
                               filterFunc = lambda (u,v): (isProp(v) or isRcmodProp(v)) and (u in self.gr.neighbors(v)))
            
            for _,v in edges:
                if (len(self.gr.neighbors(v))==1):
                    self.gr.del_node(v)
                    return True
            
            #17
            edges = find_edges(graph=self.gr,
                               filterFunc = lambda (u,v): self.gr.edge_label((u,v))==SOURCE_LABEL and (len(self.gr.neighbors(v))==0))
            for _,v in edges:
                curStr = " ".join([w.word for w in v.text])
                if curStr in contractions:
                    self.gr.del_node(v)
                    return True
                        
            #18 - verbal complements
            edges = find_edges(graph=self.gr,
                               filterFunc = lambda (u,v): self.gr.edge_label((u,v))=='ccomp' and u.isPredicate)
            for u,v in edges:
                self.gr.del_edge((u,v))
                self.gr.add_edge(edge=(u,v),
                                 label = 'dobj')
                v.features["debug"] =True
                self.types.add("DEBUG")
                return True
                    
            return change
Пример #8
0
        def inner():
            change = False
            # 1,2
            nodes = find_nodes(self.gr, isCondition)
            nodes.extend(find_nodes(self.gr, isPreposition))
            for curNode in nodes:
                sisterNodes = sister_nodes(graph=self.gr, node=curNode)
                for sisterNode in sisterNodes:
                    if isProp(sisterNode) and is_following(
                            graph=self.gr, node1=sisterNode, node2=curNode):
                        reattch(graph=self.gr,
                                node=curNode,
                                new_father=sisterNode)
                        return True
                        break
            # 3
            nodes = find_nodes(self.gr, isAdverb)
            for curNode in nodes:
                sisterNodes = sister_nodes(graph=self.gr, node=curNode)
                for sisterNode in sisterNodes:
                    if isProp(sisterNode) and is_following(
                            graph=self.gr, node1=curNode, node2=sisterNode):
                        reattch(graph=self.gr,
                                node=curNode,
                                new_father=sisterNode)
                        return True
                        break

            #4
            nodes = find_nodes(
                self.gr, lambda n: isCondition(n) and n.text[0].word ==
                "{0}-{1}".format(COND, 'that'))
            for curNode in nodes:
                curFathers = self.gr.incidents(curNode)
                curChildren = self.gr.neighbors(curNode)
                for curFather in curFathers:
                    for curChild in curChildren:
                        self.gr.add_edge(edge=(curFather, curChild),
                                         label="that")
                self.gr.del_node(curNode)
                change = True

            #5
            filterFunc = lambda n: isConjunction(n) and len(
                self.gr.incidents(n)
            ) == 1 and isConjunction(self.gr.incidents(n)[0]) and (
                n.conjType == self.gr.incidents(n)[0].conjType
            )  #TODO: efficiency - multiple calls to incidents and a lot of deref
            nodes = find_nodes(self.gr, filterFunc)

            for curNode in nodes:
                curFather = self.gr.incidents(curNode)[0]
                for curChild in self.gr.neighbors(curNode):
                    self.gr.add_edge((curFather, curChild))
                self.gr.del_node(curNode)
                change = True

            #6
            nodes = find_nodes(
                self.gr,
                lambda n: len(n.text) == 1 and n.text[0].word == "able")
            for curNode in nodes:
                curFathers = self.gr.incidents(curNode)
                if len(curFathers) == 1:
                    curChildren = self.gr.neighbors(curNode)
                    if len(curChildren) == 1:
                        child = curChildren[0]
                        if child.isPredicate and (self.gr.edge_label(
                            (curNode, child)) == "xcomp"):
                            father = curFathers[0]
                            self.gr.add_edge(edge=(father, child),
                                             label=self.gr.edge_label(
                                                 (father, curNode)))
                            child.features["Modal"] = {
                                "Value": ['able']
                            }  #TODO: is this maybe overrun previous modals?
                            self.gr.del_node(curNode)
                            change = True
            #7
            edges = find_edges(
                self.gr, lambda (u, v): isTime(u) and isTime(v) and len(
                    self.gr.neighbors(u)) == 1)
            for curFather, curSon in edges:
                for curNode in self.gr.neighbors(curSon):
                    self.gr.add_edge(edge=(curFather, curNode),
                                     label=self.gr.edge_label(
                                         (curSon, curNode)))
                self.gr.del_node(curSon)
                return True

            #8
            edges = find_edges(
                self.gr, lambda (u, v): (isTime(v) or isLocation(v)) and
                isPreposition(u) and u.is_time_prep())

            for prepNode, timeNode in edges:
                if (len(self.gr.neighbors(prepNode)) == 1):
                    # time node is only son - attach time to all of prep incidents
                    for curFather in self.gr.incidents(prepNode):
                        self.gr.add_edge(edge=(curFather, timeNode),
                                         label=self.gr.edge_label(
                                             (curFather, prepNode)))
                    self.gr.del_node(prepNode)
                    change = True

            #9
            conjNodes = find_nodes(
                self.gr,
                lambda n: isConjunction(n) and n.conjType.lower() == "and")
            for conjNode in conjNodes:
                curParents = []
                curChildren = self.gr.neighbors(conjNode)
                for curChild in curChildren:
                    curParents.extend([
                        parent for parent in self.gr.incidents(curChild)
                        if parent != conjNode
                    ])

                if len(curParents) == 1:
                    parent = curParents[0]
                    if isProp(parent):
                        # found a prop->conj construction
                        # connect all prop to parent of conj and remove the conj node
                        for child in curChildren:
                            if not (parent, child) in self.gr.edges():
                                self.gr.add_edge(edge=(parent, child))
                        self.gr.del_node(conjNode)
                        change = True

            #10
            change = change or self.fixRanges()

            #11
            edges = find_edges(
                self.gr, lambda (u, v): self.gr.edge_label(
                    (u, v)) == "loc" and len(self.gr.neighbors(u)) > 1)

            for topNode, loc in edges:
                for curNeigbor in self.gr.neighbors(topNode):
                    if curNeigbor != loc:
                        duplicateEdge(graph=self.gr,
                                      orig=(topNode, curNeigbor),
                                      new=(loc, curNeigbor))
                for curFather in self.gr.incidents(topNode):
                    duplicateEdge(graph=self.gr,
                                  orig=(curFather, topNode),
                                  new=(curFather, loc))
                self.gr.del_node(topNode)
                self.types.remove(APPENDIX_LOCATION)
                change = True

            #12
            edges = find_edges(graph=self.gr,
                               filterFunc=lambda
                               (u, v): isProp(u) and isLocation(v))

            for _, locNode in edges:
                for curFather in self.gr.incidents(locNode):
                    for curNeighbour in self.gr.neighbors(locNode):
                        duplicateEdge(graph=self.gr,
                                      orig=(locNode, curNeighbour),
                                      new=(curFather, curNeighbour))
                self.gr.del_node(locNode)
                self.types.remove(APPENDIX_LOCATION)
                change = True

            #13
            edges = find_edges(graph=self.gr,
                               filterFunc=lambda
                               (u, v): isProp(u) and v.isPredicate and
                               (len(self.gr.neighbors(v)) == 0) and
                               (len(self.gr.incidents(u)) == 1) and
                               (len(self.gr.neighbors(u)) == 1))

            for propNode, predNode in edges:
                change = True
                curFather = self.gr.incidents(propNode)[0]
                if not isApposition(curFather):
                    jointNode = node.join(node1=curFather,
                                          node2=predNode,
                                          gr=self.gr)
                    curFather.text = jointNode.text
                    self.gr.del_nodes([propNode, predNode])
                else:
                    self.gr.del_node(propNode)
                    self.gr.add_edge((predNode, curFather))
                    for curIncident in self.gr.incidents(curFather):
                        duplicateEdge(graph=self.gr,
                                      orig=(curIncident, curFather),
                                      new=(curIncident, predNode))
                        self.gr.del_edge((curIncident, curFather))

            #14
            propNodes = find_nodes(
                self.gr,
                lambda n: isProp(n) and len(self.gr.incidents(n)) == 1)
            for propNode in propNodes:
                curFather = self.gr.incidents(propNode)[0]
                if ((len(curFather.str) == 1) and
                    (not isCopular(curFather)) and
                    (curFather.str[0].word == "be"
                     or curFather.str[0].word in contractions)) or (
                         (isProp(curFather) or isRcmodProp(curFather))
                         and len(self.gr.neighbors(curFather)) == 1):
                    if len(self.gr.incidents(curFather)) == 1:
                        curAncestor = self.gr.incidents(curFather)[0]
                        duplicateEdge(graph=self.gr,
                                      orig=(curAncestor, curFather),
                                      new=(curAncestor, propNode))
                        self.gr.del_node(curFather)
                        # this node no longer describes the "be" relation
                        propNode.parent_relation = ''
                        return True

            #15
            edges = find_edges(
                graph=self.gr,
                filterFunc=lambda
                (u, v): isProp(v) and (v.parent_relation == "acomp") and len(
                    self.gr.neighbors(v)) == 1 and u.isPredicate)

            for pred, prop in edges:
                acompNode = self.gr.neighbors(prop)[0]
                duplicateEdge(graph=self.gr,
                              orig=(pred, prop),
                              new=(pred, acompNode),
                              newLabel="modifier")
                self.gr.del_node(
                    prop)  # TODO: could there be others connected to it?
                newPred = node.join(pred, acompNode, self.gr)
                newPred.isPredicate = True
                self.gr.add_node(newPred)
                for neigbour in self.gr.neighbors(pred):
                    duplicateEdge(graph=self.gr,
                                  orig=(pred, neigbour),
                                  new=(newPred, neigbour))

                for curFather in self.gr.incidents(pred):
                    duplicateEdge(graph=self.gr,
                                  orig=(curFather, pred),
                                  new=(curFather, newPred))

                if len(self.gr.neighbors(acompNode)) == 0:
                    self.gr.del_node(acompNode)

                self.gr.del_node(pred)
                #                 newPred.features["debug"] =True #TODO: remove this
                self.types.add("ACOMP")
                return True

            #16
            edges = find_edges(graph=self.gr,
                               filterFunc=lambda (u, v):
                               (isProp(v) or isRcmodProp(v)) and
                               (u in self.gr.neighbors(v)))

            for _, v in edges:
                if (len(self.gr.neighbors(v)) == 1):
                    self.gr.del_node(v)
                    return True

            #17
            edges = find_edges(graph=self.gr,
                               filterFunc=lambda (u, v): self.gr.edge_label(
                                   (u, v)) == SOURCE_LABEL and
                               (len(self.gr.neighbors(v)) == 0))
            for _, v in edges:
                curStr = " ".join([w.word for w in v.text])
                if curStr in contractions:
                    self.gr.del_node(v)
                    return True

            #18 - verbal complements
            edges = find_edges(graph=self.gr,
                               filterFunc=lambda (u, v): self.gr.edge_label(
                                   (u, v)) == 'ccomp' and u.isPredicate)
            for u, v in edges:
                self.gr.del_edge((u, v))
                self.gr.add_edge(edge=(u, v), label='dobj')
                v.features["debug"] = True
                self.types.add("DEBUG")
                return True

            return change