0

多くの数値問題は次の形式です。

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

慣用的な Scala を使用してこのようなアルゴリズムを作成する良い方法があるかどうか疑問に思っています。問題の性質上、Iteratorまたはが必要Streamです。しかし、これに対する私の現在の見解は本当に醜いように見えます:

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も警告を引き起こします。明らかに、ここでパターン マッチングを行う必要はありませんが、元の数学的パターンとの類似性を維持したいと考えています。

これをより美しく見せるためのアイデアはありますか?

4

2 に答える 2

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)
}
于 2014-04-09T19:21:28.897 に答える
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

この例では、収束すべき値を知っていますが、一般にこれがわからないため、この知識なしで収束基準を書きました。

于 2016-09-03T15:08:09.413 に答える