def testSearchNoCandidates(self): # If there are no suitable candidate data vertices for every # query vertex, then the returned solutions list should be empty. g = Graph() g.addEdge(Vertex('v1', 'A'), Vertex('v2', 'B')) q = Graph() q.addEdge(Vertex('u1', 'Z'), Vertex('u2', 'Y')) solutions = g.search(q) self.assertEquals(len(solutions), 0)
def testApplyProduction_Blackbox2(self): # Another black-box test of _applyProduction this time with # numbered vertices. # Graph is A0->A1,A0->D g = Graph() g.addEdge(Vertex('g0', 'A'), Vertex('g1', 'A')) g.addEdge('g0', Vertex('g2', 'D')) # Production is A1->A2 ==> A1->A->A2. # This production adds a new vertex "A" between the existing As, # leaving the first A still pointing to D. # Resulting graph: A1->A3->A2; A1->D lhs = Graph() lhs.addEdge(Vertex('l0', 'A', 1), Vertex('l1', 'A', 2)) rhs = Graph() rhs.addEdge(Vertex('r0', 'A', 1), Vertex('r1', 'A')) rhs.addEdge('r1', Vertex('r2', 'A', 2)) p = Production(lhs, rhs) gen = Generator() gen._applyProduction(g, p, {'l0':'g0','l1':'g1'}) # Result has 4 vertices. self.assertEqual(len(g._vertices), 4) # <g0,A> is still in the graph. self.assertIn('g0', g._vertices) self.assertEqual(g._vertices['g0'].label, 'A') # <v3,A> has been added. self.assertIn('v3', g._vertices) self.assertEqual(g._vertices['v3'].label, 'A') # g0->v3 self.assertIn(g._vertices['v3'], g._edges['g0']) # <g1,A> is still in the graph. self.assertIn('g1', g._vertices) self.assertEqual(g._vertices['g1'].label, 'A') # <g2,D> is still in the graph. self.assertIn('g2', g._vertices) self.assertEqual(g._vertices['g2'].label, 'D') # <g0,A>-><g2,D> self.assertIn(g._vertices['g2'], g._edges['g0']) # g0->v3 self.assertIn(g._vertices['v3'], g._edges['g0']) # Output looks fine: A1->A->A, A1->D self.assertEqual(str(g), 'digraph {\nA_v3->A_g1;\nA_g0->D_g2;\nA_g0->A_v3;\n\n}')
def testFindCandidates(self): # Create empty data and query graphs. g = Graph() q = Graph() # Searching finds no candidates. self.assertFalse(g._findCandidates(q)) # Add some data vertices. g.addEdge(Vertex('u1', 'A'), Vertex('u2', 'B')) # Empty query graph still finds no candidates. self.assertFalse(g._findCandidates(q)) # Add some query vertices. q.addEdge(Vertex('u1', 'A'), Vertex('u2', 'B')) q.addEdge('u1', Vertex('u3', 'C')) # Data graph has no 'C', so still returns false. self.assertFalse(g._findCandidates(q)) # Add a vertex for C, and now the test should succeeed. g.addEdge('u1', Vertex('u3', 'C')) u1 = q._vertices['u1'] self.assertTrue(g._findCandidates(q)) self.assertEquals(len(u1.candidates), 1)
def testSearchTwoSolutions(self): # A1_g0->B_g1->C_g2, A2_g3->B_g1 g = Graph() g.addEdge(Vertex('g0', 'A'), Vertex('g1', 'B')) g.addEdge('g1', Vertex('g2', 'C')) g.addEdge(Vertex('g3', 'A'), 'g1') #g.addEdge('g3', 'g2') # A_g0->B_g1->C_g2 q = Graph() q.addEdge(Vertex('g0', 'A'), Vertex('g1', 'B')) q.addEdge('g1', Vertex('g2', 'C')) solutions = g.search(q) self.assertEquals(len(solutions), 2) # First A->B,C is found. self.assertEquals(solutions[0]['g0'], 'g3') self.assertEquals(solutions[0]['g1'], 'g1') self.assertEquals(solutions[0]['g2'], 'g2') # Second A->B,C is found. self.assertEquals(solutions[1]['g0'], 'g0') self.assertEquals(solutions[1]['g1'], 'g1') self.assertEquals(solutions[1]['g2'], 'g2')
def testFindMatchingProductions(self): # Providing no productions should result in no matches. gen = Generator() g = Graph() self.assertEquals( len(gen._findMatchingProductions(g, [])), 0) # We have a production, but the LHS can't be found in the graph. # No solutions. g = Graph() g.addEdge(Vertex('g0', 'A'), Vertex('g1', 'B')) lhs = Graph() lhs.addEdge(Vertex('g0', 'C'), Vertex('g1', 'D')) rhs = Graph() p1 = Production(lhs, rhs) gen = Generator() self.assertEquals( len(gen._findMatchingProductions(g, [p1])), 0) # One matching production, a simple vertex "A". g = Graph() g.addEdge(Vertex('g0', 'A'), Vertex('g1', 'B')) lhs = Graph() lhs.addVertex(Vertex('g0', 'A', '1')) rhs = Graph() p1 = Production(lhs, rhs) self.assertEquals( len(gen._findMatchingProductions(g, [p1])), 1) # Two matching productions. g = Graph() g.addEdge(Vertex('g0', 'A'), Vertex('g1', 'B')) lhs = Graph() lhs.addVertex(Vertex('g0', 'A', '2')) rhs = Graph() p1 = Production(lhs, rhs) p2 = Production(lhs, rhs) self.assertEquals( len(gen._findMatchingProductions(g, [p1, p2])), 2)
def testApplyProductions(self): # Start graph already has the minimum number of vertices. Nothing done. g = Graph() c = {'min_vertices':0} gen = Generator() gen.applyProductions(g, None, c) self.assertEqual(len(g._vertices), 0) # No matching productions raises an error. c = {'min_vertices':1} self.assertRaises(RuntimeError, gen.applyProductions, g, [], c) # When we're done, g has more at least min_vertices. g.addEdge(Vertex('g0', 'A'), Vertex('g1', 'A')) c = {'min_vertices':10} # Production is A1->A2 ==> A1->A->A2 lhs = Graph() lhs.addEdge(Vertex('l0', 'A', 1), Vertex('l1', 'A', 2)) rhs = Graph() rhs.addEdge(Vertex('r0', 'A', 1), Vertex('r1', 'A')) rhs.addEdge('r1', Vertex('r2', 'A', 2)) p = Production(lhs, rhs) gen.applyProductions(g, [p], c) logging.debug(g) self.assertEqual(len(g._vertices), 10)
def testFindMatchedNeighbors(self): q = Graph() # No data should return an empty list. mn = q._findMatchedNeighbors(None, None) self.assertEquals(len(mn), 0) # No matching neighbors should return an empty list. q.addEdge(Vertex('u1', 'A'), Vertex('u2', 'B')) u2 = q._vertices['u2'] mn = q._findMatchedNeighbors(u2, []) self.assertEquals(len(mn), 0) # Make a matching neighbor and make sure it is returned. matches = {'u1': 'v1', 'v1': 'u1'} mn = q._findMatchedNeighbors(u2, matches) self.assertEquals(len(mn), 1) self.assertEquals(mn[0].id, 'u1')
def testNextUnmamtchedVertex(self): matches = {} # Build a little graph with three nodes. q = Graph() q.addEdge(Vertex('u1'), Vertex('u2')) q.addEdge('u1', Vertex('u3')) # Call _nextUnmatchedVertex three times. Each time it returns a # vertex, add it to matches. for i in range(3): v = q._nextUnmatchedVertex(matches) self.assertTrue(v.id in ['u1', 'u2', 'u3']) matches[v.id] = 'XYZ' # Now that all of the vertices are labeled, _nextUnmatchedVertex() # should return None. self.assertIsNone(q._nextUnmatchedVertex(matches))
def testSubgraphSearchOneCandidateNotJoinable(self): # The query vertex has a candidate data vertex, but they aren't # "joinable" -- no solution. g = Graph() g.addVertex(Vertex('v1', 'A')) g.addVertex(Vertex('v2', 'B')) v1 = g._vertices['v1'] q = Graph() q.addEdge(Vertex('u1', 'A'), Vertex('u2', 'B')) q._vertices['u1'].candidates = [v1] # u2 and v2 are already matched. There's an edge between u1 and # u2, but no edge between v1 and v2 so u1 and v1 cannot be matched. matches = {'u2': 'v2'} self.assertEqual(len(g._solutions), 0) g._subgraphSearch(matches, q) self.assertEqual(len(g._solutions), 0)
def testFilterCandidates(self): # Filtering an empty graph should return an empty array. g = Graph() c = g._filterCandidates(None) self.assertEquals(len(c), 0) # Build a little graph with two 'A' labeled vertices. g.addEdge(Vertex('u1', 'A'), Vertex('u2', 'B')) g.addEdge('u1', Vertex('u3', 'A')) # Search the graph for all 'X' vertices (should return an empty array.) u = Vertex('x', 'X') c = g._filterCandidates(u) self.assertTrue(len(c) == 0) # Search for 'A' vertices. Should return two of them. u = Vertex('x', 'A') c = g._filterCandidates(u) self.assertTrue(len(c) == 2) self.assertTrue(c[0].label == 'A') self.assertTrue(c[1].label == 'A')
def testApplyProduction(self): # A basic test that tests all four cases: add and remove vertex, # and add and remove edge. # Graph starts with A->B g = Graph() g.addEdge(Vertex('g0', 'A'), Vertex('g1', 'B')) g1 = g._vertices['g1'] # Production lhs matches A->B lhs = Graph() lhs.addEdge(Vertex('l0', 'A', 1), Vertex('l1', 'B', 1)) # Production rhs transforms that to A->C rhs = Graph() rhs.addEdge(Vertex('r0', 'A', 1), Vertex('r1', 'C')) p = Production(lhs,rhs) gen = Generator() gen._applyProduction(g, p, {'l0':'g0','l1':'g1'}) # g has a new vertex, <v2,C>. self.assertEqual(len(g._vertices), 2) self.assertEqual(g._vertices['v1'].label, 'C') # <g0,A> points to <v2,C> self.assertEqual(len(g._edges['g0']), 1) self.assertEqual(g._edges['g0'][0].id, 'v1') self.assertEqual(g._vertices['v1'].label, 'C') # <g0,A> no longer points to <g1,B> self.assertNotIn(g1, g._edges['g0']) # Vertex <g1,B> has been deleted. self.assertNotIn('g1', g._vertices)
def testSearchOneSimpleSolution(self): g = Graph() g.addEdge(Vertex('v1', 'A'), Vertex('v2', 'B')) g.addEdge('v1', Vertex('v3', 'C')) # Query graph is exact replica. q = Graph() q.addEdge(Vertex('u1', 'A'), Vertex('u2', 'B')) q.addEdge('u1', Vertex('u3', 'C')) solutions = g.search(q) self.assertEquals(len(solutions), 1) self.assertEquals(solutions[0]['u1'], 'v1') self.assertEquals(solutions[0]['u2'], 'v2') self.assertEquals(solutions[0]['u3'], 'v3')
def testApplyProduction_Blackbox(self): # Black-box test of _applyProduction. # Graph is A->C,D g = Graph() g.addEdge(Vertex('g0', 'A'), Vertex('g1', 'C')) g.addVertex(Vertex('g2', 'D')) # Production is A->C,D ==> A->B,C. # This adds vertex B, adds edge from A->B, deletes edge from A->C, # and deletes vertex D. lhs = Graph() lhs.addEdge(Vertex('l0', 'A'), Vertex('l1', 'C')) lhs.addVertex(Vertex('l2', 'D')) rhs = Graph() rhs.addEdge(Vertex('r0', 'A'), Vertex('r1', 'B')) rhs.addVertex(Vertex('r2', 'C')) p = Production(lhs, rhs) gen = Generator() gen._applyProduction(g, p, {'l0':'g0','l1':'g1','l2':'g2'}) self.assertEqual(len(g._vertices), 3) # <g0,A> is still in the graph. self.assertIn('g0', g._vertices) self.assertEqual(g._vertices['g0'].label, 'A') # <v3,B> has been added. self.assertIn('v2', g._vertices) self.assertEqual(g._vertices['v2'].label, 'B') # A->B self.assertIn(g._vertices['v2'], g._edges['g0']) # <g1,C> is still in the graph. self.assertIn('g1', g._vertices) self.assertEqual(g._vertices['g1'].label, 'C') # A->C has been removed. self.assertNotIn(g._vertices['g1'], g._edges['g0']) # <g2,D> has been removed. self.assertNotIn('g2', g._vertices) # Output looks fine. self.assertEqual(str(g), 'digraph {\nA_g0->B_v2;\n\n}')
def testAddNewEdges(self): # rhs has no edges, so nothing changes. g = Graph() lhs = Graph() rhs = Graph() p = Production(lhs,rhs) rhsMapping = {} gen = Generator() self.assertEqual(len(g._edges), 0) gen._addNewEdges(g, p, rhsMapping) self.assertEqual(len(g._edges), 0) # rhs has an edge, but it already exists in the graph. g = Graph() g.addEdge(Vertex('g0', 'A'), Vertex('g1', 'B')) lhs = Graph() rhs = Graph() rhs.addEdge(Vertex('r0', 'A', 1), Vertex('r1', 'B', 1)) p = Production(lhs,rhs) rhsMapping = {'r0':'g0', 'r1':'g1'} gen = Generator() self.assertEqual(len(g._edges['g0']), 1) gen._addNewEdges(g, p, rhsMapping) self.assertEqual(len(g._edges['g0']), 1) # rhs has a new edge not in graph. g = Graph() g.addVertex(Vertex('g0', 'A')) g.addVertex(Vertex('g1', 'B')) lhs = Graph() rhs = Graph() rhs.addEdge(Vertex('r0', 'A', 1), Vertex('r1', 'B', 1)) p = Production(lhs,rhs) rhsMapping = {'r0':'g0', 'r1':'g1'} gen = Generator() self.assertEqual(len(g._edges['g0']), 0) gen._addNewEdges(g, p, rhsMapping) self.assertEqual(len(g._edges['g0']), 1) self.assertEqual(g._edges['g0'][0].id, 'g1')
class TestGraphClass(unittest.TestCase): def setUp(self): self.g = Graph() def testConstructor(self): # New graphs should be empty. self.assertTrue(len(self.g._vertices) == 0) self.assertTrue(len(self.g._edges) == 0) self.assertTrue(len(self.g._neighbors) == 0) def testAddVertex(self): # Correct add. v = self.g.addVertex(Vertex('u1')) self.assertTrue('u1' in self.g._vertices) # Adding an existing vertex should return the existing vertex. self.assertEquals(self.g.addVertex(v), v) def testAddEdge(self): # Add edge with two vid's a = self.g.addVertex(Vertex('u1', 'A')) b = self.g.addVertex(Vertex('u2', 'B')) self.g.addEdge('u1', 'u2') # Add edge with one vid and one Vertex. self.g.addEdge('u1', Vertex('u3', 'C')) c = self.g._vertices['u3'] # Add edge with one Vertex and one vid. self.g.addEdge(Vertex('u4', 'D'), 'u1') d = self.g._vertices['u4'] # Add edge with two Vertics. self.g.addEdge(Vertex('u5', 'E'), Vertex('u6', 'F')) e = self.g._vertices['u5'] f = self.g._vertices['u6'] # Make sure A points to B and C. self.assertTrue(b in self.g._edges['u1']) self.assertTrue(c in self.g._edges['u1']) self.assertTrue(a in self.g._edges['u4']) self.assertTrue(f in self.g._edges['u5']) # Make sure neighbors all reference each other. self.assertTrue(b in self.g._neighbors['u1']) self.assertTrue(c in self.g._neighbors['u1']) self.assertTrue(d in self.g._neighbors['u1']) self.assertTrue(a in self.g._neighbors['u2']) self.assertTrue(a in self.g._neighbors['u3']) self.assertTrue(a in self.g._neighbors['u4']) self.assertTrue(e in self.g._neighbors['u6']) self.assertTrue(f in self.g._neighbors['u5']) # Make sure the vertex degrees were updated. self.assertEquals(self.g._vertices['u1'].degree, 3) self.assertEquals(self.g._vertices['u2'].degree, 1) self.assertEquals(self.g._vertices['u3'].degree, 1) self.assertEquals(self.g._vertices['u4'].degree, 1) self.assertEquals(self.g._vertices['u5'].degree, 1) self.assertEquals(self.g._vertices['u6'].degree, 1) def testDeleteEdge(self): # Referencing non-existing vertices should return False self.assertFalse(self.g.deleteEdge('aaa', 'bbb')) # Build A->B self.g.addEdge(Vertex('u1', 'A'), Vertex('u2', 'B')) u1 = self.g._vertices['u1'] u2 = self.g._vertices['u2'] # Deleting a non-existant edge should return False. self.assertFalse(self.g.deleteEdge('u1', 'bbb')) # Deleting an existing edge should return True. self.assertTrue(self.g.deleteEdge('u1', 'u2')) # u2 should not appear in the list of edges from u1. self.assertTrue(u2 not in self.g._edges['u1']) # u2 should not appear in the list of neighbors of u1. self.assertTrue(u2 not in self.g._neighbors['u1']) # Both vertex degress should be decremented. self.assertEquals(u1.degree, 0) self.assertEquals(u2.degree, 0) def testDeleteVertex(self): # Deleting a non-existing vertex raises an exception. self.assertIsNone(self.g.deleteVertex('X')) # Build A->B, B->A self.g.addEdge(Vertex('u1', 'A'), Vertex('u2', 'B')) self.g.addEdge('u2', 'u1') u1 = self.g._vertices['u1'] u2 = self.g._vertices['u2'] self.g.deleteVertex('u1') # u1 shouldn't appear anywhere as an edge or neighbor. self.assertTrue('u1' not in self.g._edges) self.assertTrue('u1' not in self.g._neighbors) self.assertTrue('u1' not in self.g._edges['u2']) self.assertTrue('u1' not in self.g._neighbors['u2']) # u1 isn't a vertex anymore. self.assertTrue('u1' not in self.g._vertices) def testEdgesProperty(self): # Build A->B, B->C self.g.addEdge(Vertex('u1', 'A'), Vertex('u2', 'B')) self.g.addEdge('u2', Vertex('u3', 'C')) for e in self.g.edges: if e[0].id == 'u1': self.assertEquals(e[1].id, 'u2') elif e[0].id == 'u2': self.assertEquals(e[1].id, 'u3') else: self.assertFalse(True) def testFindVertex(self): u1 = self.g.addVertex(Vertex('u1', 'A', 1)) self.assertIsNone(self.g.findVertex('X')) self.assertIsNone(self.g.findVertex('A2')) self.assertEqual(self.g.findVertex('A1'), u1) def testHasEdgeBetweenVertices(self): self.g.addEdge(Vertex('u0', 'A'), Vertex('u1', 'B')) self.g.addEdge('u1', Vertex('u2', 'C')) self.assertTrue(self.g.hasEdgeBetweenVertices('u0', 'u1')) self.assertFalse(self.g.hasEdgeBetweenVertices('u0', 'u2')) self.assertFalse(self.g.hasEdgeBetweenVertices('XX', 'XX')) self.assertFalse(self.g.hasEdgeBetweenVertices('u0', 'XX')) def testLabelsProperty(self): self.g.addVertex(Vertex('u1', 'A')) self.g.addVertex(Vertex('u2', 'B')) self.g.addVertex(Vertex('u3', 'C')) labels = self.g.labels self.assertEquals(len(labels), 3) self.assertTrue('A' in labels) self.assertTrue('B' in labels) self.assertTrue('C' in labels) def testNamesProperty(self): self.g.addVertex(Vertex('u1', 'A', 1)) self.g.addVertex(Vertex('u2', 'B', 2)) self.g.addVertex(Vertex('u3', 'C', 3)) names = self.g.names self.assertEquals(len(names), 3) self.assertTrue('A1' in names) self.assertTrue('B2' in names) self.assertTrue('C3' in names) def testNumVertices(self): # Empty graph. self.assertEquals(self.g.numVertices, 0) # One vertex. a = self.g.addVertex(Vertex('u1')) self.assertEquals(self.g.numVertices, 1) def testRepr(self): # Test of the output function (__repr__). # No vertices. self.assertEquals(self.g.__repr__(), "digraph {\n\n}") # A self.g.addVertex(Vertex('u1', 'A')) self.assertEquals(self.g.__repr__(), "digraph {\nA_u1\n}") # A->B self.g.addEdge('u1', Vertex('u2', 'B')) self.assertEquals(self.g.__repr__(), "digraph {\nA_u1->B_u2;\n\n}") # A->B->C self.g.addEdge('u2', Vertex('u3', 'C')) self.assertEquals(self.g.__repr__(), "digraph {\nA_u1->B_u2;\nB_u2->C_u3;\n\n}") # A->B->C, A->D self.g.addEdge('u1', Vertex('u4', 'D')) self.assertEquals( self.g.__repr__(), "digraph {\nA_u1->B_u2;\nA_u1->D_u4;\nB_u2->C_u3;\n\n}")
def testIsJoinable(self): # If there are no matched vertices yet (we just started the matching # process), then should return True. g = Graph() self.assertTrue(g._isJoinable(None, None, None, {})) # If there are matches, but none adjacent to u, then should # return False. g = Graph() g.addEdge(Vertex('v1'), Vertex('v2')) v = g._vertices['v1'] q = Graph() q.addEdge(Vertex('u1'), Vertex('u2')) u = q._vertices['u1'] self.assertFalse(g._isJoinable(u, v, q, {'u3': 'v3', 'v3': 'u3'})) # If an edge exists between u and n, but the other direction between # v and m, should return False g = Graph() g.addEdge(Vertex('v1'), Vertex('v2')) v = g._vertices['v1'] q = Graph() q.addEdge(Vertex('u2'), Vertex('u1')) u = q._vertices['u1'] self.assertFalse(g._isJoinable(u, v, q, {'u2': 'v2', 'v2': 'u2'})) # If an edge exists between n and u, but the other direction between # m and v, should return False g = Graph() g.addEdge(Vertex('v2'), Vertex('v1')) v = g._vertices['v1'] q = Graph() q.addEdge(Vertex('u1'), Vertex('u2')) u = q._vertices['u1'] self.assertFalse(g._isJoinable(u, v, q, {'u2': 'v2', 'v2': 'u2'})) # Correct case 1. Edge between u and n, and between v and m. g = Graph() g.addEdge(Vertex('v1'), Vertex('v2')) v = g._vertices['v1'] q = Graph() q.addEdge(Vertex('u1'), Vertex('u2')) u = q._vertices['u1'] self.assertTrue(g._isJoinable(u, v, q, {'u2': 'v2', 'v2': 'u2'})) # Correct case 2. Edge between n and u, and between m and v. g = Graph() g.addEdge(Vertex('v2'), Vertex('v1')) v = g._vertices['v1'] q = Graph() q.addEdge(Vertex('u2'), Vertex('u1')) u = q._vertices['u1'] self.assertTrue(g._isJoinable(u, v, q, {'u2': 'v2', 'v2': 'u2'}))
def testDeleteMissingEdges(self): # If lhs has no edges, then there's nothing missing from the rhs. # Nothing is done to the graph. g = Graph() g.addEdge(Vertex('g0', 'A', 1), Vertex('g1', 'B', 1)) lhs = Graph() rhs = Graph() p = Production(lhs,rhs) lhsMapping = {} rhsMapping = {} gen = Generator() self.assertEqual(len(g._edges['g0']), 1) gen._deleteMissingEdges(g, p, lhsMapping, rhsMapping) self.assertEqual(len(g._edges['g0']), 1) # lhs has an edge, but it also appears on the rhs. Nothing done. g = Graph() g.addEdge(Vertex('g0', 'A', 1), Vertex('g1', 'B', 1)) lhs = Graph() lhs.addEdge(Vertex('l0', 'A', 1), Vertex('l1', 'B', 1)) rhs = Graph() rhs.addEdge(Vertex('r0', 'A', 1), Vertex('r1', 'B', 1)) p = Production(lhs,rhs) lhsMapping = {'l0':'g0', 'l1':'g1'} rhsMapping = {'r0':'g0', 'r1':'g1'} gen = Generator() self.assertEqual(len(g._edges['g0']), 1) gen._deleteMissingEdges(g, p, lhsMapping, rhsMapping) self.assertEqual(len(g._edges['g0']), 1) # lhs has an edge, but the starting vertex doesn't appear in the RHS. # The edge should be deleted from the graph. g = Graph() g.addEdge(Vertex('g0', 'A', 1), Vertex('g1', 'B', 1)) lhs = Graph() lhs.addEdge(Vertex('l0', 'A', 1), Vertex('l1', 'B', 1)) rhs = Graph() rhs.addVertex(Vertex('r0', 'A', 2)) rhs.addVertex(Vertex('r1', 'B', 1)) p = Production(lhs,rhs) lhsMapping = {'l0':'g0', 'l1':'g1'} rhsMapping = {'r1':'g1'} gen = Generator() self.assertEqual(len(g._edges['g0']), 1) gen._deleteMissingEdges(g, p, lhsMapping, rhsMapping) self.assertEqual(len(g._edges['g0']), 0) # lhs has an edge, but the ending vertex doesn't appear in the RHS. # The edge should be deleted from the graph. g = Graph() g.addEdge(Vertex('g0', 'A', 1), Vertex('g1', 'B', 1)) lhs = Graph() lhs.addEdge(Vertex('l0', 'A', 1), Vertex('l1', 'B', 1)) rhs = Graph() rhs.addVertex(Vertex('r0', 'A', 1)) rhs.addVertex(Vertex('r1', 'B', 2)) p = Production(lhs,rhs) lhsMapping = {'l0':'g0', 'l1':'g1'} rhsMapping = {'r0':'g0'} gen = Generator() self.assertEqual(len(g._edges['g0']), 1) gen._deleteMissingEdges(g, p, lhsMapping, rhsMapping) self.assertEqual(len(g._edges['g0']), 0) # lhs has an edge, but it's gone from the rhs. It should be deleted # from the graph. g = Graph() g.addEdge(Vertex('g0', 'A', 1), Vertex('g1', 'B', 1)) lhs = Graph() lhs.addEdge(Vertex('l0', 'A', 1), Vertex('l1', 'B', 1)) rhs = Graph() rhs.addVertex(Vertex('r0', 'A', 1)) rhs.addVertex(Vertex('r1', 'B', 1)) p = Production(lhs,rhs) lhsMapping = {'l0':'g0', 'l1':'g1'} rhsMapping = {'r0':'g0', 'r1':'g1'} gen = Generator() self.assertEqual(len(g._edges['g0']), 1) gen._deleteMissingEdges(g, p, lhsMapping, rhsMapping) self.assertEqual(len(g._edges['g0']), 0)