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.

dataset.py 21 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. Created on Thu Mar 26 18:48:27 2020
  5. @author: ljia
  6. """
  7. import numpy as np
  8. import networkx as nx
  9. from gklearn.utils.graph_files import load_dataset
  10. import os
  11. class Dataset(object):
  12. def __init__(self, filename=None, filename_targets=None, **kwargs):
  13. if filename is None:
  14. self.__graphs = None
  15. self.__targets = None
  16. self.__node_labels = None
  17. self.__edge_labels = None
  18. self.__node_attrs = None
  19. self.__edge_attrs = None
  20. else:
  21. self.load_dataset(filename, filename_targets=filename_targets, **kwargs)
  22. self.__substructures = None
  23. self.__node_label_dim = None
  24. self.__edge_label_dim = None
  25. self.__directed = None
  26. self.__dataset_size = None
  27. self.__total_node_num = None
  28. self.__ave_node_num = None
  29. self.__min_node_num = None
  30. self.__max_node_num = None
  31. self.__total_edge_num = None
  32. self.__ave_edge_num = None
  33. self.__min_edge_num = None
  34. self.__max_edge_num = None
  35. self.__ave_node_degree = None
  36. self.__min_node_degree = None
  37. self.__max_node_degree = None
  38. self.__ave_fill_factor = None
  39. self.__min_fill_factor = None
  40. self.__max_fill_factor = None
  41. self.__node_label_nums = None
  42. self.__edge_label_nums = None
  43. self.__node_attr_dim = None
  44. self.__edge_attr_dim = None
  45. self.__class_number = None
  46. def load_dataset(self, filename, filename_targets=None, **kwargs):
  47. self.__graphs, self.__targets, label_names = load_dataset(filename, filename_targets=filename_targets, **kwargs)
  48. self.__node_labels = label_names['node_labels']
  49. self.__node_attrs = label_names['node_attrs']
  50. self.__edge_labels = label_names['edge_labels']
  51. self.__edge_attrs = label_names['edge_attrs']
  52. def load_graphs(self, graphs, targets=None):
  53. # this has to be followed by set_labels().
  54. self.__graphs = graphs
  55. self.__targets = targets
  56. # self.set_labels_attrs()
  57. def load_predefined_dataset(self, ds_name):
  58. current_path = os.path.dirname(os.path.realpath(__file__)) + '/'
  59. if ds_name == 'Acyclic':
  60. ds_file = current_path + '../../datasets/Acyclic/dataset_bps.ds'
  61. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  62. elif ds_name == 'AIDS':
  63. ds_file = current_path + '../../datasets/AIDS/AIDS_A.txt'
  64. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  65. elif ds_name == 'Alkane':
  66. ds_file = current_path + '../../datasets/Alkane/dataset.ds'
  67. fn_targets = current_path + '../../datasets/Alkane/dataset_boiling_point_names.txt'
  68. self.__graphs, self.__targets, label_names = load_dataset(ds_file, filename_targets=fn_targets)
  69. elif ds_name == 'COIL-DEL':
  70. ds_file = current_path + '../../datasets/COIL-DEL/COIL-DEL_A.txt'
  71. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  72. elif ds_name == 'COIL-RAG':
  73. ds_file = current_path + '../../datasets/COIL-RAG/COIL-RAG_A.txt'
  74. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  75. elif ds_name == 'COLORS-3':
  76. ds_file = current_path + '../../datasets/COLORS-3/COLORS-3_A.txt'
  77. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  78. elif ds_name == 'Cuneiform':
  79. ds_file = current_path + '../../datasets/Cuneiform/Cuneiform_A.txt'
  80. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  81. elif ds_name == 'Fingerprint':
  82. ds_file = current_path + '../../datasets/Fingerprint/Fingerprint_A.txt'
  83. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  84. elif ds_name == 'FRANKENSTEIN':
  85. ds_file = current_path + '../../datasets/FRANKENSTEIN/FRANKENSTEIN_A.txt'
  86. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  87. elif ds_name == 'Letter-high': # node non-symb
  88. ds_file = current_path + '../../datasets/Letter-high/Letter-high_A.txt'
  89. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  90. elif ds_name == 'Letter-low': # node non-symb
  91. ds_file = current_path + '../../datasets/Letter-low/Letter-low_A.txt'
  92. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  93. elif ds_name == 'Letter-med': # node non-symb
  94. ds_file = current_path + '../../datasets/Letter-med/Letter-med_A.txt'
  95. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  96. elif ds_name == 'MAO':
  97. ds_file = current_path + '../../datasets/MAO/dataset.ds'
  98. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  99. elif ds_name == 'Monoterpenoides':
  100. ds_file = current_path + '../../datasets/Monoterpenoides/dataset_10+.ds'
  101. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  102. elif ds_name == 'MUTAG':
  103. ds_file = current_path + '../../datasets/MUTAG/MUTAG_A.txt'
  104. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  105. elif ds_name == 'SYNTHETIC':
  106. pass
  107. elif ds_name == 'SYNTHETICnew':
  108. ds_file = current_path + '../../datasets/SYNTHETICnew/SYNTHETICnew_A.txt'
  109. self.__graphs, self.__targets, label_names = load_dataset(ds_file)
  110. elif ds_name == 'Synthie':
  111. pass
  112. self.__node_labels = label_names['node_labels']
  113. self.__node_attrs = label_names['node_attrs']
  114. self.__edge_labels = label_names['edge_labels']
  115. self.__edge_attrs = label_names['edge_attrs']
  116. def set_labels(self, node_labels=[], node_attrs=[], edge_labels=[], edge_attrs=[]):
  117. self.__node_labels = node_labels
  118. self.__node_attrs = node_attrs
  119. self.__edge_labels = edge_labels
  120. self.__edge_attrs = edge_attrs
  121. def set_labels_attrs(self, node_labels=None, node_attrs=None, edge_labels=None, edge_attrs=None):
  122. # @todo: remove labels which have only one possible values.
  123. if node_labels is None:
  124. self.__node_labels = self.__graphs[0].graph['node_labels']
  125. # # graphs are considered node unlabeled if all nodes have the same label.
  126. # infos.update({'node_labeled': is_nl if node_label_num > 1 else False})
  127. if node_attrs is None:
  128. self.__node_attrs = self.__graphs[0].graph['node_attrs']
  129. # for G in Gn:
  130. # for n in G.nodes(data=True):
  131. # if 'attributes' in n[1]:
  132. # return len(n[1]['attributes'])
  133. # return 0
  134. if edge_labels is None:
  135. self.__edge_labels = self.__graphs[0].graph['edge_labels']
  136. # # graphs are considered edge unlabeled if all edges have the same label.
  137. # infos.update({'edge_labeled': is_el if edge_label_num > 1 else False})
  138. if edge_attrs is None:
  139. self.__edge_attrs = self.__graphs[0].graph['edge_attrs']
  140. # for G in Gn:
  141. # if nx.number_of_edges(G) > 0:
  142. # for e in G.edges(data=True):
  143. # if 'attributes' in e[2]:
  144. # return len(e[2]['attributes'])
  145. # return 0
  146. def get_dataset_infos(self, keys=None):
  147. """Computes and returns the structure and property information of the graph dataset.
  148. Parameters
  149. ----------
  150. keys : list
  151. List of strings which indicate which informations will be returned. The
  152. possible choices includes:
  153. 'substructures': sub-structures graphs contains, including 'linear', 'non
  154. linear' and 'cyclic'.
  155. 'node_label_dim': whether vertices have symbolic labels.
  156. 'edge_label_dim': whether egdes have symbolic labels.
  157. 'directed': whether graphs in dataset are directed.
  158. 'dataset_size': number of graphs in dataset.
  159. 'total_node_num': total number of vertices of all graphs in dataset.
  160. 'ave_node_num': average number of vertices of graphs in dataset.
  161. 'min_node_num': minimum number of vertices of graphs in dataset.
  162. 'max_node_num': maximum number of vertices of graphs in dataset.
  163. 'total_edge_num': total number of edges of all graphs in dataset.
  164. 'ave_edge_num': average number of edges of graphs in dataset.
  165. 'min_edge_num': minimum number of edges of graphs in dataset.
  166. 'max_edge_num': maximum number of edges of graphs in dataset.
  167. 'ave_node_degree': average vertex degree of graphs in dataset.
  168. 'min_node_degree': minimum vertex degree of graphs in dataset.
  169. 'max_node_degree': maximum vertex degree of graphs in dataset.
  170. 'ave_fill_factor': average fill factor (number_of_edges /
  171. (number_of_nodes ** 2)) of graphs in dataset.
  172. 'min_fill_factor': minimum fill factor of graphs in dataset.
  173. 'max_fill_factor': maximum fill factor of graphs in dataset.
  174. 'node_label_nums': list of numbers of symbolic vertex labels of graphs in dataset.
  175. 'edge_label_nums': list number of symbolic edge labels of graphs in dataset.
  176. 'node_attr_dim': number of dimensions of non-symbolic vertex labels.
  177. Extracted from the 'attributes' attribute of graph nodes.
  178. 'edge_attr_dim': number of dimensions of non-symbolic edge labels.
  179. Extracted from the 'attributes' attribute of graph edges.
  180. 'class_number': number of classes. Only available for classification problems.
  181. All informations above will be returned if `keys` is not given.
  182. Return
  183. ------
  184. dict
  185. Information of the graph dataset keyed by `keys`.
  186. """
  187. infos = {}
  188. if keys == None:
  189. keys = [
  190. 'substructures',
  191. 'node_label_dim',
  192. 'edge_label_dim',
  193. 'directed',
  194. 'dataset_size',
  195. 'total_node_num',
  196. 'ave_node_num',
  197. 'min_node_num',
  198. 'max_node_num',
  199. 'total_edge_num',
  200. 'ave_edge_num',
  201. 'min_edge_num',
  202. 'max_edge_num',
  203. 'ave_node_degree',
  204. 'min_node_degree',
  205. 'max_node_degree',
  206. 'ave_fill_factor',
  207. 'min_fill_factor',
  208. 'max_fill_factor',
  209. 'node_label_nums',
  210. 'edge_label_nums',
  211. 'node_attr_dim',
  212. 'edge_attr_dim',
  213. 'class_number',
  214. ]
  215. # dataset size
  216. if 'dataset_size' in keys:
  217. if self.__dataset_size is None:
  218. self.__dataset_size = self.__get_dataset_size()
  219. infos['dataset_size'] = self.__dataset_size
  220. # graph node number
  221. if any(i in keys for i in ['total_node_num', 'ave_node_num', 'min_node_num', 'max_node_num']):
  222. all_node_nums = self.__get_all_node_nums()
  223. if 'total_node_num' in keys:
  224. if self.__total_node_num is None:
  225. self.__total_node_num = self.__get_total_node_num(all_node_nums)
  226. infos['total_node_num'] = self.__total_node_num
  227. if 'ave_node_num' in keys:
  228. if self.__ave_node_num is None:
  229. self.__ave_node_num = self.__get_ave_node_num(all_node_nums)
  230. infos['ave_node_num'] = self.__ave_node_num
  231. if 'min_node_num' in keys:
  232. if self.__min_node_num is None:
  233. self.__min_node_num = self.__get_min_node_num(all_node_nums)
  234. infos['min_node_num'] = self.__min_node_num
  235. if 'max_node_num' in keys:
  236. if self.__max_node_num is None:
  237. self.__max_node_num = self.__get_max_node_num(all_node_nums)
  238. infos['max_node_num'] = self.__max_node_num
  239. # graph edge number
  240. if any(i in keys for i in ['total_edge_num', 'ave_edge_num', 'min_edge_num', 'max_edge_num']):
  241. all_edge_nums = self.__get_all_edge_nums()
  242. if 'total_edge_num' in keys:
  243. if self.__total_edge_num is None:
  244. self.__total_edge_num = self.__get_total_edge_num(all_edge_nums)
  245. infos['total_edge_num'] = self.__total_edge_num
  246. if 'ave_edge_num' in keys:
  247. if self.__ave_edge_num is None:
  248. self.__ave_edge_num = self.__get_ave_edge_num(all_edge_nums)
  249. infos['ave_edge_num'] = self.__ave_edge_num
  250. if 'max_edge_num' in keys:
  251. if self.__max_edge_num is None:
  252. self.__max_edge_num = self.__get_max_edge_num(all_edge_nums)
  253. infos['max_edge_num'] = self.__max_edge_num
  254. if 'min_edge_num' in keys:
  255. if self.__min_edge_num is None:
  256. self.__min_edge_num = self.__get_min_edge_num(all_edge_nums)
  257. infos['min_edge_num'] = self.__min_edge_num
  258. # label number
  259. if 'node_label_dim' in keys:
  260. if self.__node_label_dim is None:
  261. self.__node_label_dim = self.__get_node_label_dim()
  262. infos['node_label_dim'] = self.__node_label_dim
  263. if 'node_label_nums' in keys:
  264. if self.__node_label_nums is None:
  265. self.__node_label_nums = {}
  266. for node_label in self.__node_labels:
  267. self.__node_label_nums[node_label] = self.get_node_label_num(node_label)
  268. infos['node_label_nums'] = self.__node_label_nums
  269. if 'edge_label_dim' in keys:
  270. if self.__edge_label_dim is None:
  271. self.__edge_label_dim = self.__get_edge_label_dim()
  272. infos['edge_label_dim'] = self.__edge_label_dim
  273. if 'edge_label_nums' in keys:
  274. if self.__edge_label_nums is None:
  275. self.__edge_label_nums = {}
  276. for edge_label in self.__edge_labels:
  277. self.__edge_label_nums[edge_label] = self.get_edge_label_num(edge_label)
  278. infos['edge_label_nums'] = self.__edge_label_nums
  279. if 'directed' in keys or 'substructures' in keys:
  280. if self.__directed is None:
  281. self.__directed = self.__is_directed()
  282. infos['directed'] = self.__directed
  283. # node degree
  284. if any(i in keys for i in ['ave_node_degree', 'max_node_degree', 'min_node_degree']):
  285. all_node_degrees = self.__get_all_node_degrees()
  286. if 'ave_node_degree' in keys:
  287. if self.__ave_node_degree is None:
  288. self.__ave_node_degree = self.__get_ave_node_degree(all_node_degrees)
  289. infos['ave_node_degree'] = self.__ave_node_degree
  290. if 'max_node_degree' in keys:
  291. if self.__max_node_degree is None:
  292. self.__max_node_degree = self.__get_max_node_degree(all_node_degrees)
  293. infos['max_node_degree'] = self.__max_node_degree
  294. if 'min_node_degree' in keys:
  295. if self.__min_node_degree is None:
  296. self.__min_node_degree = self.__get_min_node_degree(all_node_degrees)
  297. infos['min_node_degree'] = self.__min_node_degree
  298. # fill factor
  299. if any(i in keys for i in ['ave_fill_factor', 'max_fill_factor', 'min_fill_factor']):
  300. all_fill_factors = self.__get_all_fill_factors()
  301. if 'ave_fill_factor' in keys:
  302. if self.__ave_fill_factor is None:
  303. self.__ave_fill_factor = self.__get_ave_fill_factor(all_fill_factors)
  304. infos['ave_fill_factor'] = self.__ave_fill_factor
  305. if 'max_fill_factor' in keys:
  306. if self.__max_fill_factor is None:
  307. self.__max_fill_factor = self.__get_max_fill_factor(all_fill_factors)
  308. infos['max_fill_factor'] = self.__max_fill_factor
  309. if 'min_fill_factor' in keys:
  310. if self.__min_fill_factor is None:
  311. self.__min_fill_factor = self.__get_min_fill_factor(all_fill_factors)
  312. infos['min_fill_factor'] = self.__min_fill_factor
  313. if 'substructures' in keys:
  314. if self.__substructures is None:
  315. self.__substructures = self.__get_substructures()
  316. infos['substructures'] = self.__substructures
  317. if 'class_number' in keys:
  318. if self.__class_number is None:
  319. self.__class_number = self.__get_class_number()
  320. infos['class_number'] = self.__class_number
  321. if 'node_attr_dim' in keys:
  322. if self.__node_attr_dim is None:
  323. self.__node_attr_dim = self.__get_node_attr_dim()
  324. infos['node_attr_dim'] = self.__node_attr_dim
  325. if 'edge_attr_dim' in keys:
  326. if self.__edge_attr_dim is None:
  327. self.__edge_attr_dim = self.__get_edge_attr_dim()
  328. infos['edge_attr_dim'] = self.__edge_attr_dim
  329. return infos
  330. def print_graph_infos(self, infos):
  331. from collections import OrderedDict
  332. keys = list(infos.keys())
  333. print(OrderedDict(sorted(infos.items(), key=lambda i: keys.index(i[0]))))
  334. def remove_labels(self, node_labels=[], edge_labels=[], node_attrs=[], edge_attrs=[]):
  335. for g in self.__graphs:
  336. for nd in g.nodes():
  337. for nl in node_labels:
  338. del g.nodes[nd][nl]
  339. for na in node_attrs:
  340. del g.nodes[nd][na]
  341. for ed in g.edges():
  342. for el in edge_labels:
  343. del g.edges[ed][el]
  344. for ea in edge_attrs:
  345. del g.edges[ed][ea]
  346. if len(node_labels) > 0:
  347. self.__node_labels = [nl for nl in self.__node_labels if nl not in node_labels]
  348. if len(edge_labels) > 0:
  349. self.__edge_labels = [el for el in self.__edge_labels if el not in edge_labels]
  350. if len(node_attrs) > 0:
  351. self.__node_attrs = [na for na in self.__node_attrs if na not in node_attrs]
  352. if len(edge_attrs) > 0:
  353. self.__edge_attrs = [ea for ea in self.__edge_attrs if ea not in edge_attrs]
  354. def cut_graphs(self, range_):
  355. self.__graphs = [self.__graphs[i] for i in range_]
  356. if self.__targets is not None:
  357. self.__targets = [self.__targets[i] for i in range_]
  358. # @todo
  359. # self.set_labels_attrs()
  360. def trim_dataset(self, edge_required=False):
  361. if edge_required:
  362. trimed_pairs = [(idx, g) for idx, g in enumerate(self.__graphs) if (nx.number_of_nodes(g) != 0 and nx.number_of_edges(g) != 0)]
  363. else:
  364. trimed_pairs = [(idx, g) for idx, g in enumerate(self.__graphs) if nx.number_of_nodes(g) != 0]
  365. idx = [p[0] for p in trimed_pairs]
  366. self.__graphs = [p[1] for p in trimed_pairs]
  367. self.__targets = [self.__targets[i] for i in idx]
  368. # @todo
  369. # self.set_labels_attrs()
  370. def __get_dataset_size(self):
  371. return len(self.__graphs)
  372. def __get_all_node_nums(self):
  373. return [nx.number_of_nodes(G) for G in self.__graphs]
  374. def __get_total_node_nums(self, all_node_nums):
  375. return np.sum(all_node_nums)
  376. def __get_ave_node_num(self, all_node_nums):
  377. return np.mean(all_node_nums)
  378. def __get_min_node_num(self, all_node_nums):
  379. return np.amin(all_node_nums)
  380. def __get_max_node_num(self, all_node_nums):
  381. return np.amax(all_node_nums)
  382. def __get_all_edge_nums(self):
  383. return [nx.number_of_edges(G) for G in self.__graphs]
  384. def __get_total_edge_nums(self, all_edge_nums):
  385. return np.sum(all_edge_nums)
  386. def __get_ave_edge_num(self, all_edge_nums):
  387. return np.mean(all_edge_nums)
  388. def __get_min_edge_num(self, all_edge_nums):
  389. return np.amin(all_edge_nums)
  390. def __get_max_edge_num(self, all_edge_nums):
  391. return np.amax(all_edge_nums)
  392. def __get_node_label_dim(self):
  393. return len(self.__node_labels)
  394. def __get_node_label_num(self, node_label):
  395. nl = set()
  396. for G in self.__graphs:
  397. nl = nl | set(nx.get_node_attributes(G, node_label).values())
  398. return len(nl)
  399. def __get_edge_label_dim(self):
  400. return len(self.__edge_labels)
  401. def __get_edge_label_num(self, edge_label):
  402. el = set()
  403. for G in self.__graphs:
  404. el = el | set(nx.get_edge_attributes(G, edge_label).values())
  405. return len(el)
  406. def __is_directed(self):
  407. return nx.is_directed(self.__graphs[0])
  408. def __get_all_node_degrees(self):
  409. return [np.mean(list(dict(G.degree()).values())) for G in self.__graphs]
  410. def __get_ave_node_degree(self, all_node_degrees):
  411. return np.mean(all_node_degrees)
  412. def __get_max_node_degree(self, all_node_degrees):
  413. return np.amax(all_node_degrees)
  414. def __get_min_node_degree(self, all_node_degrees):
  415. return np.amin(all_node_degrees)
  416. def __get_all_fill_factors(self):
  417. """
  418. Get fill factor, the number of non-zero entries in the adjacency matrix.
  419. Returns
  420. -------
  421. list[float]
  422. List of fill factors for all graphs.
  423. """
  424. return [nx.number_of_edges(G) / (nx.number_of_nodes(G) ** 2) for G in self.__graphs]
  425. def __get_ave_fill_factor(self, all_fill_factors):
  426. return np.mean(all_fill_factors)
  427. def __get_max_fill_factor(self, all_fill_factors):
  428. return np.amax(all_fill_factors)
  429. def __get_min_fill_factor(self, all_fill_factors):
  430. return np.amin(all_fill_factors)
  431. def __get_substructures(self):
  432. subs = set()
  433. for G in self.__graphs:
  434. degrees = list(dict(G.degree()).values())
  435. if any(i == 2 for i in degrees):
  436. subs.add('linear')
  437. if np.amax(degrees) >= 3:
  438. subs.add('non linear')
  439. if 'linear' in subs and 'non linear' in subs:
  440. break
  441. if self.__directed:
  442. for G in self.__graphs:
  443. if len(list(nx.find_cycle(G))) > 0:
  444. subs.add('cyclic')
  445. break
  446. # else:
  447. # # @todo: this method does not work for big graph with large amount of edges like D&D, try a better way.
  448. # upper = np.amin([nx.number_of_edges(G) for G in Gn]) * 2 + 10
  449. # for G in Gn:
  450. # if (nx.number_of_edges(G) < upper):
  451. # cyc = list(nx.simple_cycles(G.to_directed()))
  452. # if any(len(i) > 2 for i in cyc):
  453. # subs.add('cyclic')
  454. # break
  455. # if 'cyclic' not in subs:
  456. # for G in Gn:
  457. # cyc = list(nx.simple_cycles(G.to_directed()))
  458. # if any(len(i) > 2 for i in cyc):
  459. # subs.add('cyclic')
  460. # break
  461. return subs
  462. def __get_class_num(self):
  463. return len(set(self.__targets))
  464. def __get_node_attr_dim(self):
  465. return len(self.__node_attrs)
  466. def __get_edge_attr_dim(self):
  467. return len(self.__edge_attrs)
  468. @property
  469. def graphs(self):
  470. return self.__graphs
  471. @property
  472. def targets(self):
  473. return self.__targets
  474. @property
  475. def node_labels(self):
  476. return self.__node_labels
  477. @property
  478. def edge_labels(self):
  479. return self.__edge_labels
  480. @property
  481. def node_attrs(self):
  482. return self.__node_attrs
  483. @property
  484. def edge_attrs(self):
  485. return self.__edge_attrs
  486. def split_dataset_by_target(dataset):
  487. from gklearn.preimage.utils import get_same_item_indices
  488. graphs = dataset.graphs
  489. targets = dataset.targets
  490. datasets = []
  491. idx_targets = get_same_item_indices(targets)
  492. for key, val in idx_targets.items():
  493. sub_graphs = [graphs[i] for i in val]
  494. sub_dataset = Dataset()
  495. sub_dataset.load_graphs(sub_graphs, [key] * len(val))
  496. sub_dataset.set_labels(node_labels=dataset.node_labels, node_attrs=dataset.node_attrs, edge_labels=dataset.edge_labels, edge_attrs=dataset.edge_attrs)
  497. datasets.append(sub_dataset)
  498. return datasets

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