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
예제 #3
0
    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
예제 #4
0
    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])

예제 #6
0
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))  
예제 #7
0
"""
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)

예제 #8
0
# -*- 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)
예제 #9
0
#!/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])
예제 #10
0
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))
예제 #11
0
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()