Exemplo n.º 1
0
    def testMatch(self): 
        matcher = GraphMatch(algorithm="U", alpha=0.3)
        permutation, distance, time = matcher.match(self.graph1, self.graph2)

        #Checked output file - seems correct 
        
        distance2 = GraphMatch(alpha=0.0).distance(self.graph1, self.graph2, permutation)
        self.assertAlmostEquals(distance[0], distance2)
        
        #Now test case in which alpha is different 
        matcher = GraphMatch(algorithm="U", alpha=0.5)
        permutation, distance, time = matcher.match(self.graph1, self.graph2)
        distance2 = GraphMatch(alpha=0.0).distance(self.graph1, self.graph2, permutation)
        self.assertAlmostEquals(distance[0], distance2)
        
        #Test normalised distance 
        alpha = 0.0
        permutation, distance, time = GraphMatch(algorithm="U", alpha=alpha).match(self.graph1, self.graph2)
        distance2 = GraphMatch(alpha=alpha).distance(self.graph1, self.graph2, permutation, True)
        self.assertAlmostEquals(distance[1], distance2)
        
        alpha = 1.0
        permutation, distance, time = GraphMatch(algorithm="U", alpha=alpha).match(self.graph1, self.graph2)
        distance2 = GraphMatch(alpha=alpha).distance(self.graph1, self.graph2, permutation, True)
        self.assertAlmostEquals(distance[1], distance2, 5)
        
        #Test empty graph
        alpha = 0.0
        graph1 = SparseGraph(VertexList(0, 0))
        graph2 = SparseGraph(VertexList(0, 0))
        
        permutation, distance, time = GraphMatch(algorithm="U", alpha=alpha).match(graph1, graph2)
        
        nptst.assert_array_equal(permutation, numpy.array([], numpy.int))
        self.assertEquals(distance, [0, 0, 0])
        
        #Test where 1 graph is empty 
        permutation, distance, time = GraphMatch(algorithm="U", alpha=alpha).match(graph1, self.graph1)
        self.assertEquals(numpy.linalg.norm(self.graph1.getWeightMatrix())**2, distance[0])
        self.assertEquals(distance[1], 1)
        self.assertEquals(distance[2], 1)
        
        permutation, distance, time = GraphMatch(algorithm="U", alpha=alpha).match(self.graph1, graph1)
        self.assertEquals(numpy.linalg.norm(self.graph1.getWeightMatrix())**2, distance[0])
        self.assertEquals(distance[1], 1)
        self.assertEquals(distance[2], 1)
        
        alpha = 1.0
        permutation, distance, time = GraphMatch(algorithm="U", alpha=alpha).match(graph1, self.graph1)
        self.assertEquals(numpy.linalg.norm(self.graph1.getWeightMatrix())**2, distance[0])
        
        V2 = self.graph1.vlist.getVertices()
        V1 = numpy.zeros(V2.shape)
        C = GraphMatch(algorithm="U", alpha=alpha).matrixSimilarity(V1, V2)
        dist = numpy.trace(C)/numpy.linalg.norm(C)
        
        self.assertAlmostEquals(distance[1], -dist, 4)
        self.assertAlmostEquals(distance[2], -dist, 4)
        
        permutation, distance, time = GraphMatch(algorithm="U", alpha=alpha).match(self.graph1, graph1)
        self.assertEquals(numpy.linalg.norm(self.graph1.getWeightMatrix())**2, distance[0])
        self.assertAlmostEquals(distance[1], -dist, 4)
        self.assertAlmostEquals(distance[2], -dist, 4)
        
        #Test one graph which is a subgraph of another 
        p = 0.2 
        k = 10 
        numVertices = 20
        generator = SmallWorldGenerator(p, k)
        graph = SparseGraph(VertexList(numVertices, 2))
        graph = generator.generate(graph)
        
        subgraphInds = numpy.random.permutation(numVertices)[0:10]
        subgraph = graph.subgraph(subgraphInds)
        
        matcher = GraphMatch(algorithm="U", alpha=0.0)
        permutation, distance, time = matcher.match(graph, subgraph)
        distance = matcher.distance(graph, subgraph, permutation, True, True)
        
        self.assertTrue(distance < 1)
Exemplo n.º 2
0
    def testDistance(self): 
        permutation = numpy.arange(self.numVertices)
        dist =  GraphMatch(alpha=0.0).distance(self.graph1, self.graph1, permutation)
        self.assertEquals(dist, 0.0)
        
        dist =  GraphMatch(alpha=0.0).distance(self.graph1, self.graph2, permutation)
        self.assertAlmostEquals(dist, 50.0)
        
        permutation = numpy.arange(self.numVertices)
        permutation[8] = 9
        permutation[9] = 8
        dist =  GraphMatch(alpha=0.0).distance(self.graph1, self.graph2, permutation)
        self.assertAlmostEquals(dist, 54.0)
        
        #Try graphs of unequal size 
        graph3 = self.graph1.subgraph(range(8))
        permutation = numpy.arange(self.numVertices)
        dist1 =  GraphMatch(alpha=0.0).distance(self.graph1, graph3, permutation)
        dist1a =  GraphMatch(alpha=0.0).distance(graph3, self.graph1, permutation)
        self.assertEquals(dist1, dist1a)

        graph3 = self.graph1.subgraph(range(5))
        dist2 =  GraphMatch(alpha=0.0).distance(self.graph1, graph3, permutation)
        dist2a =  GraphMatch(alpha=0.0).distance(graph3, self.graph1, permutation)
        self.assertEquals(dist2, dist2a)
        self.assertTrue(dist1 < dist2)
        
        #Test case where alpha!=0 
        alpha = 1.0
        permutation = numpy.arange(self.numVertices)
        distance = GraphMatch(alpha=alpha).distance(self.graph1, self.graph2, permutation, False)
        C = GraphMatch(alpha=alpha).vertexSimilarities(self.graph1, self.graph2)
        distance2 = -numpy.trace(C)
        self.assertEquals(distance, distance2)
        
        #Check case where we want non negativve distance even when alpha!=0 
        distance = GraphMatch(alpha=alpha).distance(self.graph1, self.graph2, permutation, True, True)
        self.assertTrue(distance >= 0)
        
        permutation = numpy.arange(self.numVertices)
        distance = GraphMatch(alpha=alpha).distance(self.graph1, self.graph1, permutation, True, True)
        self.assertEquals(distance, 0)
        
        #Check case where both graphs are empty 
        graph1 = SparseGraph(VertexList(0, 0))
        graph2 = SparseGraph(VertexList(0, 0))
        
        permutation = numpy.array([], numpy.int)
        distance = GraphMatch(alpha=alpha).distance(graph1, graph1, permutation, True, True)
        self.assertEquals(distance, 0)
        
        #Now, just one graph is empty 
        #Distance is always 1 due to normalisations 
        alpha = 0.0
        permutation = numpy.arange(10, dtype=numpy.int)
        distance = GraphMatch(alpha=alpha).distance(self.graph1, graph1, permutation, True, True)
        self.assertEquals(distance, 1.0)
        
        permutation = numpy.arange(10, dtype=numpy.int)
        distance = GraphMatch(alpha=alpha).distance(self.graph2, graph1, permutation, True, True)
        self.assertEquals(distance, 1.0)
        
        #distance = GraphMatch(alpha=alpha).distance(self.graph1, graph1, permutation, False, False)
        #self.assertEquals(distance, numpy.linalg.norm(self.graph1.getWeightMatrix())**2)
        
        alpha = 0.9 
        matcher = GraphMatch("U", alpha=alpha)
        permutation, distanceVector, time = matcher.match(self.graph2, graph1)
        distance = matcher.distance(self.graph2, graph1, permutation, True, True)
        self.assertEquals(distance, 1.0)        
        
        alpha = 1.0
        permutation = numpy.arange(10, dtype=numpy.int)
        distance = GraphMatch(alpha=alpha).distance(self.graph1, graph1, permutation, True, True)
        self.assertEquals(distance, 1.0)
        
        permutation = numpy.arange(10, dtype=numpy.int)
        distance = GraphMatch(alpha=alpha).distance(self.graph2, graph1, permutation, True, True)
        self.assertEquals(distance, 1.0)
        
        alpha = 0.5
        permutation = numpy.arange(10, dtype=numpy.int)
        distance = GraphMatch(alpha=alpha).distance(self.graph2, graph1, permutation, True, True)
        self.assertEquals(distance, 1.0)
           
        #Test on unequal graphs and compare against distance from graphm 
        alpha = 0.5 
        matcher = GraphMatch(alpha=alpha)
        permutation, distanceVector, time = matcher.match(self.graph1, self.graph2)
        distance = matcher.distance(self.graph1, self.graph2, permutation, True, False)
        
        self.assertAlmostEquals(distanceVector[1], distance, 3)
Exemplo n.º 3
0
    def testAddGraph(self): 
        maxSize = 100
        metrics = HIVGraphMetrics2(self.graph, maxSize)
        
        metrics.addGraph(self.graph)

        self.assertAlmostEquals(metrics.objectives[0], -0.834, 3)
        self.assertAlmostEquals(metrics.meanObjective(), -0.834, 3)
        
        #Start a new graph 
        #Compute distances directly 
        matcher = GraphMatch("QCV")
        graph =  HIVGraph(self.graph.size)
        dists = [] 
        metrics = HIVGraphMetrics2(self.graph, maxSize)
        
        graph.vlist.setInfected(1, 0.0)
        graph.vlist.setDetected(1, 0.1, 0)
        graph.endEventTime = 1
        metrics.addGraph(graph)
        
        
        t = graph.endTime()
        subgraph1 = graph.subgraph(graph.removedIndsAt(t))
        subgraph2 = self.graph.subgraph(graph.removedIndsAt(t)) 
        permutation, distance, time = matcher.match(subgraph1, subgraph2)
        lastObj, lastGraphObj, lastLabelObj = matcher.distance(subgraph1, subgraph2, permutation, True, False, True)
        self.assertEquals(metrics.objectives[-1], lastObj)

        self.assertFalse(metrics.shouldBreak())
        
        graph.vlist.setInfected(2, 2.0)
        graph.vlist.setDetected(2, 2.0, 0)
        metrics.addGraph(graph)
        
        t = graph.endTime()
        subgraph1 = graph.subgraph(graph.removedIndsAt(t))
        subgraph2 = self.graph.subgraph(graph.removedIndsAt(t)) 
        permutation, distance, time = matcher.match(subgraph1, subgraph2)
        lastObj, lastGraphObj, lastLabelObj = matcher.distance(subgraph1, subgraph2, permutation, True, False, True)
        self.assertEquals(metrics.objectives[-1], lastObj)   
        self.assertFalse(metrics.shouldBreak())
        
        graph.vlist.setInfected(7, 3.0)
        graph.vlist.setDetected(7, 3.0, 0)
        metrics.addGraph(graph)
        
        t = graph.endTime()
        subgraph1 = graph.subgraph(graph.removedIndsAt(t))
        subgraph2 = self.graph.subgraph(graph.removedIndsAt(t)) 
        permutation, distance, time = matcher.match(subgraph1, subgraph2)
        lastObj, lastGraphObj, lastLabelObj = matcher.distance(subgraph1, subgraph2, permutation, True, False, True)
        self.assertEquals(metrics.objectives[-1], lastObj) 
        self.assertFalse(metrics.shouldBreak())
        
        #Test case where one graph has zero size 
        graph1 = HIVGraph(10)
        graph2 = HIVGraph(10)
        
        graph1.vlist[:, HIVVertices.stateIndex] = HIVVertices.removed
        metrics = HIVGraphMetrics2(graph2, maxSize)
        metrics.addGraph(graph1)
        
        #Problem is that distance is 1 when one graph is zero
        self.assertEquals(len(metrics.objectives), 0) 
Exemplo n.º 4
0
class HIVGraphMetrics2(object): 
    def __init__(self, realGraph, maxSize=100, matcher=None, startTime=None, alpha=0.5):
        """
        A class to model metrics about and between HIVGraphs such as summary 
        statistics and distances. In this case we perform graph matching 
        using the QCV algorithm and other graph matching methods. 
        
        :param realGraph: The target epidemic graph 
        
        :param epsilon: The max mean objective before we break the simulation
        
        :param matcher: The graph matcher object to compute graph objective. 
        
        :param startTime: A start time of the simulation 
        
        :param alpha: This is the weight factor for the average. Weights decay faster with a larger alpha. 
        """
        
        self.objectives = [] 
        self.graphObjs = []
        self.graphSizes = []
        self.labelObjs = []
        self.times = []
        
        self.realGraph = realGraph
        self.maxSize = maxSize
        self.startTime = startTime 
        self.computationalTimes = []
        self.alpha = alpha         
        
        if matcher == None: 
            self.matcher = GraphMatch("QCV")
        else: 
            self.matcher = matcher 
        
    def addGraph(self, simulatedGraph): 
        """
        Compute the objective between this graph and the realGraph at the time 
        of the last event of this one. 
        """
        t = simulatedGraph.endTime()
        #Only select vertices added after startTime and before t 
        inds = numpy.setdiff1d(simulatedGraph.removedIndsAt(t), simulatedGraph.removedIndsAt(self.startTime))
        subgraph = simulatedGraph.subgraph(inds)  
        
        inds = numpy.setdiff1d(self.realGraph.removedIndsAt(t), self.realGraph.removedIndsAt(self.startTime))
        subTargetGraph = self.realGraph.subgraph(inds)  
        
        #logging.debug("Simulated size " + str(subgraph.size) + " and real size " + str(subTargetGraph.size))
        self.graphSizes.append(subgraph.size)
            
        #Only add objective if the real graph has nonzero size
        if subTargetGraph.size != 0 and subgraph.size <= self.maxSize: 
            permutation, distance, time = self.matcher.match(subgraph, subTargetGraph)
            lastObj, lastGraphObj, lastLabelObj = self.matcher.distance(subgraph, subTargetGraph, permutation, True, False, True)
     
            self.computationalTimes.append(time)
            self.objectives.append(lastObj)
            self.graphObjs.append(lastGraphObj)
            self.labelObjs.append(lastLabelObj)
            self.times.append(t) 
        else: 
            logging.debug("Not adding objective at time " + str(t) + " with simulated size " + str(subgraph.size) + " and real size " + str(subTargetGraph.size))
            
    def meanObjective(self, objectives=None):
        """
        This is the moving average objective of the graph matches so far. 
        """
        if objectives == None: 
            objectives = numpy.array(self.objectives)       
        
        if objectives.shape[0]!=0: 
            weights = self.alpha * (1 - self.alpha)**(numpy.arange(objectives.shape[0], 0, -1)-1)
            logging.debug("weights="+str(weights))
            return numpy.average(objectives, weights=weights)
        else: 
            return float("inf")
            
    def meanGraphObjective(self):
        """
        This is the mean graph objective of the graph matches so far. 
        """
        graphObjs = numpy.array(self.graphObjs)
        if graphObjs.shape[0]!=0: 
            return graphObjs.mean()
        else: 
            return float("inf")
            
    def meanLabelObjective(self):
        """
        This is the mean label objective of the graph matches so far. 
        """
        labelObjs = numpy.array(self.labelObjs)
        if labelObjs.shape[0]!=0: 
            return labelObjs.mean()
        else: 
            return float("inf")
        
    def shouldBreak(self): 
        """
        We break when the graph size exceeds a threshold 
        """
        if self.graphSizes[-1] > self.maxSize:
            logging.debug("Breaking as size has become too large: " + str(self.graphSizes[-1]) + " > " + str(self.maxSize))
            
        return self.graphSizes[-1] > self.maxSize 
        
Exemplo n.º 5
0
    def testMatch(self):
        matcher = GraphMatch(algorithm="U", alpha=0.3)
        permutation, distance, time = matcher.match(self.graph1, self.graph2)

        #Checked output file - seems correct

        distance2 = GraphMatch(alpha=0.0).distance(self.graph1, self.graph2,
                                                   permutation)
        self.assertAlmostEquals(distance[0], distance2)

        #Now test case in which alpha is different
        matcher = GraphMatch(algorithm="U", alpha=0.5)
        permutation, distance, time = matcher.match(self.graph1, self.graph2)
        distance2 = GraphMatch(alpha=0.0).distance(self.graph1, self.graph2,
                                                   permutation)
        self.assertAlmostEquals(distance[0], distance2)

        #Test normalised distance
        alpha = 0.0
        permutation, distance, time = GraphMatch(algorithm="U",
                                                 alpha=alpha).match(
                                                     self.graph1, self.graph2)
        distance2 = GraphMatch(alpha=alpha).distance(self.graph1, self.graph2,
                                                     permutation, True)
        self.assertAlmostEquals(distance[1], distance2)

        alpha = 1.0
        permutation, distance, time = GraphMatch(algorithm="U",
                                                 alpha=alpha).match(
                                                     self.graph1, self.graph2)
        distance2 = GraphMatch(alpha=alpha).distance(self.graph1, self.graph2,
                                                     permutation, True)
        self.assertAlmostEquals(distance[1], distance2, 5)

        #Test empty graph
        alpha = 0.0
        graph1 = SparseGraph(VertexList(0, 0))
        graph2 = SparseGraph(VertexList(0, 0))

        permutation, distance, time = GraphMatch(algorithm="U",
                                                 alpha=alpha).match(
                                                     graph1, graph2)

        nptst.assert_array_equal(permutation, numpy.array([], numpy.int))
        self.assertEquals(distance, [0, 0, 0])

        #Test where 1 graph is empty
        permutation, distance, time = GraphMatch(algorithm="U",
                                                 alpha=alpha).match(
                                                     graph1, self.graph1)
        self.assertEquals(
            numpy.linalg.norm(self.graph1.getWeightMatrix())**2, distance[0])
        self.assertEquals(distance[1], 1)
        self.assertEquals(distance[2], 1)

        permutation, distance, time = GraphMatch(algorithm="U",
                                                 alpha=alpha).match(
                                                     self.graph1, graph1)
        self.assertEquals(
            numpy.linalg.norm(self.graph1.getWeightMatrix())**2, distance[0])
        self.assertEquals(distance[1], 1)
        self.assertEquals(distance[2], 1)

        alpha = 1.0
        permutation, distance, time = GraphMatch(algorithm="U",
                                                 alpha=alpha).match(
                                                     graph1, self.graph1)
        self.assertEquals(
            numpy.linalg.norm(self.graph1.getWeightMatrix())**2, distance[0])

        V2 = self.graph1.vlist.getVertices()
        V1 = numpy.zeros(V2.shape)
        C = GraphMatch(algorithm="U", alpha=alpha).matrixSimilarity(V1, V2)
        dist = numpy.trace(C) / numpy.linalg.norm(C)

        self.assertAlmostEquals(distance[1], -dist, 4)
        self.assertAlmostEquals(distance[2], -dist, 4)

        permutation, distance, time = GraphMatch(algorithm="U",
                                                 alpha=alpha).match(
                                                     self.graph1, graph1)
        self.assertEquals(
            numpy.linalg.norm(self.graph1.getWeightMatrix())**2, distance[0])
        self.assertAlmostEquals(distance[1], -dist, 4)
        self.assertAlmostEquals(distance[2], -dist, 4)

        #Test one graph which is a subgraph of another
        p = 0.2
        k = 10
        numVertices = 20
        generator = SmallWorldGenerator(p, k)
        graph = SparseGraph(VertexList(numVertices, 2))
        graph = generator.generate(graph)

        subgraphInds = numpy.random.permutation(numVertices)[0:10]
        subgraph = graph.subgraph(subgraphInds)

        matcher = GraphMatch(algorithm="U", alpha=0.0)
        permutation, distance, time = matcher.match(graph, subgraph)
        distance = matcher.distance(graph, subgraph, permutation, True, True)

        self.assertTrue(distance < 1)
Exemplo n.º 6
0
    def testDistance(self):
        permutation = numpy.arange(self.numVertices)
        dist = GraphMatch(alpha=0.0).distance(self.graph1, self.graph1,
                                              permutation)
        self.assertEquals(dist, 0.0)

        dist = GraphMatch(alpha=0.0).distance(self.graph1, self.graph2,
                                              permutation)
        self.assertAlmostEquals(dist, 50.0)

        permutation = numpy.arange(self.numVertices)
        permutation[8] = 9
        permutation[9] = 8
        dist = GraphMatch(alpha=0.0).distance(self.graph1, self.graph2,
                                              permutation)
        self.assertAlmostEquals(dist, 54.0)

        #Try graphs of unequal size
        graph3 = self.graph1.subgraph(range(8))
        permutation = numpy.arange(self.numVertices)
        dist1 = GraphMatch(alpha=0.0).distance(self.graph1, graph3,
                                               permutation)
        dist1a = GraphMatch(alpha=0.0).distance(graph3, self.graph1,
                                                permutation)
        self.assertEquals(dist1, dist1a)

        graph3 = self.graph1.subgraph(range(5))
        dist2 = GraphMatch(alpha=0.0).distance(self.graph1, graph3,
                                               permutation)
        dist2a = GraphMatch(alpha=0.0).distance(graph3, self.graph1,
                                                permutation)
        self.assertEquals(dist2, dist2a)
        self.assertTrue(dist1 < dist2)

        #Test case where alpha!=0
        alpha = 1.0
        permutation = numpy.arange(self.numVertices)
        distance = GraphMatch(alpha=alpha).distance(self.graph1, self.graph2,
                                                    permutation, False)
        C = GraphMatch(alpha=alpha).vertexSimilarities(self.graph1,
                                                       self.graph2)
        distance2 = -numpy.trace(C)
        self.assertEquals(distance, distance2)

        #Check case where we want non negativve distance even when alpha!=0
        distance = GraphMatch(alpha=alpha).distance(self.graph1, self.graph2,
                                                    permutation, True, True)
        self.assertTrue(distance >= 0)

        permutation = numpy.arange(self.numVertices)
        distance = GraphMatch(alpha=alpha).distance(self.graph1, self.graph1,
                                                    permutation, True, True)
        self.assertEquals(distance, 0)

        #Check case where both graphs are empty
        graph1 = SparseGraph(VertexList(0, 0))
        graph2 = SparseGraph(VertexList(0, 0))

        permutation = numpy.array([], numpy.int)
        distance = GraphMatch(alpha=alpha).distance(graph1, graph1,
                                                    permutation, True, True)
        self.assertEquals(distance, 0)

        #Now, just one graph is empty
        #Distance is always 1 due to normalisations
        alpha = 0.0
        permutation = numpy.arange(10, dtype=numpy.int)
        distance = GraphMatch(alpha=alpha).distance(self.graph1, graph1,
                                                    permutation, True, True)
        self.assertEquals(distance, 1.0)

        permutation = numpy.arange(10, dtype=numpy.int)
        distance = GraphMatch(alpha=alpha).distance(self.graph2, graph1,
                                                    permutation, True, True)
        self.assertEquals(distance, 1.0)

        #distance = GraphMatch(alpha=alpha).distance(self.graph1, graph1, permutation, False, False)
        #self.assertEquals(distance, numpy.linalg.norm(self.graph1.getWeightMatrix())**2)

        alpha = 0.9
        matcher = GraphMatch("U", alpha=alpha)
        permutation, distanceVector, time = matcher.match(self.graph2, graph1)
        distance = matcher.distance(self.graph2, graph1, permutation, True,
                                    True)
        self.assertEquals(distance, 1.0)

        alpha = 1.0
        permutation = numpy.arange(10, dtype=numpy.int)
        distance = GraphMatch(alpha=alpha).distance(self.graph1, graph1,
                                                    permutation, True, True)
        self.assertEquals(distance, 1.0)

        permutation = numpy.arange(10, dtype=numpy.int)
        distance = GraphMatch(alpha=alpha).distance(self.graph2, graph1,
                                                    permutation, True, True)
        self.assertEquals(distance, 1.0)

        alpha = 0.5
        permutation = numpy.arange(10, dtype=numpy.int)
        distance = GraphMatch(alpha=alpha).distance(self.graph2, graph1,
                                                    permutation, True, True)
        self.assertEquals(distance, 1.0)

        #Test on unequal graphs and compare against distance from graphm
        alpha = 0.5
        matcher = GraphMatch(alpha=alpha)
        permutation, distanceVector, time = matcher.match(
            self.graph1, self.graph2)
        distance = matcher.distance(self.graph1, self.graph2, permutation,
                                    True, False)

        self.assertAlmostEquals(distanceVector[1], distance, 3)