今回は 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つです。 タイトルは付け忘れましたがまぁいいでしょう。
- 作者: 関谷和愛,上原潤二,須江信洋,中野靖治
- 出版社/メーカー: 技術評論社
- 発売日: 2011/07/06
- メディア: 単行本(ソフトカバー)
- 購入: 6人 クリック: 392回
- この商品を含むブログ (155件) を見る
- 作者: ハーベイゴールド,ジャントボチニク,Harvey Gould,Jan Tobochnik,鈴木増雄,石川正勝,溜渕継博,宮島佐介
- 出版社/メーカー: ピアソンエデュケーション
- 発売日: 2000/12
- メディア: 単行本
- 購入: 1人 クリック: 28回
- この商品を含むブログ (45件) を見る