Any alternative to a (very slow) deepcopy in a DFS?

随声附和 提交于 2019-12-02 00:48:36

Deepcopy can be a lot slower than simply copying the same amount of data, presumably because of all the effort that goes into detecting loops. If you copy your graph yourself in a way that avoids loops (easy, since you know the network topology) instead of delegating to deepcopy, it's likely to give you a serious speed-up. I got a 50% speedup for copying a very simple data structure element-wise (using comprehensions), and it wouldn't surprise me if complex ones gave even bigger savings.

Of course there's a bigger speedup to be gained if you can avoid making a complete copy of your entire state at each step. For example, since you're searching depth first, you could switch your approach to maintaining an undo stack: just record each list of choices you selected from, and restore them as you backtrack.

cPickle is faster than deepcopy:

Line # Hits Time Per Hit % Time Line Contents

15                                           @profile
16                                           def test():
17       100       967139   9671.4     95.0      b = deepcopy(a)
18                                               #c = copy(a)
19                                               #d = ujson.loads(ujson.dumps(a))
20                                               #e = json.loads(json.dumps(a))
21                                               #f = pickle.loads(pickle.dumps(a, -1))
22       100        50422    504.2      5.0      g = cPickle.loads(cPickle.dumps(a, -1))

do you need to copy the whole graph? typically you are only going to modify a small part of it at any step in the search, so it may be more efficient to use immutable data structures and only rebuild what is needed. this doesn't work for loops, but i suspect your graph is a list?

i solved a similar problem in clojure, which has native support for immutable structures, and managed to get reasonable efficiency in this way. but i don't know of any immutable datastructure libraries for python (there is a copy-on-write list package somewhere - would that be sufficient?)

[just to clarify with a simple example - you're right that tuples are immutable, so if you had a tree made of tuples like this: (1, (2, 3), (4, (5, 6))) then you could generate a new tree like this (1, (2, 99), (4, (5, 6))) by creating just two tuples - you can copy the (4, (5, 6)) without doing a deep copy. what clojure has, and what i don't know of for python, are much more complex structures (like hash tables) that follow the same principle. it makes dfs really easy, because you don't have to worry about changing values "upstream" at all.]

ps it was only through doing what you are doing, and seeing the costs involved, that i understood the elegance of norvig's approach...

I'm not fully cognizant of the sudoku specifics, but what if you use a single copy of your graph and give each node a class that includes:

1) The list of adjacent vertices 2) A "visited" flag that can be used to keep track of what's already been seen and what hasn't

?

Your Depth First Search can still be recursive, but instead of packaging up modified subsets of your graph, you just mark a node "visited" and continue on until there's nowhere else to go. If your graph is connected, it seems like it should work...

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!