def test_random_mod(): """ Test the GraphPartition operation that selects random modules to merge and split XXX not working yet""" #nnod_mod, av_degrees, nmods networks = [[4, [2, 3], [2, 4, 6]], [8, [4, 6], [4, 6, 8]]] n_iter = 100 for nnod_mod, av_degrees, nmods in networks: for nmod in nmods: nnod = nnod_mod * nmod for av_degree in av_degrees: g = mod.random_modular_graph(nnod, nmod, av_degree) part = dict() while (len(part) <= 1) or (len(part) == nnod): part = mod.rand_partition(g) graph_partition = mod.GraphPartition(g, part) for i in range(n_iter): graph_partition.random_mod() #check that the partition has > 1 modules true = len(graph_partition) > 1 npt.assert_equal(true, 1) #check that the partition has < nnod modules true = len(graph_partition) < nnod npt.assert_equal(true, 1)
def test_modularity(): """Test the values that go into the modularity calculation after randomly creating a graph""" # Given a partition with the correct labels of the input graph, verify that # the modularity returns 1 # We need to measure the degree within/between modules nnods = 120, 240, 360 nmods = 2, 3, 4 av_degrees = 8, 10, 16 for nnod in nnods: for nmod in nmods: for av_degree in av_degrees: g = mod.random_modular_graph(nnod, nmod, av_degree) #Compute the of nodes per module nnod_mod = nnod / nmod #Make a "correct" partition for the graph part = mod.perfect_partition(nmod, nnod_mod) #Make a graphpartition object graph_partition = mod.GraphPartition(g, part) #call modularity mod_meas = graph_partition.modularity() mod_true = 1.0 - 1.0 / nmod npt.assert_almost_equal(mod_meas, mod_true, 2)
def test_find_unconnected_nodes(): jnk = np.zeros((10, 10)) jnk[:6, :6] = 1 jnk = np.triu(jnk, 1) graph = nx.from_numpy_matrix(jnk > 0, nx.Graph(weighted=False)) index = {0: set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])} graph_partition = mod.GraphPartition(graph, index) solitary_nodes = graph_partition.find_unconnected_nodes() npt.assert_equal(solitary_nodes, [6, 7, 8, 9])
def test_index_as_node_names(): graph = nx.Graph() graph.add_edge('a', 'b') graph.add_edge('c', 'd') ## NOTE network x does not store names as added ## for this graph ['a', 'c', 'b', 'd'] index = {0: set([0, 2]), 1: set([1, 3])} gpart = mod.GraphPartition(graph, index) named_index = gpart.index_as_node_names() assert ['a', 'b'] in named_index
def betweenness_to_modularity(g, ppart): """Function to convert between betweenness fractions and modularity Parameters: ---------- g = graph object ppart = perfect partition Returns: -------- mod = best modularity associated with this graph object """ graph_partition = mod.GraphPartition(g, ppart) return graph_partition.modularity()
def test_graphpartition(): """ test GraphPartition correctly handles graph whose nodes are strings""" graph = nx.Graph() graph.add_edge('a', 'b') graph.add_edge('c', 'd') index = {0: set([0, 1]), 1: set([2, 3])} gpart = mod.GraphPartition(graph, index) assert gpart._node_set == set([0, 1, 2, 3]) # test raise error if matrix unweighted jnk = np.random.random((10, 10)) jnk = np.triu(jnk, 1) graph = nx.from_numpy_matrix(jnk, nx.Graph(weighted=False)) npt.assert_raises(ValueError, mod.GraphPartition, graph, index)
def test_badindex_graphpartition(): """ when making a GraphPArtition, check index is valid""" ## index should be dict of sets e = np.loadtxt(os.path.join(os.path.dirname(__file__), 'jazz.net'), skiprows=3, dtype=int)[:, :2] - 1 g = nx.Graph() g.add_edges_from(e) index = {0: set(g.nodes()[:100]), 1: set(g.nodes()[100:])} gp = mod.GraphPartition(g, index) nt.assert_true(gp.index == index) npt.assert_raises(TypeError, mod.GraphPartition, g, {0: g.nodes()}) npt.assert_raises(ValueError, mod.GraphPartition, g, {0: set(g.nodes()[:-1])}) npt.assert_raises(TypeError, mod.GraphPartition, g, g.nodes())
def test_apply_node_move(): """Test the GraphPartition operation that moves a single node so that it returns a change in modularity that reflects the difference between the modularity of the new and old parititions""" # nnod_mod, av_degrees, nmods #networks = [ [3, [2], [2, 3, 4]], # [4, [2, 3], [2, 4, 6]], # [8, [4, 6], [4, 6, 8]] ] networks = [[4, [2, 3], [2, 4, 6]], [8, [4, 6], [4, 6, 8]]] for nnod_mod, av_degrees, nmods in networks: for nmod in nmods: nnod = nnod_mod * nmod for av_degree in av_degrees: print nnod_mod, nmod, av_degree g = mod.random_modular_graph(nnod, nmod, av_degree) #Make a "correct" partition for the graph #part = mod.perfect_partition(nmod,nnod/nmod) #Make a random partition for the graph part_rand = dict() while len(part_rand) <= 1: #check if there is only one module part_rand = mod.rand_partition(g) #List of modules in the partition r_mod = range(len(part_rand)) #Make a graph_partition object graph_partition = mod.GraphPartition(g, part_rand) #select two modules to change node assignments mod_per = np.random.permutation(r_mod) m1 = mod_per[0] m2 = mod_per[1] while len(graph_partition.index[m1]) <= 1: mod_per = np.random.permutation(r_mod) m1 = mod_per[0] m2 = mod_per[1] #pick a random node to move between modules m1 and m2 node_list = list(graph_partition.index[m1]) nod_per = np.random.permutation(node_list) n = nod_per[0] #list of nodes within the original modules (before node move) ## n1_init = list(nod_per) #list(graph_partition.index[m1]) ## n2_init = list(graph_partition.index[m2]) ## n1_new = copy.deepcopy(n1_init) ## n2_new = copy.deepcopy(n2_init) # calculate modularity before node move mod_init = graph_partition.modularity() # move node from m1 to m2 node_moved_mods,e1,a1,delta_energy_meas,n,m1,m2 = \ graph_partition.compute_node_update(n,m1,m2) graph_part2 = copy.deepcopy(graph_partition) m2_new = graph_part2.apply_node_update(n, m1, m2, node_moved_mods, e1, a1) #if the keys get renamed, the m1,m2 numbers are no longer the same #test that m2 now contains n nt.assert_true(n in graph_part2.index[m2_new]) #if n not in graph_part2.index[m2_new]: # 1/0 # recalculate modularity after splitting mod_new = graph_part2.modularity() # difference between new and old modularity delta_energy_true = -(mod_new - mod_init) #print delta_energy_meas,delta_energy_true # Test that the measured change in energy is equal to the true # change in energy calculated in the node_update function npt.assert_almost_equal(delta_energy_meas, delta_energy_true)
def test_apply_module_split(): """Test the GraphPartition operation that splits modules so that it returns a change in modularity that reflects the difference between the modularity of the new and old parititions. Also test that the module that was split now contains the correct nodes, the correct modularity update, the correct energy,and that no empty modules result from it.""" # nnod_mod, av_degrees, nmods networks = [[3, [2], [2, 3, 4]], [4, [2, 3], [2, 4, 6]], [8, [4, 6], [4, 6, 8]]] for nnod_mod, av_degrees, nmods in networks: for nmod in nmods: nnod = nnod_mod * nmod for av_degree in av_degrees: g = mod.random_modular_graph(nnod, nmod, av_degree) # Make a "correct" partition for the graph ## part = mod.perfect_partition(nmod,nnod/nmod) # Make a random partition for the graph part_rand = mod.rand_partition(g, nnod / 2) #List of modules in the partition that have two or more nodes r_mod = [] for m, nodes in part_rand.iteritems(): if len(nodes) > 2: r_mod.append(m) # Note: The above can be written in this more compact, if # slightly less intuitively clear, list comprehension: # r_mod = [ m for m, nodes in part_rand.iteritems() if # len(nodes)>2 ] #Module that we are splitting for m in r_mod: graph_partition = mod.GraphPartition(g, part_rand) #index of nodes within the original module (before split) n_init = list(graph_partition.index[m]) #calculate modularity before splitting mod_init = graph_partition.modularity() # assign nodes to two groups n1_orig, n2_orig = graph_partition.determine_node_split(m) # make sure neither of these is empty nt.assert_true(len(n1_orig) >= 1) nt.assert_true(len(n2_orig) >= 1) #make sure that there are no common nodes between the two node_intersection = set.intersection(n1_orig, n2_orig) nt.assert_equal(node_intersection, set([])) #make sure that sum of the two node sets equals the #original set node_union = set.union(n1_orig, n2_orig) npt.assert_equal(np.sort(list(node_union)), np.sort(n_init)) # split modules split_modules,e1,a1,delta_energy_meas,type,m,n1,n2 = \ graph_partition.compute_module_split(m,n1_orig,n2_orig) #note: n1 and n2 are output from this function (as well as #inputs) because the function is called from within another #(rand_mod) def but then output to the simulated script, so #the node split needs to be passed along. #as a simple confirmation, can make sure they match npt.assert_equal(n1_orig, n1) npt.assert_equal(n2_orig, n2) #split_moduels should be a dictionary with two modules #(0,1) that contain the node sets n1 and n2 respectively. #test this. npt.assert_equal(split_modules[0], n1) npt.assert_equal(split_modules[1], n2) #make a new graph partition equal to the old one and apply #the module split to it (graph_part2) graph_part2 = copy.deepcopy(graph_partition) graph_part2.apply_module_split(m, n1, n2, split_modules, e1, a1) #make a third graph partition using only the original graph #and the partition from graph_part2 graph_part3 = mod.GraphPartition(g, graph_part2.index) #index of nodes within the modules after splitting n1_new = list(graph_part2.index[m]) n2_new = list(graph_part2.index[len(graph_part2) - 1]) n_all = n1_new + n2_new # recalculate modularity after splitting mod_new = graph_part2.modularity() mod_new_3 = graph_part3.modularity() # difference between new and old modularity delta_energy_true = -(mod_new - mod_init) # Test that the measured change in energy by splitting a # module is equal to the function output from module_split npt.assert_almost_equal(delta_energy_meas, delta_energy_true) # Test that the nodes in the split modules are equal to the # original nodes of the module nt.assert_equal(sorted(list(n1)), sorted(n1_new)) nt.assert_equal(sorted(list(n2)), sorted(n2_new)) n_init.sort() n_all.sort() # Test that the initial list of nodes in the module are # equal to the nodes in m1 and m2 (split modules) npt.assert_equal(n_init, n_all) # Test that the computed modularity found when # apply_module_split is used is equal to the modularity you # would find if using that partition and that graph npt.assert_almost_equal(mod_new, mod_new_3) # Check that there are no empty modules in the final # partition for m in graph_part2.index: nt.assert_true(len(graph_part2.index[m]) > 0)
def test_mutual_information(): """ Test the function which returns the mutual information in two partitions XXX - This test is currently incomplete - it only checks the most basic case of MI(x, x)==1, but doesn't do any non-trivial checks. """ # nnod_mod, av_degrees, nmods networks = [[4, [2, 3], [2, 4, 6]], [8, [4, 6], [4, 6, 8]], [40, [20], [2]]] for nnod_mod, av_degrees, nmods in networks: for nmod in nmods: nnod = nnod_mod * nmod for av_degree in av_degrees: #make a graph object g = mod.random_modular_graph(nnod, nmod, av_degree) #Compute the of nodes per module nnod_mod = nnod / nmod #Make a "correct" partition for the graph ppart = mod.perfect_partition(nmod, nnod_mod) #graph_out, mod_array =mod.simulated_annealing(g, temperature = #temperature,temp_scaling = temp_scaling, tmin=tmin) #test the perfect case for now: two of the same partition #returns 1 mi_orig = mod.mutual_information(ppart, ppart) npt.assert_equal(mi_orig, 1) #move one node and test that mutual_information comes out #correctly graph_partition = mod.GraphPartition(g, ppart) graph_partition.node_update(0, 0, 1) mi = mod.mutual_information(ppart, graph_partition.index) npt.assert_array_less(mi, mi_orig) ## NOTE: CORRECTNESS NOT TESTED YET #merge modules and check that mutual information comes out #correctly/lower graph_partition2 = mod.GraphPartition(g, ppart) merged_module, e_new, a_new, d, t, m1, m2, x = graph_partition2.compute_module_merge( 0, 1) graph_partition2.apply_module_merge(m1, m2, merged_module, e_new, a_new) mi2 = mod.mutual_information(ppart, graph_partition2.index) npt.assert_array_less(mi2, mi_orig) ## NOTE: CORRECTNESS NOT TESTED YET #split modules and check that mutual information comes out #correclty/lower graph_partition3 = mod.GraphPartition(g, ppart) n1 = set(list(graph_partition3.index[0])[::2]) n2 = set(list(graph_partition3.index[0])[1::2]) split_modules, e_new, a_new, d, t, m, n1, n2 = graph_partition3.compute_module_split( 0, n1, n2) graph_partition3.apply_module_split(m, n1, n2, split_modules, e_new, a_new) mi3 = mod.mutual_information(ppart, graph_partition3.index) npt.assert_array_less(mi3, mi_orig)
def test_apply_module_merge(): """Test the GraphPartition operation that merges modules so that it returns a change in modularity that reflects the difference between the modularity of the new and old parititions""" # nnod_mod, av_degrees, nmods networks = [[3, [2], [3, 4]], [4, [2, 3], [2, 4, 6]], [8, [4, 6], [4, 6, 8]]] for nnod_mod, av_degrees, nmods in networks: for nmod in nmods: nnod = nnod_mod * nmod for av_degree in av_degrees: g = mod.random_modular_graph(nnod, nmod, av_degree) #Make a "correct" partition for the graph part = mod.perfect_partition(nmod, nnod / nmod) #Make a random partition for the graph part_rand = dict() while len(part_rand) <= 1: #check if there is only one module part_rand = mod.rand_partition(g) #List of modules in the partition r_mod = range(len(part)) #Loop through pairs of modules for i in range(1): # DB: why is this necessary? #select two modules to merge mod_per = np.random.permutation(r_mod) m1 = mod_per[0] m2 = mod_per[1] #make a graph partition object graph_partition = mod.GraphPartition(g, part) #index of nodes within the original module (before merge) n1_init = list(graph_partition.index[m1]) n2_init = list(graph_partition.index[m2]) n_all_init = n1_init + n2_init #calculate modularity before merging mod_init = graph_partition.modularity() #merge modules merge_module,e1,a1,delta_energy_meas,type,m1,m2,m2 = \ graph_partition.compute_module_merge(m1,m2) graph_part2 = copy.deepcopy(graph_partition) graph_part2.apply_module_merge(m1, m2, merge_module, e1, a1) #index of nodes within the modules after merging n_all = list(graph_part2.index[min(m1, m2)]) # recalculate modularity after splitting mod_new = graph_part2.modularity() # difference between new and old modularity delta_energy_true = -(mod_new - mod_init) # Test the measured difference in energy against the # function that calculates the difference in energy npt.assert_almost_equal(delta_energy_meas, delta_energy_true) # Check that the list of nodes in the two original modules # is equal to the list of nodes in the merged module n_all_init.sort() n_all.sort() npt.assert_equal(n_all_init, n_all) # Test that the keys are equivalent after merging modules npt.assert_equal(r_mod[:-1], sorted(graph_part2.index.keys())) # Test that the values in the mod_e and mod_a matrices for # the merged module are correct. npt.assert_equal(graph_part2.mod_e[min(m1, m2)], e1) npt.assert_equal(graph_part2.mod_a[min(m1, m2)], a1)