问题描述
因此,我正在进行人工化学模拟,并使用networkx的无向图来表示分子的结构。我希望能够确定两个分子是否具有相同的结构。因此,确定两个分子图是否同构是确定它们是否具有相同结构的一种适当方法。在模拟中,原子可以是不同的化学元素。因此,节点/原子具有一个标签,该标签实际上是元素的原子序数。但是,原子上也有特定的键合位点,它们也具有整数标记。例如,考虑分子结构1-1-3(虚线是边缘,数字是标记的节点/原子)。假设有两个具有这种结构但具有不同键合位点构型的分子:
1(2)-(1)1(2)-(1)3和1(1)-(2)1(1)-(1)3
其中括号中的数字是原子的键合位置。如果我使用以下代码比较这些分子,则is_isomorphic将错误地返回true:
node_match = iso.numerical_node_match('element',-1)
nx.is_isomorphic(molecule1,molecule2,node_match=node_match))
另外,如果我使每个边缘都包含bonding_sites属性(这是绑定站点的排序列表)(例如bonding_sites = [1,2]),并尝试添加边缘匹配器,则以下代码也会错误地返回正确:
edge_match = iso.categorical_edge_match('bonding_sites',None)
node_match = iso.numerical_node_match('element',node_match=node_match,edge_match=edge_match))
我想确保is_isomorphic返回false的唯一方法是引入基于节点边缘元组的某种标签匹配。但是我在networkx中找不到任何工具。谁能想到使用networkx的解决方案(我的其余代码在很大程度上依赖于此)?另外,在这里我想比较的图形类型有名称吗?
我可以想到一个稍微复杂的解决方案,即用完整的子图表示每个原子,并且该子图的每个节点表示每个键合位置。但是我想避免这种情况。
解决方法
我还没有使用networkx
,但是您可以尝试一下。可能会有帮助。
首先尝试是否可以添加类数据结构的顶点,而不是通过数字列表添加顶点。
因此,[Node(id=1),Node(id=2),Node(id=3)]
而不是[1,2,3]
。这样,您的Node类可以具有可以比较的多个属性。
如果这不起作用。
然后,您可以使用[1、2、3]并创建一个外部数据结构,例如字典。
ds = {}
class MyDataStructure:
def __init__(attrib1,):
self.attrib1 = attrib1
for i in range(10):
networkx.add_node(i)
ds[i] = MyDataStructure(myattrib=i)
您始终可以使用相同的[1,3,...]
,但现在可以使用
map(lambda i:d[i].attribute,[1,3])
返回新列表。
我认为您实际上正在寻找的是规范化方法,而不是同构,尽管它们是非常相似的概念。
https://en.wikipedia.org/wiki/Canonicalization(通常)
https://en.wikipedia.org/wiki/Graph_canonization(仅用于图形)
规范化是指将输入转换为标准形式,以便进行比较以确定它们是否等效。
请记住,分子可以表示为图形,但是从纯粹的数学意义上讲,它们并不是完全的图形,它们确实具有物理结构,并且该结构具有自己的规则,在一般的图形同构中可能无法解释。因此,我会警惕使用标准的图形同构算法,而是编写一种算法以根据实际可能的排列来搜索它们。可悲的是,我的化学有点生疏,无法给出可靠的例子,而又没有大量分子看起来与实际情况不同的不同排列的例子。您可能还需要研究子图同构。
https://en.wikipedia.org/wiki/Subgraph_isomorphism_problem https://en.wikipedia.org/wiki/Induced_subgraph_isomorphism_problem
如上所述,您也许还可以使用Canonicalizationm将分子的表示形式转换为分子结构的“标准”表示形式。从理论上讲,这至少比同构同等困难,但有可能更容易确定分子的结构(由于物理约束)。
如果您提供了一些定义分子的方法以使分子等效,那么这会有所帮助,同时还定义了可以定义分子的方法使它们相似但不相同。 / p>
例如,列出定义您提供的两个分子的所有等效方法。
另一种选择可能是研究加权图同构。