Scala:使用收敛实现数学递归

时间:2014-04-09 18:58:14

标签: scala stream iterator convergence

许多数字问题的形式如下:

initialize:  x_0 = ...
iterate:     x_i+1 = function(x_i) until convergence, e.g., 
             || x_i+1 - x_i || < epsilon

我想知道是否有一种很好的方法来使用惯用的Scala编写这样的算法。问题的性质需要IteratorStream。但是,我目前对此的看法看起来很丑陋:

val xFinal = Iterator.iterate(xInit) { x_i =>
  // update x_i+1
}.toList      // necessary to pattern match within takeWhile
 .sliding(2)  // necessary since takeWhile needs pair-wise comparison
 .takeWhile{ case x_i :: x_iPlus1 :: Nil => /* convergence condition */ }
 .toList      // since the outer container is still an Iterator
 .last        // to get the last element of the iteration
 .last        // to get x_iPlus1

这不仅很难看,takeWhile中的模式匹配也会引起警告。显然我不需要在这里进行模式匹配,但我希望与数学原型保持强烈的相似性。

任何想让它看起来更漂亮的想法?

2 个答案:

答案 0 :(得分:1)

以下极简主义(愚蠢)的例子可能会说明一个有用的框架,

def function (i:Int): Int = i+1

def iter (x0: Int): Int = {
  val x1 = function(x0)
  if (x1 - x0 == 1) x1 else iter(x1)
}

答案 1 :(得分:1)

这是我使用牛顿方法找到平方根的例子的解决方案,在这种情况下减少了巴比伦方法:

import math.abs                                                                                                                                                                                                    

val tol=0.00001                                                                                                                                                                                                    
val desiredSqRoot=256                                                                                                                                                                                              
val xFinal = Iterator.iterate(1.0) { x => 0.5*(x+desiredSqRoot/x) }                                                                                                                                                

def converged(l: Seq[Double]): Boolean = l match{
  case x_old :: x_new :: Nil => if( abs(x_old-x_new)/x_old < tol ) true else false                                                                                                                                 
  case _ => true                                                                                                                                                                                                  
}                                                                                                                                                                                                                  

xFinal.sliding(2).dropWhile( x=> !converged(x) ).next.last 

结果为:

scala> xFinal.sliding(2).dropWhile( x=> !converged(x) ).next.last
res23: Double = 16.00000000000039

在这个例子中,我们知道它应该收敛的值,但是我在没有这方面知识的情况下编写了收敛标准,因为通常我们不知道这一点。