[英]recursive backtracking - python. not returning value
Problem 问题
I am aware that somewhere in my function, I am not returning something I should. 我知道在函数的某个地方,我没有返回应有的东西。
I am returning the recursive call, but it appears that I am not returning "all the way out" 我正在返回递归调用,但似乎没有返回“全部”
Context 语境
I am doing a depth first search of every single combination in a list. 我正在对列表中的每个单个组合进行深度优先搜索。 Once I reach a combination that reaches a condition, I want to return.
一旦达到条件的组合,我想返回。
I am maintaining "state" of my combination and am backtracking where I should be (I think). 我正在维持合并的“状态”,并回溯到应该的位置(我认为)。
What am I doing wrong? 我究竟做错了什么?
class Combo:
def __init__(self, list):
self.staples = list
Combo has a property called "staples", consisting of a list of staple classes. 组合具有名为“装订”的属性,其中包括装订类别的列表。 I want to iterate over the list of staples in a decision tree to find an optimal number.
我想遍历决策树中的订书钉列表以找到最佳数量。
In this case, the optimal number is summed across the quantities of each staple instance in the list and stored/recalculated as a property on the Combo instance. 在这种情况下,最佳数量将在列表中每个订书钉实例的数量上相加,并作为组合实例上的属性进行存储/重新计算。
def IterateStaples(combo, target):
#Exit condition for combo dictionary
if all(combo.diff[macro] < 2 for macro in combo.diff):
return combo;
#iterate through all items in list
for staple in combo.staples:
#Increment and calc conditions
staple.increment()
combo.calcTotals()
combo.findDiff(target)
#If exceeds target value, backtrack
if combo.findConflict(target):
staple.decrement()
combo.calcTotals()
combo.findDiff(target)
#Redundant exit condition to try and return
elif all(combo.diff[macro] < 2 for macro in combo.diff):
return combo
#Recursive call
else:
return IterateStaples(combo, target)
staple.decrement()
combo.calcTotals()
combo.findDiff(target)
Your first if
statement inside the for
loop doesn't return anything. for
循环内的第一个if
语句不返回任何内容。 What it should return depends on your algorithm's logic: 它应返回的内容取决于算法的逻辑:
#If exceeds target value, backtrack
if combo.findConflict(target):
staple.decrement()
combo.calcTotals()
combo.findDiff(target)
return SOMETHING
Additionally, the last 3 lines won't ever get executed, they're after the return
statement. 此外,最近3线永远不会得到执行,他们是后
return
的语句。
If I understand your code correctly (which is more difficult than usual, since you've not shown what most of the methods you're calling on combo
and staple
are), this should be what you want: 如果我正确地理解了您的代码(这比平时更困难,因为您没有显示要在
combo
和staple
上调用的大多数方法是什么),那么这应该是您想要的:
def IterateStaples(combo, target):
# base case
if all(combo.diff[macro] < 2 for macro in combo.diff): # iterate on combo.diff.values()?
return combo # returning combo indicates success!
for staple in combo.staples:
staple.increment() # update state
combo.calcTotals()
combo.findDiff(target)
if not combo.findConflict(target): # skip recursing on invalid states
result = IterateStaples(combo, target) # recursive case
if result is not None: # if the recursion was successful, return the result
return result
staple.decrement() # otherwise, undo the change to the state (backtrack)
combo.calcTotals() # these two lines might not be necessary when backtracking
combo.findDiff(target) # since other branches will call them after staple.increment()
return None # if we got to the end of the loop, explicitly return None to signal failure
The return None
at the end is not strictly necessary, since None
is the default return value if you don't return anything else. 最后没有严格要求
return None
,因为如果您不返回其他任何内容,则None
是默认的返回值。 I just think that it's better to be explicit about it. 我只是认为最好将其明确。
I'm following your code in returning combo
on success (and extending it to returning None
on failure). 我正在遵循您的代码,如果成功则返回
combo
(并将失败时扩展为返回None
)。 Since the code mutates combo
in place, you could just as well return True
for success (in the base case at the top of the function) and False
for failure (at the bottom of the function, after the end of the loop). 由于代码会原地改变
combo
,因此您也可以返回True
表示成功(在函数的顶部是基本情况),而False
表示失败(在循环结束后在函数的底部)。 The recursive logic would pass on True
results, and backtrack after False
results. 递归逻辑将传递
True
结果,并在False
结果之后回溯。 The top-level caller would need to check the combo
instance they'd passed in for the actual solution if they got a True
return value: 如果顶级调用者获得了
True
返回值,则需要检查传入的combo
实例以获取实际的解决方案:
combo = Combo(something)
if IterateStaples(combo, target):
do_stuff(combo) # success!
I was able to pass my own test case by incorporating a helper function in the following: 通过在下面合并一个辅助函数,我能够通过自己的测试用例:
Is this not backtracking? 这不是回溯吗? I implemented N-queens with a similar approach
我用类似的方法实现了N皇后
def IterateStaples(combo, target):
#iterate through all items in list
bestCombo = []
def helper(combo):
for staple in combo.staples:
#Increment and calc conditions
staple.increment()
combo.calcTotals()
combo.findDiff(target)
#If exceeds target value, backtrack
if combo.findConflict(target):
staple.decrement()
combo.calcTotals()
combo.findDiff(target)
#Redundant exit condition to try and return
elif all(combo.diff[macro] < 2 for macro in combo.diff):
bestCombo.append(deepcopy(combo))
return
#Recursive call
else:
helper(combo)
staple.decrement()
combo.calcTotals()
combo.findDiff(target)
helper(combo)
return bestCombo
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.