gpt4 book ai didi

递归函数中的 Python 参数

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:28:42 27 4
gpt4 key购买 nike

我正在尝试实现一个递归函数来解决这个很棒的 Udacity 类(class)中描述的 3-SAT 问题 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 中对 bool 子句/谓词进行回溯编程,其中当分支失败时变量会自动设置为上一步。

最佳答案

it behaves as if the parameter was passed by reference and not by value

在 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(...) 构造函数。

关于递归函数中的 Python 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20926999/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com