我写了a little app,它将表达式解析为抽象语法树。现在,我使用一堆启发式方法来决定如何最好地评估查询。不幸的是,有一些例子使得查询计划非常糟糕。
我找到了一种方法可以更好地猜测如何评估查询,但我需要先将表达式放入CNF或DNF,以获得可证明的正确答案。我知道这可能导致潜在的指数时间和空间,但对于典型的查询,我的用户运行这不是问题。
现在,转换为CNF或DNF是我一直手工完成的,以简化复杂的表达式。 (好吧,也许不是所有的时间,但我确实知道如何使用例如demorgan的定律,分配法则等)但是,我不知道如何开始将其转换为一种方法可以实现为算法。我查看了有关查询优化的论文,其中一些开头是“首先我们将内容放入CNF”或“首先我们将内容放入DNF”,他们似乎从未解释过他们实现这一目标的方法。
我应该从哪里开始?
答案 0 :(得分:10)
看看https://github.com/bastikr/boolean.py 示例:
def test(self):
expr = parse("a*(b+~c*d)")
print(expr)
dnf_expr = normalize(boolean.OR, expr)
print(list(map(str, dnf_expr)))
cnf_expr = normalize(boolean.AND, expr)
print(list(map(str, cnf_expr)))
输出是:
a*(b+(~c*d))
['a*b', 'a*~c*d']
['a', 'b+~c', 'b+d']
更新:现在我更喜欢这个sympy logic package:
>>> from sympy.logic.boolalg import to_dnf
>>> from sympy.abc import A, B, C
>>> to_dnf(B & (A | C))
Or(And(A, B), And(B, C))
>>> to_dnf((A & B) | (A & ~B) | (B & C) | (~B & C), True)
Or(A, C)
答案 1 :(得分:8)
对于无量词公式,天真的香草算法是:
我不清楚你的配方是否已量化。但即使它们不是,它似乎是维基百科关于conjunctive normal form的文章的结尾,它的 - 在自动化的规范证明世界中大致相当 - clausal normal form改变自我概述一个可用的算法(并指向引用,如果你想让这个转变更聪明一点)。如果您需要更多,请告诉我们您遇到困难的地方。
答案 2 :(得分:2)
我已经看过这个页面:How to Convert a Formula to CNF。它显示了在伪代码中将布尔表达式转换为CNF的算法。帮助我开始讨论这个话题。