有効結婚リンク判定の重複処理を削減する

複数のバグをクリアできたので安定版として確保しておこう.Version 2.2.0.013 Release 2020-10-31となる.20201031-MTHOANBというパッケージを作った.⇒おかしい.インストールして走らせてみたが,ヘルプで出るバージョン番号が古い.⇒Program Files(x86)\babalaboで見ると,EXEやその他のDLLは最新版に差し替わっているが,OCXだけは元のままだ.おそらくOCXもバージョンを更新しないと差し替えてくれないのだろう.公式版のリリース手順は結構面倒くさいので,今日のところはアンインストール→再インストールしておこう.⇒アンインストール中以下のエラーが出た.

image

エラーは出たがアンインストールは完了している.⇒多分このパネルはアンインストールとは無関係だと思う.エクスプローラでその場所を開いていたために出されたものだろう.⇒今度はうまくいった.昨日の修正で予定していた「有効結婚枠判定の厳格化@20201030」というオプションの導入は不要ということになったが,処理が重複していると見られるところがあるので整理しておこう.「有効結婚リンク判定の重複処理削減@20201031」で切り分けることにする.

修正した.問題なく動作しているが,一つ致命的な欠陥が出てきた.Ancesty.zelのシンメトリが崩れてしまった.この修正はトポロジーには影響を与えないはずなので,もっと前から起きていたのかもしれない.⇒確かにそのようだ.この手戻りがどこで始まったのか突き止める必要がある.10月25日リリースの20201025-KGWZMZCでは正常動作していた.10月28日版も動作している.29日バックアップまではOKだ.おそらく10月29日の修正で何かやらかしたのに違いない.ログのタイトルは「ZTシステム構成図の構築が予想外に手間取っている」だ.

結婚枠間ギャプを取るようにしたことでSUWが発生するようになり,その原因がCheckInnerSplitであることが突き止められて,CheckGeneSplitの処理対象を人名枠から結婚枠に変更している.この修正は「METRIX:margvhを増加させる@20201028」で行っているので元に戻してみよう.⇒ダメだ.復旧しない.どこかに「METRIX:margvhを増加させる@20201028」を付けない修正が入っていたのではないか?少なくとも20201029の修正はあと, deltaを1増加させる@20201029というのがあるだけだ.これはdelta++するだけの軽微な修正だ.かなりまずいことになってきた.ここまで戻して回復しないとしたら,29日の始業時パッケージに戻るしかない.

その前にWinMergeで比較してみよう.修正の入っているソースファイル20本を目視でチェックしてみたが,有意差は認められなかった.⇒2箇所NOTHINGで止めているブロックがある.これはチェックしてみた方がよいかもしれない.念のためZELKOVA 2020-10-29をクリーンビルドして動作を確認しておこう.⇒確かに動いている.⇒CheckGeneSplitとSolveGeneSplitの論理をNOTHINGで書き換えている部分を復活させたら動作した.この修正を「系列内スプリット検査でGリングを使う@20201029」で切り分けるようにした.

系列内スプリット検査が必要となった主な理由は「フロート婚(TYW婚ないしシンメトリ婚)の存在」にあったと考えられる.Ancestryはその典型例であり,この処理がなければ壊れる,必須論理だ.もう少し垢抜けた方法があってもよいとは思われるが現状はこれで手を打つしかないだろう.⇒この版は保全しておいた方がよい.バージョンを繰り上げて差し替えることにする.Version 2.2.0.014を20201031-CQDZPJCとして保存した.この前の20201031-MTHOANBは廃棄しておこう.これでやっと一歩前進というところだ.

ファイルを保存したとき,修復が必要な「不完全データファイル」として保存されるという問題を考えておこう.最新版は問題となったZTシステム構成図(ERR11).ZELを開くことができるので,これを保存しても不完全ファイルにはならない.プログラムはサンプルファイルのエディションとバージョン番号が一致するかより大きくなければならないので,このような問題が発生するとすれば,バージョンより新しいエディションのファイルを読み込んだときに限定されるように思われる.一応動作を確認してみよう.(ERR11).ZELとして保存し問題なく読み込むことができる.ただし,ZTシステム構成図3.ZELを読み込んだ場合は出口検査でInvestigateHSplitsが検出されている.⇒一箇所スプリットが出ている.このスプリットは系列間スプリットで系列内スプリットではない.

このエラーはこれまでにも出ていたのに無視されていた可能性がある.念のため2020-10-29版で確認してみよう.⇒この版では系列間スプリットは発生しない.⇒逆に現行版でも29日以降の修正を全部復旧させれば解消する.主な修正3件を個別に復活させてチェックしてみよう.「deltaを1増加を廃止@20201029」を復活させると発生する.スプリットは「親参照リスト」と「所属グループ」の間で起きている.「deltaを1増加を廃止」以外のすべての修正は無害だ.この修正はTREEVIEW::InvestigateHSplitsに入っている.いま問題になっている検査ルーチンそのものだ.deltaは検査のモジュール単位だから,この値以下のスプリットは見逃されることになるが,値が小さい方がより精度の高い検査になるはずなのに,逆にスプリットが発生するという結果になっている.偶然ということもあるのかもしれないが…

スプリットが発生しない論理でdeltaの現在値は16になっている.インクリメントしなかったとすれば,15という値で検査していたことになる.delta値は標準フォント幅と結婚枠間ギャップの大きい方の値を採用することになっているが,現在の仕様では結婚枠間ギャップ=標準フォント幅=15になっている.InvestigateHSplitsを系列間スプリット検査と呼ぶのは当たっていない.この検査は広域検査で結婚枠や系列枠の存在とは無関係に描画関数を直接(仮想的に)呼び出して「(描画オブジェクトが)何も描画されていない区間」を検査するものだ.この意味では修正論理で検出しているのは「結婚枠間のギャップの幅15の区間」に相当する.それが一箇所しか検出されていないのは区間の座標がぴったり一致することが稀だからと言える.

この検定方式では最大で30の幅のスプリットが検出できない可能性があるが,少なくともそれ以上のスプリットの発生は抑制可能と言えるだろう.しかし,結婚枠間ギャップをスプリットと誤認するというのは論外なのでやはり,この論理は戻しておくしかないと思う.さて,本題に戻ろう.MAXPARENTSはCARDBASEでは親番号配列サイズを決めているが,保存データでは参照されていないのでMAXPARENTSが増減してもその範囲内のデータまでは安全に読み込むことができる.しかし,PERSONALとCARDDATAおよびMARGBASEは保存されたデータがそのまま読み込まれるので不整合が発生する可能性がある.

現行版はMAXPARENTS=32でビルドされている.8に落とした版を作ってみよう.⇒「不完全データファイル」に関して少し勘違いしていた.下のパネルはファイルを読み込んだときに表示される.

image

従って,ここで保存してもう一度読み直してもエラーは発生しない.ただし,サポート範囲外のデータは破棄されている.実際,noduleの父母ページ数は8に変化している.これをZTシステム構成図 MAX=8.ZELとして保存して読み直せばエラーは発生しない.つまり,読み込んだときにはすでに補修されているので,保存時に整合性検査を行う必要はない.もちろん,これをたとえばMAX=4の版で読めば同じことが繰り返されるが,動作的にはこれで十分だ.言い換えれば,保存時に「不完全データファイル」として保存されることは起こり得ないと言える.

「可変長配列」が使えればこのような問題も一掃されてしまうのだが,宿題としておこう.NODULEの派生クラスにはARRAYという任意サイズの配列を持つクラスもあるが,この配列はnodule*の配列で一般のデータ型を扱うものではない.気になる点はまだ残っているような気がするが,MAXPARENTSを32に変更してデータ入力に戻るとしよう.

構成図5.zelを開いて,部分図「GENEBOX」に切り替えて,多重カードを検出.「不可避の多重」はゼロなのでこれは明らかな障害だ.⇒※解決

系列枠背景色が基準カード色と連動してしまう.かなりおかしい.系列枠背景色はBGColorTribeBox,基準ノード背景色はBGColorBaseNodeでCOUPLINGの系図画面カラー設定ではそれぞれColorTribeBoxとColorBaseNodeとい変数名で使われている.どうもVB側で誤っているのではないかという気がする.いや,これは仕様かもしれない.TRIBEBOX::Drawに以下の行がある.

if (primetype == PRIME_START) BGColor = metrix->col->BGColorBaseNode;

つまり,始系列を他の系列から区別するために背景色を基準ノード色で塗りつぶしている.しかし,始系列というのは1個しかないはずだから明らかにこの動作はどこかで間違っている.

部分図で閉じたときは再読み込みしたとき部分図が開くはずなのにそのような動作になっていない.⇒いや,保存しないで終了しているのだから当然だ.⇒※単なる勘違い.

image

GENELISTは系列GENELISTの優先ノードで先祖ノードでもあるように思われるが,原図ではbaselistとともにcoupling系列の一部となっている.部分図にはbaselistとGENELISTしか含まれていないのだから,baselistの単身先祖配偶者とならなくてはならないはずのところ,あくまで独立の存在を主張している.TRIBELIST::MakeUpTreeには,「単身先祖配偶者→系列を廃棄」という手順が組まれているから本来ならここで系列は破棄されていなくてはならないところなのだが…「始系列は削除されない」というルールから除外されている.場合によっては始系列でも削除される場合があるということだろうか?⇒先行系列と完全に縁が切れていれば始系列となり得るが,GENELISTの場合は先行系列とつながりがあるので,このノードがPRIME_STARTという属性を持っていること自体誤りと考えられる.

初期状態ではすべての系列はPRIME_START属性を付与される.どうも錯綜として状況を掴みきれないので,primetypeをprivateに設定してアクセス関数を使うことにしよう.関数の引数でprimetypeの参照を渡して直接書き込んでいるところがある.SearchLaterFosterChild,SearchLaterPrimeNodeの2つだ.ここで使われているprimetypeはTribeDecompositionのローカル変数だ.まぎらわしいのでPRIMETYPEとしておく.TribeDecompositionの中で一度もsetprimetypeが実行されていないように思われる.これはかなり奇妙だ.⇒いや,実行されている.GENELISTの系列は2回設定が回ってくるが毎回PRIME_STARTで呼び出されている.初回はMakeTribeBoxで系列枠オブジェクトを生成するために初期化しているだけだ.

「有効結婚リンク判定の重複処理削減@20201031」を復活させると動作に少し変化が現れたが,描画はできない(白紙になってしまう).現行版では先祖リストには2個のエントリがあるが,重複処理削減版では先祖は1人しかいない.また,validcard=2, validmarg=1となっている.これが正常だ.現行版ではこれが,validcard=2, validmarg=88になっている.これでは解けるはずがない!いや,そもそもCountValidMargが呼び出されていない!⇒TribeDecompositionはFilteringKinshipの中で実行されている.⇒修正に誤りがあった.これで有効なカードリンクと結婚リンクの数は正しい値にセットされたが,まだ描画できる状態になっていない.

あちこちでcheckブロックに不備があり,例外が発生していたためと考えられる.ロジックを整理して通るようになった.

image

この部分図はGENEBOXというタイトルが付いているが,baselistとGENELISTしか登録されていない.おそらくGENEBOXのクラス構成を見ようとしていると思われるので,GENEBOXの直系血族図を取ってみた.これはかなりよい説明図になっているのではないだろうか?

image

GENEBOXから名前でアクセスできるメンバー変数は出揃っているし,それに関係するクラスもすべて表記されている.クラスの継承関係も明瞭だ.この図でGENEBOXが先祖ということは,GENEBOXを基本クラスとする派生クラスが存在しないことを意味する.Bobjectの直系血族図を見てみよう.これもわかり易い図だ.

image

Bobjectの上にはBobjectの派生クラスが6つ並んでいる.

imagePAIRBOXの出方はかなり違う.構成木のルートのcouplingまで繋がっている.なぜだろう?また,PAIRBOXはBobjectの派生クラスであるのにそれが展開されていない.原因は分かった.PAIRBOXという名前で2つの要素が登録されている.男性型と女性型だ.この図は男性型つまり,実装としてのPAIRBOXだ.女性型を選べば上のGENEBOXなどと類似のパターンになる.PAIRBOXではなく小文字でpairboxとしておけばよかったのかもしれないが,pairboxという実装名はおそらく使われていないのではないかと思う.

PAIRBOXはPAIRLISTのリスト要素として使われているが,PAIRLISTはNLIST < LISTNODE, CID>の派生クラスで引数のLISTNODEでPAIRBOXをクラス名として指定しているが,内部要素であるPAIRBOXのインスタンスには名前は付いてない.まぁ,これはこれでよいだろう.

全体図で見ると蜘蛛の巣を張ったように見えるが,個別にソートするとそれなりの図が出てくるところを見ると,この図面の制作意図はかなり的中しているように思われる.多分まだあちこち欠陥はあると思われるが,大雑把に見てかなりいい線をいっていると思われるので今回はこの辺りで一旦手仕舞いすることにしておこう.

設定を親族図:直系血族図にしておいて,検索パネルで検索→系統並び替えを繰り返し実行することでいろいろなクラスやクラスのインスタンスの構成図を見ることができる.直系血族図だけでなく,Z木家系図というのもおもしろい.この図では直系血族の配偶者まで出てくるのでもう少し詳しい情報が得られる.たとえば,上記PAIRBOX(実装)のZ木家系図はこんな感じだ.

image

親族図から全体図に移ろうとしてTOPOLOGY::topologicalSortで (treeview->validmarg != validmargnum) というエラーが出た.treeview->validmargが10でTOPOLOGY::validmargnumが…ということは同期が取れていないということになる.なぜだろう?HideNameboxの呼び出しが (CHARTTYPE) ※のときしか掛かってこないためだ.⇒このエラーは解消したが,まだ何かある.

※(CHARTTYPE)は(CHARTTYPE != DISP_ALLCARD)の意⇒修正した

PAIRBOX(♂)の直系血族図から全体図に切り替えて,CARDLINK:DownStreamで (mywife && mywife->Invalidated && CHARTTYPE == DISP_ALLCARD)になった.mywifeはPAIRBOX(♀)だ.全体図では隠蔽されているカードはないはずだから,HideNameboxの動作に何か問題があることになる.⇒TOPOLOGY::HideNameboxではカードテーブルで処理するのではなく,cardQという待ち行列を使って有効無効の判定をしている.このQは親族範囲の検定に使われている.全体図のときはこの処理をやっていないため不足が発生するのだろう.いや,FilteringKinshipもHideNameboxも実行されているように見える.

修正ミスがあった.全体図のときHideNameboxが呼び出されてた.TOPOLOGY::ClearTableではすべてのカードと結婚リンクを有効に初期化している.しかし,全体図の場合にも「親族範囲の検定」は必要になる.つまり,親族範囲とカードの有効無効は必ずしも一致しない.このため全体図の場合はHideNameboxを実行しないというのが正しい.

現在システム構成図には36個のクラスと153個のオブジェクトが登録されている.この資料をクラスの直系血族図をすべて部分図として登録しようとすると,部分図のMAXをオーバーしてしまう.部分図MAXは32個しかないからだ.これは部分図が互いに排他的ではない(複数の部分図に重複登録できる)ために集合論的に扱う必要があるからだ.

ゼルコバの木のクラスにはアルファベットの一文字を割り当てているので記号を入れても128というのが最大登録数ということになるが,CID(クラス識別子)は排他的なので短整数で間に合う.現在のマシンの長整数は64ビットだから,部分図を128個まで扱えるようにするにはCARDBASE::partialbitsをULONGに延長すればよい.

全体図は込み入り過ぎて通常は開くこともないが,もっぱら部分図ないし親族図で調べものをするという使い方はゼルコバの木の適切な用法であるような気がする.名前さえ分かれば親族図でソートするという方法があるので,いまのところは部分図MAX32でもしばらくはしのげるだろう.大きなデータベースが使えるようになると通常は標準家系図や法定親族図のようなものがもっぱら使われるようになるのではないか?

コメントを残す

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

CAPTCHA