|
26 | 26 | "metadata": {}, |
27 | 27 | "outputs": [], |
28 | 28 | "source": [ |
29 | | - "def load_graph_from_gml_file(graph_file: str, weight_attribute_name: str = \"weight\"):\n", |
30 | | - " import os\n", |
31 | | - " # Check if the graph file exists\n", |
32 | | - " if not os.path.exists(graph_file):\n", |
33 | | - " print(f\"Error: Graph file '{graph_file}' not found.\")\n", |
34 | | - " print(f\"Please ensure '{graph_file}' is a valid path to your 'lesmis.gml' file.\")\n", |
35 | | - " print(\"You can typically find this file by searching for 'lesmis.gml network dataset'.\")\n", |
36 | | - " return # Exit the function if file is not found\n", |
37 | | - "\n", |
38 | | - " try:\n", |
39 | | - " # Load network from GML file\n", |
40 | | - " # igraph.Graph.Read_GML will automatically load edge attributes like 'value'\n", |
41 | | - " # if they are present in the GML file.\n", |
42 | | - " graph = ig.Graph.Read_GML(graph_file)\n", |
| 29 | + "# def load_graph_from_gml_file(graph_file: str, weight_attribute_name: str = \"weight\"):\n", |
| 30 | + "# import os\n", |
| 31 | + "# # Check if the graph file exists\n", |
| 32 | + "# if not os.path.exists(graph_file):\n", |
| 33 | + "# print(f\"Error: Graph file '{graph_file}' not found.\")\n", |
| 34 | + "# print(f\"Please ensure '{graph_file}' is a valid path to your 'lesmis.gml' file.\")\n", |
| 35 | + "# print(\"You can typically find this file by searching for 'lesmis.gml network dataset'.\")\n", |
| 36 | + "# return # Exit the function if file is not found\n", |
| 37 | + "\n", |
| 38 | + "# try:\n", |
| 39 | + "# # Load network from GML file\n", |
| 40 | + "# # igraph.Graph.Read_GML will automatically load edge attributes like 'value'\n", |
| 41 | + "# # if they are present in the GML file.\n", |
| 42 | + "# graph = ig.Graph.Read_GML(graph_file)\n", |
43 | 43 | " \n", |
44 | | - " # Check if the graph has the correct weight attribute name\n", |
45 | | - " if weight_attribute_name not in graph.edge_attributes():\n", |
46 | | - " print(f\"Warning: Graph '{graph_file}' does not have a '{weight_attribute_name}' attribute. \"\n", |
47 | | - " \"Community detection will proceed without explicit weights, or if the algorithm \"\n", |
48 | | - " \"expects them, it might use default uniform weights.\")\n", |
49 | | - " # If no 'value' attribute, assign a default uniform weight for visualization purposes\n", |
50 | | - " graph.es[weight_attribute_name] = 1 \n", |
| 44 | + "# # Check if the graph has the correct weight attribute name\n", |
| 45 | + "# if weight_attribute_name not in graph.edge_attributes():\n", |
| 46 | + "# print(f\"Warning: Graph '{graph_file}' does not have a '{weight_attribute_name}' attribute. \"\n", |
| 47 | + "# \"Community detection will proceed without explicit weights, or if the algorithm \"\n", |
| 48 | + "# \"expects them, it might use default uniform weights.\")\n", |
| 49 | + "# # If no 'value' attribute, assign a default uniform weight for visualization purposes\n", |
| 50 | + "# graph.es[weight_attribute_name] = 1 \n", |
51 | 51 | "\n", |
52 | | - " return graph\n", |
| 52 | + "# return graph\n", |
53 | 53 | "\n", |
54 | 54 | "\n", |
55 | | - " except Exception as e:\n", |
56 | | - " print(f\"An error occurred while loading or processing the graph: {e}\")\n", |
57 | | - " return\n", |
| 55 | + "# except Exception as e:\n", |
| 56 | + "# print(f\"An error occurred while loading or processing the graph: {e}\")\n", |
| 57 | + "# return\n", |
| 58 | + "\n", |
58 | 59 | "\n", |
59 | 60 | "def community_detection(graph: ig.Graph, community_detection_method: str = \"multilevel\", weight_attribute_name: str = \"weight\", \n", |
60 | 61 | " params: dict = None):\n", |
|
67 | 68 | " params[\"weights\"] = weight_attribute_name if weight_attribute_name in graph.edge_attributes() else None\n", |
68 | 69 | " return graph.community_leiden(**params)\n", |
69 | 70 | " elif community_detection_method == \"fastgreedy\":\n", |
70 | | - " return graph.community_fastgreedy(weights=weight_attribute_name if weight_attribute_name in graph.edge_attributes() else None).as_clustering()\n", |
71 | | - "\n", |
72 | | - "\n" |
| 71 | + " return graph.community_fastgreedy(weights=weight_attribute_name if weight_attribute_name in graph.edge_attributes() else None).as_clustering()" |
73 | 72 | ] |
74 | 73 | }, |
75 | 74 | { |
|
80 | 79 | "## Functions useful to test community structure" |
81 | 80 | ] |
82 | 81 | }, |
| 82 | + { |
| 83 | + "cell_type": "markdown", |
| 84 | + "id": "6309417d-2705-4454-9e68-84cf34883c1b", |
| 85 | + "metadata": {}, |
| 86 | + "source": [ |
| 87 | + "### Method 1: Testing network structure with modularity" |
| 88 | + ] |
| 89 | + }, |
83 | 90 | { |
84 | 91 | "cell_type": "code", |
85 | 92 | "execution_count": 3, |
86 | 93 | "id": "1ab35a72-4bcd-4391-8f28-85b39c6a29ef", |
87 | 94 | "metadata": {}, |
88 | 95 | "outputs": [], |
89 | 96 | "source": [ |
90 | | - "\n", |
91 | | - "def get_modularity_on_clustering(graph: ig.Graph, community_detection_method: str = \"multilevel\", params: dict = None):\n", |
92 | | - " partition = community_detection(graph, community_detection_method, weight_attribute_name=None, params=params)\n", |
93 | | - " return partition.modularity\n", |
94 | | - "\n", |
95 | 97 | "def rewire(graph: ig.Graph, community_detection_method: str = \"multilevel\", params: dict = None):\n", |
96 | 98 | " num_randomizations = 500 # Number of randomized networks to generate\n", |
97 | 99 | " modularity_random_networks = []\n", |
|
101 | 103 | " for i in range(num_randomizations):\n", |
102 | 104 | " # G.rewire() modifies the graph in-place, so we must work on a copy.\n", |
103 | 105 | " graph_random = graph.copy()\n", |
104 | | - " \n", |
| 106 | + "\n", |
105 | 107 | " graph_random.rewire(n=num_swaps_for_randomization)\n", |
106 | | - " \n", |
107 | | - " modularity_random_networks.append(get_modularity_on_clustering(graph_random))\n", |
| 108 | + "\n", |
| 109 | + " partition = community_detection(graph, community_detection_method, weight_attribute_name=None, params=params)\n", |
| 110 | + " modularity_random_networks.append(partition.modularity)\n", |
108 | 111 | "\n", |
109 | 112 | " return modularity_random_networks\n", |
110 | 113 | "\n", |
| 114 | + "\n", |
| 115 | + "def test_community_structure(graph: ig.Graph, graph_name: str = \"Karate Club Network\", community_detection_method: str = \"multilevel\", \n", |
| 116 | + " params: dict = None):\n", |
| 117 | + " partition = community_detection(graph, community_detection_method, weight_attribute_name=None, params=params)\n", |
| 118 | + " modularity_orig = partition.modularity\n", |
| 119 | + " modularity_random_networks = rewire(graph, community_detection_method, params)\n", |
| 120 | + " plot_histogram(modularity_orig, modularity_random_networks, graph_name)\n", |
| 121 | + " \n", |
| 122 | + "\n", |
111 | 123 | "def plot_histogram(modularity_original: float, modularity_random_networks: list[float], graph_name: str=\"Karate Club Network\"):\n", |
112 | 124 | " import matplotlib.pyplot as plt\n", |
113 | 125 | " \n", |
|
128 | 140 | " plt.legend()\n", |
129 | 141 | " plt.grid(axis='y', alpha=0.75)\n", |
130 | 142 | " plt.tight_layout()\n", |
131 | | - " plt.show()\n", |
132 | | - "\n", |
133 | | - "\n", |
134 | | - "def test_community_structure(graph: ig.Graph, graph_name: str = \"Karate Club Network\", community_detection_method: str = \"multilevel\", \n", |
135 | | - " params: dict = None):\n", |
136 | | - " modularity_orig = get_modularity_on_clustering(graph, community_detection_method, params)\n", |
137 | | - " modularity_random_networks = rewire(graph, community_detection_method, params)\n", |
138 | | - " plot_histogram(modularity_orig, modularity_random_networks, graph_name)\n" |
| 143 | + " plt.show()\n" |
| 144 | + ] |
| 145 | + }, |
| 146 | + { |
| 147 | + "cell_type": "markdown", |
| 148 | + "id": "7eba4c89-d320-4178-bf00-77966010d148", |
| 149 | + "metadata": {}, |
| 150 | + "source": [ |
| 151 | + "### Method 2: Testing network structure with NMI values" |
139 | 152 | ] |
140 | 153 | }, |
141 | 154 | { |
|
313 | 326 | " return pairwise_nmi_values\n" |
314 | 327 | ] |
315 | 328 | }, |
| 329 | + { |
| 330 | + "cell_type": "markdown", |
| 331 | + "id": "45c898fe-e73d-4b0d-aed2-6574df05132d", |
| 332 | + "metadata": {}, |
| 333 | + "source": [ |
| 334 | + "### Testing Significance of Community Structure on a Grid Graph" |
| 335 | + ] |
| 336 | + }, |
316 | 337 | { |
317 | 338 | "cell_type": "code", |
318 | 339 | "execution_count": 5, |
319 | 340 | "id": "0e018281-2fe7-4c7c-b608-c2e97e315e34", |
320 | 341 | "metadata": {}, |
321 | 342 | "outputs": [], |
322 | 343 | "source": [ |
323 | | - "def create_grid_graph(rows, cols, circular=False):\n", |
324 | | - " \"\"\"\n", |
325 | | - " Generates a 2D grid graph (lattice) without plotting.\n", |
326 | | - " Returns the graph and its column count for later layout.\n", |
327 | | - " \"\"\"\n", |
328 | | - " G = ig.Graph.Lattice(dim=[rows, cols], nei=1, circular=circular)\n", |
329 | | - " return G\n", |
330 | | - "\n", |
331 | | - "# --- Final version of cluster_and_plot_leiden with grid_cols ---\n", |
332 | | - "def cluster_and_plot_leiden_on_grid(graph, grid_cols, title=\"Graph with Leiden Communities\", plot_size=(8, 8)):\n", |
| 344 | + "def plot_leiden_on_grid(graph, grid_cols, communities, title=\"Graph with Leiden Communities\", plot_size=(8, 8)):\n", |
333 | 345 | " \"\"\"\n", |
334 | 346 | " Clusters a graph using the Leiden algorithm and plots the result\n", |
335 | 347 | " with vertices colored by their community, specifically for grid layouts.\n", |
|
344 | 356 | " igraph.clustering.VertexClustering: The community detection result.\n", |
345 | 357 | " \"\"\"\n", |
346 | 358 | " import matplotlib.pyplot as plt\n", |
347 | | - " \n", |
348 | | - " print(f\"Clustering graph with {graph.vcount()} vertices and {graph.ecount()} edges using Leiden algorithm...\")\n", |
349 | | - "\n", |
350 | | - " resolution = 0.15\n", |
351 | | - " communities = graph.community_leiden(objective_function=\"modularity\", resolution=resolution)\n", |
352 | 359 | "\n", |
353 | 360 | " # Assign colors based on community membership\n", |
354 | 361 | " palette = ig.GradientPalette(\"red\", \"blue\", n=len(communities)) \n", |
|
376 | 383 | " )\n", |
377 | 384 | " ax.set_title(title)\n", |
378 | 385 | " ax.axis('off')\n", |
379 | | - " plt.show()\n", |
380 | | - "\n", |
381 | | - " return communities, resolution" |
| 386 | + " plt.show()" |
382 | 387 | ] |
383 | 388 | }, |
384 | 389 | { |
|
0 commit comments