我需要为家庭作业做一个SAT求解器。我的输入给了我n个变量x1,x2 ... xn和M个子句,它们是文字的分离,由列表ex表示。 [[-1,2,3],[2,-3],[1,-3]]其中[-1,3],[2,-3]表示(~X1或X3)和(X2或〜 X3)。
我的计划是实现一个回溯解决方案,我首先选择X1 = False,然后递归检查每个其他变量的等式。
我的问题是如何设置递归。我有两个函数,一个用于检查程序中的矛盾,另一个用于根据为变量选择的真值来简化表达式。
def contradiction(clauses):
for clause in clauses:
if clause == ['F']: #checks if any clause evaluates to False
return True
for other in clauses:
if len(clause)==1 and len(other)==1:
if clause[0] == -other[0]: #checks if clauses Xi and ~Xi exist
return True
return False
def simplification(clauses, value):
new_clauses = [i for i in clauses]
for i in range(len(new_clauses)):
if -(value) in new_clauses[i]: #for assignment Xi, removes ~Xi from each clause, + vice versa
del new_clauses[i][new_clauses[i].index(-value)]
if new_clauses[i] == []:
new_clauses[i] = ['F']
if value in new_clauses[i]: #for value Xi, removes clauses satisfied by Xi
new_clauses [i] = []
return new_clauses
我希望从X1开始并递归到Xn,如果发现矛盾则停止该过程。非递归解决方案也很好。
编辑:这是我到目前为止所做的:
def isSat(clauses,variable,n):
if variable > n:
if not contradiction(clauses):
return 'satisfiable'
if contradiction(clauses):
return 'unsatisifable'
clauses1 = simplification(clauses,variable)
clauses2 = simplification(clauses,-variable)
if not contradiction(clauses1):
return isSat(clauses1,variable+1,n)
if not contradiction(clauses2):
return isSat(clauses2,variable+1,n)
return 'unsatisfiable'
基本上我需要从第一个变量开始,将其设置为true和false,并检查两种情况是否存在矛盾。然后,对于没有矛盾的每个案例,递归地测试两个案例的下一个变量。如果它到达最后一个没有矛盾的变量,它将返回可满足的。 (它只需要返回是或否)
答案 0 :(得分:0)
原来问题是在罕见的边缘情况下,同一变量在条款I.E中出现两次。 [9,-5,10,3,9]。在这种情况下,我的简化函数只会删除变量的一个实例。不应假设每个子句只有一个变量实例