コード例 #1
0
    def testParseEdgeList(self):
        # edgeList -> ID | ID '->' edgeList

        # Left off first required ID.
        p = Parser(Lexer(''))
        g = Graph()
        self.assertRaises(SyntaxError, p._parseEdgeList, g)

        # Using non-existing label should create a new vertex.
        g = Graph()
        p = Parser(Lexer('A'))
        p._parseEdgeList(g)
        self.assertEqual(g._vertices['v0'].label, 'A')

        # Using an existing label should not create a new vertex.
        g = Graph()
        g.addVertex(Vertex('u0', 'A'))
        p = Parser(Lexer('A'))
        p._parseEdgeList(g)
        self.assertEqual(g._vertices['u0'].label, 'A')

        # Left off second ID.
        p = Parser(Lexer('A ->'))
        g = Graph()
        self.assertRaises(SyntaxError, p._parseEdgeList, g)

        # Simple transition should create two vertices and connect them.
        g = Graph()
        p = Parser(Lexer('A -> B'))
        p._parseEdgeList(g)
        self.assertEquals(len(g._vertices), 2)
        self.assertEquals(g._vertices['v0'].label, 'A')
        self.assertEquals(g._vertices['v1'].label, 'B')
        self.assertEquals(g._edges['v0'][0].label, 'B')
コード例 #2
0
ファイル: testGenerator.py プロジェクト: riffsircar/GraphGen
    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)
コード例 #3
0
ファイル: testGenerator.py プロジェクト: riffsircar/GraphGen
    def testDeleteMissingVertices(self):
        # lhs has no vertices(!). Nothing done.
        g = Graph()
        lhs = Graph()
        rhs = Graph()
        p = Production(lhs, rhs)
        gen = Generator()
        gen._deleteMissingVertices(g, p, {})
        self.assertEqual(len(g._vertices), 0)

        # lhs has vertices, but they all appear in the rhs. Nothing done.
        g.addVertex(Vertex('g0', 'A', 1))
        lhs.addVertex(Vertex('l0', 'A', 1))
        rhs.addVertex(Vertex('r0', 'A', 1))
        p = Production(lhs, rhs)
        gen._deleteMissingVertices(g, p, {'l0':'g0'})
        self.assertEqual(len(g._vertices), 1)

        # lhs has a vertex (A2) that don't appear in the rhs. It should be
        # deleted from g.
        g.addVertex(Vertex('g1', 'A', 2))
        lhs.addVertex(Vertex('l1', 'A', 2))
        p = Production(lhs, rhs)
        self.assertEqual(len(g._vertices), 2)
        gen._deleteMissingVertices(g, p, {'l0':'g0', 'l1':'g1'})
        self.assertEqual(len(g._vertices), 1)
コード例 #4
0
 def testSubgraphSearchSolutionFound(self):
     # Test that when the length of query=>data vertex matches is the
     # same as the number of query vertices, then the solution is stored.
     g = Graph()
     q = Graph()
     q.addVertex(Vertex('u1', 'A'))  # one query vertex
     matches = {'u1': 'v1'}  # one match
     g._subgraphSearch(matches, q)
     self.assertEqual(len(g._solutions), 1)
コード例 #5
0
 def testSubgraphSearchSolutionNoCandidates(self):
     # Test when an umatched query vertex doesn't have any candidates, we
     # don't find any solutions.
     g = Graph()
     g.addVertex(Vertex('v1', 'A'))
     q = Graph()
     q.addVertex(Vertex('u1', 'B'))
     matches = {}
     self.assertEqual(len(g._solutions), 0)
     g._subgraphSearch(matches, q)
     self.assertEqual(len(g._solutions), 0)
コード例 #6
0
    def testSubgraphSearchSimpleSolution(self):
        # One simple solution.
        g = Graph()
        g.addVertex(Vertex('v1', 'A'))
        v1 = g._vertices['v1']

        q = Graph()
        q.addVertex(Vertex('u1', 'A'))
        q._vertices['u1'].candidates = [v1]

        self.assertEqual(len(g._solutions), 0)
        g._subgraphSearch({}, q)
        self.assertEqual(len(g._solutions), 1)
        self.assertIn('u1', g._solutions[0])
        self.assertEquals(g._solutions[0]['u1'], 'v1')
コード例 #7
0
    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)
コード例 #8
0
ファイル: testGenerator.py プロジェクト: riffsircar/GraphGen
    def testAddNewVertices(self):
        # Production rhs has no vertices, so nothing done.
        g = Graph()
        lhs = Graph()
        rhs = Graph()
        p = Production(lhs, rhs)
        gen = Generator()
        self.assertEqual(len(g._vertices), 0)
        gen._addNewVertices(g, p, {})
        self.assertEqual(len(g._vertices), 0)
        
        # Production rhs has vertices, but they all appear in the LHS. Hence
        # they aren't new and nothing is done.
        lhs.addVertex(Vertex('l1', 'A', 1))
        rhs.addVertex(Vertex('r1', 'A', 1))
        self.assertEqual(len(g._vertices), 0)
        gen._addNewVertices(g, p, {})
        self.assertEqual(len(g._vertices), 0)

        # rhs has one new vertex not in the lhs.
        rhsMapping = {}
        rhs.addVertex(Vertex('r2', 'B', 2))
        self.assertEqual(len(g._vertices), 0)
        gen._addNewVertices(g, p, rhsMapping)
        self.assertEqual(len(g._vertices), 1)
        self.assertIn('v0', g._vertices)               # new vertex is v0
        self.assertEqual(g._vertices['v0'].label, 'B') # with label B
        self.assertEqual(g._vertices['v0'].number, 2)  # with number 2
        self.assertIn('r2', rhsMapping)                # now appears in rhsMapping
        self.assertEqual(rhsMapping['r2'], 'v0')       # r2 mapped to v0 (the newly added vertex) in graph
コード例 #9
0
ファイル: testGenerator.py プロジェクト: riffsircar/GraphGen
    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')
コード例 #10
0
ファイル: testGenerator.py プロジェクト: riffsircar/GraphGen
    def testMapRHSToGraph(self):
        # No vertices in rhs. Mapping returned is empty.
        g = Graph()
        lhs = Graph()
        rhs = Graph()
        p = Production(lhs, rhs)
        gen = Generator()
        rhsMapping = gen._mapRHSToGraph(g, p, {})
        self.assertEqual(len(rhsMapping), 0)

        # rhs has vertex r1, but it doesn't appear in the lhs. Mapping returned
        # is empty.
        rhs.addVertex(Vertex('r1', 'A', '1'))
        rhsMapping = gen._mapRHSToGraph(g, p, {})
        self.assertEqual(len(rhsMapping), 0)

        # rhs vertex r1 also appears in lhs as l1, which is mapped to g1. 
        # r1 should appear in rhsMapping mapped to g1.
        lhs.addVertex(Vertex('l1', 'A', '1'))
        rhsMapping = gen._mapRHSToGraph(g, p, {'l1':'g1'})
        self.assertEqual(len(rhsMapping), 1)
        self.assertIn('r1', rhsMapping)
        self.assertEqual(rhsMapping['r1'], 'g1')
コード例 #11
0
    def testParseVertexID(self):
        p = Parser(Lexer(''))

        # No text label raises an error.
        g = Graph()
        t = Token(0, '123')
        self.assertRaises(AttributeError, p._parseVertexID, t, g)

        # Only a label - doesn't exist in the graph.
        g = Graph()
        t = Token(0, 'A')
        v = p._parseVertexID(t, g)
        self.assertEqual(v.label, 'A')
        self.assertIsNone(v.number)

        # Label and a number - not in the graph.
        g = Graph()
        t = Token(0, 'A1')
        v = p._parseVertexID(t, g)
        self.assertEqual(v.label, 'A')
        self.assertEqual(v.number, '1')

        # Only a label - already in the graph.
        g = Graph()
        u = Vertex('v1', 'A')
        g.addVertex(u)
        t = Token(0, 'A')
        v = p._parseVertexID(t, g)
        self.assertEqual(v, u)

        # Label and a number - already in the graph.
        g = Graph()
        u = Vertex('v1', 'A', '1')
        g.addVertex(u)
        t = Token(0, 'A1')
        v = p._parseVertexID(t, g)
        self.assertEqual(v, u)
コード例 #12
0
ファイル: testGenerator.py プロジェクト: riffsircar/GraphGen
    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}')
コード例 #13
0
ファイル: testGraph.py プロジェクト: drobertadams/YapyGraph
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}")
コード例 #14
0
ファイル: testGenerator.py プロジェクト: riffsircar/GraphGen
    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)