NOCOMMONPAIRノード対は端点共有束で唯一でなくてはならない

源氏物語全系譜6.1.ZELの直系血族図 #114 先帝でPAIRBOX:SwapBundledPairのエラー,「NOCOMMONPAIRノード対は端点共有束で唯一でなくてはならない」というルールの違反が起きている.PAIRBOX:#23978:#20650 冷泉院(2)→#20622(1)とPAIRBOX:#26892:#26825 冷泉院(3)→#20622(1)が競合している.どちらもNOCOMMONPAIRで端点共有の中では両存できないことになっている.ノード対の仮ノードが前者は実親子関係,後者は養親子関係であるという点からも共存できないとされるのだが…

PAIRBOX:MoveSamePointではCheckCommonEndPointで端点共有を見つけているのだが,おそらくルールが甘いのだろう.CheckCommonEndPointではsearchCommonPairで候補を見つけた後,共有種別不一致と始点共有の親子関係のチェックを実施している.⇒判定が悪いのではなく,ロジックが悪い.端点共有候補がリジェクトされた場合もリセットされないため,ループから出るときその値が残ってしまっている.⇒修正した.

image

CheckCommonEndPointのロジックをsearchCommonPairに移植した.この論理はCheckCommonEndPointの追加条件ではなく,searchCommonPair自身が判定できなくてはならない.親子関係による実子太線,養子細線の別は,細線の方が長ければ判別できるので,その条件も加味してより詳細化した.これでノード対の端点共有論理は完全にsearchCommonPair一本に統括できたのではないかと思う.

同上サンプルの全体図:#1 光源氏でPAIRBOX:#60400:#23602 蛍兵部卿宮の前の北の方(1)→#13153(0)の端点共有が解決できない.⇒searchCommonPairでは共有種別を返していない.⇒対処した.

同上サンプルの傍系血族図:#42 朱雀院でMakePairListClean中,PAIRBOX:MoveChannelToで停止した.この関数は対象ノード対が直列リスト上にあることを仮定しているが,端点共有ノード対が引っかかった.⇒障害ノードはPAIRBOX #38053:#21312 雲井の雁(1)→ #12405(0)で,PAIRBOX:#38039:#21295 玉鬘(1)→ #10977(0)に繋がっている.CheckPairEndPoint→ CheckInverseCycle→ PAIRBOX::RepairVerticalInverseで起きている.

この関数では「始点終点が同一座標で逆転」が起きたときの処理を実施している.「逆転循環検定」は端点共有とまったく関わりがないと考えられるので,MoveChannelToに変わるノード対単体の移動ができる関数を用意する必要がある.MoveChannelToの中で使っているTakeoutを小文字のtakeoutに変えればよいと思われるので,引数で判別できるようにしてみよう.⇒対処した.

同上サンプルの傍系血族図 基準ノード=#57 女三宮でPAIRBOX:RepairCommonEndPointの出口検査で停止した.PAIRBOX #39234:#21555 蛍兵部卿宮の前の北の方(1)→#13153(0) の「共有端点不一致」が解決していない.CheckSamePointの判定のロジックが悪いのではないか?現行では対象ノードが端点共有代表ノード対の場合に限って検査しているが,その逆ではないか?つまり,代表ノード対を基準にして他のメンバーが間違っているかいないかを決めるべきではないのか?⇒書き直してみよう.⇒うまくいったようだ.

同上サンプルの傍系親族図 基準ノード=#135 致仕太政大臣の北の方でNAMEBOX::IsPossibleBTWLeftHandのエラーで停止した (rightwife->IsLeftHandBox())というエラーが起きている.BTW(Between Two Women)の右手結婚枠配偶者が左手結婚枠本人というエラーだ.エラーを無視して描画は可能.障害ノードはNAMEBOX #21314 冷泉院(1).冷泉院は結婚を7つ持っている.子どもは3人で弘徽殿女御との子ども女一宮と冷泉院の御息所との子ども女二宮,若宮だけだ.この図面は致仕太政大臣の傍系親族図なので,表示されているのは冷泉院+弘徽殿女御→女一宮だけのようだ.⇒いや,違う.

image

表示されている結婚枠は3つ,弘徽殿女御,冷泉院の御息所,秋好中宮の3箇所だ.冷泉院の仮ノード(人名枠)は5つ出ているが,うち,可視ノードは弘徽殿女御のところに出ている(0)と上図右端の光源氏の下の2つだけだ.桐壷院の下の養子ノードは消去された仮ノードになっていて,残り2つがBTWに関係している.⇒この図面は他にもいろいろ問題があるが,保留して先に進もう.ここでは「右手配偶者が左手本人で停止しない@20210108」としておく.

▲HOMEキーが利かなくなっている.

同上サンプルの法定親族図:#110 弘徽殿大后を開いてNAMEBOX:makePairBoxで停止した.ノード対冷泉院(3)→#101539147(1)で「共有端点不一致」が発生している.makePairBoxは新規ノード対を生成する関数だが,この時点で端点共有可能であれば端点共有を実施している.makePairBoxが呼び出される前にこの端点共有は指定されていて,それを決定しているのはAvailableChannelだ.

この関数は内部でSearchSamePointPairを呼び出している.SearchSamePointPairはNAMEBOX::IsBindablePair→ getCommonPairで判定している.NAMEBOX::IsBindablePairは複数箇所から呼び出されている.判定基準をすべての箇所で統一する必要がある.Bobject:getCommonPairTypeという関数を作ってNAMEBOX::IsBindablePairから呼び出すようにした.この論理はPAIRLIST::searchCommonPairから切り出してきたものだ.

しかし,これだけではエラーは止まらない.今度はノード対生成後に,端点共有エラーが発生するようになった.元々あったノード対の連結線の方向が逆向きに変化している.これは仮ノード消去によってトポロジーにドラスティックな変化が生じたためと考えられる.⇒この変化はNAMEBOX::EraseGhostNodeの中でEraseGhostを実行することによって生じているので,端点共有サーチを実施する前にEraseGhostを実行するように書き換えた.⇒これで一応解決したが,searchCommonPairもこの関数を使うように書き換える必要がある.

傍系血族図 基準ノード=#75 葵の上でソートしてPAIRBOX:SwapBundledPairで「NOCOMMONPAIRノード対は端点共有束で唯一でなくてはならない」というエラーで停止した.⇒このエラーはNAMEBOX::makePairBoxで発生している.実際には複数のNOCOMMONPAIRが発生していた訳ではないが,その点を修正しても「最大区間でないnocommonを別チャンネルに移動」が発生する.これは,端点共有を探すときにはまだ,ノード対実ノードのNOCOMMONENDPT属性がセットされていないためだ.これを避けるためにgetCommonPairTypeに渡す引数でNoCommonGoodSonをチェックするようにした.

傍系親族図 基準ノード=#133 麗景殿女御(朱雀院の)でソートしてPAIRBOX::CheckSamePointで停止した.対象ノードが直列リスト上にないというエラーだ.障害ノードはPAIRBOX:#36478:#21473 冷泉院(3)→#21310(1)で右始点共有となってはいるが,所属しているノード対はこれだけだ.これは結局,samepointが間違った値を持っているということを意味する.この不良は「非共有対でsamepoint」としてCheckPairBoxで検出されているが,CheckSamePointに伝達されていない.このようなパラメータ不良が発生したときは,CheckSamePointを呼び出さずにCheckPairBoxでエラー復帰するようにした.

takeoutでノード対を削除して端点共有が解消した場合には,samepointをリセットしておくべきだ.⇒一応そのような論理は整備されているのだが… 何か穴があるのだろうか?⇒ノード対の移動関数には,takeout, Takeoutの他,MoveChannelTo,MoveSamePointがある.PAIRLIST::dataCountDownにも所要の修正を入れた.⇒いや,ここに入れても効果ないのではないだろうか?dataCountDownは事前処理であり,この時点では接続関係に変化はないはずだ.

源氏物語全系譜6.1.ZELの完全木テストが通った!

image

所要時間を以前のレコードと比較したいのだが… 2020/03/12に「源氏4の完全木テストとパックマン全点をPCで並行して走らせておいたのだが,完全木テストの方は5726面:12時間12分21秒で完了していた.」というのがあった.2020年3月なら多分開発環境はいまと同じではないかと思うのだが… 5726面で12時間も掛かっている.今回の検定図面数は2862面で約半分だが,30分そこそこで完了している.体感的には「昔より遅くなった」ような気がしていたのだが… 1台のマシンで2つのテストを並列実行するというのは少し負荷が大き過ぎるような気もするが,それを差し引いてもかなり大きな落差がある.

いや,違う.上の引用は2012/03/12投稿の記事だ.確かにこの頃ならそんなものだったかもしれない.CPUも速くなっているし,この頃はおそらくまたリサイクルシステムも導入されていなかったはずだ.確かに,源氏の完全木テストが30分くらいで終わるというのはこれまで見たことがないような気がする.もう少し整理したらリリース版を起こしてみることにしよう.リリース版は多分これよりずっと速いと思う.

端点共有ノード対が削除されて共有ノード対が単体に戻ったときにsamepointをリセットするために,PAIRLIST::deleteElementを新設した.これで上記傍系親族図 #133 麗景殿女御で出ていた問題は完全にクリアできた.Bobject::getCommonPairTypeという関数を作ってあるので,PAIRLIST::searchCommonPairでこの関数を使うようにする必要がある.⇒対処した.これで端点共有に関する修正は基本的に閉じたのではないかと思う.リリース版を起こしてみよう.

RepairCommonEndPoint「右端点共有で種別不一致」

源氏物語全系譜6.1.ZELの全体図を#12 桐壷の更衣の母でソートして,PAIRBOX::MoveChannelTo→ PAIRLIST::Takeoutで停止した.この関数では対象ノード対が直列リスト上にあることを仮定している.⇒「共有端点不一致」で「端点共有解除」していなかった.

バックアップも取ったので,ここで修正をフィックスしておこう.

  1. CheckSamePointの戻り値仕様変更@20210106 3箇所
  2. CheckSamePointとCheckPairBoxを統一@20210106 4箇所
  3. CalcPairBoxからSwapBundledPairを切り出す@20210107 4箇所

同上サンプルを#97 若君(紅梅の)でソートして,NAMEBOX:makePairBox→ CheckPairBoxで停止した.「最大区間ノード対の逆転」が起きている.ここでは新規ノード対を生成して端点共有束の末尾に直接接続している.PAIRBOX::SwapBundledPairを実行して最大区間ノード対を差し替えるようにした.

同上サンプルを#106 六条御息所でソートして,TOPOLOGY:CheckPairEndPointでループカウントオーバーが発生した.PAIRBOX #59496:#22720 玉鬘(1)→#10977(0)とPAIRBOX #59510:#22766 雲井の雁(1)→#12405(0)が関係する端点共有だ.玉鬘のノード対が「危険対」になっていて,共有解除と共有設定が反復されている.⇒searchCommonPairでCRITICALPAIRを弾くようにした.

同上サンプルを#110 弘徽殿大后でソートして,COUPLING:TopologicalSort→ TREEVIEW::EraseTreeViewを実行中,PAIRLISTのcancelでデータ数不一致が発生した.detacount=0でデータが残留している.弘徽殿大后の前は,#109 二条太政大臣だ.この事象は#109 二条太政大臣で開いて→終了でも再現できる.この障害はTribeRelocationの出口ではすでに発生している.

障害が起きているのはPAIRLIST #29168だ.MoveSamePointの実行によって生じている.MoveSamePointでは移転元リストと移転先リストが異なるときだけカウントアップする論理になっていた.しかし,これは誤っている.移転元ではつねにカウントダウンしているので,移転元と移転先が同じ場合でもカウントアップは必要だ.

同上サンプルを#123 左大臣の女御でソートして,PAIRBOX:RepairCommonEndPointの出口検査で停止した.「右端点共有で種別不一致」というのが起きている.障害ノードはPAIRBOX #60318:#23480 蛍兵部卿宮の前の北の方(1)→#13153(0)とPAIRBOX #60343:#23492 致仕太政大臣の北の方(1)→#13170(0)だ.samepointにはCOMMON_LEFTEND 左終点共有が入っている.しかし,その前には「左端点共有で種別不一致|端点共有で始点不一致」というのも起きている.確かに,この時点ではそうなっているようだ.

この事例はいろいろと問題がある.共有解除する前の状態は蛍兵部卿宮の前の北の方と致仕太政大臣の北の方の他にPAIRBOX:#57882:#22568 冷泉院(4)→#11028(0)も加わっている.おそらく,この三者は最初から三つ巴の状態になっていたのではないかと思われる.

従来論理では端点共有の接続種別の判定をNAMEBOX::IsBindablePairで実施しているが,この関数の解釈は間違っている.現行のsearchCommonPairの解釈と合わせる必要がある.PAIRBOX:getCommonPairという関数を作って論理の共通化を図った.これで完全に問題は解決した.致仕太政大臣の北の方と蛍兵部卿宮の前の北の方はどういうフローになっているのか分からないが,最終的には端点共有で収まっている.ただし,蛍兵部卿宮の前の北の方と朧月夜はなぜか共有にならない.これは別途調べる必要がある.

▲同上サンプルの直系血族図 基準ノード=#114 先帝でPAIRBOX:SwapBundledPairのエラー,「NOCOMMONPAIRノード対は端点共有束で唯一でなくてはならない」というルールの違反が起きている.

image

藤壷の宮から冷泉院に連結線が2本入っている.1本は桐壷院+藤壷の宮,もう1本は光源氏+藤壷の宮だ.冷泉院は光の実子で桐壷院とは事実上義理の関係にあるため,2本の連結線の太さで書き分けている.もし,これがどちらも養親子関係であったとすれば,長さが同じでNOCOMMONのノード対が2つ存在することになる.

この意味で「NOCOMMONPAIRノード対は端点共有束で唯一」というルールは必ずしも絶対とは言えないのだが,今の場合は,「始点共有で実親子関係⇔養親子関係が一致しない場合は共有不成立 実親子と養親子では連結線の太さが違うなど不具合が発生するため」というルールが適用されなくてはならないところなのだが…

CheckSamePointの戻値の仕様を変更する

「端点共有束全体を移動する@20210105」オプションをフィックスしてから進むことにしよう.7箇所ある.仮修正が19箇所.

源氏物語全系譜6.1.ZELの全体図を#3 桐壷の更衣でソートしてPAIRBOX::RepairCommonEndPointの出口でCheckSamePointエラーが出る.「端点共有で始点不一致」が起きている.障害はPAIRBOX:#234599:#199072 明石の尼君(1)→#188661(0)とPAIRBOX:#234457:#198879 先帝の后宮(1)→#188559(0)で起きている.両者の区間は前者が(-207, -117),後者が(4066, 3989)のようにかけ離れているので,最初の判定が間違っていたか,ないし関係するノードのいずれかが大きく移動しているものと思われる.

このエラーはTOPOLOGY::CheckPairEndPoint→ PAIRBOX:RepairCommonEndPointで起きている.RepairCommonEndPointの目的は「対象ノード対の端点共有状態を検査し再構成する」なので,それに失敗していると考えるしかない.RepairPairBoxで修復を試みているが,変化していない模様だ.

CheckSamePointの従来の仕様では,エラーがあるかないかを示すだけのブール値を返していたが,仕様を変更して障害の詳細な要因を返すようにした.これらのビット定数はコード内から日本語でアクセスすることができる.障害をダンプするときにも,数値だけでなく名前まで表示できるようにした.

  1. 無効なノード対 disable状態のノード対
  2. 長さゼロのノード対 長さゼロのノード対は無視する
  3. ノーマルなノード対 ノーマルなノード対(端点共有束を含む)
  4. 実仮ノード不在 ノードないし仮ノードが取得できない → 不良
  5. ノード対不一致  仮ノードの参照するノード対と現物が一致しない → 不良
  6. カードリンク不一致 仮ノードと実ノードで参照する人名リンクが一致しない → 不良
  7. NOCOMMON属性不整合 実ノードとノード対でNOCOMMON属性が整合しない → 不良
  8. 直列リスト上にない非共有対 非端点共有ノード対でBundledTopが間違った値を返している → 不良
  9. 非共有対でsamepoint 直列リスト上の非端点共有ノード対がsamepointの値を持っている → 不良
  10. 最大区間ノード対の逆転 端点共有リストの先頭ノード対が最大区間ノード対でない → 順位入れ替え
  11. 危険対を端点共有 始点終点が同一座標で逆転するノード対を端点共有 → 端点共有解除
  12. NOCOMMONGOODSON NOCOMMONGOODSONで端点共有代表でない → 端点共有解除
  13. NOCOMMONで非共有代表 実ノードがgoodsonであるノード対は最大区間でなくては共有不可 → 端点共有解除
  14. samepoint不良 端点共有ノード対のsamepointが代表ノード対と一致しないかゼロ → 端点共有解除
  15. 共有端点不一致 端点共有ノード対で座標不一致 → 端点共有解除
  16. 左端点共有で種別不一致 左端点共有でsamepointが一致しない → 端点共有解除
  17. 右端点共有で種別不一致 右端点共有でsamepointが一致しない → 端点共有解除
  18. 端点共有で始点不一致 始点共有で始点が一致していない → 端点共有解除
  19. 端点共有で終点不一致 終点共有で終点が一致していない → 端点共有解除
  20. 端点一致でsamepointゼロ 端点共有可能なノード対のsamepointがゼロ → 端点共有
  21. 端点共有でsamepointゼロ 端点共有束上のノード対でsamepointがゼロ → 端点共有
  22. 直列リストノード対の衝突 直列リスト(同一チャンネル)上のノード対区間で交叉している → チャンネル移動(連結)
  23. 端点共有解除 シンメトリ婚/危険対の端点共有を解除する → チャンネル移動(単体)

CheckSamePointで「端点一致でsamepointゼロ」というエラー

源氏物語全系譜6.1.ZELの全体図を#127 摂政太政大臣でソートしてPAIRBOX:repairCommonEndPointの出口でGENELIST:CheckPairBoxの不良ノード対エラーにより停止.CheckSamePointで「端点一致でsamepointゼロ」というエラーが起きている.問題のノード対はPAIRBOX:#49223:#23382 蛍兵部卿宮の前の北の方(1)→#13126 蛍兵部卿宮の前の北の方(0).

PAIRBOX:#49223:#23382 蛍兵部卿宮の前の北の方(1)→#13126(0)と#49237:#23394 致仕太政大臣の北の方(1)→#13143(0)が端点共有と認定されているが,CheckCommonEndPointでは端点共有なしを返している.つまり,CheckCommonEndPointとCheckSamePointの基準が異なる.⇒CheckSamePointのロジックから,PAIRLIST::searchCommonPairという関数を作り,CheckCommonEndPointから呼び出すようにした.

系統並び替えの出口検査でCheckPairListのエラーが検出される.サンプルは源氏物語全系譜6.1.ZELの全体図 #1 光源氏.CheckPairBoxCollisionで障害が発生している.ノード対の衝突が5件発生している.この障害はHeapTribeBoxesを実行することで発生している.たとえば,PAIRBOX:#55361:#23947 八宮の北の方の母(1)→#14452(0)とPAIRBOX:#55518:#24194 受領(1)→#15438(0)が衝突している.

これは当然あり得ない.受領はまるきり離れた別系統のノードだ.これは,HeapTribeBoxesの中で独立系列をMoveRectRightで前詰めしているために起きている.ノード対管理は全域的に実施されているため,別系統のノード対とも数字的には衝突が起きる可能性はある.区間計算で用いている数字は,あらかじめ計算されてノード対の矩形領域に格納されているものが使われているためだ.

HeapTribeBoxesの実行後に再計算するか,ないし直接値を計算するしかない.衝突はPAIRLIST::VerifyPairBox→ CheckNormalizedSectionで検出されているので,この関数では値を直接計算するようにしておこう.⇒だいぶ正確に動作するようになってきたようだ.

同上サンプルを#2 桐壷院でソートして,CheckCommonEndPointで停止した.PAIRLIST::searchCommonPairとCheckCommonEndPointの判定が相反している.⇒searchCommonPairでは計算誤差を見ているのに対し,CheckCommonEndPointでは厳密値を適用しているためだ.⇒対処した.これでエラーは解消したが,別のエラーが発生している.

同上サンプルを開いて,PAIRBOX::MoveSamePointで停止する.この関数は対象ノード,移動先ノードともに直列リスト上のノードと仮定している.⇒searchCommonPairで端点共有の中まで探していた.

同上サンプルを#12 桐壷の更衣の母でソートして,TRIBELIST:MakePairListCleanでループカウントオーバーになった.PAIRBOX:#53758:#23537 致仕太政大臣の北の方(1)→#13143(0)の補修を反復しているようだ.衝突の相手方は毎回変化している.どうも補修が循環してしまっているように思われる.⇒#156006 ノード対:四宮(桐壷院の)(1)→(0)が割り込んで,致仕太政大臣の北の方を共有端点から追い出しているようだ.判定ではAfordableChannelが使われている.⇒checkNormalizedSectionで正規化していない区間を使っていた.

同上サンプルの#13 春宮でTOPOLOGY::CheckPairListのループカウントオーバーが起きた.PAIRBOX::CalcPairBoxで最大区間ノード対の逆転を解決が反復されている.PAIRBOX:#54628:#23016 致仕太政大臣の北の方(1)→#13143(0)とPAIRBOX:#54614:#23004 蛍兵部卿宮の前の北の方(1)→#13126(0)の入れ替えが実施されている.蛍兵部卿宮の前の北の方は同じチャンネルの葵の上のノード対と衝突して一旦チャンネルを追い出され,その後もう一度端点共有でこのチャンネルに戻るという動作を繰り返している.

端点共有ノード対とそうでないノード対の衝突では非共有ノード対側で処理するようにしてエラーは一応解消したが,端点共有同士の衝突という可能性もあり,むしろ,端点共有ノード対を移動する場合は端点共有束全体を移動するようにすべきだろう.チャンネル移動はPAIRBOX::MoveChannelToで実施している.

あらたまの年も新たに去年の月

image

今年はいよいよどっからもカレンダーが来ない… まぁ,いっか.コロナ時代だ!一旦ここまでの修正をフィックスしてから作業に掛かることにしよう.仕掛りのオプションには以下がある.

  1. DecidePrimaryNodeを書き換え@20201226 1箇所
  2. mergeUpperSegmentで移動禁止@20201227 1箇所
  3. 最大区間ノード対を端点共有の先頭に置く@20210101 25箇所

源氏物語全系譜6.1.ZELの全体図を#18 左兵衛督で開いて,PAIRBOX::CheckPairBoxで不良ノード対エラーで停止.「最大区間ノード対の逆転」が起きている.PAIRBOX:#84668:#23457 弘徽殿大后(1)→#12718 (0) と#50680:#23481 致仕太政大臣の北の方(1)→#13143(0)だ.NAMEBOX::makePairBoxではノード対を生成するだけで,端点共有の調整までは実施していない.ただし,端点共有はチェックされていて,端点共有束には追加されている.PAIRBOX:CalcPairBoxではNOCOMMONの場合には調整しているが,すべての場合をカバーしていない.ここで調整しておくべきだろう.

源氏物語全系譜6.1.ZELの傍系血族図を#5 紫の上(若紫)でソートしてLIST::nextで(PHASE > INITIALSTATE)という理由で停止した.系統並び替えでTribeRelocation→MakePairListCleanを実行しているところだ.PAIRLIST::SearchSamePointPairの中で起きている.この関数は「端点を共有するノード対を探す」ためのものだが,探しているノード対リストに属していないノード対をピックアップしてきたように思われる.IsBindablePairの中で書き換わっているのではないだろうか?

IsBindablePairの中でPAIRBOX::CalcPairBoxが実行され,「最大区間ノード対の逆転を解決」によってリストが再編されている.このため,直列リスト上にあったPAIRBOX:#35362:#21617 雲井の雁(1)→#12378(0)が端点共有リストの下位に移ってしまっている.IsBindablePairの中でPAIRBOX::CalcPairBoxが実行されること自体問題だが,最大区間先頭の調整が遅れていることも問題だ.いや,この動作はPAIRLIST::RepairPairBoxGenerationの中で起きているので,状態がある程度流動的になるのは避けられないのではないか?

IsBindablePairの中でCalcPairBoxを実行しないことでこのエラーは解消したが,雲井の雁と玉鬘の端点共有が崩れてしまっている.なぜか?⇒明石中宮と雲井の雁が同一チャンネルに入ったため,玉鬘が加わる余地がなくなったためと考えられる.(最終出力では明石中宮と雲井の雁は同一チャンネルにはなっていない… )最適解を求めるとすれば,玉鬘と雲井の雁の端点共有を成立させた上で,明石中宮は別チャンネルに移るというのが正解と思われるが,そこまでの動作にはなっていない.これで見ると,最優先すべき条件は端点共有であるということが分かる.

▲源氏物語全系譜6.1.ZELの全体図を#127 摂政太政大臣でソートしてPAIRBOX:repairCommonEndPointの出口でGENELIST:CheckPairBoxの不良ノード対エラーにより停止.CheckSamePointで「端点一致でsamepointゼロ」というエラーが起きている.問題のノード対はPAIRBOX:#49223:#23382 蛍兵部卿宮の前の北の方(1)→#13126 蛍兵部卿宮の前の北の方(0).

ノード対の「端点共有で始点不一致」エラー

多重カードを削減する基本的な方法は二つのカードを連結線で接続して片方のカードを削除することだ.このような連結線のうち,親から出て子どもに入るように見える親子連結線の水平部分をノード対と呼んでいる.これはノード対の両端に同一人名のカード(一方は可視,他方は不可視)が接続していることによる.ノード対の処理はZTシステムのコンポーネントの中でももっとも基本的なパートとなっている.

これらの水平連結線を交叉しない範囲でできるだけ簡潔に描画するというのはかなり難しい課題で,達成目標はベストエフォート(できる限り)ということになっているのだが,どうもあまりできがよくないので見直す必要が出てきた.おおまかな方針を決定し,すでに実装も進んでいるので,バグを潰しながら整理してゆくことにする.

NAMEBOX::makePairBoxでCheckSamePointの「端点共有で始点不一致」エラー.障害ノード対は#1226:#1099 雲井の雁(1)→#587 雲井の雁(0)と#1225:#1098 玉鬘(1)→#419 玉鬘(0)だ.⇒解決済

源氏物語全系譜6.1.ZELの傍系血族図の基準ノードを#13 春宮から#1光源氏に変えて,系統並び替えの冒頭でノード対リストのcancelを実行中,PAIRBOXの削除で参照カウントが負になった.⇒系統並び替えしなくても,アプリ終了だけで再現できる.⇒完全参照リスト管理をオンにしてテストしてみよう.⇒nodule::CheckSansyoで被参照カウント不一致が多発している.#34442 ノード対:蛍兵部卿宮の前の北の方(1)→(0)で参照元ノードリスト不記載,#34134 ノード対:玉鬘(1)→(0)でも同じエラーが発生している.これらは起動時にすでに発生している.LIST::bottomlistへの書き込みだ.PAIRLIST:swapで直接書き込んでいるためだろう.Bottomlist関数を使うようにした.

同上サンプルの全体図:#5 紫の上(若紫)でソートしてMakePairListCleanでループカウントオーバーになった.「最大区間ノード対の逆転」がPAIRBOX:#1492439:#1462069 致仕太政大臣の北の方(1)→#2449 (0)で起きている.親族図:傍系血族図 基準ノード=#5 紫の上(若紫)を開くと,NAMEBOX::makePairBoxでCheckPairBoxのエラーで停止する.⇒エラーを無視して描画は可能.全体図は問題なく開けた.紫の上の全体図を開いて,基準ノードを変えずに反復ソートしたら,3回目でMakePairListCleanの障害が出た.これは初期化が不完全ということを意味している.かなりまずい.

まず,先に最大区間ノード対の逆転がなぜ止まらないのかを見ておこう.PAIRBOX 蛍兵部卿宮の前の北の方(1)→(0)と競合しているが,これを端点共有と認定しているところが誤りだ.(3434, 3293)と(3434, 3293)で向きが逆になっている.⇒PAIRLIST::takeoutで共有解除,PAIRBOX::RepairCommonEndPointとPAIRBOX::MoveSamePointで共有を設定している.CheckCommonEndPointが間違った値を返している.⇒比較対象の矩形領域を正規化していなかった.

これで問題は解決したが,系統並び替えを反復すると動作が変化するというのはとてもまずいので,シューティングしておかなくてはならない.正規化すれば正しく動作するのだから,正規化しなくても動いているというのは,「たまたま」動いていただけと解釈するしかない.しかし,何がどうなっているとそのような動作になるのかを解析するのは難しい.類似のバグがまだ潜んでいる可能性はある.複数のバグが競合して動いたり動かなかったりということもありそうだ.⇒系統並び替えの冒頭で描画要素を完全にクリーンアップすることでソートを反復しても動作には変化が見られないようになった.

その上でCheckCommonEndPointの修正(比較対象矩形領域の正規化)を行うと,連結線のもつれはほぼ完全に消えた.これまでは端点共有と通常ノード対の区間交叉がかなり見られたが,一見したところ見当たらなくなった.EraseTreeViewで行っている描画要素のクリーンアップは多少時間コストは掛かるが,これを実行しておけば間違いはない.

類似した関数にInitTreeViewというのがあり,修正履歴では「InitCoupling>InitTreeViewを廃止@20201208 余分な処理になっている → FIXED@20201209」となっているので,多分使わなくてよいのではないかと思う.この関数は,現在,①FAMILYTREE:callSendCard,②FAMILYTREE::getNewCardで使われている.

「InitTreeViewをCOUPLINGのコンストラクタに移動@20170731」というコメントもあるが,COUPLING()では「ここではTREEVIEWの初期化は実行しない@20170804」となっている.⇒タイトル枠を初期化しているのが気になるが,各種フラグのリセットなどをやっているので,実行しておいた方がよいと思う.

▲源氏物語全系譜6.1.ZELの全体図を#18 左兵衛督でソートしてNAMEBOX::makePairBox→ PAIRBOX::CheckPairBoxエラーが出た.

春宮の傍系血族図で端点共有の始点不一致

SUPPORTSIMPLEGRAPHオフのバージョンで,源氏物語全系譜6.1.ZELの傍系血族図を#13 春宮で開いて,repairCommonEndPointで停止した.CheckSamePointでエラーが出ている.「端点共有で始点不一致」が起きている.repairCommonEndPointではPAIRBOX:#1237:#1120 藤壷の宮(2)→(0)を端点共有リストに移動しているが,最初から対象を間違えている.⇒いや,違う.これは誤差の累積だ.

この端点共有束には藤壷の宮と承香殿女御が入っている.区間は(4299, 1364)と(4302, 1680)だ.この結果,端点共有束としての区間は(4302, 1680)となり,明石の上の(4305, 1496)も誤差の範囲で一致する.これを避けるための唯一の方法は,端点共有リストの先頭につねに最大区間のノード対を置くようにすることだろう.それにはどうしたらよいか?

問題は区間を比較するとき,端点共有の場合は「正規化区間」というのを使っている点にある.正規化区間というのは言ってみれば「最大区間」と同じだが,誤差を含んでいるため許容誤差を3として±3以上の誤差を許容してしまうことになる.これをまず,廃止する必要がある.

#90 雲井の雁の出口検査で水平スプリット

#90 雲井の雁で出口検査で水平スプリットを検出 TRIBEBOX #1082 :先祖 #843 ※218でスプリットが生じている

TRIBELIST::DetectHorizontalSplitではこのスプリットを検出できない.DetectSplitの対象となるのは,FreeTribeBoxと呼ばれる束縛されていない系列に限定されている.⇒これを暫定的に無差別に検査を実行するようにしても状態は変わらない.この仮修正の下で,「系列間衝突が発生で移動量ゼロ」という事象が起きているので見ておこう.

TRIBEBOX::DetectSplitでERR_CROSSINTRIBESを返しているが,MoveLeftUptoLimitは移動量ゼロを返している.障害が起きているのは,RIBEBOX: #1058 先祖=#427 一院(0)だ.T1=#1070 [系列枠]:先祖=大臣(橋姫)とT2=#1062 [系列枠]:先祖=先帝の衝突が検出されているのだが… TRIBEBOX::CheckConflictでは水平交叉量を返しているが,エラーコードを返す場合もある.また,この関数を呼び出しているTRIBEBOX::DetectSplitでは,「厳密値を適用する@20180729」という決定がなされている.

今の場合は交叉量は1なので許容誤差範囲と推定されるのだが… 2018年当時のログを読み直してみるとこの項目に直接言及した記述はないが,「checkBondedTribeCollision 束縛系列ないし下位系列を持たない系列を対象とする.対象系列枠の主系列およびその下流系列(つまり系列ブロック)と対象系列との衝突検定を実施する 下位系列を持たない場合は系列ブロック核のみを検査する 厳密値を適用する 」とある.

「衝突検定はすべて厳密値を適用するものとし,実動作が完了してから丸めるものとする」というコメントもあるので,この方針に従ったものだろう.ただし,TRIBEBOX::DetectSplitでは交叉量ではなく,エラーコードを返しているので丸めようがない.TRIBEBOX::DetectSplitで誤差を見るようにしておこう.⇒「系列間衝突が発生で移動量ゼロ」エラーは解消した.⇒おかしい.系列枠リストから※218系列が消えてしまっているように見える.第14位にいるはずなのだが…

いや,そもそも当初は96系列あったはずなのに,64系列になっている.32個もどこかに消えてしまっている.⇒MakeUpTreeの出口近く(系列グループ(系統)を構成するの段)ではすでにそのカウントだ.96の中には単身先祖系列で抹消されるものもあるから,カウントが減少するのは不思議ではないが… ※218が先祖となる系列は消えている.⇒※218は一院系列に取り込まれている.つまり,これは系列内スプリットだ.@58 大宮と@68桃園式部卿宮の間が開いている点が問題になる.

image

一院系列のTRIBEBOX::CheckGeneSplitでスプリットが検出されていない.⇒CheckGeneSplitとInvestigateHSplitsで微妙に動作が異なる点が問題だ.InvestigateHSplitsでは許容範囲としてmax(Metrix.nfontW, Metrix.marghgap)という値を使い,これを1ふかした定規で区間検査を行っている.いま,marghgapは12という値が適用されているので,delta=13となっている.上の図でイエローの帯の幅は13で,これはほぼ結婚枠間のギャップに等しい.

CheckGeneSplitでは結婚枠矩形領域を集積するとき,結婚枠間ギャップを加味した値を取っている上に,さらに計算誤差を回避するためとして+1しているため,大宮の入っているボックスと桃園式部卿の入っているボックスは接触していると認定されている.⇒InvestigateHSplitsの許容範囲を拡げてこの矛盾を回避することも可能だが,CheckGeneSplitの検査を厳格にして,1単位でも移動するように修正した.

基準ノード#121 明石の尼君で開いて,TRIBEBOX:DecidePrimaryNodeで系列優先実ノード不在が起きる.⇒障害が起きているのはTRIBEBOX: #1064 先祖=#635 先帝(0)[0] 優先=紫の上(若紫)だ.TRIBEBOX::DecidePrimaryNodeの書き換えがまだ完結していない.現行ではほとんどをGetAlternativePrimeNodeに委ねるという論理になっているが,やり過ぎだ.すでにGoDownStreamでほぼ確定している条件があるのだから,それを活かすようにしなくてはならない.

もっともシンプルな解決として,優先ノードの持つ仮ノードリストの中で自系列に属するノードがあれば,それを優先仮ノードとし,他系列で自系列の下位系列に属さないものがあれば,優先実ノードとするというロジックを組み込んだ.基本的にはこれでよいのではないかと思う.

#18 左兵衛督で「系列間衝突が発生で移動量ゼロ」が起きた.ERR_CROSSINTRIBESが起きている.交叉量は18あるので無視できる値ではない.衝突はTRIBEBOX: #1058 先祖=#661 摂政太政大臣(0)と#1064 先祖=#507 ※3(0)の間で起きている.どちらも一院系列の従系列だ.関数MoveLeftUptoLimitで,ERR_CROSSINTRIBES,ERR_SPLITINTRIBES,ERR_WRONGSENZOORDERのケースを処理している.検査対象は始系列の#1056 先祖=#791 右大臣(明石)(0)だ.これはかなりおかしい.⇒仮修正がそのまま残っていた.

源氏の全体図テストが通った!

image