仮想コラッツ木の実装はぼぼ完了した

昨日は寝落ちして夜中にベッドに転げ込んだものの,畳んだままの布団の上に朝までうつ伏せで寝ていた.それほど寒くなかったので室温もあまり下がっていなかったのだろう.予備機に仕掛けておいたはずの検証テストの続きが消えてしまっている.理由はまったく不明だ.タスクバーのアイコンから起動すると初期画面になってしまっているので,落ちていたことは間違いない.開発機に仕掛けたテストは順調に走っている.11時間58分経過して残り時間は13時間46分になっている.

2^27というオーダーで走らせているので,検定対象奇数カウントは134217728.昨日から実際にテストされた実カウントとその比率を表示するようにしているが,現在46970000台で進捗率は46.6%,有効ノード率は35%だ.テスト完了時には進捗率100%,有効ノード率は75%くらいになる.有効ノード率というのは,最大枝数と樹高を同じ値に設定したときの仮想木と一般木のノード数の比率を表すものでこの値が3/4に収束することは間違いないように思われる.

この値はコラッツ数と奇数全体の比率を表すものであると考えられるが,コラッツ数の割合はもっとずっと小さいものと推定していたので,まだよく理由が飲み込めていない.何か仮想木の構成を勘違いしているところがあるのではないか?という気もする.開発環境の上で直接走らせているので,テストは一度打ち切るしかない.ネットに接続してレポートを送信しておこう.「いますぐ再起動する時間です」という表示が出たので再起動した.Collatz Milky Highwayはまだ仕上がったという訳ではないが,リリースして予備機で走らせておくことにする.

予備機のテストは一般木のテスト結果をそのまま引き継いで,2348811361から開始することにする.2^26で丸1日+10時間くらいの見込みだ.CollatzTreeGenertor.exeというプログラム名もCollatzMilkyHighway.exeに変えた.ルート5から始まる枝数3,高さ12の仮想コラッツ木を仕掛けてみた.このテストの楽しみは,どのくらい大きな奇数が採集できるかという点にある.いや,大きな奇数ならただ数字を並べるだけでいくらでも大きくすることはできるが,比較的小さい木の上にそれを見つけるのが楽しみと言うわけだ.つまり,欲しいのは木に成っているりんごだ.

いや,仮想木のコラッツ数生成を実行すればいくらでも大きな(身元のわかった)奇数を生成することができる.枝番号リストにはいくらでも長い数列を記入できるからだ.(と言っても上限はある)数字が相当大きくなってもびくともしない程度にプログラムが堅牢であることは確認できた.⇒枝番号に大きな整数を設定したら,さすがにハングした.GetNodeNumberでループしている.ここでは枝数分の乗算が実行されている.4N+1をバイナリで計算してみよう.⇒多分効果は出ていると思われるが,大勢には影響がない.枝数は精々3桁というのが限界ではないか?それ以上になると,今度は高さで進まなくなってしまう.⇒高さも相当深刻だ.枝数100で高さ3の枝番号リストですでにハングしている.超巨大数の計算になってしまうためだ.

どうも高さ3というのが壁になっているようだ.枝数をわずか3にしても3の壁を超えられない.いや,どうもどこか壊してしまったのかもしれない…GetTheNumberの動作がおかしい.どうもシフト演算と加算を1行でやろうとしたことが原因らしい.楽勝に動作するようになった.ただし,枝数が5桁を超えると流石にしんどいらしい.それでも何とかがんばって動いているようなので,この辺りが限界ということなのだろう.

4N+1を複数回ループする演算を代数式で置き換えることは可能なのではないか?計算途中で結果を判定するなどのことはやっていないのだから,1段で処理できるはずだ.どこかでこの種の計算をやったことはあるような気がする.あった,あった.

N(k)=(M(k)-1) / 3 = (4^(k-1)N*2^c – 1) / 3

これが使えるのでは無いだろうか?これはNのk番目の子ノードの値を計算する式だ.GetNodeNumberはまさにその計算を行っているルーチンだ.ただし,これは一般木用の計算で,仮想木の場合は3の倍数ノードをパスしなくてはならないため,ループの中に判定が入っている.ともかく,この計算式を一般木の計算のところで適用することにしよう.実装した.Nの長子をFとするとき,

N(k) = ((3F+1)4^(k-1) – 1) / 3

で与えられる.GetNodeNumberはGetTheNumberの中でしか使われていないが,GetTheSequenceと双対な処理であり,比較して一致しているのでまず,問題ないだろう.この2つの結果が一致しなければ検証テストは通らない.これでおそらく一般木の方はかなり高速化したのではないかと思われるが,仮想木に適用できる何かうまい方法があるだろうか?もし,ノードNの枝数番までの子ノードの中で3の倍数になるノードの個数がわかればその分を減ずるだけで同じ式が使えるのだが…たとえば,子ノードの1/3は3の倍数であるなどということが言えるだろうか?

数直線上の奇数であればそのようなことを言うのは難しくないような気はするが,ノードNの子ノードの値は演算を施されているので直ちにはそのようなことは言えない.枝番号のどこで3の倍数が発生するか?ということはおそらく予測できないと思われるが,全体の何分の一などのような手がかりを得られる可能性はあるような気もする.これを調べてみる価値はあるだろうか?⇒やってみた.思いの他単純な仕掛けだった.

ノードNの子ノードの数列で3の倍数になるノードは3つ置きに出現する.つまり,兄弟3人のうちの一人は必ず3の倍数だ.これだけわかれば対処するのは難しくない.最初の2人を調べてどちらも3の倍数でないとすれば,3番目の兄弟は必ず3の倍数になっている.これによって,兄弟全体に含まれる3の倍数の個数が確定するから,その分をカウントから減じてやればよいというだけだ.⇒大体動作するようになった.既存論理と平行に走らせて比較検査を行っているところだが,なぜかやけくそ遅くなった.倍速遅くなるくらいならわかるがそのレベルではない…

計算が間違っているのなら停止するはずだが…デバッグ用のダンプで遅くなっていたようだ.動作するようになったが,既存論理とそれほど変わらないような気がする.いや,かなりの変化はあった.以前はほとんど動作しなかった領域でも動作している.枝番号が100000で高さ13という数列の計算を遅いながらも実行している.Get the NumberやGet the Sequenceでは計算時間を計測していないので,どこで終わったかよく分からない.すでに超巨大数になっているため,Big numberも空欄になったままだ.かろうじてTree Heightの値が更新されるので,検定の進行を見ることができる.これはもう,ここまで動いているというので良しとするしかないだろう.

ループを計算式に変えられるところはまだ他にもあるだろうか?Get the NumberとGet the Sequenceは逆演算になっているが,Get the Numberの方がかなり速い.これは上記の高速化が効果を発揮しているためと考えられる.Get the Sequenceにはまだ高速化の余地があるのではないか?可能ならば等速レベルまで持ち込みたい.

▲テスト中にMicrosoft.VisualBasic.Coreが突然パネルを開いてダンプを表示した.⇒いや,理由はわかった.ある数字が3の倍数だと言っているのだが,どうしろという言葉がないので,メッセージとしては不十分だ.

image

超巨大数で遊んでいることはこれを見てもわかるだろう.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA