def testMatrixSimilarity(self): numExamples = 5 numFeatures = 3 V1 = numpy.random.rand(numExamples, numFeatures) matcher = GraphMatch(alpha=0.0) C = matcher.matrixSimilarity(V1, V1) Cdiag = numpy.diag(C) nptst.assert_array_almost_equal(Cdiag, numpy.ones(Cdiag.shape[0])) V1[:, 2] *= 10 C2 = matcher.matrixSimilarity(V1, V1) Cdiag = numpy.diag(C2) nptst.assert_array_almost_equal(Cdiag, numpy.ones(Cdiag.shape[0])) nptst.assert_array_almost_equal(C, C2) #print("Running match") J = numpy.ones((numExamples, numFeatures)) Z = numpy.zeros((numExamples, numFeatures)) C2 = matcher.matrixSimilarity(J, Z) #This should be 1 ideally nptst.assert_array_almost_equal(C2, numpy.ones(C2.shape)) C2 = matcher.matrixSimilarity(J, J) nptst.assert_array_almost_equal(C2, numpy.ones(C2.shape))
def profileSimulateGraphMatch(self): N, matchAlpha, breakDist, purtScale = HIVModelUtils.toyABCParams() startDate, endDate, recordStep, M, targetGraph = HIVModelUtils.toySimulationParams() theta, stdTheta = HIVModelUtils.toyTheta() featureInds= numpy.ones(targetGraph.vlist.getNumFeatures(), numpy.bool) featureInds[HIVVertices.dobIndex] = False featureInds[HIVVertices.infectionTimeIndex] = False featureInds[HIVVertices.hiddenDegreeIndex] = False featureInds[HIVVertices.stateIndex] = False featureInds = numpy.arange(featureInds.shape[0])[featureInds] #QCV is fastest and most accurate #PATH is slowests but quite accurate #RANK is very fast by less accurate than PATH #U is fastest but least accurate matcher = GraphMatch("QCV", alpha=matchAlpha, featureInds=featureInds, useWeightM=False) matcher.lambdaM = 50 matcher.init = "rand" graphMetrics = HIVGraphMetrics2(targetGraph, breakDist, matcher, float(endDate)) def run(): times, infectedIndices, removedIndices, graph = HIVModelUtils.simulate(theta, startDate, endDate, recordStep, M, graphMetrics) print("Mean distance " + str(graphMetrics.meanDistance())) ProfileUtils.profile('run()', globals(), locals())
def testVertexSimilarities(self): matcher = GraphMatch(alpha=0.0) C = matcher.vertexSimilarities(self.graph1, self.graph1) Cdiag = numpy.diag(C) nptst.assert_array_almost_equal(Cdiag, numpy.ones(Cdiag.shape[0])) #Now compute trace(C)/||C|| #print(numpy.trace(C)/numpy.linalg.norm(C)) #Test use of feature inds matcher = GraphMatch(alpha=0.0, featureInds=numpy.array([0])) C = matcher.vertexSimilarities(self.graph1, self.graph2) #Now, let's vary the non-used feature self.graph1.vlist[:, 1] = 0 C2 = matcher.vertexSimilarities(self.graph1, self.graph2) nptst.assert_array_equal(C, C2) self.graph2.vlist[:, 1] = 0 C2 = matcher.vertexSimilarities(self.graph1, self.graph2) nptst.assert_array_equal(C, C2) #Vary used feature self.graph1.vlist[:, 0] = 0 C2 = matcher.vertexSimilarities(self.graph1, self.graph2) self.assertTrue((C != C2).any())
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 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)
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)
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)
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
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)
def testDistance2(self): permutation = numpy.arange(self.numVertices) dist = GraphMatch(alpha=0.0).distance2(self.graph1, self.graph1, permutation) self.assertEquals(dist, 0.0) dist = GraphMatch(alpha=0.0).distance2(self.graph1, self.graph2, permutation) dist2 = GraphMatch(alpha=0.0).distance(self.graph1, self.graph2, permutation, True) self.assertAlmostEquals(dist, dist2) permutation = numpy.arange(self.numVertices) permutation[8] = 9 permutation[9] = 8 dist = GraphMatch(alpha=0.0).distance2(self.graph1, self.graph2, permutation) dist2 = GraphMatch(alpha=0.0).distance(self.graph1, self.graph2, permutation, True) self.assertAlmostEquals(dist, dist2) #Try graphs of unequal size graph3 = self.graph1.subgraph(range(8)) permutation = numpy.arange(self.numVertices) dist1 = GraphMatch(alpha=0.0).distance2(self.graph1, graph3, permutation) dist1a = GraphMatch(alpha=0.0).distance2(graph3, self.graph1, permutation) self.assertEquals(dist1, dist1a) graph3 = self.graph1.subgraph(range(5)) dist2 = GraphMatch(alpha=0.0).distance2(self.graph1, graph3, permutation) dist2a = GraphMatch(alpha=0.0).distance2(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).distance2(self.graph1, self.graph1, permutation) self.assertEquals(distance, 0.0) #Check distances are between 0 and 1 for i in range(100): alpha = numpy.random.rand() permutation = numpy.random.permutation(self.numVertices) distance = GraphMatch(alpha=alpha).distance2( self.graph1, self.graph1, permutation) self.assertTrue(0 <= distance <= 1)
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)