子圖枚舉
回答
這個問題有在接受答案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))
什麼是枚舉父圖的所有子圖的有效算法。在我的具體情況中,父圖是分子圖,因此它將被連接並且通常包含少於100個頂點。
比較用數學子圖:
你可以給每個元件的數目從0到N,然後枚舉每個子圖作爲長度爲N的任何二進制數你不會需要掃描圖形在所有。
如果你真的想要的是具有某種屬性的子圖(完全連接等),那麼你需要更新你的問題。正如一位評論員指出的那樣,2^100非常大,所以你絕對不希望(像上面那樣)列舉數學上正確但物理上無聊的斷開的子圖。如果假設每秒鐘進行十億次計數,至少需要40萬億年才能列舉出所有這些數據,否則它會從字面上把你帶走。
連接 - 子發電機:
如果你想要某種枚舉的,在某些指標保留子圖的DAG屬性,例如(1,2,3) - >(2,3) - >(2),(1,2,3) - >(1,2) - >(2),您只需要一個可以生成所有CONNECTED子圖都作爲迭代器(產生每個元素)。這可以通過遞歸地刪除單個元素(可選地從「邊界」)來完成,檢查剩餘的元素集是否在緩存中(否則添加它),產生它並遞歸。如果您的分子非常連鎖且週期非常短,這種方法很好。例如,如果你的元素是一個N元素的五角星,它只會有(100/5)^ 5 = 320萬個結果(小於1秒)。但是,如果您開始添加多個單個戒指,例如芳香族化合物和其他,你可能會很難過。
例如在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})
不幸的是,化合物中往往會有一個或幾個環。但是在最大環數爲零的情況下,你的算法應該沒問題。 – Narwe 2011-05-13 13:31:04
我認爲{對於子圖的粗略數量,{環的直徑或某物的某個最小直徑,或環可能加入以形成更復雜結構的方式(例如在晶體中)}可能比環的數量更重要。這是一個單獨的問題,而不是能夠優化代碼中上面的註釋中生成連續的子圖。不相關的是,由於空間結構的原因,可能會有很好的方法來基於三維空間中的嵌入來細分問題。儘管如此。 – ninjagecko 2011-05-13 18:03:49
- 1. 將枚舉映射到「子枚舉」
- 2. Java:舊枚舉子集的新枚舉
- 3. 駱駝藍圖:在枚舉值枚舉
- 4. 枚舉圖像資源枚舉
- 5. 地圖枚舉爲[標誌]枚舉
- 6. 枚舉圖
- 7. UML類圖枚舉
- 8. 枚舉子範圍在ADA
- 9. 有效枚舉子集
- 10. 枚舉Google電子表格?
- 11. 枚舉prolog的子列表
- 12. 枚舉註冊表子項
- 13. 轉換枚舉來枚舉
- 14. 枚舉的枚舉[JAVA]
- 15. 帶枚舉的MySQL枚舉
- 16. Java類枚舉枚舉類
- 17. 重新枚舉枚舉
- 18. Java枚舉找到枚舉
- 19. 在枚舉中枚舉
- 20. 設置基於國家枚舉一個子狀態枚舉
- 21. C#中的枚舉子集或子集
- 22. 可枚舉裝飾圖案
- 23. 定義枚舉地圖
- 24. 枚舉「地圖」可變
- 25. 休眠3地圖枚舉
- 26. 修改圖像枚舉
- 27. JPA地圖集合枚舉
- 28. 枚舉matplotlib中的圖塊
- 29. 在枚舉語句中枚舉mysql枚舉
- 30. 地圖一個枚舉另一個枚舉
你想要的所有子圖或全部連通子? – 2011-05-12 21:12:47
無論您的效率如何,都需要花費時間來枚舉2^100個頂點子集,並且在您考慮邊緣可以存在與否之前。你能在太陽爆炸之前切換到可能完成的問題嗎? – btilly 2011-05-12 21:27:46
@btilly:你說的對,假設它是一個頂點標記圖,通常在應用程序中就是這種情況。如果頂點未被標記(即它們不可區分),則例如在n個頂點上的完整圖只有n個子圖(包括它本身)。 – 2011-05-13 01:53:15