You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

utils.py 6.7 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import networkx as nx
  2. import numpy as np
  3. #from itertools import product
  4. # from tqdm import tqdm
  5. def getSPLengths(G1):
  6. sp = nx.shortest_path(G1)
  7. distances = np.zeros((G1.number_of_nodes(), G1.number_of_nodes()))
  8. for i in sp.keys():
  9. for j in sp[i].keys():
  10. distances[i, j] = len(sp[i][j]) - 1
  11. return distances
  12. def getSPGraph(G, edge_weight=None):
  13. """Transform graph G to its corresponding shortest-paths graph.
  14. Parameters
  15. ----------
  16. G : NetworkX graph
  17. The graph to be tramsformed.
  18. edge_weight : string
  19. edge attribute corresponding to the edge weight.
  20. Return
  21. ------
  22. S : NetworkX graph
  23. The shortest-paths graph corresponding to G.
  24. Notes
  25. ------
  26. For an input graph G, its corresponding shortest-paths graph S contains the same set of nodes as G, while there exists an edge between all nodes in S which are connected by a walk in G. Every edge in S between two nodes is labeled by the shortest distance between these two nodes.
  27. References
  28. ----------
  29. [1] Borgwardt KM, Kriegel HP. Shortest-path kernels on graphs. InData Mining, Fifth IEEE International Conference on 2005 Nov 27 (pp. 8-pp). IEEE.
  30. """
  31. return floydTransformation(G, edge_weight=edge_weight)
  32. def floydTransformation(G, edge_weight=None):
  33. """Transform graph G to its corresponding shortest-paths graph using Floyd-transformation.
  34. Parameters
  35. ----------
  36. G : NetworkX graph
  37. The graph to be tramsformed.
  38. edge_weight : string
  39. edge attribute corresponding to the edge weight. The default edge weight is bond_type.
  40. Return
  41. ------
  42. S : NetworkX graph
  43. The shortest-paths graph corresponding to G.
  44. References
  45. ----------
  46. [1] Borgwardt KM, Kriegel HP. Shortest-path kernels on graphs. InData Mining, Fifth IEEE International Conference on 2005 Nov 27 (pp. 8-pp). IEEE.
  47. """
  48. spMatrix = nx.floyd_warshall_numpy(G, weight=edge_weight)
  49. S = nx.Graph()
  50. S.add_nodes_from(G.nodes(data=True))
  51. ns = list(G.nodes())
  52. for i in range(0, G.number_of_nodes()):
  53. for j in range(i + 1, G.number_of_nodes()):
  54. if spMatrix[i, j] != np.inf:
  55. S.add_edge(ns[i], ns[j], cost=spMatrix[i, j])
  56. return S
  57. def untotterTransformation(G, node_label, edge_label):
  58. """Transform graph G according to Mahé et al.'s work to filter out tottering patterns of marginalized kernel and tree pattern kernel.
  59. Parameters
  60. ----------
  61. G : NetworkX graph
  62. The graph to be tramsformed.
  63. node_label : string
  64. node attribute used as label. The default node label is 'atom'.
  65. edge_label : string
  66. edge attribute used as label. The default edge label is 'bond_type'.
  67. Return
  68. ------
  69. gt : NetworkX graph
  70. The transformed graph corresponding to G.
  71. References
  72. ----------
  73. [1] Pierre Mahé, Nobuhisa Ueda, Tatsuya Akutsu, Jean-Luc Perret, and Jean-Philippe Vert. Extensions of marginalized graph kernels. In Proceedings of the twenty-first international conference on Machine learning, page 70. ACM, 2004.
  74. """
  75. # arrange all graphs in a list
  76. G = G.to_directed()
  77. gt = nx.Graph()
  78. gt.graph = G.graph
  79. gt.add_nodes_from(G.nodes(data=True))
  80. for edge in G.edges():
  81. gt.add_node(edge)
  82. gt.node[edge].update({node_label: G.node[edge[1]][node_label]})
  83. gt.add_edge(edge[0], edge)
  84. gt.edges[edge[0], edge].update({
  85. edge_label:
  86. G[edge[0]][edge[1]][edge_label]
  87. })
  88. for neighbor in G[edge[1]]:
  89. if neighbor != edge[0]:
  90. gt.add_edge(edge, (edge[1], neighbor))
  91. gt.edges[edge, (edge[1], neighbor)].update({
  92. edge_label:
  93. G[edge[1]][neighbor][edge_label]
  94. })
  95. # nx.draw_networkx(gt)
  96. # plt.show()
  97. # relabel nodes using consecutive integers for convenience of kernel calculation.
  98. gt = nx.convert_node_labels_to_integers(
  99. gt, first_label=0, label_attribute='label_orignal')
  100. return gt
  101. def direct_product(G1, G2, node_label, edge_label):
  102. """Return the direct/tensor product of directed graphs G1 and G2.
  103. Parameters
  104. ----------
  105. G1, G2 : NetworkX graph
  106. The original graphs.
  107. node_label : string
  108. node attribute used as label. The default node label is 'atom'.
  109. edge_label : string
  110. edge attribute used as label. The default edge label is 'bond_type'.
  111. Return
  112. ------
  113. gt : NetworkX graph
  114. The direct product graph of G1 and G2.
  115. Notes
  116. -----
  117. This method differs from networkx.tensor_product in that this method only adds nodes and edges in G1 and G2 that have the same labels to the direct product graph.
  118. References
  119. ----------
  120. [1] Thomas Gärtner, Peter Flach, and Stefan Wrobel. On graph kernels: Hardness results and efficient alternatives. Learning Theory and Kernel Machines, pages 129–143, 2003.
  121. """
  122. # arrange all graphs in a list
  123. from itertools import product
  124. # G = G.to_directed()
  125. gt = nx.DiGraph()
  126. # add nodes
  127. for u, v in product(G1, G2):
  128. if G1.nodes[u][node_label] == G2.nodes[v][node_label]:
  129. gt.add_node((u, v))
  130. gt.nodes[(u, v)].update({node_label: G1.nodes[u][node_label]})
  131. # add edges, faster for sparse graphs (no so many edges), which is the most case for now.
  132. for (u1, v1), (u2, v2) in product(G1.edges, G2.edges):
  133. if (u1, u2) in gt and (
  134. v1, v2
  135. ) in gt and G1.edges[u1, v1][edge_label] == G2.edges[u2,
  136. v2][edge_label]:
  137. gt.add_edge((u1, u2), (v1, v2))
  138. gt.edges[(u1, u2), (v1, v2)].update({
  139. edge_label:
  140. G1.edges[u1, v1][edge_label]
  141. })
  142. # # add edges, faster for dense graphs (a lot of edges, complete graph would be super).
  143. # for u, v in product(gt, gt):
  144. # if (u[0], v[0]) in G1.edges and (
  145. # u[1], v[1]
  146. # ) in G2.edges and G1.edges[u[0],
  147. # v[0]][edge_label] == G2.edges[u[1],
  148. # v[1]][edge_label]:
  149. # gt.add_edge((u[0], u[1]), (v[0], v[1]))
  150. # gt.edges[(u[0], u[1]), (v[0], v[1])].update({
  151. # edge_label:
  152. # G1.edges[u[0], v[0]][edge_label]
  153. # })
  154. # relabel nodes using consecutive integers for convenience of kernel calculation.
  155. # gt = nx.convert_node_labels_to_integers(
  156. # gt, first_label=0, label_attribute='label_orignal')
  157. return gt

A Python package for graph kernels, graph edit distances and graph pre-image problem.