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.

run_treeletkernel_acyclic-checkpoint.ipynb 57 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. {
  2. "cells": [
  3. {
  4. "cell_type": "code",
  5. "execution_count": 1,
  6. "metadata": {},
  7. "outputs": [
  8. {
  9. "name": "stdout",
  10. "output_type": "stream",
  11. "text": [
  12. "\n",
  13. " --- This is a regression problem ---\n",
  14. "\n",
  15. "\n",
  16. " Loading dataset from file...\n",
  17. "\n",
  18. " Calculating kernel matrix, this could take a while...\n",
  19. "\n",
  20. " --- treelet kernel matrix of size 185 built in 0.47543811798095703 seconds ---\n",
  21. "[[4.00000000e+00 2.60653066e+00 1.00000000e+00 ... 1.26641655e-14\n",
  22. " 1.26641655e-14 1.26641655e-14]\n",
  23. " [2.60653066e+00 6.00000000e+00 1.00000000e+00 ... 1.26641655e-14\n",
  24. " 1.26641655e-14 1.26641655e-14]\n",
  25. " [1.00000000e+00 1.00000000e+00 4.00000000e+00 ... 3.00000000e+00\n",
  26. " 3.00000000e+00 3.00000000e+00]\n",
  27. " ...\n",
  28. " [1.26641655e-14 1.26641655e-14 3.00000000e+00 ... 1.80000000e+01\n",
  29. " 1.30548713e+01 8.19020657e+00]\n",
  30. " [1.26641655e-14 1.26641655e-14 3.00000000e+00 ... 1.30548713e+01\n",
  31. " 2.20000000e+01 9.71901120e+00]\n",
  32. " [1.26641655e-14 1.26641655e-14 3.00000000e+00 ... 8.19020657e+00\n",
  33. " 9.71901120e+00 1.60000000e+01]]\n",
  34. "\n",
  35. " Starting calculate accuracy/rmse...\n",
  36. "calculate performance: 98%|█████████▊| 983/1000 [00:01<00:00, 796.45it/s]\n",
  37. " Mean performance on train set: 2.688029\n",
  38. "With standard deviation: 1.541623\n",
  39. "\n",
  40. " Mean performance on test set: 10.099738\n",
  41. "With standard deviation: 5.035844\n",
  42. "calculate performance: 100%|██████████| 1000/1000 [00:01<00:00, 745.11it/s]\n",
  43. "\n",
  44. "\n",
  45. " rmse_test std_test rmse_train std_train k_time\n",
  46. "----------- ---------- ------------ ----------- --------\n",
  47. " 10.0997 5.03584 2.68803 1.54162 0.475438\n"
  48. ]
  49. }
  50. ],
  51. "source": [
  52. "%load_ext line_profiler\n",
  53. "\n",
  54. "import sys\n",
  55. "sys.path.insert(0, \"../\")\n",
  56. "from pygraph.utils.utils import kernel_train_test\n",
  57. "from pygraph.kernels.treeletKernel import treeletkernel\n",
  58. "\n",
  59. "datafile = '../../../../datasets/acyclic/Acyclic/dataset_bps.ds'\n",
  60. "kernel_file_path = 'kernelmatrices_path_acyclic/'\n",
  61. "\n",
  62. "kernel_para = dict(node_label = 'atom', edge_label = 'bond_type', labeled = True)\n",
  63. "\n",
  64. "kernel_train_test(datafile, kernel_file_path, treeletkernel, kernel_para, normalize = False)\n",
  65. "\n",
  66. "# %lprun -f treeletkernel \\\n",
  67. "# kernel_train_test(datafile, kernel_file_path, treeletkernel, kernel_para, normalize = False)"
  68. ]
  69. },
  70. {
  71. "cell_type": "code",
  72. "execution_count": null,
  73. "metadata": {},
  74. "outputs": [],
  75. "source": [
  76. "# results\n",
  77. "\n",
  78. "# with y normalization\n",
  79. " RMSE_test std_test RMSE_train std_train k_time\n",
  80. "----------- ---------- ------------ ----------- --------\n",
  81. " 8.3079 3.37838 2.90887 1.2679 0.500302\n",
  82. "\n",
  83. "# without y normalization\n",
  84. " RMSE_test std_test RMSE_train std_train k_time\n",
  85. "----------- ---------- ------------ ----------- --------\n",
  86. " 10.0997 5.03584 2.68803 1.54162 0.484171\n",
  87. "\n",
  88. " \n",
  89. "\n",
  90. "# G0 -> WL subtree h = 0\n",
  91. " rmse_test std_test rmse_train std_train k_time\n",
  92. "----------- ---------- ------------ ----------- --------\n",
  93. " 13.9223 2.88611 13.373 0.653301 0.186731\n",
  94. "\n",
  95. "# G0 U G1 U G6 U G8 U G13 -> WL subtree h = 1\n",
  96. " rmse_test std_test rmse_train std_train k_time\n",
  97. "----------- ---------- ------------ ----------- --------\n",
  98. " 8.97706 2.90771 6.7343 1.17505 0.223171\n",
  99. " \n",
  100. "# all patterns \\ { G3 U G4 U G5 U G10 } -> WL subtree h = 2 \n",
  101. " rmse_test std_test rmse_train std_train k_time\n",
  102. "----------- ---------- ------------ ----------- --------\n",
  103. " 7.31274 1.96289 3.73909 0.406267 0.294902\n",
  104. "\n",
  105. "# all patterns \\ { G4 U G5 } -> WL subtree h = 3\n",
  106. " rmse_test std_test rmse_train std_train k_time\n",
  107. "----------- ---------- ------------ ----------- --------\n",
  108. " 8.39977 2.78309 3.8606 1.58686 0.348912\n",
  109. "\n",
  110. "# all patterns \\ { G5 } \n",
  111. " rmse_test std_test rmse_train std_train k_time\n",
  112. "----------- ---------- ------------ ----------- --------\n",
  113. " 9.47647 4.22113 3.18029 1.5669 0.423638\n",
  114. " \n",
  115. " \n",
  116. " \n",
  117. "# G0, -> WL subtree h = 0\n",
  118. " rmse_test std_test rmse_train std_train k_time\n",
  119. "----------- ---------- ------------ ----------- --------\n",
  120. " 13.9223 2.88611 13.373 0.653301 0.186731 \n",
  121. " \n",
  122. "# G0 U G1 U G2 U G6 U G8 U G13 -> WL subtree h = 1\n",
  123. " rmse_test std_test rmse_train std_train k_time\n",
  124. "----------- ---------- ------------ ----------- --------\n",
  125. " 8.62431 2.54327 5.63422 0.255002 0.290797\n",
  126. " \n",
  127. "# all patterns \\ { G5 U G10 } -> WL subtree h = 2\n",
  128. " rmse_test std_test rmse_train std_train k_time\n",
  129. "----------- ---------- ------------ ----------- --------\n",
  130. " 10.1294 3.50275 3.69664 1.55116 0.418498"
  131. ]
  132. },
  133. {
  134. "cell_type": "code",
  135. "execution_count": 3,
  136. "metadata": {
  137. "scrolled": true
  138. },
  139. "outputs": [
  140. {
  141. "name": "stdout",
  142. "output_type": "stream",
  143. "text": [
  144. "{0: 'C', 1: 'C', 2: 'C', 3: 'C', 4: 'C', 5: 'O', 6: 'O'}\n"
  145. ]
  146. },
  147. {
  148. "data": {
  149. "image/png": "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\n",
  150. "text/plain": [
  151. "<matplotlib.figure.Figure at 0x7f23a4d68ef0>"
  152. ]
  153. },
  154. "metadata": {},
  155. "output_type": "display_data"
  156. },
  157. {
  158. "name": "stdout",
  159. "output_type": "stream",
  160. "text": [
  161. "{0: 'C', 1: 'C', 2: 'C', 3: 'C', 4: 'C', 5: 'C', 6: 'O', 7: 'O'}\n"
  162. ]
  163. },
  164. {
  165. "data": {
  166. "image/png": "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\n",
  167. "text/plain": [
  168. "<matplotlib.figure.Figure at 0x7f23a02cfac8>"
  169. ]
  170. },
  171. "metadata": {},
  172. "output_type": "display_data"
  173. },
  174. {
  175. "name": "stdout",
  176. "output_type": "stream",
  177. "text": [
  178. "\n",
  179. " pattern 0: [0, 1, 2, 3, 4, 5, 6, 7]\n",
  180. " treelet 0: ['C', 'C', 'C', 'C', 'C', 'C', 'O', 'O']\n",
  181. "\n",
  182. " pattern 1 : [[4, 0], [4, 1], [5, 4], [6, 2], [6, 5], [7, 3], [7, 5]]\n",
  183. " treelet 1 : ['1C1C', '1C1C', '1C1C', '1C1O', '1C1O', '1C1O', '1C1O']\n",
  184. "\n",
  185. " pattern 2 : [[1, 4, 0], [5, 4, 0], [5, 4, 1], [5, 6, 2], [5, 7, 3], [6, 5, 4], [7, 5, 4], [7, 5, 6]]\n",
  186. " treelet 2 : ['2C1C1C', '2C1C1C', '2C1C1C', '2C1O1C', '2C1O1C', '2C1C1O', '2C1C1O', '2O1C1O']\n",
  187. "\n",
  188. " pattern 3 : [[4, 5, 6, 2], [4, 5, 7, 3], [6, 5, 4, 0], [6, 5, 4, 1], [6, 5, 7, 3], [7, 5, 4, 0], [7, 5, 4, 1], [7, 5, 6, 2]]\n",
  189. " treelet 3 : ['3C1C1O1C', '3C1C1O1C', '3C1C1C1O', '3C1C1C1O', '3C1O1C1O', '3C1C1C1O', '3C1C1C1O', '3C1O1C1O']\n",
  190. "\n",
  191. " pattern 4 : [[2, 6, 5, 4, 0], [2, 6, 5, 4, 1], [3, 7, 5, 4, 0], [3, 7, 5, 4, 1], [3, 7, 5, 6, 2]]\n",
  192. " treelet 4 : ['4C1C1C1O1C', '4C1C1C1O1C', '4C1C1C1O1C', '4C1C1C1O1C', '4C1O1C1O1C']\n",
  193. "\n",
  194. " pattern 5 : []\n",
  195. " treelet 5 : []\n",
  196. "\n",
  197. " pattern 3 star: [[4, 0, 1, 5], [5, 4, 6, 7]]\n",
  198. " treelet 3 star: ['6CC1C1C1', '6CC1O1O1']\n",
  199. "\n",
  200. " pattern 4 star: []\n",
  201. " treelet 4 star: []\n",
  202. "\n",
  203. " pattern 5 star: []\n",
  204. " treelet 5 star: []\n",
  205. "\n",
  206. " pattern 7: [[4, 0, 1, 5, 6], [4, 0, 1, 5, 7], [5, 7, 6, 4, 0], [5, 7, 6, 4, 1], [5, 4, 7, 6, 2], [5, 4, 6, 7, 3]]\n",
  207. " treelet 7: ['7CC1C1C1O1', '7CC1C1C1O1', '7CO1O1C1C1', '7CO1O1C1C1', '7CC1O1O1C1', '7CC1O1O1C1']\n",
  208. "\n",
  209. " pattern 11: []\n",
  210. " treelet 11: []\n",
  211. "\n",
  212. " pattern 10: [[4, 0, 1, 5, 6, 2], [4, 0, 1, 5, 7, 3]]\n",
  213. " treelet 10: ['aCO1C1C1C1C1', 'aCO1C1C1C1C1']\n",
  214. "\n",
  215. " pattern 12: [[4, 0, 1, 5, 7, 6]]\n",
  216. " treelet 12: ['cCC1C1C1O1O1']\n",
  217. "\n",
  218. " pattern 9: [[5, 7, 6, 4, 2, 0], [5, 7, 6, 4, 2, 1], [5, 6, 7, 4, 3, 0], [5, 6, 7, 4, 3, 1], [5, 4, 7, 6, 3, 2]]\n",
  219. " treelet 9: ['9CO1C1O1C1C1', '9CO1C1O1C1C1', '9CO1C1O1C1C1', '9CO1C1O1C1C1', '9CC1O1O1C1C1']\n",
  220. "\n",
  221. " numbers of canonical keys: {'2O1C1O': 1, '7CC1C1C1O1': 2, '7CC1O1O1C1': 2, 'aCO1C1C1C1C1': 2, '2C1C1C': 3, '6CC1C1C1': 1, '9CO1C1O1C1C1': 4, '1C1C': 3, '3C1C1C1O': 4, '4C1C1C1O1C': 4, '7CO1O1C1C1': 2, '2C1C1O': 2, '1C1O': 4, '9CC1O1O1C1C1': 1, '3C1C1O1C': 2, '6CC1O1O1': 1, '2C1O1C': 2, '0O': 2, '4C1O1C1O1C': 1, 'cCC1C1C1O1O1': 1, '0C': 6, '3C1O1C1O': 2}\n",
  222. "\n",
  223. " pattern 0: [0, 1, 2, 3, 4, 5, 6]\n",
  224. " treelet 0: ['C', 'C', 'C', 'C', 'C', 'O', 'O']\n",
  225. "\n",
  226. " pattern 1 : [[2, 0], [3, 1], [5, 2], [5, 4], [6, 3], [6, 4]]\n",
  227. " treelet 1 : ['1C1C', '1C1C', '1C1O', '1C1O', '1C1O', '1C1O']\n",
  228. "\n",
  229. " pattern 2 : [[4, 5, 2], [4, 6, 3], [5, 2, 0], [6, 3, 1], [6, 4, 5]]\n",
  230. " treelet 2 : ['2C1O1C', '2C1O1C', '2C1C1O', '2C1C1O', '2O1C1O']\n",
  231. "\n",
  232. " pattern 3 : [[4, 5, 2, 0], [4, 6, 3, 1], [5, 4, 6, 3], [6, 4, 5, 2]]\n",
  233. " treelet 3 : ['3C1C1O1C', '3C1C1O1C', '3C1O1C1O', '3C1O1C1O']\n",
  234. "\n",
  235. " pattern 4 : [[3, 6, 4, 5, 2], [5, 4, 6, 3, 1], [6, 4, 5, 2, 0]]\n",
  236. " treelet 4 : ['4C1O1C1O1C', '4C1C1O1C1O', '4C1C1O1C1O']\n",
  237. "\n",
  238. " pattern 5 : [[2, 5, 4, 6, 3, 1], [3, 6, 4, 5, 2, 0]]\n",
  239. " treelet 5 : ['5C1C1O1C1O1C', '5C1C1O1C1O1C']\n",
  240. "\n",
  241. " pattern 3 star: []\n",
  242. " treelet 3 star: []\n",
  243. "\n",
  244. " pattern 4 star: []\n",
  245. " treelet 4 star: []\n",
  246. "\n",
  247. " pattern 5 star: []\n",
  248. " treelet 5 star: []\n",
  249. "\n",
  250. " pattern 7: []\n",
  251. " treelet 7: []\n",
  252. "\n",
  253. " pattern 11: []\n",
  254. " treelet 11: []\n",
  255. "\n",
  256. " pattern 10: []\n",
  257. " treelet 10: []\n",
  258. "\n",
  259. " pattern 12: []\n",
  260. " treelet 12: []\n",
  261. "\n",
  262. " pattern 9: []\n",
  263. " treelet 9: []\n",
  264. "\n",
  265. " numbers of canonical keys: {'3C1C1O1C': 2, '2O1C1O': 1, '1C1O': 4, '2C1O1C': 2, '0O': 2, '5C1C1O1C1O1C': 2, '1C1C': 2, '4C1O1C1O1C': 1, '0C': 5, '3C1O1C1O': 2, '4C1C1O1C1O': 2, '2C1C1O': 2}\n"
  266. ]
  267. }
  268. ],
  269. "source": [
  270. "import sys\n",
  271. "import pathlib\n",
  272. "from collections import Counter\n",
  273. "from itertools import chain\n",
  274. "sys.path.insert(0, \"../\")\n",
  275. "\n",
  276. "import networkx as nx\n",
  277. "import numpy as np\n",
  278. "import time\n",
  279. "\n",
  280. "from sklearn.metrics.pairwise import rbf_kernel, paired_distances\n",
  281. "import matplotlib.pyplot as plt\n",
  282. "\n",
  283. "# main\n",
  284. "import sys\n",
  285. "from collections import Counter\n",
  286. "import networkx as nx\n",
  287. "sys.path.insert(0, \"../\")\n",
  288. "from pygraph.utils.graphfiles import loadDataset\n",
  289. "\n",
  290. "\n",
  291. "def main(): \n",
  292. " dataset, y = loadDataset(\"../../../../datasets/acyclic/Acyclic/dataset_bps.ds\")\n",
  293. " G1 = dataset[15]\n",
  294. " print(nx.get_node_attributes(G1, 'label'))\n",
  295. " nx.draw_networkx(G1)\n",
  296. " plt.show()\n",
  297. " G2 = dataset[57] # 180 double 4, 57, 3, double 3\n",
  298. " print(nx.get_node_attributes(G2, 'label'))\n",
  299. " nx.draw_networkx(G2)\n",
  300. " plt.show()\n",
  301. "\n",
  302. " treeletkernel(G1, G2, labeled = True)\n",
  303. " # Kmatrix = weisfeilerlehmankernel(G1, G2)\n",
  304. " \n",
  305. "def find_paths(G, source_node, length):\n",
  306. " if length == 0:\n",
  307. " return [[source_node]]\n",
  308. " path = [ [source_node] + path for neighbor in G[source_node] \\\n",
  309. " for path in find_paths(G, neighbor, length - 1) if source_node not in path ]\n",
  310. " return path\n",
  311. "\n",
  312. "def find_all_paths(G, length):\n",
  313. " all_paths = []\n",
  314. " for node in G:\n",
  315. " all_paths.extend(find_paths(G, node, length))\n",
  316. " all_paths_r = [ path[::-1] for path in all_paths ]\n",
  317. " \n",
  318. " # remove double direction\n",
  319. " for idx, path in enumerate(all_paths[:-1]):\n",
  320. " for path2 in all_paths_r[idx+1::]:\n",
  321. " if path == path2:\n",
  322. " all_paths[idx] = []\n",
  323. " break\n",
  324. " \n",
  325. " return list(filter(lambda a: a != [], all_paths))\n",
  326. "\n",
  327. "def get_canonkey(G, node_label = 'atom', edge_label = 'bond_type', labeled = True):\n",
  328. " \n",
  329. " patterns = {}\n",
  330. " canonkey = {} # canonical key\n",
  331. " \n",
  332. " ### structural analysis ###\n",
  333. " # linear patterns\n",
  334. " patterns['0'] = G.nodes()\n",
  335. " canonkey['0'] = nx.number_of_nodes(G)\n",
  336. " for i in range(1, 6):\n",
  337. " patterns[str(i)] = find_all_paths(G, i)\n",
  338. " canonkey[str(i)] = len(patterns[str(i)])\n",
  339. " \n",
  340. " # n-star patterns\n",
  341. " patterns['3star'] = [ [node] + [neighbor for neighbor in G[node]] for node in G.nodes() if G.degree(node) == 3 ]\n",
  342. " patterns['4star'] = [ [node] + [neighbor for neighbor in G[node]] for node in G.nodes() if G.degree(node) == 4 ]\n",
  343. " patterns['5star'] = [ [node] + [neighbor for neighbor in G[node]] for node in G.nodes() if G.degree(node) == 5 ] \n",
  344. " # n-star patterns\n",
  345. " canonkey['6'] = len(patterns['3star'])\n",
  346. " canonkey['8'] = len(patterns['4star'])\n",
  347. " canonkey['d'] = len(patterns['5star'])\n",
  348. " \n",
  349. " # pattern 7\n",
  350. " patterns['7'] = []\n",
  351. " for pattern in patterns['3star']:\n",
  352. " for i in range(1, len(pattern)):\n",
  353. " if G.degree(pattern[i]) >= 2:\n",
  354. " pattern_t = pattern[:]\n",
  355. " pattern_t[i], pattern_t[3] = pattern_t[3], pattern_t[i]\n",
  356. " for neighborx in G[pattern[i]]:\n",
  357. " if neighborx != pattern[0]:\n",
  358. " new_pattern = pattern_t + [ neighborx ]\n",
  359. "# new_patterns = [ pattern + [neighbor] for neighbor in G[pattern[i]] if neighbor != pattern[0] ]\n",
  360. " patterns['7'].append(new_pattern)\n",
  361. " canonkey['7'] = len(patterns['7'])\n",
  362. " \n",
  363. " # pattern 11\n",
  364. " patterns['11'] = []\n",
  365. " for pattern in patterns['4star']:\n",
  366. " for i in range(1, len(pattern)):\n",
  367. " if G.degree(pattern[i]) >= 2:\n",
  368. " pattern_t = pattern[:]\n",
  369. " pattern_t[i], pattern_t[4] = pattern_t[4], pattern_t[i]\n",
  370. " for neighborx in G[pattern[i]]:\n",
  371. " if neighborx != pattern[0]:\n",
  372. " new_pattern = pattern_t + [ neighborx ]\n",
  373. "# new_patterns = [ pattern + [neighborx] for neighborx in G[pattern[i]] if neighborx != pattern[0] ]\n",
  374. " patterns['11'].append(new_pattern)\n",
  375. " canonkey['b'] = len(patterns['11'])\n",
  376. " \n",
  377. " # pattern 12\n",
  378. " patterns['12'] = []\n",
  379. " rootlist = []\n",
  380. " for pattern in patterns['3star']:\n",
  381. "# print(pattern)\n",
  382. " if pattern[0] not in rootlist:\n",
  383. " rootlist.append(pattern[0])\n",
  384. " for i in range(1, len(pattern)):\n",
  385. " if G.degree(pattern[i]) >= 3:\n",
  386. " rootlist.append(pattern[i])\n",
  387. " pattern_t = pattern[:]\n",
  388. " pattern_t[i], pattern_t[3] = pattern_t[3], pattern_t[i]\n",
  389. " for neighborx1 in G[pattern[i]]:\n",
  390. " if neighborx1 != pattern[0]:\n",
  391. " for neighborx2 in G[pattern[i]]:\n",
  392. " if neighborx1 > neighborx2 and neighborx2 != pattern[0]:\n",
  393. " new_pattern = pattern_t + [neighborx1] + [neighborx2]\n",
  394. "# new_patterns = [ pattern + [neighborx1] + [neighborx2] for neighborx1 in G[pattern[i]] if neighborx1 != pattern[0] for neighborx2 in G[pattern[i]] if (neighborx1 > neighborx2 and neighborx2 != pattern[0]) ]\n",
  395. " patterns['12'].append(new_pattern)\n",
  396. " canonkey['c'] = int(len(patterns['12']) / 2)\n",
  397. " \n",
  398. " # pattern 9\n",
  399. " patterns['9'] = []\n",
  400. " for pattern in patterns['3star']:\n",
  401. "# print('pattern: ', pattern)\n",
  402. " for pairs in [ [neighbor1, neighbor2] for neighbor1 in G[pattern[0]] if G.degree(neighbor1) >= 2 \\\n",
  403. " for neighbor2 in G[pattern[0]] if G.degree(neighbor2) >= 2 if neighbor1 > neighbor2 ]:\n",
  404. "# print('pairs: ', pairs)\n",
  405. " pattern_t = pattern[:]\n",
  406. "# print('pattern_t: ', pattern_t)\n",
  407. " pattern_t[pattern_t.index(pairs[0])], pattern_t[2] = pattern_t[2], pattern_t[pattern_t.index(pairs[0])]\n",
  408. "# print('pattern_t: ', pattern_t)\n",
  409. " pattern_t[pattern_t.index(pairs[1])], pattern_t[3] = pattern_t[3], pattern_t[pattern_t.index(pairs[1])]\n",
  410. "# print('pattern_t: ', pattern_t)\n",
  411. " for neighborx1 in G[pairs[0]]:\n",
  412. " if neighborx1 != pattern[0]:\n",
  413. " for neighborx2 in G[pairs[1]]:\n",
  414. " if neighborx2 != pattern[0]:\n",
  415. " new_pattern = pattern_t + [neighborx1] + [neighborx2]\n",
  416. "# new_patterns = [ pattern + [neighborx1] + [neighborx2] for neighborx1 in G[pairs[0]] if neighborx1 != pattern[0] for neighborx2 in G[pairs[1]] if neighborx2 != pattern[0] ]\n",
  417. " patterns['9'].append(new_pattern)\n",
  418. " canonkey['9'] = len(patterns['9'])\n",
  419. " \n",
  420. " # pattern 10\n",
  421. " patterns['10'] = []\n",
  422. " for pattern in patterns['3star']: \n",
  423. " for i in range(1, len(pattern)):\n",
  424. " if G.degree(pattern[i]) >= 2:\n",
  425. " for neighborx in G[pattern[i]]:\n",
  426. " if neighborx != pattern[0] and G.degree(neighborx) >= 2:\n",
  427. " pattern_t = pattern[:]\n",
  428. " pattern_t[i], pattern_t[3] = pattern_t[3], pattern_t[i]\n",
  429. " new_patterns = [ pattern_t + [neighborx] + [neighborxx] for neighborxx in G[neighborx] if neighborxx != pattern[i] ]\n",
  430. " patterns['10'].extend(new_patterns)\n",
  431. " canonkey['a'] = len(patterns['10'])\n",
  432. " \n",
  433. " ### labeling information ###\n",
  434. " if labeled == True:\n",
  435. " canonkey_l = {}\n",
  436. " \n",
  437. " # linear patterns\n",
  438. " canonkey_t = Counter(list(nx.get_node_attributes(G, node_label).values()))\n",
  439. " for key in canonkey_t:\n",
  440. " canonkey_l['0' + key] = canonkey_t[key]\n",
  441. " print('\\n pattern 0: ', patterns['0'])\n",
  442. " print(' treelet 0: ', list(nx.get_node_attributes(G, node_label).values()))\n",
  443. " \n",
  444. " for i in range(1, 6):\n",
  445. " treelet = []\n",
  446. " for pattern in patterns[str(i)]:\n",
  447. " canonlist = list(chain.from_iterable((G.node[node][node_label], \\\n",
  448. " G[node][pattern[idx+1]][edge_label]) for idx, node in enumerate(pattern[:-1])))\n",
  449. " canonlist.append(G.node[pattern[-1]][node_label])\n",
  450. " canonkey_t = ''.join(canonlist)\n",
  451. " canonkey_t = canonkey_t if canonkey_t < canonkey_t[::-1] else canonkey_t[::-1]\n",
  452. " treelet.append(str(i) + canonkey_t)\n",
  453. " canonkey_l.update(Counter(treelet))\n",
  454. " print('\\n pattern', i, ': ', patterns[str(i)])\n",
  455. " print(' treelet', i, ': ', treelet)\n",
  456. " \n",
  457. "# print(canonkey_l)\n",
  458. " \n",
  459. " # n-star patterns\n",
  460. " for i in range(3, 6):\n",
  461. " treelet = []\n",
  462. " for pattern in patterns[str(i) + 'star']:\n",
  463. " canonlist = [ G.node[leaf][node_label] + G[leaf][pattern[0]][edge_label] for leaf in pattern[1:] ]\n",
  464. " canonlist.sort()\n",
  465. " canonkey_t = ('d' if i == 5 else str(i * 2)) + G.node[pattern[0]][node_label] + ''.join(canonlist)\n",
  466. " treelet.append(canonkey_t)\n",
  467. " canonkey_l.update(Counter(treelet))\n",
  468. " print('\\n pattern', i, 'star: ', patterns[str(i) + 'star'])\n",
  469. " print(' treelet', i, 'star: ', treelet)\n",
  470. " \n",
  471. " # pattern 7\n",
  472. " treelet = []\n",
  473. " for pattern in patterns['7']:\n",
  474. " canonlist = [ G.node[leaf][node_label] + G[leaf][pattern[0]][edge_label] for leaf in pattern[1:3] ]\n",
  475. " canonlist.sort()\n",
  476. " canonkey_t = '7' + G.node[pattern[0]][node_label] + ''.join(canonlist) \\\n",
  477. " + G.node[pattern[3]][node_label] + G[pattern[3]][pattern[0]][edge_label] \\\n",
  478. " + G.node[pattern[4]][node_label] + G[pattern[4]][pattern[3]][edge_label]\n",
  479. " treelet.append(canonkey_t)\n",
  480. " canonkey_l.update(Counter(treelet))\n",
  481. " print('\\n pattern 7: ', patterns['7'])\n",
  482. " print(' treelet 7: ', treelet)\n",
  483. " \n",
  484. " # pattern 11\n",
  485. " treelet = []\n",
  486. " for pattern in patterns['11']:\n",
  487. " canonlist = [ G.node[leaf][node_label] + G[leaf][pattern[0]][edge_label] for leaf in pattern[1:4] ]\n",
  488. " canonlist.sort()\n",
  489. " canonkey_t = 'b' + G.node[pattern[0]][node_label] + ''.join(canonlist) \\\n",
  490. " + G.node[pattern[4]][node_label] + G[pattern[4]][pattern[0]][edge_label] \\\n",
  491. " + G.node[pattern[5]][node_label] + G[pattern[5]][pattern[4]][edge_label]\n",
  492. " treelet.append(canonkey_t)\n",
  493. " canonkey_l.update(Counter(treelet))\n",
  494. " print('\\n pattern 11: ', patterns['11'])\n",
  495. " print(' treelet 11: ', treelet)\n",
  496. "\n",
  497. " # pattern 10\n",
  498. " treelet = []\n",
  499. " for pattern in patterns['10']:\n",
  500. " canonkey4 = G.node[pattern[5]][node_label] + G[pattern[5]][pattern[4]][edge_label]\n",
  501. " canonlist = [ G.node[leaf][node_label] + G[leaf][pattern[0]][edge_label] for leaf in pattern[1:3] ]\n",
  502. " canonlist.sort()\n",
  503. " canonkey0 = ''.join(canonlist)\n",
  504. " canonkey_t = 'a' + G.node[pattern[3]][node_label] \\\n",
  505. " + G.node[pattern[4]][node_label] + G[pattern[4]][pattern[3]][edge_label] \\\n",
  506. " + G.node[pattern[0]][node_label] + G[pattern[0]][pattern[3]][edge_label] \\\n",
  507. " + canonkey4 + canonkey0\n",
  508. "# canonkey_t = 'a' + G.node[pattern[0]][node_label] + ''.join(canonlist) \\\n",
  509. "# + G.node[pattern[3]][node_label] + G[pattern[3]][pattern[0]][edge_label] \\\n",
  510. "# + G.node[pattern[4]][node_label] + G[pattern[4]][pattern[3]][edge_label]\n",
  511. " treelet.append(canonkey_t)\n",
  512. " canonkey_l.update(Counter(treelet))\n",
  513. " print('\\n pattern 10: ', patterns['10'])\n",
  514. " print(' treelet 10: ', treelet)\n",
  515. " \n",
  516. " # pattern 12\n",
  517. " treelet = []\n",
  518. " for pattern in patterns['12']:\n",
  519. " canonlist0 = [ G.node[leaf][node_label] + G[leaf][pattern[0]][edge_label] for leaf in pattern[1:3] ]\n",
  520. " canonlist0.sort()\n",
  521. " canonlist3 = [ G.node[leaf][node_label] + G[leaf][pattern[3]][edge_label] for leaf in pattern[4:6] ]\n",
  522. " canonlist3.sort()\n",
  523. " canonkey_t1 = 'c' + G.node[pattern[0]][node_label] \\\n",
  524. " + ''.join(canonlist0) \\\n",
  525. " + G.node[pattern[3]][node_label] + G[pattern[3]][pattern[0]][edge_label] \\\n",
  526. " + ''.join(canonlist3)\n",
  527. " \n",
  528. " canonkey_t2 = 'c' + G.node[pattern[3]][node_label] \\\n",
  529. " + ''.join(canonlist3) \\\n",
  530. " + G.node[pattern[0]][node_label] + G[pattern[0]][pattern[3]][edge_label] \\\n",
  531. " + ''.join(canonlist0)\n",
  532. " \n",
  533. " treelet.append(canonkey_t1 if canonkey_t1 < canonkey_t2 else canonkey_t2)\n",
  534. " canonkey_l.update(Counter(treelet))\n",
  535. " print('\\n pattern 12: ', patterns['12'])\n",
  536. " print(' treelet 12: ', treelet)\n",
  537. " \n",
  538. " # pattern 9\n",
  539. " treelet = []\n",
  540. " for pattern in patterns['9']:\n",
  541. " canonkey2 = G.node[pattern[4]][node_label] + G[pattern[4]][pattern[2]][edge_label]\n",
  542. " canonkey3 = G.node[pattern[5]][node_label] + G[pattern[5]][pattern[3]][edge_label]\n",
  543. " prekey2 = G.node[pattern[2]][node_label] + G[pattern[2]][pattern[0]][edge_label]\n",
  544. " prekey3 = G.node[pattern[3]][node_label] + G[pattern[3]][pattern[0]][edge_label]\n",
  545. " if prekey2 + canonkey2 < prekey3 + canonkey3:\n",
  546. " canonkey_t = G.node[pattern[1]][node_label] + G[pattern[1]][pattern[0]][edge_label] \\\n",
  547. " + prekey2 + prekey3 + canonkey2 + canonkey3\n",
  548. " else:\n",
  549. " canonkey_t = G.node[pattern[1]][node_label] + G[pattern[1]][pattern[0]][edge_label] \\\n",
  550. " + prekey3 + prekey2 + canonkey3 + canonkey2\n",
  551. " treelet.append('9' + G.node[pattern[0]][node_label] + canonkey_t)\n",
  552. " canonkey_l.update(Counter(treelet))\n",
  553. " print('\\n pattern 9: ', patterns['9'])\n",
  554. " print(' treelet 9: ', treelet)\n",
  555. " \n",
  556. "\n",
  557. " \n",
  558. " \n",
  559. " print('\\n numbers of canonical keys: ', canonkey_l)\n",
  560. " \n",
  561. " \n",
  562. " return canonkey_l\n",
  563. " \n",
  564. " return canonkey\n",
  565. " \n",
  566. "\n",
  567. "def treeletkernel(*args, node_label = 'atom', edge_label = 'bond_type', labeled = True):\n",
  568. " if len(args) == 1: # for a list of graphs\n",
  569. " Gn = args[0]\n",
  570. " Kmatrix = np.zeros((len(Gn), len(Gn)))\n",
  571. "\n",
  572. " start_time = time.time()\n",
  573. " \n",
  574. " for i in range(0, len(Gn)):\n",
  575. " print(i)\n",
  576. " for j in range(i, len(Gn)):\n",
  577. " Kmatrix[i][j] = treeletkernel(Gn[i], Gn[j], labeled = labeled, node_label = node_label, edge_label = edge_label)\n",
  578. " Kmatrix[j][i] = Kmatrix[i][j]\n",
  579. "\n",
  580. " run_time = time.time() - start_time\n",
  581. " print(\"\\n --- treelet kernel matrix of size %d built in %s seconds ---\" % (len(Gn), run_time))\n",
  582. " \n",
  583. " return Kmatrix, run_time\n",
  584. " \n",
  585. " else: # for only 2 graphs\n",
  586. " \n",
  587. " G1 = args[0]\n",
  588. " G = args[1]\n",
  589. " kernel = 0\n",
  590. " \n",
  591. "# start_time = time.time()\n",
  592. " \n",
  593. " \n",
  594. " canonkey2 = get_canonkey(G, node_label = node_label, edge_label = edge_label, labeled = labeled)\n",
  595. " canonkey1 = get_canonkey(G1, node_label = node_label, edge_label = edge_label, labeled = labeled)\n",
  596. " \n",
  597. " keys = set(canonkey1.keys()) & set(canonkey2.keys()) # find same canonical keys in both graphs\n",
  598. " vector1 = np.matrix([ (canonkey1[key] if (key in canonkey1.keys()) else 0) for key in keys ])\n",
  599. "# print(vector1)\n",
  600. " vector2 = np.matrix([ (canonkey2[key] if (key in canonkey2.keys()) else 0) for key in keys ]) \n",
  601. " kernel = np.sum(np.exp(- np.square(vector1 - vector2) / 2))\n",
  602. "# print(vector2)\n",
  603. " \n",
  604. " # labeling information\n",
  605. " \n",
  606. " # equal keys and graph isomorphism\n",
  607. " \n",
  608. "\n",
  609. "# run_time = time.time() - start_time\n",
  610. "# print(\"\\n --- treelet kernel built in %s seconds ---\" % (run_time))\n",
  611. " \n",
  612. "# print(kernel)\n",
  613. " return kernel#, run_time\n",
  614. " \n",
  615. "if __name__ == '__main__':\n",
  616. " main()"
  617. ]
  618. }
  619. ],
  620. "metadata": {
  621. "kernelspec": {
  622. "display_name": "Python 3",
  623. "language": "python",
  624. "name": "python3"
  625. },
  626. "language_info": {
  627. "codemirror_mode": {
  628. "name": "ipython",
  629. "version": 3
  630. },
  631. "file_extension": ".py",
  632. "mimetype": "text/x-python",
  633. "name": "python",
  634. "nbconvert_exporter": "python",
  635. "pygments_lexer": "ipython3",
  636. "version": "3.5.2"
  637. }
  638. },
  639. "nbformat": 4,
  640. "nbformat_minor": 2
  641. }

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