【问题标题】:Infinite loop scala code无限循环scala代码
【发布时间】:2012-03-15 22:40:53
【问题描述】:
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 可以简化的情况下。一旦 Prop 不能被简化,它应该返回整个东西。

我不知道如何测试任何进一步的简化。 (我不允许使用其他库,正如 freenodes #scala 频道中所建议的那样)。

有人可以解释是否是导致循环的“案例_”,以及如何解决它?如何在不循环的情况下测试可能的简化?

提前致谢!

【问题讨论】:

    标签: scala loops pattern-matching case


    【解决方案1】:

    很明显会发生什么,默认case 是正确的。如果您的输入 prop 与您调用的任何案例都不匹配:

    simplify(prop)
    

    具有相同的论点。因为之前它导致了对simplify() 的递归调用,并且您正在使用相同的输入调用您的函数,所以它再次输入simplify()。所以这不是一个无限循环,而是永远不会终止的递归调用:

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

    但是修复(基于您的代码)很简单:

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

    只需将其替换为...

     case _ => prop
    

    两个分支返回相同的值。如果您考虑一段时间,这实际上是正确的。您有一组优化。如果它们都不匹配您的表达式,则意味着它不能再被简化。因此,您按原样返回它。

    顺便说一句,您似乎正在使用案例类简化布尔表达式。您可能会对我的article 感兴趣,我在其中做同样的事情,但使用算术表达式。

    【讨论】:

    • 感谢您的回答。我试着这样做。 (对不起,按下回车,并不想发布)。但在某些情况下,简化会导致字符串包含新的 Not(Not(a)),例如,重新运行简化会消除这些。但是,当它们在以前的任何情况下似乎都是新匹配时,我无法让它再次运行它。..:\
    • @Sander:你能告诉我们没有简化Not(Not(a))的输入吗?这可以通过在单独的术语上调用simplify() 来解决,例如:要简化And(Not(Not(a)), b),您必须返回And(simplify(Not(Not(a)), simplify(b))(简化模式是:And(a, b) => And(simplify(a), simplify(b))
    • @Thomasz Not(And(Not(a),Not(b))) 据我所知,这将首先简化为 Or(Not(Not(a)),Not(Not(b)))。代码应该重新运行以消除新创建的 Not(Not(a)) 和 Not(Not(b))。
    • @Sander:这是De Morgan's laws 的一个特例,我认为在开头明确写它是公平的:case Not(And(Not(a), Not(b)) => Or(simplify(a), simplify(b))Not(Or(Not(a), Not(b)) 类似。
    • @Thomasz:这确实是另一种方式。但不知何故,它似​​乎也不能 100% 工作。 (pastebin.com/rK28yn2J)。看看给出的另一个答案,我认为首先使用 De Morgan's 是公平的,然后消除 Not() 的双重出现。但这可能吗?再次感谢。 (:
    【解决方案2】:

    问题在于,您试图在一个步骤中完成两件需要按顺序进行的事情——应用德摩根定律(并消除双重否定)并递归地简化任何子级。这就是为什么将 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
    }
    

    【讨论】:

    • 我明白你的意思。不过,我的作业明确告诉我使用伴生对象。 Prop.simplify(Prop):Prop that returns a simplified and equivalent Proposition by repeatedly applying de Morgan's law and double negation ellimination to the argument Proposition. The resulting proposition must meet the requirements outlined below. 另外,您的建议与我讲师的回答不完全相符。 (我们有一个系统可以针对测试运行我们的工作)请参阅:pastebin.com/WDuQKreD(目前还提供完整代码)无论如何谢谢!
    • @Sander:您只需将案例添加到simplify 即可进行其他操作(另外,我很抱歉我不明白这是家庭作业——我不会那么做直接在我的回答中)。
    • @Sander:此外,从案例类继承和具有空构造函数的案例类都是不好的形式。 trait Prop; case object True extends Prop 更好。
    • 您是否有任何文档或某种示例来说明如何在我的simplify 中实施您正在谈论的案例? (无需道歉,我不只是复制/粘贴,我试图了解它的实际作用)。非常感谢! (:
    • 您可以将ImplEquiv 完全等同于AndOr
    【解决方案3】:

    是的,默认情况会导致循环。 if (simplify(prop) == prop) prop 是有问题的行。 您不需要测试它是否可以进一步简化,因为当您处于默认情况下时,所有可能的简化都会尝试。

    【讨论】:

      猜你喜欢
      • 2013-12-30
      • 1970-01-01
      • 2021-12-25
      • 1970-01-01
      • 2014-05-14
      • 1970-01-01
      • 2014-11-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多