from typing import List, Tuple

from networkx import Graph
from networkx.algorithms import is_isomorphic

def lewis_graph(molecule: 'Molecule') -> Graph:
    '''
    Return the Lewis graph of a molecule (Using networkx' Graph() class).
    '''
    G = Graph()

    for atom in molecule.atoms.values():
        G.add_node(atom.index, element=atom.element, non_bonded_electrons=molecule.non_bonded_electrons[atom.index])

    for bond in molecule.bonds:
        G.add_edge(*bond, order=molecule.bond_orders[bond])

    return G

def unique_molecules(molecules: List['Molecule'], debug: bool = False) -> List['Molecule']:
    '''
    Return list of one-by-one non-isomorphic graphs (including bond order, chemical elements and number of lone pairs)
    '''
    lewis_graphs = [
        lewis_graph(molecule)
        for molecule in molecules
    ]

    unique_molecules: List[Tuple['Molecules', Graph]] = []

    print_if_debug = lambda *args, **kwargs: print(*args, **kwargs) if debug else None

    for (molecule_1, graph_1) in zip(molecules, lewis_graphs):
        print_if_debug('Assessing {0} (unique_molecules={1})'.format(molecule_1.name, [m.name for (m, _) in unique_molecules]))
        if all(
            not is_isomorphic(
                graph_1,
                graph_2,
                node_match=lambda node_1, node_2: node_1['element'] == node_2['element'] and node_1['non_bonded_electrons'] == node_2['non_bonded_electrons'],
                edge_match=lambda edge_1, edge_2: edge_1['order'] == edge_2['order'],
            )
            for (_, graph_2) in unique_molecules
        ):
            print_if_debug('UNIQUE: {0}'.format(molecule_1.name))
            unique_molecules.append(
                (molecule_1, graph_1),
            )
        else:
            print_if_debug('NOT UNIQUE: {0}'.format(molecule_1.name))

    return [
        molecule
        for (molecule, _) in unique_molecules
    ]

@@ -23,16 +23,36 @@
 t, Tuple
+, Callable, Sequence
 %0A%0Afrom n
@@ -155,16 +155,55 @@
 olecule'
+, use_non_bonded_electrons: bool = True
 ) -%3E Gra
@@ -377,19 +377,44 @@
 ode(
-atom.index,
+%0A            atom.index,%0A           
  ele
@@ -431,16 +431,28 @@
 element,
+%0A           
  non_bon
@@ -506,16 +506,64 @@
 m.index%5D
+ if use_non_bonded_electrons else None,%0A        
 )%0A%0A    f
@@ -664,16 +664,640 @@
 turn G%0A%0A
+def are_nodes_equivalent(node_1: 'Node', node_2: 'Node') -%3E bool:%0A    return node_1%5B'element'%5D == node_2%5B'element'%5D and node_1%5B'non_bonded_electrons'%5D == node_2%5B'non_bonded_electrons'%5D%0A%0Adef are_edges_equivalent(edge_1: 'Edge', edge_2: 'Edge') -%3E bool:%0A    return edge_1%5B'order'%5D == edge_2%5B'order'%5D%0A%0Adef are_graphs_isomorphic(%0A    graphs: Sequence%5BGraph%5D,%0A    node_match: Callable%5B%5B'Node', 'Node'%5D, bool%5D = are_nodes_equivalent,%0A    edge_match: Callable%5B%5B'Edge', 'Edge'%5D, bool%5D = are_edges_equivalent,%0A) -%3E bool:%0A    return is_isomorphic(%0A        *graphs,%0A        node_match=node_match,%0A        edge_match=edge_match,%0A    )%0A%0A
 def uniq
@@ -1978,17 +1978,25 @@
     not 
-i
+are_graph
 s_isomor
@@ -2021,16 +2021,17 @@
     
+(
 graph_1,
 %0A   
@@ -2030,32 +2030,16 @@
 h_1,
-%0A               
  graph_2
 ,%0A  
@@ -2034,16 +2034,17 @@
  graph_2
+)
 ,%0A      
@@ -2068,224 +2068,77 @@
 tch=
-lambda node_1, node_2: node_1%5B'element'%5D == node_2%5B'element'%5D and node_1%5B'non_bonded_electrons'%5D == node_2%5B'non_bonded_electrons'%5D,%0A                edge_match=lambda edge_1, edge_2: edge_1%5B'order'%5D == edge_2%5B'order'%5D
+are_nodes_equivalent,%0A                edge_match=are_edges_equivalent
 ,%0A  

Refactor the graph isomorphism matching code