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_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_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) yield 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) yield 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) yield 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 = list(graph_partition3.index[0])[::2] n2 = 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) yield npt.assert_array_less(mi3,mi_orig)
def SA(): """ Test the simulated annealing script""" #nnod_mod, av_degrees, nmods #networks = [ [4, [2, 3], [2, 4, 6]]]#, #networks = [ [8, [4, 6], [4, 6, 8]]] #networks = [[40, [20], [2]]] networks = [[32, [16], [4]]] #networks = [[64, [12], [6]]] btwn_fracs = [0] temperature = 10 temp_scaling = 0.9995 tmin = 1e-4 nochange_ratio_min = 0.01 #keep time for nnod_mod, av_degrees, nmods in networks: for nmod in nmods: nnod = nnod_mod * nmod for av_degree in av_degrees: for btwn_frac in btwn_fracs: t1 = time.clock() g = mod.random_modular_graph(nnod, nmod, av_degree, btwn_frac) #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, energy_array, rej_array, temp_array = mod.simulated_annealing( g, temperature=temperature, temp_scaling=temp_scaling, tmin=tmin, nochange_ratio_min=nochange_ratio_min) print "perfect partition", ppart print "SA partition", graph_out.index t2 = time.clock() print 'Elapsed time: ', float(t2 - t1) / 60, 'minutes' print 'partition similarity: ', mod.mutual_information( ppart, graph_out.index) return graph_out, g, energy_array, rej_array, ppart, temp_array
def SA(): """ Test the simulated annealing script""" # nnod_mod, av_degrees, nmods # networks = [ [4, [2, 3], [2, 4, 6]]]#, # networks = [ [8, [4, 6], [4, 6, 8]]] # networks = [[40, [20], [2]]] networks = [[32, [16], [4]]] # networks = [[64, [12], [6]]] btwn_fracs = [0] temperature = 10 temp_scaling = 0.9995 tmin = 1e-4 nochange_ratio_min = 0.01 # keep time for nnod_mod, av_degrees, nmods in networks: for nmod in nmods: nnod = nnod_mod * nmod for av_degree in av_degrees: for btwn_frac in btwn_fracs: t1 = time.clock() g = mod.random_modular_graph(nnod, nmod, av_degree, btwn_frac) # 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, energy_array, rej_array, temp_array = mod.simulated_annealing( g, temperature=temperature, temp_scaling=temp_scaling, tmin=tmin, nochange_ratio_min=nochange_ratio_min, ) print "perfect partition", ppart print "SA partition", graph_out.index t2 = time.clock() print "Elapsed time: ", float(t2 - t1) / 60, "minutes" print "partition similarity: ", mod.mutual_information(ppart, graph_out.index) return graph_out, g, energy_array, rej_array, ppart, temp_array
def test_sim_anneal_simple(): """Very simple simulated_annealing test with a small network""" # nnod, nmod, av_degree, btwn_frac = 24, 3, 4, 0 g = mod.random_modular_graph(nnod, nmod, av_degree, btwn_frac) #Compute the # of nodes per module nnod_mod = nnod/nmod #Make a "correct" partition for the graph ppart = mod.perfect_partition(nmod,nnod_mod) temperature = 10 temp_scaling = 0.95 tmin=1 graph_out, graph_dict = mod.simulated_annealing(g, temperature = temperature, temp_scaling = temp_scaling, tmin=tmin, extra_info = True, debug=True) # Ensure that there are no empty modules util.assert_no_empty_modules(graph_out.index) mi = mod.mutual_information(ppart, graph_out.index)
def danon_benchmark(): """This test comes from Danon et al 2005. It will create the line plot of Mututal Information vs. betweenness fraction to assess the performance of the simulated annealing algorithm.""" networks = [[32, [16], [6]]] btwn_fracs = [float(i)/100 for i in range(0,80,3)] temperature = 0.1 temp_scaling = 0.9995 tmin=1e-4 num_reps = range(1) mi_arr=np.empty((len(btwn_fracs),len(num_reps))) #keep time for rep in num_reps: t1 = time.clock() for nnod_mod, av_degrees, nmods in networks: for nmod in nmods: nnod = nnod_mod*nmod for av_degree in av_degrees: x_mod = [] for ix,btwn_frac in enumerate(btwn_fracs): print 'btwn_frac: ',btwn_frac g = mod.random_modular_graph(nnod, nmod, av_degree,btwn_frac) #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, graph_dict =mod.simulated_annealing(g, temperature = temperature,temp_scaling = temp_scaling, tmin=tmin, extra_info = True) #print "SA partition",graph_out.index mi = mod.mutual_information(ppart,graph_out.index) t2 = time.clock() print 'Elapsed time: ', (float(t2-t1)/60), ' minutes' print 'partition similarity: ',mi mi_arr[ix,rep] = mi ## plot_partition(g,graph_out.index,'mi: '+ str(mi),'danon_test_6mod'+str(btwn_frac)+'_graph.png') x_mod.append(betweenness_to_modularity(g,ppart)) ## mi_arr_avg = np.mean(mi_arr,1) ## plt.figure() ## plt.plot(btwn_fracs,mi_arr_avg) ## plt.xlabel('Betweenness fraction') ## plt.ylabel('Mutual information') ## plt.savefig('danon_test_6mod/danontest_btwn.png') ## plt.figure() ## plt.plot(x_mod,mi_arr_avg) ## plt.xlabel('Modularity') ## plt.ylabel('Mutual information') ## plt.savefig('danon_test_6mod/danontest_mod.png') #plt.figure() #plt.plot(graph_dict['energy'], label = 'energy') #plt.plot(graph_dict['temperature'], label = 'temperature') #plt.xlabel('Iteration') return mi_arr
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)
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 yield nt.assert_true(len(n1_orig)>= 1) yield 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) yield 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) yield 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 yield npt.assert_equal(n1_orig,n1) yield 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. yield npt.assert_equal(split_modules[0],n1) yield 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 yield 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 yield npt.assert_equal(np.sort(list(n1)), n1_new) yield npt.assert_equal(np.sort(list(n2)), 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) yield 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 yield 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: yield 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 danon_benchmark(): """This test comes from Danon et al 2005. It will create the line plot of Mututal Information vs. betweenness fraction to assess the performance of the simulated annealing algorithm.""" networks = [[32, [16], [6]]] btwn_fracs = [float(i) / 100 for i in range(0, 80, 3)] temperature = 0.1 temp_scaling = 0.9995 tmin = 1e-4 num_reps = range(1) mi_arr = np.empty((len(btwn_fracs), len(num_reps))) #keep time for rep in num_reps: t1 = time.clock() for nnod_mod, av_degrees, nmods in networks: for nmod in nmods: nnod = nnod_mod * nmod for av_degree in av_degrees: x_mod = [] for ix, btwn_frac in enumerate(btwn_fracs): print 'btwn_frac: ', btwn_frac g = mod.random_modular_graph(nnod, nmod, av_degree, btwn_frac) #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, graph_dict = mod.simulated_annealing( g, temperature=temperature, temp_scaling=temp_scaling, tmin=tmin, extra_info=True) #print "SA partition",graph_out.index mi = mod.mutual_information(ppart, graph_out.index) t2 = time.clock() print 'Elapsed time: ', (float(t2 - t1) / 60), ' minutes' print 'partition similarity: ', mi mi_arr[ix, rep] = mi ## plot_partition(g,graph_out.index,'mi: '+ str(mi),'danon_test_6mod'+str(btwn_frac)+'_graph.png') x_mod.append(betweenness_to_modularity(g, ppart)) ## mi_arr_avg = np.mean(mi_arr,1) ## plt.figure() ## plt.plot(btwn_fracs,mi_arr_avg) ## plt.xlabel('Betweenness fraction') ## plt.ylabel('Mutual information') ## plt.savefig('danon_test_6mod/danontest_btwn.png') ## plt.figure() ## plt.plot(x_mod,mi_arr_avg) ## plt.xlabel('Modularity') ## plt.ylabel('Mutual information') ## plt.savefig('danon_test_6mod/danontest_mod.png') #plt.figure() #plt.plot(graph_dict['energy'], label = 'energy') #plt.plot(graph_dict['temperature'], label = 'temperature') #plt.xlabel('Iteration') return mi_arr
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)