Scala中的固定点

时间:2014-03-06 10:11:27

标签: scala functional-programming higher-order-functions fixed-point

以下代码段是否有快捷方式?

while (true) {
  val newClusters = this.iterate(instances, clusters)

  if (newClusters == clusters) {
    return clusters
  }

  clusters = newClusters
}

我想计算固定点,即执行一个函数,使其结果稳定。您是否知道任何适合我目的的高阶函数?

2 个答案:

答案 0 :(得分:1)

来自Martin Odersky的 Scala By Example 的修正点计算示例的改编(章节'First-Class functions',第5.3节),

val instances = ...  // from question statement 

def isApproxFeasible(x: Clusters, y: Clusters) = some_distance_x_y < threshold

def fixedPoint(f: Clusters => Clusters)(initApprox: Clusters) = {
  def iterate(approx: Clusters): Clusters = {
    val newClusters = f(approx)
    if (isCloseEnough(approx, newClusters)) newClusters
    else iterate(newClusters)
  }
  iterate(initApprox)
}

其中,函数f: Clusters => Clusters提供新的候选聚类,initApprox对应于第一个对修复点的初始猜测。函数isApproxFeasible有助于确保先验阈值的终止。

答案 1 :(得分:0)

另一种方法是将著名的单行斐波那契数计算(https://stackoverflow.com/a/9864521/788207)和takeWhile结合起来:

val reductions = Stream.iterate(clusters)(this.iterate(instances, _))
(reductions, reductions.tail).zipped.takeWhile { case (p, n) => p != n }.last._1

另一种不需要在内存中构造流对象的方法是使用迭代器:

Iterator.iterate(clusters)(this.iterate(instances, _))
  .sliding(2)
  .dropWhile { case prev +: next +: _ => prev != next }
  .next()
  .head

尽管强制性解决方案可能会更有效,因为它是一个简单的循环,无需构造流或不调用闭包。