def distance(self, sem1, sem2): from jazzparser.formalisms.music_halfspan.harmstruct import \ semantics_to_dependency_trees # Get dependency graphs for the two logical forms trees1 = semantics_to_dependency_trees(sem1) trees2 = semantics_to_dependency_trees(sem2) # Count the number of dependencies in each graph len1 = sum([len(tree) for tree in trees1]) len2 = sum([len(tree) for tree in trees2]) # Take the ratio between the sizes if len1 > len2: return 1.0 - (float(len2) / len1) else: return 1.0 - (float(len1) / len2)
def test_call_me_irresponsible(self): # Call Me Irresponsible cadence sem = semantics_from_string( r"[<0,0>, " r"(((\$y.(((\$x.leftonto(leftonto(leftonto(leftonto(leftonto($x)))))) " r"& (\$x.leftonto(leftonto($x)))) leftonto($y))) " r"& (\$x.leftonto(leftonto($x)))) <0,0>)]" ) trees = semantics_to_dependency_trees(sem) self.assertEqual(len(trees), 2) # One node in first tree self.assertEqual(len(trees[0]), 1) # Second tree is the hard one! # Should look like this: # <(0,0)/(0,0)> # (leftonto( # leftonto(leftonto(leftonto(leftonto(leftonto)))) # leftonto(leftonto)) # leftonto(leftonto)) # Check some things about the structure tree = trees[1].root # First split (just after root) self.assertEqual(len(tree), 2) # Other split self.assertEqual(len(tree[0]), 2) # Others should not split self.assertEqual(len(tree[0][0]), 1) self.assertEqual(len(tree[0][0][0]), 1) self.assertEqual(len(tree[0][0][0][0]), 1) self.assertEqual(len(tree[0][0][0][0][0]), 1) # This is the lowest leaf self.assertTrue(tree[0][0][0][0][0][0].is_leaf())
def test_call_me_irresponsible(self): # Call Me Irresponsible cadence sem = semantics_from_string(r"[<0,0>, "\ r"(((\$y.(((\$x.leftonto(leftonto(leftonto(leftonto(leftonto($x)))))) "\ r"& (\$x.leftonto(leftonto($x)))) leftonto($y))) "\ r"& (\$x.leftonto(leftonto($x)))) <0,0>)]") trees = semantics_to_dependency_trees(sem) self.assertEqual(len(trees), 2) # One node in first tree self.assertEqual(len(trees[0]), 1) # Second tree is the hard one! # Should look like this: # <(0,0)/(0,0)> # (leftonto( # leftonto(leftonto(leftonto(leftonto(leftonto)))) # leftonto(leftonto)) # leftonto(leftonto)) # Check some things about the structure tree = trees[1].root # First split (just after root) self.assertEqual(len(tree), 2) # Other split self.assertEqual(len(tree[0]), 2) # Others should not split self.assertEqual(len(tree[0][0]), 1) self.assertEqual(len(tree[0][0][0]), 1) self.assertEqual(len(tree[0][0][0][0]), 1) self.assertEqual(len(tree[0][0][0][0][0]), 1) # This is the lowest leaf self.assertTrue(tree[0][0][0][0][0][0].is_leaf())
def test_coordinate(self): # Build a semantics of a single point sem = semantics_from_string("[<3,1>]") # Build a tree for this trees = semantics_to_dependency_trees(sem) # Should be only one tree self.assertEqual(len(trees), 1) # Should just contain the root node corresponding to the point self.assertEqual(len(trees[0]), 1)
def test_coordinate(self): # Build a semantics of a single point sem = semantics_from_string("[<3,1>]") # Build a tree for this trees = semantics_to_dependency_trees(sem) # Should be only one tree self.assertEqual(len(trees), 1) # Should just contain the root node corresponding to the point self.assertEqual(len(trees[0]), 1)
def test_coordinates(self): # Build a semantics of two points sem = semantics_from_string("[<3,1>, <2,2>]") # Build a tree for this trees = semantics_to_dependency_trees(sem) # Should be two trees self.assertEqual(len(trees), 2) # Should just contain the root node each corresponding to the points self.assertEqual(len(trees[0]), 1) self.assertEqual(len(trees[1]), 1)
def test_coordinates(self): # Build a semantics of two points sem = semantics_from_string("[<3,1>, <2,2>]") # Build a tree for this trees = semantics_to_dependency_trees(sem) # Should be two trees self.assertEqual(len(trees), 2) # Should just contain the root node each corresponding to the points self.assertEqual(len(trees[0]), 1) self.assertEqual(len(trees[1]), 1)
def test_predicates(self): # Build a semantics of a leftonto/rightonto with resolution sem = semantics_from_string("[leftonto(<0,0>)]") # Build a tree for this trees = semantics_to_dependency_trees(sem) # Should have two nodes, leaf should be leftonto self.assertEqual(len(trees[0]), 2) self.assertEqual(trees[0][0].label, "leftonto") sem = semantics_from_string("[rightonto(<0,0>)]") trees = semantics_to_dependency_trees(sem) # Should have two nodes, leaf should be rightonto self.assertEqual(len(trees[0]), 2) self.assertEqual(trees[0][0].label, "rightonto") # Try multiple applications sem = semantics_from_string("[leftonto(leftonto(leftonto(<0,0>)))]") trees = semantics_to_dependency_trees(sem) # Should have 4 nodes self.assertEqual(len(trees[0]), 4)
def test_predicates(self): # Build a semantics of a leftonto/rightonto with resolution sem = semantics_from_string("[leftonto(<0,0>)]") # Build a tree for this trees = semantics_to_dependency_trees(sem) # Should have two nodes, leaf should be leftonto self.assertEqual(len(trees[0]), 2) self.assertEqual(trees[0][0].label, "leftonto") sem = semantics_from_string("[rightonto(<0,0>)]") trees = semantics_to_dependency_trees(sem) # Should have two nodes, leaf should be rightonto self.assertEqual(len(trees[0]), 2) self.assertEqual(trees[0][0].label, "rightonto") # Try multiple applications sem = semantics_from_string("[leftonto(leftonto(leftonto(<0,0>)))]") trees = semantics_to_dependency_trees(sem) # Should have 4 nodes self.assertEqual(len(trees[0]), 4)
def test_coordination(self): # Build a semantics of a coordination sem = semantics_from_string(r"[((\$x.leftonto($x)) & (\$y.leftonto($y)) leftonto(<0,0>))]") trees = semantics_to_dependency_trees(sem) # Should look like this: # <(0,0)/(0,0)>(leftonto(leftonto leftonto)) self.assertEqual(len(trees), 1) tree = trees[0] self.assertEqual(tree.root.label, (0, 0)) self.assertEqual(tree[0].label, "leftonto") self.assertEqual(tree[0][0].label, "leftonto") self.assertEqual(tree[0][1].label, "leftonto")
def test_coordination(self): # Build a semantics of a coordination sem = semantics_from_string(r"[((\$x.leftonto($x)) & (\$y.leftonto($y)) leftonto(<0,0>))]") trees = semantics_to_dependency_trees(sem) # Should look like this: # <(0,0)/(0,0)>(leftonto(leftonto leftonto)) self.assertEqual(len(trees), 1) tree = trees[0] self.assertEqual(tree.root.label, (0,0)) self.assertEqual(tree[0].label, "leftonto") self.assertEqual(tree[0][0].label, "leftonto") self.assertEqual(tree[0][1].label, "leftonto")
def run(self, args, state): from jazzparser.formalisms.music_halfspan.harmstruct import \ semantics_to_dependency_trees if self.options['res']: resnum = int(args[0]) res = state.results[resnum] song = res.semantics print "Dependency tree for result %d\n" % resnum else: songnum = int(args[0]) name, song = get_song(songnum, state) print "Dependency tree for '%s'\n" % name print "Semantics:" print song print "\nTrees:" for t in semantics_to_dependency_trees(song): print t
def fscore_match(self, sem1, sem2): """ The core computation of the distance metric. Takes care of the tree comparison and cadence alignment and return the vital statistics. """ from jazzparser.formalisms.music_halfspan.harmstruct import \ semantics_to_dependency_trees from jazzparser.misc.tree.lces import lces_size from jazzparser.utils.distance import align res_score = self.options['res_score'] # Get dependency graphs for the two logical forms if sem1 is None: trees1 = [] else: trees1 = semantics_to_dependency_trees(sem1) if sem2 is None: trees2 = [] else: trees2 = semantics_to_dependency_trees(sem2) if sem1 is None or sem2 is None: # Empty input: give zero score to everything alignment_score = 0.0 alignment = [] transpose = None else: # Try each possible transposition of the second tree to make this # metric key independent distances = [] for x_trans in range(4): for y_trans in range(3): def _align(tree1, tree2): # Transpose the label in the second tree label2 = ((tree2.root.label[0] + x_trans) % 4, (tree2.root.label[1] + y_trans) % 3) # Check the root to find out whether they have the same resolution same_res = tree1.root.label == label2 # Find out what cadence type each is same_cad = _cadence_type(tree1) == _cadence_type(tree2) if same_cad: # Compare the structure of the cadences tree_similarity = lces_size(tree1, tree2) else: tree_similarity = 0 # Work out how much score to give a matching resolution if res_score == -1: res_match = tree_similarity + 1 else: res_match = res_score return - tree_similarity - (res_match if same_res else 0) aligned,dist = align(trees1, trees2, delins_cost=0, subst_cost=_align, dist=True) distances.append((dist,aligned,(x_trans,y_trans))) alignment_score,alignment,transpose = min(distances, key=lambda x:x[0]) alignment_score = -float(alignment_score) def _max_score(trees): """ Get the maximum possible score that could be assigned to a match with this tree set. """ score = 0 for tree in trees: # Do the same things as _align (below), but max possible score # Maximum similarity is just the size of the tree tree_sim = len(tree) if res_score == -1: res_match = tree_sim + 1 else: res_match = res_score # Assume the same resolution and cadence type score += tree_sim + res_match return score max_score1 = _max_score(trees1) max_score2 = _max_score(trees2) return alignment_score, max_score1, max_score2, alignment, transpose