def test_save_load(self): with tempfile.NamedTemporaryFile(mode="r") as fid: gtn.savetxt(fid.name, self.g) loaded = gtn.loadtxt(fid.name) self.assertTrue(gtn.isomorphic(self.g, loaded)) with tempfile.NamedTemporaryFile(mode="r") as fid: gtn.save(fid.name, self.g) loaded = gtn.load(fid.name) self.assertTrue(gtn.isomorphic(self.g, loaded))
def test_transitions(self): num_tokens = 4 # unigram transitions = make_transitions_graph(1, num_tokens) expected = gtn.Graph() expected.add_node(True, True) for i in range(num_tokens): expected.add_arc(0, 0, i) self.assertTrue(gtn.isomorphic(transitions, expected)) # bigram transitions = make_transitions_graph(2, num_tokens) expected = gtn.Graph() expected.add_node(True, False) for i in range(num_tokens): expected.add_node(False, False) expected.add_arc(0, i + 1, i) for i in range(num_tokens): for j in range(num_tokens): expected.add_arc(i + 1, j + 1, j) expected.add_node(False, True) for i in range(num_tokens + 1): expected.add_arc(i, num_tokens + 1, gtn.epsilon) self.assertTrue(gtn.isomorphic(transitions, expected)) # trigram transitions = make_transitions_graph(3, num_tokens) expected = gtn.Graph() expected.add_node(True, False) for i in range(num_tokens): expected.add_node(False, False) expected.add_arc(0, i + 1, i) for i in range(num_tokens): for j in range(num_tokens): expected.add_node(False, False) expected.add_arc(i + 1, num_tokens * i + j + num_tokens + 1, j) for i in range(num_tokens): for j in range(num_tokens): for k in range(num_tokens): expected.add_arc( num_tokens * i + j + num_tokens + 1, num_tokens * j + k + num_tokens + 1, k, ) end_idx = expected.add_node(False, True) self.assertEqual(end_idx, num_tokens * num_tokens + num_tokens + 1) for i in range(end_idx): expected.add_arc(i, end_idx, gtn.epsilon) self.assertTrue(gtn.isomorphic(transitions, expected))
def test_sum(self): # Empty graph self.assertTrue(gtn.equal(gtn.union([]), gtn.Graph())) # Check single graph is a no-op g1 = gtn.Graph() g1.add_node(True) g1.add_node(False, True) g1.add_arc(0, 1, 1) self.assertTrue(gtn.equal(gtn.union([g1]), g1)) # Simple union g1 = gtn.Graph() g1.add_node(True) g1.add_node(False, True) g1.add_arc(0, 1, 1) g2 = gtn.Graph() g2.add_node(True) g2.add_node(False, True) g2.add_arc(0, 1, 0) expected = gtn.Graph() expected.add_node(True) expected.add_node(True) expected.add_node(False, True) expected.add_node(False, True) expected.add_arc(0, 2, 1) expected.add_arc(1, 3, 0) self.assertTrue(gtn.isomorphic(gtn.union([g1, g2]), expected)) # Check adding with an empty graph works g1 = gtn.Graph() g1.add_node(True) g1.add_node(False, True) g1.add_arc(0, 1, 1) g2 = gtn.Graph() g3 = gtn.Graph() g3.add_node(True, True) g3.add_arc(0, 0, 2) expected = gtn.Graph() expected.add_node(True) expected.add_node(False, True) expected.add_node(True, True) expected.add_arc(0, 1, 1) expected.add_arc(2, 2, 2) self.assertTrue(gtn.isomorphic(gtn.union([g1, g2, g3]), expected))
def test_loadsave(self): _, tmpfile = tempfile.mkstemp() g = gtn.Graph() gtn.save(tmpfile, g) g2 = gtn.load(tmpfile) self.assertTrue(gtn.equal(g, g2)) g = gtn.Graph() g.add_node(True) g.add_node(True) g.add_node() g.add_node() g.add_node(False, True) g.add_node(False, True) g.add_arc(0, 1, 0, 1, 1.1) g.add_arc(1, 2, 1, 2, 2.1) g.add_arc(2, 3, 2, 3, 3.1) g.add_arc(3, 4, 3, 4, 4.1) g.add_arc(4, 5, 4, gtn.epsilon, 5.1) gtn.save(tmpfile, g) g2 = gtn.load(tmpfile) self.assertTrue(gtn.equal(g, g2)) self.assertTrue(gtn.isomorphic(g, g2))
def test_comparisons(self): g1 = gtn.Graph() g1.add_node(True) g1.add_node(False, True) g1.add_arc(0, 1, 0) g2 = gtn.Graph() g2.add_node(True) g2.add_node(False, True) g2.add_arc(0, 1, 0) self.assertTrue(gtn.equal(g1, g2)) self.assertTrue(gtn.isomorphic(g1, g2)) g2 = gtn.Graph() g2.add_node(False, True) g2.add_node(True) g2.add_arc(1, 0, 0) self.assertFalse(gtn.equal(g1, g2)) self.assertTrue(gtn.isomorphic(g1, g2))
def test_loadtxt(self): g1 = gtn.Graph() g1.add_node(True, True) g1.add_node(False, True) g1.add_node() g1.add_arc(0, 0, 1) g1.add_arc(0, 2, 1, 1, 1.1) g1.add_arc(2, 1, 2, 2, 2.1) g_str = ["0", "0 1", "0 0 1 1 0", "0 2 1 1 1.1", "2 1 2 2 2.1"] g2 = create_graph_from_text(g_str) self.assertTrue(gtn.equal(g1, g2)) self.assertTrue(gtn.isomorphic(g1, g2)) _, tmpfile = tempfile.mkstemp() # Write the test file gtn.savetxt(tmpfile, g2) g3 = gtn.loadtxt(tmpfile) self.assertTrue(gtn.equal(g1, g3)) # Empty graph doesn't load g_str = [""] self.assertRaises(ValueError, create_graph_from_text, g_str) # Graph without accept nodes doesn't load g_str = ["1"] self.assertRaises(ValueError, create_graph_from_text, g_str) # Graph with repeat start nodes doesn't load g_str = ["1 0 0", "0 1"] self.assertRaises(ValueError, create_graph_from_text, g_str) # Graph loads if the start and accept nodes are specified g_str = ["0", "1"] g = gtn.Graph() g.add_node(True) g.add_node(False, True) self.assertTrue(gtn.equal(g, create_graph_from_text(g_str))) # Graph doesn't load if arc incorrect g_str = ["0", "1", "0 2"] self.assertRaises(ValueError, create_graph_from_text, g_str) g_str = ["0", "1", "0 1 2 3 4 5"] self.assertRaises(ValueError, create_graph_from_text, g_str) # Transducer loads g1 = gtn.Graph() g1.add_node(True, True) g1.add_node(False, True) g1.add_node() g1.add_arc(0, 0, 1, 1) g1.add_arc(0, 2, 1, 2, 1.1) g1.add_arc(2, 1, 2, 3, 2.1) g_str = ["0", "0 1", "0 0 1", "0 2 1 2 1.1", "2 1 2 3 2.1"] g2 = create_graph_from_text(g_str) self.assertTrue(gtn.equal(g1, g2)) self.assertTrue(gtn.isomorphic(g1, g2))
def test_isomorphic(self): g1 = gtn.Graph() g1.add_node(True) g2 = gtn.Graph() g2.add_node(True) self.assertTrue(gtn.isomorphic(g1, g2)) g1 = gtn.Graph() g1.add_node(True) g2 = gtn.Graph() g2.add_node(True, True) self.assertFalse(gtn.isomorphic(g1, g2)) g1 = gtn.Graph() g1.add_node(True) g1.add_node(False, True) g1.add_arc(0, 1, 0, 0, 1) g2 = gtn.Graph() g2.add_node(True) g2.add_node(False, True) g2.add_arc(0, 1, 0, 0, 1) self.assertTrue(gtn.isomorphic(g1, g2)) g1 = gtn.Graph() g1.add_node(True) g1.add_node(False, True) g1.add_arc(0, 1, 0, 0, 1) g2 = gtn.Graph() g2.add_node(True) g2.add_node(False, True) g2.add_arc(0, 1, 0, 0, 1) g2.add_arc(0, 1, 0, 0, 1) self.assertFalse(gtn.isomorphic(g1, g2)) # Graph with loops g1 = gtn.Graph() g1.add_node(True) g1.add_node() g1.add_node(False, True) g1.add_arc(0, 2, 0) g1.add_arc(0, 1, 0) g1.add_arc(1, 1, 3) g1.add_arc(2, 1, 3) g2 = gtn.Graph() g2.add_node(True) g2.add_node(False, True) g2.add_node() g2.add_arc(0, 1, 0) g2.add_arc(1, 2, 3) g2.add_arc(0, 2, 0) g2.add_arc(2, 2, 3) self.assertTrue(gtn.isomorphic(g1, g2)) # Repeat arcs g1 = gtn.Graph() g1.add_node(True) g1.add_node(False, True) g1.add_arc(0, 1, 1, 1, 3.1) g1.add_arc(0, 1, 1, 1, 3.1) g1.add_arc(0, 1, 1, 1, 4.1) g2 = gtn.Graph() g2.add_node(True) g2.add_node(False, True) g2.add_arc(0, 1, 1, 1, 3.1) g2.add_arc(0, 1, 1, 1, 4.1) g2.add_arc(0, 1, 1, 1, 4.1) self.assertFalse(gtn.isomorphic(g1, g2)) # Transducer with different outputs g1 = gtn.Graph() g1.add_node(True) g1.add_node(False, True) g1.add_arc(0, 1, 0, 1, 2.1) g1.add_arc(1, 1, 1, 3, 4.1) g2 = gtn.Graph() g2.add_node(True) g2.add_node(False, True) g2.add_arc(0, 1, 0, 1, 2.1) g2.add_arc(1, 1, 1, 4, 4.1) self.assertFalse(gtn.isomorphic(g1, g2))
def test_graph_build(self): # unigram test case graph = build_graph([[(0, ), (1, )]]) expected = gtn.Graph() expected.add_node(True, True) expected.add_arc(0, 0, 0) expected.add_arc(0, 0, 1) self.assertTrue(gtn.isomorphic(graph, expected)) # bigram test cases # fmt: off ngrams = [ [(0, )], # unigrams [(-1, 0), (-1, 1), (0, 1), (1, 0), (1, 1)] # bigrams ] # fmt: on with self.assertRaises(ValueError): build_graph(ngrams) # fmt: off # text = ["ab, "ba", "bb"] ngrams = [ [(0, ), (1, ), (-2, )], # unigrams [(-1, 0), (-1, 1), (0, 1), (1, 0), (1, 1), (0, -2), (1, -2)] # bigrams ] # fmt: on graph = build_graph(ngrams) expected = gtn.Graph() expected.add_node(True, False) # <s> expected.add_node(False, False) # 0 expected.add_node(False, False) # 1 expected.add_node(False, False) # back-off expected.add_node(False, True) # </s> expected.add_arc(0, 1, 0) expected.add_arc(1, 2, 1) expected.add_arc(0, 2, 1) expected.add_arc(2, 1, 0) expected.add_arc(2, 2, 1) expected.add_arc(0, 3, gtn.epsilon) expected.add_arc(1, 3, gtn.epsilon) expected.add_arc(2, 3, gtn.epsilon) expected.add_arc(3, 1, 0) expected.add_arc(3, 2, 1) expected.add_arc(3, 4, gtn.epsilon) expected.add_arc(1, 4, gtn.epsilon) expected.add_arc(2, 4, gtn.epsilon) self.assertTrue(gtn.isomorphic(expected, graph)) # bigram test case with empty string ngrams = [ [(0, ), (-2, )], [(-1, 0), (0, 0), (0, -2), (-1, -2)], ] # unigrams # bigrams graph = build_graph(ngrams) expected = gtn.Graph() expected.add_node(True, False) # (<s>) expected.add_node(False, False) # (a) expected.add_node(False, False) # (back-off) expected.add_node(False, True) # (</s>) expected.add_arc(2, 1, 0) # p(a) expected.add_arc(2, 3, gtn.epsilon) # p(</s>) expected.add_arc(1, 1, 0) # p(a/a) expected.add_arc(0, 1, 0) # p(a/<s>) expected.add_arc(1, 3, gtn.epsilon) # p(</s>/a) expected.add_arc(0, 3, gtn.epsilon) # p(</s>/<s>) expected.add_arc(0, 2, gtn.epsilon) expected.add_arc(1, 2, gtn.epsilon) self.assertTrue(gtn.isomorphic(expected, graph)) # trigram test case # fmt: off ngrams = [ [(0, ), (1, ), (-2, )], # unigrams [(-1, 0), (0, 1), (1, 1), (1, -2)], # bigrams [(-1, 0, 1), (0, 1, 1), (1, 1, 1), (1, 1, -2)], # trigrams ] # fmt: on graph = build_graph(ngrams) expected = gtn.Graph() expected.add_node(True, False) # (<s>) expected.add_node(False, False) # unigram back-off expected.add_node(False, False) # 0 expected.add_node(False, False) # 1 expected.add_node(False, False) # (<s>, 0) expected.add_node(False, False) # (0, 1) expected.add_node(False, False) # (1, 1) expected.add_node(False, True) # </s> # unigram arcs expected.add_arc(1, 2, 0) expected.add_arc(1, 3, 1) expected.add_arc(1, 7, gtn.epsilon) # bigram arcs expected.add_arc(0, 4, 0) expected.add_arc(2, 5, 1) expected.add_arc(3, 6, 1) expected.add_arc(3, 7, gtn.epsilon) # trigram arcs expected.add_arc(4, 5, 1) expected.add_arc(5, 6, 1) expected.add_arc(6, 6, 1) expected.add_arc(6, 7, gtn.epsilon) # back-off to bigram expected.add_arc(4, 2, gtn.epsilon) expected.add_arc(5, 3, gtn.epsilon) expected.add_arc(6, 3, gtn.epsilon) # back-off to unigram expected.add_arc(0, 1, gtn.epsilon) expected.add_arc(2, 1, gtn.epsilon) expected.add_arc(3, 1, gtn.epsilon) self.assertTrue(gtn.isomorphic(expected, graph))
def test_composition(self): # Compos,ing with an empty graph gives an empty graph g1 = gtn.Graph() g2 = gtn.Graph() self.assertTrue(gtn.equal(gtn.compose(g1, g2), gtn.Graph())) g1.add_node(True) g1.add_node() g1.add_arc(0, 1, 0) g2.add_node(True) g2.add_node(False, True) g2.add_arc(0, 1, 0) g2.add_arc(0, 1, 0) self.assertTrue(gtn.equal(gtn.compose(g1, g2), gtn.Graph())) self.assertTrue(gtn.equal(gtn.compose(g2, g1), gtn.Graph())) self.assertTrue(gtn.equal(gtn.intersect(g2, g1), gtn.Graph())) # Check singly sorted version g1.arc_sort(True) self.assertTrue(gtn.equal(gtn.compose(g1, g2), gtn.Graph())) # Check doubly sorted version g2.arc_sort() self.assertTrue(gtn.equal(gtn.compose(g1, g2), gtn.Graph())) # Self-loop in the composed graph g1 = gtn.Graph() g1.add_node(True) g1.add_node(False, True) g1.add_arc(0, 0, 0) g1.add_arc(0, 1, 1) g1.add_arc(1, 1, 2) g2 = gtn.Graph() g2.add_node(True) g2.add_node() g2.add_node(False, True) g2.add_arc(0, 1, 0) g2.add_arc(1, 1, 0) g2.add_arc(1, 2, 1) g_str = ["0", "2", "0 1 0", "1 1 0", "1 2 1"] expected = create_graph_from_text(g_str) self.assertTrue(gtn.isomorphic(gtn.compose(g1, g2), expected)) self.assertTrue(gtn.isomorphic(gtn.intersect(g1, g2), expected)) # Check singly sorted version g1.arc_sort(True) self.assertTrue(gtn.isomorphic(gtn.compose(g1, g2), expected)) # Check doubly sorted version g2.arc_sort() self.assertTrue(gtn.isomorphic(gtn.compose(g1, g2), expected)) # Loop in the composed graph g1 = gtn.Graph() g1.add_node(True) g1.add_node(False, True) g1.add_arc(0, 1, 0) g1.add_arc(1, 1, 1) g1.add_arc(1, 0, 0) g2 = gtn.Graph() g2.add_node(True) g2.add_node(False, True) g2.add_arc(0, 0, 0) g2.add_arc(0, 1, 1) g2.add_arc(1, 0, 1) g_str = ["0", "2", "0 1 0", "1 0 0", "1 2 1", "2 1 1"] expected = create_graph_from_text(g_str) self.assertTrue(gtn.isomorphic(gtn.compose(g1, g2), expected)) self.assertTrue(gtn.isomorphic(gtn.intersect(g1, g2), expected)) # Check singly sorted version g1.arc_sort(True) self.assertTrue(gtn.isomorphic(gtn.compose(g1, g2), expected)) # Check doubly sorted version g2.arc_sort() self.assertTrue(gtn.isomorphic(gtn.compose(g1, g2), expected)) g1 = gtn.Graph() g1.add_node(True) g1.add_node() g1.add_node() g1.add_node() g1.add_node(False, True) for i in range(g1.num_nodes() - 1): for j in range(3): g1.add_arc(i, i + 1, j, j, j) g2 = gtn.Graph() g2.add_node(True) g2.add_node() g2.add_node(False, True) g2.add_arc(0, 1, 0, 0, 3.5) g2.add_arc(1, 1, 0, 0, 2.5) g2.add_arc(1, 2, 1, 1, 1.5) g2.add_arc(2, 2, 1, 1, 4.5) g_str = [ "0", "6", "0 1 0 0 3.5", "1 2 0 0 2.5", "1 4 1 1 2.5", "2 3 0 0 2.5", "2 5 1 1 2.5", "4 5 1 1 5.5", "3 6 1 1 2.5", "5 6 1 1 5.5", ] expected = create_graph_from_text(g_str) self.assertTrue(gtn.isomorphic(gtn.compose(g1, g2), expected)) self.assertTrue(gtn.isomorphic(gtn.intersect(g1, g2), expected)) # Check singly sorted version g1.arc_sort(True) self.assertTrue(gtn.isomorphic(gtn.compose(g1, g2), expected)) # Check doubly sorted version g2.arc_sort() self.assertTrue(gtn.isomorphic(gtn.compose(g1, g2), expected))