この記事ではカオスというアイデアをごく簡単な計算で解説します。

カオスとはなにか

日本語でカオスというと混乱したとかめちゃくちゃとかいうイメージを思い浮かべるかもしれませんが、数学でのカオスは予測不可能なシステムのことを意味します。例でいうと、お湯を沸騰させた時に鍋の中にできる乱流、天気の変化、お互いに干渉しあう二つの振り子の軌道、などで日常にはカオスなシステムが溢れています。

カオスは予測不能だと書きましたが、決してランダム(非決定的)という意味ではありません。カオスは決定的(インプットが同じであればアウトプットは予測できる)にもかかわらず実際に計算してみるとその動きは全くめちゃくちゃであたかも非決定的に見えてしまいます。決定的なのに非決定的に振る舞う:ここがカオスの不思議なところであり魅力でもあります。

もう一つカオスの面白いところは、そうゆうめちゃくちゃに振る舞うシステムをごく簡単な計算で再現できることです。この記事ではそれを実際にやってみてカオスを体験してもらおうと思います。

カオスの特徴

後でこの話には戻ってきますが、先にカオスが持つ特徴を書いておきます。主に三つあり、

  • 予測不可能
  • Xt+1 = F(Xt)
  • 初期値に敏感

ということが挙げられます。一つずつ説明してきます。

予測不可能

予測不可能は上に書いたので説明不要です。

Xt+1 = F(Xt)

Xt+1 = F(Xt) という式があった時

tは時間を意味します。tは0から始まり、1,2,3,4…とどんどん増えていきます。なので、X0 というと一番最初のXの値、X1というと2回目のXの値という意味になります。なのでXt+1というのは次のtの時のXの値という意味になります。F()というのは関数です。

ここから、Xt+1 = F(Xt) というのは、何かF()という関数があって、インプット (Xt)を入れて計算した値がアウトプット(Xt+1)になり、Xt+1が次のインプットになってXt+2のアウトプットが作ってそれがまた、、、ということをずっと続けていけることを意味します。

初期値に敏感

初期値というのはtが0のときの値、つまりX0です。Xt+1 = F(Xt)ではアウトプットが次のインプットになるので最初の値を何にするかによってtが増えるに従って結果が違っていきます。

普通インプットが少し変わればアウトプットも少ししか変わらないと考えます。例えば、時速100kmで1時間走った場合、100km進めます。時速101kmで走ったら101km進めます。このように時速が少し増えたら距離も少ししか変わりません。これは初期値にも同じことが言えます。初期値が1の時と1.1の時では結果はちょっとしか変わらないと予想できます。

カオスなシステムではこれがあてはまりません。例えば、初期値が1の時の結果が153だったのに、初期値を1.001にして計算してみたら結果が303になったりします。初期値は0.001しか変わっていないのに結果は2倍以上になっています。

このように初期値をちょっと変えただけで、結果が全く変わってしまう、という特徴がカオスにはあります。

ロジスティック写像

ロジスティック写像というのは生物の個体数の変化を単純な式で表したもので一番有名なカオスの例です。他の人も似たような発見を過去にしていましたが、ロバート・メイという生物学者の研究で有名になりました。以下の簡単な式で表されます。

Xt+1 = aXt(1 - Xt); 0 < x < 1

XtXt+1 はさっき説明した通りです。aはパラメータでXtにかかわらず独立して変更できる値です。tは世代、Xtはその世代の個体数、それがインプットになり、次の世代の個体数Xt+1を計算するということになります。aはその生物の繁殖力です(一回の出産で1匹産むか、3匹産むかとか)。aはフィードバックとも呼ばれアウトプットがどれだけインプットに影響されるかを示します。

もちろん実際の生物の個体数の増減はこんな簡単な式で表せるものではありません。様々な要素に影響されるからです。この式は主に実験室の中で使われるものであり、完全に環境をコントロールできる場合個体数はこの式で予測することができます。現実では役に立たない式ですが、ロバート・メイは研究中にこの簡単な式が予測不能な動きをすることを発見して後にカオスと呼ばれるようになりました。

それではこのロジスティック写像でどうやってカオスを作れるか実際にやってみます。まずは初期値X0を0.4に固定してaを変えて15世代計算した時にどのように結果が違ってくるかみてみます。

Clojureで書くとこんな感じになります。

(def max_iteration 14)

(defn logistic [x_0 feedback]
  (loop [x_t x_0 iteration 0]
    (println x_t)
    (if (= iteration max_iteration)
      nil
      (let [x_t_1
            (->> x_t
                 (- 1)
                 (* x_t)
                 (* feedback))]
        (recur x_t_1 (+ iteration 1))))))

X0=0.4 a=2の時の結果

0.4
0.48
0.4992
0.49999872
0.4999999999967232
0.5
0.5
0.5
0.5
0.5
0.5
0.5
0.5
0.5
0.5

X0=0.4 a=1+√5 (3.23606)の時の結果

0.4
0.7766544
0.5613345495612088
0.7968411786098619
0.523870591428241
0.8071710763943982
0.5036795676750128
0.8089711862773091
0.5000903765874327
0.8090149735680964
0.50000280899902
0.809014999974466
0.500002756186754
0.8090149999754171
0.5000027561848518

X0=0.4 a=4の時の結果

0.4
0.96
0.15360000000000013
0.5200281600000003
0.9983954912280576
0.006407737294172653
0.02546671278776609
0.09927263731020608
0.3576703231667294
0.918969052370147
0.297859732624244
0.8365572492210314
0.5469168719870904
0.9911952284917879
0.034908990027601214

a=2の時結果はすぐに0.5に収束します。a=1+√5の時は4世代までは上がったり下がったりしたあと5世代からは0.80と0.50の間を行ったり来たりします。こうゆう繰り返しが起こるとき、振幅するといいます。a=4の時は全くめちゃくちゃで収束したり振幅したりする感じが全然しません。

これはまさに二つ目のカオスの特徴である予測不能、ということを示しています。先ほども書きましたが、Xt+1 = aXt(1 - Xt)の式は決定的な式なので決してランダムではありません。一つ一つ地道に計算していけば将来の値は予測できます。しかし、その見かけは全くの予測不能です。こんなに単純な式なのに、なぜaを変えただけでこんなに結果が違ってしまうのか?a=2の時は収束したのにa=4の時にはなぜ結果がめちゃくちゃになってしまうのか?こうゆう疑問がカオスの魅力の一つです。

次にX0も少し変えてどうゆう結果になるか見てみます。

X0=0.40001 a=2の時の結果

0.40001
0.48000399979999997
0.4992003199520032
0.4999987210236417
0.4999999999967285
0.5
0.5
0.5
0.5
0.5
0.5
0.5
0.5
0.5
0.5

X0=0.40001 a=1+√5 (3.23606)の時の結果

0.40001
0.776660871796394
0.5613229614122776
0.7968457782598055
0.5238617545503489
0.8071724413804047
0.5036768540111918
0.8089712508783068
0.5000902474048949
0.8090149736436049
0.5000028088480044
0.8090149999744687
0.5000027561867487
0.8090149999754171
0.5000027561848518

X0=0.40001 a=4の時の結果

0.40001
0.9600079995999999
0.15357056121602583
0.5199465757752828
0.9984085364593636
0.006355723137741059
0.02526131168454977
0.09849271126610319
0.3551675883742209
0.9160942901706436
0.307462166749553
0.8517167310688923
0.5051813643448498
0.9998926138541037
4.2949845644802873E-4

X0が0.4のときと0.40001の時の結果を見比べてみるとa=2a=1+√5 (3.23606)の時は最初の方の世代の結果が違うだけですぐに同じ値になりますが、a=4の時は世代が増えるにつれて結果の誤差がどんどん大きくなっていきます。たった、0.00001しか初期値を変えていないのにその結果は大きく違っています。これがカオスの3番目の特徴である初期値に敏感といういうことです。

自己相違/フラクタル

tが増えるにつれて、a=2の時は0.5に、a=1+√5の時は0.5と0.8へと値が定まっていくことを先ほど見ました。ある値を繰り返すようになることを周期的といい、何回で同じ値に戻ってくるかをN周期といいます。a=2はずっと同じ値を繰り返す、つまり1回で次の値に戻る、ので1周期です。a=1+√5の場合は0.8へ行ったあと0.5へ戻るので2周期です。aの値を変えて行ったときどのように周期が変化するのかを示したのが次のグラフで分岐ダイアグラムとか周期倍分岐といいます。

bunki-diagram1

このグラフにはとても面白い特徴がいくつもあります。まず一つ目に周期の増え方は、1、2、4、8…と2のベキ上で増えていくことです。二つ目はaの値が3.5699456に達すると分岐がカオスになるということです。三つ目は分岐がカオスになると自己相違という特徴が現れるということです。

自己相違とは一部分が全体と同じ形をしているということです。マトリョーシカは自己相違のいい例です。どんなに人形が小さくなっても基本的に大きい人形と形が同じだからです。

自己相違は自然にたくさんあります。次の写真を見てください。私のお気に入りの本のブラックスワン(下 p162)からお借りしました。レンズのフタが地面に落ちているように見えると思います。

surface_fractal2
























しかし実際にはもっと遠いところから見た地面の写真でした。このように地表はフラクタルの一例です。

surface_fractal1

さっきの分岐ダイアグラムもフラクタルなっています。カオスになっているところを拡大していくとつねに二股の熊手のような構造が現れます。

以下の写真は http://brain.cc.kogakuin.ac.jp/~kanamaru/Chaos/BifArea/ からダウンロードしたプログラムを走らせてスクリーンショットをとりました。プログラムをダウンロードして実際に拡大してみるとよくわかるので是非やってみてください。

bunki-diagram2

bunki-diagram3

このように拡大しても常に熊手の構造が現れます。従ってロジスティック写像の分岐ダイアグラムはフラクタルだと言えます。

まとめ

ものすごく駆け足でカオスを紹介しましたが、カオスの魅力を感じてもらえたでしょうか?私の理解もまだまだ不十分ななので間違っているところもあると思いますが、カオスの大まかなアイデアは理解してもらえたと思います。

私がカオスを勉強し始めて学んだ一番重要なことは未来は予測不可能で、そのことは数学的に証明されているということです。ロジスティック写像のような極めて簡単な数式がカオスになりうるなら、様々な要素が複雑に関わりあう世の中の現象は基本的にすべてカオスだからです。将来の景気や、アメリカ大統領選の結果、来年何が流行るかなどをそれっぽい説明をつけて予想する人たちがいますがそれらはすべて当てずっぽうに過ぎません。初期値がほんの少し変わっただけで結果が大きく変わってしまうカオスの性質を思い出してください。これは例えば将来の景気を予想する時に出発地点の現在の景気の計測を0.001%間違っただけでまったく違う結果になってしまうということです。これはつまり、正確な景気の計測が不可能なので、将来の景気の予測もまた不可能ということになります。

カオスの研究はまだまだわかっていないことが多い分野なので今後もどんどん面白い発見があることを願っています。