Exemple #1
0
 def testUpdateState(self):
     matches = {}
     u = Vertex('u1')
     v = Vertex('v1')
     g = Graph()
     g._updateState(u, v, matches)
     self.assertEquals(len(g._matchHistory), 1)
     self.assertEquals(len(matches), 1)
     self.assertEquals(matches[u.id], 'v1')
Exemple #2
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)
Exemple #3
0
 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)
Exemple #4
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')
Exemple #5
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)
Exemple #6
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)
Exemple #7
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')
Exemple #8
0
    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))
Exemple #9
0
    def _parseGraph(self):
        """
        graph -> edgeList | edgeList ',' graph

        An edgeList represents a connected path of vertices. A "graph" is
        a comma-separated list of such paths. This method builds a graph
        from the given representation.
        Input: none
        Output: Graph build from the incoming list of edgeLists
        """
        #logging.debug('parsing new graph')
        g = Graph()
        self._parseEdgeList(g)
        while self.lookahead.type == TokenTypes.COMMA:
            self._match(TokenTypes.COMMA)
            self._parseEdgeList(g)
        return g
Exemple #10
0
    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')
Exemple #11
0
    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')
Exemple #12
0
    def testRestoreState(self):
        # Save state with a couple calls to updateState() and then see that
        # they are undone.
        g = Graph()
        matches = {}
        u1 = Vertex('u1')
        v1 = Vertex('v1')
        g._updateState(u1, v1, matches)  # u1 matched with v1
        u2 = Vertex('u2')
        v2 = Vertex('v2')
        g._updateState(u2, v2, matches)  # u2 matched with v2

        # Now we should get the dictionary with only the original set of
        # matches.
        matches = g._restoreState(matches)
        self.assertEquals(len(matches), 1)
        self.assertTrue('u1' in matches)
        self.assertTrue(matches['u1'], 'v1')

        # Now we should have an empty dictionary.
        matches = g._restoreState(matches)
        self.assertEquals(len(matches), 0)
Exemple #13
0
    def testRefineCandidates(self):
        # An empty candidate list should return an empty list.
        g = Graph()
        c = g._refineCandidates([], None, {})
        self.assertEquals(len(c), 0)

        # Build a graph and some vertices for use later.
        u = Vertex('g0')  # query vertex
        v = Vertex('g0')  # data vertex

        # Test with unmatched candidate with the v.degree >= u.degree. This
        # should return the id of v.
        u.degree = 1
        v.degree = 1
        c = [v]
        c = g._refineCandidates(c, u, {})
        self.assertEqual(len(c), 1)
        self.assertEqual(c[0].id, 'g0')

        # Test with matched candidate with v.degree >= u.degree. This should
        # return no candidates.
        u.degree = 1
        v.degree = 1
        m = {'g0': 'g0'}
        c = g._refineCandidates(c, u, m)
        self.assertEqual(len(c), 0)

        # Test with unmatched candidate with v.degree < u.degree. This should
        # return no candidates.
        u.degree = 1
        v.degree = 0
        c = g._refineCandidates(c, u, {})
        self.assertEqual(len(c), 0)

        # Test with matched candidate with v.degree < u.degree. This should
        # return no candidates.
        u.degree = 1
        v.degree = 0
        m = {'g0': 'g0'}
        c = g._refineCandidates(c, u, m)
        self.assertEqual(len(c), 0)
Exemple #14
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}')
Exemple #15
0
    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)
Exemple #16
0
    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)
Exemple #17
0
    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)
Exemple #18
0
    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)
Exemple #19
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')
Exemple #20
0
    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')
Exemple #21
0
    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}')
Exemple #22
0
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}")
Exemple #23
0
    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')
Exemple #24
0
    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)
Exemple #25
0
    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'}))
Exemple #26
0
    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)
Exemple #27
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)
Exemple #28
0
    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
Exemple #29
0
 def setUp(self):
     self.g = Graph()
Exemple #30
0
    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')