だいぶ目鼻が整ってきたように思われる

なかなか進まない.てか,もっと大胆にフィックスして行ってよいのではないか?というより,ほとんどフィックスしているような気もする.

N=1, K=1でPrime Testを実行して,Count cannot be less than zero エラが発生した.⇒MakeDecimalStringでmaxfixedがゼロになっているため,エラーが生じていた.maxfixedが0のときは1に書き換えるようにした.B=1のときは,maxfixed-1だけ0を並べるようになっているが,N=1の場合は0で回ってきているため.fixedの値はInvertFuncが決めているが,B=1の場合には,fixed = n-1 になっている.いや,おかしい.B=10だ.MakeDecimalStringではB=1で呼び出されていたはずだ.PrimeTestは1~Bまでの範囲のテストを実施しているためだ.

ある範囲を包括的にテストする場合には,範囲を設定できるようにした方がよい.PrimeTest, InvertTest, SeedTestはすべてこのカテゴリに入る.⇒大体動作するようになった.現行ではBとψが連動しているが,ψとBは切り離した方がよい.ψを決定するのはKでなくてはならないと思われる.⇒ダンプ時にψ(N)ないしψ(K)などのように明示すればよい.

ValueChangedの中ではBにアクセスしないようにしたいのだが,可能だろうか?ValueChangedの後半ではInvertFuncを呼び出して,循環節を生成しているので完全に排除することはできないが2つに区分することは可能なのではないか?DispMovePowでは何をやっているのだろう?この関数は単にN^P mod K を計算しているだけだ.⇒一つエラーが出ていたのだが,再現しなくなってしまった.しかし,だいぶ話がまとまってきたのではないかと思う.顕著なところは,ψ数が2つ必要になってきたという点だ.ValueChangedの前半と後半を分離して,前半ではKを用い,後半ではBを用いるようにしているので,ψもそれに応じた値を計算する必要がある.これで目鼻が少し付いてきたのではないかと思う.

現行ではValueChangedでは剰余数列周期を計算していないが,これを求めて表示するようにしておこう.ResidueFuncは剰余マトリックスに依存していないので,単独で実行することが可能だ.DispModPowという関数があるので,この中から呼び出すようにしてみよう.⇒だいぶいい感じになってきた.弁慶の泣き所と言えば,Nが8桁を超えるとがくっと重くなるところだけだ.こればかりは右から左という訳にもゆかない.ResidueFuncが加わったのでなおさらだ.どこかで処理を統合するということも考えられる.類似アルゴリズムを使っているところでは,優劣を見極める必要もあるだろう.

PsiFunctionで一つ疑問が持ち上がっている

さて,かなり整っては来ているのだが,PsiFunctionで一つ疑問が持ち上がっている.「n・kが素は,①(n, k)=1,②drop=0, ③ψ=periodと同値ということになる」という点だ.ψが値を持つとき,つまり,非ゼロのときは確かにψ=periodになっているが,drop=0でψが値を持たない場合がある.これは,剰余マトリックスの最終版でも同じ動作になっているので,最近の修正の影響ではない.つまり,②drop=0と①(n, k)=1は同値は元々成立していなかったと見るしかない.drop=0のときに強制的にψ=periodとすることは不可能ではないが,果たしてそれが正しいのかどうかという点に関しては吟味する必要があるだろう.

TestMatrixにはもう一つ疑問がある.gcd1とgcd2には i ないし j とK-1のGCMが入っているが,これは i, j とKのGCMだったのではないだろうか?⇒暫定的に修正を入れた.こちらの方が正しいように思われる.ただし,K=10のとき,N=1ではG=1だが,ψ=0になっている.これはG=1の場合はつねにψが立つというルールと整合しない.⇒これを修正すると,今度は「文字数xGCMは k-1 に一致する」と整合しなくなる.これはK=3,J=2で発生する.これは縦数列でのみ発生するエラーなので,gcd2は従来仕様に戻してみよう.⇒これは暫定修正である.

N-123,K=10,B=10→リターンで確定して,ValueChangedで停止した.InvertFuncがketa=5を返し,B^keta ≡1 mod Nとなった.ψ=5がketaと一致しないためだ.従来のPsiFunctionなら問題は生じない.⇒従来関数と現関数ではModPowの呼び出しが逆になっている.従来方式ではModPow(B, px, num)となっているのに対し,新版ではModPow(num, px, K)であり,num⇔B/Kが逆転している.従って,関数を共通化するためには,呼び出し側で逆転させる以外ない.実際,InvertFuncは通常のべき乗剰余の逆操作になっているのだから,そうならなければおかしい.⇒対処した.

N=12345678で制御が戻ってこない.⇒InvertFuncで時間が掛かっている.それにしてもこんなに遅かったろうか?前にはもっと速かったような気もする… 10桁くらいまではそこそこ走っていたような気もするのだが… このInvertFunc中の周期の計算とべき乗剰余数列の周期計算を共通化するというのがおそらく当面の目標になるのではないか?

ValueChangedでStrComp(str3.Substring(0, MAXDOUBLEKETA), str4.Substring(0, MAXDOUBLEKETA))により停止した.MAXDOUBLEKETA=16という定数だ.これは検算のために倍精度数と比較しているところだ.str3はゼロの並び.”0.0000000000000…0000000000″,str4は”0.0000000810000066″のように数字が入っている.この数字は8.1000006642000542E-08だ.MakeDecimalStringで失敗しているような気もする.

現行では,N^pow でpowに64以上の値が設定できない.これは不都合だ.Maximumが64に設定されていた.とりあえず,65,535までは設定できるようにしてみた.

さて,問題はPsiFunctionだ

さて,問題はPsiFunctionだ.現在PsiFunctionには2つバージョンがある.Kinai.vbにあるものとModule1.vbにあるものだ.前者がオリジナルで後者はマトリックスに入ってから修正したものが,これらをどちらかに統一しなくてはならない.後者の方が新しいので当然こちらを取ることになるが,微妙なところで差異がある.どうやって調整すればよいか?問題の焦点は除数にBを使うか,Kを使うかにあるのではないかと思われるが,現行では,BはB進表記にのみ適用され,それ以外ではKを使うということにはなっている.循環小数ではB進表記を使わざるを得ないが,べき乗剰余では進数に関わりなく計算ができなくてはならない.

循環小数をカバーしているのは,結局,InvertFuncであると考えられるから,まず,これを通常処理から切り離す必要がある.ResidueFuncもバージョンが別れている.⇒ダブっている関数をすべて(PsiFunctionとResidueFuncを除き)整理した.引数も整理してBとKを見分けやすい用に書き換えた.これで準備は整った.ResidueFuncを比較してみよう.⇒論理的な有意差はないように思われる.Module1.vbの版では①scount(初項出現カウント)を取っていない,②「非ゼロ列で初項なし」という検査を行っていない,③出口でPsiFunctionを実行してψと周期を比較している,という点が異なる.

①に関しては旧版でもscountは事実上カウントされていないので,意味がない.また,観察された限りではドロップ項はかならず初項から連続して落ちているので,初項のみに注目しても意味がないと思われる.現行ではどちらの版も戻り値でドロップ項数を返し,参照で周期を返すようになっているので,一応これらの値が一致していることを確認しておこう.⇒問題なさそうだ.これで旧版のResidueFuncは廃止できる.

Residue Cycle Test の後,BuildMatrixを実行して例外が発生した.⇒再現しない.⇒再現した.上から順番にテストしてくると発生する.Kは13で変化していない.DumpMatrixで例外が起きているようだ.「Index was outside the bounds of the array.」というエラーが起きている.gcd1配列が空のままだ.S1配列も長さゼロだ.BuildMatrixではT()という2次元テーブルを生成しているが,テーブルを作るだけで付属的は配列などは整備していない.それをやっているのは,TestMatrixだ.DumpMatrixに先行してTestMatrixが実行されていなくてはならない.どこかでverboseがオンになっているのだろう.DumpMatrixはTestMatrixと一体化される必要がある.実際,TestMatrixの中でも実行されているので,それ以外の場所での使用は禁止した方がよい.

PsiFunctionを比較してみよう.主な相違点は以下の通りだ.①新版では約数のダンプは省略されている,②旧版ではnと除数が互いに素の場合のみを対象としている.③旧版ではnと除数が互いに素でない場合にはResidueFuncを呼び出して周期を求めようとしている.ψ値はnと除数が互いに素でない場合には決定できないので,これらの差異はトリビアルなものである.時間効率的には,旧版の方がロスがない.ただし,ResidueFuncでも周期は決定できないので,その意味ではどっちもどっちというところだ.PsiFunctionからResidueFuncを呼び出すとスタックオーバーフローしてしまう可能性があるので,避けるべきだろう.

結局,結論的には剰余数列の周期はResidueFuncでしか決定できないということになる.いや,それも少し言い過ぎかもしれない.少なくともTestMatrixでは異種文字数まではカウントできる.異種文字数=ドロップ項+周期だ.TestMatrixでは内部でResidueFuncを呼び出して比較している.いや,新版と旧版のPsiFunctionには大きな違いがある.PsiFunctionでは基数のべき乗を生成しそれを除数で除した剰余を求めているが,基数と除数の関係がまったく反対になっている.もし,新版の論理が正しいとすれば,従来論理の呼び出し時の引数を変えなくてはならない.従来論理が正しいとすれば,その逆が必要になる.つまり,ものの見方がまったく逆向きになっている.

どちらが正しいというより,その差異がどこから発するものかを突き止めなくてはならない.基数と除数が入れ替わっているだけではなく,引数で渡しているφ値も異なる.新版の場合は,φ(K)が使われているのに対し,旧版ではφ(n)になっている.⇒どうもこのφ値の扱い方に問題があったようだ.関数内部でKのφ値を取るようにしたら,新版で問題なく動作するようになった.引数の入れ替えも不要ということになる.これでよいのだろうか?結局,どちらかが逆向きの読み方をしていたということになるのだが…というか,φとψの関係が繋がっていなかっただけということかもしれない.⇒ともかく,動作しているので,この方向で落着させることにしよう.⇒いや,まだ落着していないような気もする.2023/05/18のログでは「n・kが素は,①(n, k)=1,②drop=0, ③ψ=periodと同値ということになる」としているが,現時点ではdrop=0でも,ψが立たない場合がある.

べき乗剰余数列周期とマトリックスの統合

べき剰余数列周期とマトリックスの統合はなった.あとは,これを仕上げるだけだ.画面は大体固まった.

image

ポイントはB進数表記を別枠としたことだ.これは結局,循環小数の周期性とべき乗剰余数列の周期性を切り分けることを意味する.マトリックスがその仲立ちとして機能するかどうかが興味深いところだ.とりあえず,これらのパーツに正しい値が表示できることを確認しておこう.⇒まず,φとψを出しているところをチェックしておこう.φはTextBox7に出力している.ValueChanged→DispParametorで表示される.この値はPhi(n)で計算されている.

▲17桁の整数{18867829946740099}の因数分解で手間取っている.

n:1000 x k:50 のテストが完了

昨夜仕掛けておいた n:1000 x k:50 のテストが完了している.問題があれば停止することになっているので,特に問題になる事象は発生していない.ResidueFuncをマトリックスで走らせてみよう.ResidueFuncは周期とドロップを返さなくてならないので,引数を追加してbyrefにしておこう.フォームが開けなくなった.

Failed to launch the design tools server process

VS2019を修復インストールしてみたが効果なし.デバッグモードで一度走らせたら,その後は開けるようになった.TestAllPrimeでk=2~1000までのテストが完了した.Mとcycle+dropは完全に一致している.ψとMないし,ψとcycleでは乖離がある.ただし,このテストでは対象kを素数に限定している.一般の場合はどうか?⇒問題なさそうだ.ただし,一つのkの検査ではk^2のコストが掛かるので,kが大きくなるとかなり時間を要するようになる.とりあえず,k>600でテストを打ち切ることにしよう.

M=cycle+dropは完全に確立できたが,ψ値はほとんど一致していないという感じだ.ψという数は本来,n^ψ=1 mod k となるような最小の値と定義されているので,ψ値を求められない場合がある(ψ=0).ψが剰余類群の位数であるという定義に従えば,ψ=cycle ないし ψ=cycle+dropであってもよいような気がするのだが,ともかく,もう一度ψ関数周りをチェックしてみることにしよう.PsiFunctionでは,「トーシェント数を因数分解してψ数を推定する」ということをやっている.このループの中で,ModPow(b, px, num)=1となる場合のpxをψと認定している.式で書くと,k^p mod n ≡1ということになる.しかし,上掲の式ではn^ψ=1 mod kとなっていて,除数と基数が逆になっているようにも思われる.

PsiFunctionでは引数でnのφ数を与えているが,これはφ(n)であり,φ(k)ではない.どうもModPowの使い方が間違っているのではないかという気がする.逆に入れ替えてみよう.⇒動作しない.nとbが互いに素であるのにψ値が決められなくなってしまった.やはり現状の設定で間違っていないようだ.⇒いや,そもそもPsiFunctionに渡しているφが間違っているのではないか?⇒確かにそのようだ.φ(k)を使わなくてはならないところ,φ(n)を使っていた.これを修正したら,ψの不一致はψが値を持っていない場合のみになった.⇒この修正はresiduFuncないしPsiFunctionを呼び出しているすべての箇所に影響するので久留島喜内の方も点検しておいた方がよい.

nとkが互いに素であるという条件はφ(k)からψを割り出すための絶対条件である.つまり,一般にはnとkが素でなければψを決定することはできないが,マトリックスでは異種文字数の形式で巡回周期を割り出すことができる.ResidueFuncではdropとcycleとしてψに相当する数字を取り出すことができる.だとすれば,PsiFunctionを使わなくてもψを決定できるのではないか?

ともあれ,先に進む前にPsiFunctionの修正の始末を付けておこう.⇒喜内ではすべてφ(n)を使っている.φ(n)とφ(k)では意味がまったく違う.これでよいのだろうか?⇒これはもう一度後から見直すことにする.喜内では逆数の循環小数を見ているので状況はおそらくかなり異なるものと思われる.こちらの用法では基数と除数が逆転している可能性はある.⇒PsiFunctionの仕様は現行で正しいと思われるので,喜内側の呼び出し方を変える必要があるのではないか?

TestMatrixで検査している限りでは,ψとcycleはψが決定不能(=0)でない場合にはつねに一致している.従って,ResidueFuncのcycle値をψとしてよいものと思われる.

スタックオーバーフローが発生した.⇒ResidueFuncの中でPsiFunctionを実行するようにしたためと思われる.PsiFunctionの中からResiduFuncを呼び出している.⇒これは実装を中断している部分のコードだ.これは止めておこう.

一応これですべて整合するようになったのではないだろうか?現行ではψ値はn・kが素でないときは未定ないし決定不能となっているが,これを拡張してψ=剰余数列周期とするのかどうか?が問題だ.この問題は,ここではとりあえず保留としておこう.どちらが使い勝手がよいかで決定すればよい.剰余類群の位数という定義もかなりあいまいであるような気がする.剰余類群と呼ぶときに,その中にドロップ項は入っているのかいないのか?数値的には入っていないように思われるが,それでよいのかどうか?⇒ドロップが発生するときにはψ=0になっている.剰余類群というのは,nとkが互いに素の場合しか定義されていないと思うので,その限りでは整合していると言える.n・kが素は,①(n, k)=1,②drop=0, ③ψ=periodと同値ということになる.

そろそろ,マトリックスとべき乗剰余数列を統合してもよいのではないだろうか?マトリックスにはもう少し付加情報を出したいのだが,それよりも優先度が高いような気がする.マトリックスはボタン2つまで簡素化したので,統合は難しくない.⇒とりあえず,動いた.

image

べき乗剰余数列とべき剰余マトリックス

さて,いよいよ佳境に入るというところだが,その第一歩はべき乗剰余数列とべき剰余マトリックスの統合だ.これをどちら側でやればよいのか?それが問題だ.最終的には剰余数列をマトリックスに吸収するという流れに落ち着くものと思われるが,過渡的には剰余数列でテストしてみるということも考えられる.特にドロップ項(落伍項)と呼ばれるものの実態を究める必要がある.そのためにはむしろ剰余数列の延長上で考えた方が分かり易いのではないか?しばらくその方向で進むことにしよう.⇒マトリックスでドロップ項の話が出てこないのは,まだそこまで進んでいないためだ.たとえば,k=12でn=2, 6, 10ならドロップが発生するが,マトリックスでは完全に無視されている.マトリックスでは以下が出力される.

1    1    1    1    1    1    1    1    1    1    1    Σ=11 G=1 M=1 ψ=0

2    4    8    4    8    4    8    4    8    4    8    Σ=2 G=1 M=3 ψ=0

3    9    3    9    3    9    3    9    3    9    3    Σ=3 G=1 M=2 ψ=0
4    4    4    4    4    4    4    4    4    4    4    Σ=8 G=1 M=1 ψ=0
5    1    5    1    5    1    5    1    5    1    5    Σ=11 G=1 M=2 ψ=2

6    0    0    0    0    0    0    0    0    0    0    Σ=6 G=1 M=2 ψ=0

7    1    7    1    7    1    7    1    7    1    7    Σ=11 G=1 M=2 ψ=2
8    4    8    4    8    4    8    4    8    4    8    Σ=8 G=1 M=2 ψ=0
9    9    9    9    9    9    9    9    9    9    9    Σ=3 G=1 M=1 ψ=0

10    4    4    4    4    4    4    4    4    4    4    Σ=2 G=1 M=2 ψ=0

11    1    11    1    11    1    11    1    11    1    11    Σ=11 G=11 M=2 ψ=2
0    0    0    0    0    0    0    0    0    0    0    Σ=0 G=0 ψ=0
6    2    0    2    0    2    0    2    0    2    0    4=∑
1    1    1    1    1    1    1    1    1    1    11    =G
11    4    9    4    9    4    9    4    9    4    9    =M
0    0    0    0    2    0    2    0    0    0    2    =ψ

n=2の場合は{2, 4, 8, 4, 8, …}という数列になるが,異種文字数は3になっている.つまり,異種文字数=周期は必ずしも成立しない.ドロップ項の2を除外すれば,{4, 8}という周期が取り出される.n=6の場合は,6がドロップ項で巡回数列は{0}だ.n=10の場合には{4}が巡回数列になる.n=4や9では{4}や{9}のような自己ループに墜ちているが,ドロップとは言わない.これは初項が存続しているためだ.実際,このような場合には異種文字数=周期が成立している.従って,マトリックスにドロップという概念を移植することは必須であると言える.

k=12のマトリックスでは,n=5, 7, 11のように対象数が素数である場合にしかψが立っていないが,周期数列の周期=ψであると定義すれば,すべての場合にψ数を決定することができる.実際,ψ=剰余類群の位数と解釈されるが,剰余類群の位数とは剰余数列の周期に他ならない.剰余類群=マトリックスの行とみなすとすると,この集合の要素にはドロップ項が含まれるが,乗群とみなすためにはドロップ項を外す必要があるのではないか?ここでは暫定的にψ=周期とみなすという立場を取ることにする.従って,剰余数列=ドロップ項+周期という構成になる.まず,この周期を明示するところから始めなくてはならない.また,この周期を確立することができれば,懸案の剰余数列のすべての周期を確定するという課題が解決されることになるだろう.

Psiという関数と別にPsiFunctionという関数がある.これは何だろう?どちらもψ値を求めるものと思われるが… PsiFunctionは以下から呼び出されている.①Inverse_Click,②PrimeTestClick,③SeedTestClick,④ValueChanged.一方Psiの方は,現状ではまったく使われていない.PsiFunctionとPsiの大きな違いは,前者が引数でφを渡されている点だ.PsiFunctionではGetDivisorsを使ってφの約数を求め,これからψを推定しようとしている.後者はGetDivisorsは使っていないが,同等処理を内部で実施している.結局,Psiを整理したものがPsiFunctionと考えてよいだろう.やっていることはほぼ同じだ.Psiは旧式と考えられるので,廃棄してよいのではないだろうか?

ResidueFunc2ではkの範囲しかチェックしていない.これに関しては問題ないと思われるが,ドロップ項の検査で1~周期までの間しか見ていないというのは誤りだ.ドロップ項はつねに連続していると推定されるので,非ドロップ項を検出した時点で打ち切ってもよいのではないかとは思われるが,周期の範囲では取りこぼしが発生する.

ResidueFuncにはすでに修正が入っているので,ResidueFunc2はお役御免になったのではないか?⇒ゴミ箱に移しておこう.ResidueFuncではすべての場合に例外なく周期が取れるようになったので,マトリックスに組み込むことができるだろう.もちろん,マトリックスはマトリックスで独自検査をやってもよいのだが…

進捗は遅いが,多少は進んだ

進捗は遅いが,多少は進んだ.φとψを出力するようにしてみたが,出力との関わりが不明だ.Gをnとk-1の最大公約数,Mを異種文字数としたとき,縦数列ではG*M=k-1がつねに成立しているが,横数列では崩れているように思われる.周期とψには連関があるはずだが読み取れない.ψの取り方が間違っているのだろうか?つまり,横数列・縦数列の周期性と循環小数の周期性ないし,剰余数列の周期性との関係が見えない.ψを計算するためには,nとbを決める必要があるが,何がnに該当し,何をbとすればよいのかがいまいち釈然としない.

ψ値はφ値の約数である.今のところ,nのφ値を表示している.この値とψは,確かにψ|φの関係になっているが,これでよいのだろうか?φ(k)とすると,値は6になる.GとMの積はn=1, 6を除くとすべてこの値に一致する.ただし,この場合,たとえばn=5ではφ=6, ψ=4でψはφを割り切れなくなる.ψ(k, i)を取ると,n=1では0となるが,それ以外では3, 6, 3, 6, 2となり,φの約数が出てくる.特に,n=3, 5 などの尽数列になるところで,ψ=6となっている点が興味深い.また,この数字はn=1の場合を除いて,Mと完全に一致している.確かにこの数値の方が正しいように思われる.

Mとψが(ほぼ)完全に一致するというのは重要なポイントではあるが,ここではちょっと置いて,もう少し先に進んでおくことにしよう.べき剰余マトリックスではテーブルの出力をもう少し充実させるという課題が残っているが,そこに進む前に,べき乗剰余との関係をもう少し明らかにしておきたい.循環小数との関係についてはまだかなり不明な点が多いのでしばらく置くとして,べき乗剰余とべき剰余マトリックスは地続きであるのだから,その関係をもっとはっきりさせる必要がある.このためには,べき乗剰余とべき剰余マトリックスを一体化させるというのが一番近道なのではないかと思う.

べき乗剰余数列には3機能ある.①n^p mod k を計算する,②n^p mod k の剰余数列周期を計算する,③これらの包括テスト.3機能の中心が②の剰余数列周期の計算にあることは確かだ.べき乗剰余周期はψに関わりがあるはずだから,いま興味を持っている点にもっとも近いはずだ.この機能のコアはResidueFuncという関数だ.この関数は「’対象数nのべき乗の k による剰余を計算し,剰余列の周期を返す」というもので,nとkは画面上の入力から取り出している.ModPowでべき剰余を計算しているが,その範囲を1~2kとしている.kはBigIntegerではあるが,およそ整数範囲内であることが予定されている.

R()という配列にはべき剰余の計算値が格納され,それを上から走査して繰り返しの開始点を見つけるというやり方だ.原理的にはべき乗マトリックスで実施していることと大差ないものと思われる.マトリックスでは剰余をRというハッシュテーブルに格納する代わりに,直接マトリックスとして構成している.つまり,マトリックスの一行がほぼべき乗剰余の1回分に相当する.マトリックスのkがべき乗剰余のnに相当しているという点がやや混乱を招き易いところだ.

べき乗剰余では一行分の計算しか実施していないので,そこそこの時間で計算完了しているが,マトリックスではk^2の計算を行っているので,数字が大きくなるとやや実際的なものではなくなってしまうという点が致命的なところだ.逆にべき乗剰余の計算法を使ってマトリックスを構成することは可能だろうか?いや,べき乗剰余にはPというパラメータが関わっている.ここで計算しているのはn^p mod kという計算だ.いや,pは可変で1~2kまでというのはこの値のことだ.従って,マトリックスのkと剰余数列のkは一致している.

マトリックスでも n^p mod k を計算しているが,マトリックスではn≦kの範囲しか扱わない.循環しているからそれ以上は不要という立場だ.従って,剰余数列でもkの剰余を取っているのだから,kより大きい数字は数列には現れない.であるとすれば,べき乗剰余数列で計算するときでも最初に n=N mod k から始めてよいのではないか?これができれば計算は相当縮小され,高速化するものと思われる.ResidueFuncにはResidueFunc2というバリエーションがあり,並列実行して値が一致していることを確認しているが,どこが違うのか?⇒多分この違いはスキャンする範囲が違うだけではないかと思う.つまり,ResidueFunc2では2kではなく,kまでの範囲しか検定していない.

周期の開始点を見つけるだけなら,おそらくこれで十分と思われるが,周期そのものはkの範囲を超えないと出て来ないのではないだろうか?もう一つ不審な点は,ResidueFuncにはドロップという概念があるのに,マトリックスではそのような概念が存在していないように見える点だ.ドロップは循環小数の固定部に関係しているような気がするが,ドロップが出てこないのは,マトリックスの対象をいまのところ素数に限定しているためかもしれない.

ResidueFuncのバリエーションをもうひとつ作って,N mod k をnとして与えた場合にどうなるかを見てみるというのがよいのではないか?ResidueFuncをマトリックスに移植してテストするより,剰余数列側で試した方が早い.ちゃんぽんになってしまうが,やってみることにしよう.ResidueFuncとResidueFunc2の比較ではおそらくcycleしか見ていないのだろう.⇒いや,「N mod k をnとして与えた場合」というのはすでにGoButtonでやっていることだ.冒頭でa=ModPow(n, p, k)を実行し,その値を使って,ResidueFunc(a, k, True)を実行している.つまり,ResidueFuncの対象値aはすでに剰余を取った値だ.

確かに,マトリックスの計算と剰余数列の計算は一致している.この計算にはBは関わっていないので,ψ値も計算されていない.また,循環小数とは異なり,「固定部」というのは出て来ない.k=24でドロップが発生した.N=2,i=48, cycle=2, x=2だ.どういう現象が起きているのか?Kを1から25まで変えてテストしてみた.K=9で発生する.開始番号Nを1~に変更したら,K-4で発生した.i=8, cycle=1, x=2だ.ドロップというのは,かなり限られた条件でしか起きていないようだ.

包括テストではGoButtonでやっているようなa=ModPow(n, p, k)の操作は行わず,直接numを対象にべき乗剰余を取っている.また,PsiFunctionでは(nとbが互いに素でない場合には)内部でResidueFuncを使って循環周期を求めている.ただし,ここではResidueFuncを呼び出しているだけで,その結果は反映されていない.つまり,未完ということのようだ.

ドロップが発生するのはkが合成数の場合に限られているというのは間違いない.k=1~25の範囲では,k=4, 8, 9, 12, 16, 18, 20, 24, 25で起きている.ドロップが起きていない数として,6, 10, 14, 15, 21, 22がある.おそらくドロップが起きる条件は素因数の積に指数が2以上のものが含まれるという点にあるように推定される.どこかでこのような条件を見たことがあるような気がするのだが,思い出せない.⇒以下の「ひとつ,おもしろいことを発見した」でそのことを述べている.

https://www.facebook.com/groups/2354748741306929/posts/6031847776930322/?comment_id=6046762375438862

引用しておこう.「べき乗の剰余数列は一般に周期性を持っているが,べき乗の剰余数列の初項とそれに続く項は周期数列から漏れ落ちる場合がある.このような項をドロップアウト項ないし落伍項と呼ぶことにする.①nとkが互いに素の場合には,落伍項は生じない.②kが素数の単純な積である場合にも落伍項は生じない,③kの素因数がべきになっている場合には落伍項が生じる.」

縦数列と横数列の転置に関わる混乱を整理

横が短いのか,縦が短いのかでぐらついていたが,横が短いというので正しいと思う.Fukuzo氏の京大後期試験の問題のコメントで一週間前となっているので,7日頃のものと思われるが,16×17というテーブルを提示している.この時期は,まだ縦・横を転置していなかったはずだ.

https://www.facebook.com/groups/2354748741306929/posts/6131697793611986/?comment_id=6136094699838962&reply_comment_id=6140540209394411

テーブルを転置したのはその後で,6日前となっているから,5月8日頃のことと思われる.

縦横の集計が剰余になっていない.ただ足しただけの数字を表示しているようだ.⇒修正していないつもりだが,正常動作するようになった.ビルドしていなかったのだろうか?

現行では,マトリックス,テーブルとも2kの範囲の剰余を単純に出力している.従って,配列サイズは動作に無関係.TestMatrixのコードではiがkまで,jがk-1となっているので,正しい.TestMatrixには混乱が見られる.これは,縦・横転置以前のコードが残っていたためではないか?⇒ようやくTestMatrixがまともに動くようになった.チェックポイントは以下の通り.

  1. s1, s2(異種文字数カウント用)配列はソート時の誤動作を避けるため0発進とする
  2. 配列の初期化でarray(s)としたときのsは配列サイズではなく,最大インデックスの意味.従って,サイズがk-1のときは,array(k-2)とする
  3. x(約数格納用)も0発進とする
  4. work(異種文字数カウント作業用)は1行/1列ごとにゼロクリアする 検定は縦軸もk-1の範囲とする(末尾の0は除外する)
  5. 文字数xGCMは k-1 に一致することを確認する
  6. 縦数列で尽数列でない場合で末尾が1の場合は回文となる
  7. ‘縦軸と横軸の異種文字数の分布は完全一致する(縦軸末尾の0を除き)

項5, 6, 7はほぼ確定しているが,なぜそうなるのかを追求する必要がある.異種文字数やGCMはマトリックス生成時に計算し,テーブルにも表示するようにする.つまり,TestMatrixの動作をBuildMatrixに組み込む.⇒k=10のときTestMatrixで停止する.項目5の「文字数xGCMは k-1 に一致」が成立していない.s=5,g=1,k-1=9だ.s1とs2の内容もまったく異なる.つまり,項5と7はkが素数の場合にしか成立しないように思われる.項6の回文性はkが非素数でも整列しているようだ.⇒暫定的にTestMatrixをDumpMatrixに先行して実行することとし,DumpMatrixでGCDとs1, s2をダンプするようにしてみよう.

べき剰余マトリックスのボタンを整理

まず,べき剰余マトリックスを少し整理して一つないし二つのボタンにまとめることにしよう.その後,画面を整えて,必要な情報が閲覧できるような状態にしたのち,移植という段取りで進めることにする.まず,ボタン1,Dump Matrix.これはDumpMatrixにR, G, Kのダンプを追加したものだ.DumpMatrixをこの関数で置き換えてもよい.この関数はCalcPoint(k)だ.CalcPointとDumpMatrixの大きな違いは,後者が生成済みのマトリックスのデータを使っているのにたいし,CalcPointでは自前で計算しているというところだ.前者が生値を使っているのに対し,後者は剰余になった小さい値のみを取り扱っている.マトリックスの立場は,すべての演算を剰余演算として完結するというものであるから,CalcPointのような計算は除去されるべきということになるのだが…

ここでは,この関数は形だけ温存し,処理の内容だけをDumpMatrixに移すことにする.つまり,G, R, Kの計算だ.GというのはGCMのことだ.(n, k-1)の値が出力されている.Rはsumのkによる剰余だ.Kは縦数列の和の剰余,Tはその総和だ.Tは縦と横で同じ値にならなくてはならないはずだが,現状では横では6,縦では5になっている.これは横ではmaxrangeの範囲を計算しているためだろう.縦横のサイズを一致させれば,多分この不一致は解消されるものと思われるが,計算範囲をどこまで取るか?というのが問題だ.kの範囲に限定するか,それともテーブルの実サイズに合わせるか?

行と列のそれぞれの項の和を取るというのは,発端となった京大の試験問題を引き摺っているためだが,それが果たして必要なのか不要なのかも考えなくてはならない.検算のために置くというのであれば,値はともあれ,縦横の合計が一致することを確認するだけでもよいということになるはずだが… ⇒とりあえず,ここは「検算のため」ということで残すことにしよう.GCMは後から必要になってくるので存続させる必要がある.この値はテーブルにも記載されるべきだろう.

CalcPointでは,nとkが互いに素の場合にはトータルの剰余Rがゼロとなることを仮定している.これは正しいか?⇒これは縦数列についての話と思われる.pが素数の場合,n^(p-1)≡0 mod pが成立するから,残余は1となり,Σ1=p-1になる.それ以外では0になる.これは,マトリックスの周期性を示す一つの証拠と認められるので検査する意義はあるように思われる.⇒これはマトリックスの周期性を解析するとき改めて確認することにする.ボタン2に移ろう.Power Sum Sequenceだ.CalcResidueという処理を呼び出している.

CalcPoint2という関数もあるが,いまは使われていない.CalcPoint3というのもあった.中間的な産物と思われるので,廃棄してもよいのではないか?CalcResidue2というのもある.これも廃棄でよさそうだ.CalcResidueではべき乗和を生値で蓄積して最後にk-1の剰余を取っている.この値はマトリックスのΣ値と一致しなくてはならないはずだが,一致しない.マトリックスでは{6. 0. 0. 0. 0. 0. 0}で,CalcResidueのm値は{1, 2, 3, 4, 5, 6, 0}だ.いや,違う.これは全然関係がない.CalcResidueではテキストボックスに入力された値をnとして,{i=1→k-1}i^nを計算している.しかも,これは累和(の剰余)をそのつど出力しているので,マトリックスの表示形式とはまったく違う.

これは言ってみれば,K=19と指定したマトリックスの19列目の一部を表示したものに過ぎない.あまり意味がないと考えられるので,廃止でよい.おそらく,テキストボックスのnを参照しているのはここだけと思われるが,ボックスを削除して確認しておく.⇒これでボタンは3つだけになった.2つ目のボタン Test Matrix は TestMatrix(k) を実行している.TestMatrixはとりあえず,Build Matrix ボタンでつねに実行するようにしておこう.そうすれば,ボタンを一つ減らせる.⇒いや,現状ですでにそうなっている.もう一つの All Prime Test というボタンは 2≦k≦1000の範囲内のすべての素数を検定するというだけのものだ.

All Prime Test がどこまで走るのかを見ておこう.現状kが260を超えると処理を打ち切るようになっている.ただし,遅くなるのはテーブル(九九表)を生成するためであり,処理はそこそこの時間で終わるはずだから,テーブルを生成しないようにすれば問題ないのではないか?いや,実際,TestMatrixにはテーブルは不要であり,これまではそれで動いていたはずだ.2~1000まではあっと言う間に終わる.10000まで試してみよう.⇒さすがに3000を超えると重くなる.⇒この機能を公開するとしたら,打ち切りボタンは必須だろう.しかし,1枚のテーブルくらいは何とかなりそうなので,その中の一行ないし一列を指定して表示するくらいのことはできるのではないか?テーブルもまったく作らないというのではなく,たとえば128x128までは見せるような仕様でもよいかもしれない.まぁ.64x64くらいが適切かもしれないが…

k=64で「奇数値を設定してください」が出た.TestMatrixでは除数が奇数でないとまずいところがあったかもしれない.制限なしでテストできるようにした方がよい.現行では指定したkの2x2のテーブルを作っているが,kxkに戻せばそれほどまでは時間は掛からないようになるだろう.先に一次元配列をゼロ発進に統一するというところを片付てしまおう.作業用に生成された一次元配列ではライブラリ関数などを使ってソートしているので,ゼロ発進にしておく必要がある.TestMatrixでやっていることを見てみよう.すべての一次元配列を対象とするのではなく,ソートが掛かるものに限定する.

Array.Sortが掛かるのは,s1とs2だけだ.s1とs2は約数を格納した配列だ.いや,違う.ここに入っているのは行と列の異種文字数だ.s1(0), s2(0)には0が入っているだけだから,影響ないのではないか?文字数カウントはworkに入っている.

どうも,まだ,縦横の関係が頭に入っていない.マトリックスはk-1xkとしているが,逆ではないか?横数列には短周期というのがあるが,縦数列にはそのようなものはないはずだ.横数列の長周期はp-1ではなかったか?また,縦数列の場合には,周期列に末尾の0を含めなくてはならないから,kになるのではないか?実際マトリックスを見てもそうなっている.つまり,短いのは横軸であり,縦軸がkで横軸がk-1のはずだ.壊しそうなので一度バックアップを取ってから考えた方がよい.

どうやってまとめればよいのか?

どうも,どうやってまとめればよいのか?整理が付かない.喜内の道具箱ではN,K,Bの3つのパラメータを扱っているが,KとBはどちらも剰余演算の除数となる数なので,その切り分けが不明確だ.循環小数を考えるときには基数Bは必須だが,べき乗剰余では不要なのでないか?やはり,まず,べき剰余マトリックスを仕上げるところから入った方が分かり易いような気がする.そのためには,k-1xkで十分であることをまず確認する必要がある.公開の前にまず,その辺りを固めておこう.