Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions rmgpy/molecule/fragment.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,20 +80,23 @@ def __repr__(self):
def symbol(self):
return self.name

def is_specific_case_of(self, other):
def is_specific_case_of(self, other, check_labels=False):
"""
Return ``True`` if `self` is a specific case of `other`, or ``False``
otherwise. At this moment, this is the same as the :math:`equivalent()`.
"""
return self.equivalent(other)
return self.equivalent(other, check_labels=check_labels)

def equivalent(self, other, strict=True):
def equivalent(self, other, strict=True, check_labels=False):
"""
Return ``True`` if `other` is indistinguishable from this CuttingLabel, or
``False`` otherwise. If `other` is an :class:`CuttingLabel` object, then all
attributes must match exactly.
attributes must match exactly. If ``check_labels`` is ``True``, the
`label` attributes must also match.
"""
if isinstance(other, CuttingLabel):
if check_labels and self.label != other.label:
return False
return self.name == other.name
else:
return False
Expand Down Expand Up @@ -247,7 +250,7 @@ def get_radical_count(self):
return radicals

def is_subgraph_isomorphic(
self, other, initial_map=None, generate_initial_map=False, save_order=False
self, other, initial_map=None, generate_initial_map=False, save_order=False, check_labels=False
):
"""
Fragment's subgraph isomorphism check is done by first creating
Expand Down Expand Up @@ -303,15 +306,15 @@ def is_subgraph_isomorphic(
for i, key in enumerate(keys):
initial_map[key] = atmlist[i]
if self.is_mapping_valid(
other, initial_map, equivalent=False
other, initial_map, equivalent=False, strict=True, check_labels=check_labels
) and Graph.is_subgraph_isomorphic(
self, other, initial_map, save_order=save_order
self, other, initial_map, save_order=save_order, check_labels=check_labels
):
return True
else:
return False
else:
if not self.is_mapping_valid(other, initial_map, equivalent=False):
if not self.is_mapping_valid(other, initial_map, equivalent=False, strict=True, check_labels=check_labels):
return False

# Do the isomorphism comparison
Expand All @@ -322,7 +325,7 @@ def is_subgraph_isomorphic(
repr_mol_vertex = mapping[fragment_vertex]
new_initial_map[repr_mol_vertex] = initial_map[fragment_vertex]

result = Graph.is_subgraph_isomorphic(self.mol_repr, other, new_initial_map)
result = Graph.is_subgraph_isomorphic(self.mol_repr, other, new_initial_map, check_labels=check_labels)
return result

def calculate_cp0(self):
Expand Down
14 changes: 7 additions & 7 deletions rmgpy/molecule/graph.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ cdef class Vertex(object):

cpdef Vertex copy(self)

cpdef bint equivalent(self, Vertex other, bint strict=?) except -2
cpdef bint equivalent(self, Vertex other, bint strict=?, bint check_labels=?) except -2

cpdef bint is_specific_case_of(self, Vertex other) except -2
cpdef bint is_specific_case_of(self, Vertex other, bint check_labels=?) except -2

cpdef reset_connectivity_values(self)

Expand Down Expand Up @@ -110,13 +110,13 @@ cdef class Graph(object):

cpdef restore_vertex_order(self)

cpdef bint is_isomorphic(self, Graph other, dict initial_map=?, bint generate_initial_map=?, bint save_order=?, bint strict=?) except -2
cpdef bint is_isomorphic(self, Graph other, dict initial_map=?, bint generate_initial_map=?, bint save_order=?, bint strict=?, bint check_labels=?) except -2

cpdef list find_isomorphism(self, Graph other, dict initial_map=?, bint save_order=?, bint strict=?)
cpdef list find_isomorphism(self, Graph other, dict initial_map=?, bint save_order=?, bint strict=?, bint check_labels=?)

cpdef bint is_subgraph_isomorphic(self, Graph other, dict initial_map=?, bint save_order=?) except -2
cpdef bint is_subgraph_isomorphic(self, Graph other, dict initial_map=?, bint save_order=?, bint check_labels=?) except -2

cpdef list find_subgraph_isomorphisms(self, Graph other, dict initial_map=?, bint save_order=?)
cpdef list find_subgraph_isomorphisms(self, Graph other, dict initial_map=?, bint save_order=?, bint check_labels=?)

cpdef bint is_cyclic(self) except -2

Expand All @@ -140,6 +140,6 @@ cdef class Graph(object):

cpdef list get_largest_ring(self, Vertex vertex)

cpdef bint is_mapping_valid(self, Graph other, dict mapping, bint equivalent=?, bint strict=?) except -2
cpdef bint is_mapping_valid(self, Graph other, dict mapping, bint equivalent=?, bint strict=?, bint check_labels=?) except -2

cpdef list get_edges_in_cycle(self, list vertices, bint sort=?)
40 changes: 24 additions & 16 deletions rmgpy/molecule/graph.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,23 @@ cdef class Vertex(object):
new = Vertex()
return new

cpdef bint equivalent(self, Vertex other, bint strict=True) except -2:
cpdef bint equivalent(self, Vertex other, bint strict=True, bint check_labels=False) except -2:
"""
Return :data:`True` if two vertices `self` and `other` are semantically
equivalent, or :data:`False` if not. You should reimplement this
function in a derived class if your vertices have semantic information.
If `check_labels` is ``True``, subclasses with a `label` attribute
should also require that the labels match.
"""
return True

cpdef bint is_specific_case_of(self, Vertex other) except -2:
cpdef bint is_specific_case_of(self, Vertex other, bint check_labels=False) except -2:
"""
Return ``True`` if `self` is semantically more specific than `other`,
or ``False`` if not. You should reimplement this function in a derived
class if your edges have semantic information.
class if your edges have semantic information. If `check_labels` is
``True``, subclasses with a `label` attribute should also require that
the labels match.
"""
return True

Expand Down Expand Up @@ -499,7 +503,7 @@ cdef class Graph(object):
else:
self.vertices = self.ordered_vertices

cpdef bint is_isomorphic(self, Graph other, dict initial_map=None, bint generate_initial_map=False, bint save_order=False, bint strict=True) except -2:
cpdef bint is_isomorphic(self, Graph other, dict initial_map=None, bint generate_initial_map=False, bint save_order=False, bint strict=True, bint check_labels=False) except -2:
"""
Returns :data:`True` if two graphs are isomorphic and :data:`False`
otherwise. Uses the VF2 algorithm of Vento and Foggia.
Expand All @@ -509,6 +513,7 @@ cdef class Graph(object):
generate_initial_map (bool, optional): if ``True``, initialize map by pairing atoms with same labels
save_order (bool, optional): if ``True``, reset atom order after performing atom isomorphism
strict (bool, optional): if ``False``, perform isomorphism ignoring electrons
check_labels (bool, optional): if ``True``, atoms only match if their `label` attributes match
"""
if generate_initial_map:
initial_map = dict()
Expand All @@ -520,12 +525,12 @@ cdef class Graph(object):
break
else:
return False
if not self.is_mapping_valid(other, initial_map, equivalent=True):
if not self.is_mapping_valid(other, initial_map, equivalent=True, strict=True, check_labels=check_labels):
return False

return vf2.is_isomorphic(self, other, initial_map, save_order=save_order, strict=strict)
return vf2.is_isomorphic(self, other, initial_map, save_order=save_order, strict=strict, check_labels=check_labels)

cpdef list find_isomorphism(self, Graph other, dict initial_map=None, bint save_order=False, bint strict=True):
cpdef list find_isomorphism(self, Graph other, dict initial_map=None, bint save_order=False, bint strict=True, bint check_labels=False):
"""
Returns :data:`True` if `other` is subgraph isomorphic and :data:`False`
otherwise, and the matching mapping.
Expand All @@ -535,24 +540,25 @@ cdef class Graph(object):
initial_map (dict, optional): initial atom mapping to use
save_order (bool, optional): if ``True``, reset atom order after performing atom isomorphism
strict (bool, optional): if ``False``, perform isomorphism ignoring electrons
check_labels (bool, optional): if ``True``, atoms only match if their `label` attributes match
"""
return vf2.find_isomorphism(self, other, initial_map, save_order=save_order, strict=strict)
return vf2.find_isomorphism(self, other, initial_map, save_order=save_order, strict=strict, check_labels=check_labels)

cpdef bint is_subgraph_isomorphic(self, Graph other, dict initial_map=None, bint save_order=False) except -2:
cpdef bint is_subgraph_isomorphic(self, Graph other, dict initial_map=None, bint save_order=False, bint check_labels=False) except -2:
"""
Returns :data:`True` if `other` is subgraph isomorphic and :data:`False`
otherwise. Uses the VF2 algorithm of Vento and Foggia.
"""
return vf2.is_subgraph_isomorphic(self, other, initial_map, save_order=save_order)
return vf2.is_subgraph_isomorphic(self, other, initial_map, save_order=save_order, check_labels=check_labels)

cpdef list find_subgraph_isomorphisms(self, Graph other, dict initial_map=None, bint save_order=False):
cpdef list find_subgraph_isomorphisms(self, Graph other, dict initial_map=None, bint save_order=False, bint check_labels=False):
"""
Returns :data:`True` if `other` is subgraph isomorphic and :data:`False`
otherwise. Also returns the lists all of valid mappings.

Uses the VF2 algorithm of Vento and Foggia.
"""
return vf2.find_subgraph_isomorphisms(self, other, initial_map, save_order=save_order)
return vf2.find_subgraph_isomorphisms(self, other, initial_map, save_order=save_order, check_labels=check_labels)

cpdef bint is_cyclic(self) except -2:
"""
Expand Down Expand Up @@ -838,14 +844,16 @@ cdef class Graph(object):
longest_cycle = cycle
return longest_cycle

cpdef bint is_mapping_valid(self, Graph other, dict mapping, bint equivalent=True, bint strict=True) except -2:
cpdef bint is_mapping_valid(self, Graph other, dict mapping, bint equivalent=True, bint strict=True, bint check_labels=False) except -2:
"""
Check that a proposed `mapping` of vertices from `self` to `other`
is valid by checking that the vertices and edges involved in the
mapping are mutually equivalent. If equivalent is ``True`` it checks
if atoms and edges are equivalent, if ``False`` it checks if they
are specific cases of each other. If strict is ``True``, electrons
and bond orders are considered, and ignored if ``False``.
and bond orders are considered, and ignored if ``False``. If
check_labels is ``True``, atoms only match if their `label`
attributes also match.
"""
cdef Vertex vertex1, vertex2
cdef list vertices1, vertices2
Expand All @@ -855,10 +863,10 @@ cdef class Graph(object):
# Check that the mapped pairs of vertices compare True
for vertex1, vertex2 in mapping.items():
if equivalent:
if not vertex1.equivalent(vertex2, strict=strict):
if not vertex1.equivalent(vertex2, strict=strict, check_labels=check_labels):
return False
else:
if not vertex1.is_specific_case_of(vertex2):
if not vertex1.is_specific_case_of(vertex2, check_labels=check_labels):
return False

# Check that any edges connected mapped vertices are equivalent
Expand Down
14 changes: 7 additions & 7 deletions rmgpy/molecule/group.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ cdef class GroupAtom(Vertex):

cpdef apply_action(self, list action)

cpdef bint equivalent(self, Vertex other, bint strict=?) except -2
cpdef bint equivalent(self, Vertex other, bint strict=?, bint check_labels=?) except -2

cpdef bint is_specific_case_of(self, Vertex other) except -2
cpdef bint is_specific_case_of(self, Vertex other, bint check_labels=?) except -2

cpdef bint is_surface_site(self) except -2

Expand Down Expand Up @@ -190,15 +190,15 @@ cdef class Group(Graph):

cpdef update_charge(self)

cpdef bint is_isomorphic(self, Graph other, dict initial_map=?, bint generate_initial_map=?, bint save_order=?, bint strict=?) except -2
cpdef bint is_isomorphic(self, Graph other, dict initial_map=?, bint generate_initial_map=?, bint save_order=?, bint strict=?, bint check_labels=?) except -2

cpdef list find_isomorphism(self, Graph other, dict initial_map=?, bint save_order=?, bint strict=?)
cpdef list find_isomorphism(self, Graph other, dict initial_map=?, bint save_order=?, bint strict=?, bint check_labels=?)

cpdef bint is_subgraph_isomorphic(self, Graph other, dict initial_map=?, bint generate_initial_map=?, bint save_order=?) except -2
cpdef bint is_subgraph_isomorphic(self, Graph other, dict initial_map=?, bint generate_initial_map=?, bint save_order=?, bint check_labels=?) except -2

cpdef list find_subgraph_isomorphisms(self, Graph other, dict initial_map=?, bint save_order=?)
cpdef list find_subgraph_isomorphisms(self, Graph other, dict initial_map=?, bint save_order=?, bint check_labels=?)

cpdef bint is_identical(self, Graph other, bint save_order=?)
cpdef bint is_identical(self, Graph other, bint save_order=?, bint check_labels=?)

cpdef bint is_surface_site(self) except -2

Expand Down
Loading
Loading