Exemplo n.º 1
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
Exemplo n.º 2
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)
Exemplo n.º 3
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)
Exemplo n.º 4
0
    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'))
Exemplo n.º 5
0
 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)
Exemplo n.º 6
0
 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)
Exemplo n.º 7
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)
Exemplo n.º 8
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')
Exemplo n.º 9
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)
Exemplo n.º 10
0
    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)
Exemplo n.º 11
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')
Exemplo n.º 12
0
    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)
Exemplo n.º 13
0
 def testConstructorLabelNumber(self):
     """Building a vertex with an id, label, and number should store all."""
     v = Vertex('v1', 'label', 1)
     self.assertEqual(v.id, 'v1')
     self.assertEqual(v.label, 'label')
     self.assertEqual(v.number, 1)
     self.assertEqual(v.name, 'label1')
Exemplo n.º 14
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)
Exemplo n.º 15
0
 def testConstructorNoLabelNoNumber(self):
     """Building a vertex with only an id should have None for the label,
     and number."""
     v = Vertex('v1')
     self.assertEqual(v.id, 'v1')
     self.assertIsNone(v.label)
     self.assertIsNone(v.number)
     self.assertEqual(v.name, '')
Exemplo n.º 16
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')
Exemplo n.º 17
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')
Exemplo n.º 18
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)
Exemplo n.º 19
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)
Exemplo n.º 20
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))
Exemplo n.º 21
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)
Exemplo n.º 22
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}')
Exemplo n.º 23
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)
Exemplo n.º 24
0
 def _parseVertexID(self, token, graph):
     """
     Parses the given token (ID) into a text label and optional
     vertex number (e.g., "A1"). If a vertex with these two data don't 
     exist in the given graph, it is added. Otherwise, the existing 
     vertex from the graph is returned.
     """
     label = re.match('[A-z]+', token.text).group(0)
     match = re.search('[0-9]+$', token.text)
     number = match.group(0) if match is not None else None
     name = Vertex.makeName(label, number)
     vertex = graph.findVertex(name)
     if vertex == None:
         # graph doesn't contain a vertex with the label.
         vertex = Vertex(
             'v%d' % graph.numVertices,  # vertex id
             label,
             number)
         graph.addVertex(vertex)
     return vertex
Exemplo n.º 25
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')
Exemplo n.º 26
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)
Exemplo n.º 27
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)
Exemplo n.º 28
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)
Exemplo n.º 29
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')
Exemplo n.º 30
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}')