Chromatic and Community Partitions of Networks

Moses Boudourides & Sergios Lenis

This notebook is executed by "sage -ipython notebook." The following are the libraries that need to be loaded first.

In [29]:
from IPython.display import Image
%matplotlib inline
%load_ext sage
%load_ext autoreload
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib
import random
from sage.graphs.graph_coloring import vertex_coloring
The sage extension is already loaded. To reload it, use:
  %reload_ext sage
The autoreload extension is already loaded. To reload it, use:
  %reload_ext autoreload

Generating a connected E-R random graph G

In [30]:
%autoreload 2
from chAs import create_conn_random_graph_chrom,create_conn_random_graph,draw_domcomms

nodes=30
p=0.15

G=create_conn_random_graph(nodes,p)
g=Graph(G)
vc=vertex_coloring(g, value_only=False)

print 'An example of a connected E-R random graph with n =', nodes, 'and p =', "%.2f" % p
print
print 'G is connected:', nx.is_connected(G)
print 'Number of vertices of G:', len(G.nodes())
print 'Number of edges of G:', len(G.edges())
print 'List of edges of random graph G:'
print G.edges()
# print vc
An example of a connected E-R random graph with n = 30 and p = 0.15

G is connected: True
Number of vertices of G: 30
Number of edges of G: 68
List of edges of random graph G:
[(0, 17), (0, 26), (1, 4), (1, 5), (1, 8), (1, 10), (1, 16), (1, 21), (1, 24), (1, 26), (1, 28), (2, 8), (2, 24), (2, 13), (2, 22), (3, 5), (3, 6), (3, 8), (3, 9), (3, 10), (3, 12), (3, 23), (3, 27), (3, 29), (4, 24), (4, 29), (4, 9), (5, 24), (5, 12), (6, 10), (6, 28), (6, 29), (7, 8), (7, 12), (7, 16), (7, 18), (7, 19), (7, 27), (8, 15), (8, 17), (8, 22), (8, 24), (9, 10), (9, 11), (9, 14), (9, 24), (9, 29), (10, 23), (11, 20), (11, 21), (11, 25), (12, 19), (12, 24), (13, 24), (13, 28), (13, 14), (14, 25), (14, 28), (14, 21), (16, 28), (18, 25), (18, 29), (19, 26), (19, 27), (20, 23), (24, 28), (25, 26), (28, 29)]

Computing the chromatic and community partitions of G

In [31]:
%autoreload 2
from chAs import create_conn_random_graph_chrom,draw_domcomms,modul_arity
import community as comm

cn=vertex_coloring(g, value_only=True)
collpar={}
for v,i in enumerate(vc):
    for j in i:
        collpar[j]=v
part=comm.best_partition(G) 
print 'Chromatic number of G =',cn
print 'Chromatic partition of G:'
print vc
print 'Chromatic modularity of G =', "%.4f" % modul_arity(G,'vertex_colors')
print
print 'Community number of G =', max(part.values())+1
for nd in G.nodes():
    G.add_node(nd,vertex_colors=collpar[nd],comm_coll=part[nd])
print 'Community partition of G:'
parLis=[]
partdi={}
for i,k in part.items():
    if k not in partdi:
        partdi[k]=[i]
    else:
        partdi[k].append(i)
for i,k in partdi.items():
    parLis.append(k)
print parLis
for i,v in enumerate(parLis):
    gg=Graph(G.subgraph(v))
    print 'Community %i (as a subgraph) has chromatic number %i' %(i,vertex_coloring(gg, value_only=True))
print 'Community modularity of G =', "%.4f" % comm.modularity(part,G)

d=.8
dd=.8
c=1.2
cc=1.4
alpha=0.2
ealpha=.2
vcc={}
for i,nd in enumerate(vc):
    for ndd in nd:
        vcc[ndd]=i
        
draw_domcomms(G,G.nodes(),[],[],[] ,vcc,part,d,dd,c,cc,alpha,ealpha)
Chromatic number of G = 4
Chromatic partition of G:
[[1, 3, 13, 19, 11, 22, 18, 17, 15], [4, 10, 28, 5, 8, 25, 27, 21, 20, 0], [24, 29, 14, 7, 26, 23], [6, 9, 12, 2, 16]]
Chromatic modularity of G = 0.0000

Community number of G = 5
Community partition of G:
[[0, 11, 17, 18, 20, 25, 26], [1, 14, 16, 21, 28], [2, 8, 13, 15, 22, 24], [3, 4, 6, 9, 10, 23, 29], [5, 7, 12, 19, 27]]
Community 0 (as a subgraph) has chromatic number 2
Community 1 (as a subgraph) has chromatic number 3
Community 2 (as a subgraph) has chromatic number 3
Community 3 (as a subgraph) has chromatic number 3
Community 4 (as a subgraph) has chromatic number 3
Community modularity of G = 0.3489

Chromatic and Community Partitions of 2-Layer Graphs:

The Lazega 2-Layer Network of Researchers and Institutions in French Cancer Studies

In [21]:
import pickle
import networkx as nx
lg = pickle.load(open('lazega_graph.txt'))
# print nx.info(lg)
G = nx.Graph(lg)
# print nx.info(G)
# print G.nodes()
nodes = G.nodes()
nodes.sort()
# print nodes
# print len(nodes)
llist=[]
xlist=[]
for i in nodes:
    if 'l' in i:
        llist.append(i)
    if 'x' in i:
        xlist.append(i)
# print llist
# print xlist
# print len(llist)
# print len(xlist)
names = llist+xlist
# print names
# print len(names)
idies = range(208)
mapping_dict={}
for i in range(len(names)):
    mapping_dict[names[i]] = idies[i]
# print mapping_dict
nx.relabel_nodes(G, mapping_dict, copy=False)
# print G.nodes()
Out[21]:
<networkx.classes.graph.Graph object at 0x7fa1b86fee50>
In [22]:
%autoreload 2

from chAs import plot_paral
layer1=range(82)
layer2=range(82,208)
# d1=0.6 #1.5
# d2=15. # 5.
# d3=0.3 #0.8
nodesize=200
withlabels=False
edgelist=[]
layout=True
alpha=0.25
plot_paral(G,layer1,layer2,d1=1.,d2=11.,d3=.8,d4=.5,d5=.5,d6=7,nodesize=50,withlabels=True,edgelist=[],layout=True,alpha=0.5)

Taking the connected components of both upper and lower layers

In [23]:
F=nx.Graph(G)
print nx.isolates(F)
F.remove_nodes_from(nx.isolates(F))
layer1=range(82)
fl1=nx.subgraph(F,layer1)
F.remove_nodes_from(nx.isolates(fl1))
fl1.remove_nodes_from(nx.isolates(fl1))
# fl1=nx.subgraph(F,layer1)
print nx.is_connected(fl1)
layer2=range(82,208)
fl2=nx.subgraph(F,layer2)
F.remove_nodes_from(nx.isolates(fl2))
fl2.remove_nodes_from(nx.isolates(fl2))
print nx.is_connected(fl2)
layer1=fl1.nodes()
layer2=fl2.nodes()
print
print "INSTITUTIONS (UPPER LAYER) ARE DENOTED AS SQUARES"
print
print layer1
print
print "RESEARCHERS (LOWER LAYER) ARE DENOTED AS CIRCLES"
print
print layer2
# d1=0.6 #1.5
# d2=15. # 5.
# d3=0.3 #0.8
# print type(F)
nodesize=200
withlabels=False
edgelist=[]
layout=True
alpha=0.25
plot_paral(F,layer1,layer2,d1=1.,d2=9.,d3=.8,d4=1.,d5=.5,d6=11,nodesize=200,withlabels=True,edgelist=[],layout=True,alpha=0.5)
[]
True
True

INSTITUTIONS (UPPER LAYER) ARE DENOTED AS SQUARES

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 57, 59, 60, 61, 62, 63, 64, 65, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 80, 81]

RESEARCHERS (LOWER LAYER) ARE DENOTED AS CIRCLES

[82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207]

Chromatic and Community Partitions of the Lazega 2-Layer Network

In [27]:
%autoreload 2
from chAs import create_conn_random_graph_chrom,draw_domcomms_sr,modul_arity,plot_paral_chr_comm
import community as comm
g=Graph(F)
cn=vertex_coloring(g, value_only=True)
# print 'done',cn
vc=vertex_coloring(g,value_only=False)
# print 'done'
collpar={}
for v,i in enumerate(vc):
    for j in i:
        collpar[j]=v
part=comm.best_partition(F) 
print 'Chromatic number of F =',cn
print 'Chromatic partition of F:'
print vc
print 'Chromatic modularity of F =', "%.4f" % modul_arity(F,'vertex_colors')
print
print 'Community number of F =', max(part.values())+1
for nd in F.nodes():
    F.add_node(nd,vertex_colors=collpar[nd],comm_coll=part[nd])
print 'Community partition of F:'
parLis=[]
partdi={}
for i,k in part.items():
    if k not in partdi:
        partdi[k]=[i]
    else:
        partdi[k].append(i)
for i,k in partdi.items():
    parLis.append(k)
print parLis
for i,v in enumerate(parLis):
    gg=Graph(F.subgraph(v))
    print 'Community %i (as a subgraph) has chromatic number %i' %(i,vertex_coloring(gg, value_only=True))
print 'Community modularity of F =', "%.4f" % comm.modularity(part,F)

d=.6
dd=.8
c=1.2
cc=1.4
alpha=.1
ealpha=.1
nodesize=20
vcc={}
for i,nd in enumerate(vc):
    for ndd in nd:
        vcc[ndd]=i
        
draw_domcomms_sr(F,layer1,layer2,F.nodes(),[],[],[] ,vcc,part,d,dd,c,cc,alpha,ealpha,nodesize=nodesize)
Chromatic number of F = 8
Chromatic partition of F:
[[86, 89, 93, 99, 101, 111, 127, 128, 146, 152, 183, 82, 168, 87, 125, 186, 43, 97, 59, 19, 8, 50, 28, 38, 13, 201, 203, 197, 196, 193, 185, 178, 154, 142, 139, 138, 132, 112, 106, 105, 85, 80, 73, 69, 67, 64, 54, 52, 45, 44, 41, 40, 35, 34, 26, 16, 12, 11, 4, 2], [91, 102, 103, 104, 107, 115, 119, 133, 134, 123, 22, 113, 3, 174, 27, 109, 60, 75, 24, 1, 62, 189, 202, 194, 173, 166, 143, 118, 88, 78, 49, 33, 30, 17, 14], [92, 94, 95, 131, 135, 151, 158, 161, 163, 164, 130, 0, 20, 147, 23, 51, 117, 46, 76, 63, 190, 171, 159, 149, 140, 137, 120, 116, 84, 79, 71, 68, 61, 57, 47, 42, 36, 32, 31, 5], [96, 110, 114, 122, 126, 144, 175, 187, 199, 204, 150, 83, 37, 7, 181, 136, 124, 90, 81, 77, 74, 56, 53], [108, 153, 156, 160, 165, 188, 191, 18, 25, 9, 129, 100, 70, 48, 15, 6], [121, 148, 155, 157, 169, 172, 179, 182, 184, 207, 65, 29, 21, 10], [98, 141, 145, 162, 177, 198], [167, 170, 176, 192, 195, 200, 205, 206]]
Chromatic modularity of F = -0.1451

Community number of F = 7
Community partition of F:
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 33, 35, 36, 37, 38, 40, 41, 43, 45, 46, 48, 50, 53, 56, 57, 59, 60, 61, 62, 63, 64, 65, 70, 71, 73, 74, 75, 76, 78, 79, 80, 81, 138], [16, 47, 93, 96, 97, 99, 100, 102, 104, 108, 110, 111, 115, 132, 135, 142, 150, 151, 158, 161, 164, 165, 167, 172, 177, 183, 185, 194], [17, 34, 51, 54, 69, 77, 90, 94, 112, 127, 139, 143, 144, 145, 147, 159, 166, 168, 186, 189, 193, 195, 202, 203], [26, 42, 44, 82, 89, 98, 103, 107, 109, 113, 114, 119, 121, 128, 129, 153, 155, 156, 157, 163, 170, 178, 187, 198, 199, 200, 204, 206], [32, 49, 52, 84, 106, 118, 140], [67, 68, 83, 85, 86, 87, 95, 101, 116, 122, 123, 124, 130, 134, 137, 141, 149, 169, 171, 173, 174, 175, 176, 181, 191, 196, 197, 201], [88, 91, 92, 105, 117, 120, 125, 126, 131, 133, 136, 146, 148, 152, 154, 160, 162, 179, 182, 184, 188, 190, 192, 205, 207]]
Community 0 (as a subgraph) has chromatic number 5
Community 1 (as a subgraph) has chromatic number 6
Community 2 (as a subgraph) has chromatic number 3
Community 3 (as a subgraph) has chromatic number 8
Community 4 (as a subgraph) has chromatic number 3
Community 5 (as a subgraph) has chromatic number 6
Community 6 (as a subgraph) has chromatic number 5
Community modularity of F = 0.4415

Visualizing the Chromatic and Community Partitions of the Lazega Network as a 2-Layer Graph

In [25]:
nodesize=200
withlabels=False
edgelist=[]
layout=True
alpha=0.125
plot_paral_chr_comm(F,layer1,layer2,vc,parLis,d1=.75,d2=9.,d3=.8,d4=1.,d5=.75,d6=11,nodesize=200,withlabels=False,edgelist=[],layout=True,alpha=0.15)

Chromatic Numbers of 3-Layer Graphs

In [26]:
%autoreload 2
from syntheticThreeLayerGraph import synthetic_three_level, plot_graph_comms

n1=n2=n3=50
p1=p2=p3=0.1
q1=q2=q3=0.01

H1,H2,H3,G,J,FF,DD,edgeList = synthetic_three_level(n1,n2,n3,p1,p2,p3,q1,q2,q3,no_isolates=True)
g=Graph(G)
vc=vertex_coloring(g, value_only=False)

print 'An example of a 3-layer E-R random graph G with n =', n1+n2+n3, 'p =', "%.2f," % p1, 'q =', "%.2f" % q1, \
'and maximum degree =', max(G.degree().values())
print 'G is connected:', nx.is_connected(G)
print
print 'Chromatic number of the 3-layer graph G is %i' %len(vc)

gg=Graph(J)
print 'Top left layer (as a subgraph) has chromatic number %i' %vertex_coloring(gg, value_only=True)
gg=Graph(FF)
print 'Top right layer (as a subgraph) has chromatic number %i' %vertex_coloring(gg, value_only=True)
gg=Graph(DD)
print 'Bottom layer (as a subgraph) has chromatic number %i' %vertex_coloring(gg, value_only=True)
part=comm.best_partition(G) 
print
print 'Community number of the 3-layer graph G is %i' %len(set(part.values()))
parLis=[]
partdi={}
for i,k in part.items():
    if k not in partdi:
        partdi[k]=[i]
    else:
        partdi[k].append(i)
for i,k in partdi.items():
    parLis.append(k)
pos=plot_graph_comms(G,J,FF,DD,n1,n2,n3,vc,parLis,d1=1,d2=10.,d3=0.8,nodesize=150,withlabels=False,edgelist=edgeList,layout=False,b_alpha=0.25)
An example of a 3-layer E-R random graph G with n = 150 p = 0.10, q = 0.01 and maximum degree = 11
G is connected: True

Chromatic number of the 3-layer graph G is 4
Top left layer (as a subgraph) has chromatic number 4
Top right layer (as a subgraph) has chromatic number 4
Bottom layer (as a subgraph) has chromatic number 3

Community number of the 3-layer graph G is 7
In [ ]: