読者です 読者をやめる 読者になる 読者になる

倭算数理研究所

科学・数学・学習関連の記事を、「倭マン日記」とは別に書いていくのだ!

2.4 True Basic のプログラム seriesTest

計算物理学入門 Groovy シミュレーション

今回は while 文による繰り返しを見ていきます。 シミュレーション的には、状態更新の前後で物理量の変化が設定値以下になるまで反復を繰り返すといったときに使えます。

True BASIC

まずは True BASIC のコード。

PROGRAM series_test
! DO LOOP 文の使用例
LET sum = 0
LET n = 0
LET relative_change = 1
DO while relative_change > 0.0001
    LET n = n + 1
    LET newtterm = 1/(n*n)
    LET sum = sum + newterm
    LET relative_change = newterm/sum
    PRINT n,relative_change,sum
LOOP
END
  • relative_change は sum (それまでの和)に対する newterm (新しく加える項)の比です。
  • 繰り返しは relative_change が 0.0001 より大きい間、繰り返します。

Groovy

上記の True BASIC のコードを Groovy で書くと、以下のようになります:

double sum = 0d
int n = 0
double relativeChange = 1

while(relativeChange > 0.0001d){
    n++
    double newTerm = 1/(n*n)
    sum += newTerm
    relativeChange = newTerm/sum
    println "$n, $relativeChange, $sum"
}

ほとんど同じように書けますね。 「++」演算子や「+=」演算子なんかも使ってみました。

ちなみに Groovy では演算子は全てメソッド呼び出しに変更されます。 たとえば「++」演算子は next() メソッド、「+」演算子は plus() メソッドの呼び出しになっています。 自分が実装したクラスにこれらのメソッドを定義しておけば、同じように演算子を使用することができます。 メソッド演算子の対応はこちらこちらを参照。

Groops

んでは、同じシミュレーションを Groops で書いてみましょう。

import org.waman.groops.builder.SimulationBuilder

new SimulationBuilder().simulation{
    
    observableSystem{
        states = [n:0, sum:0d, newTerm:0d]
        evolve = { system, Map params ->
            system.n++
            system.newTerm = 1d/(system.n*system.n)
            system.sum += system.newTerm
        }
    }

    continueWhile{ it.newTerm/it.sum >1e-4d }
    console()
}.simulate()

反復条件「continueWhile」は、クロージャを引数にとり、その評価が true の間反復を繰り返します。 このクロージャに渡されているオブジェクト(「it」で参照されているオブジェクト)は、測定された物理量の値を格納している DataStore オブジェクトです。 物理量の値はプロパティのように取得できます(「it.sum」など)。 また、continueWhile の逆の反復条件として「continueUntil」というのも使えます。

newTerm を測定しないなら、反復条件「converge」を使って以下のようにも書けます:

import org.waman.groops.builder.SimulationBuilder

new SimulationBuilder().simulation{
    
    observableSystem{
        states = [n:0, sum:0d]
        evolve = { system, Map params ->
            system.n++
            system.sum += 1d/(system.n*system.n)
        }
    }

    converge(sum:1e-4d)
    console()
}.simulate()

これは、内部でやってることは上記のものとほとんど同じです。 「物理量の変化がある比率以下になるまで反復を繰り返す」というのはよく使いそうなので Groops に組み込みました。

グラフを出力する完成版は以下のようになります:

@GrabResolver('https://github.com/waman/groops-core/tree/master/repo')
@Grab('org.waman.groops:groops-core:0.1-beta')

import org.waman.groops.builder.SimulationBuilder
import java.awt.Color

new SimulationBuilder().simulation{
    
    observableSystem{
        states = [n:0, sum:0d]
        evolve = { system, Map params ->
            system.n++
            system.sum += 1d/(system.n*system.n)
        }
    }

    converge(sum:1e-4d)
    console()
    png(fileName:'seriesTest.png', overwrite:true){
        chart{
            dot(label:'Simulation', x:'n', y:'sum')
            marker(label:'pi^2/6', y:Math.PI**2/6d, color:Color.BLUE)
        }
    }
}.simulate()

出力は下図の通り:


今回はドット (dot) でプロットするようにしました。 プロットに使えるのは、今のところ

  • point
  • dot
  • line

の3つです。 タイトルは付け忘れましたがまぁいいでしょう。

プログラミングGROOVY

プログラミングGROOVY

計算物理学入門

計算物理学入門

  • 作者: ハーベイゴールド,ジャントボチニク,Harvey Gould,Jan Tobochnik,鈴木増雄,石川正勝,溜渕継博,宮島佐介
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/12
  • メディア: 単行本
  • 購入: 1人 クリック: 28回
  • この商品を含むブログ (45件) を見る