Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
递归函数中的Python参数_Python_Algorithm - Fatal编程技术网

递归函数中的Python参数

递归函数中的Python参数,python,algorithm,Python,Algorithm,我正试图实现一个递归函数来解决一个3-SAT问题,如本课程中所述 我是Python编程新手,我注意到了一个我觉得奇怪的行为 事实上,当recursive3SatSolver结束时返回None,且算法回溯到新分支时,解决方案变量(在每次迭代时作为参数传递)不会设置为前一个状态,而是保留最新的值(在ended函数中修改的值) 它的行为就像是通过引用而不是通过值传递参数一样 def solve_3SAT(num_variables, clauses): solution = [-1]*(num

我正试图实现一个递归函数来解决一个3-SAT问题,如本课程中所述 我是Python编程新手,我注意到了一个我觉得奇怪的行为

事实上,当recursive3SatSolver结束时返回None,且算法回溯到新分支时,解决方案变量(在每次迭代时作为参数传递)不会设置为前一个状态,而是保留最新的值(在ended函数中修改的值)

它的行为就像是通过引用而不是通过值传递参数一样

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'
def solve_3SAT(num_变量、子句):
解决方案=[-1]*(num_变量+1)
满足条款=[0]*len(条款)
对于范围内的i(0,num_变量+1):
正=假
否定=错误
对于ID子句,枚举中的子句(子句):
正=正或(第条中的i)
否定=否定或(-i在子句中)
候选者=积极的^消极的
对于ID子句,枚举中的子句(子句):
如果我在第条中:
如果候选人:
满足条款[idClause]=1
如果候选人:
如果是肯定的:
解[i]=1
其他:
解[i]=0
解决方案[0]=0
打印“预处理:”,解决方案
solution=recursive3SatSolver(num_变量、解决方案、子句)
如果是解决方案!=无:
对于枚举(解决方案)中的ID,s:
如果解决方案[idS]
它的行为就像是通过引用而不是通过值传递参数一样

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'
在Python中,每个对象都是通过引用传递的。在您的情况下,如果
解决方案
是一个列表,您可能应该复制它

您可以使用以下一些方法:

>>> 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]

我首选的方法是使用
列表(…)
构造函数

它的行为是这样的,因为这正是正在发生的事情,因为Python就是这样工作的。请看一看以下问题的答案,这些问题解释了变量在Python中的工作方式。这里有很多代码,但您的问题涉及一个相当具体和狭窄的行为。我想我知道哪里出了问题,但是你能举一个简单的例子来说明同样的行为吗?这将使你的问题更容易理解;这也将使这种现象更容易解释;在Python中,每个对象都是按值传递的。即使引用也是按值传递的——在本例中,也会传递引用的副本。@ÓscarLópez。如果传递一个
mutable
对象,对象引用(id(object))将按值传递。这意味着对象get通过引用传递。这更是一个语法问题,因为你不能认为一个列表的价值是它的参考,你能吗?尤其是在高级语言中。(另请参见sys.getrefcount)此外,它实际上并没有传递任何值,而是增加对象的
refcount
,并将其引用绑定到新名称(变量)。请正确理解您的概念。这已经被讨论过无数次了。Python是按值传递的,就像Java一样。只是在对象的情况下,传递的值是一个引用