def cvModelSelection(self, graph, paramList, paramFunc, folds, errorFunc): """ ParamList is a list of lists of parameters and paramFunc is a list of the corresponding functions to call with the parameters as arguments. Note that a parameter can also be a tuple which is expanded out before the function is called. e.g. paramList = [[1, 2], [2, 1], [12, 1]] paramFunc = [predictor.setC, predictor.setD] """ inds = Sampling.crossValidation(folds, graph.getNumEdges()) errors = numpy.zeros((len(paramList), folds)) allEdges = graph.getAllEdges() for i in range(len(paramList)): paramSet = paramList[i] logging.debug("Using paramSet=" + str(paramSet)) for j in range(len(paramSet)): if type(paramSet[j]) == tuple: paramFunc[j](*paramSet[j]) else: paramFunc[j](paramSet[j]) predY = numpy.zeros(0) y = numpy.zeros(0) j = 0 for (trainInds, testInds) in inds: trainEdges = allEdges[trainInds, :] testEdges = allEdges[testInds, :] trainGraph = SparseGraph(graph.getVertexList(), graph.isUndirected()) trainGraph.addEdges(trainEdges, graph.getEdgeValues(trainEdges)) testGraph = SparseGraph(graph.getVertexList(), graph.isUndirected()) testGraph.addEdges(testEdges, graph.getEdgeValues(testEdges)) self.learnModel(trainGraph) predY = self.predictEdges(testGraph, testGraph.getAllEdges()) y = testGraph.getEdgeValues(testGraph.getAllEdges()) #Note that the order the edges is different in testGraphs as #opposed to graph when calling getAllEdges() errors[i, j] = errorFunc(y, predY) j = j + 1 logging.info("Error of current fold: " + str(numpy.mean(errors[i, :]))) meanErrors = numpy.mean(errors, 1) strErrors = numpy.std(errors, 1) return meanErrors, strErrors
def cvModelSelection(self, graph, paramList, paramFunc, folds, errorFunc): """ ParamList is a list of lists of parameters and paramFunc is a list of the corresponding functions to call with the parameters as arguments. Note that a parameter can also be a tuple which is expanded out before the function is called. e.g. paramList = [[1, 2], [2, 1], [12, 1]] paramFunc = [predictor.setC, predictor.setD] """ inds = Sampling.crossValidation(folds, graph.getNumEdges()) errors = numpy.zeros((len(paramList), folds)) allEdges = graph.getAllEdges() for i in range(len(paramList)): paramSet = paramList[i] logging.debug("Using paramSet=" + str(paramSet)) for j in range(len(paramSet)): if type(paramSet[j]) == tuple: paramFunc[j](*paramSet[j]) else: paramFunc[j](paramSet[j]) predY = numpy.zeros(0) y = numpy.zeros(0) j = 0 for (trainInds, testInds) in inds: trainEdges = allEdges[trainInds, :] testEdges = allEdges[testInds, :] trainGraph = SparseGraph(graph.getVertexList(), graph.isUndirected()) trainGraph.addEdges(trainEdges, graph.getEdgeValues(trainEdges)) testGraph = SparseGraph(graph.getVertexList(), graph.isUndirected()) testGraph.addEdges(testEdges, graph.getEdgeValues(testEdges)) self.learnModel(trainGraph) predY = self.predictEdges(testGraph, testGraph.getAllEdges()) y = testGraph.getEdgeValues(testGraph.getAllEdges()) #Note that the order the edges is different in testGraphs as #opposed to graph when calling getAllEdges() errors[i, j] = errorFunc(y, predY) j = j+1 logging.info("Error of current fold: " + str(numpy.mean(errors[i, :]))) meanErrors = numpy.mean(errors, 1) strErrors = numpy.std(errors, 1) return meanErrors, strErrors
def findInfoDecayGraph(self, egoTestFileName, alterTestFileName, egoIndicesR, alterIndices, egoIndicesNR, alterIndicesNR, egoFileName, alterFileName, missing=0): (egoTestArray, egoTitles) = self.readFile(egoTestFileName, self.egoTestIds, missing=0) (alterTestArray, alterTitles) = self.readFile(alterTestFileName, self.alterTestIds, missing=0) egoMarks = numpy.zeros(egoTestArray.shape[0]) alterMarks = numpy.zeros(alterTestArray.shape[0]) decays = numpy.zeros(egoIndicesR.shape[0]) correctAnswers = numpy.array([1,2,4,5,8,9,10,12]) wrongAnswers = numpy.array([3, 6, 7, 11]) for i in range(egoTestArray.shape[0]): egoMarks[i] = numpy.intersect1d(egoTestArray[i], correctAnswers).shape[0] egoMarks[i] += wrongAnswers.shape[0] - numpy.intersect1d(egoTestArray[i], wrongAnswers).shape[0] for i in range(alterMarks.shape[0]): alterMarks[i] = numpy.intersect1d(alterTestArray[i], correctAnswers).shape[0] alterMarks[i] += wrongAnswers.shape[0] - numpy.intersect1d(alterTestArray[i], wrongAnswers).shape[0] """ We just return how much the alter understood, since this represents the decay in understanding of the ego and transmission. """ for i in range(decays.shape[0]): decays[i] = alterMarks[alterIndices[i]] #A lot of people could not be bothered to fill the questions and hence #get 4 correct by default decays = (decays) / float(self.numTestQuestions) defaultDecay = 10**-6 #Finally, put the data into a graph (egoArray, egoTitles) = self.readFile(egoFileName, self.egoQuestionIds, missing) (alterArray, alterTitles) = self.readFile(alterFileName, self.alterQuestionIds, missing) V = egoArray V = numpy.r_[V, alterArray[alterIndices, :]] V = numpy.r_[V, egoArray[alterIndicesNR, :]] vList = VertexList(V.shape[0], V.shape[1]) vList.setVertices(V) graph = SparseGraph(vList, False) edgesR = numpy.c_[egoIndicesR, egoArray.shape[0]+numpy.arange(alterIndices.shape[0])] graph.addEdges(edgesR, decays) edgesNR = numpy.c_[egoIndicesNR, egoArray.shape[0]+alterIndices.shape[0]+numpy.arange(alterIndicesNR.shape[0])] graph.addEdges(edgesNR, numpy.ones(edgesNR.shape[0]) * defaultDecay) return graph
def cvModelSelection(self, graph, paramList, paramFunc, folds): """ ParamList is a list of lists of parameters and paramFunc is a list of the corresponding functions to call with the parameters as arguments. e.g. paramList = [[1, 2], [2, 1], [12, 1]] paramFunc = [predictor.setC, predictor.setD] """ inds = Sampling.crossValidation(folds, graph.getNumEdges()) errors = numpy.zeros(len(paramList)) allEdges = graph.getAllEdges() numTestExamples = 0 for i in range(len(paramList)): paramSet = paramList[i] logging.debug("Using paramSet=" + str(paramSet)) for j in range(len(paramSet)): paramFunc[j](paramSet[j]) for (trainInds, testInds) in inds: trainEdges = allEdges[trainInds, :] testEdges = allEdges[testInds, :] trainGraph = SparseGraph(graph.getVertexList()) trainGraph.addEdges(trainEdges) self.learnModel(trainGraph) P, S = self.predictEdges(testEdges[:, 0]) for k in range(testEdges.shape[0]): if not testEdges[k, 1] in P[k, :]: errors[i] += 1.0 numTestExamples += testEdges.shape[0] return errors / numTestExamples
Data: December, 2016 function: """ import numpy from apgl.graph.VertexList import VertexList from apgl.graph.SparseGraph import SparseGraph numVertex = 5 numFeature = 2 # vector labels of size 2 graph = SparseGraph(VertexList(numVertex, numFeature)) # Add some edges to the graph(method 1) # Vertices are indexed starting from 0 # graph[0, 1] = 0.1 # graph[1, 2] = 1 # Add some edges to the graph(method 2 is identity to method 1) edges = numpy.array([[0, 1], [1, 2]], numpy.int) edgeValues = numpy.array([0.1, 1]) graph.addEdges(edges, edgeValues) # Set the label of 0th vertex to [2, 3] graph.setVertex(0, numpy.array([2, 3])) # Displays edge weights print(graph[1, 2]) print(graph[1, 3])
class GraphMatchTest(unittest.TestCase): def setUp(self): numpy.set_printoptions(suppress=True, precision=3) numpy.random.seed(21) numpy.set_printoptions(threshold=numpy.nan, linewidth=100) #Use the example in the document self.numVertices = 10 self.numFeatures = 2 self.graph1 = SparseGraph(VertexList(self.numVertices, self.numFeatures)) self.graph1.setVertices(range(self.numVertices), numpy.random.rand(self.numVertices, self.numFeatures)) edges = numpy.array([[0,1], [0, 2], [0,4], [0,5], [0,8], [0,9]]) self.graph1.addEdges(edges) edges = numpy.array([[1,3], [1, 5], [1,6], [1,8], [2,9], [3,4], [3,5], [3,6], [3,7], [3,8], [3,9]]) self.graph1.addEdges(edges) edges = numpy.array([[4,2], [4, 7], [4,9], [5,8], [6, 7]]) self.graph1.addEdges(edges) self.graph2 = SparseGraph(VertexList(self.numVertices, self.numFeatures)) self.graph2.setVertices(range(self.numVertices), numpy.random.rand(self.numVertices, self.numFeatures)) edges = numpy.array([[0,3], [0, 4], [0,5], [0,8], [0,9], [1,2]]) self.graph2.addEdges(edges) edges = numpy.array([[1,3], [1,5], [1, 7], [1,8], [1,9], [2,3], [2,5], [3,5], [4,5], [4,6]]) self.graph2.addEdges(edges) edges = numpy.array([[4,9], [6, 8], [7,8], [7,9], [8, 9]]) self.graph2.addEdges(edges) 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 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 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 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))
""" Name: Generate Graph: Author: Jia_qiu Wang(王佳秋) Data: December, 2016 function: """ from apgl.graph.DictGraph import DictGraph from apgl.graph.SparseGraph import SparseGraph from apgl.graph.GeneralVertexList import GeneralVertexList graph = DictGraph() graph.addEdge("a", "b") graph.addEdge("a", "c") graph.addEdge("a", "d") edgeIndices = graph.getAllEdgeIndices() graph2 = SparseGraph(GeneralVertexList(graph.getNumVertices())) graph2.addEdges(edgeIndices)
# -*- coding: utf-8 -*- from apgl.graph.DictGraph import DictGraph from apgl.graph.SparseGraph import SparseGraph from apgl.graph.GeneralVertexList import GeneralVertexList graph = DictGraph() graph.addEdge("a", "b") graph.addEdge("a", "c") graph.addEdge("a", "d") edgeIndices = graph.getAllEdgeIndices() graph2 = SparseGraph(GeneralVertexList(graph.getNumVertices())) graph2.addEdges(edgeIndices)
#!/usr/bin/env python import numpy as np from apgl.graph.VertexList import VertexList from apgl.graph.SparseGraph import SparseGraph numVertices = 5 numFeatures = 2 graph = SparseGraph(VertexList(numVertices, numFeatures)) # Add some edges to the graph. # Vertices are indexed starting from 0. graph[0, 1] = 0.1 graph[1, 2] = 1.0 # Set the label of the 0th vertex to [2, 3]. graph.setVertex(0, np.array([2, 3])) # Display edge weights. print(graph[1, 2]) # 1.0 print(graph[1, 3]) # 0.0 (default) # Add some edges to the graph. edges = np.array([[0, 1], [1, 2]], np.int) edgeValues = np.array([0.1, 1.0]) graph.addEdges(edges, edgeValues) # Display the edge weight between v1 and v2. print(graph[1, 2])
class GraphMatchTest(unittest.TestCase): def setUp(self): numpy.set_printoptions(suppress=True, precision=3) numpy.random.seed(21) numpy.set_printoptions(threshold=numpy.nan, linewidth=100) #Use the example in the document self.numVertices = 10 self.numFeatures = 2 self.graph1 = SparseGraph( VertexList(self.numVertices, self.numFeatures)) self.graph1.setVertices( range(self.numVertices), numpy.random.rand(self.numVertices, self.numFeatures)) edges = numpy.array([[0, 1], [0, 2], [0, 4], [0, 5], [0, 8], [0, 9]]) self.graph1.addEdges(edges) edges = numpy.array([[1, 3], [1, 5], [1, 6], [1, 8], [2, 9], [3, 4], [3, 5], [3, 6], [3, 7], [3, 8], [3, 9]]) self.graph1.addEdges(edges) edges = numpy.array([[4, 2], [4, 7], [4, 9], [5, 8], [6, 7]]) self.graph1.addEdges(edges) self.graph2 = SparseGraph( VertexList(self.numVertices, self.numFeatures)) self.graph2.setVertices( range(self.numVertices), numpy.random.rand(self.numVertices, self.numFeatures)) edges = numpy.array([[0, 3], [0, 4], [0, 5], [0, 8], [0, 9], [1, 2]]) self.graph2.addEdges(edges) edges = numpy.array([[1, 3], [1, 5], [1, 7], [1, 8], [1, 9], [2, 3], [2, 5], [3, 5], [4, 5], [4, 6]]) self.graph2.addEdges(edges) edges = numpy.array([[4, 9], [6, 8], [7, 8], [7, 9], [8, 9]]) self.graph2.addEdges(edges) 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 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 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 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))
import numpy import matplotlib.pyplot as plt from apgl.data.Standardiser import Standardiser from apgl.data.FeatureGenerator import FeatureGenerator from apgl.graph.SparseGraph import SparseGraph from apgl.graph.GeneralVertexList import GeneralVertexList from sklearn.cluster import KMeans """ Test the error bound for the clustering process. """ k = 3 numVertices = 15 graph1 = SparseGraph(GeneralVertexList(numVertices)) cluster1 = numpy.array([[0,1], [0,2], [1,3], [2,3], [3,4], [4,5]]) graph1.addEdges(cluster1) cluster2 = numpy.array([[5,7], [5,8], [7,9], [8,9], [6,7]]) graph1.addEdges(cluster2) cluster3 = numpy.array([[6,10], [10,11], [10,12], [11,12], [11,13], [12,14]]) graph1.addEdges(cluster3) graph2 = SparseGraph(GeneralVertexList(numVertices)) cluster1 = numpy.array([[0,1], [0,2], [1,3], [2,3], [3,4], [0,3],[4,5]]) graph2.addEdges(cluster1) cluster2 = numpy.array([[5,7], [5,8], [7,9], [8,9], [6,7]]) graph2.addEdges(cluster2) cluster3 = numpy.array([[6,10], [10,11], [10,12], [11,12], [11,13], [12,14]]) graph2.addEdges(cluster3) L1 = graph1.normalisedLaplacianSym() L2 = graph2.normalisedLaplacianSym()