object Prop {
def simplify(prop : Prop) : Prop = {
prop match {
case Not(Or(a,b)) => simplify(And(Not(a),Not(b)))
case Not(And(a,b)) => simplify(Or(Not(a),Not(b)))
case Not(Not(a)) => simplify(a)
case _ => {
if (simplify(prop) == prop) prop
else prop
}
}
}
}
我很确定我的'默认'案例导致了无限循环。我在所有情况下都使用递归。这意味着,但是,只有简化了Prop。一旦道具不能简化,就应该归还整个事物。
我看不出如何测试任何进一步的简化。 (我不允许使用其他库,如freenodes #scala频道所示。)
有人可以解释是否是'case _'导致循环,以及如何解决它?如何在不进行循环的情况下测试可能的简化?
提前致谢!
答案 0 :(得分:9)
很明显发生了什么,你使用默认的case
是正确的。如果您的输入prop
与您要调用的任何案例都不匹配:
simplify(prop)
使用相同的参数。因为之前它导致了simplify()
的递归调用,并且您使用相同的输入调用函数,它再次输入simplify()
。所以这不是一个无限循环,而是永远不会终止递归调用:
...simplify(simplify(simplify(simplify(simplify(simplify(simplify(prop)))))))
然而,修复(基于您的代码)很简单:
if (simplify(prop) == prop) prop
else prop
只需将其替换为......
case _ => prop
两个分支都返回相同的值。如果您考虑一段时间,这实际上是正确的。您有一组优化。如果它们都不匹配您的表达式,则意味着它不再被简化。因此,你按原样返回。
BTW看起来像是在使用case类进行布尔表达式简化。您可能会对我的article感兴趣,但我会使用算术表达式。
答案 1 :(得分:6)
问题在于你试图在一个步骤中做两件事,需要按顺序发生 - 应用De Morgan定律(并删除双重否定)并递归地简化任何孩子。这就是为什么只将case And(a, b) => And(simplify(a), simplify(b))
放入match
将无效。
尝试以下方法:
val deMorganAndDoubleNegation: Prop => Prop = {
case Not(Or(a, b)) => And(Not(a), Not(b))
case Not(And(a, b)) => Or(Not(a), Not(b))
case Not(Not(a)) => a
case a => a
}
val simplify: Prop => Prop = deMorganAndDoubleNegation andThen {
case And(a, b) => And(simplify(a), simplify(b))
case Or(a, b) => Or(simplify(a), simplify(b))
case Not(a) => Not(simplify(a))
case a => a
}
答案 2 :(得分:2)
是的,默认情况是导致循环。
if (simplify(prop) == prop) prop
是有问题的。
您无需测试是否可以进一步简化,因为当您处于默认情况下时,会尝试所有可能的简化。