减少布尔表达式

时间:2012-02-28 07:13:09

标签: language-agnostic boolean-expression reduction boolean-operations constraint-programming

我有一个表达式,假设,

a = 1 && (b = 1 || b != 0 ) && (c >= 35 || d != 5) && (c >= 38 || d = 6)

我希望它减少到,

a = 1 && b != 0 && (c >= 38 || d = 6)

有人有什么建议吗?指向任何算法的指针?

Nota Bene: Karnaugh Map或Quine-McCluskey不是这里的选择,我相信。由于这些方法不处理灰色案例。我的意思是,表达只能减少,就像A或A'或任何东西,或说黑色或白色或缺乏颜色。但是在这里,我有灰色阴影,正如大家们所看到的那样。

解决方案:我已经在Clojure中为此编写了程序。我使用了包含函数值的地图。这非常方便,只是几个组合的一些规则,你很好。谢谢你的有用答案。

2 个答案:

答案 0 :(得分:2)

我认为您应该能够使用Constraint Handling Rules达到您想要的效果。您需要编写简化OR和AND表达式的规则。

主要的困难是约束蕴涵检查,告诉你哪些部分可以放弃。例如,(c> = 35 || d!= 5)&& (c> = 38 || d = 6)简化为(c> = 38 || d = 6),因为前者是后者所必需的,即后者更具体。但是对于OR表达式,您需要选择更通用的部分。

Google找到paper on an extension of CHR with entailment check for user-defined constraints。我不知道CHR能告诉你是否需要这样的扩展。

答案 1 :(得分:1)

我相信constraint logic programming会定期完成这些事情。不幸的是,我没有足够的经验来提供更准确的细节,但这应该是一个很好的起点。

一般原则很简单:未绑定的变量可以有任何值;当你针对不等式进行测试时,它的一组可能值受到一个或多个间隔的限制。当/如果这些间隔收敛到单个点时,该变量将绑定到该值。如果OTOH,任何这些不等式被认为对于区间中的每个值都是无法解决的,则会出现[编程]逻辑失败。

另请参阅this,了解如何使用swi-prolog在实践中完成此操作。希望您能找到基础算法的链接或参考,以便您可以在您选择的平台中重现它们(甚至可以找到现成的库)。

更新:我尝试使用swi-prolog和clpfd重现您的示例,但没有得到我预期的结果,只有接近的结果。这是我的代码:

?- [library(clpfd)].
simplify(A,B,C,D) :-
    A #= 1 ,
    (B #= 1 ; B #\= 0 ) ,
    (C #>= 35 ; D #\= 5) ,
    (C #>= 38 ; D #= 6).

我的结果,回溯(插入换行符以便于阅读):

10 ?- simplify(A,B,C,D).

A = 1,
B = 1,
C in 38..sup ;

A = 1,
B = 1,
D = 6,
C in 35..sup ;

A = 1,
B = 1,
C in 38..sup,
D in inf..4\/6..sup ;

A = 1,
B = 1,
D = 6 ;

A = 1,
B in inf.. -1\/1..sup,
C in 38..sup ;

A = 1,
D = 6,
B in inf.. -1\/1..sup,
C in 35..sup ;

A = 1,
B in inf.. -1\/1..sup,
C in 38..sup,
D in inf..4\/6..sup ;

A = 1,
D = 6,
B in inf.. -1\/1..sup.

11 ?- 

所以,该计划产生了8个结果,其中包括你感兴趣的2个(第5和第8个):

A = 1,
B in inf.. -1\/1..sup,
C in 38..sup ;

A = 1,
D = 6,
B in inf.. -1\/1..sup.

另一个是冗余的,也许可以使用简单,自动化的逻辑规则来消除:

1st or 5th ==> 5th          [B == 1  or B != 0 --> B != 0]
2nd or 4th ==> 4th          [C >= 35 or True   --> True  ]
3rd or 1st ==> 1st ==> 5th  [D != 5  or True   --> True  ]
4th or 8th ==> 8th          [B == 1  or B != 0 --> B != 0]
6th or 8th ==> 8th          [C >= 35 or True   --> True  ]
7th or 3rd ==> 3rd ==> 5th  [B == 1  or B != 0 --> B != 0]

我知道成为一般解决方案还有很长的路要走,但正如我所说,希望这是一个开始......

P.S。我使用“常规”AND和OR(,;),因为clpfd的那些(#/\#\/)给出了一个非常奇怪的结果,我无法理解自己。 ..也许更有经验的人可以对它施加一些启示......