全てのseedを調べる。1番単純な力業。指定された個体値の条件が広い時は案外効率悪くないのかもしれない(そんなことはない)。1回の検索にかかる時間は一律で、判定処理2^32(約42億)回分。長い。
個体値から16bitの乱数値の内15bit上位bitが求まる。残り1bitは0,1のそれぞれを指定してやる必要があるが、HAB決定のseedからLCG1回回して上位16bitがSCDと一致すれば良いので、個体値1つ当たり2^17回ループを回すだけで済む。指定された個体値の個数が2^17個を超えない限り上よりも効率的。
◾️上の条件を更に考察してみる
本題。効率的になったとは言え、毎回n *2^17回ループ回すのはまだ非効率的。検索に時間がかかるとストレスがマッハで非人道的なので、更なる高速化を図る。
HAB, SCDを生成するseedをそれぞれr[n]=HAB<<16 +y r[n+1]=SCD<<16 +zと置く。HABとSCDからyを求められないか? と言う方針。前に書いたこれの考え方(上位と下位を分けて式変形)とか使えそうな気がする。
f(HAB<<16 +y) = SCD<<16 +z
0x41c64e6d *(HAB<<16+y)+0x6073=SCD<<16+z
f(y)=SCD<<16 +z -0x41c64e6d*HAB<<16
ここで右辺の0x41c64e6d*HAB<<16
は0x4e6d *HAB<<16に等しいことに注意すると、
f(y) =(SCD-0x4e6d *HAB)<<16 +z
zの値は個体値に関係無くf(y)の下位16bitに等しいので、問題になるのは両辺の上位16bitということになる。つまり、yの満たすべき条件はf(y)>>16 = (SCD-0x4e6d *HAB)&0xFFFFであるということがわかる。各SCD-0x4e6d *HABの値に対応するyがわかっていれば、指定された個体値を生成するseedを簡単に得ることができるのだ。
ではこれをどう求めれば良いのかというと、上手い方法が思いつかなかった。
現在は65536項のListの配列を用意し、起動時に各i(0≦i≦65565)についてk=f(i)>>16を計算して、配列のk番目にiをAddする方法を取っている。指定された個体値に対してk=SCD-0x4e6d *HABを計算すれば、配列のk番目に格納されたListを取り出すだけで目的のseedが得られるようになっている(もちろん存在しない場合や、複数存在する場合もある)。
こんな感じ。
実際速い。
◾️締まらない
これで生成開始seedはわかったわけだが、シンクロ有効個体については性格決定処理を考慮する必要があるし、与えられた消費数以内にこのseedを実現できる初期seedで起動時間等の条件をクリアするものを探さなければならない。しかしそこまで話を進めると長くなるので、一旦ここで終わることにする。
