部分群を列挙する問題は思ったより難しい

部分群を列挙する問題は思ったより難しい.部分群検定で生成される部分群は極小な部分群であると言えると思われるが,すべての部分群がこれら極小な部分群(以下では素群と呼ぶ)から合成可能であるか否かは不明である.というか,その組み合わせを見つけるのは中々困難だ.A5の場合の素群は位数2×15,位数3×10,位数5×6の31個で,これら部分群の元集合はA5の台集合を(単位元を除いて)直和に分割している.

確かに,(2-1)x15+(3-1)x10+(5-1)x6 = 1×15+2×10+4×6 = 15+20+24=59で完全に|A5|-1=60-1と一致している.つまり,どの部分群も単位元を除いては共通元を持たない.部分群検定で生成された部分群の台集合をシードごとに保管するようにしてみよう.⇒クラス群の中にstring[][] 部分集合を追加した.こんな感じのダンプになった.

i=1 {e,1,2,}
i=2
i=3 {e,3,}
i=4 {e,4,6,}
i=5 {e,5,9,}
i=6
i=7 {e,7,10,}
i=8 {e,8,}
i=9
i=10
i=11 {e,11,}
i=12 {e,12,}
i=13 {e,13,}
i=14 {e,14,}
i=15 {e,15,24,}
i=16 {e,16,32,48,45,}
i=17 {e,17,35,36,57,}
i=18 {e,18,46,26,56,}
i=19 {e,19,37,}
i=20 {e,20,42,50,34,}
i=21 {e,21,58,25,44,}
i=22 {e,22,49,}
i=23 {e,23,54,38,31,}
i=24
i=25
i=26
i=27 {e,27,}
i=28 {e,28,39,}
i=29 {e,29,51,}
i=30 {e,30,}
i=31
i=32
i=33 {e,33,}
i=34
i=35
i=36
i=37
i=38
i=39
i=40 {e,40,52,}
i=41 {e,41,}
i=42
i=43 {e,43,}
i=44
i=45
i=46
i=47 {e,47,}
i=48
i=49
i=50
i=51
i=52
i=53 {e,53,}
i=54
i=55 {e,55,}
i=56
i=57
i=58
i=59 {e,59,}

あとはこれを組み合わせて合成群を作るだけだ.⇒いや,素群2つでは部分群は構成できない.必ず元の補充が必要になる.つまり,3つ以上の素群を合わせなければ部分群を構成することは不可能と考えられる.少なくとも位数4の部分群は3つの素群から構成できる.次の作業に入る前に,A5の部分群を素群に分解できることを確認しておいた方がよい.

A5の位数4の部分群を生成する

部分群検定3では,59+2=61個の部分群が生成されるが,そのうちのかなりの個数は同型というより,おそらく同一と思われるので重複検査を導入してこれらを弾いてみよう.⇒これで生成される部分群の個数は33個まで減少した.■群A5は33個の部分群を持つ合成群である■位数2X15 位数3X10 位数5X6 飽和=0 これは,既存の部分群検定の出力とまったく同じだ.つまり,xのべきを追加登録するという方式はもっと単純な方式とまったく等価ということになる.別の言い方をすれば,部分群検定≡部分群検定3と言ってよい.

位数2x15,位数3x10,位数5x6まではGAPの出力と一致している.出てこないのは位数4x5,位数6x10,位数10x6,位数12x5の4種だ.部分群検定2のノード対を含めるという方式では,現状■群A5は135個の部分群を持つ合成群である■位数2X16 位数3X21 位数5X25 位数6X4 位数10X3 位数12X64 飽和=58.このカウントにはシードが1個だけの場合が含まれている.A5の位数4の部分群{e,(12)(34),(13)(24),(14)(23)}を見てみよう.

#0 → {1,2,3,4,5,}  →  ()
#13 → {2,1,4,3,5,}  →  (1 2)(3 4)
#30 → {3,4,1,2,5,}  →  (1 3)(2 4)
#43 → {4,3,2,1,5,}  →  (1 4)(2 3)

なので,この群を生成してみよう.いや,置換の集合から群を直接生成するような関数はまだ作っていない.現行では置換というクラスはあるが,全,偶,奇の3つのパターンしかサポートしていない.元の集合を与えて親グループから直接生成するというのが手っ取り早いのではないか?⇒部分群の生成という関数を作ってみた.以下が出力された.

群A5-4の台集合 ={e,13,30,43,}
e→     e, 13, 30, 43,
13→    13, e, 43, 30,
30→    30, 43, e, 13,
43→    43, 30, 13, e,

これは見たところV4と同型であるように見える.つまり,13, 30, 43という3つのシードが揃わないとC4は生成できない.A5には位数2の単純群が15個ある.C4はこれらを3個合体させたものだが,位相4の部分群は5個しかない.いや,15÷3=5で数字は完全にあっている.あとは,どういう組み合わせが可能かを調べればよいだけだ.位数6,10,12も調べてみよう.位相10の場合:

<[(1,3),(4,5)], [(1,4),(2,3)]>

[(),
(1,5,4,3,2),
(1,4,2,5,3),
(1,3,5,2,4),
(1,2,3,4,5),
(2,5)(3,4),
(1,5)(2,4),
(1,4)(2,3),
(1,3)(4,5),
(1,2)(3,5)]

位数10:6

これは,{e. 11, 14, 16, 27, 32, 43, 45, 48, 59}に等しい..

群A5-10の台集合 ={e,11,14,16,27,32,43,45,48,59,}
e→     e, 11, 14, 16, 27, 32, 43, 45, 48, 59,
11→    11, e, 16, 14, 32, 27, 45, 43, 59, 48,
14→    14, 48, e, 27, 16, 43, 32, 59, 11, 45,
16→    16, 59, 11, 32, 14, 45, 27, 48, e, 43,
27→    27, 45, 48, 43, e, 59, 16, 11, 14, 32,
32→    32, 43, 59, 45, 11, 48, 14, e, 16, 27,
43→    43, 32, 45, 59, 48, 11, e, 14, 27, 16,
45→    45, 27, 43, 48, 59, e, 11, 16, 32, 14,
48→    48, 14, 27, e, 43, 16, 59, 32, 45, 11,
59→    59, 16, 32, 11, 45, 14, 48, 27, 43, e,

この中で,11, 14, 27, 43は位数2の元と思われる.#27=(13)(45),#43=(14, 23)で生成集合に入っている.#11=(25)(34),#14=(12)(35)は生成集合には含まれていない.

生成元による部分群の生成を試してみる

群の検査関数では,単位元と逆元の存在を確認している他,乗積表をスキャンして記載漏れがないかどうかをチェックしている.従って,この検査を通っている限り,その群は成立していると考えられるのだが… 追加登録関数を見てみよう.⇒既存の論理でxの2乗は登録されている.従って,2乗が落ちているという問題ではない.位数4の部分群{e,(12)(34),(13)(24),(14)(23)}が出てこない理由を調べてみよう.e=#0,(12)(34)=#13,(13)(24)=#30,(14)(23)=#43だ.これはノード対から生成するという今の方法では生成できないのではないか?

むしろ,1個の元xから生成される群を列挙した方が話が早いような気がする.x^n=eとなったときにはすでに群として閉じている可能性はあるが,すべての要素の逆元を取る必要はあるだろう.それだけで十分だろうか?多分,べきも取る必要があるのではないかと思う.いや,追加登録関数はすでにそれらのことをやっているのだから,x^n=eの時点で処理は完了しているはずだ.部分群検定3というのを作って試してみた.

今度は■群A5は61個の部分群を持つ合成群である■位数2X15 位数3X20 位数5X24 飽和=0という結果になった.位数2X15 というのは一致している.位数3X20は合わない.定数は10なので倍になっている.位数4の部分群は出てこない. 位数5X24も定数6なので18個も多い.位数6以上の部分群はまったく生成されていない. 位数4にはV4が含まれているはずだ.乗積表を見てみよう.※

※A5の部分群にV4が含まれているというのは間違い

1→     1, 2, 3, 4,
2→     2, 1, 4, 3,
3→     3, 4, 1, 2,
4→     4, 3, 2, 1,

なるほど,これでは現在の方式では生成できない.

1^2=2^2=3^2=4^2=1

だ.つまり,すべての元が生成元になっている.

さて,部分群の列挙の続きをやろう

さて,部分群の列挙の続きをやろう.現状ではA5の部分群として76個我列挙されている.内訳は,■群A5は76個の部分群を持つ合成群である■位数2X1 位数3X1 位数5X1 位数6X4 位数10X3 位数12X64 飽和=58.まだ,列挙というには程遠い状況だ.ともかく,重複を弾くところから入ることにする.⇒今度はだいぶいい感じになってきた.■群A5は62個の部分群を持つ合成群である■位数2X15 位数3X20 位数5X24 位数12X1 飽和=1.ただし,位数4, 6, 10 の部分群が消えてしまった.

その代わり位数3が本来10個のところ,20個も生成されている.論理ミスがあった.修正して,■群A5は17個の部分群を持つ合成群である■位数2X1 位数3X1 位数5X1 位数6X5 位数10X2 位数12X5 飽和=58のように変わっった.今度は17個まで減ってしまった.seed1, seed2だけを除外するようにしたら,元の76個に戻ってしまった.(seedがダブらないようにループしているのだから当然だが)そもそも,この位数1:1,位数2:15,位数3:10,位数4:5,位数5:6,位数6:10,位数10:6,位数12:5,位数60:1,合計:59 という数字はどこから拾ってきたものだろう?

⇒この数字の出所は以下のURLだ.

http://mathweb.sc.niigata-u.ac.jp/~hoshi/2007/gap-hoshi.pdf

タイトルは「GAPを使ってみよう」となっている.新潟大のサイトだが,筆者の所属は早大だ.筆者の星明考氏は新潟大理学部教授で「群論序説」という本を書いている.

シードが1個だけの場合も部分群にカウントするようにして,以下の結果を得た.■群A5は135個の部分群を持つ合成群である■位数2X16 位数3X21 位数5X25 位数6X4 位数10X3 位数12X64 飽和=58.かなり網羅的になってきたように思われる.不足しているのは,位数4:5(▼5),位数6:10(▼6),位数10:6(▼3)だけになった.この方法で位数4がまったく出てこないのはなぜだろう?位数4は分解しないと得られないのだろうか?

シードを1個追加したときに群とならない場合でもシードを追加するようにしてみたが,結果は変わらなかった.■群A5は135個の部分群を持つ合成群である■位数2X16 位数3X21 位数5X25 位数6X4 位数10X3 位数12X64 飽和=58 まぁ,当然かもしれない.部分群を再分解してみたが,位相4という部分群は出てこない.なぜだろう?まず,これを取り出す方法を考えた方がよいのではないか?

A5の位数3の部分群は{e,(123),(132)}で,共役部分群は10個ある.A5の位数4の部分群は、{e,(12)(34),(13)(24),(14)(23)}で,共役部分群は5個.A5の位数3,4の部分群はp-Sylow群.部分群がp-Sylow群でない場合には互いに共役でない部分群が存在する可能性がある.

Elsieの出力する置換リストには{e,(12)(34),(13)(24),(14)(23)}の記載がない.いや,これは意味が違うのではないか?これは「生成元の集合」であり,むしろ,〈e,(12)(34),(13)(24),(14)(23)〉と書くべきものだろう.つまり,位相4の部分群の生成集合の位数は4である.⇒いや,読み違えている.{e,(12)(34),(13)(24),(14)(23)}というのはそのものずばり,位数4の部分群だ.

位数と指数の関係:|G:H|=|G|/|H| ラグランジュの定理

A4と位数12の部分群HではHの指数は60/12=5となる.

Elsieですべての部分群を列挙する

現行のElsieではA5の(に限らず)すべての部分群を列挙することはできない.単純群から合成するという方法も考えてみたのだが,別策として,点対を含む群を構成することを考えてみる.現行の部分群検定は①正規部分群を生成するモードと②単純に分解するモードに分かれているが,これにさらに点対を含む分解を加えると論理が必要以上に込み入ってしまうので,別立てで改造することにする.

部分群検定でused配列の使い方に疑義がある.関数本体では準同型検定.正規部分群の場合に限ってusedをマークしているが,それから呼び出される 追加登録 では逆に正規部分群検定でない場合に限りオンにしている.⇒usedの使われ方を点検する必要がある.⇒いや,その前にusedを無視したらどうなるか?というチェックをした方がよいのではないか?

※一番外側のiループでは台集合の並び順に原則すべて生成することになる(正規部分群の場合はつねにその動作を行う)が,その後の追加登録で追加されたノードを処理済にするためのマークになっているので,現行論理でよいと思われる.

usedを無視したらどうなるか?⇒A5の部分群は61個ということになった.ただし,位数は2,3,5の三種しかない.台集合を比較すると重複しているので,やはりusedを無視するというのは間違いだ.ただし,部分群の合計が61になるというのはそれ自体問題なので調べておく必要がある.というか,i=1~N-1までの部分群を作って,それに2を足しているのだから当然の数字だ.

ノード対を含む部分群を生成する場合もusedと同様の仕掛けが必要になる.2次元のテーブルを作らなくてはならないが,それに記載されている場合にはパスするというのでよいのだろうか?群表に記載された対はすべて除外されることになるのだが…

まだ,ロジックは書き始めたばかりだが,「■群A5は12個の部分群を持つ合成群である■位数3X1 位数12X9」というメッセージが出力された.本来なら位数3はx10,位数12x5だが,位数12の部分群が生成できたということはこの方針が間違っていなかったことを示していると言えそうだ.外側のiループですでに部分群に入っているかどうかを無視して生成するようにしたところ,■群A5は76個の部分群を持つ合成群である■位数2X1 位数3X1 位数5X1 位数6X4 位数10X3 位数12X64 という結果になった.これには相当重複が入っているが,位数10の群が出てきたというのはよい傾向だ.

位相10の部分群は6個あるのでまだ漏れはあるが,当初論理で位数2x15,位数3x10,位数5x6は確定しているので,位数4x6(不足数4)と位数5x5(不足数4),位数6x10(不足数6),位数10x6(不足数3)という状態だ.ともかく,重複が発生しないような仕掛けにしなくてはならない.

A4の部分群を既成ツールを使って出力する

先に進む前に,A4の部分群を既成ツールを使って出しておこうとしたのだが,例外が発生する.Printでエラーを出している.2023/09/14のログによると「A4の置換リストを保持しようとすると,479001600x12xStringのサイズを持つ配列を用意しなくてはならない… OutOfMemory例外が起きてしまう」とあり,「置換リストを使わない」というオプションを設置している.

▲C#のPermuteで配列の長さ不足エラーが発生する.

image

array.CopyTo(Form1.Homo.map.map1, 1); をインデックス1から開始しているためだ.コピー元はarrayでコピー先は常設のHomoという準同型クラスオブジェクトの写像.map1だ.写像は0発進になっていたような気もするのだが…他の部分を見ても写像は0発進となっているように思われる.仮修正として写像のコンストラクタでmap1/2を1だけ長くしてみよう.おかしい.長さが増えていない.どうも,この「置換リストを使わない」というオプションは仕掛りのまま放置になっていたように思われる.⇒仮修正の妥当性をチェックする必要がある

置換関数の中で「置換リストを使わない」という分岐中で置換リストにアクセスしているというのはかなりおかしい.いや,置換リストの最初の1項目だけは使っているのかもしれない.置換リストはクラス置換のメンバーオブジェクトだ.置換リストは,①全単射の生成,②置換の生成の2箇所で生成されている.Permuteでは「置換リストを使わない」ときは,ArrayListの先頭しか生成しないようになっているはずだ.おそらく,「置換リストを使わない」は行列同型検定のときのみ適用することを予定していたのではないだろうか?

実際,自己同型検定は現状ではN<5であるか,ないし置換リストを使わないモードでないと動作しないようになっている.置換::id[]というのは,群の台集合のようなものなのではないだろうか?いずれにしても,置換リストがないと置換群は生成不能であるようだ.行列同型判定にELSIEを使おうとしていたので,群についての興味は薄くなっていたものと思われる.何か方法はあるだろうか?

おかしい.S4の部分群検定は動作している.S4が通っって,A4が通らないというのは妙だ.parityが非ゼロのときには,IsPermutationEvenが実行される.この中で落ちている.少なくともC#に移ってからは偶置換はテストされていないようだ.ただし,VBでは実施していたはずだ.VBでは通っていたものが通らなくなっているのだろうか?⇒IsPermutationEvenに入る前に落ちている.

IsPermutationEven((string[])list[0], array, size);

C#に移行した時点では, IsPermutationEven(ArrayList list, string[] array, int n)のような構文で動いていたのを修正している.従来論理ではIsPermutationEvenの冒頭で,if (list.Count < 1) return result;としていたので,問題は発生しなかった.元の論理に戻して動作するようになった.とりあえず,A4程度なら置換リストを使っても問題なく動作している.A5を試してみよう.

デバッグ版を起動できないという問題

リリース版は走っているのだが,デバッグ版で起動時に障害が起きる.フォームのコンストラクタでInitializeComponentを実行する前に落ちてしまうので,手が付けられない.コンソールはこの時点ではすでに開かれている.C#プロジェクトがコンソールアプリになっているためだ.出力をWindowsアプリに切り替えても動作は変わらないので,コンソールが出ていることは障害の原因にはなっていないと思う.では,何のどこが悪いのか?C#部分(に限らず既存コードすべて)にはまったく手を触れていないはずなので,なぜこのようなことになってしまったのか?まったく理解に苦しむところだ.

ビルドオプション関係が書き換わってしまっていたり,いじってしまっている可能性はあり,それが影響している可能性が一番高いように思われるのだが,特定するのは難しい.既存コードと目視で比較するのと,作り直ししてしまうのでどちらが早いだろう?原因を特定したいところだが,動かないことにはどうにもならない(デバッグもできない)ので,出直して動かすことを優先する方が賢明かもしれない… まず,最終の準同型検定CSまで戻ってみることにしよう.とりあえず,最終版の準同型検定CSを準同型検定CS+とリネームして始めることにする.

警告が1件出ている.warning MSB8004: Output ディレクトリの末尾がスラッシュではありません。Output ディレクトリが適切に評価されるようにするために、このビルド インスタンスによってスラッシュが追加されます。⇒これは簡単に解決する.ElsieProjectの出力ディレクトリの末尾の\が落ちているためだ.しかし,別の警告が出てきた.

warning MSB3270: 構築されているプロジェクトのプロセッサ アーキテクチャ “MSIL” と、参照 “D:\準同型検定CS+\Debug\ElsieProject.dll” のプロセッサ アーキテクチャ “x86” の間には不一致がありました。この不一致は、ランタイム エラーを発生させる可能性があります。プロジェクトと参照の間でプロセッサ アーキテクチャが一致するように、構成マネージャーを使用してターゲットとするプロジェクトのプロセッサ アーキテクチャを変更するか、ターゲットとするプロジェクトのプロセッサ アーキテクチャに一致するプロセッサ アーキテクチャとの依存関係を参照で設定することを検討してください。

https://nanoris.livedoor.blog/archives/51798587.html

上のリンクの記事によると,原因は「Any CPU、x86、x64 が混在している。Any CPU に対して、x86, または x64 が固定的に組み合わさっている。」ということのようだが… 確かに,Any CPUとWin32が混在した状態になっている.ただし,これで問題なく動作してきたような気がするのだが… おそらく,この警告は昔から出ていたのだろう.

MSILというのは,ProcessorArchitectureの値で,「プロセッサおよびワードあたりのビット数に関して中立」という意味だ.x86というのはIntelのCPUという意味で,32ビットの場合も,64ビットの場合もあり得る.今の場合,AmdやAppleのCPUを使うということは想定されていないのだから,x86でよいのではないだろうか?どうしたことだろう.今度はリリース版で起動時障害が発生してしまった.デバッグ版でも同じだ.プラットフォームをAny CPUに戻したら実行できるようになった.これは警告を無視するしかないような気がする.

ここにAriadne100を移植する.前回は既存プロジェクトを使ったが,今回は新規にプロジェクトを起こしてみよう.⇒ちょっと失敗してしまった.Ariadne100の下にAriadne100ができてしまった.⇒既存フォルダがあると新規プロジェクトを生成できない.

pch.cpp, pch.h, framework.hをプロジェクトから除外した.dllmain.cppも外しておく.⇒*.pchファイルがない⇒プリコンパイル済みヘッダを使わないとする.これでようやくコンパイルができるようになった.エラーがかなり出ている.

E0167    型 “const char *” の引数は型 “char *” のパラメーターと互換性がありません    Ariadne100    D:\準同型検定CS+\Ariadne100\Contract.cpp    613    ⇒対処した.

リリース版,デバッグ版のどちらでも動作するようになった.一度バックアップを取っておこう.フォルダ名は「アリアドネの糸巻き」,アセンブリ名は「アリアドネの糸」に変えてみた.EXEはアリアドネの糸.exeという名前になる.現行では下図のような画面になっている.これにどう組み込んだらよいか?

image

タブで切り替えるような作りになっているが,コンソールが常時出ているとしたら,それも不要という感じになる.当面,①行列同型,②ハミルトン閉路の2つのボタンがあればよいのではないか?画面に出すとすれば,むしろマトリックスを入出力できるようなグリッドを表示するというのが適切なのではないかという気がする.Ariadneを組み込むに当たってまずやるべきことは,すべてのクラスを名前空間の中に収納することだ.ARIADNATIVEとした.⇒一応EXEが走るところまで来たので,一度バックアップを取っておこう.

▲コンソールにはスクロールバーは付けられないのだろうか?⇒縦スクロールバーは自動的に付加されているが…

image

テストボタンを押すと,ハミルトン検定のメニュー画面が出るようになった.つまり,アリアドネ100の画面がそのままコンソールに表示される.行列同型検定も同じような作りで起動できるようにしておこう.

開発機がいつの間にか落ちている

開発機がいつの間にか落ちている.このようなことは時偶起きているが,ロック画面にログインの入力ボックスが出てこない.再起動しても同じだ.⇒Ctrl+Alt+Delで再起動しようとしてみたところ,再起動の代わりに入力ボックスが出てきた.エッジが立ち上がっている.これが原因かもしれない.いつ何時何が起こるか分からないので,バックアップはこまめに,それも外部ストレージにコピーしておく必要がある.

開發用ドライブには現に仕掛りになっているものを残して,すべて開発履歴に移した.それでも100GBのうち,空き領域は33.7GBしかない.Cドライブはもっと逼迫していて18.1GBで赤塗りになっている.xampp関係がCドライブに残っている.⇒バックアップに移動した.結構大きい.それでも空き領域は20GBくらいしかない.⇒完全なディスククリーンアップを実行して30GBまで増えた.ドライブのバナーも青色に変わったのでしばらくはこれで遊べる.昨日の続きに戻ろう.警告が100件くらい出ているので,ともかく,これを片付けてしまおう.

This function or variable may be unsafeがかなりの件数ある.fopen, scanf, getch, strcpy, sprintf, ctime, strcpy,.. などだ.⇒終わった.バッファサイズで生値を使っているところはリテラルに変えた.⇒いや,まだ終わっていない.デバッグモードでコンパイルして新たな警告が出てきた.⇒コンパイルエラーはすべて取れた.

一つだけビルドエラーが残っている.「warning MSB8028: 中間ディレクトリ (Debug\) に別のプロジェクト (Ariadne.vcxproj) と共有されているファイルが含まれています。これにより、クリーンしてリビルド動作が適切に行われない可能性があります。」中間フォルダを全削除してリビルドでこのエラーは消えたが,まだ2つある.一つは「warning MSB8004: Output ディレクトリの末尾がスラッシュではありません。Output ディレクトリが適切に評価されるようにするために、このビルド インスタンスによってスラッシュが追加されます。」もうひとつは,

「warning MSB3270: 構築されているプロジェクトのプロセッサ アーキテクチャ “AMD64” と、参照 “D:\アリアドネ\Debug\ElsieProject.dll” のプロセッサ アーキテクチャ “x86” の間には不一致がありました。この不一致は、ランタイム エラーを発生させる可能性があります。プロジェクトと参照の間でプロセッサ アーキテクチャが一致するように、構成マネージャーを使用してターゲットとするプロジェクトのプロセッサ アーキテクチャを変更するか、ターゲットとするプロジェクトのプロセッサ アーキテクチャに一致するプロセッサ アーキテクチャとの依存関係を参照で設定することを検討してください。」

上の警告はELSIEで出ているようだ.いや,ElsieProjectではないか?確かに\が落ちている.これでビルドも通った.しかし,起動して冒頭で例外が発生する状況は変わらない.

▲リリース版は走ったが,デバッグ版が起動時エラーになる.

Application.Run(new Form1());のところで,「ハンドルされていない例外」が起きている.詳細は以下の通り:

System.TypeInitializationException
   HResult=0x80131534
   Message=’準同型検定CS.Form1′ のタイプ初期化子が例外をスローしました。
   Source=準同型検定CS
   スタック トレース:
    at 準同型検定CS.Form1..ctor() in D:\アリアドネ\準同型検定.cs:line 129
    at 準同型検定CS.Program.Main() in D:\アリアドネ\Program.cs:line 19

内部例外 1:
BadImageFormatException: ファイルまたはアセンブリ ‘ElsieProject, Version=1.0.8684.30681, Culture=neutral, PublicKeyToken=null’、またはその依存関係の 1 つが読み込めませんでした。間違ったフォーマットのプログラムを読み込もうとしました。

デバッグビルドでは「warning MSB3270: 構築されているプロジェクトのプロセッサ アーキテクチャ “AMD64” と、参照 “D:\アリアドネ\Debug\ElsieProject.dll” のプロセッサ アーキテクチャ “x86” の間には不一致がありました。この不一致は、ランタイム エラーを発生させる可能性があります。プロジェクトと参照の間でプロセッサ アーキテクチャが一致するように、構成マネージャーを使用してターゲットとするプロジェクトのプロセッサ アーキテクチャを変更するか、ターゲットとするプロジェクトのプロセッサ アーキテクチャに一致するプロセッサ アーキテクチャとの依存関係を参照で設定することを検討してください。」がまだ出ている.

ElsieProjectからAriadne100への参照が入っていなかった.⇒このエラーは解消したが,もうひとつ出てきた.「LNK1181    入力ファイル ‘D:\アリアドネ\Debug\Ariadne100.lib’ を開けません。    ElsieProject    D:\アリアドネ\ElsieProject\LINK    1    」

ElsieComeBackはLIBを持っているのだが…Ariadne100ではどこにもLIBはない.インポートライブラリ:$(OutDir)$(TargetName).libは設定されている.すべての中間ファイルを削除してリビルドしたところ,今度はリリースモードでも同じエラーが出るようになってしまった.Ariadne100.libが存在しない.これはElsieProjectが静的リンクを要求しているということだろうか?⇒ELSIEとAriadneの出力をDLLからLIBに変えてビルドは通ったが,起動時のエラーは収まらない.Ariadne100をビルドから外してみたところ,

「ElsieComeBack.dll(NativeFunc.obj) : MSIL .netmodule または /GL を伴ってコンパイルされたモジュールが見つかりました。/LTCG を使用して再開始してください。リンカーのパフォーマンスを向上させるためには、コマンドラインに /LTCG を追加してください。」

というエラーになった.これは最適化に関係するオプションのようだ.Debugモードではまた別のエラーになった.「warning LNK4075: /EDITANDCONTINUE は /INCREMENTAL:NO の指定によって無視されます。」⇒エディットコンティニュをオフにして解消した.

Ariadne100を切り離したにも関わらず,起動時障害が発生する.準同型検定のForm1が開けないという意味だが… Form1.csを準同型検定.csにリネームしているためではないか?クラス名はForm1のまま変更されていない.いや,そもそもリリース版では走っているのだから,そういう問題ではない.やはり,ビルドオプションが関係しているのではないだろうか?どうもよく分からない.リリースモードではLIBを指定しているのにDLLが生成されている.DLLを生成するようにしてみたが,結果は同じだ.⇒アリアドネ再開発の開始点まで戻るしかないのではないか?

戻ってくるアリアドネのために部屋を整える

NHKの笑わない数学の第一弾は「確率論」,第二弾は「非ユークリッド幾何」でどちらもFBの数学グループで話題沸騰中だ.わたしも巻き込まれてだいぶ時間を消費してしまったが,本線に戻ろう.グラフの隣接行列から距離行列を生成する「ワーシャル・フロイド法」というアルゴリズムがあり,これをハミルトン閉路問題に応用するという課題がにわかに浮上してきた.ロバート・フロイドがこのアルゴリズムを最初に発表したのは1962年(それ以前にバーナード・ロイとステファン・ワーシャルが独立に発見している)で,現在の三重ループの形に整理されたのはピーター・インガーマン(1962)による.

このアルゴリズムは元々はオートマトンや正規表現の世界から渡ってきたようで,重み付き最短経路を多項式時間で計算することができ,さらに重みの和が負であるようなサイクルを含まないグラフのサイクル検出にも適用できる.また,推移的閉包の検出にも適用可能であるようだ.FBのコメントではこのアルゴリズムが「フロイド・ライブネッツアルゴリズム」という名称で紹介されていた.

https://pydocument.hatenablog.com/entry/2023/04/29/132317?fbclid=IwAR1gENpzpPoA2siiWajP0Z3eyj4oCE9R4All5ovWCpKaCTFMPa6FebswHrY

しかし,どこを探してもそのようなものは出てこない.そもそも,Leibnizの名前をライブネッツとなまっている時点でおかしいのだが,上の記事では何度もこの名前で出てくるので執筆者はそれが正しいと確信しているようだ.この記事はHatena BlogのPyDocumentというシリーズものの一部で,『問題解決のための「アルゴリズム×数学」が基礎からしっかり身につく本』米田優峻著からの抜粋のように見えるが,ひょっとすると本当の著者はChatGPTなのではないだろうか?いかにもChatGPTのやりそうな間違いだ.

「GPU上での高速なブロック化フロイド・ワーシャル法」などというのもあり,かなり実用的に使われているアルゴリズムではあるようだ.

https://cir.nii.ac.jp/crid/1050564287852717824?fbclid=IwAR2oMq0IYmoIrE51iR163SnZNPBA-mxKVd9MzsPwBcowTvNgwBGhGZVwU3M

この記事では改良によって頂点数256~1024の場合は従来手法より高速化し,それ以上の場合は遅くなったと報告しているが,アリアドネの既存コードでは100点までしか計算できない.行列同型でもN=520を超えるサンプルではスタックオーバーフローが起きていたはずなので,500点を超えるサンプルを扱えるようにするのは難しそうだ.我々の目的からすれば,そこまで大きなサンプルは必要ないので,まぁ,500点が限界だとしてもとりあえず問題はないが…

アリアドネはFドライブのBACK2006-05-05/BABA_LABORATORYにある.このフォルダにはsamplesというフォルダがあるが,この中にはファイルが9452本も入っている.フォルダだけで13個もある.Narcissus,ないしNarkissosというフォルダが気になる.ハミルトン閉路問題ではないかという気がするのだが… 2002~2004年頃のものだ.どちらが最終版なのか?EXEのタイムスタンプはまったく同じなので時期は完全に一致している.前者はフォルダ数293, ファイル数19に対し,後者のフォルダ数は30.ファイル数は3566なので,おそらく,Narcissusを保存版としてくくり出したのだろう.

Narcissusのpublishというフォルダには,Narcissus.exeと一緒にELSIE.exeも入っている.このフォルダではELSIEとNAICISUSを並行して開発していたのだろうか?このフォルダのSOURCEにはELSIEのソースファイルしか入っていない.⇒走らせてみれば分かるだろう.

image

NarcissusというのはELSIEの一部だ.つまり,ELSIEはNarcissusを含んでいる.NarcissusはELSIEの機能のうち,グラフ同型検定に特化したものと言ってよい.ただし,この機能に関してはELSIEより少し詳細な設定ができる可能性がある.たとえば,表示モードを切り替えたり,ファイル形式の変換ツールが入っていたりする.まぁ,とりあえずはELSIEに含まれているものだけで十分だ.アリアドネのソースはVBだと思っていたが,C++だった.AriadneはELSIEとほぼ同等だから,準同型検定CSに組み組むのは難しくないと思われる.ただし,Ariadneを組み込むとこのプロジェクト全体の性格が大きく変化することになるので,フォルダ名を変えておくのが順当だろう.

もし,今後ハミルトン閉路問題が主題になるとすれば,日本語で「アリアドネ」ということでよいのではないだろうか?Ariadneの中にはAriadne100の他に,Asha, CounterStas, Hcp2Sat01というフォルダがある.Hcp2Satはハミルトン閉路問題をSAT(論理式の充足可能性問題)に変換するためのツールだ.CounterStasというのはよく分からないが,Stanislav Busyginとのやり取りに関係したものだろう.Ashaの中にはBlkblu.exeというのが入っているが実行できない.あとはBlkblu.cとテキストファイルが2本入っているだけだ.

Ashaというのは多分人名だと思う.確かにそうだ.Cソースの中に

printf(“\n%s   v. %d, by Asha Goldberg\n\n”, progname, versionno );

という一行があるので,Asha Goldbergという人物が書いたコードだということが分かる.この頃はネット上にソースが転がっているという時代ではないので,多分本人から送ってもらったものではないかと思う.ただし,メールの現物は残っていない.このコードはハミルトン閉路の解法アルゴリズムだ.いや,ハミルトン閉路を含むグラフを生成するためのコードかも知れない.ブラックとかブルーなどの色を頂点に割り当てるようなことをしている.おもしろそうだが,読み切るにはちょっと時間が必要なのでパスしておこう.データファイルのフォーマットはアリアドネと完全に同じ,各行が#で始まる隣接行列だ.

ELSIEを組み込んだときの手順を忘れてしまった.既存のプロジェクトを組み込むというのが最速だが,新規プロジェクトとして登録してからファイルを追加していったような気もする.その辺り,ログに残っているだろうか?ELSIEのときは,boostというライブラリの組み込みで立ち往生していた.ELSIEのプロジェクトファイルはElsieComeBackフォルダに入っているので多分既存プロジェクトを組み込んだだけだと思う.その後,ソースファイルの入れ替えをやったような記憶もあるが… それよりも,Ariadneに入っている本体以外のフォルダを削除してディレクトリを1段上げておいた方がよい.つまり,アリアドネの直下にAriadne100が来るという構成だ.

準同型検定CSというソリューション名も変える必要がある.名前の変更は調整できたが,ビルド→実行でエラーが出てしまった.

image

アプリケーションのシングルスタートアッププロジェクトがElsieComeBackになっていた.準同型検定に変えて動作するようになった.⇒既存プロジェクトの追加で以下のメッセージが出た.

image

OKでビルドできたが,「D8016    コマンド ライン オプション ‘/ZI’ と ‘/Gy-‘ は同時に指定できません」のようなエラーになった./Gy-というのは,関数レベルでリンクしないという意味のようだ.ZIはエディットコンティニュの意味だ./Gy 関数レベルでリンクするに統一した.

i, j, k が定義されていない,ないし,未使用という警告⇒対処した.

warning D9035: オプション ‘Gm’ の使用は現在推奨されていません。今後のバージョンからは削除されます。⇒最小リビルドを有効にするという意味だ.⇒オフにしておこう.

▲This function or variable may be unsafeがかなりの件数ある.fopen, scanf, getch, strcpy, sprintf, ctime, strcpy,.. などだ.

MAXNを520まで拡大してスタックオーバーフローが発生

▲MAXNを520まで拡大して,スタックオーバーフローが発生した.ExcentricGraphでMakeRandomGraphの後,Shuffle関数の呼び出しができない.プロセスメモリは200MBくらいしか消費していない.MAXN=400なら動する.500でも動いている.⇒Shuffleの引数を参照からポインタに変えてみたが,スタックの使用量は減少していない上,Shuffleの中でGP例外が発生した.一度修正を元に戻すことにする.