def testNativeAdjacencyMatrix(self):
        numVertices = 10
        graph = SparseGraph(GeneralVertexList(numVertices))

        graph.addEdge(1, 1, 0.1)
        graph.addEdge(1, 3, 0.5)
        graph.addEdge(2, 5, 1)
        graph.addEdge(7, 0, 2)

        A = graph.nativeAdjacencyMatrix()
        self.assertEquals(A[0, 7], 1)
        self.assertEquals(A[7, 0], 1)
        self.assertEquals(A[1, 3], 1)
        self.assertEquals(A[3, 1], 1)
        self.assertEquals(A[1, 1], 1)
        self.assertEquals(A[2, 5], 1)
        self.assertEquals(A[5, 2], 1)
        self.assertEquals(A.getnnz(), 7)

        graph = SparseGraph(GeneralVertexList(numVertices), False)
        graph.addEdge(1, 1, 0.1)
        graph.addEdge(1, 3, 0.5)
        graph.addEdge(2, 5, 1)

        A = graph.nativeAdjacencyMatrix()
        self.assertEquals(A[1, 3], 1)
        self.assertEquals(A[1, 1], 1)
        self.assertEquals(A[2, 5], 1)
        self.assertEquals(A.getnnz(), 3)
    def testGenerate2(self):
        """
        Make sure that the generated degree is less than or equal to the given degree
        
        """
        numVertices = 10

        for i in range(10):
            degSequence = numpy.random.randint(0, 3, numVertices)
            generator = ConfigModelGenerator(degSequence)
            graph = SparseGraph(GeneralVertexList(numVertices))
            graph = generator.generate(graph)

            self.assertTrue((graph.outDegreeSequence() <= degSequence).all())

        #We try to match an evolving degree sequence
        degSequence1 = numpy.array([0, 0, 1, 1, 1, 2, 2, 2, 3, 4])
        degSequence2 = numpy.array([2, 0, 3, 1, 2, 2, 2, 2, 3, 4])
        degSequence3 = numpy.array([2, 1, 4, 1, 2, 2, 2, 2, 3, 6])

        generator = ConfigModelGenerator(degSequence1)
        graph = SparseGraph(GeneralVertexList(numVertices))
        graph = generator.generate(graph)
        self.assertTrue((degSequence1 >= graph.outDegreeSequence()).all())

        deltaSequence = degSequence2 - graph.outDegreeSequence()
        generator = ConfigModelGenerator(deltaSequence)
        graph = generator.generate(graph, False)
        self.assertTrue((degSequence2 >= graph.outDegreeSequence()).all())

        deltaSequence = degSequence3 - graph.outDegreeSequence()
        generator = ConfigModelGenerator(deltaSequence)
        graph = generator.generate(graph, False)
        self.assertTrue((degSequence3 >= graph.outDegreeSequence()).all())
    def testConcat(self):
        numVertices = 5
        graph = SparseGraph(GeneralVertexList(numVertices))
        graph.addEdge(1, 1, 0.1)
        graph.addEdge(1, 3, 0.5)
        graph.addEdge(2, 4, 1)
        graph.addEdge(2, 3, 2)
        graph.setVertex(0, "abc")

        graph2 = SparseGraph(GeneralVertexList(numVertices))
        graph2.addEdge(1, 1)
        graph2.addEdge(1, 4)
        graph2.setVertex(1, "def")

        graph3 = graph.concat(graph2)

        self.assertTrue(graph3.getNumVertices, 10)
        self.assertEquals(graph3.getVertex(0), "abc")
        self.assertEquals(graph3.getVertex(6), "def")
        self.assertEquals(graph3.getEdge(1, 1), 0.1)
        self.assertEquals(graph3.getEdge(1, 3), 0.5)
        self.assertEquals(graph3.getEdge(2, 4), 1)
        self.assertEquals(graph3.getEdge(2, 3), 2)

        self.assertEquals(graph3.getEdge(6, 6), 1)
        self.assertEquals(graph3.getEdge(6, 9), 1)
    def concat(self, graph):
        """
        Take a new graph and concatenate it to the current one. Returns a new graph
        of the concatenated graphs with this graphs vertices first in the new list of
        vertices.

        :param graph: the input graph.
        :type graph: :class:`apgl.graph.SparseGraph`
        """
        Parameter.checkClass(graph, SparseGraph)
        if type(graph.getVertexList()) != type(self.getVertexList()):
            raise ValueError("Vertex lists must be of same type")
        if graph.isUndirected() != self.isUndirected():
            raise ValueError("Graphs must be of the same directed type")

        numVertices = self.getNumVertices() + graph.getNumVertices()
        vList = GeneralVertexList(numVertices)
        vList.setVertices(self.getVertexList().getVertices(),
                          list(range(self.getNumVertices())))
        vList.setVertices(graph.getVertexList().getVertices(),
                          list(range(self.getNumVertices(), numVertices)))
        newGraph = SparseGraph(vList)

        W = scipy.sparse.bmat([[self.W, None], [None, graph.W]], format="csr")
        newGraph.setWeightMatrixSparse(W)

        return newGraph
    def testAddVertices(self):
        vList = GeneralVertexList(10)
        vList.setVertex(1, 2)
        self.assertEquals(vList.getNumVertices(), 10)
        self.assertEquals(vList[1], 2)

        vList.addVertices(5)
        self.assertEquals(vList.getNumVertices(), 15)
        vList.setVertex(11, 2)
        self.assertEquals(vList[1], 2)
        self.assertEquals(vList[1], 2)
Example #6
0
    def fromNetworkXGraph(cls, networkXGraph):
        """
        Take a networkx Graph or DiGraph object, and return a subclass of AbstractMatrixGraph. Notice
        that networkx must be installed to use this function. The networkXGraph graph
        dict must have an attribute VListType which is the type of the VertexList used to
        construct the SparseGraph. Furthermore, only node attributes index by "label"
        are stored in the VertexList, and edge values are currently ignored.

        :returns: A networkx Graph or DiGraph object.
        """
        try:
            import networkx
        except ImportError:
            raise ImportError("toNetworkXGraph() requires networkx")

        if type(networkXGraph) == networkx.classes.graph.Graph:
            undirected = True
        elif type(networkXGraph) == networkx.classes.digraph.DiGraph:
            undirected = False
        else:
            raise ValueError("Unsupported NetworkX graph type")

        numVertices = networkXGraph.number_of_nodes()

        if "VListType" in networkXGraph.graph and networkXGraph.graph["VListType"] == VertexList:
            vList = networkXGraph.graph["VListType"](numVertices, networkXGraph.graph["numFeatures"])
        else:
            vList = GeneralVertexList(numVertices)

        graph = cls(vList, undirected)

        #Map from networkx nodes to an index
        nodeDict = {}

        #Set the vertices - note that vertex names are ignored
        for i in range(len(networkXGraph.nodes())):
            if "label" in networkXGraph.node[networkXGraph.nodes()[i]]:
                graph.setVertex(i, networkXGraph.node[networkXGraph.nodes()[i]]["label"])
            else:
                graph.setVertex(i, None)
            nodeDict[networkXGraph.nodes()[i]] = i

        #Set edges
        for i in range(len(networkXGraph.edges())):
            vertexIndex1 = nodeDict[networkXGraph.edges()[i][0]]
            vertexIndex2 = nodeDict[networkXGraph.edges()[i][1]]
            graph.addEdge(vertexIndex1, vertexIndex2)

        return graph
Example #7
0
    def __init__(self):
        numVertices = 1000
        graph = SparseGraph(GeneralVertexList(numVertices))

        p = 0.1
        generator = ErdosRenyiGenerator(p)
        graph = generator.generate(graph)

        subgraphIndicesList = []
        for i in range(100, numVertices, 10):
            subgraphIndicesList.append(range(i))

        k1 = 5
        k2 = 100

        self.graph = graph
        self.subgraphIndicesList = subgraphIndicesList
        self.clusterer = IterativeSpectralClustering(k1, k2, T=10, alg="IASC")
    def testKwayNormalisedCut(self):
        numVertices = 6
        graph = SparseGraph(GeneralVertexList(numVertices))

        graph.addEdge(0, 1)
        graph.addEdge(0, 2)
        graph.addEdge(2, 1)

        graph.addEdge(3, 4)
        graph.addEdge(3, 5)
        graph.addEdge(5, 4)

        W = graph.getWeightMatrix()
        clustering = numpy.array([0, 0, 0, 1, 1, 1])

        self.assertEquals(GraphUtils.kwayNormalisedCut(W, clustering), 0.0)

        #Try sparse W
        Ws = scipy.sparse.csr_matrix(W)
        self.assertEquals(GraphUtils.kwayNormalisedCut(Ws, clustering), 0.0)

        graph.addEdge(2, 3)
        W = graph.getWeightMatrix()
        self.assertEquals(GraphUtils.kwayNormalisedCut(W, clustering), 1.0 / 7)

        Ws = scipy.sparse.csr_matrix(W)
        self.assertEquals(GraphUtils.kwayNormalisedCut(Ws, clustering),
                          1.0 / 7)

        clustering = numpy.array([0, 0, 0, 1, 1, 2])
        self.assertEquals(GraphUtils.kwayNormalisedCut(W, clustering),
                          61.0 / 105)

        self.assertEquals(GraphUtils.kwayNormalisedCut(Ws, clustering),
                          61.0 / 105)

        #Test two vertices without any edges
        W = numpy.zeros((2, 2))
        clustering = numpy.array([0, 1])
        self.assertEquals(GraphUtils.kwayNormalisedCut(W, clustering), 0.0)

        Ws = scipy.sparse.csr_matrix(W)
        self.assertEquals(GraphUtils.kwayNormalisedCut(Ws, clustering), 0.0)
    def testSaveLoad(self):
        try:
            vList = GeneralVertexList(self.numVertices)
            vList.setVertex(0, "abc")
            vList.setVertex(1, 12)
            vList.setVertex(2, "num")

            tempDir = PathDefaults.getTempDir()
            fileName = tempDir + "vList"

            vList.save(fileName)

            vList2 = GeneralVertexList.load(fileName)

            for i in range(self.numVertices):
                self.assertEquals(vList.getVertex(i), vList2.getVertex(i))
        except IOError as e:
            logging.warn(e)
            pass
Example #10
0
    def clusterFromIterator(self, graphListIterator, timeIter=False):
        """
        Find a set of clusters for the graphs given by the iterator. 
        """
        clustersList = []
        timeList = [] 

        for subW in graphListIterator:
            logging.debug("Clustering graph of size " + str(subW.shape))
            #Create a SparseGraph
            startTime = time.time()
            graph = SparseGraph(GeneralVertexList(subW.shape[0]))
            graph.setWeightMatrixSparse(subW)
            iGraph = graph.toIGraph()

            vertexCluster = iGraph.community_leading_eigenvector(self.k)
            clustersList.append(vertexCluster.membership)
            timeList.append(time.time()-startTime)

        if timeIter:
            return clustersList, timeList
        else:
            return clustersList
    def testModularity(self):
        numVertices = 6
        graph = SparseGraph(GeneralVertexList(numVertices))

        graph.addEdge(0, 0)
        graph.addEdge(1, 1)
        graph.addEdge(2, 2)
        graph.addEdge(0, 1)
        graph.addEdge(0, 2)
        graph.addEdge(2, 1)

        graph.addEdge(3, 4, 2)
        graph.addEdge(3, 5, 2)
        graph.addEdge(4, 5, 2)
        graph.addEdge(3, 3, 2)
        graph.addEdge(4, 4, 2)
        graph.addEdge(5, 5, 2)

        W = graph.getWeightMatrix()
        clustering = numpy.array([0, 0, 0, 1, 1, 1])

        #This is the same as the igraph result
        Q = GraphUtils.modularity(W, clustering)
        self.assertEquals(Q, 4.0 / 9.0)

        Ws = scipy.sparse.csr_matrix(W)
        Q = GraphUtils.modularity(Ws, clustering)
        self.assertEquals(Q, 4.0 / 9.0)

        W = numpy.ones((numVertices, numVertices))
        Q = GraphUtils.modularity(W, clustering)

        self.assertEquals(Q, 0.0)

        Ws = scipy.sparse.csr_matrix(W)
        Q = GraphUtils.modularity(Ws, clustering)
        self.assertEquals(Q, 0.0)
Example #12
0
"""
Name: Generate Graph:
Author: Jia_qiu Wang(王佳秋)
Data: December, 2016
function:
"""

from apgl.graph.GeneralVertexList import GeneralVertexList
from apgl.graph.SparseGraph import SparseGraph

numVertices = 10
graph = SparseGraph(GeneralVertexList(numVertices))

graph[0, 1] = 1
graph[0, 2] = 1

P = graph.floydWarshall()
print("geodesicDistance:", graph.geodesicDistance(P=P))
print("harmonicGeodesicDistance:", graph.harmonicGeodesicDistance(P=P))

    def testGenerate(self):
        degSequence = numpy.array([2, 1, 3, 0, 0, 0, 0, 0, 0, 1])
        generator = ConfigModelGenerator(degSequence)

        numVertices = 10
        graph = SparseGraph(GeneralVertexList(numVertices))
        graph = generator.generate(graph)

        tol = 3
        self.assertTrue(
            numpy.linalg.norm(degSequence - graph.degreeSequence()) < tol)

        degSequence = numpy.array([2, 1, 3, 0, 2, 1, 4, 0, 0, 1])
        generator.setOutDegSequence(degSequence)
        graph.removeAllEdges()
        graph = generator.generate(graph)

        self.assertTrue(
            numpy.linalg.norm(degSequence - graph.degreeSequence()) < tol)

        #Test using a non-empty graph
        degSequence = numpy.array([0, 0, 0, 2, 0, 0, 0, 1, 1, 0])
        generator.setOutDegSequence(degSequence)
        oldDegSequence = graph.degreeSequence()

        self.assertRaises(ValueError, generator.generate, graph, True)
        graph = generator.generate(graph, False)

        diffSequence = graph.degreeSequence() - oldDegSequence
        self.assertTrue(numpy.linalg.norm(degSequence - diffSequence) < tol)

        #Test the case where we also have an in-degree sequence
        degSequence = numpy.array([2, 1, 3, 0, 0, 0, 0, 0, 0, 1])
        inDegSequence = numpy.array([1, 1, 1, 1, 1, 1, 1, 0, 0, 0])
        generator = ConfigModelGenerator(degSequence, inDegSequence)

        graph = SparseGraph(GeneralVertexList(numVertices))
        self.assertRaises(ValueError, generator.generate, graph)

        graph = SparseGraph(GeneralVertexList(numVertices), False)
        graph = generator.generate(graph)

        self.assertTrue(
            numpy.linalg.norm(degSequence - graph.outDegreeSequence()) < tol)
        self.assertTrue(
            numpy.linalg.norm(inDegSequence - graph.inDegreeSequence()) < tol)

        outDegSequence = numpy.array([2, 1, 3, 0, 2, 1, 4, 0, 0, 1])
        inDegSequence = numpy.array([1, 2, 1, 1, 2, 1, 2, 1, 2, 1])
        generator.setOutDegSequence(outDegSequence)
        generator.setInDegSequence(inDegSequence)
        graph.removeAllEdges()
        graph = generator.generate(graph)

        self.assertTrue(
            numpy.linalg.norm(outDegSequence -
                              graph.outDegreeSequence()) < tol)
        self.assertTrue(
            numpy.linalg.norm(inDegSequence - graph.inDegreeSequence()) < tol)

        #In the case that the in-degree sequence sum larger than that of the out-degree it is
        #not satisfied, but the out-degree should be.
        inDegSequence = numpy.array([1, 2, 1, 1, 2, 1, 2, 1, 5, 6])
        generator.setInDegSequence(inDegSequence)
        graph.removeAllEdges()
        graph = generator.generate(graph)
        self.assertTrue(
            numpy.linalg.norm(outDegSequence -
                              graph.outDegreeSequence()) < tol)

        #Now try the other way around
        generator.setOutDegSequence(inDegSequence)
        generator.setInDegSequence(outDegSequence)
        graph.removeAllEdges()
        graph = generator.generate(graph)
        self.assertTrue(
            numpy.linalg.norm(outDegSequence - graph.inDegreeSequence()) < tol)

        #Test growing graph
        outDegSequence = numpy.array([2, 1, 3, 0, 2, 1, 4, 0, 0, 1])
        inDegSequence = numpy.array([1, 2, 1, 1, 2, 1, 2, 1, 2, 1])

        generator.setOutDegSequence(outDegSequence)
        generator.setInDegSequence(inDegSequence)
        graph.removeAllEdges()
        graph = generator.generate(graph)

        newOutDegreeSequence = numpy.array([2, 1, 3, 5, 2, 1, 4, 0, 0, 1])
        newInDegreeSequence = numpy.array([2, 3, 2, 2, 3, 1, 2, 1, 2, 1])
        diffOutSequence = newOutDegreeSequence - graph.outDegreeSequence()
        diffInSequence = newInDegreeSequence - graph.inDegreeSequence()
        generator.setOutDegSequence(diffOutSequence)
        generator.setInDegSequence(diffInSequence)
        graph = generator.generate(graph, False)

        self.assertTrue(
            numpy.linalg.norm(newOutDegreeSequence -
                              graph.outDegreeSequence()) < tol)
        self.assertTrue(
            numpy.linalg.norm(newInDegreeSequence -
                              graph.inDegreeSequence()) < tol)
 def setUp(self):
     self.VListType = GeneralVertexList
     self.numVertices = 10
     self.vList = GeneralVertexList(self.numVertices)
     self.emptyVertex = None
     self.initialise()
"""
Name: Generate Graph:
Author: Jia_qiu Wang(王佳秋)
Data: December, 2016
function:
"""

import numpy
import scipy.sparse as sps
from apgl.graph.GeneralVertexList import GeneralVertexList
from apgl.graph.SparseGraph import SparseGraph

numVertices = 10
vList = GeneralVertexList(numVertices)
wght = sps.csc_matrix(numVertices, numVertices)
graph = SparseGraph(vList, W=wght, undirected=False)

graph[0, 1] = 1
graph[0, 2] = 1
graph.setVertex(0, "abc")
graph.setVertex(1, 123)

print(graph)
Example #16
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)

"""
Name: Generate Graph:
Author: Jia_qiu Wang(王佳秋)
Data: December, 2016
function:
"""

from apgl.graph.DenseGraph import DenseGraph
from apgl.graph.GeneralVertexList import GeneralVertexList
from apgl.generator.ErdosRenyiGenerator import *

numVertices = 20
graph = DenseGraph(GeneralVertexList(numVertices))
p = 0.2
generator = ErdosRenyiGenerator(p)
graph = generator.generate(graph)


    def __init__(self,
                 vertices,
                 undirected=True,
                 W=None,
                 dtype=numpy.float,
                 frmt="csr"):
        """
        Create a SparseGraph with a given AbstractVertexList or number of 
        vertices, and specify whether it is directed. One can optionally pass 
        in a sparse matrix W which is used as the weight matrix of the 
        graph. Different kinds of sparse matrix can impact the speed of various
        operations. The currently supported sparse matrix types are: lil_matrix, 
        csr_matrix, csc_matrix and dok_matrix. The default sparse matrix is 
        csr_matrix. 

        :param vertices: the initial set of vertices as a AbstractVertexList object, or an int to specify the number of vertices in which case vertices are stored in a GeneralVertexList.  
        
        :param undirected: a boolean variable to indicate if the graph is undirected.
        :type undirected: :class:`boolean`

        :param W: a square sparse matrix of the same size as the number of vertices, or None to create the default one.
        
        :param dtype: the data type of the sparse matrix if W is not specified. 
        
        :param frmt: the format of the sparse matrix: lil, csr or csc if W is not specified 
        """
        Parameter.checkBoolean(undirected)

        if isinstance(vertices, AbstractVertexList):
            self.vList = vertices
        elif isinstance(vertices, int):
            self.vList = GeneralVertexList(vertices)
        else:
            raise ValueError("Invalid vList parameter: " + str(vertices))

        if W != None and not (sparse.issparse(W) and W.shape == (
                self.vList.getNumVertices(), self.vList.getNumVertices())):
            raise ValueError(
                "Input argument W must be None or sparse matrix of size " +
                str(self.vList.getNumVertices()))

        self.undirected = undirected

        if frmt == "lil":
            matrix = sparse.lil_matrix
        elif frmt == "csr":
            matrix = sparse.csr_matrix
        elif frmt == "csc":
            matrix = sparse.csc_matrix
        else:
            raise ValueError("Invalid sparse matrix format: " + frmt)

        #Terrible hack alert:  can't create a zero size sparse matrix, so we settle
        #for one of size 1. Better is to create a new class.
        if self.vList.getNumVertices() == 0 and W == None:
            self.W = matrix((1, 1), dtype=dtype)
        elif W == None:
            self.W = matrix(
                (self.vList.getNumVertices(), self.vList.getNumVertices()),
                dtype=dtype)
        else:
            self.W = W
            #The next line is for error checking mainly
            self.setWeightMatrix(W)