def is_same(self, prod_rule, ignore_order=False): """ judge whether this production rule is the same as the input one, `prod_rule` Parameters ---------- prod_rule : ProductionRule production rule to be compared Returns ------- is_same : bool isomap : dict isomorphism of nodes and hyperedges. ex) {'bond_42': 'bond_37', 'bond_2': 'bond_1', 'e36': 'e11', 'e16': 'e12', 'e25': 'e18', 'bond_40': 'bond_38', 'e26': 'e21', 'bond_41': 'bond_39'}. key comes from `prod_rule`, value comes from `self`. """ if self.is_start_rule: if not prod_rule.is_start_rule: return False, {} else: if prod_rule.is_start_rule: return False, {} else: if prod_rule.lhs.num_nodes != self.lhs.num_nodes: return False, {} if prod_rule.rhs.num_nodes != self.rhs.num_nodes: return False, {} if prod_rule.rhs.num_edges != self.rhs.num_edges: return False, {} subhg_bond_symbol_counter \ = Counter([prod_rule.rhs.node_attr(each_node)['symbol'] \ for each_node in prod_rule.rhs.nodes]) each_bond_symbol_counter \ = Counter([self.rhs.node_attr(each_node)['symbol'] \ for each_node in self.rhs.nodes]) if subhg_bond_symbol_counter != each_bond_symbol_counter: return False, {} subhg_atom_symbol_counter \ = Counter([prod_rule.rhs.edge_attr(each_edge)['symbol'] \ for each_edge in prod_rule.rhs.edges]) each_atom_symbol_counter \ = Counter([self.rhs.edge_attr(each_edge)['symbol'] \ for each_edge in self.rhs.edges]) if subhg_atom_symbol_counter != each_atom_symbol_counter: return False, {} gm = GraphMatcher( prod_rule.rhs.hg, self.rhs.hg, partial(_node_match_prod_rule, ignore_order=ignore_order), partial(_edge_match, ignore_order=ignore_order)) try: return True, next(gm.isomorphisms_iter()) except StopIteration: return False, {}
def test_iso(self): base = os.path.dirname(os.path.abspath(__file__)) hg_list = HGGen(os.path.join(base, "test.smi")) hg_list = list(hg_list) hrg = HyperedgeReplacementGrammar() prod_rule_seq_list = hrg.learn(hg_list) not_iso = 0 for idx, each_prod_rule_seq in enumerate(prod_rule_seq_list): hg = hrg.construct(each_prod_rule_seq) self.assertEqual(len(hg.nodes), len(list(hg_list)[idx].nodes)) self.assertEqual(len(hg.edges), len(list(hg_list)[idx].edges)) gm = GraphMatcher(hg.hg, list(hg_list)[idx].hg) try: isomap = next(gm.isomorphisms_iter()) except StopIteration: isomap = None if isomap is None: print("not isomorphic") not_iso += 1 self.assertEqual(not_iso, 0) print("not_iso = {}".format(not_iso))
def sparse_orbigraph_nx(n, H): import networkx as nx from networkx.algorithms.isomorphism import GraphMatcher bag = nx.Graph() for i in range(n): bag.add_node(i, syndrome=H[i,i]) for i in range(n): for j in range(n): if i==j: continue if H.get((i, j)): bag.add_edge(i, j) def node_match(n0, n1): return n0['syndrome'] == n1['syndrome'] matcher = GraphMatcher(bag, bag, node_match=node_match) print("search...") graph = nx.Graph() for i in range(n): graph.add_node(i) count = 0 for iso in matcher.isomorphisms_iter(): # too slow :P #print iso write('.') for i, j in list(iso.items()): graph.add_edge(i, j) count += 1 print() equs = nx.connected_components(graph) m = len(equs) print("isomorphisms:", count) print("components:", m)
def add_subhg(self, subhg): if len(self.subhg_list) == 0: node_dict = {} for each_node in subhg.nodes: node_dict[each_node] = subhg.node_attr(each_node)['symbol'].__hash__() node_list = [] for each_key, _ in sorted(node_dict.items(), key=lambda x:x[1]): node_list.append(each_key) for each_idx, each_node in enumerate(node_list): subhg.node_attr(each_node)['order4hrg'] = each_idx self.subhg_list.append(subhg) return 0, True else: match = False for each_idx, each_subhg in enumerate(self.subhg_list): subhg_bond_symbol_counter \ = Counter([subhg.node_attr(each_node)['symbol'] \ for each_node in subhg.nodes]) each_bond_symbol_counter \ = Counter([each_subhg.node_attr(each_node)['symbol'] \ for each_node in each_subhg.nodes]) subhg_atom_symbol_counter \ = Counter([subhg.edge_attr(each_edge).get('symbol', None) \ for each_edge in subhg.edges]) each_atom_symbol_counter \ = Counter([each_subhg.edge_attr(each_edge).get('symbol', None) \ for each_edge in each_subhg.edges]) if not match \ and (subhg.num_nodes == each_subhg.num_nodes and subhg.num_edges == each_subhg.num_edges and subhg_bond_symbol_counter == each_bond_symbol_counter and subhg_atom_symbol_counter == each_atom_symbol_counter): gm = GraphMatcher(each_subhg.hg, subhg.hg, node_match=_easy_node_match, edge_match=_edge_match) try: isomap = next(gm.isomorphisms_iter()) match = True for each_node in each_subhg.nodes: subhg.node_attr(isomap[each_node])['order4hrg'] \ = each_subhg.node_attr(each_node)['order4hrg'] if 'ext_id' in each_subhg.node_attr(each_node): subhg.node_attr(isomap[each_node])['ext_id'] \ = each_subhg.node_attr(each_node)['ext_id'] return each_idx, False except StopIteration: match = False if not match: node_dict = {} for each_node in subhg.nodes: node_dict[each_node] = subhg.node_attr(each_node)['symbol'].__hash__() node_list = [] for each_key, _ in sorted(node_dict.items(), key=lambda x:x[1]): node_list.append(each_key) for each_idx, each_node in enumerate(node_list): subhg.node_attr(each_node)['order4hrg'] = each_idx #for each_idx, each_node in enumerate(subhg.nodes): # subhg.node_attr(each_node)['order4hrg'] = each_idx self.subhg_list.append(subhg) return len(self.subhg_list) - 1, True