ある範囲の奇数ノードを含む極小のコラッツ木を生成できるようになった

昨日開発機に仕掛けた2^24の検証テストはすでに完了しているが,制御が戻ってこない状態が続いている.多分ゼルコバの木にエクスポートするためのファイルの整形に時間が掛かっているためと思われるが,少しかかり過ぎのような気もする.テスト自体は7時間10分掛かっている.⇒デバッグ用のダンプ出力を止めることでほぼ妥当な時間で完了できるようになっていたはずなのだが,その前の版を使っているのだろうか?いや,開発環境から直接走らせているのでこれが最新版だ.

デバッグの一時停止も効かない状態だ.「デバッガー操作に予想以上に時間が掛かっています」を表示したままのハング状態だ.デバッグ中止ボタンも効かない.アプリを強制終了するしかなさそうだ.パネルが隠れていてOKボタンを押せなかったためかもしれない.すでにアプリを落としてしまったのでどうしようもないが…エクスポートファイルのサイズが大き過ぎる.22.9GBもある.これでは時間が掛かっても当然だ.VerifyTest.CSVは読めないので一旦捨てるしかない.

コラッツ銀河高速道路系に含まれる5機能すべてで隣接リストのCSV出力とゼルコバの木へのエクスポートができるようになった.特に,検証テストの結果をゼルコバの木にインポートできるようになったというのが目玉だ.これまでの出力はすべて正則木だったが,検証テストではある範囲の奇数ノードを含む極小のコラッツ木を生成できる.たとえば,1~511までの奇数を含むコラッツ木は以下のようなものになる.

ゼルコバの木最新版をリリースしてインストールしたが,起動時に「パラメータが間違っています」のエラーが出る.最大カード数を6000に増量した版なのだが…とりあえず,アンインストールしてインストールし直してみる.⇒タスクバーに古いバージョンのアイコンが残っていたためと思われる.再インストールして起動するようになった.しかし,動作が少しおかしい.タスクバーのアイコンが白くなっている.アプリのタイトルバーのアイコンやデスクトップ上のアイコンは問題ないのだが…⇒古いアイコンがリンク切れになっためだろう.

image   image   image

もう少し小さいサンプルを取ってみよう.小さいと言ってもこんなものになってしまう.これは1~127までの113点サンプルだ.一番右のサンプルは1~31の53点サンプルで,長い鎖の終端は27という奇数だ.一番左の図などは,「コラッツというゴースト」がどのように見えるかをもっともよく示すものと言える.下図は1-3-4 仮想正則コラッツ木だ.

image

仮想木の場合は,完全正則木を出力することができる.上のコラッツゴースト図と比較するとその差が鮮明にわかると思う.つまり,「コラッツ木というかつて人々を悩ました亡霊」はいまや完全にアンダーコントロール状態にあると言える.

現在ゼルコバの木は最大カード数6000という設定で運用しているが大きいCSVファイルをインポートしようとするとエラーが発生する.まず,これを見ておこう.

検証テストが遅くなるという難題が解決した

検証テストが遅くなるという難題がようやく解決した.この問題をややこしいものにしていた原因の一つは,.NET 5.0が生成するEXEやDLLのファイルサイズがほとんど変化しないということがある.これまでのプログラミングでは一行コードを書き換えればそれが敏感にファイルサイズに反映され,それによって「改ざん」などのリスクを回避することもできていたのだが,ここまでファイルサイズが無変化ということになると,そのリスクはかなり高いものになってしまうような気がする.少なくともカスペルスキーなどでは見落とされてしまう可能性は高い.

検証テストはリリース版で2^13の設定で10秒罹っている.以前は3秒で完了しているので多少遅くなっていることは確かだが,2分近くかかっていたことを考えればおんの字だろう.コラッツ銀河ハイウェイは完成に近づきつつある.あと残っているのは主に表示に関わる修正と,CSV出力だけになった.多少面倒だが,波乱なく進めることができるだろう.

まず,最初にコラッツ木生成で大きなDを与えたとき,Max tree heightやMultiple of 3がほとんど変化しないという問題を片付けよう.Multiple of 3(3の倍数)という用語も今後は”triple”という語で表現したいと思っているので,それも合わせてやっておくことにする.⇒通常 triple number というのは111とか777のような数字の並びを意味しているようなのでちょっとまずいのかもしれない.⇒現状のままとしておこう.⇒対処した.統計情報の更新をすべて子ノードを展開するところで実施するようにしたので,ルートノードだけ別扱いする必要が生じた.仮想木ではノード1のところで発生する無効ノードカウントはここでまとめて処理するようにした.あとは,マニュアルを書く時点で詳細チェックすることにして,最後のCSVファイルへの書き出しに進もう.

Open Live Writer をオープンできない

Open Live Writer をオープンできない.An unexpected error happened というメッセージパネルが出ている.スクリーンショットを取ってJPGで保存しておいたのだが,それを開くこともできない.パネルにはSend MessageとContinueという2つのボタンが付いているが,どちらも作動しない.時間が経つとこのパネルは消えるが,何度やってもOpen Live Writerを起動することはできない.

やむを得ず,もう一度本家サイトからダウンロードしてインストールした.問題はこれで一応解決したのだが,数日前からカスペルスキーでアプリ更新しようとして失敗するという状態が続いていたのと関係あるかもしれない※.アンインストールしないで再インストールしているので,設定などはすべて温存されていたようで,何も言わず黙ってこの画面が開いた.とりあえず,問題なく動作している,ようだ.

※これは勘違い.アップデートできなかったのはLibreOfficeだ.

検証テストの実行速度が極端に落ちている問題を解決しなくてはならない.状況はある程度までつかめたが,ある意味でいよいよわからなくなってきたという感じもある.これまでわかったことを整理しておこう.開発環境はVS2019のVBを用いている.

  1. 異変は「仮想木」を実装して動き始めた時期と重なっている.具体的には2月8日から9日のころで,障害はすでに8日の午後5時ころには発現しているが,それに気付くのはだいぶ時間が経ったあとで,その後も作業を継続していた.
  2. この時期にはすでに,仮想木の実装は一段落してコードの整理に着手していたので作業量が膨大かつ慎重を要するものであったため,8日だけでバックアップを5回,9日には3回バックアップしている.
  3. 9日にはフォルダ名やアセンブリ名をCollatz Milky Highwayに変更.
  4. 当初は,スタックオーバーフローに対処するために開発プロジェクトのポストイベントに組み込んだスタックサイズ変更のためのスクリプトに関係しているのではないかと推定,スタックを大量消費するA面のコラッツ木生成などには影響が出ていないため,この推因は放棄された.
  5. 正常動作している版のバックアップが2つある,一つは8日の午後2時に作ったBACKUP1と午後9時に作ったBACKUP4でそれ以外は全滅.
  6. BACKUP1に残っているリリース版のEXEは正常動作しているが,BACKUP1のコピーをリビルドして生成したEXEでは事象が発生する.
  7. BACKUP1のコピーをリビルドした版をREBUILD1とする.BACKUP1(のコピー)にREBULID1で生成されたモジュールを1個づつ移植して動作チェックしたところ,CollatzMilkyHighway.DLLが不良の原因であることが突き止められた.
  8. この2日間ではソースコードの各処に相当量の修正が入っているが,EXEのサイズは一貫して202,752バイトでまったく変化していない.
  9. WinMergeのバイナリファイル比較検査を通してみると,これらのEXEには数バイト~の相違点があるが,それらを除けばほとんど同一
  10. バックアップをリビルドして生成したCollatzMilkyHighway.DLLのサイズはBACKUP0では218,624で正常動作するDLLと一致しているが,BACKUP1では異なる値217,600になる.このDLLでは事象が発生する.

これらのことから推定されることは,①.NET 5.0ではマネージドコードのみを含むモジュールをEXEとして生成し,それ以外の部分はDLLに吐き出しているものと考えられる.これは効率を最優先するというポリシーによるものと考えられるが,これにより,EXEを見ていただけでは開発状況を把握できないという事態になっている.②EXEのサイズが不変なのでウィルス検査ルーチンはこのようなプログラムの改変を検出できない可能性がある.VBのソースコードである*.VBとEXEのコードは一対一対応しているというのはまったくの思い込みであり,実際には複数のDLLに分散配置されている.

問題はこのような事態にどう対処すればよいのか?ないしどう対処可能か?という点にある.BACKUP0をリビルドした版では正常動作するDLLと同サイズのDLLが生成されているので,まずこれが動作可能かどうかをチェックしてみよう.

ここまでをアップロードしようとして,以下のエラーになった.

image

どうもこのフロントエンド機は恒常的なディスク領域不足状態に陥っている模様だ.プログラムはCドライブに置くしかないので,外部ドライブに移動できるものは限られている.デスクトップ,ドキュメント,ピクチャなどをすべて空にしたが,空き領域はゼロのままだ…一度リブートしてみよう.⇒アップロードは失敗に終わったが,リブートしてここまでの記事は残っていた.Cドライブの空き領域は1.26GBにはなったが,赤い状態だ.もう少し拡げておかないと安定した作業はできない.しかし,もう削れるものはすべて削ってしまった.

どうすればよいか?あとできることは一時ファイルの削除くらいしかない.⇒全部削っても17.9MBしかない.ウィンドウズの更新プログラムのバックアップが削除できると多少は効果があるのだが…逆に累積更新プログラムのダウンロード中になってしまった.かなり無理なところまで削ったが,1.29GBまでだ.このマシンは何度もメーカーに出しているが,HDDもメモリも増設不可ということで対処できなかった.その代わりにSDカード256GBを使っているが,それも満杯になっている.

現在正常動作することが確認されているのは,BACKUP1に含まれるサイス218,264のCollatzMilkyHighway.DLLとサイズ202,752のCollatzMilkyHighway.EXEの組み合わせだけだ.しかし,リビルドして同サイズのDLLとEXEを生成するREBUILD0では症状が出てしまう.これはBACKUP1とREBUILD0に含まれるモジュールに差異があることを意味する.どこが違うのかチェックしてみよう.

  • BouncyCastle.Crypto.dll    3,318,504    3,318,504     ○
  • CollatzMilkyHighway.deps.json 3,669    3,669     ○
  • CollatzMilkyHighway.dll     218,624     218,624     ○
  • CollatzMilkyHighway.exe    202,752    202,752      ○
  • CollatzMilkyHighway.pdb    26,928     26,664     ○
  • CollatzMilkyHighway.runtimeconfig.dev.json 385  385     ○
  • CollatzMilkyHighway.rutimeconfig.json   260    154
  • Mailkit.dll   859,136     859,136     ○
  • Mimekit.dll  1,155,584       1,155,584     ○

サイズで比較すると差異があるのは,rutimeconfig.jsonだけということになる.これを差し替えて動作を見てみよう.⇒変化しない.⇒やはり,原因はCollatzMilkyHighway.dll にあるようだ.WinMergeで比較するとほとんど一致するところがないくらい違うという感じだ.しかし,逆アセンブリで見ると差異はそれほど大きくはないようにも見えなくはない.むしろ,前後のブロックの配置が変化しているのではないか?確かに,ロジックを整理するために前後関係を入れ替えたりなどのことをしていたかもしれない.もっとも肝心な点は正常動作しているときのソースコードを確定することだ.いまのところリビルドして正常動作するバージョンは見つかっていない.

いや,もしかすると手順を間違えているかもしれない.BUILD0は動作しているようだ.もう一度作り直してみよう.⇒いや,やはりできていない.スタックサイズが違う.DLLのスタックサイズは設定していないのだが,合わせてみた.⇒結果は同じだ.というか,BUILD0としているのは実際にはBUILD4のあとなのではないか?BACKUP1の直前はCollatzProject 2022-02-07-1なのではないだろうか?まず,先に2022-02-08-1をもう一度リビルドしてみよう.

ようやく,リビルドで高速動作する版を見つけた.CollatzProject 2022-02-07だ.この一つあとの2022-02-07-1では実行時にエラーが発生してしまうため,テストできない.ともかく,ここまで戻って何が実行速度に影響しているのかを確認しなくてはならない.2022-02-07-1はエラーが出るので,2022-02-07と2022-02-08-1を比較することにしよう.⇒無数と言ってよいくらいの差異があるが,本質的な点がどこにあるのか探る必要がある.

  1. MAXDUMPTEXT 4096 ← 2048
  2. Truncate Truncate ← Trancate
  3. CutTextBuffer 新設
  4. RichTextのスクロールを抑制
  5. EnabelDisable関数 新設
  6. Hideボタン 新設
  7. 枝番号リストチェック チェックの場合はループ内で転記する

検証テストに関わる部分に限定すれば,時間に影響しそうなところと言えば枝番号リストの転記だけのように思われる.⇒確かにそのようだ.これで最新版まで戻ることができる.⇒動いた.以前は3秒で完了していたところ,11秒かかっているが,まぁ妥当なところだろう.これで難題は解決した.一旦バックアップを取って次に掛かることにしよう.もうほとんど出荷できるレベルに達している.あとはブラッシュアップするだけだ.一度ログを読み直しておこう.

枝番号リストを更新するような変更が入ったのは,巨大数のコラッツ数列を求めるとき,枝番号リストが処理終了まで空白になってしまうのを避けるためだ.検証テストのときに更新するのは時間のムダだが,コラッツ数列のときはむしろ表示した方がよいと思う.

GetTheSequenceでダンプを止めていると画面がフリーズして何も変化しない状態になる.これはTree heightを更新していないためで,最大数から下降しているため,数字が変化しない.このため,開始も終了もわからないような状態になっている.最大高を与える番号は確定しているが,高さは変化するようにした方がよい.仮想木では現在もそうなっている.⇒対処した.

一般木でMax degreeを与えるノード番号がかなりおかしい.これはおそらく個別検査時に更新しているためと思われる.検証テスト中はUpdate以外での更新は認められない.⇒戻るところを間違えていた.もう一つ新しいバージョンがある.やり直しだ.CollatzMilkyway 2022-02-09と2022-02-09 BADがあるが,後者は捨ててもよいだろう.

どこかやりそこなったのだろうか?ValidNumberとWXの不一致が発生して停止する.⇒WXをローカル変数に変えているためだ.この値はグローバルでなくてはならない.⇒再帰関数の呼び出して参照渡しするようにした.

現在の実装では枝数と高さはUlongで取っているが,さすがに大き過ぎるのではないか?マニュアルではInt16<=32767としているのだが,この辺りが妥当な線なのではないだろうか?実際問題として,最大枝数が8桁にもなると,べき乗の計算ですら抜けてこなくなってしまう.⇒Int16では少し小さ過ぎるような気がする.枝数列をInt16範囲内い抑えても,中間の計算でオーバーフローしてしまう.CountValidPostでInt16を超えているようだ.⇒Uintに変更した.設定はInt16のままとする.

▲A面では検定中に仮想木モードに切り替えができてしまう.⇒B面と同じようにアクセス不可としておくのがよいのではないか?それが一番簡単だ.

▲GoボタンがStopに切り替わらない.⇒動作しているが,応答が遅れているため入らないように見えている.⇒仮想木モードでは停止しないかもしれない.

一般木で樹高800を設定してスタックオーバーフローが発生する.少し早過ぎるような気がするのだが…高さ425で発生している.⇒CollatzTreeStructureで使っているローカル変数をグローバルに戻したが,効果なし.以前はheight=11111でオーバーフローしているので,800というのはまったくの番外だ.いや,開発環境では同レベルで発生していたようだ.あ,なるほどわかった.デバッグモードではスタックサイズの変更を実施していない.⇒マクロでDebugを指定することはできるが,実行されていないだけでなく,その文字列自体消去されてしまう.固定した文字列しか受け付けていないようだ.まぁ,この件に関してはこれで仕方ないものとしておくことにする.

▲DとHをそれぞれ最大値の32767に設定して走らせて,計算は進んではいるが,表示がまったく更新されない.これは,そのノードの現物を処理するまでは表示を更新していないためだが,子ノードを出力した時点で更新するようにした方がよい.H=3267ではボトムに達するまで何も表示が更新されない状態が続いてしまう.D=32767,H=1でも同じだ.有効ノードが1に変わる以外何の変化もない.

リビルドして実行速度低下という不可解

椅子の上で眠り込んでベッドに戻る前に朝になった.検証テストが遅くなるという難題が発生している.フォルダやアセンブリ名の変更などでスタックサイズ変更が効いていないのではないかと思ったが,どうもそれではなさそうだ.もしスタックサイズの問題なら系列木生成の方にむしろ大きい影響が出るはずだが,特に問題はないように思われる.速度の点は比較していないので分からないが,樹高を1万以上の大きな数字にしてもスタックオーバーフローが発生しないということは,明らかにスタックの問題ではないことを示している.どうも腑に落ちないのは,検査カウント2^13の設定を3秒でクリアできる版を開発環境でリビルドするとなぜか遅くなってしまうという点だ.

つまり,おそらく昨日のどこかの時点で開発環境が変化してしまったと見るしかないような感じだ.スクロールするつもりでマウスのリールを操作すると画面に表示されているオプションリストが勝手に変化したりすることがあり得るので,どこかで不用意に環境パラメータを変更してしまっているようなことも考えられるが,VSの動作環境設定はほとんどプロジェクトが保持しているので,ここまで影響するような環境パラメータが「場」によって保持されているということはかなり考えヅライ.

どう対処したらよいのか?それが問題だ.秒速で動いているパッケージがリビルドで遅くなるとすると,問題はソースコードの問題ではないということになるから,いくらデバッグしようとしても解決を見出すことはできないだろう.まだやらなくてはならないことは山のようにあるので,このまま進むことも考えられなくもないが,いつかそれが自然解消することなど期待できないとすれば,ここでシューティングしておかないと将来禍根を残すことになる.

考えられるのは,OSの再インストールとか,別のマシンにVSをインストールしてビルドしてみるくらいのことしか思いつかない.秒速で走る版の中で最新のものは,CollatzProject 2022-02-04というものだ.その後,フォルダ名をCollatzMilkywayと変更したあとの版は全滅だ.つまり,タイミング的には開発フォルダ名をCollatzMilkywayとリネームした辺りからおかしくなってきたと思って間違いないだろう.もちろん,フォルダ名そのものの問題でないことは,CollatzProjectと呼ばれていたころの版でもリビルドして遅くなっていることから見ても間違いない.ここまでほとんどノンストップで全力疾走してきたが,思いもかけない伏兵にしてやられたという感じだ.

VS2019を修復インストールしてみたが状況は変わらない.この際なので,VS2022をインストールしたが同じだ.ビルド時にスタックサイズを変更するためのeditbin.exeの場所が違うのでエラーになったが,””C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\editbin.exe”を指定して通った.また,VS2022はプロジェクトを開くときにネットに接続していないとエラーになる.ビルドして走らせてみたが,2^13で3分47秒もかかった.VS2019では最速で3秒,遅くとも2分以内だったのでデグレードしている.もう一つ,この環境には.NET 5.0はインストール済みなのに再インストールを求められた.

VS2019に戻すことにしてVS2019 Communityは過去バージョンのダウンロードページで探したが見つからない.マイクロソフトアカウントでサインインして中に入ったら見つかった.editbin.exeの場所も戻さなくてはならない.”C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\editbin.exe”

ようやく原因が見えてきた.少なくともこちらのソースコードの問題ではないことは確定した.つまり,最速で動いている環境にリビルドしたEXEを差し込むと最速で動作することができる.配布パッケージにはファイル(マニュアルのPDFを除く)が10本入っているが,それらのうちのどれかが速度に影響を与えているものと考えられる.これらはビルド時に生成されるので,ソースコードとまったく無関係と言えるかどうかは分からないが,プログラムの論理は基本的にすべてEXEに埋め込まれていると考えられるから,こちらの立場からすればあくまで外部(から持ち込まれた)ファイルであると言える.これらの中にはEXEが1,DLLが5,JSONが3,PDBが1含まれる.JSONはおそらく情報を保持しているだけなので,問題はおそらくこれら5つのDLLのうちのいずれかなのではないかと推定される.

原因となっているDLLはCollatzMilkyHighway.DLLという名前のDLLだ.これとまったく同じ名前のファイルがフォルダの中のrefというフォルダに隠されているが,これと置き換えるとアプリが起動しなくなる.このDLLはおそらくアプリと.NETのインタフェース用の関数群と推定されるので,アプリが変われば変化する可能性もある.ただし,これはおそらくBigIntegerの取り扱いに関わるものと推定されるので,その辺りに変更がない限りは同じものが使えるのではないかと思う.最速で動作可能なDLLをあらかじめパッケージに含むように構成できればよいのだが,このプロジェクトでは配布用パッケ時を生成するプロジェクトのようなものは存在しないので,お任せになっている.

サイズは動作する版は214KB,遅くなる版は少し小さくなって213KBだ.いや,違う.その逆だ.正確には前者が218,624バイト,後者が217,600バイトだ.デバッグフォルダにも入っているが,動作する版で217KB,遅くなる版では218KBで両者の差は約1KBだ.正確な数字で言うと,前者は222,208バイト,後者は223,232バイトで,どちらも前者と後者の差は1024バイト,デバッグ版とリリース版の差は4408バイトだ.

いつからそうなっているのかを見てみよう.バックアップは2月8日に4回,9日に2回の計6回取っているが,リリース版に限ればこの期間に3種のバージョンが発生している.①218624B,②217088B,③216576Bで今回リビルドした版は④217600Bだ.②と③ではすでに同じ症状が発生している.2022/02/08-1はソースとDLLが一致指定ない可能性もあるので,もう少し古い版をチェックしてみよう.

幹線図で一つ大きなバグが出ている

今日はどのマシンも検証テストはお休みだ.予備機はテスト完了してレポート送信に失敗した状態になっている.ネットに接続していなかったためだ.予備機はマウスを持っていないので,WiFiに繋がっていないと操作も面倒くさくなる.要修正点はかなりあるが,方針はほぼ確立したので淡々と進めるだけだ.ユーザインタフェースを整備するだけでなく,内部ロジックの整理も進めている.基本的には共通処理の関数化だ.幹線図で一つ大きなバグが出ている.

まずこれを片付けなくてはならない.一般木モードで枝番号リストに以下のような枝番号列を入力して,幹線図を実行すると下図が出力される.150, 150, 149, 150, 149, 150, 150, 149, 150, 150, 150, 149, 149, 149, 150, 150, 150, 150, 150, 149, 150, 150, 149, 149, 150, 150, 150, 149, 150, 150, 149, 150, 1,

image

まるきり壊れている.基本的に幹線図と系統図はまった同じ論理になっているはずなのだが,一方は正しく動作し,他方は誤動作している.どこが違うのか?比較してみればわかるだろう.仮想木では問題は発生していないように見える.悪いのはもちろん幹線図の方だ.いや,系統図の方も動作しているようには見えるが正しくない.高さは33あるはずなのに主力は2段しかない.いや,コラッツ数列の方もおかしいのではないか?10段しか出力されていない.枝番号リストの要素数は33なので33段分の出力がなければおかしい.

いや,これはおそらく勘違いだ.というか,現行では裾刈りしているのですべてのデータが画面上に残っている訳ではない.やはり,ファイル出力を取っておくことがどうしても不可避だ.まず,それから片付けるのが先決だと思う.ダンプ出力(Output Frame)に出力している内容を逐次ファイルに保存すればよいというだけだから,それほど難しくない.出力先ファイル名は現行を踏襲でよいのではないか?B面の4機能すべてについて対応する必要がある.

GetTheNumberとTruncatedTreeを統合するという一度挫折した試みを再試行してみた.大体動作しているように見えるが,上のサンプルではやはり不具合が発生する.この仕掛けで少し調べてみることにする.Workingが落ちている.なぜだろう?⇒対処した.DumpSuccessorではN=1のときはループから脱出するような作りになっている.理由はよく分からないが,これでは問題は解けない.⇒この一行を止めて動作するようになった.N=1でループから脱出というのは仮想木の論理だ.

しかし,同じ論理で通常は正しく動作しているのはなぜか?いや,やはり誤動作している.たとえば,{3, 4 1, 2}のような枝番号列を与えると同じ不具合が発生する.⇒正しく動作するようになった.これで4つの主要機能のうちの2つが完全統合できた.この論理は十分整理された短いものになっているので,ここに関してはほぼ仕上がったと言ってよさそうだ.GetTheSequenceの動作に関しては「遅い」という以外ではいまのところ不具合は検出されていない.VerificationTestはこれら2つの機能を同時実行しているだけだから,GetTheSequenceが正しく動作している限り問題は発生しないと考えられる.

従って,主要な課題は,①ダンプ出力のCSVファイル保存,②GetTheSequenceの時間効率の改善の2点に絞られたと見てよいが,その前にユーザインタフェースの仕上がり度を見ておこう.以前は検証テストのときは,Verify以外のボタンはすべて隠すようになっていたが,現行では表示したままになっている.ただし,不能状態になっているため,アクセスはできない.処理を止めることができるのはその処理を実行したボタンだけだ.この仕様は統一していた方がよいと思われるので,現行仕様でゆくことにする.つまり,検証テスト時でもボタンは表示されたままとする.

いまのところUI上の問題としては,幹線図でボタンを押しても停止しないということぐらいだろう.これは上記の幹線図と系統図の統合に関わる修正がまだ収束していないことを意味する.それ以外の気になる点としては,幹線図ではダンプのスクロールが止まっているという点くらいだ.これはリッチテキストへの書き込みのタイミングの問題であるか,もしくは巨大数ではイベント取り出しを挿入することで解決できる可能性はある.それ以外に関しては大体整ったのではないだろうか?

なぜだろう?今度はスクロールしている.どこかで詰まっていたような感じの動作だ.Hideしたあと,復帰するとスクロールが止まるようだ.Hideでは一度バッファを空にしているはずだが,何かそれが影響しているのだろうか?処理速度もガタ落ちになる.⇒いや,Hideは無関係だ.おそらく,幹線図ボタンを押して停止しないことに関係があるような気がする.⇒修正箇所の末尾にExit Subが入っていなかった.⇒問題なく動作するようになった.

一度バックアップを取って次に進むことにしよう.GetTheNumberからストリームの生成と削除を外部に出しておこう.巨大数からスタートしたら,検証テストが停止してしまった.画面は完全にフリーズして進捗は0.1%から進まない.時間パラメータなどもまったく更新されていない.検証テストでは分岐枝リストは隠蔽されているので巨大数が変化しなければ画面は更新されないかもしれない.GetTheSequenceの中でループしているが,現在処理している数は以下のような超巨大数だ.

2528058605650309290508888155878365873428777429329610245413531311009122565860838398507676428668641990449924367323415451899873821658847829619188476564609366352702999427697461717245345793567375753419434826837084809819187673744168005156233758197632068953158785059785541461281384157479418664309929750546454137807100651733674745192215247806173061415661839289683203890090799608996185234179653008138574134546686477565876857223738465581402202324837022126911299780190554607097797321091022298422990450981213040487361883130177550274229688099047178007993463543466203946899609777870963425143600687946887565306149102811552895681467300892411042453238919661322541656922453905703571728895506294249735279164519588778426338081418949046404041681479238492604279022081466893412796769929379101948906135366346556249038540581372645520472412289359158618160358472412007263793121017706881937054156793116038312573754653787854831684987083042562324675862091671106947587988672526236381818013363344313272643366547662655499416749339394332340176276845975735034944354345222361668081960134567712321247966403147137800022177709922207678398723630459082515612288167182980860868275309339807915114956553254228004239564965290904251972179527263931857494381014516047575390935825383341046273927855566344464493488087683285937219283412323388880268163013662384395026919914134269357896864175558581186612427162216168365618463641156257182811002745355638232058728168430212999716687243704359848387162463650198548737380336455000358109722081517100982229523851170083754245876978645997331446338585042572500540785537263453251586772867411773336673190389168808627642636740855484632735780130900694184850022908970961446381394196206567809487558672332285449135115500613758090759592501637733418414924494658499763499749856740392865738955937234908453589448627698488692327206913615159097455685630844807972113898597783728932686448197518328126736829742390484357327113612260986903860617280533132678703505809113795840336620912869135871285494809094219271876873193265897002339123448429406329793247623719431024457369184752032579844081845296815886142703127974129227170157151804670910364810214712275525981570448756401609764176601856457372634115371231558719016454868541064094196519074271639976183450304297493329628312917928009732620232965631112624422524888664476298883361486396999151217833342975058899339373560896635625507523367553360174880186864107155082164864619938566418729901717598133498744620859209004876233472945760658609354893169209360729580935766846602167702420539905855305875674621605368095487025419303392943367665067729641716782433336757636642964226393686660548609857855764209129788534360371354102204246160762995746366552409916472833822395730989310836921450340272188606083871652340560597556625997008012136989408662213438565313314843377659202426377961998727361330326547838071166092452532445441603781668225681266965867081944059412887781

確かにこれではとてつもない時間がかかっても仕方ないような気はするが…はて,どう対処したらよいのだろう?処理に要する時間を見積もることができるだろうか?ループ回数が分かればある程度の推定はできる.樹高は現在9287という数字になっている.まず,その前に最大分岐数と最大樹高を格納しているパラメータを計算用と統計用に分離しておくことが必要だ.コラッツ数列処理と分岐枝リスト処理はそれぞれ分岐数,最大樹高を管理しているが,それと検証テストで使っている大域変数を分離する必要がある.この修正も結構広範なものになるので,一度バックアップを取り直すのが賢明だ.

▲コラッツ木生成でダンプのスクロールが始まるまでに時間がかかる.

なぜだろう?検証テストがやけくそ遅くなっている.画面もほとんど更新されない.いまの修正の影響だろうか?2^13で2分39秒もかかっている.また,テスト終了時にスクロールしていない.GetTheSequenceの動作にはまったく問題がないようだ.GetTheNumberではMax Degreeが0のままだ.また,それを与えるノード番号も間違っている.Max Degree 3 @ 77と表示されているが,77[3]=821なので,3 @ 821と表示されなくてはならないところだ.TruncatedTreeでは上の症状がまたぶり返している.しかし,修正は残っているので,今回の修正の影響だろう.反例はOdd number=16385.

共通処理のGetTheNumberでは冒頭で最大分岐数を取得しているが,その計算を仮想木のときしか実施していない.これはかなりおかしい.これでは動作するはずがない.しかし,それにしては分岐枝リスト処理では正しく動作しているように見えるのだが…⇒おそらくこれは,分岐枝リストでは最大分岐数は動作に関わりがないためだろう.幹線木ではその値がないと木を構成できない.⇒対処した.

幹線木ではMax Degree 3 @ 262165はた出しいが,Tree height 15 @ 262165は間違っている.これは15 @ 16385でなくてはならない.Tree heightはあとから見ることにして,分岐枝リストのMax Degreeの誤認を見ておこう.この処理ではMaxDはあらかじめ定まっているので,比較して該当ノードを決めているはずだ.821の分岐枝が1になっている.これは間違っている.⇒幹線図と分岐枝の統合で手抜かりがあった.⇒完全に動作するようになった.上記のTree height 15 @ 262165の誤りも解消した.Tree heightのローカル化もやっておこう.

不測の事態に備えてバックアップを取ってから始めよう.木の高さに関してはTreeHeightとMaxHeightの2つのパラメータが使われている.B面のTreeHeight2に格納されているのはこの値だ.MaxHeightが使われる場合もある.混乱を避けるために,MaxHeightを統計更新用に用いることにする.MaxHeightはすでにそのような使い方に統一されている.TreeHeightは現状でも問題なさそうだが,一旦廃止して個別にローカル変数として再定義することにする.

大体収まったように思われるが,仮想木ではまだかなり悪い.GetTheSequenceでMax degree=0,Tree height 0 @ 85などのおかしな値が出ている.GetTheNumber, TruncatedTreeは正しく動作しているようだ.GetTheSequenceではMaxHeightは最後にならないと確定しない.⇒大体収まったのではないかと思う.⇒検証テストがやけくそ遅くなっているのはなぜだろう?このテストはGetTheSequenceとGetTheNumberを交互に実行しているだけなので,そのどちらかないし両方が遅くなっていると考えるしかない.GetTheSequenceはGetTheNumberよりだいぶ遅い感じがするので,それが原因かもしれない.この速度の差は元々存在していたように思われるのだが…

ともかくMax degreeとTree heightを片付けてしまおう.検証テストではMax degreeがまったく更新されていない.直接値を書き換えている場所があったので,すべて排除した.多分これで問題は解消したのではないかと思う.もう一つ整理しておきたいことがある.汎用の小さな変数がグローバル変数として定義されているという問題だ.この中には,D, H, i, j, Nなどがある.⇒片付いた.

今日の午後5時ころにバックアップした版では,まだここまで遅くなっていない.多分この直後の修正で何か致命的な不良が紛れ込んだものと思われる.この版ではすでにGetTheNumberとTruncatedTreeの統合は実現されている.確定的なことは分からないが,上記の3000桁以上あるような超巨大数に対処するための修正にかかった辺りから異変が生じているもののように見える.このバックアップのあとに2回バックアップを取っているので,修正は相当広い範囲に及ぶものになっている.これをもう一度手戻りするのはかなりきつい.しかし,シューティングもかなり難しそうだ.この版と次の版の差分を調べてみるというのが一番早いのではないだろうか?ともかく,いま現状でバックアップしておこう.

フォルダ名を変更したことが影響している可能性はあるだろうか?これまではCollatzProjectという名称だったものをCollatzMilkywayに変更している.これで影響するのはスタックサイズの変更でそれに失敗していれば速度に影響する可能性は大きい.変更点を列挙してみよう.

  1. HIDEBRANCHLISTのON/OFFが違う
  2. sjisEncという変数名をUTF16に変えた
  3. Nが巨大数のときDoEventsを実行する
  4. ゼルコバの木CSV出力を前方に移動
  5. GetTheNumberのオリジナルコードを廃棄
  6. TruncatedTreeの修正をフィックス
  7. UpdateTreeHeight関数の修正を確定

いや,どうも少し勘違いしていたような気がする.上記の3つ前のバージョンでも開発環境で走らせるとそれほど速いというほどのものではない2^13で1分58秒かかる.一方最新版もEXEを走らせた場合には同じ設定で3秒で完了する.ということは,まったく遅くなっていないと言える.この版は廃棄して作り直すつもりだったが,そのまま続行で問題ないようだ.いや,しかし,どうにも腑に落ちない点はある.上で実行速度をチェックしたときは,すべて開発環境でリリース版を試している.3つ前のバージョンは少なくともそのときは十分速い実効速度を持っていた.

いや,間違っている.いま試している版はColatzProject 2022-02-08 BADというものだ.最新版は同じBADでも,CollatzMilkyway 2022-02-09 BADだ.それではColatzProject 2022-02-08 BADはどこから出てきたのか?これは今日の午前0時32分なので最新版ではないかと思うのだが,CollatzProjectとついているのだから旧版の系統だろう.しかし,中身は2022/02/08のCollatzMilkyHighway.exeだ.どうも訳がわからなくなってきた.いや,これは少なくとも24時間以上前の版なので,最速版よりも古いことは間違いない.確実なのは,CollatzProjcect 2022-02-008-2というバージョンだ.ともかく,ここから出直そう.

B面のユーザインターフェースを整備する

開発機では昨日仕掛けた仮想木の検証テストがまだ走っている.2^26という設定で,9時間40分走って残り時間9時間40分だ.予備機の検証テストも続いている.こちらの版は古いので仮想木ではなく,一般木のテストを実行している.22時間34分走って残り時間2時間だ.テスト範囲は2^26で開発機と同じだが,だいぶ遅い.開発機にはもう一つ画面が開いていて,こちらはA面で5-3-12の仮想木を生成したところで止まっている.このテストには1時間27分掛かっている.最大数は95374949936989296587566193というすでに十分大きな数だ.

同じ設定で一般木をテストすれば一般木と仮想木の規模の差を感じられることだろう.仮想木モードと一般木モードを切り替えるとルート番号が5から1に切り替わる.仮想モードで1をルートとすることも可能だが,1の下には5というノードしかないので意味がない.仮想木のテストは1分34秒で終わってしまった.最大数は1106193406531349.テストした有効ノード数は12286で仮想木の797161より圧倒的に少ない.所要時間はほぼ有効ノード数に見合っているとみてよいだろう.開発機のテストは一旦打ち切って先に進むことにしよう.

現行ではB面の処理は検証テストを除くと実行時イベントを取っていない.つまり,打ち切ることができない状態になっている.ここまで大きな数を扱うようになると,それでは不便なのではないか?少なくともどこかでイベントを取るようにしなくてはならないし,またそれが可能になったときには少なくともボタンが押されたときに停止するようになっていなくてはならない.しかし,通常ならあっと言う間に終わってしまうので,ループで毎回イベントを取るというのも負荷が大き過ぎるような気がする.まぁ,軽い処理なら余分な処理が入っても逆に大した負荷にはならないとも考えられるが…

枝番号列が1, 10000, 10000, 10000, 10000, 10000, 10000の設定で幹線木を実行してハングした.DumpSuccessorsでループしている.木の高さ1のところで立ち往生している.DoEventsを入れたら動作するようになった.ただし,出力枠の表示は更新できない.B面でもA面と同じようにバッファの裾刈りをするしかないのではないか?テキストボックスは現在最大32767バイトになっている(リッチテキストボックスは2147483647).A面の最大テキスト長は2048でこれよりはるかに少ない.裾刈りをするとそのたびに再描画が発生するのであまり長いと却って効率を落とす可能性がある.両者共通に4096=1000Hくらいではどうだろうか?多少軽くなったが,スクロールは起きない.最大奇数の更新が忙しくて間に合わないように見受けられる.⇒幹線木では木の高さが増加するまでは画面が更新されていない.⇒テキストが更新されたタイミングで画面を更新するようにした

▲テキストをカットしているのでそれを補完するためにはファイルへの保存ができるようにする必要がある.

コラッツ数列取得では計算完了しないと枝番号列を出力しないが,中間結果を表示するようにした方がよい.⇒対処した.

B面にもHideボタンを設ける.⇒設置したが,それほど目覚ましい変化はないような感じもする.⇒いや,確かに速くなっている.

▲コラッツ数列取得処理をコラッツ番号取得と同等程度にスピードアップする.

▲処理開始で他の機能ボタンはディスエーブルとし,処理開始ボタンの二度押しで処理を停止するようにする.このボタンは中断ではなく,停止なので再開はできないが,表示されている内容が改変されないようにするというところがポイントだ.Get the Numberは停止→再実行を反復実行できる.Get the Sequenceでも動作している.⇒幹線木でも動作しているようだ.ただし,停止したときに枝番号列を書き換えている.また,Odd numberなどの更新が即時には停止しない.しばらくすると止まる.DumpSuccessorsで抜けてこないのではないか?⇒停止するようになった.

Get the Numberでエラーで停止したあとの動作が悪い.Value could not be parsed というエラーが起きている.カンマの後の空白だろうか?どうもそのようだ.というか,改行コードかもしれない.⇒次の構文で除去できた.

s = s.Replace(Chr(13), “”).Replace(Chr(10), “”)

コラッツ数列ではTree heightが更新されない.中間でも表示した方がよい.⇒対処した.

検証テストは巨大数から開始すると動作していないように見える.⇒動いてはいるようだが,画面が更新されていないためではないか?巨大数の場合はその場でDoEventsを実行するなど対処して,改善した.

▲Odd numberの最大テキスト長を2147483647にしてみたが,表示が消えてしまう.ただし,中身は入っているように思われる.実際問題として32767を超えていないのではないかと思うのだが…⇒効果がないので戻しておこう.⇒数字が表示されていない場合でも保持されている内容は正しいことを確認する.

検証テストでコラッツ数ではない数からテストに入ると,検定に失敗する.いや,そもそも,GetTheNumberでは仮想木モードのときは開始番号は1以外を認めていない.いや,それ以前に一般木モードでも動作しなくなっている…どこか壊してしまったのではないだろうか?⇒どうも何か致命的なミスを冒してしまったようだ.今日の始業時バックアップまで戻らないと動作しない.今日の修正はかなり広範にわたるものであり,しかもその間一度もバックアップを取っていなかった…

バックアップまで戻るしかないのではないか?しかし,それをやるとしたら今日の仕事ではなくなる.もう少し粘ってデバッグしてみることにしよう.GetTheNumberに一つ余分な処理を挿入したのが敗因だったようだ.それを除いたら動き始めた.どうもかなり由々しき事態になってきた.これまでのテスト結果がすべて無効になる可能性がある.無効というよりはほとんどイカサマだ.検証テストは通常1から始まるが,GetTheSequenceは1を与えられたときに返す値がない.1には親がないのだから当然だ.⇒コラッツ数列処理では1に戻るまでの経路を出力する.1は戻るべき親がいないのだから,無出力というのが正しい.

枝番号リストを指定してコラッツ数列の逆演算を実行する場合,「空」が与えられた場合には1が出力される.枝番号リストは1を出発点とする経路リストであり,たとえば,1を与えると1[1]=5が出力される.枝番号リストが「空」であるということは移動が発生しないということを意味すると考えられるので,1を出力することにした.すべての処理開始番号である1と枝番号リストの関係が確立された.

枝番号リストが空のとき,一般木ではエラ-にならないのに,仮想木ではエラーになるのはなぜか?仮想木の場合は冒頭でリストをチェックして先頭要素が1であることを求めている.枝番号リストは必ず1から始まることを想定している.⇒対処した.

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

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

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

Collatz Milky Highway 銀河高速道路系

予備機では引き続き検証テストが走っている.これもやがては仮想木の検証テストに切り替えることになるので,ある意味もうどうでもよい作業になってきた.新しい概念として「コラッツ仮想木」というものが導入された.これは,コラッツ数のみからなるコラッツ木であり,系図学的には長子ノードのみを集めた,長子木と呼ぶことができる.この概念を説明するよいメタファーを探していたが,最終的にはやはり一般道と高速道という区別で説明するのがわかり易いという結論に達した.

通常のコラッツ木を一般コラッツ木,仮想化されたコラッツ木を仮想コラッツ木と呼ぶとすれば,一般コラッツ木は一般道路系であり,仮想コラッツ木は高速道路系である.一般道路網ないし,高速道路網の方がイメージし易いが,コラッツ木は放射状に広がる木構造を持ったネットワークであり,網と呼ぶと誤解を招くおそれがあるため,ここではあえて「系」と呼ぶことにする.このコラッツ高速道路系を今後はCollatz Milky Highwayと呼ぶことにしたい.これはもちろん,宮沢賢治の銀河鉄道からの着想で銀河高速道路ということを意味している.これまではCollatz Tree Generatorと呼んできた我々の検証ツールも今後はCollatz Milky Highwayという製品名に変わることになる.

仮想コラッツ木はコラッツ木の各ノードの子ノードの集合を1点に集約したものであり,この操作を反復適用すると,最終的にはコラッツ高速道路系は一本のストレートな数直線まで転換することができる.わたしのイメージではこれこそ賢治が夢見た銀河鉄道にほかならない.宇宙エレベータというSF的なアイディアもあるが,それにも少し似ている.マニュアルがあるので,そう簡単にはゆかないかもしれないが,あと数日以内には「コラッツ木生成機」に代わる「銀河高速道システム」をリリースできるだろう.これがリリースされたらどうなるか?もう誰も反論できなくなることだけは間違いない.実装を続けよう.

すでに①コラッツ木生成・②コラッツ数列生成・③枝番号列からノード番号取得の3機能に関しては実装はほぼ完了している.検証テストは②と③の組み合わせ以上のものではないので,残っている大きなところとしては,④コラッツ幹線木生成があるだけだ.まず,これを片付けてしまおう.仮想木⇔一般木の切り替えスイッチをタブBにも設けることにした.このスイッチはタブAのスイッチと状態を共有し,連動する.

▲Get the Numberで枝番号に大きな数を入れたらエラーになった.単に大きいという理由ではなさそうだ.10000を超える数を入れても問題ない.おそらく,枝番号の組み合わせて何か大きな番号にぶち当たっのではないだろうか?⇒いや,違う.おそらくコンマとピリオドを間違えたのだろう.エラーになるのはよいが,入力が消えてしまうのはまずい.⇒例外処理でクリアしていた.そのまま抜けるように修正した.

Trancated TreeとGet the Numberは1行の表示内容が異なるだけだから統合できる.⇒ほぼ統合完了というとろまで作業したが,最後の詰めでやはり分離しておいた方がよいという結論に達したので巻き戻して作り直した.コラッツ仮想木の実装はほぼ完了した.

▲検証テストで上記と同じThe value could not be parsedエラーになった.ボタンにはStopが表示されている.これは実行時に表示されるものではなかったか?仮想木モードでなければ動作する.1から開始するとエラーになるようだ.Odd number=1でGet the Sequenceを実行したとき,枝番号リストが空になったままだ.N=1のときはループを無動作で抜けている.⇒対処した.

仮想コラッツ木と一般コラッツ木の関係を明確なものにするために,論理を整理して共通部分は可能な限り共通化するようにした.関数は仮想木・一般木の共通処理と,それぞれの専用処理に区分される.

幹線路と支線路の相互乗り入れをどうする?

予備機の検証テストが完了していたので,メール送信でレポートし,そのまま続行する.コラッツ木生成処理ではコラッツ仮想木の実装はほぼ完了しているが,タブBの方はまだ未着手に等しい.どういう仕様にするのが最適か?悩んでいるところだ.仮想木出力を指定したときには非コラッツ数は扱わないというのが一番わかり易いような気もするのだが…たとえば,非コラッツ数が指定されたときの出力はどうなるのか?一番重要なポイントは,Get the SequenceとGet the Numberが完全な逆演算になっていなくてはならないという点だ.つまり,Get the Sequence⇔Get the Numberでなくてはならない.それを仲介する枝番号列の基準ノードをコラッツ数に限定するのか,それとも枝番号列の書式を拡張して幹線路と支線路のいずれも扱えるようにするのか?

どこかで幹線路と支線路の乗り入れをしなくてはならないのだが,どこでそれをやるか?が問題だ.一つの考え方として,通常のコラッツ木を指定した画面でGet the Sequenceを実行したときの出力にその情報を含めるということが考えられる.そして,それ以外の場所では幹線路と支線路は完全に分離するという方式だ.まず,これを試してみるのがよいのではないだろうか?もし,それがそれなりにわかり易いものであれば,その方向でまとめるものとし,そうでなければまた別の方法を考えてみるとしてみよう.この情報を出力すると,解法の理論的な正当性も確認できる.あるいは,先にタブBの仮想木検定を仕込んでしまうという手順もあるかもしれない.

やり易いところから着手するとすれば,後者ではないだろうか?「仮想木出力では非コラッツ数は扱わない」とすれば,既存のコラッツ木生成でルートに非コラッツ数を指定したときの動作には問題があると言えるかもしれない.最初にこの部分を修正して,動作に違和感を感じるかどうかを見てみることにしよう.⇒与えられた数字がコラッツ数でないときには,メッセージを出してコラッツ数に切り替えることを通知するようにした.これがベストなのではないか?

image

コラッツ数に切り替えるということは支線路から幹線路に切り替えるというように翻訳できるので適切ではないかと思う.これでよいとすれば,タブBの処理もすべてこのように扱うことができる.上ではGet the Sequenceで通常のコラッツ木のときには幹線路を併記するとしているが,むしろ逆に仮想木のときにそうすればよいのではないか?木の高さは同じになるはずだから,併記で問題ない.通常のコラッツ木では予備知識のない人でも理解できるように現状のままとしておく方がよい.

どこか間違えているのだろうか?433という数は432を4で割った商108が奇数ではないため,コラッツ数と考えられるが,5-3-10という仮想木上に現れない.⇒ゼルコバの木のカード数上限は現在3069点で打ち切りになっている.樹高61で試してみよう.⇒出てきた.きっちり対応している.下記のリストでは右側が仮想木,左が一般木のコラッツ数列だ.

433    433
325 [1]    81
61 [2]    15
23 [2]    23
35 [1]    35
53 [1]    3
5 [3]    5
1 [1]    1

433という数は一般的なコラッツ数列では433→ 325 → 61 → 23 → 35 → 53 → 5 → 1のように進むが,仮想木ではそれとはまったく異なる経路をたどる.433はそれ自体はコラッツ数だが,コラッツ数から出発してもすぐに一般道路に降りてしまう場合がある.433の場合の高速道経路は433→ 81→ 15→ 15→ 23→ 35→ 3→ 5→ 1のようになっていて,一度高速道から一般道に分岐しているが,その後もう一度高速道に戻っていることがわかる.このことから,一般道と高速道は平行して走っていて,高速道が一般道を束ねた構造になっていることが認められる.

高速道にはまだ枝番号が付されていないが,それを付けるのは簡単だ.また,それが与えられれば枝番号リストから高速道経路を1から上昇することはできる.ただし,それだけの情報では一般道の経路を完全に復元することはできない.上記したようにここは割り切ることが必要なのではないだろうか?ランプを出たところで元のアドレスへの地番を指定することができれば復元は不可能ではないが,仮想木の検証テストには非コラッツ数を含めないという予定なので,その元になる論理に支線のアドレスを加えると論理が無闇に複雑なものになってしまうのではないかと思う.むしろ逆に,Get the Sequenceでも仮想路を本線とし,そのおまけ情報として一般道路情報を付加するという仕様の方がわかり易いのではないかと思う.そういう方針でまとめることにしよう.

つまり,Get the sequenceでは任意の奇数を設定できるが,それ以外の処理では原則として非コラッツ数はまったく扱わないということにしたい.仮想木と一般木を比較したい場合には,Get the Sequenceを使うしかないということになるが,それでよいのではないか?これだけの仕様なら論理もそれほど複雑なものにはならないと考えられるし,高速道と一般道の相互乗り入れというものがどういうことを意味しているかは,これだけでも十分理解できるのではないかと思う.Get the sequenceの付帯情報の中に乗り入れに関する付帯情報を追加してもよい.

コラッツ数の仮想木上の枝番号をvorderとする.与えられたコラッツ数Mからvorderを得るにはどうすればよいか?例えば,21233という値が与えられたときの親番号は995,最右コラッツ数は663,vorderは3である.21233の親は15925.しかし,これはコラッツ数ではない.その右ノードは3981でコラッツ数ではない.その隣りが995で親に出てしまった.いや,手続き的には合っているのではないか?親の右に進めば仮親に出るはずだ.しかし,これではvorderを求めたことにはならない.

663は995の長子のはずだが,合っているだろうか?確かにそのようだ.3981は3の倍数なので子どもがいない.そのため21233の隣りが663になっている.つまり,コラッツ数でない親からコラッツ数までのノード数を数えて,そこから3の倍数を落としたものがそのノードの枝番号になると考えてよい.つまり,いまの場合は2だ.⇒一応できたようだ.

433    433
81 [1]    325 [1]
15 [1]    61 [2]
23 [1]    23 [2]
35 [1]    35 [1]
3 [2]    53 [1]
5 [1]    5 [3]
1 [1]    1 [1]

これで仮想木の枝番号リストを取ることができるようになった.仮想木モードではこの枝番号列を出力するということになる.おかしい.枝番号リストが出力されていない.一般木モードでも出力されない.出荷版でもそうなっていたのだろうか?読み間違えていた.出力されている.枝番号リストは逆順に出力しているので,更新されていないと勘違いしてしまった.⇒Get the Sequenceの基本機能はこれで完全だ.高速道と一般道をつなげるブリッジ情報は後回しにして先に進もう.

今度は枝番号リストからコラッツ数を求めるという段だ.一応バックアップを取っておこう.このプロジェクトは開発環境で開いていてもコピーできるというのはなぜだろう?VS2017では一旦閉じないとコピーできないことになっているのだが…

GetNodeNumberでは引数でNとposを渡して,その次の番号を返すようになっている.一般木の場合には,Nの長子ノードを見つけて,そこからpos分左にシフトして得た値を返すようになっている.仮想木の場合も先頭はNの長子ノードのはずだが,それでよいのだろうか?たとえば,ノード3の長子ノードは…いや,3には子どもがいないのだから,長子もクソもない.それではどういうことになるのか?

3の親の子どもを見るしかないだろう.3の親は5でその子どもを列挙すればよいのではないか?その子どもの中で3の倍数でないものは必ず有効な子どもを持つはずだからそれをカウントすればよいはずだ.いや,5は3の他にも113とか227などのコラッツ数を持っている.どこで区分すればよいのだろう?3の子どもには17や35がある.これらは3の兄弟の子どもだ.兄弟ノードは3から初めて左にシフトすれば取り出すことができる.そのうちで,3の倍数でないノードをカウントすればよいのではないか?⇒大体動くようになった.仮想木モードではどんな枝番号リストを与えても即座に答えが出る.つまり,コラッツ木の全領域に自由にアクセスできるようになった.もう誰もこれを否定することはできない.

仮想木モードで以下のような枝番号リストを与えてみた.

1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,

この数列は最大枝数8,高さ46の仮想木上にある.終端ノードは

32173099041860762800256009014059337270151874861822163878010366212117093498044081202440322041294047798815956074582858403201045161834721742197820853207051899509256665790691

という巨大数だ.10進で170桁もある!ここまで大きな数はWindows 10の電卓にも入り切らない.

1 [1]
5 [5]
14563 [5]
79535217 [5]
1737473334385 [5]
9488921036856433 [5]
51822160755951934577 [5]
141509046970919416019171 [5]
386414037595257285343017187 [5]
2110335863986898454353331199089 [5]
46100990394081792368166637821172849 [5]
251772875538878695386680731354031987825 [5]
687507798804831424202562850417410014755043 [5]
1877354629269726342355798290206474280291104995 [5]
10252859415318398797719133062247624869429821414513 [5]
27997141443429440983638379348644180976789699009231075 [5]
152901721803049320358643735749395420374574142855747312753 [5]
835047270007053354918672988839364855805674252182854657383537 [5]
4560471490598520722329179416381384599173388982587963568857291889 [5]
12453127483661027252440212592998767545476134181786865852026311719139 [5]
34005340115383711750663407187281967910846830405732668353266515201063139 [5]
185714497483482244440956421118809254083771489789174679433306195018072824945 [5]
507124387794895515486771667268428469818085348117639657972548116529350860650723 [5]
2769575323210522708578422332175310683166503447853136052074076113738961500300483697 [5]
7562787015913534009558145248393381705499998748270963512863610507916524203487187482851 [5]
165211603291636454950134202332902887817215972655561954926343192748939110066578772958714993 [5]
3609102544440228903870665028029707885329688661318302759350942493331491172441102154874115267697 [5]
78842048117478280481355967758984978657655492036052096545607789080990868492366690273943339394604145 [5]
1722330821809018863208714901017613187102703442024903399737650688403939185838581137931050230188259089521 [5]
37624890912691953406415446584363432609987590925514689735068891838413519494372417818483102628539249230290033 [5]
205482070904514988203570225612736826627345563241210892206456241293522367798599231179342384488662353129690635377 [5]
561103041616595594454549096073180027910404951357333209651763176225511745668708300607057604577040665612808561670371 [5]
1532185372307717036590555398343830262880679120506424551155747979879797406839352799524338632231705710900042579067893987 [5]
4183887523314939321249943274410885837839507785062876641022629150391766785609326044567794025080711061231049602574729181411 [5]
22849604393997321946453023535982651189054165183490056962171585333339569005141065971399579102307456675736505562861454302747761 [5]
499157224521669497027581783484719676108617923155068124357625672135247331440308299833880938682940493567022542855896089728292428913 [5]
1363031994427172173216649990102274528893932675495439358245889835377315379719668530746384216563549507767016223691833589018057192552675 [5]
7443972065564929628660531145945221960466064318439092815166886354273978393775683069249586334725731711751597936322333840823949680927677553 [5]
20327006387035967839329023715861086100045999632217682780615711004737477000603465234430870418024398060889696764784186274676598595386511505635 [5]
111012557548399099026522241520222678221051219324751504892535936367206274392629058133638460309637245943205597264741369308100463795604201502776433 [5]
606276580957656946150180135022442786657901059138909552053102927146769199882944829487177511237698879177826835195174198247972666275726412473829694577 [5]
13244314003213668540966068442943603488804067937242525467784051144496888761176224115090555125491277915266019823783645418793045552348668722628300954606705 [5]
72331613542884248458396021789729333186855283027927179088057964650479008487703751967214551725349699121239489597623748847168419443226862783847360946758753393 [5]
1580108208382154035656480561337233859911249276172745202904988923777930766750051029641124287290839293869850396756623334816009845543771893134073549002260554128497 [5]
4314748814355535286699296252824873260130984690135709567399223087862936280405472678273363387162185165127271483410086119604250884898193116184776837808839486473550051 [5]
11782140762400181689546878301047120582331008860530577592044811845257724669693877393471797622544206957574202664031808497266007749695332669261897285110004357730440673507 [5]
32173099041860762800256009014059337270151874861822163878010366212117093498044081202440322041294047798815956074582858403201045161834721742197820853207051899509256665790691

この数列は仮想木上の枝数番号列だが,これを一般木の数列つまり,通常のコラッツ数列に変換すると下記のようになる.

32173099041860762800256009014059337270151874861822163878010366212117093498044081202440322041294047798815956074582858403201045161834721742197820853207051899509256665790691
48259648562791144200384013521089005905227812292733245817015549318175640247066121803660483061941071698223934111874287604801567742752082613296731279810577849263884998686037 [1]
17673211143600272534320317451570680873496513290795866388067217767886587004540816090207696433816310436361303996047712745899011624542999003892845927665006536595661010261 [7]
6472123221533302930048944379237309890196477035203564351098834631794404420608209017410045080743277747690907225115129179406376327347289674277165256713259229710325077 [7]
1185081156286615526742360421002925394933436957129558902178741692833448075062538272230843215468129470402387797567467501112007384157828919850555161751695415596373 [7]
54248710157163186343797016342296999890141462270945384316043473487859256365777813975410913794012274340929617198217811635376314582420147087885520710069065045 [8]
9933235502410251405724551332207702616603050952931894100838038358372666570882168086317916344118458436449514867837734064094784164261501541971225715955029 [7]
454707435718242709612635101266832089993425794354182164039827195360076899912208622115383133428274159383370126396380648685979499706794809355372270933 [8]
83259418161299324269891681140167008665788414493563628669401952275404705794471793600228845232227934457404197948556026981075347846703151127082325 [7]
30490509580553951758993535573791629150068999448326524170923566507106215500905197851646305627036597091334545147176279412014897893079767258453 [7]
5582979049173697221495398359458916470349548238829319611375164765705483795331762301937189751044298783813698452241750380617962260695758165 [7]
2044547991640758259824974985153411793340899013243159037368834753065973069579502796119576324845324261650524335537750383527085788829013 [7]
374367918391252122770686337613539757081463442366301093268219254101435498580231224875410704012205370175266907141922067296219321685 [7]
17137203295497991459839767651986988391790623887617542721628689000004676753855799478549684326730592506802379172146090727060821 [8]
6275831284972408981874914911616328756759261677594314961533943725587650178413989066851691037621066591846574403862093772117 [7]
2298278058461575554885833097515745394321018680759636826733621969819696110259029199286507948347558566350063868601840981 [7]
841654562424893391681823644109770041865607427035999814477644764338267618503062450910586406865560998419212842505557 [7]
154111553178386241152677669209552619970509172430908169154842180970141775848949423384506788366496764847267976533 [7]
28218668184518965054811584938272574457490693194136017301301668878810139620779313363862326971404436922717525 [7]
1291748116356764147406536175763209890327027581518677549803238016302954389378935853448287672641194317141 [8]
59131536088108710361016975819238733993241619027039072409205841810743151369275017705457504545953109 [8]
2706826908330171677902998771022280913997266495988727069513206869998618379330826616155586450773 [8]
123908702468727341212600651749677165862911979491671466194757394561704332549934079719036245 [8]
11344180523870301014337217872590072558249998122406445269295415761874786305230781224277 [8]
2077181492407892031433816749131483012374877585889852039055557085304221125225362773 [7]
760686581692343273230157500902642704727128022176459486958822174794026290976085 [7]
139285873112611683330717315839106940562828617341881009574979646263554618709 [7]
51008010173075567625995110780922951866270245608599002529899772801594709 [7]
18679691225491540878660318889498151318214201272680298778039467578709 [7]
3420353617948890541746884562286038449380041736940972676642968917 [7]
626285452505290016189004741629523641854255689137140993037653 [7]
114676291352286990268982801812046565280930607141810484565 [7]
41995712165144161475457569022966271465184548513846613 [7]
7689644561488799098289349796685718652072366060885 [7]
2816031943904589513533697435309711420436657493 [7]
1031261698207247136303844275626115022132565 [7]
188829656654159021540010548515523990869 [7]
34575742795561344276124978365879637 [7]
1582751897990173840764998399317 [8]
579621056392885928014525781 [7]
212263570456379124028757 [7]
38866620566963950933 [7]
7116690777642325 [7]
1303105000789 [7]
59651413 [8]
21845 [7]
1 [7]

最大枝数と木の高さは変化していない.

瀕死のフロントエンド機を蘇生させる

予備機の検証テストは11時間走って40%,残り時間16時間24分.フロントエンド機を起動したら,また画面の崩れが始まってしまった.しかも,電源を落として再起動しようとしても立ち上がってこない.もうこれはいよいよダメかと諦めかけたところ,外部デバイスをすべて外して電源投入で起きてきた.そのあとは画面の乱れもピタッと止まっているので,まだしばらくはこれで使えそうだ.

コラッツ核木(Core Collatz Tree)の生成処理を実装した.まだ細かい詰めは残っているが,走っている.コラッツ核木とはコラッツ数のみからなるようなコラッツ木,コラッツ数とはそれから1引いた数を4で割った商が奇数とならないような奇数である.コラッツ核木の別名をコラッツ長子木(Eldest Sons Tree)としているが,系図を読み慣れた人でないとピンとこないかもしれないので,コラッツ放射高速路系(Collatz Radial Highway System)と呼んでみたい.コラッツ木というのは基本的に環状線を持たない放射線状の経路網で合流点以外の交差を持たないことが特徴だが,コラッツ放射高速路系はそれらの支線道路を1本の本線にまとめた幅広い複数車線を持つ自動車専用道路であるとみなせる.

コラッツ放射高速路系の経路状には通常のコラッツ木では行き止まり点(終端ノード)となっている3の倍数が含まれる場合がある.たとえば,3や75などはその例である.コラッツ放射高速路系の経路は通常のコラッツ写像ではトレースできない経路(トンネル)を含むある種の「仮想経路」であり,あまり直感的ではないかもしれないが,ノード数が大幅に減じているので広範囲の奇数の検定を短時間で実施できるとい利点がある.実際,枝数3,樹高12という設定のコラッツ木に含まれる奇数は最大でも1106193406531349だが,コラッツ核木なら…

同じ設定で計算を開始したが,どうもかなりの時間が掛かりそうな形勢だ.Max node countは797161で多分この数字はまった変わらないはずだが,コラッツ核木は基本的に完全正則木なのでこの数値が実際の有効カウントになってしまうためだ(1をルートとする場合にはこれよりも多少少なくなるが…)コラッツ木生成では残り時間をカウントしていないので,あとどのくらい掛かるか予測できないが,ともかく,しばらく走らせてみることにしよう.8分経過した時点の最大奇数は279418798644035773131889で,上の1106193406531349と比較すればどの程度「高速化」しているかがわかるだろう.

おおっ,意外にも短時間で停止した.所要時間24分8秒,有効ノード数は265721で最大ノード数の797161よりだいぶ少ない.差分は531440.これはノード1が5という子ノードしか持たないためだ.最大奇数は595730981401673782972529で前の数から倍増している.ルートノードを5にすると名実ともに完全正則木になる.1をルートとしたときの有効ノード数は最大ノード数の1/3程度なので,この3倍の時間を掛ければ完了できるかもしれない.仕掛けてみよう.どのくらい大きな数が出現するかを見るのが楽しみだ.

コラッツ放射高速路系という命名は直感的で悪くないと思われるが,実態をもっともよく表す名称として,「コラッツ仮想木(Virtual Collatz Tree)」というのを提唱したい.これは物理的なロケーションとは独立に仮想的なアドレスにデバイスを割り付ける仮想化と呼ぶ考え方にかなり類似した手法であり,「仮想化」という考え方に馴染んでいる人には理解し易いのではないかと思う.

コラッツ仮想木を考える最大の利点は,それが完全正則木を構成可能であるという点に尽きる.つまり,あちこちに穴のあいたシステムではなく,完全な均一性を持ったシステムとして扱うことができる.多分この利点は最終的な証明を与えるときに効いてくるだろうう.つまり,「我々の最後の切札」であるコラッツ木の仮想化という方式の導入によって最後のリングが繋がったと言えるのではないか?これにより,理論的な弱点/難点は完全に払拭されたのではないかと思う.あとは証明を与えるだけだが,その前にコラッツ木生成ツールを整備して,コラッツ木生成以外の4機能でもコラッツ仮想木を扱えるようにしておきたい.マニュアル整備まで入れるとまだしばらく掛かりそうだ…

ルートノードを5に設定したコラッツ仮想木生成が完了した.枝数3,樹高12で1時間15分.有効ノード数は797161で最大ノード数と一致している.最大奇数は95374949936989296587566193という巨大数だ.4桁で区切ると95 3749 4993京 6989兆 2965億 8756万 6193.無量大数10^68にはまだほど遠いが相当大きな数であることは間違いない.1までのコラッツ数列をトレースすると,

95374949936989296587566193
71531212452741972440674645 [1]
209564098982642497384789 [5]
613957321238210441557 [5]
1798703089565069653 [5]
5269637957710165 [5]
15438392454229 [5]
180918661573 [4]
33922249045 [2]
99381589 [5]
291157 [5]
853 [5]
5 [5]
1 [1]

で13階になっている.1から数えているので樹高が1増加している.しかし,それを除けば仮想木と通常のコラッツ木との間には階数の相違はない.つまり,これは仮想木が実コラッツ木を正確に翻訳したものになっていることを示している.「 」の次の「」の字が出ない…フォントがこの字形を持っていないのだろうか?

コラッツ仮想木の実装を進めよう.コラッツ木生成タブの処理はほとんど動作しているが,一部パラメータに未整備のところがある.というか,多分3の倍数のカウントが出ていないだけであとは動作しているのではないかと思う.Void node countもカウントされていない.ルートが5以上の場合はこれで問題ないが,1の場合はMax=Void+Validという式が成立しなくなるので,やはり更新しておいた方がよい.

3の倍数ノードをカラー表示してみた.カウントは40になっている.

image

女子を選択して部分図に登録し,ノード数のカウントを取って比較してみる.40で一致している.3をルートとしたときにどんな図になるのか見ておこう.⇒ルートは当然3で枝数3を指定しているので,その下に3つノードがある.17, 35, 1137だ.標準コラッツ仮想木のルート5と比較してみよう.⇒3は5の直下のノードでその部分木は3をルーツとする仮想木と完全に一致する.問題ないようだ.Void node countも実装してみたが,数字が一致しない.⇒一致した.3の倍数でも算入していた.

CSVファイル名も変えておいた方がよい.⇒コラッツ仮想木の場合は,CollatzCore.csvの名前で保存するようにした.同じD=3, H=4の正則木でもコラッツ正則木の場合は46点,仮想木の場合は121点と大きな違いがある.これは仮想木が完全正則木になっているためだ.これでタブAに関してはほぼ修正は完了したのではないかと思う.タブBには4つ処理が入っている.修正箇所はできるだけ少なく,かつ既存論理を壊さないようにしなくてはならない.まず,Get the Sequenceから見ることにしよう.⇒一応ここでバックアップを取っておこう.

もう一つ確認しておくことがある.ルートノードに非コラッツ数を指定した場合だ.⇒いや,それはすでに確認済みのはずだ.ルートノードは非コラッツ数でそれ以外は仮想木という構成になったはずだ.たとえば,13をルートとすると,直下ノードは17, 35, 1137になる.53をルートとしたときの直下ノードは35, 1137, 2275だ.13と35はいずれもコラッツ数3の兄弟ノードだが,13がノード3の部分木を完全に引き継いでいるのに対し,53には17は入ってこない.これは53を最右ノードと見立てたときの動作になっているからだ.動作的にはこれでよいのではないかと思う.どんな奇数が与えられた場合にも,その左には無数の兄弟ノードが存在するので,仮想木を構成するのに過不足はない.

Get the Sequenceという処理は通常のコラッツ数列を得るための手続きであり,幹線を通る場合も基本的には段数は同じになると考えられるが,支線から幹線に乗り換えるのに1段必要になるので系図的には1世代高くなると考えられる.あるいは,水平移動を省略して垂直下降して幹線に乗るというのでもよいのかもしれないが…Get the SequenceとGet the Numberは逆手順にならなくてはならない.つまり,GTSの出力はGTNの入力であり,GTNの出力はGTSの入力とならなくてはならない.