给定图H,我必须找到满足特殊要求的所有图g(我称之为要求2)。所有这些图都存储在一组中。图g必须具有与H相同数量的顶点,并且所有图都是定向的。所以从本质上讲,我发现可以添加到g以满足要求2的边缘。我使用字典来表示我的图表,例如:
H = {
'1': {'1': set([(0, 1)])},
'3': {'3': set([(0, 1)]), '2': set([(0, 1)])},
'2': {'1': set([(0, 1)]), '3': set([(0, 1)]), '2': set([(0, 1)])},
}
表示从顶点1到1有一条边,从3到2有一条边等...请忽略现在的集合([(0,1)]),因为它们不相关我的问题。为了找到满足要求2的这些g,我向具有与H相同数量的顶点的空图g添加边,然后使用requirement1来获得我知道可能用于满足要求2的边数组。然后我添加其中一个被Requirements1认为正确的边缘到g并测试require2。为什么我不直接使用要求2是添加g没有的每个边缘然后测试其上的需求2会花费太多时间。早期修剪为我节省了时间。我继续深度优先搜索,如果需求1返回一个空数组,我知道我必须回溯。我当前的代码使用memoization存储子问题解决方案,但这段代码仍然不够快......有7个节点,这段代码可能需要2500秒才能运行。任何关于如何加快这一点的建议将不胜感激。
关于此代码使用的某些函数的更多内容:
addanedge(g,e)将边e添加到g
delanedge(g,e)删除边缘e in g
edgelist(g)返回g
的边缘列表补码(g)返回g没有的边缘列表
如果g满足某些要求,则requirement1(H,g)返回T. 否则涉及H和F.它的目的是修剪每轮需要添加的边数。
如果g满足某些涉及H和F的要求,则要求2(H,g)返回T.如果为true,我将g添加到s
备忘录存储我的子问题解决方案
gsig只是将图形g转换为我可以添加到集合中的表单。
def findgs(H):
g = {n:{} for n in H}
s = set()
@memo
def addedges(g,H,edges):
if edges:
masks = []
for e in edges:
addanedge(g,e)
if requirement1(H,g):
masks.append(False)
else:
masks.append(True)
delanedge(g,e)
nedges = [edges[i] for i in range(len(edges)) if masks[i]]
n = len(nedges)
if n:
for i in range(n):
addanedge(g,nedges[i])
if requirement2(H,g):
s.add(gsig(g))
addedges(g,H,nedges[:i]+nedges[i+1:])
delanedge(g,nedges[i])
edges = edgelist(complement(g))
addedges(g,H,edges)
return s
def memo(func):
cache = {}
@wraps(func)
def wrap(*args):
s = tool.signature(args[0],args[2])
if s not in cache:
cache[s] = func(*args)
return cache[s]
return wrap
我注意到的一件事是,满足要求2的相同图表出现了很多次并被删除,因为s是一个集合,不允许重复。