Beispiel #1
0
 def getTreeAsNet(self,thinning=True):
     if thinning:
         newNet=pynet.SymmNet()
         for edge in self.net.edges:
             newNet[edge[0],edge[1]]=1#edge[2]
         for node in self.net:
             if newNet[node].deg()==2:
                 l=list(newNet[node])
                 n1=self._getNodeByName(l[0])
                 n2=self._getNodeByName(l[1])
                 me=self._getNodeByName(node)
                 if n1[0]<me[0]:
                     parent=n1
                     child=n2
                 else:
                     parent=n2
                     child=n1
                 if newNet[self._getNameByNode(parent)].deg()==2:
                     newNet[node,l[0]]=0
                     newNet[node,l[1]]=0
                     newNet[self._getNameByNode(parent),self._getNameByNode(child)]=1
         deletedNodes=[]
         for node in newNet:
             if newNet[node].deg()==0:
                 deletedNodes.append(node)
         for node in deletedNodes:
             del newNet[node]
         return newNet
     else:
         return self.net
Beispiel #2
0
def dist_to_weights(net, epsilon=0.001):
    '''Transforms a distance matrix / network to a weight
    matrix / network using the formula W = 1 - D / max(D).
    Returns a matrix/network'''

    N = len(net._nodes)

    if (isinstance(net, pynet.SymmFullNet)):
        newmat = pynet.SymmFullNet(N)
    else:
        newmat = pynet.SymmNet()

    edges = list(net.edges)

    maxd = 0.0
    for edge in edges:
        if edge[2] > maxd:
            maxd = edge[2]

    # epsilon trick; lowest weight will be almost but
    # not entirely zero

    maxd = maxd + epsilon

    for edge in edges:
        if not (edge[2] == maxd):
            newmat[edge[0]][edge[1]] = 1 - edge[2] / maxd

    netext.copyNodeProperties(net, newmat)

    return newmat
Beispiel #3
0
    def __iter__(self):
        if self.buildNet:
            if self.symmetricNet:
                net = pynet.SymmNet()
            else:
                net = pynet.Net()

        if self.nodes == None:
            ktree = Ktree()
        else:
            ktree = Ktree(size=len(self.nodes), nodeNames=self.nodes)

        for edge in self.edges:
            if isinstance(edge, EvaluationEvent):
                if self.returnKtree:
                    ktree.threshold = edge.threshold
                    ktree.addedEdges = edge.addedElements
                    yield ktree
                else:
                    cs = ktree.getCommStruct()
                    cs.threshold = edge.threshold
                    cs.addedEdges = edge.addedElements
                    if self.buildNet:
                        cs.net = net
                    yield cs
            else:
                ktree.addEdge(edge)
                if self.buildNet:
                    net[edge[0], edge[1]] = edge[2]
Beispiel #4
0
    def __init__(self,cslist):
        cslist.reverse()
        self.tree=[]
        self.cslist=cslist
        self.tree.append([])

        self.net=pynet.SymmNet()
        #self.multiplier=10**ceil(np.log10(len(cslist)))
        
        #add roots:
        for c in cslist[0]:
            self.tree[0].append(None)

        #go through each level and add links:
        for thisLevel in range(1,len(cslist)):
            self.tree.append([])
            for communityIndex in range(0,len(cslist[thisLevel])):
               self.tree[thisLevel].append(None)
               for fatherIndex in range(0,len(cslist[thisLevel-1])):
                    if cslist[thisLevel][communityIndex]<=cslist[thisLevel-1][fatherIndex]:
                        bestFatherIndex=fatherIndex #there might be multiple candidates for father, choose the smallest one
               self.tree[thisLevel][communityIndex]=bestFatherIndex                        
               self.net[self._getNameByNode((thisLevel,communityIndex)),self._getNameByNode((thisLevel-1,bestFatherIndex))]=len(cslist)+1-thisLevel

        cslist.reverse()
Beispiel #5
0
    def _getOverlapNetwork(self, other):
        """Create a bipartite network from overlapping nodes.

        Nodes correspond to communities and edge weight is the number
        of common nodes between the two communities. Nodes [0
        ... len(self)-1] correspond to communities in self, and nodes
        [len(self) ... len(self)+len(other)] correspond to
        communities in `other`.
        """

        # Find out the number of nodes.
        N = max(self.N_nodes, other.N_nodes)

        # Construct community ID dictionaries.
        cID_A = self.getCommIDs()
        cID_B = other.getCommIDs()

        # Construct the bipartite community net.
        Nc_A = len(self.comm)
        commNet = pynet.SymmNet()
        for node in xrange(N):
            try:
                for cj in cID_B[node]:
                    cj += Nc_A
                    for ci in cID_A[node]:
                        commNet[ci, cj] += 1
            except AttributeError:
                # `node` does not occur in one of the node
                # covers. Skip this node.
                continue

        return commNet
Beispiel #6
0
    def getCommunityNetwork(self, net):
        """
        Builds a network where each node is a node set in this node cover, and
        there is an edge between two nodes if there is an edge in the network
        given as a parameter between two nodes in the two node sets. 
        The weight of each edge is the sum of weights of such edges.

        Todo: tests
        """
        newNet = pynet.SymmNet()
        commID = self.getCommIDs()

        #First add the nodes
        for node in range(len(self)):  #communities are named from 0 to n-1
            newNet.addNode(node)

        #Then add the edges by going through the edges in the underlying net
        for edge in net.edges:
            if edge[0] in commID and edge[
                    1] in commID:  #node might not belong to a community
                for newNode1 in commID[edge[0]]:
                    for newNode2 in commID[edge[1]]:
                        if newNode1 != newNode2:  #no self-edges
                            newNet[newNode1, newNode2] += edge[2]
        return newNet
Beispiel #7
0
def getBetweennessCentrality(net, edgeBC=False):
    """
    Returns a map from each node to its unweighted betweenness centrality.

    Note: this function needs some more testing.
    """
    #Implementation of the algorithm found in this paper:
    #www.inf.uni-konstanz.de/algo/publications/b-fabc-01.pdf
    cb = {}
    for node in net:
        cb[node] = 0
    if edgeBC:
        bcNet = pynet.SymmNet()

    for node in net:
        st = []
        p = {}
        sigma = {}
        d = {}
        delta = {}
        for t in net:
            p[t] = []
            sigma[t] = 0
            d[t] = -1
            delta[t] = 0
        sigma[node] = 1
        d[node] = 0
        q = [node]
        while len(q) > 0:
            v = q.pop(0)
            st.append(v)
            for w in net[v]:
                if d[w] < 0:
                    q.append(w)
                    d[w] = d[v] + 1
                if d[w] == d[v] + 1:
                    sigma[w] += sigma[v]
                    p[w].append(v)
        while len(st) > 0:
            w = st.pop()
            for v in p[w]:
                partialDelta = float(sigma[v]) / float(
                    sigma[w]) * (1 + delta[w])
                delta[v] += partialDelta
                if edgeBC:
                    bcNet[v, w] = bcNet[v, w] + partialDelta
            if w != node:
                cb[w] += delta[w]

    for node in cb:
        cb[node] = cb[node] / 2.0

    if edgeBC:
        for e in bcNet.edges:
            bcNet[e[0], e[1]] = e[2] / 2.0
        return cb, bcNet
    else:
        return cb
Beispiel #8
0
def kcliquesByEdges(edges, k):
    """Generate k-cliques from edges.

    Generator function that generates a list of cliques of size k in
    the order they are formed when edges are added in the order
    defined by the `edges` argument.  If many cliques are formed by
    adding one edge, the order of the cliques is arbitrary.
    
    This generator will pass through any EvaluationEvent objects that
    are passed to it in the `edges`.

    Parameters
    ----------
    edges : iterable with elements (node_1, node_2, weight)
        The edges that form the network. `edges` may also contain
        EvaluationEvent objects, which are simply passed through.
    k : int, >= 3
        The function returns `k`-cliques, that is, induced full subnets
        of `k` nodes.

    Yield
    -----
    kclique : KClique object
        When a new k-clique is formed, it is returned as a KClique
        object.

    Notes
    -----
    If an edge is included in `edges` multiple times, all k-cliques in
    the network constructed so far will be returned every time. Most
    of the time this is not what is wanted, so take care not the
    supply multiple edges. (LK 31.7.2009)
    """
    newNet = pynet.SymmNet()  # Edges are added to an empty network one by one
    for edge in edges:
        if isinstance(edge, EvaluationEvent):
            yield edge
        else:
            # First we find all new triangles that are born when the new edge is added
            triangleEnds = set(
            )  # We keep track of the tip nodes of the new triangles
            for adjacentNode in newNet[
                    edge[0]]:  # Neighbor of one node of the edge ...
                if newNet[adjacentNode, edge[
                        1]] != 0:  #...is a neighbor of the other node of the edge...
                    triangleEnds.add(
                        adjacentNode
                    )  #...then the neighbor is a tip of a new triangle

            # New k-cliques are now (k-2)-cliques at the triangle end points plus
            # the two nodes at the tips of the edge we are adding to the network
            for kclique in kcliquesAtSubnet(triangleEnds, newNet, k - 2):
                yield kclique + KClique([edge[0], edge[1]])

            # Finally we add the new edge to the network.
            newNet[edge[0], edge[1]] = edge[2]
Beispiel #9
0
def makeER(n, p):
    """
    Make a realisation of Erdos-Renyi network
    * fast for non-sparse networks
    * the sparce version should be implemented
    """
    net = pynet.SymmNet()
    for i in range(0, n):
        for j in range(0, i):
            if p > np.random.ranf():
                net[i, j] = 1
    return net
Beispiel #10
0
def linearLattice(n, r):
    """Linear lattice with periodic boundary conditions. Two nodes are connected
    if they are at most r steps away from each other in the lattice.
    """
    net = pynet.SymmNet()
    if r >= n:
        r = n - 1
    for i in range(n):
        for ri in range(r):
            net[i, (i + ri + 1) % n] = 1
            net[i, (i - 1 - ri) % n] = 1
    return net
Beispiel #11
0
def getKRCliqueNet(net, k):
    """
    Returns a network of (k-1)-cliques, which are subcliques of some k-clique in the
    network given as a parameter.
    Two (k-1)-cliques are adjacent if they are subcliques of the same k-clique.
    """
    krnet = pynet.SymmNet()
    for kclique in kcliquesByEdges(net.edges, k):
        krcliques = list(kclique.getSubcliques())
        for krclique in krcliques:
            for krclique2 in krcliques:
                krnet[krclique][krclique2] = 1
    return krnet
Beispiel #12
0
def collapseBipartiteNet(net, nodesToRemove):
    """
    Returns an unipartite projection of a bipartite network.
    """
    newNet = pynet.SymmNet()
    for node in nodesToRemove:
        degree = float(net[node].deg())
        for node1 in net[node]:
            for node2 in net[node]:
                if node1.__hash__() > node2.__hash__():
                    newNet[node1, node2] = newNet[node1, node2] + 1.0 / degree

    netext.copyNodeProperties(net, newNet)
    return newNet
Beispiel #13
0
def sumNets(nets):
    """Aggregates networks defined in nets (list of SymmNets)
    by summing up edge weights between nodes in all nets"""

    newNet = pynet.SymmNet()

    for currnet in nets:

        curr_edges = list(currnet.edges)

        for edge in curr_edges:

            newNet[edge[0], edge[1]] += edge[2]

    return newNet
Beispiel #14
0
    def _getOverlapNetwork(self, other):
        """Create a bipartite network from overlapping nodes.

        In the overlap network the nodes correspond to communities and
        edge weight is the number of common nodes between two
        communities. Nodes [0 ... len(self)-1] correspond to
        communities in self, and nodes [len(self)
        ... len(self)+len(otherCover)] correspond to communities in
        `other`.
        """
        commNet = pynet.SymmNet()
        for node in self._commIDs:
            ci = self._commIDs[node]
            cj = len(self) + other._commIDs[node]
            commNet[ci, cj] += 1
        return commNet
Beispiel #15
0
def mst_kruskal(net, randomize=True, maximum=False):
    """Find a minimum/maximum spanning tree using Kruskal's algorithm

    If random is set to true and the mst is not unique, a random
    mst is chosen.

    >>> t=pynet.SymmNet()
    >>> t[1,2]=1
    >>> t[2,3]=2
    >>> t[3,1]=3
    >>> m=mst_kruskal(t)
    >>> print m.edges
    [[1, 2, 1], [2, 3, 2]]

    
    """

    edges = list(net.edges)
    if randomize:
        random.shuffle(
            edges)  #the sort has been stable since python version 2.3
    edges.sort(lambda x, y: cmp(x[2], y[2]), reverse=maximum)
    mst = pynet.SymmNet()
    numberOfNodes = len(net)
    #ktree=percolator.Ktree(numberOfNodes)
    ktree = percolator.Ktree()  #just use dict
    addedEdges = 0

    for edge in edges:
        if ktree.getParent(edge[0]) != ktree.getParent(edge[1]):
            mst[edge[0], edge[1]] = edge[2]
            ktree.setParent(edge[0], edge[1])
            addedEdges += 1

        if addedEdges == numberOfNodes - 1:

            #the mst is a tree

            netext.copyNodeProperties(net, mst)

            return mst

    # else it is a forest

    netext.copyNodeProperties(net, mst)

    return mst
Beispiel #16
0
def getKCliqueBipartiteNet(net, k):
    """
    Returns a bipartite network where to partitions are k-cliques and 
    (k-1)-cliques in the net that is given as a parameter. There is a link
    between a k-clique and (k-1)-clique if the (k-1)-clique is a subclique of 
    the k-clique.
    """

    kcliques = set()
    krcliques = set()
    kbinet = pynet.SymmNet()
    for kclique in kcliquesByEdges(net.edges, k):
        kcliques.add(kclique)
        for krclique in kclique.getSubcliques():
            krcliques.add(krclique)
            kbinet[kclique, krclique] = 1
    return kbinet, kcliques, krcliques
Beispiel #17
0
def local_threshold_by_value(net, threshold):
    '''Generates a new network by thresholding the input network.
       Inputs: net = network, threshold = threshold value,
       mode = 0 (accept weights < threshold), 1 (accept weights > threshold)
       Returns a network. Note! threshold is really alpha which is defined in
       "Extracting the multiscale backbone of complex weighted networks"
       http://www.pnas.org/content/106/16/6483.full.pdf'''

    newnet = pynet.SymmNet()
    for node in net:
        s = net[node].strength()
        k = net[node].deg()
        for neigh in net[node]:
            w = net[node, neigh]
            if (1 - w / s)**(k - 1) < threshold:
                newnet[node, neigh] = w
    netext.copyNodeProperties(net, newnet)

    return newnet
Beispiel #18
0
def threshold_by_value(net, threshold, accept="<", keepIsolatedNodes=False):
    '''Generates a new network by thresholding the input network. 
       If using option keepIsolatedNodes=True, all nodes in the
       original network will be included in the thresholded network;
       otherwise only those nodes which have links will remain (this
       is the default). 
    
       Inputs: net = network, threshold = threshold value,
       accept = "foobar": accept weights foobar threshold (e.g accept = "<": accept weights < threshold)
       Returns a network.'''

    newnet = pynet.SymmNet()
    edges = list(net.edges)
    if accept == "<":
        for edge in edges:
            if (edge[2] < threshold):
                newnet[edge[0], edge[1]] = edge[2]
    elif accept == ">":
        for edge in edges:
            if (edge[2] > threshold):
                newnet[edge[0], edge[1]] = edge[2]
    elif accept == ">=":
        for edge in edges:
            if (edge[2] >= threshold):
                newnet[edge[0], edge[1]] = edge[2]
    elif accept == "<=":
        for edge in edges:
            if (edge[2] <= threshold):
                newnet[edge[0], edge[1]] = edge[2]
    else:
        raise Exception(
            "Parameter 'accept' must be either '<', '>', '<=' or '>='.")

    # Add isolated nodes to the network.
    if keepIsolatedNodes == True:
        for node in net:
            if not newnet.__contains__(node):
                newnet.addNode(node)

    netext.copyNodeProperties(net, newnet)

    return newnet
Beispiel #19
0
def loadNet_gml(input):
    """
    Reads a networks data from input in gml format.

    Note: This is not a complete gml-parser, because gml format can
    hold almost anykind of data. Instead this parser tries to find
    edges of one graph from the given input. Use at you own risk with
    complicated gml-files.
    """

    source = None
    target = None
    value = None
    for line in input:
        line = line.strip()
        if line.startswith("directed"):
            if line[9:10] == "0":
                net = pynet.SymmNet()
            elif line[9:10] == "1":
                net = pynet.Net()
        elif line.startswith("source"):
            source = line.split()[1]
        elif line.startswith("target"):
            target = line.split()[1]
        elif line.startswith("value"):
            value = line.split()[1]
        elif line.startswith("edge"):
            if source != None and target != None:
                if value != None:
                    net[source][target] = float(value)
                else:
                    net[source][target] = 1
                source = None
                target = None
                value = None
    if source != None and target != None:
        if value != None:
            net[source][target] = float(value)
        else:
            net[source][target] = 1

    return net
Beispiel #20
0
def makeSparseER(n, p):
    """
    Make a realisation of Erdos-Renyi network
    * fast for sparse networks
    * 0 < p < 1
    * Algorithm: 
    Efficient generation of large random networks
    Phys. Rev. E 71, 036113 (2005) 
    """

    net = pynet.SymmNet()
    v = 1
    w = -1
    while (v < n):
        r = np.random.ranf()
        w = w + 1 + int(np.floor(np.log(1 - r) / np.log(1 - p)))
        while ((w >= v) and (v < n)):
            w = w - v
            v = v + 1
        if (v < n):
            net[v, w] = 1

    return net
Beispiel #21
0
def girvanNewman(communitySize, numberOfCommunities, kIn, kOut):
    """
    A network model producing equally sized communities with equal expected 
    link density inside the communities and between the communities. The model
    was first defined in the article:
    M. Girvan and M.E.J. Newman: Community structure in social and biological networks,
    PNAS 99, 7821 (2002)

    Parameters
    ----------
    communitySize : int 
      Size of a single community in nodes.
    numberOfCommunities : int
      Number of communities
    kIn : int
      Expected value for inside community node degrees. That is, the expected
      number of links from each node going to other nodes in the same community. This
      parameter is used to calculate the probability of links inside communities. If
      kIn > communitySize-1, then kIn is set to communitySize-1.
    kOut : int
      Expected value for outside community node degrees. That is, the expected
      number of links from each node going to nodes in other communities. This
      parameter is used to calculate the probability of links between communities. If
      kOut > (numberOfCommunities-1)*communitySize, then kOut is set to (numberOfCommunities-1)*communitySize.

    Return
    ------
    net : SymmNet 
      A realisation of the model network.
      
    Complexity
    ----------
    For a network with N nodes:
    Time complexity: O(N**2)
    Memory complexity: Memory used by the returned network object. 

    Time complexity can be improved for sparse networks.

    """

    #Calculate pIn and pOut from kIn and kOut
    if (communitySize - 1) < kIn:
        kIn = communitySize - 1
    if (numberOfCommunities - 1) * communitySize < kOut:
        kOut = (numberOfCommunities - 1) * communitySize
    pIn = float(kIn) / float(communitySize - 1)
    if numberOfCommunities > 1:
        pOut = float(kOut) / float((numberOfCommunities - 1) * communitySize)
    else:
        pOut = 0.0

    net = pynet.SymmNet()  #the net object to be returned

    #First, put the internal edges:
    for communityIndex in range(numberOfCommunities):
        for node1Index in range(communitySize):
            for node2Index in range(node1Index + 1, communitySize):
                if pIn > np.random.ranf():
                    net[communityIndex * communitySize + node1Index,
                        communityIndex * communitySize + node2Index] = 1

    #Second, put the external edges:
    for community1Index in range(numberOfCommunities):
        for community2Index in range(community1Index + 1, numberOfCommunities):
            for node1Index in range(communitySize):
                for node2Index in range(communitySize):
                    if pOut > np.random.ranf():
                        net[community1Index * communitySize + node1Index,
                            community2Index * communitySize + node2Index] = 1

    return net
Beispiel #22
0
def loadNet_edg(input,
                mutualEdges=False,
                splitterChar=None,
                symmetricNet=True,
                numerical=None,
                allowSelfEdges=True,
                hasHeaderLine=False):
    """Read network data from input in edg format.

    If `mutualEdges` is set to True, an edge is added between nodes i
    and j only if both edges (i,j) and (j,i) are listed. The weight of
    the edge is the sum of the weights of the original edges.

    If the same edge is encountered multiple times, the edge weight
    will be the sum of all weights.

    If 'allowSelfEdges', the self edges are translated as nodes with
    no edges. Otherwise those edges are just thrown out.

    If hasHeaderLine is True the first line is skipped, if it is False
    the first line is read normally, and if it is None the first line
    is skanned for "from to weight" string to decide if it is a header
    line.
    """
    def isNumerical(input):
        try:
            for line in input:
                int(line.split(splitterChar)[0])
                int(line.split(splitterChar)[1])
        except ValueError:
            input.seek(0)
            return False
        input.seek(0)
        return True

    if numerical is None:
        numerical = isNumerical(input)

    if symmetricNet:
        newNet = pynet.SymmNet()
    else:
        newNet = pynet.Net()

    #Check for headers
    possibleHeaders = [["from", "to", "weight"], ["head", "tail", "weight"]]
    if hasHeaderLine != False:
        firstLine = input.readline().strip().lower()
        fields = firstLine.split(splitterChar)
        if hasHeaderLine == None and fields not in possibleHeaders:
            input.seek(0)
        if hasHeaderLine == True:
            input.seek(0)

    nodeMap = {}  # Used only if mutualEdges = True.

    for line in input:
        fields = line.split(splitterChar)
        if len(fields) > 1:
            if len(fields) == 2:  #if weight is missing:
                fields[1] = fields[1].strip(
                    '\n')  #strip the endline from the node name
                fields.append(1)  #add one as the weight
            if fields[0] != fields[1] or allowSelfEdges:
                if numerical:
                    fields[0] = int(fields[0])
                    fields[1] = int(fields[1])
                if fields[0] != fields[1]:
                    if mutualEdges:
                        if nodeMap.has_key((fields[1], fields[0])):
                            newNet[fields[0]][fields[1]] += nodeMap[(
                                fields[1], fields[0])]
                            newNet[fields[0]][fields[1]] += float(fields[2])
                            nodeMap[(fields[1], fields[0])] = 0
                            nodeMap[(fields[0], fields[1])] = 0
                        else:
                            nodeMap[(fields[0], fields[1])] = nodeMap.get(
                                (fields[0], fields[1]), 0) + float(fields[2])
                    else:
                        newNet[fields[0]][fields[1]] += float(fields[2])
                else:
                    newNet.addNode(fields[0])

    return newNet
Beispiel #23
0
def fullNet(nodes,weight=1):    
    net=pynet.SymmNet()
    for node1 in nodes:
        for node2 in nodes:
            net[node1,node2]=weight
    return net
Beispiel #24
0
def netConfiguration(net, keepsOrigNet=False, seed=None):
    """Generate configuration network
    
    This function generates a configuration network from any arbitrary
    net. It retains the degree of each node but randomize the edges
    between them.
		
    Parameters
    ----------
    net : pynet.SymmNet object
        The network to be used as the basis for the configuration
        model.
    keepsOrigNet : bool (default: False)
        If False, the input network, `net`, will be overwritten by the
        configuration network.
    seed : int (default: None)
        A seed for the random number generator. If None, the RNG is
        not be re-initialized but the current state is used.

    Return
    ------
    configuration_net : pynet.SymmNet object
        The shuffled network. Note that if `keepsOrigNet` is False,
        the returned value will be identical to `net`.
    """
    if seed is not None:
        random.seed(int(seed))

    newNet = pynet.SymmNet()
    if keepsOrigNet:
        testNet = pynet.SymmNet()
        for edge in net.edges:
            testNet[edge[0], edge[1]] = edge[2]
    else:
        testNet = net

    edgeList = list(net.edges)

    for i in range(len(edgeList)):

        j = i
        while j == i:
            j = random.randint(0, len(edgeList) - 1)

        if ((edgeList[i][1] == edgeList[j][0])
                or (edgeList[j][1] == edgeList[i][0])):
            continue
        if ((edgeList[i][1] == edgeList[j][0])
                and (edgeList[j][1] == edgeList[i][0])):
            continue
        if ((edgeList[i][0] == edgeList[j][0])
                or (edgeList[i][1] == edgeList[j][1])):
            continue
        if ((newNet[edgeList[i][0], edgeList[j][1]] > 0.0)
                or (newNet[edgeList[j][0], edgeList[i][1]] > 0.0)):
            continue
        if ((testNet[edgeList[i][0], edgeList[j][1]] > 0.0)
                or (testNet[edgeList[j][0], edgeList[i][1]] > 0.0)):
            continue

        edgeList[i][1] += edgeList[j][1]
        edgeList[j][1] = edgeList[i][1] - edgeList[j][1]
        edgeList[i][1] = edgeList[i][1] - edgeList[j][1]

        newNet[edgeList[i][0], edgeList[j][1]] = 0.0
        newNet[edgeList[j][0], edgeList[i][1]] = 0.0

        testNet[edgeList[i][0], edgeList[j][1]] = 0.0
        testNet[edgeList[j][0], edgeList[i][1]] = 0.0

        newNet[edgeList[i][0], edgeList[i][1]] = 1.0
        newNet[edgeList[j][0], edgeList[j][1]] = 1.0
        testNet[edgeList[i][0], edgeList[i][1]] = 1.0
        testNet[edgeList[j][0], edgeList[j][1]] = 1.0

    return newNet
Beispiel #25
0
def getLineGraph(net, useWeights=False, output=None, format='edg'):
    """Return a line graph constructed from `net`.

    The nodes in the line graph correspond to edges in the original
    graph, and there is an edge between two nodes if they have a
    common incident node in the original graph. 

    If weights are not used (`useWeights = False`), the resulting
    network will be undirected and the weight of each new edge will be
    1/(k_i-1), where k_i is the degree of the common node in `net`.

    If weights are used (`useWeights = True`), the resulting network
    will be directed and the weight of edge (e_ij, e_jk) will be
    w_jk/sum_{x != i} w_jx, where the indices i, j and k refer to
    nodes in `net`.

    Parameters
    ----------
    net : pynet.SymmNet object
        The original graph that is used for constructing the line
        graph.
    useWeights : boolean
        If True, the edge weights will be used when constructing the
        line graph.
    output : file object
        If given, the edges will be written to output in edg-format
        instead of returning a pynet.Net() or pynet.SymmNet() object.
    format : str, 'edg' or 'net'
        If `output` is specified, `format` specifies how the output is
        written. 'edg' is the standard edge format (FROM TO WEIGHT)
        and 'net' gives the Pajek format.

    Return
    ------
    IF `output` is None:
        linegraph : pynet.SymmNet or pynet.Net object
            The weighted line graph.
    id_array : numpy.array with shape (len(net.edges), 2)
        Array for converting the nodes in the line graph back into the
        edges of the original graph. id_array[EDGE_ID] contains the
        two end nodes of given edge, where EDGE_ID is the same as used
        in `linegraph`.
    """

    if output is None:
        if useWeights:
            linegraph = pynet.Net()
        else:
            linegraph = pynet.SymmNet()
    edge_map = dict()  # edge_map[sorted([n_i, n_j])] = new_node_ID

    if output is not None and format == 'net':
        # Print Pajek file header.
        N_edges = len(list(net.edges))
        output.write("*Vertices %d\n" % N_edges)
        for i in range(N_edges):
            output.write('%d "%d"\n' % (i, i))
        N_edge_links = 0
        for n in net:
            degree = len(list(net[n]))
            N_edge_links += (degree * (degree - 1)) / 2
        if useWeights:
            output.write("*Arcs %d\n" % (2 * N_edge_links, ))
        else:
            output.write("*Edges %d\n" % N_edge_links)

    # Go through all nodes (n_c = center node), and for each node, go
    # through all pairs of neighbours (n_i and n_j). The edges
    # e_i=(n_c,n_i) and e_j=(n_c,n_j) are nodes in the line graph, so
    # we add a link between them.
    for n_c in net:
        strength = net[n_c].strength()
        nb = list(net[n_c])  # List of neighbours
        for i, n_i in enumerate(nb):
            e_i = edge_map.setdefault(tuple(sorted([n_c, n_i])), len(edge_map))
            other_nb = (nb[:i] + nb[i + 1:] if useWeights else nb[i + 1:])
            for n_j in other_nb:
                e_j = edge_map.setdefault(tuple(sorted([n_c, n_j])),
                                          len(edge_map))
                if useWeights:
                    w = net[n_c][n_j] / (strength - net[n_c][n_i])
                else:
                    w = 1.0 / (len(nb) - 1)
                if output is None:
                    linegraph[e_i][e_j] = w
                else:
                    output.write(" ".join(map(str, [e_i, e_j, w])) + "\n")

    # Construct id_array from edge_map
    id_array = np.zeros((len(edge_map), 2), int)
    for node_pair, edgeID in edge_map.iteritems():
        id_array[edgeID] = list(node_pair)

    if output is None:
        return linegraph, id_array
    else:
        return id_array