短い軸線・伸びる軸線を描画する

STAGE6.ZELをNLIST LISTNODE@61でソートすると,SIMPLEGRAPH:GetLongestChainで無限ループが発生する.「反鎖リスト(同世代ノードリスト)を生成する」の段で,「重複パス上の(基準ノード以外の)任意のノードを削除する」の操作に失敗している.ループに入る直前のグラフをインポートすると下図のようにすでに最長鎖のみの状態になっている.

image

しかし,この図面はdumpgraphと内容が一致しない.ダンプでは節点数=6 枝数=8となっているのに,図面では11点も表示されている.

デスクトップ上のCSVを削除して作り直ししたら,開けなくなった.⇒CSVをインポートしたときも同じ動作になる.つまり,GetLongestChainで無限ループしている.CSVファイルをテキストエディタで開いてみると,確かにLISTは親を2つ持っている.NLISTとnlistだ.その後は,LIST→DATALIST→nodule→NODULEのように単線になっている.最下位のNODULEは自己ループを持っている.⇒初歩的な論理ミスがあった.下図のようになるのが本当だ.

image

仕上がりはこんな感じだ.

image

NLISTは「この図面」では親を持たないので先祖ノードになっているが,軸線図としては正しい.もう一つ反例がある.#201 noduleだ.このCSV(ループ直前でエクスポート)は別アプリで開けた.

image

反鎖リストの長さは11で,データ数は1, 1, 1, 1, 1, 4, 5, 4, 4, 1, 1となっている.上の図とかなり異なる並びになっているのは,世代番号によって区分しているためだ.⇒GetLongestChainにもう一つ誤りがあった.ループ中でノードが削除される場合があるのに,次のノードを取り出すのに削除されたノードを参照していた.⇒処理に入るまえに次ノードをあらかじめ取り出すようにして解決したが,まだ不具合が残っている.TREEVIEW::baseboxが空になってしまう.

この人名枠は昨日新設したSelectBaseBoxで設定しているが,初期ステージで設定したnodule(0)がExtractBox2LDRで削除され空の状態になっている.TREEVIEW::CleanSansyoの中で対象オブジェクトがbaseboxの場合にはSelectBaseBoxを実行するようした.これで問題は解決したが,BUILDCENTERLINEフェーズでCallBuildShaftLineを実行した後も,SelectBaseBoxを実行するようにした.

同上サンプルの親族種別=5(法定親族図) #1 name=couplingでソートして,TOPOLOGY::FindJikusenAncestorで停止した.軸線グラフ上に基準ノードが存在しないというエラーだ.MakeParentChildGraphで生成した直系血族グラフをエクスポートして確認しておこう.

image

節点数26,枝数32で基準ノードも健在だ.GetLongestChainの結果を見てみよう.⇒ダメだ.壊滅している.

image

GetLongestChainの中から呼び出されているGetHasseDiagramの出力を見てみよう.GetHasseDiagramでは絶対世代番号を確定し,推移枝を除去する.

image

総点数は変化していない.次の反鎖リスト(同世代ノードリスト)を生成するという段で失敗しているようだ.このブロックでは重複パスを削減してグラフを単線化することを行っている.パスの削減は一世代づつ実施され,そのたびにMakeAntiChainListで反鎖リストを更新して単線になっているかどうかをチェックしている.MakeAntiChainListではCOMPLISTを使って反鎖リストを生成しているだけで,節点や枝の操作は行っていない.最初に2段目のpagesetupが削除される.ノード削除後,グラフは下図のように変化する.

image

いや,違う.削除されたのはpagesetupではなくて,familytreeだ.確かにこれはまずいかもしれない.familytreeが削除されると,coupling→pagesetupが直結して,最長鎖が短縮してしまう.しかし,仮に短くなったとしても最終出力が得られなくてはならない.まず,こちらの方を先に調べることにする.この後は下図のようになる.

image

軸線が短縮してしまうのは仕方ない.pairlistとnlistが残っているのは末裔ノードとしてロックされているからだ.後はこの2つのノードを削除するだけなのだが,どうなるのだろう?末裔ノードはpairlistとnlistの他にnoduleがある.重複パスを削減対象となったノードは自己ループを持っていても削除される.この3つのノードには優劣はない.重複パスカットで見ているのは「基準ノードは削除されない」という一点だけだ.というのは,パスが重複している限りはどのパスを選択しても到達可能と考えられるからだ.しかし,今の場合は少し事情が違う.

pairlistとnlistはnoduleと同位ではあるが,noduleの方は「パスを持っている」だけの優位性がある.従って,「孤立点となっている場合には削除」としなくてはならないだろう.DeleteIsolatedNodeでは孤立点は削除しているが,自己ループを持っている限りは削除されない.これを修正して「自己ループしか持たない孤立ノードも削除対象」とするのが早いのではないか?⇒IsDeadEndPointという関数を新設して,「パスを失った末裔ノード」つまり,自己ループだけになったノードを検出できるようにした.これで一応動くようになって,下図が出力された.

image

一応これはこれで筋は通っているが,やはり最長軸線と呼ぶのには抵抗がある.推移枝をすべて削除してしまえばこのようなことは起こらないが,そうすると軸線が引けない場合が発生する可能性がある.どうすればよいか?現行論理では重複パスのカットでは枝ではなく節点を対象に削除しているので,その節点が接続している枝が推移枝しか持たないのかどうかということはにわかには分からない.

しかし,最長鎖には推移枝を含まないと言い切れるかどうかも疑問だ.どのノードを残すべきかの判定が必要になる.いや,そもそも,その枝以外ない場合は推移枝を残すという方式が間違っている.ここで削除したいのは,まさにそのような枝であり,それをあらかじめ排除しておけばこのような問題は発生しない.⇒GetHasseDiagramで推移枝は無条件に削除するようにした.この結果,下図の出力を得た.

image

これが正解だ.昨日のサンプルにも「伸びた軸線図」がいくつかあるが,すべて間違いだと思う.「短い軸線」が存在するのは避けられないが,「伸びる」ということは原理的にあり得ない.なぜなら,伸びた軸線があるとすれば,必ずそれを代替する伸びていない軸線があるはずであるからだ.GetHasseDiagramは2箇所で使われている.①血統軸線図,②重婚クラスタ検定だが,少なくとも血統軸線図の場合はこの方式で間違いない.Stage6.zelの完全木テストが通った.

image

実際の出力を見ると,かなり「伸びた軸線」が発生している.これは避けられないものなのかどうか?チェックする必要がある.下図はStage6.zelをTreeViewでソートしたものだが,軸線は伸びている.

image   image

一見すると伸びない軸線が存在するように見えるが,それらはTreeViewを通っていない.血統軸線図の検定を行うときの対象グラフはそもそも直系血族図なので,これらのノードはグラフ上に現れない.実際,TreeViewの直系血族図(上の右図)に含まれるのは,軸線上のノード8点とpagesetupの1点だけだ.

▲ZTシステム構成図7.ZELをMDB @30で開いて,MARGBOX:CheckMarchainで「上位人名ノード不整合」のエラーが出た.

「 非多重グラフで多重枝の登録は不可 」というエラーが出ているので,TOPOLOGY::MakeParentChildGraphで「親子関係の重複登録は行わない@20210210」としたが,果たして問題ないだろうか?一人の人物が,同じ子どもを対象とする複数の養子関係を結ぶということはあり得るので,A→Bという親子関係は異なる結婚に関係して複数あり得ると考えるべきなのではないか?しかし,現行論理では多分多重カードを許したとしても,そこまでは対応していないものと思われる.あるいは,このサンプルではそれが必要になるのだろうか?「軸線ノードでMOTHERLESSでない」というエラーも起きている.

MOTHERLESSというのは「配偶者を持たないか隠蔽された本人直下の単親婚子ども枠」となっているが,本人直下の子ども枠は有配偶者の場合でもMOTHERLESSとされるのではなかったろうか?実際,このエラーメッセージはそのことを言っているものと思われる.多重枝を持つのはよいが,それをハンドリングするのが難しい.いよいよ奥の手を使うときが来たのではないだろうか?

コメントを残す

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

CAPTCHA