Algorithm 从SAT到3-SAT的转换器

Algorithm 从SAT到3-SAT的转换器,algorithm,satisfiability,reference-implementation,Algorithm,Satisfiability,Reference Implementation,有谁知道一个好的程序可以将每个子句包含任意数量变量的CNF文件转换为每个子句包含3个变量的CNF文件(3-CNF)?我在计算机科学书籍中看到过这个算法,但在任何地方都找不到实现,如果别人已经实现了,我也不愿意浪费时间自己实现它。谢谢 SAT在多项式时间内是不可解的(根据目前的知识)。 2-SAT在多项式时间内是可解的 因此,从通用SAT到2-SAT的转换不会很快(不是在多项式时间内),否则我们会找到一个用于SAT的多项式时间算法 换句话说,将SAT转换为2-SAT所需的时间与只解SAT所需的时间

有谁知道一个好的程序可以将每个子句包含任意数量变量的CNF文件转换为每个子句包含3个变量的CNF文件(3-CNF)?我在计算机科学书籍中看到过这个算法,但在任何地方都找不到实现,如果别人已经实现了,我也不愿意浪费时间自己实现它。谢谢

SAT在多项式时间内是不可解的(根据目前的知识)。 2-SAT在多项式时间内是可解的

因此,从通用SAT到2-SAT的转换不会很快(不是在多项式时间内),否则我们会找到一个用于SAT的多项式时间算法

换句话说,将SAT转换为2-SAT所需的时间与只解SAT所需的时间大致相同


也许你指的是3-SAT,而不是2-SAT?

我也不知道任何程序可以这样做,但算法非常简单,所以我编写了以下python脚本(),它以DIMACS格式读取一般CNF,并以DIMACS格式写入等效3-SAT问题的CNF:

from __future__ import print_function
import fileinput

cnf = list()
cnf.append(list())
maxvar = 0

for line in fileinput.input():
    tokens = line.split()
    if len(tokens) == 0 or tokens[0] == "p" or tokens[0] == "c":
        continue
    for tok in tokens:
        lit = int(tok)
        maxvar = max(maxvar, abs(lit))
        if lit == 0:
            cnf.append(list())
        else:
            cnf[-1].append(lit)

assert len(cnf[-1]) == 0
cnf.pop()

new_cnf = list()
for clause in cnf:
    while len(clause) > 3:
        new_clause = list()
        for i in range(0, len(clause), 2):
            if i+1 < len(clause):
                new_cnf.append(list())
                new_cnf[-1].append(clause[i])
                new_cnf[-1].append(clause[i+1])
                maxvar += 1
                new_cnf[-1].append(-maxvar)
                new_clause.append(maxvar)
            else:
                new_clause.append(clause[i])
        clause = new_clause
    new_cnf.append(clause)

print("p cnf %d %d" % (maxvar, len(new_cnf)))
for clause in new_cnf:
    print(" ".join([ "%d" % lit for lit in clause ]) + " 0")
进入以下一组子句

(A[1] or A[2] or ~X[1])
(A[3] or A[4] or ~X[2])
(A[5] or A[6] or ~X[3])

(X[1] or X[2] or X[3] or A[7])
前三个条款添加到
new\u cnf
。最后一个子句不是3-sat,因此在最后一个子句上重新运行算法,生成以下新子句:

(X[1] or X[2] or ~Y[1])
(X[3] or A[7] or ~Y[2])

(Y[1] or Y[2])

这些都是3-sat子句,因此它们被添加到
new\u cnf
中,算法继续执行
cnf
中的下一个子句。(如果最后一个子句不是3-sat,则算法将继续处理它,直到只剩下3-sat子句。每次迭代后,最后一个子句的长度大约为一半。)

哇,我们是不是在完全相同的时间发布了相同的答案?哦!我完全疯了。我的意思是3分。我想如果你有那台2SAT algo,你就不会告诉我了;)要将包含3个以上文本的子句转换为3-CNF子句,您可以将每个子句转换为嵌套的布尔表达式,并应用Tseitin编码,如相关帖子中所示:@AxelKemper您知道我可以为此下载哪些程序吗?我不知道这样的程序。但我有另一个帖子可能会有所帮助:
(X[1] or X[2] or ~Y[1])
(X[3] or A[7] or ~Y[2])

(Y[1] or Y[2])