简体   繁体   English

无限循环scala代码

[英]Infinite loop scala code

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
      }
    }
  }
}

I'm pretty sure I've an infinite loop caused by my 'default' case. 我很确定我的'默认'案例导致了无限循环。 I'm using recursion in all cases. 我在所有情况下都使用递归。 Which is meant to be, but, only if the Prop can be simplified. 这意味着,但是,只有简化了Prop。 As soon as the Prop can't be simplified, it should return the whole thing. 一旦道具不能简化,就应该归还整个东西。

I don't see how I can test for any further simplification. 我不知道如何测试任何进一步的简化。 (I'm not allowed to use other libraries, as suggested in freenodes #scala channel). (我不允许使用其他库,如freenodes #scala频道所示)。

Can someone explain whether it IS the 'case _' causing the loop, and how to solve it? 有人可以解释它是否是导致循环的“case _”,以及如何解决它? How can I test for possible simplification without making a loop? 如何在不进行循环的情况下测试可能的简化?

Thanks in advance! 提前致谢!

It is pretty obvious what happens and you are right with the default case . 很明显发生了什么,你对默认case是正确的。 If your input prop does not match any of the cases you are invoking: 如果您的输入prop与您正在调用的任何案例都不匹配:

simplify(prop)

with the same argument. 用同样的论点。 Because previously it caused recursive call to simplify() and you are calling your function with the same input, it enters simplify() again. 因为之前它引起了对simplify()递归调用,并且您使用相同的输入调用函数,所以它再次进入simplify() So this is not an infinite loop but rather never terminated recursive call: 所以这不是一个无限循环,而是永远不会终止递归调用:

...simplify(simplify(simplify(simplify(simplify(simplify(simplify(prop)))))))

However the fix (based on your code) is simple: 但是修复(基于您的代码)很简单:

if (simplify(prop) == prop) prop
    else prop

just replace it with... 只需用......替换它

 case _ => prop

Both branches return the same value. 两个分支都返回相同的值。 This is actually correct if you think about if for a while. 如果您考虑一段时间,这实际上是正确的。 You have a set of optimizations. 您有一组优化。 If none of them matched your expressions it means it can no longer be simplified. 如果它们都不匹配您的表达式,则意味着它不再被简化。 Hence you are returning it as-is. 因此,你按原样返回它。

BTW looks like you are doing boolean expressions simplification using case classes. BTW看起来像是在使用case类进行布尔表达式简化。 You might by interested in my article where I do the same but with arithmetic expressions. 您可能会对我的文章感兴趣,但我会使用算术表达式。

The problem is that you're trying to do two things in one step that need to happen in sequence—applying De Morgan's law (and removing double negation) and recursively simplifying any children. 问题是你试图在一个步骤中做两件事,需要顺序发生 - 应用De Morgan定律(并删除双重否定)并递归地简化任何孩子。 This is why just dropping a case And(a, b) => And(simplify(a), simplify(b)) into your match won't work. 这就是为什么只丢弃一个case And(a, b) => And(simplify(a), simplify(b))到你的match将无法正常工作。

Try the following: 请尝试以下方法:

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
}

Yes, default case is causing the loop. 是的,默认情况是导致循环。 if (simplify(prop) == prop) prop is problematic line. if (simplify(prop) == prop) prop是有问题的一行。 You don't need to test if it can be simplified further because when you are in the default case all possible simplifications are tried. 您不需要测试它是否可以进一步简化,因为当您处于默认情况下时,会尝试所有可能的简化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM