什么是枚举父图的所有子图的有效算法。在我的特定情况下,父图是一个分子图,因此它将被连接,通常包含少于100个顶点。
编辑:我只对连接的子图感兴趣。
答案 0 :(得分:4)
什么是枚举父图的所有子图的有效算法。在我的特定情况下,父图是一个分子图,因此它将被连接,通常包含少于100个顶点。
与数学子图的比较:
你可以给每个元素一个从0到N的数字,然后将每个子图枚举为长度为N的任何二进制数。你根本不需要扫描图形。
如果你真正想要的是具有不同属性(完全连接等)的子图,那么你需要更新你的问题。正如评论家指出的那样,2 ^ 100非常大,所以你绝对不希望(如上所述)枚举数学上正确但物理上无聊的断开子图。假设每秒有10亿次枚举,至少需要40万亿年来计算所有这些内容,它真的会占用你。
<强>连接 - 子 - 发电机:强>
如果您希望某种枚举在某个指标下保留子图的DAG属性,例如(1,2,3) - &gt;(2,3) - &gt;(2),(1,2,3) - &gt;(1,2) - &gt;(2),你只需要一个可以生成所有CONNECTED子图作为迭代器的算法(产生每个元素)。这可以通过一次递归地移除单个元素(可选地从“边界”),检查剩余的元素集是否在缓存中(否则添加它),产生它并递归来实现。如果你的分子非常链状,只有很少的循环,这种方法很好。例如,如果你的元素是N个元素的五角星,那么它只有大约(100/5)^ 5 = 320万个结果(不到一秒)。但是,如果你开始添加一个以上的戒指,例如芳香族化合物和其他物质,你可能会陷入困境。
e.g。在python中
class Graph(object):
def __init__(self, vertices):
self.vertices = frozenset(vertices)
# add edge logic here and to methods, etc. etc.
def subgraphs(self):
cache = set()
def helper(graph):
yield graph
for element in graph:
if {{REMOVING ELEMENT WOULD DISCONNECT GRAPH}}:
# you fill in above function; easy if
# there is 0 or 1 ring in molecule
# (keep track if molecule has ring, e.g.
# self.numRings, maybe even more data)
# if you know there are 0 rings the operation
# takes O(1) time
continue
subgraph = Graph(graph.vertices-{element})
if not subgraph in cache:
cache.add(subgraph)
for s in helper(subgraph):
yield s
for graph in helper(self):
yield graph
def __eq__(self, other):
return self.vertices == other.vertices
def __hash__(self):
return hash(self.vertices)
def __iter__(self):
return iter(self.vertices)
def __repr__(self):
return 'Graph(%s)' % repr(set(self.vertices))
演示:
G = Graph({1,2,3,4,5})
for subgraph in G.subgraphs():
print(subgraph)
结果:
Graph({1, 2, 3, 4, 5})
Graph({2, 3, 4, 5})
Graph({3, 4, 5})
Graph({4, 5})
Graph({5})
Graph(set())
Graph({4})
Graph({3, 5})
Graph({3})
Graph({3, 4})
Graph({2, 4, 5})
Graph({2, 5})
Graph({2})
Graph({2, 4})
Graph({2, 3, 5})
Graph({2, 3})
Graph({2, 3, 4})
Graph({1, 3, 4, 5})
Graph({1, 4, 5})
Graph({1, 5})
Graph({1})
Graph({1, 4})
Graph({1, 3, 5})
Graph({1, 3})
Graph({1, 3, 4})
Graph({1, 2, 4, 5})
Graph({1, 2, 5})
Graph({1, 2})
Graph({1, 2, 4})
Graph({1, 2, 3, 5})
Graph({1, 2, 3})
Graph({1, 2, 3, 4})
答案 1 :(得分:4)
此问题在this question的已接受答案中有更好的答案。它避免了在@ninjagecko的回答中标记为“你填写以上函数”的计算复杂步骤。它可以有效地处理有多个环的化合物。
有关详细信息,请参阅链接的问题,但这是摘要。 (N(v)表示顶点v的邻居集合。在“选择顶点”步骤中,您可以选择任意任意顶点。)
GenerateConnectedSubgraphs(verticesNotYetConsidered, subsetSoFar, neighbors):
if subsetSoFar is empty:
let candidates = verticesNotYetConsidered
else
let candidates = verticesNotYetConsidered intersect neighbors
if candidates is empty:
yield subsetSoFar
else:
choose a vertex v from candidates
GenerateConnectedSubgraphs(verticesNotYetConsidered - {v},
subsetSoFar,
neighbors)
GenerateConnectedSubgraphs(verticesNotYetConsidered - {v},
subsetSoFar union {v},
neighbors union N(v))