[与2013 年 9 月 27 日的https://codegolf.stackexchange.com/questions/12664/implement-superoptimizer-for-addition相关]
我对如何编写超级优化器很感兴趣。特别是要找到位和的小逻辑公式。这以前被设置为对 codegolf 的挑战,但它似乎比人们想象的要困难得多。
我想编写代码来找到可能的最小命题逻辑公式,以检查 y 二进制 0/1 变量的总和是否等于某个值 x。让我们将变量称为 x1、x2、x3、x4 等。在最简单的方法中,逻辑公式应该等价于总和。也就是说,当且仅当总和等于 x 时,逻辑公式才应该为真。
这是一种天真的方法。假设 y=15 和 x = 5。选择所有 3003 种不同的方式来选择 5 个变量,并为每种方式创建一个新子句,其中包含这些变量的 AND 以及其余变量的否定 AND。您最终得到 3003 个子句,每个子句长度正好为 15,总成本为 45054。
但是,如果允许您在解决方案中引入新变量,那么您可以通过消除常见的子公式来潜在地减少这一点。因此,在这种情况下,您的逻辑公式由 y 个二进制变量、x 和一些新变量组成。当且仅当 y 变量之和等于 x 时,整个公式才是可满足的。唯一允许的运算符是and
,or
和not
。
事实证明,至少在理论上,当 x =1 时,有一种巧妙的方法可以解决这个问题。但是,我正在寻找一种计算密集型方法来搜索小型解决方案。
How can you make a superoptimizer for this problem?
例子。以两个变量为例,我们想要一个逻辑公式,当它们的总和为 1 时,它恰好为真。一个可能的答案是:
(((not y0) and (y1)) or ((y0) and (not y1)))
要在公式中引入新变量z0
以表示,y0 and not y1
那么我们可以引入一个新子句 并在公式的其余部分(y0 and not y1) or not z0
替换y0 and not y1
为。z0
当然,这在这个例子中是没有意义的,因为它会使表达式变长。