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
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 """
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
62 start_nodes = []
63 for (pre_start, pre_end, pre_label) in self._edges_by_end.get(start, []):
64 if pre_label == label:
65
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
72 end_nodes = []
73 for (post_start, post_end, post_label) in self._edges_by_start.get(end, []):
74 if post_label == label:
75
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
82
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
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