如何在没有DFS / BFS的情况下枚举哈密顿循环的可能重建?

时间:2013-08-15 14:27:30

标签: python graph

我有一个有向哈密顿循环:

[..., a, b, ... , c, d, ..., e, f, ...]

b = next(a)d = next(c)f = next(e)

假设我删除了边(a,b),(c,d)和(e,f)。

问题:如何生成图形的所有可能的重组,使其保持哈密顿循环(请记住,我可能必须反转其中一个部分中的顺序来修复方向) ?

我所知道的

我知道通过去除n边可达到的新汉密尔顿周期数是double-factorial(n-1)。我也知道,如果我删除两个连续的边,我会得到重复的解决方案(我很好......它们相对于唯一的循环应该是最小的并且它保持结果代码干净)。

我尝试过的(粗略的伪代码)

考虑到这一点的一种方法是,任何屈服的哈密尔顿循环都必须保留必须沿着断开图形的部分行进的属性,然后再跳到新的部分。

因此,例如,考虑上面的循环(n = 3),有以下3个部分:

[b, ..., c]
[d, ..., e]
[f, ..., a]

所以,让我们说我的新解决方案如下:

[..., a, d, ...]

我知道e是我的终端顶点列表中必须出现的顶点。

因此,使用这个想法,Python将是这样的:

from itertools import permutations

def hamiltonian_cycles(l, s=None, r=None):
    if s is None:
        s = [l[0]]
    if r is None:
        r = l[1:]
    if not r:
        yield s
    else:
        for permutation in permutations(r):
            s1 = s[:] + [permutation[0]]
            for cycle in hamiltonian_cycles(l, s1, permutation[1:]):
                yield cycle
            s2 = s[:] + [(permutation[0][1], permutation[0][0])]
            for cycle in hamiltonian_cycles(l, s2, permutation[1:]):
                yield cycle

>>> l = [('f', 'a'), ('b', 'c'), ('d', 'e')]
>>> for cycle in hamiltonian_cycles(l):
...    print(cycle)
[('f', 'a'), ('b', 'c'), ('d', 'e')]
[('f', 'a'), ('b', 'c'), ('e', 'd')]
[('f', 'a'), ('c', 'b'), ('d', 'e')]
[('f', 'a'), ('c', 'b'), ('e', 'd')]
[('f', 'a'), ('d', 'e'), ('b', 'c')]
[('f', 'a'), ('d', 'e'), ('c', 'b')]
[('f', 'a'), ('e', 'd'), ('b', 'c')]
[('f', 'a'), ('e', 'd'), ('c', 'b')]

这看起来很丑陋并且停止了过去n=3,因此问题就在这里。

为什么我不想使用BFS / DFS

我需要一个删除边数为线性的生成器,而不是总边数+顶点数。

2 个答案:

答案 0 :(得分:1)

感谢这个有用的答案here,这是执行此操作的代码。

from itertools import chain, permutations, product

def new_edge_sets(deleted_edges):

    def edges_to_pieces(l):
        new_list = []
        n = len(l)
        for i in xrange(-1,n-1):
            new_list.append((l[i%n][1], l[(i+1)%n][0]))
        return new_list

    def permute(it):
        return product(*(permutations(i) for i in it))

    def permute2(it):
        return chain.from_iterable(permute(p) for p in permutations(it))

    def pieces_to_edges(p):
        new_list = []
        n = len(p)
        for i in xrange(n):
            new_list.append((p[i%n][1], p[(i+1)%n][0]))
        return new_list

    def permute3(s):
        return (pieces_to_edges(s[:1] + list(p)) for p in permute2(s[1:]))

    return permute3(edges_to_pieces(deleted_edges))

示例:

>>> deleted_edges = [('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', 'h')]
>>> l = list(new_edge_sets(deleted_edges))
>>> len(l)
48
>>> for new_edges in l:
...     print(new_edges)
[('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', 'h')]
[('a', 'b'), ('c', 'd'), ('e', 'g'), ('f', 'h')]
[('a', 'b'), ('c', 'e'), ('d', 'f'), ('g', 'h')]
[('a', 'b'), ('c', 'e'), ('d', 'g'), ('f', 'h')]
[('a', 'c'), ('b', 'd'), ('e', 'f'), ('g', 'h')]
[('a', 'c'), ('b', 'd'), ('e', 'g'), ('f', 'h')]
[('a', 'c'), ('b', 'e'), ('d', 'f'), ('g', 'h')]
[('a', 'c'), ('b', 'e'), ('d', 'g'), ('f', 'h')]
[('a', 'b'), ('c', 'f'), ('g', 'd'), ('e', 'h')]
[('a', 'b'), ('c', 'f'), ('g', 'e'), ('d', 'h')]
[('a', 'b'), ('c', 'g'), ('f', 'd'), ('e', 'h')]
[('a', 'b'), ('c', 'g'), ('f', 'e'), ('d', 'h')]
[('a', 'c'), ('b', 'f'), ('g', 'd'), ('e', 'h')]
[('a', 'c'), ('b', 'f'), ('g', 'e'), ('d', 'h')]
[('a', 'c'), ('b', 'g'), ('f', 'd'), ('e', 'h')]
[('a', 'c'), ('b', 'g'), ('f', 'e'), ('d', 'h')]
[('a', 'd'), ('e', 'b'), ('c', 'f'), ('g', 'h')]
[('a', 'd'), ('e', 'b'), ('c', 'g'), ('f', 'h')]
[('a', 'd'), ('e', 'c'), ('b', 'f'), ('g', 'h')]
[('a', 'd'), ('e', 'c'), ('b', 'g'), ('f', 'h')]
[('a', 'e'), ('d', 'b'), ('c', 'f'), ('g', 'h')]
[('a', 'e'), ('d', 'b'), ('c', 'g'), ('f', 'h')]
[('a', 'e'), ('d', 'c'), ('b', 'f'), ('g', 'h')]
[('a', 'e'), ('d', 'c'), ('b', 'g'), ('f', 'h')]
[('a', 'd'), ('e', 'f'), ('g', 'b'), ('c', 'h')]
[('a', 'd'), ('e', 'f'), ('g', 'c'), ('b', 'h')]
[('a', 'd'), ('e', 'g'), ('f', 'b'), ('c', 'h')]
[('a', 'd'), ('e', 'g'), ('f', 'c'), ('b', 'h')]
[('a', 'e'), ('d', 'f'), ('g', 'b'), ('c', 'h')]
[('a', 'e'), ('d', 'f'), ('g', 'c'), ('b', 'h')]
[('a', 'e'), ('d', 'g'), ('f', 'b'), ('c', 'h')]
[('a', 'e'), ('d', 'g'), ('f', 'c'), ('b', 'h')]
[('a', 'f'), ('g', 'b'), ('c', 'd'), ('e', 'h')]
[('a', 'f'), ('g', 'b'), ('c', 'e'), ('d', 'h')]
[('a', 'f'), ('g', 'c'), ('b', 'd'), ('e', 'h')]
[('a', 'f'), ('g', 'c'), ('b', 'e'), ('d', 'h')]
[('a', 'g'), ('f', 'b'), ('c', 'd'), ('e', 'h')]
[('a', 'g'), ('f', 'b'), ('c', 'e'), ('d', 'h')]
[('a', 'g'), ('f', 'c'), ('b', 'd'), ('e', 'h')]
[('a', 'g'), ('f', 'c'), ('b', 'e'), ('d', 'h')]
[('a', 'f'), ('g', 'd'), ('e', 'b'), ('c', 'h')]
[('a', 'f'), ('g', 'd'), ('e', 'c'), ('b', 'h')]
[('a', 'f'), ('g', 'e'), ('d', 'b'), ('c', 'h')]
[('a', 'f'), ('g', 'e'), ('d', 'c'), ('b', 'h')]
[('a', 'g'), ('f', 'd'), ('e', 'b'), ('c', 'h')]
[('a', 'g'), ('f', 'd'), ('e', 'c'), ('b', 'h')]
[('a', 'g'), ('f', 'e'), ('d', 'b'), ('c', 'h')]
[('a', 'g'), ('f', 'e'), ('d', 'c'), ('b', 'h')]

答案 1 :(得分:1)

生成所有可能的哈密顿循环。试一试

MatrixOperations模块通过矩阵操作(如打印和stuff.u)实现自我控制,可以尝试使用普通的打印语句
from matrix import MatrixOperations
A=[[0,1,0,1,1,0,0],[1,0,1,0,0,0,0],[0,1,0,1,0,0,1],[1,0,1,0,1,0,1],[1,0,0,1,0,1,0],[0,0,0,0,1,0,1],[0,0,1,1,0,1,0]]
print("THE ADJACENCY MATRIX\n");MatrixOperations.PrintMatrix(A)
n=len(A)
X=[]
vis=[0 for i in range(n)]
def hamiltonian(vis,A,i):
    vis[i]=1
    if(len(X)==n-1 and A[i][0]==1):
        print (X)   
    for j in range(0,n):
        if (vis[j]==0 and A[i][j]==1):
            X.append(j)

            #print(X) this print shows the whole tracing process
            hamiltonian(vis,A,j)

    if(len(X)>0):
        del X[-1]
        vis[i]=0
print("\nPossible Hamiltonian cycles")
hamiltonian(vis,A,0)