我有一个表达式,假设,
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中为此编写了程序。我使用了包含函数值的地图。这非常方便,只是几个组合的一些规则,你很好。谢谢你的有用答案。
答案 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的那些(#/\
和#\/
)给出了一个非常奇怪的结果,我无法理解自己。 ..也许更有经验的人可以对它施加一些启示......