ひとり勉強会

ひとり楽しく勉強会

1.4 Computing Actions

さて、ここまでの知識を実際にSchemeで動かしてみようタイムです。guile版を準備。

guile> (load "/usr/local/scim/load.scm")
guile> (set-current-module generic-environment)
guile> (define D derivative)

一番簡単な例として、1個の粒子が自由に飛んでいるケースを考えてみよう!とのこと。座標は、普通にx,y,zにしましょう。q(t)=(x(t),y(t),z(t))

(define x (literal-function 'x))
(define y (literal-function 'y))
(define z (literal-function 'z))
(define (q t) (up (x t) (y t) (z t)))

昔の偉いひとによると、このシステムのラグランジアンは、物体の速さをv、質量をmとすると\frac{1}{2}mv^2だそうです。

(define ((L m) q)
  (let ((v (velocity q)))
    (* 1/2 m (dot-product v v))))

で、actionの積分の中身は L \circ \Gamma(q) でした。

(define sekibun-nakami (compose (L 'm) (Gamma q)))

いきなり変数名が酷くなりましたが気にしないことにしましょう。あ、ちなみに、compose, Gamma, velocity, dot-product などは全てライブラリ側で提供されている関数です。

guile> (pe (sakibun-nakami 't))
(+ (* 0.5 m (expt ((D x) t) 2))
   (* 0.5 m (expt ((D y) t) 2))
   (* 0.5 m (expt ((D z) t) 2)))

積分の中身を表示してみました。pe = print-expression。
このライブラリは、こういう風に記号的に式を式として扱うこともできますし、実際に計算させることもできます。

guile> (define (fp-action q t1 t2)
         (definite-integral (compose (L 3) (Gamma q)) t1 t2))

configuraion path と開始終了時刻を与えると、重さ 3 の粒子の action を計算してくれる関数。直線状にぶっとんで行くpathを与えると…

guile> (fp-action
         (lambda (t) (up (+ (* 4 t) 7)
                         (+ (* 3 t) 5)
                         (+ (* 2 t) 1))) 0 10)
435.0

最小作用のpath

ここまでの知識によれば、fp-actionは、「ありえる動き」のところで極小値をとるはずです。何も他に要因がなければ、一定速度でどこまでも飛んでいくのが「ありえる動き」で、それ以外の、微妙に速度が変わったりするpathは「ありえない動き」でしょう。というわけで、そういうpathを与えると、値は435.0より大きくなるはず。

guile> (fp-action
         (lambda (t) (up (+ (* 4 t) 7)
                         (+ (* 3 t) 5)
                         (+ (* 2 t t) 1))) 0 10)
8375.00000000001

何故かz軸方向にものすごい加速してみるとか。。。ちょっと極小とか以前にこれは動きが違いすぎますかね。

guile> (define ((v-action q t1 t2) eps)
         (fp-action
           (lambda (t) (+ (q t) (up 0 0 (* eps (- t t1) (- t t2)))))
           t1 t2))
guile> ((v-action
         (lambda (t) (up (+ (* 4 t) 7)
                         (+ (* 3 t) 5)
                         (+ (* 2 t) 1))) 0 10) 0.01)
435.05

qとepsを与えると、微妙に揺れてるpath q'(t) = (x(t), y(t), z(t)+{eps}(t-t1)(t-t2)) に関するactionを計算してくれる関数です。時刻t1とt2では揺れが0になるようにしてあるので、始点終点がちゃんと同じconfigurationになります。微妙にずらすと微妙にactionが増えてますね。

guile> (minimize (v-action
...          (lambda (t) (up (+ (* 4 t) 7)
...                          (+ (* 3 t) 5)
...                          (+ (* 2 t) 1))) 0 10) -2 2)
(-1.11022302462516e-16 435.0 5)

上のようにminimize関数を使うと、-2〜2の範囲で、v-actionを最小にするepsを探すことができます。実際、epsがほぼ0、つまり直線のところでactionが最小になってるようです。