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

倭算数理研究所

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

ターゲットは反復シミュレーション

Groops ではオブジェクト指向で物理シミュレーションを扱っていきますが、最近は ScalaClojure のように JVM 上で動く関数指向言語が注目されているので、オブジェクト指向物理シミュレーションと言うとちょっと時代を逆行している感もありますが、まぁ、

みたいな棲み分けをすれば問題ないかと*1

ターゲットは反復シミュレーション


さて、「オブジェクト指向で物理シミュレーションを扱う」と言っても、全ての物理シミュレーションを扱おう!と大風呂敷を広げても収拾がつかなくなりそうなので、Groops で対象とするシミュレーションは、物理系を表すオブジェクトの状態を繰り返し発展させていく『反復シミュレーション (Iterative Simulation)』のみを扱うことにしましょう。 大抵の物理シミュレーションはそれで事足りると思うので、大した制限にならないと思います(たぶん)。

反復シミュレーションを行うコード


あまり抽象論・概念論ばかりでもアレなので、ちょっとこんな API にする予定、みたいなのを見ていきましょう。 かなり断片ですけど。 実際の Groops の API はちょっと名前が違ったり、シグニチャが違ったりするかも知れませんが、あしからず。

Groops では、(API によって)シミュレーションの実行を行う手順は以下のようになります:

  1. 物理シミュレーションを表すクラス IterativeSimulatorインスタンスを生成する
  2. IterativeSimulator オブジェクトからシミュレーションを実行する

です・・・って、書くまでもない? IterativeSimulator のインスタンスを生成する方法は次回以降に見ていくことにして、今回はシミュレーションの実行方法を簡単に説明します。 Groops では扱うのは反復シミュレーションですが、以下の2つの方法でそのシミュレーションを実行できるようにします:

  • プッシュ・シミュレート (push simulate)
  • プル・シミュレート (pull simulate)

これらは拙者の造語ですが、振る舞いは XML 解析などに出てくる「プッシュ・パース」、「プル・パース」と同じです。

プッシュ・シミュレート

プッシュ・シミュレートは、1つのメソッド呼び出し(IterativeSimulator では simulate())によって、最後まで反復を実行しきるシミュレーションです。 プログラムをベタ書きしている物理シミュレーションは大抵この方法です。 もちろん、がっつりとシミュレーションを実行したいときはこの方法を使うといいと思うので、これはこれで存在意義はあります*2。 Groovy コードではこんな感じ(あえて型を明示):

IterativeSimulator sim = ...    // インスタンス生成
Map params = [:]    // シミュレーションの実行時パラメータ

sim.simulate(params)

simulate() メソッドの処理が終わればシミュレーションが完了しますが、逆に言えば処理が終わるまでは何の操作も受け付けません。

プル・シミュレート

一方、プル・シミュレートイテレータ (java.util.Iterator) のように反復を手動(?)で繰り返します。 Java 風に try-catch 文を使って書くとこんな感じです:

IterativeSimulator sim = ...
Map params = [:]

try{
    sim.prepare(params)

    while(sim.hasNext()){
        sim.next(params)
    }

}finally{
    if(sim != null) sim.dispose()
}

プル・シミュレートを行う際に使用するメソッドは

  • prepare() / dispose() ・・・シミュレーションの前処理、後処理
  • hasNext() / next() ・・・イテレーションのためのメソッド

です。 シミュレーション結果をファイルに書き出したりしたいので、finally 節で後処理をする dispose() メソッドを呼び出してます。 また、繰り返し処理は while 文で行う必要はなく、next() メソッドでの状態更新の合間に何らかの処理を実行することができます。

prepare() / dispose() は定型コードなので、Groovy のクロージャを使って以下のように書けた方がいいですね:

IterativeSimulator sim = ...
Map params = [:]

simulator.simulate(params){ IterativeSimulator sim, Map p ->
    // assert sim == simulator && p == params (今のところ)
    while(sim.hasNext()){
        sim.next(p)
    }
}

クロージャの引数や委譲対象 (delegate 対象) のオブジェクトは、どうなってると使いやすいか思案中。 まぁともかく、せっかく柔軟性の高いプログラミング言語の Groovy を使うなら、こういったプル・シミュレートもできるようにした方がいいでしょうね*3

Groops でのシミュレーションの実行方法は大体こんな感じです。 まぁ、IterativeSimulator オブジェクトの生成方法の方がもっと大事ですが、それは次回以降に。

Groovyイン・アクション

Groovyイン・アクション

*1:数学が状態を持たず、物理が状態を持つってのはどの程度一般性のあることか分かりませんが、個人的な感覚では違和感なし。

*2:Groops では当面あまりパフォーマンスに気をかけませんが。

*3:後戻りできるようにするのはさすがに大風呂敷を広げすぎな気がするので、とりあえずスルー。