我有一个ANTLR表达式解析器,它可以使用生成的访问者计算表单的表达式(A&(B | C))。 A,B和C可以采用true
或false
中的任意两个值。然而,我面临着找到表达式为真的A,B和C的所有组合的挑战。我尝试通过以下方法解决这个问题。
虽然这种方法有效但随着变量数量的增加,这种方法变得计算密集。因此,对于具有20个变量1048576的表达式,需要计算。如何优化这种复杂性,以便获得所有真正的表达式?我希望这属于Boolean satisfiabilty problem
答案 0 :(得分:3)
确实如此。如果您使用20-30个变量,您可以简单地强制尝试所有组合。如果每次尝试需要100ns(即500台机器指令),它将在大约100秒内运行。这比你快。
如果你想解决比这更大的方程,你需要建立一个真正的约束求解器。
编辑由于OP的说法,试图并行加速Java程序,暴力强迫答案:
我不知道你如何表示你的布尔公式。对于蛮力,你不想解释公式树或做一些缓慢的事情。
关键技巧是评估布尔公式 fast 。对于大多数编程语言,您应该能够将公式编码为手动测试该语言的本机表达式,将其包装N个嵌套循环并编译整个事物,例如,
A=false;
do {
B=false;
do {
C= false;
do {
if (A & (B | C) ) { printf (" %b %b %b\n",A,B,C);
C=~C;
} until C==false;
B=~B;
} until B==false;
A=~A;
} until A==false;
编译(甚至是JIT的Java),我希望内部循环每个布尔操作需要1-2个机器指令,只接触寄存器或单个cachec行,再加上2个循环。 对于大约42个机器指令的20个变量,甚至比我在第一段中的粗略估计要好。
如果有人坚持,可以将最外面的循环(3或4)转换为平行线程,但如果你想要的只是打印语句,我就不知道这在实用性方面是多么重要。
如果你有很多这些公式,很容易编写一个代码生成器来生成这个公式的任何表示形式(例如,ANTLR解析树)。