简体   繁体   English

全路径算法中的Python和列表可变性

[英]Python and list mutability in an all-paths algorithm

I've been working on a all-simple-paths algorithm in python based off of networkx's version . 我一直在基于networkx的版本开发 python中的全简单路径算法。 At the moment the only changes I'm trying to make are to get it to get ALL paths for ALL nodes without doing it inside of a O(n^2) double loop. 目前,我要进行的唯一更改是获取它的所有节点的所有路径,而无需在O(n ^ 2)双循环内进行。

I believe I have the main algorithm sorted, but I'm not quite used to the mutability of Python's list structure and I think that's what's messing up the algorithm. 我相信我已经对主要算法进行了排序,但是我还不太习惯Python列表结构的可变性,我认为这是在弄乱算法。

I've written a similar program in Java so I know how many paths there should be on a test graph, but I can't seem to even get the numbers reasonably close. 我已经用Java编写了一个类似的程序,所以我知道测试图上应该有多少条路径,但是我似乎甚至无法使数字合理地接近。

def _all_simple_paths_graph(DG, cutoff):
    uniquePaths = []
    nlist = DG.nodes()
    for source in nlist:
        uniqueTreePaths = []
        if cutoff < 1:
            return
        visited = [source]
        stack = [iter(DG[source])]
        while stack:
            children = stack[-1]
            child = next(children, None)
            if child is None:
                stack.pop()
                visited.pop()
            elif len(visited) < cutoff:
                if child not in visited:
                    visited.append(child)
                    stack.append(iter(DG[child]))
                    if visited not in uniqueTreePaths:
                        yield visited
                        uniqueTreePaths.append(visited)
            else: #len(visited) == cutoff:
                if visited not in uniqueTreePaths:
                    yield visited + [child]
                    uniqueTreePaths.append(visited)
                stack.pop()
                visited.pop()
    uniquePaths.extend(uniqueTreePaths)

Can anyone tell me where I've gone wrong? 谁能告诉我我哪里出问题了? I believe it's to do with where visited should be mutable and where it shouldn't. 我认为这与visited应该是可变的和不应该的有关。 However, I could also have got the basic functionality wrong, I'm fairly new to Python! 但是,我也可能将基本功能弄错了,我对Python还是很新!

You didn't specify what the symptom is. 您没有指定症状是什么。 Is the yielded stuff wrong, or is uniquePaths wrong? 产生的东西是错误的,还是uniquePaths是错误的? It looks like that the function yields the right paths, but at the end of the function, uniquePaths has far fewer paths than it should, and they're all empty. 看起来该函数产生了正确的路径,但是在该函数的结尾, uniquePaths的路径远远少于应有的路径,并且它们都是空的。

The reason why there's not enough paths, is that uniquePaths.extend(uniqueTreePaths) is not at the right indention. 路径不足的原因是uniquePaths.extend(uniqueTreePaths)不在正确的缩进位置。

The problem you're here for, is that visited is a mutable list. 您在这里遇到的问题是visited的列表是可变的。 In Python, all lists are mutable. 在Python中,所有列表都是可变的。 In fact, that's the reason this algorithm works. 实际上,这就是该算法起作用的原因。 visited is treated like a stack that happens to be the path. visited对象就像是碰巧是路径的堆栈一样。 When you append visited to uniqueTreePaths multiple times, you are really appending the same object over and over again. 当您多次将visited对象附加到uniqueTreePaths ,实际上是一次又一次地添加相同的对象。 When you modify visited , all of them are modified. 修改visited ,所有这些都将被修改。

To fix this problem, you should append a copy of the list. 若要解决此问题,您应该附加列表的副本。 This is going to be fairly expensive memory-wise, but you wanted all unique paths in a graph, so you should've been aware of that already. 这在内存方面将是非常昂贵的,但是您需要图形中的所有唯一路径,因此您应该已经意识到这一点。 You can use uniqueTreePaths.append(list(visited)) to make a new list object out of visited . 您可以使用uniqueTreePaths.append(list(visited))使一个新的list对象进行的visited I would actually create a tuple out of it, so that it can't be modified: uniqueTreePaths.append(tuple(visited)) . 我实际上会从中创建一个元组,以便无法对其进行修改: uniqueTreePaths.append(tuple(visited))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM