[英]Python parameters in recursive functions
我正在嘗試實現一個遞歸函數來解決3-SAT問題,如本本很棒的Udacity課程中所述:https: //www.udacity.com/course/cs313我是Python編程的新手,並且注意到我發現了一個行為奇怪。
事實是,當recursive3SatSolver結束時返回None且該算法回溯到新分支時,解決方案變量(在每次迭代中作為參數傳遞)未設置為先前狀態,而是保留為最新值(在結束函數中修改的值) )
它的行為就像參數是通過引用而不是通過值傳遞的
def solve_3SAT(num_variables, clauses):
solution = [-1]*(num_variables+1)
satisfiedClauses = [0]*len(clauses)
for i in range(0, num_variables+1):
positive = False
negative = False
for idClause,clause in enumerate(clauses):
positive = positive or (i in clause)
negative = negative or (-i in clause)
candidate = positive ^ negative
for idClause,clause in enumerate(clauses):
if i in clause:
if candidate:
satisfiedClauses[idClause]=1
if candidate:
if positive:
solution[i]=1
else:
solution[i]=0
solution[0]=0
print 'preprocessing: ',solution
solution = recursive3SatSolver(num_variables,solution,clauses)
if solution != None:
for idS,s in enumerate(solution):
if solution[idS]<0:
solution[idS]=0
return solution
def recursive3SatSolver(num_variables, solution, clauses):
if is_satisfiable(clauses,solution)==False:
return None
satisfiedClauses = satisfied_clauses(clauses,solution)
for idC,sat in enumerate(satisfiedClauses):
if sat == 0:
chosenClause=idC
clause = clauses[chosenClause]
for idVar,var in enumerate(clause):
absVar = abs(var)
if solution[absVar]<0:
value=-1
if var>0:
value=1
else:
value=0
solution[absVar]=value
if is_satisfied(num_variables,clauses,solution):
return solution
else:
finalSolution = recursive3SatSolver(num_variables,solution,clauses)
if finalSolution!=None:
#print 'returning ...'
return finalSolution
else:
print 'changing branch: ',solution,'=>'
solution[absVar]=1-solution[absVar]
continue
print 'finished possibilities for this clause'
return None
if is_satisfied(num_variables,clauses,solution):
return solution
else:
print 'no more clauses'
return None
def satisfied_clauses(clauses,assignment):
satisfiedClauses= [0]*len(clauses)
for idClause,clause in enumerate(clauses):
if is_clause_satisfied(clause,assignment):
satisfiedClauses[idClause]=1
return satisfiedClauses
def is_satisfiable(clauses, assignment):
for clause in clauses:
if is_clause_satisfiable(clause,assignment):
continue
else:
return False
return True
def is_clause_satisfiable(clause,assignment):
sat = is_clause_satisfied(clause,assignment)
if sat :
return True
else:
for idVar, var in enumerate(clause):
absVar = abs(var)
if assignment[absVar]==-1:
return True
return False
def is_clause_satisfied(clause,assignment):
for idVar,var in enumerate(clause):
absVar = abs(var)
if assignment[absVar]<0:
continue
if var>0:
if assignment[absVar]==1:
return True
else:
if assignment[absVar]==0:
return True
return False
def is_satisfied(num_variables, clauses, assignment):
if assignment==None:
return False
check=True
for clause in clauses:
clauseVal = False;
for var in clause:
val=False;
if var<0:
val = not assignment[abs(var)]
else:
val = assignment[var]
clauseVal = clauseVal or val
check = check and clauseVal
return check
def test():
clauses = [[-2, -3, -1], [3, -2, 1], [-3, 2, 1],
[2, -3, -1], [3, -2, 1], [3, -2, 1]]
solutions = [[0, 0, 0, 0],
[0, 0, 1, 1],
[0, 1, 0, 0],
[0, 1, 1, 0],
[1, 0, 0, 0],
[1, 0, 1, 1],
[1, 1, 0, 0],
[1, 1, 1, 0]]
assert solve_3SAT(3,clauses) in solutions
clauses = [[2, 1, 3], [-2, -1, 3], [-2, 3, -1], [-2, -1, 3],
[2, 3, 1], [-1, 3, -2], [-3, 2, 1], [1, -3, -2],
[-2, -1, 3], [1, -2, -3], [-2, -1, 3], [-1, -2, -3],
[3, -2, 1], [2, 1, 3], [-3, -1, 2], [-3, -2, 1],
[-1, 3, -2], [1, 2, -3], [-3, -1, 2], [2, -1, 3]]
assert solve_3SAT(3,clauses) == None
print 'Tests passed'
clauses = [[2, 1, 3], [-2, -1, 3], [-2, 3, -1], [-2, -1, 3],
[2, 3, 1], [-1, 3, -2], [-3, 2, 1], [1, -3, -2],
[-2, -1, 3], [1, -2, -3], [-2, -1, 3], [-1, -2, -3],
[3, -2, 1], [2, 1, 3], [-3, -1, 2], [-3, -2, 1],
[-1, 3, -2], [1, 2, -3], [-3, -1, 2], [2, -1, 3]]
assert solve_3SAT(3,clauses) == None
print 'Tests passed'
更新我一直在想為什么我需要一些時間才能做到這一點。 而且我已經知道原因是我習慣於對Prolog中的布爾子句/謂語進行回溯編程,其中當分支失敗時,變量會自動設置為上一步。
它的行為就像參數是通過引用而不是通過值傳遞的
每個對象都通過Python中的引用傳遞。 在您的情況下,如果solution
是一個列表,則可能應復制它。
您可以使用一些方法:
>>> l = [0,1,2]
>>> list(l) # creates a new list from the old one
[0, 1, 2]
>>> l[:] # slices also create a new object
[0, 1, 2]
>>> import copy
>>> copy.deepcopy(l) # create a deep copy of the object
[0, 1, 2]
>>> [i for i in l] # manually copy an object
[0, 1, 2]
我的首選方法是使用list(...)
構造函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.