Edit stdlib2.rst: Tools for Working with Lists: edit implementation of breadth_first_search() #111925
Edit stdlib2.rst: Tools for Working with Lists: edit implementation of breadth_first_search() #111925zipperer wants to merge 2 commits into
Conversation
I claim the implementation of `breadth_first_search` is incorrect because: - the search does not check whether `is_goal(starting_node)` - the search stops after it checks+enqueues each child of `starting_node` -- put differently: the search enqueues each child of `starting_node` but does not proceed to apply `gen_moves` to each child So, the implementation will fail to return `starting_node` when `is_goal(starting_node)` and it will fail to return a goal if that goal has depth > 1. This commit proposes two changes: - check whether `is_goal(starting_node)` - use `while` so search continues after it enqueues children of `starting_node` This commit does not propose adding a set for visited nodes, because the example specifies tree searches rather than graph searches: "These objects are well suited for implementing queues and breadth first tree searches...".
|
Before and after this commit, the implementation takes it as given that: when |
|
Further, the implementation in this commit relies on an empty deque evaluating to false in a boolean context. (https://docs.python.org/3/library/stdtypes.html#truth-value-testing). That is, |
|
You think that It does not check It only implements a single step of the search. This is why it takes For example take the eight queens puzzle. The cc @rhettinger |
|
Hey, @serhiy-storchaka Thank you for your reply! It is very helpful.
I agree. From the name I inferred the intent is to perform breadth first search through the entire space of nodes -- either returning a goal node when found or failing after having visited every node. But there is no evidence (e.g. a docstring, test, comment, or surrounding text) that states that is the intent. So, I inferred more than what is stated. The intent of Given that:
we can close the pull request and mark it invalid. Additional notes
I agree it implements only a single step of the search and that it can be called repeatedly to possibly return a result or enqueue more nodes. The version in the commit on this pull request executes the body repeatedly in the This is another version of how I was thinking about it: def expand_next_unsearched_node(unsearched): # -> Optional[Node]; modifies input unsearched
node = unsearched.popleft()
if is_goal(node):
return node
for m in gen_moves(node):
unsearched.append(m)
def breadth_first_search(starting_node): # -> Optional[Node]
unsearched = deque([starting_node])
while unsearched:
goal_node_or_none = expand_next_unsearched_node(unsearched)
if goal_node_or_none is not None:
return goal_node_or_nonewhere the version in the docs corresponds to
I think I see why that suggests the intent of
I agree that in the example you provide the Thank you again! |
I claim: the implementation of
breadth_first_searchis incorrect.Argument 1:
The search does not check whether
is_goal(starting_node).So, the implementation will fail to return
starting_nodewhenis_goal(starting_node).Argument 2:
The search stops after it checks and enqueues each child of
starting_node. Put differently: the search enqueues each child ofstarting_nodebut does not proceed to applygen_movesto each child.So, the implementation will fail to return a goal if that goal has depth > 1.
This commit proposes two changes:
is_goal(starting_node)whileso search continues after it enqueues each child ofstarting_nodeThis commit does not propose adding a set for visited nodes, because the example specifies tree searches rather than graph searches: "These objects are well suited for implementing queues and breadth first tree searches...".
📚 Documentation preview 📚: https://cpython-previews--111925.org.readthedocs.build/