1 """Harmonic structure from semantics.
2
3 Functions for converting a logical form to trees representing the harmonic
4 structure. This is a list of trees of the dependencies in the logical form.
5
6 """
7 """
8 ============================== License ========================================
9 Copyright (C) 2008, 2010-12 University of Edinburgh, Mark Granroth-Wilding
10
11 This file is part of The Jazz Parser.
12
13 The Jazz Parser is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 The Jazz Parser is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with The Jazz Parser. If not, see <http://www.gnu.org/licenses/>.
25
26 ============================ End license ======================================
27
28 """
29 __author__ = "Mark Granroth-Wilding <mark.granroth-wilding@ed.ac.uk>"
30
31 from .semantics import Semantics, List, EnharmonicCoordinate, \
32 FunctionApplication, Predicate, Coordination, Variable, \
33 LambdaAbstraction, Now
34 from jazzparser.misc.tree import ImmutableTree, Node
35 from jazzparser.data.dependencies import DependencyGraph
36
56
58 if type(lf) is EnharmonicCoordinate:
59
60 return Node(lf.zero_coord)
61 elif type(lf) is FunctionApplication:
62
63 arg_tree = lf_to_depedency_tree(lf.argument, bound_var=bound_var)
64
65 if isinstance(lf.functor, Predicate):
66 if type(lf.functor) is Now:
67
68 return arg_tree
69
70 leaf = Node(lf.functor.name)
71 arg_tree.leftmost_leaf().children.append(leaf)
72 return arg_tree
73 elif type(lf.functor) is Coordination:
74
75 trees = []
76 for cadence in lf.functor:
77
78 if type(cadence) is not LambdaAbstraction:
79 raise SemanticsToTreesError, "invalid cadence: %s" % cadence
80 var = cadence.variable
81
82
83 tree = lf_to_depedency_tree(cadence.expression, bound_var=var)
84
85
86 trees.append(tree[0])
87
88 arg_tree.leftmost_leaf().children = trees
89 return arg_tree
90 else:
91 raise SemanticsToTreesError, "unknown functor: %s (%s)" % \
92 (lf.functor, type(lf).__name__)
93 elif type(lf) is Variable:
94
95 if lf != bound_var:
96 raise SemanticsToTreesError, "got unbound variable '%s'. Bound "\
97 "variable was '%s'" % (lf, bound_var)
98
99 return Node("var")
100 else:
101 raise SemanticsToTreesError, "unhandled lf type: %s (%s)" % \
102 (lf, type(lf).__name__)
103
104
106 """
107 Converts the semantics to a L{jazzparser.data.dependencies.DependencyGraph}
108 of the dependencies in it. Returns this graph and a mapping from the
109 indices of the graph to the timings in the semantics.
110
111 """
112 if not isinstance(sems, Semantics):
113 raise SemanticsToDependenciesError, "input must be a Semantics. "\
114 "Got: %s" % type(sems).__name__
115 if not isinstance(sems.lf, List):
116 raise SemanticsToDependenciesError, "top level of semantics must be a "\
117 "List. Got '%s'" % type(sems.lf).__name__
118
119 all_arcs = []
120 next_index = 1
121 time_mapping = {}
122
123 root_arcs = []
124 for lf in sems.lf:
125
126 arcs,node_times,__,root_arc = lf_to_depedency_arcs(lf)
127
128
129
130 time_nodes = {}
131 rename = {}
132 for node,time in node_times.items():
133 if time in time_nodes:
134 rename[node] = time_nodes[time]
135 else:
136 time_nodes[time] = node
137 arcs = [(rename.get(source, source), rename.get(target, target), label) \
138 for (source,target,label) in arcs]
139
140 arcs = [(s,t,l) for (s,t,l) in arcs if s != t]
141 for node in rename:
142 del node_times[node]
143
144
145 arcs,node_times,root_arc = \
146 _reorder_nodes(arcs, node_times, root_arc, shift=next_index)
147 all_arcs.extend(arcs)
148 root_arcs.append(root_arc)
149 time_mapping.update(node_times)
150
151
152
153 next_index += len(node_times)
154
155
156 for (source, label) in root_arcs:
157 all_arcs.append((source,0,label))
158
159 return DependencyGraph(all_arcs), time_mapping
160
162
163 ordering = list(enumerate(sorted(node_times.items(), key=lambda x:x[1])))
164
165 ordering = [(i+shift, old) for (i,old) in ordering]
166
167 node_map = dict([(old_node,new_node) for (new_node,(old_node,time)) \
168 in ordering])
169 new_node_times = dict([(new_node,time) for (new_node,(old_node,time)) \
170 in ordering])
171
172 new_arcs = [(node_map[source], node_map[target], label) for \
173 (source,target,label) in arcs]
174
175 if root_arc is not None:
176 root_arc = (node_map[root_arc[0]], root_arc[1])
177 return new_arcs,new_node_times,root_arc
178
180 if type(lf) is EnharmonicCoordinate:
181
182
183
184 return [], {start_index: lf.time}, start_index, (start_index, lf)
185 elif type(lf) is FunctionApplication:
186
187 if type(lf.argument) is Variable:
188
189
190
191 if bound_var is None:
192 raise SemanticsToDependenciesError, "got unbound variable "\
193 "'%s'" % lf
194 arcs = []
195 node_times = {}
196 arg_start_index = bound_var
197 root_arc = None
198 else:
199 arcs,node_times,arg_start_index,root_arc = \
200 lf_to_depedency_arcs(lf.argument,
201 start_index=start_index,
202 bound_var=bound_var)
203
204 start_index += len(node_times)
205
206 if isinstance(lf.functor, Predicate):
207 if type(lf.functor) is Now:
208
209 return arcs,node_times,arg_start_index,root_arc
210
211
212 arcs.append((start_index, arg_start_index, lf.functor.name))
213 node_times[start_index] = lf.functor.time
214 outer_index = start_index
215 elif type(lf.functor) is Coordination:
216
217 for i,cadence in enumerate(lf.functor):
218
219 if type(cadence) is not LambdaAbstraction:
220 raise SemanticsToDependenciesError, "invalid cadence: %s" % cadence
221
222
223 cad_arcs,cad_times,cad_outer,__ = \
224 lf_to_depedency_arcs(cadence.expression,
225 start_index=start_index,
226 bound_var=arg_start_index)
227
228
229 start_index += len(cad_times)
230
231 arcs.extend(cad_arcs)
232
233 node_times.update(cad_times)
234
235 if i == 0:
236 outer_index = cad_outer
237 else:
238 raise SemanticsToTreesError, "unknown functor: %s (%s)" % \
239 (lf.functor, type(lf).__name__)
240
241 return arcs,node_times,outer_index,root_arc
242 elif type(lf) is Variable:
243 raise SemanticsToDependenciesError, "variable '%s' was found on its "\
244 "own. It should have had something applied to it" % lf
245 else:
246 raise SemanticsToDependenciesError, "unhandled lf type: %s (%s)" % \
247 (lf, type(lf).__name__)
248
249
252
255