Package jazzparser :: Package parsers :: Package base :: Module utils
[hide private]
[frames] | no frames]

Source Code for Module jazzparser.parsers.base.utils

 1  """Utils for chart-related processing 
 2   
 3  """ 
 4  """ 
 5  ============================== License ======================================== 
 6   Copyright (C) 2008, 2010-12 University of Edinburgh, Mark Granroth-Wilding 
 7    
 8   This file is part of The Jazz Parser. 
 9    
10   The Jazz Parser is free software: you can redistribute it and/or modify 
11   it under the terms of the GNU General Public License as published by 
12   the Free Software Foundation, either version 3 of the License, or 
13   (at your option) any later version. 
14    
15   The Jazz Parser is distributed in the hope that it will be useful, 
16   but WITHOUT ANY WARRANTY; without even the implied warranty of 
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
18   GNU General Public License for more details. 
19    
20   You should have received a copy of the GNU General Public License 
21   along with The Jazz Parser.  If not, see <http://www.gnu.org/licenses/>. 
22   
23  ============================ End license ====================================== 
24   
25  """ 
26  __author__ = "Mark Granroth-Wilding <mark.granroth-wilding@ed.ac.uk>"  
27   
28 -class SpanCombiner(object):
29 """ 30 For various purposes, we want to combine adjacent identical spanning 31 edges into one before adding them to the chart. This class makes it 32 easy to keep track of what additional edges should be added when a 33 new edges is added to do this. 34 35 Use this by adding edges to this combiner in the order they'd get added 36 to the main chart (from the lexicon). L{combine_edge} returns the additional 37 spans that should be added along with this edge (with the same 38 category). We assume that those additional edges were added - 39 they get added to the combiner for future reference. 40 41 """
42 - def __init__(self):
43 self.edges = [] 44 self._edges_by_start = {} 45 self._edges_by_end = {} 46 self.edge_properties = {}
47
48 - def add_edge(self, edge, properties=None):
49 self.edges.append(edge) 50 self._edges_by_start.setdefault(edge[0], []).append(edge) 51 self._edges_by_end.setdefault(edge[1], []).append(edge) 52 self.edge_properties[edge] = properties
53
54 - def combine_edge(self, edge, 55 properties=None, 56 prop_combiner=lambda x:None):
57 start,end,label = edge 58 self.add_edge(edge, properties=properties) 59 60 new_edges = [] 61 # Look for edges that combine with this at the beginning 62 start_nodes = [] 63 for (pre_start, pre_end, pre_label) in self._edges_by_end.get(start, []): 64 if pre_label == label: 65 # Match: combine these 66 pre_props = self.edge_properties[(pre_start,pre_end,label)] 67 start_nodes.append((pre_start, pre_props)) 68 new_edges.append((pre_start, end, 69 prop_combiner((pre_props,properties)) )) 70 71 # Look for edges that combine at the end 72 end_nodes = [] 73 for (post_start, post_end, post_label) in self._edges_by_start.get(end, []): 74 if post_label == label: 75 # Match: combine 76 post_props = self.edge_properties[(post_start,post_end,label)] 77 end_nodes.append((post_end,post_props)) 78 new_edges.append((start, post_end, 79 prop_combiner((properties,post_props)) )) 80 81 # If we match at the start and end, we can also combine all three 82 # into one big edge 83 for (pre_start,pre_props) in start_nodes: 84 for (post_end,post_props) in end_nodes: 85 new_edges.append((pre_start, post_end, 86 prop_combiner((pre_props,properties,post_props)) )) 87 88 # Add all of these new ones for future reference 89 for (nstart, nend, props) in new_edges: 90 self.add_edge((nstart, nend, label), properties=props) 91 92 return [(start,end) for (start,end,props) in new_edges]
93