├── .idea └── vcs.xml ├── Graphlet.py └── README.md /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Graphlet.py: -------------------------------------------------------------------------------- 1 | import networkx as nx 2 | import matplotlib.pyplot as plt 3 | import time 4 | import numpy as np 5 | import pdb 6 | 7 | 8 | class Graphlet: 9 | # class variables 10 | # 3-nodes triangles 11 | open_triangle_dict = {} 12 | close_triangle_dict = {} 13 | 14 | total_close_triangle = [] 15 | total_open_triangle = [] 16 | # 4-nodes 17 | four_path_dict = {} 18 | four_chordal_cycle_dict = {} 19 | four_tailed_triangle_dict = {} 20 | four_clique_dict = {} 21 | four_cycle_dict = {} 22 | three_star_dict = {} 23 | 24 | total_four_path = [] 25 | total_three_star = [] 26 | total_four_cycle = [] 27 | total_four_tailed_triangle = [] 28 | total_four_chordal_cycle = [] 29 | total_four_clique = [] 30 | 31 | # 5-nodes, totally 21 of them 32 | total_five_graphlet = [] 33 | for _ in range(21): 34 | total_five_graphlet.append({}) 35 | 36 | # 6-nodes, totally 112 of them 37 | total_six_graphlet = [] 38 | for _ in range(112): 39 | total_six_graphlet.append({}) 40 | 41 | # 7-nodes, totally 853 of them 42 | total_seven_graphlet = [] 43 | for _ in range(853): 44 | total_seven_graphlet.append({}) 45 | 46 | # initializer 47 | def __init__(self, init_graph): 48 | self.G = init_graph 49 | self._init_all_data() 50 | self._count_triangles() 51 | self._count_4_nodes_global() 52 | self._count_total_5_nodes() 53 | 54 | def show_graph(self): 55 | nx.draw(self.G, with_labels=True) 56 | plt.show() 57 | 58 | # print triangles 59 | def print_triangles(self): 60 | print("close triangle dict:") 61 | print(self.close_triangle_dict) 62 | print("open triangle dict:") 63 | print(self.open_triangle_dict) 64 | 65 | print("total close triangles:") 66 | print(self.total_close_triangle) 67 | print("total open triangles:") 68 | print(self.total_open_triangle) 69 | print("number of total close triangle: %d" % len(self.total_close_triangle)) 70 | print("number of totla open triangle: %d" % len(self.total_open_triangle)) 71 | 72 | def print_4_nodes(self): 73 | ''' 74 | print("4 path dict:") 75 | print(self.four_path_dict) 76 | print("3 star dict:") 77 | print(self.three_star_dict) 78 | print("four cycle dict") 79 | print(self.four_cycle_dict) 80 | print("4 tailed triangle:") 81 | print(self.four_tailed_triangle_dict) 82 | print("4 chordal cycle:") 83 | print(self.four_chordal_cycle_dict) 84 | print("4 clique:") 85 | print(self.four_clique_dict) 86 | ''' 87 | 88 | print("total four path:") 89 | print(len(self.total_four_path)) 90 | print("total three star: ") 91 | print(len(self.total_three_star)) 92 | print("total four cycle: ") 93 | print(len(self.total_four_cycle)) 94 | print("total four tailed triangle:") 95 | print(len(self.total_four_tailed_triangle)) 96 | print("total four chordal cycle:") 97 | print(len(self.total_four_chordal_cycle)) 98 | print("total four clique:") 99 | print(len(self.total_four_clique)) 100 | 101 | def print_5_nodes(self): 102 | print("total five node graphlets") 103 | print(self.total_five_graphlet) 104 | 105 | def print_6_nodes(self): 106 | print("total six node graphlets") 107 | print(self.total_six_graphlet) 108 | 109 | 110 | # add one node and count 3-node graphlets 111 | def add_one_node(self, added_node, connected_nodes): 112 | # add_node 113 | self.G.add_node(added_node) 114 | 115 | # add_edge 116 | for i in connected_nodes: 117 | self.G.add_edge(added_node, i) 118 | 119 | k = added_node 120 | 121 | for i in self.G.neighbors(k): 122 | for j in self.G.neighbors(i): 123 | if self.G.has_edge(j, k): 124 | if i in self.close_triangle_dict: 125 | self.close_triangle_dict[i].append((j, k)) 126 | else: 127 | self.close_triangle_dict[i] = [] 128 | self.close_triangle_dict[i].append((j, k)) 129 | if i < j: 130 | self.total_close_triangle.append((i, j, k)) 131 | 132 | else: 133 | if i in self.open_triangle_dict: 134 | self.open_triangle_dict[i].append((j, k)) 135 | else: 136 | self.open_triangle_dict[i] = [] 137 | self.open_triangle_dict[i].append((j, k)) 138 | 139 | self.total_open_triangle.append((i, j, k)) 140 | 141 | for i in self.G.neighbors(k): 142 | for j in self.G.neighbors(k): 143 | if i < j and not self.G.has_edge(i, j): 144 | if k in self.open_triangle_dict: 145 | self.open_triangle_dict[k].append((i, j)) 146 | else: 147 | self.open_triangle_dict[k] = [] 148 | self.open_triangle_dict[k].append((i, j)) 149 | 150 | self.total_open_triangle.append((k, i, j)) 151 | if i < j and self.G.has_edge(i, j): 152 | if k in self.close_triangle_dict: 153 | self.close_triangle_dict[k].append((i, j)) 154 | else: 155 | self.close_triangle_dict[k] = [] 156 | self.close_triangle_dict[k].append((i, j)) 157 | 158 | 159 | # helper methods 160 | 161 | def _init_all_data(self): 162 | # class variables 163 | # 3-nodes triangles 164 | self.open_triangle_dict = {} 165 | self.close_triangle_dict = {} 166 | 167 | self.total_close_triangle = [] 168 | self.total_open_triangle = [] 169 | # 4-nodes 170 | self.four_path_dict = {} 171 | self.four_chordal_cycle_dict = {} 172 | self.four_tailed_triangle_dict = {} 173 | self.four_clique_dict = {} 174 | self.four_cycle_dict = {} 175 | self.three_star_dict = {} 176 | 177 | self.total_four_path = [] 178 | self.total_three_star = [] 179 | self.total_four_cycle = [] 180 | self.total_four_tailed_triangle = [] 181 | self.total_four_chordal_cycle = [] 182 | self.total_four_clique = [] 183 | 184 | # 5-nodes, totally 21 of them 185 | self.total_five_graphlet = [] 186 | for _ in range(21): 187 | self.total_five_graphlet.append({}) 188 | 189 | # 6-nodes, totally 112 of them 190 | total_six_graphlet = [] 191 | for _ in range(112): 192 | total_six_graphlet.append({}) 193 | 194 | # 7-nodes, totally 853 of them 195 | total_seven_graphlet = [] 196 | for _ in range(853): 197 | total_seven_graphlet.append({}) 198 | 199 | def _add_2_dict(self, dictionary, index, content): 200 | if index not in dictionary: 201 | dictionary[index] = [content] 202 | else: 203 | dictionary[index].append(content) 204 | 205 | # count five total nodes from four total node 206 | def _count_total_5_nodes(self): 207 | ''' 208 | # derive from 3-star 209 | for node_pair in self.total_three_star: 210 | node, node1, node2, node3 = node_pair 211 | for i in self.G.neighbors(node): 212 | # No.1 5 node graphlet 213 | if (i != node1 and i != node2 and i != node3 and i > node3 and not self.G.has_edge(i, node1) 214 | and not self.G.has_edge(i, node2) 215 | and not self.G.has_edge(i, node3)): 216 | # outside nodes from small to large 217 | sorted_list = sorted((node1, node2, node3, i)) 218 | index = (node, sorted_list[0], sorted_list[1], sorted_list[2], sorted_list[3]) 219 | self.total_five_graphlet[0][index] = None 220 | for i in self.G.neighbors(node1): 221 | # No.2 222 | if (i != node and not self.G.has_edge(i, node) and not self.G.has_edge(i, node2) 223 | and not self.G.has_edge(i, node3)): 224 | index = (node, node2, node3, node1, i) 225 | self.total_five_graphlet[1][index] = None 226 | 227 | for i in self.G.neighbors(node2): 228 | # No.2 229 | if (i != node and not self.G.has_edge(i, node) and not self.G.has_edge(i, node1) 230 | and not self.G.has_edge(i, node3)): 231 | index = (node, node1, node3, node2, i) 232 | self.total_five_graphlet[1][index] = None 233 | 234 | for i in self.G.neighbors(node3): 235 | # No.2 236 | if (i != node and not self.G.has_edge(i, node) and not self.G.has_edge(i, node1) 237 | and not self.G.has_edge(i, node2)): 238 | index = (node, node1, node2, node3, i) 239 | self.total_five_graphlet[1][index] = None 240 | 241 | # derive from 3 path 242 | for node_pair in self.total_four_path: 243 | node, node1, node2, node3 = node_pair 244 | for i in self.G.neighbors(node): 245 | pass 246 | for i in self.G.neighbors(node1): 247 | # No.3 248 | if (i != node and node1 < node2 and not self.G.has_edge(node, i) and not self.G.has_edge(i, node2) 249 | and not self.G.has_edge(i, node3)): 250 | self.total_five_graphlet[2][(node, node1, i, node2, node3)] = None 251 | # No.8 252 | if (i != node and self.G.has_edge(i, node1) and self.G.has_edge(i, node3) 253 | and not self.G.has_edge(i, node) and not self.G.has_edge(i, node2)): 254 | if i == sorted((i, node1, node, node3, node2))[0]: 255 | self.total_five_graphlet[7][(i, node1, node, node3, node2)] = None 256 | 257 | for i in self.G.neighbors(node2): 258 | pass 259 | for i in self.G.neighbors(node3): 260 | # No.3 261 | if (i != node2 and node < node3 and not self.G.has_edge(node, i) and not self.G.has_edge(i, node2) 262 | and not self.G.has_edge(i, node1)): 263 | self.total_five_graphlet[2][(node2, node, node1, node3, i)] = None 264 | # No.8 265 | if (i != node2 and self.G.has_edge(i, node1) and self.G.has_edge(i, node3) 266 | and not self.G.has_edge(i, node) and not self.G.has_edge(i, node2)): 267 | if i == sorted((i, node1, node, node3, node2)): 268 | self.total_five_graphlet[7][(i, node1, node, node3, node2)] = None 269 | 270 | # derive from 4-cycle 271 | for node_pair in self.total_four_cycle: 272 | node, node1, node2, node3 = node_pair 273 | for i in self.G.neighbors(node): 274 | # No.7 275 | if (i != node1 and i != node2 and not self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) and 276 | not self.G.has_edge(i, node3)): 277 | self.total_five_graphlet[6][(i, node, node1, node2, node3)] = None 278 | # No.12 279 | if (i != node1 and i != node2 and self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) and 280 | not self.G.has_edge(i, node3)): 281 | self.total_five_graphlet[11][(i, node, node1, node2, node3)] = None 282 | if (i != node1 and i != node2 and not self.G.has_edge(i, node1) and self.G.has_edge(i, node2) and 283 | not self.G.has_edge(i, node3)): 284 | self.total_five_graphlet[11][(i, node, node1, node2, node3)] = None 285 | # No.13 286 | if (i != node1 and i != node2 and not self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) and 287 | self.G.has_edge(node3, i)): 288 | if i == sorted((node1, node2, i))[0]: 289 | self.total_five_graphlet[12][(i, node, node1, node2, node3)] = None 290 | # No.18 291 | if (i != node1 and i != node2 and self.G.has_edge(i, node1) and self.G.has_edge(i, node2) and 292 | G.has_edge(i, node3)): 293 | self.total_five_graphlet[17][(i, node, node1, node2, node3)] = None 294 | 295 | for i in self.G.neighbors(node1): 296 | # No.7 297 | if (i != node and i != node3 and not self.G.has_edge(i, node) and not self.G.has_edge(i, node2) and 298 | not self.G.has_edge(i, node3)): 299 | self.total_five_graphlet[6][(i, node1, node, node3, node2)] = None 300 | # No.13 301 | if (i != node and i != node3 and not self.G.has_edge(i, node) and self.G.has_edge(i, node2) 302 | and not self.G.has_edge(i, node3)): 303 | if i == sorted((i, node, node3))[0]: 304 | self.total_five_graphlet[12][(i, node1, node, node3, node2)] = None 305 | 306 | for i in self.G.neighbors(node2): 307 | # No.7 308 | if (i != node and i != node3 and not self.G.has_edge(i, node) and not self.G.has_edge(i, node1) and 309 | not self.G.has_edge(i, node3)): 310 | self.total_five_graphlet[6][(i, node2, node, node3, node1)] = None 311 | 312 | for i in self.G.neighbors(node3): 313 | # No.7 314 | if (i != node1 and i != node2 and not self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) and 315 | not self.G.has_edge(i, node)): 316 | self.total_five_graphlet[6][(i, node3, node1, node2, node)] = None 317 | # No.12 318 | if (i != node1 and i != node2 and self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) and 319 | not self.G.has_edge(i, node)): 320 | self.total_five_graphlet[11][(i, node3, node1, node2, node)] = None 321 | if (i != node1 and i != node2 and not self.G.has_edge(i, node1) and self.G.has_edge(i, node2) and 322 | not self.G.has_edge(i, node)): 323 | self.total_five_graphlet[11][(i, node3, node1, node2, node)] = None 324 | 325 | # derive from chord triangle 326 | for node_pair in self.total_four_chordal_cycle: 327 | node, node1, node2, node3 = node_pair 328 | for i in self.G.neighbors(node): 329 | # No.10 330 | if (i != node1 and i != node2 and not self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) 331 | and not self.G.has_edge(node3, i)): 332 | self.total_five_graphlet[9][(i, node, node1, node2, node3)] = None 333 | # No.16 334 | if (i != node1 and i != node2 and i < node3 and self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) and 335 | not self.G.has_edge(i, node3)): 336 | self.total_five_graphlet[15][(i, node, node1, node2, node3)] = None 337 | if (i != node1 and i != node2 and i < node3 and not self.G.has_edge(i, node1) and self.G.has_edge(i, node2) and 338 | not self.G.has_edge(i, node3)): 339 | self.total_five_graphlet[15][(i, node, node1, node2, node3)] = None 340 | # No.17 341 | if (i != node1 and i != node2 and not self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) and 342 | self.G.has_edge(node3, i)): 343 | self.total_five_graphlet[16][(i, node, node1, node2, node3)] = None 344 | # No.20 345 | if (i != node1 and i != node2 and self.G.has_edge(i, node1) and self.G.has_edge(i, node2) and 346 | G.has_edge(i, node3)): 347 | if i == sorted((i, node1, node2))[0]: 348 | self.total_five_graphlet[19][(i, node, node1, node2, node3)] = None 349 | for i in self.G.neighbors(node1): 350 | # No.11 351 | if (i != node and i != node3 and i != node2 and not self.G.has_edge(i, node) and not self.G.has_edge(i, node2) and 352 | not self.G.has_edge(i, node3)): 353 | self.total_five_graphlet[10][(i, node1, node, node3, node2)] = None 354 | # No.14 355 | if (i != node and i != node3 and i != node2 and not self.G.has_edge(i, node) and self.G.has_edge(i, node2) 356 | and not self.G.has_edge(i, node3)): 357 | if i == sorted((node, node3, i))[0]: 358 | self.total_five_graphlet[13][(i, node, node1, node2, node3)] = None 359 | for i in self.G.neighbors(node2): 360 | # No.11 361 | if (i != node and i != node3 and i != node1 and not self.G.has_edge(i, node) and not self.G.has_edge(i, node1) and 362 | not self.G.has_edge(i, node3)): 363 | self.total_five_graphlet[10][(i, node2, node, node3, node1)] = None 364 | for i in self.G.neighbors(node3): 365 | # No.10 366 | if (i != node1 and i != node2 and not self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) and 367 | not self.G.has_edge(i, node)): 368 | self.total_five_graphlet[9][(i, node3, node1, node2, node)] = None 369 | # No.16 370 | if (i != node1 and i != node2 and i < node and self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) and 371 | not self.G.has_edge(i, node)): 372 | self.total_five_graphlet[15][(i, node3, node1, node2, node)] = None 373 | if (i != node1 and i != node2 and i < node and not self.G.has_edge(i, node1) and self.G.has_edge(i, node2) and 374 | not self.G.has_edge(i, node)): 375 | self.total_five_graphlet[15][(i, node3, node1, node2, node)] = None 376 | ''' 377 | # derive from 4 clique: 378 | for node_pair in self.total_four_clique: 379 | node, node1, node2, node3 = node_pair 380 | for i in self.G.neighbors(node): 381 | ''' 382 | # No.15, almost same as No.7 383 | if (i != node1 and i != node2 and i != node3 and not self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) and 384 | not self.G.has_edge(i, node3)): 385 | self.total_five_graphlet[14][(i, node, node1, node2, node3)] = None 386 | # No.19, almost same as No.12 387 | if (i != node1 and i != node2 and i != node3 and self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) and 388 | not self.G.has_edge(i, node3)): 389 | self.total_five_graphlet[18][(i, node, node1, node2, node3)] = None 390 | if (i != node1 and i != node2 and i != node3 and not self.G.has_edge(i, node1) and self.G.has_edge(i, node2) and 391 | not self.G.has_edge(i, node3)): 392 | self.total_five_graphlet[18][(i, node, node1, node2, node3)] = None 393 | ''' 394 | # No.21 395 | if (i != node1 and i != node2 and i != node3 and self.G.has_edge(i, node1) and self.G.has_edge(i, node2) 396 | and self.G.has_edge(i, node3)): 397 | if i == sorted((i, node, node1, node2, node3))[0]: 398 | self.total_five_graphlet[20][(i, node, node1, node2, node3)] = None 399 | 400 | ''' 401 | for i in self.G.neighbors(node1): 402 | # No.15, almost same as No.7 403 | if (i != node and i != node3 and i != node2 and not self.G.has_edge(i, node) and not self.G.has_edge(i, node2) and 404 | not self.G.has_edge(i, node3)): 405 | self.total_five_graphlet[14][(i, node1, node, node3, node2)] = None 406 | 407 | 408 | for i in self.G.neighbors(node2): 409 | # No.15, almost same as No.7 410 | if (i != node and i != node3 and i != node2 and not self.G.has_edge(i, node) and not self.G.has_edge(i, node1) and 411 | not self.G.has_edge(i, node3)): 412 | self.total_five_graphlet[14][(i, node2, node, node3, node1)] = None 413 | 414 | for i in self.G.neighbors(node3): 415 | # No.15, almost same as No.7 416 | if (i != node1 and i != node2 and i != node and not self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) and 417 | not self.G.has_edge(i, node)): 418 | self.total_five_graphlet[14][(i, node3, node1, node2, node)] = None 419 | # No.19 almost same as No.12 420 | if (i != node1 and i != node2 and i != node and self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) and 421 | not self.G.has_edge(i, node)): 422 | self.total_five_graphlet[18][(i, node3, node1, node2, node)] = None 423 | if (i != node1 and i != node2 and i != node and not self.G.has_edge(i, node1) and self.G.has_edge(i, node2) and 424 | not self.G.has_edge(i, node)): 425 | self.total_five_graphlet[18][(i, node3, node1, node2, node)] = None 426 | ''' 427 | 428 | 429 | 430 | 431 | 432 | 433 | # derive from tailed triangle 434 | for node_pair in self.total_four_tailed_triangle: 435 | node, node1, node2, node3 = node_pair 436 | # No.4 437 | for i in self.G.neighbors(node): 438 | # No.6 439 | if (i != node1 and i != node2 and i < node3 and not self.G.has_edge(i, node1) and not self.G.has_edge(i, node2) 440 | and not self.G.has_edge(i, node3)): 441 | self.total_five_graphlet[5][(node1, node, i, node2, node3)] = None 442 | for i in self.G.neighbors(node1): 443 | # No.6 444 | if (i != node and i != node2 and i < node3 and not self.G.has_edge(i, node) and not self.G.has_edge(i, node2) 445 | and not self.G.has_edge(i, node3)): 446 | self.total_five_graphlet[5][(node, node1, i, node2, node3)] = None 447 | for i in self.G.neighbors(node2): 448 | # No.6 449 | if (i != node and i != node1 and i > node3 and not self.G.has_edge(i, node) 450 | and not self.G.has_edge(i, node1) and not self.G.has_edge(i, node3)): 451 | self.total_five_graphlet[3][(node, node1, node2, node3, i)] = None 452 | # No.9 453 | if (i != node and i != node1 and i > node3 and node3 > node and not self.G.has_edge(i, node) 454 | and not self.G.has_edge(i, node1) and self.G.has_edge(i, node3)): 455 | self.total_five_graphlet[8][(node, node1, node2, node3, i)] = None 456 | for i in self.G.neighbors(node3): 457 | # No.5 458 | if (i != node2 and not self.G.has_edge(node, i) and not self.G.has_edge(node1, i) 459 | and not self.G.has_edge(node2, i)): 460 | self.total_five_graphlet[4][(node, node1, node2, node3, i)] = None 461 | 462 | # this function only generate global counting 463 | def _count_4_nodes_global(self): 464 | # derive from close triangles dict 465 | for node_pairs in self.total_close_triangle: 466 | (node, node1, node2) = node_pairs 467 | ''' 468 | for i in self.G.neighbors(node1): 469 | # 4 tailed triangle 470 | if i != node2 and i != node and not self.G.has_edge(i, node2) and not self.G.has_edge(i, node): 471 | self.total_four_tailed_triangle.append((node, node2, node1, i)) 472 | # 4-chordal cycle 473 | if i != node and self.G.has_edge(i, node2) and not self.G.has_edge(i, node): 474 | if node < i: 475 | self.total_four_chordal_cycle.append((node, node1, node2, i)) 476 | for i in self.G.neighbors(node2): 477 | # 4 tailed triangle 478 | if i != node1 and i != node and not self.G.has_edge(i, node1) and not self.G.has_edge(i, node): 479 | self.total_four_tailed_triangle.append((node, node1, node2, i)) 480 | # 4 chordal cycle 481 | if i != node and i != node1 and self.G.has_edge(i, node) and not self.G.has_edge(i, node1): 482 | if node1 < i: 483 | self.total_four_chordal_cycle.append((node1, node, node2, i)) 484 | ''' 485 | for i in self.G.neighbors(node): 486 | ''' 487 | # 4 tailed triangle 488 | if i != node1 and i != node2 and not self.G.has_edge(i, node1) and not self.G.has_edge(i, node2): 489 | self.total_four_tailed_triangle.append((node1, node2, node, i)) 490 | ''' 491 | # 4 clique 492 | if self.G.has_edge(i, node1) and self.G.has_edge(i, node2): 493 | if node < node1 < node2 < i: 494 | self.total_four_clique.append((node, node1, node2, i)) 495 | ''' 496 | # 4 chordal cycle 497 | if i != node1 and i != node2 and self.G.has_edge(i, node1) and not self.G.has_edge(i, node2): 498 | if node2 < i: 499 | self.total_four_chordal_cycle.append((node2, node, node1, i)) 500 | ''' 501 | 502 | ''' 503 | # derive from open triangles 504 | for node_pairs in self.total_open_triangle: 505 | (node, node1, node2) = node_pairs 506 | for i in self.G.neighbors(node1): 507 | # 4-path, small node first 508 | if not self.G.has_edge(node2, i) and not self.G.has_edge(node, i): 509 | # eliminate duplication 510 | if node < node1: 511 | self.total_four_path.append((node, node2, node1, i)) 512 | # 4-cycle, small node first 513 | if i != node and self.G.has_edge(node2, i) and not self.G.has_edge(node, i): 514 | if node < i and node < node1 and node < node2: 515 | self.total_four_cycle.append((node, node1, node2, i)) 516 | 517 | for i in self.G.neighbors(node2): 518 | # 4-path, small node first 519 | if not self.G.has_edge(node1, i) and not self.G.has_edge(node, i): 520 | # eliminate duplication 521 | if node < node2: 522 | self.total_four_path.append((node, node1, node2, i)) 523 | for i in self.G.neighbors(node): 524 | # 3-star 525 | if node1 < node2 < i and not self.G.has_edge(node1, i) and not self.G.has_edge(node2, i): 526 | # eliminate duplication: from small to big index 527 | self.total_three_star.append((node, node1, node2, i)) 528 | ''' 529 | # this function must be after _count_trianlges function 530 | def _count_4_nodes(self): 531 | # derive from close triangles dict 532 | for node in self.close_triangle_dict: 533 | for node_pairs in self.close_triangle_dict[node]: 534 | (node1, node2) = node_pairs 535 | for i in self.G.neighbors(node1): 536 | # 4 tailed triangle 537 | if i != node2 and not self.G.has_edge(i, node2) and not self.G.has_edge(i, node): 538 | self._add_2_dict(self.four_tailed_triangle_dict, node, (node2, node1, i)) 539 | if node < node2: 540 | self.total_four_tailed_triangle.append((node, node2, node1, i)) 541 | # 4-chordal cycle 542 | if i != node and self.G.has_edge(i, node2) and not self.G.has_edge(i, node): 543 | self._add_2_dict(self.four_chordal_cycle_dict, node, (node1, node2, i)) 544 | if node < i: 545 | self.total_four_chordal_cycle.append((node, node1, node2, i)) 546 | for i in self.G.neighbors(node2): 547 | # 4 tailed triangle 548 | if i != node1 and not self.G.has_edge(i, node1) and not self.G.has_edge(i, node): 549 | self._add_2_dict(self.four_tailed_triangle_dict, node, (node1, node2, i)) 550 | if node < node1: 551 | self.total_four_tailed_triangle.append((node, node1, node2, i)) 552 | for i in self.G.neighbors(node): 553 | # 4-clique 554 | if self.G.has_edge(i, node1) and self.G.has_edge(i, node2): 555 | if node1 < node2 < i: 556 | self._add_2_dict(self.four_clique_dict, node, (node1, node2, i)) 557 | if node < node1 < node2 < i: 558 | self.total_four_clique.append((node, node1, node2, i)) 559 | 560 | # derive from open triangles 561 | for node in self.open_triangle_dict: 562 | for node_pairs in self.open_triangle_dict[node]: 563 | (node1, node2) = node_pairs 564 | for i in self.G.neighbors(node1): 565 | # 4-path, small node first 566 | if not self.G.has_edge(node2, i) and not self.G.has_edge(node, i): 567 | self._add_2_dict(self.four_path_dict, node, (node2, node1, i)) 568 | # eliminate duplication 569 | if node < node1: 570 | self.total_four_path.append((node, node2, node1, i)) 571 | # 4-cycle, small node first 572 | if i != node and self.G.has_edge(node2, i) and not self.G.has_edge(node, i): 573 | self._add_2_dict(self.four_cycle_dict, node, (node1, node2, i)) 574 | if node < i and node < node1 and node < node2: 575 | self.total_four_cycle.append((node, node1, node2, i)) 576 | 577 | for i in self.G.neighbors(node2): 578 | # 4-path, small node first 579 | if not self.G.has_edge(node1, i) and not self.G.has_edge(node, i): 580 | self._add_2_dict(self.four_path_dict, node, (node1, node2, i)) 581 | # eliminate duplication 582 | if node < node2: 583 | self.total_four_path.append((node, node1, node2, i)) 584 | for i in self.G.neighbors(node): 585 | # 3-star 586 | if node1 < node2 < i and not self.G.has_edge(node1, i) and not self.G.has_edge(node2, i): 587 | # eliminate duplication: from small to big index 588 | self._add_2_dict(self.three_star_dict, node, (node1, node2, i)) 589 | self.total_three_star.append((node, node1, node2, i)) 590 | 591 | def _count_triangles(self): 592 | num_node = nx.number_of_nodes(self.G) 593 | for k in range(num_node): 594 | for i in self.G.neighbors(k): 595 | for j in self.G.neighbors(k): 596 | if i < j: 597 | # There is a close triangle 598 | if self.G.has_edge(i, j): 599 | if k in self.close_triangle_dict: 600 | self.close_triangle_dict[k].append((i, j)) 601 | else: 602 | self.close_triangle_dict[k] = [] 603 | self.close_triangle_dict[k].append((i, j)) 604 | 605 | if k < i: 606 | self.total_close_triangle.append((k, i, j)) 607 | 608 | # There is an open triangle 609 | else: 610 | if k in self.open_triangle_dict: 611 | self.open_triangle_dict[k].append((i, j)) 612 | else: 613 | self.open_triangle_dict[k] = [] 614 | self.open_triangle_dict[k].append((i, j)) 615 | 616 | self.total_open_triangle.append((k, i, j)) 617 | 618 | # main function 619 | if __name__ == "__main__": 620 | G = nx.Graph() 621 | ''' 622 | G.add_edges_from( 623 | [(0, 3), (1, 3), (1, 4), (1, 7), (2, 3), (2, 4), (2, 5), (2, 7), (3, 4), (3, 5), (3, 6), (4, 5), (4, 6), 624 | (4, 7),(5, 6)]) 625 | ''' 626 | # G.add_edges_from([(0, 1), (0, 2), (0,3), (0,4), (3, 5), (5, 9), (5, 8), (5, 7), (5, 6)]) 627 | ''' 628 | size = 10 629 | for i in range(7): 630 | start = time.time() 631 | G = nx.fast_gnp_random_graph(size, 0.5, seed=0) 632 | graphlet = Graphlet(G) 633 | end = time.time() 634 | print("%d sized graph: %f" % (size, end - start)) 635 | size = size * 2 636 | ''' 637 | G = nx.fast_gnp_random_graph(100, 0.4, seed=0) 638 | #G = nx.barabasi_albert_graph(100, 3, seed=0) 639 | graphlet = Graphlet(G) 640 | graphlet.print_triangles() 641 | print("\n") 642 | graphlet.print_4_nodes() 643 | print("\n") 644 | print(len(graphlet.total_five_graphlet[20])) 645 | ''' 646 | count = 1 647 | for d in graphlet.total_five_graphlet: 648 | print("%dth graphlet: %d" % (count, len(d))) 649 | print(d) 650 | count = count + 1 651 | graphlet.show_graph() 652 | ''' 653 | 654 | 655 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | "# graphlet_counting" 2 | --------------------------------------------------------------------------------