メインコンテンツへスキップ
見出し画像

無限周期ジュリア集合

    どうも、108Hassiumです。

    以前、以下の記事で「ccがz2+cz^2+cのマンデルブロ集合のフチの位置にあるとき、z2+cz^2+cのジュリア集合は特殊な性質を持つ」という話をしました。

    通常はzn+1=zn2+cz_{n+1}=z_n^2+cは無限大に発散しないときは周期数列に収束していくのに対し、ccがマンデルブロ集合のフチにあるときは非周期的になる、という話でした。

    画像
    ☝z_0=0,z_{n+1}=(z_n)^2+0.37+0.16iという数列の値が閉曲線上を非周期的に巡回する様子 (非周期的なので、曲線全体が点で埋め尽くされている)

    そして、以下の記事ではz2+cz^2+cのマンデルブロ集合のフチにある点の具体例を求める方法を解説しました。

    この記事では、特殊なジュリア集合の詳しい性質や、他の関数における例などを紹介したいと思います。

    ※以下、znz_nが非周期的になるジュリア集合を「無限周期ジュリア集合」と呼ぶことにします。また、ccがマンデルブロ集合の枝状の部分にあるときもznz_nは非周期的になりますが、この記事ではznz_nが閉曲線上を周回するようなものだけを無限周期ジュリア集合と呼ぶことにします。

    実例

    まず、今までnote上で扱ったことのある関数を中心に無限周期のジュリア集合の例を紹介します。

    画像
    ☝z^2-0.47+0.54iのジュリア集合
    画像
    ☝z^2-0.8+0.15iのジュリア集合

    z2+cz^2+cのジュリア集合のうち、ccの実部と虚部の桁数が2桁以下で無限周期になるものは以下の1624種類で全部だと思われます。

    • 0.37±0.16i

    • 0.33±0.06i

    • -0.23±0.64i

    • -0.47±0.54i

    • -0.76±0.07i

    • -0.8±0.15i

    • -0.85±0.2i

    • -0.93±0.24i

    • -1.07±0.24i

    • -1.15±0.2i

    • -1.2±0.15i

    • -1.24±0.07i

    前半の8つが中央のカージオイドのフチに、残りの8つ16個が左側にある円のフチに対応します。

    ※2023/07/06追記:円のフチの値に見落としがあったので訂正。(訂正部分は太字)

    画像
    ☝(0.28+0.96i)(z^3/3-z)のジュリア集合
    画像
    ☝(1.02+0.14i)(z^3/3-z)のジュリア集合
    画像
    ☝c(z^3/3-z)のマンデルブロ集合

    c(z33−z)c(\frac{z^3}{3}-z)のマンデルブロ集合は3つの大きな円を含むので、c(z2−z)c(z^2-z)と同様に無限周期ジュリア集合を簡単に見つけられます。

    画像
    ☝(0.1+0.3i)(z+1/z)
    画像
    ☝(0.6+0.8i)(z+1/z)
    画像
    ☝c(z+1/z)のマンデルブロ集合

    c(z+1z)c(z+\frac{1}{z})もc(z33−z)c(\frac{z^3}{3}-z)と同様に無限周期ジュリア集合を探しやすい関数ですが、ジュリア集合の見た目は大きく異なります。

    画像
    ☝(0.84+1.15i)/(z^2-1)+1のジュリア集合
    画像
    ☝(0.48+0.64)(z^5-1)のジュリア集合

    高周期ジュリア集合選手権のための調査では参加条件を満たす全てのジュリア集合の周期を機械的に計算するので、c(z33−z)c(\frac{z^3}{3}-z)やz2+cz^2+cのように探し方が確立されていなくても偶然により無限周期ジュリア集合(っぽいもの)が見つかることがあります。

    画像
    ☝(-0.4+0.8i)(z^2/2+1/z)のジュリア集合

    縞模様の密度が低い領域が混ざっていますが、これはc(z22+1z)c(\frac{z^2}{2}+\frac{1}{z})の「形状の異なる2つのサイクルが存在し得る」という性質と関係ありそうです。

    描画方法

    私が無限周期ジュリア集合を描画する際にいつも使っている赤黒い彩色方法は、以下のようなコードで出来ています。

    void setup(){
      size(2000,2000);
      background(0);
      noStroke();
      double x,y,px,py,cx,cy,v;
      boolean o;
      for(int a=0;a<2000;a++){
        for(int b=0;b<2000;b++){
          x=(double)a/500.0-2.0;
          y=(double)b/500.0-2.0;
          cx=0.28;
          cy=0.96;
          v=0;
          o=true;
          for(int c=1;c<5000&&o;c++){
            px=x;
            py=y;
            x=px*px-py*py+cx;
            y=2.0*px*py+cy;
            v=(v/((double)c))*((double)c-1.0)+((x-px)*(x-px)+(y-py)*(y-py))/((double)c);
            if(x*x+y*y>100){
              o=false;
              fill(cr(c*7),cr(c*8),cr(c*9));
              rect(a,b,1,1);
            }
          }
          if(o){
            fill(cr((float)v*5000),0,0);
            rect(a,b,1,1);
          }
        }
      }
    }
    
    float cr(float c){
      return (c%256)*(256-(c%256))/65;
    }

    ※言語はProcessing

    以下の記事で紹介したジュリア集合の描画コードと比べると変数名などが色々と違いますが、一番重要なのは"v"という変数です。

    コードの真ん中あたりでznz_nの計算をした後に何やら長い式を計算していますが、これは∣zn−zn−1∣2|z_{n}-z_{n-1}|^2の平均値です。

    ...
            v=(v/((double)c))*((double)c-1.0)+((x-px)*(x-px)+(y-py)*(y-py))/((double)c);
    ...

    znz_nを規定回数計算しても発散しなかった場合、vの値を使って彩色します。

    ...
          if(o){
            fill(cr((float)v*5000),0,0);
            rect(a,b,1,1);
          }
    ...

    ここでvに掛けている5000という値を変えると、縞模様の幅が変わります。

    画像
    ☝係数が1000のときと10000のとき

    ジュリア集合の種類によってちょうどいいパラメータは異なるので、試行錯誤でいい感じの値を探す必要があります。

    ちなみに、無限周期じゃない普通のジュリア集合にこの彩色方法を使うとこうなります。

    画像
    ☝z^2+0.3+0.5iのジュリア集合

    収束速度にもよりますが、あまりはっきりした模様は現れないようです。

    さて、無限周期ジュリア集合の彩色に適した方法として、こんなものもあります。

    void setup(){
      size(2000,2000);
      background(0);
      noStroke();
      double x,y,px,py,cx,cy,r;
      int rn;
      boolean o;
      for(int a=0;a<2000;a++){
        for(int b=0;b<2000;b++){
          x=(double)a/500.0-2.0;
          y=(double)b/500.0-2.0;
          cx=-0.47;
          cy=0.54;
          r=1e10;
          rn=0;
          o=true;
          for(int c=0;c<50000&&o;c++){
            px=x;
            py=y;
            x=px*px-py*py+cx;
            y=2.0*px*py+cy;
            if(x*x+y*y<r&&50000-100<c){
              r=x*x+y*y;
              rn=c;
            }
            if(x*x+y*y>100){
              o=false;
              fill(cr(c*7),cr(c*8),cr(c*9));
              rect(a,b,1,1);
            }
          }
          if(o){
            fill(cr(rn*9),cr(rn*9+85),cr(rn*9+170));
            rect(a,b,1,1);
          }
        }
      }
    }
    
    float cr(float c){
      return (c%256)*(256-(c%256))/65;
    }
    画像
    ☝z^2-0.47+0.54iのジュリア集合
    画像
    ☝z^2+0.33+0.06iのジュリア集合
    画像
    ☝(1.02+0.14)(z^3/3-z)のジュリア集合
    画像
    ☝(0.6+0.8i)(z+1/z)のジュリア集合

    znz_nの残りの計算回数が100未満になってから、∣zn∣2|z_n|^2が"r"より小さかったらrに∣zn∣2|z_n|^2の値を入れ、"rn"にその時のc(znz_nのnn)の値を入れるという動作を繰り返し、最終的にrnの値を使って彩色しています。

    ジーゲル円板

    Wikipediaを眺めていたら、こんなページを発見しました。

    冒頭の長文は置いといて、画像を見ると無限周期ジュリア集合と関係ある話をしていそうな気がしてきます。(赤黒の方の彩色法は、実はこのページの画像と説明を参考にしています)

    また、以下の記事でも「ジーゲル円板」という単語を扱っています。

    分からないなりに何とか解読を試みたところ、おおよそ以下のような話だろう、と理解しました。

    まず、全ての複素数はzn+1=f(zn)z_{n+1}=f(z_n)という数列を使って「f(z)f(z)のジュリア集合」と「f(z)f(z)のファトゥ集合」のどちらか一方の要素として分類することができます。

    ジュリア集合は「近くにある別の値を初期値にした時とznz_nの挙動が同じにならないようなz0z_0」の集合で、今まで私がジュリア集合と呼んできた図形のフチの部分を表すようです。

    ファトゥ集合は、ジュリア集合に含まれない複素数全体の集合です。

    例えばf(z)=z2+0.16+0.4if(z)=z^2+0.16+0.4iとすると、00はファトゥ集合に含まれます。

    何故なら以下のように、z0z_0のの値を00からほんの少しだけずらしたときの数列の挙動がz0=0z_0=0のときの挙動と一緒だからです。

    画像
    ☝z_0=0(橙)とz_0=0.01(青)のときの数列の挙動

    一方、1−0.4i1-0.4iはジュリア集合の方に入ります。

    z0=1−0.4iz_0=1-0.4iとするとznz_nは1−0.4i1-0.4iのまま一切変動しませんが、ほんの少しでもズレた値を初期値にするとズレがどんどん拡大していき、別の不動点に吸い込まれたり無限大に発散したりします。

    画像
    ☝z_0=1-0.4i(橙)とz_0=1.01-0.4i(青)のときの数列の挙動

    f(z)=z2+0.16+0.4if(z)=z^2+0.16+0.4iのファトゥ集合の成分は0.4i0.4iに収束するものと発散するものしかありませんが、他の関数では違う性質を持った成分が存在し、その一つが「ジーゲル円板」です。

    ざっくりいうと、(周期1の)ジーゲル円板は「znz_nがその領域の中にあるとき、znz_nがある1点を中心にして回転し続けるような挙動になる領域」を指すようです。

    例えば、f(z)=z2+0.33+0.06if(z)=z^2+0.33+0.06iとすると、znz_nは発散しなかった場合は0.4+0.3i0.4+0.3iの周りをぐるぐる回り続けるようになります。

    画像
    ☝f(z)=z^2+0.33+0.06iのときの、z_0=0(青)とz_0=0.2+0.2i(灰)とz_0=0.4+0.3i(橙)のときの数列の挙動

    なので、おそらくz2+0.33+0.06iz^2+0.33+0.06iのファトゥ集合はジーゲル円板を含んでいる、という事になると思います。

    ちなみに今までジーゲル円板を含むファトゥ集合を「無限周期」と呼んでいましたが、ジーゲル円板そのものにも(有限の)周期という概念があるようです。

    f(z)=z2+0.33+0.16if(z)=z^2+0.33+0.16iのときはznz_nは1個の環を描くように動いていましたが、f(z)=z2−0.8+0.15if(z)=z^2-0.8+0.15iは環が2つになります。

    画像
    ☝f(z)=z^2-0.8+0.15iのときの、z_0=0の数列の挙動

    これが「2周期のジーゲル円板」の特徴で、多分3周期以上も同様に環の数が増えていくんだと思います。(3周期のジーゲル円板は今のところ一切見たことが無いです)

    なお、ファトゥ成分の種類は他にもたくさんあるようで、分数関数でしか出てこない「エルマン環」、超越関数限定の「ベイカー領域」や「wandering domain」なんていうものもあるようですが、よくわからなかったので今回はスルーします。

    探し方

    ※ここからはジュリア集合の定義を従来のものに戻します。

    ある特定の関数f(c,z)f(c,z)(例えばz3+cz^3+c)に対して、f(α,z)f(\alpha,z)のジュリア集合が無限周期になるようなキリのいい定数α\alphaを見つけるのは困難です。

    ただし、「無限周期ジュリア集合を探すのが簡単で、f(c,z)f(c,z)と相似なジュリア集合しか生成しないg(c,z)g(c,z)」を作ることならできる場合があります。

    先程の「ジーゲル円板」のページには、以下のような記述が存在します。

    ジーゲル円板は、ファトゥ成分の分類によると、ファトゥ集合の連結成分の一つであり、無理中立な周期点の周りにおいて生じ得る。

    ジーゲル円板 - Wikipedia

    ここで、周期点が「無理中立」であるというのは多分以下のような意味です。(先程引用した部分の直前に説明があるのですが、長くて引用しにくいうえに肝心な部分が間違っているっぽいです)

    まず、fp(z0)=z0f^p(z_0)=z_0を満たすようなz0z_0に対して、(fp)′(z0)(f^p)'(z_0)(f(z)f(z)のpp重合成関数を微分してz0z_0を代入した値)をρ\rhoとします。

    そして、周期点z0z_0はρ\rhoの絶対値によって以下のように分類できます。

    • ∣ρ∣<1|\rho|<1:吸引的

    • ∣ρ∣=1|\rho|=1:中立的

    • 1<∣ρ∣1<|\rho|:反発的

    ※Wikipediaでは中立的であるための条件を「ρ=1\rho=1」と書いていますが、これは誤りだと判断しました。

    さらに、中立的な周期点のうちρn=1\rho^n=1となるような自然数nnが存在するものを「有理中立」、存在しないものを「無理中立」というそうです。

    例えば、f(z)=c(z33−z)f(z)=c(\frac{z^3}{3}-z)はz0=0z_0=0のときf(z0)=z0f(z_0)=z_0を満たします。

    このときf′(z0)=−cf'(z_0)=-cになるため、∣c∣=1|c|=1であればz0z_0は中立的な周期点(1周期なので不動点)になります。

    c=0.28+0.96c=0.28+0.96は∣c∣=1|c|=1で、なおかつ1の冪乗根ではないので、結果として(0.28+0.96i)(z33−z)(0.28+0.96i)(\frac{z^3}{3}-z)は既に紹介した通りジーゲル円板を持つことがわかります。

    画像
    ☝(0.28+0.96i)(z^3/3-z)のジュリア集合(再掲)

    さて、ここで話を戻します。

    「無限周期ジュリア集合を探すのが簡単で、f(c,z)f(c,z)と相似なジュリア集合しか生成しないg(c,z)g(c,z)」を作るには、f(c,z)f(c,z)を以下の条件を満たすように相似変換すればOKです。

    • g(c,0)=0g(c,0)=0

    • g′(c,z)=1g'(c,z)=1 ※zzで微分

    • g(c,z)=ch(z)g(c,z)=ch(z)を満たすような、ccに依存しない関数h(z)h(z)が存在する

    ※☟相似変換のやり方

    例えば、z3+cz^3+cを上手く変換するとc(z33−z2+z)c(\frac{z^3}{3}-z^2+z)という関数にできますが、これは3つ全ての性質を満たしています。

    そして、∣c∣=1|c|=1かつ1の冪乗根にならないようにccを設定すると、z3+cz^3+cのジュリア集合と同じく3回回転対称を持った無限周期ジュリア集合が生成されます。

    画像
    ☝(0.96+0.28i)(z^3/3-z^2+z)のジュリア集合

    ちなみに、c(z33−z2+z)c(\frac{z^3}{3}-z^2+z)のマンデルブロ集合はこんな形です。

    画像
    ☝c(z^3/3-z^2+z)のマンデルブロ集合(z_0=1)

    c(z33−z)c(\frac{z^3}{3}-z)と同様に、中央に半径1の円があります。

    他のパターンも試してみます。

    画像
    ☝c(z^7/7-z^6+3z^5-5z^4+5z^3-3z^2+z)のマンデルブロ集合(元はz^7+c)
    画像
    ☝(0.8+0.6i)(z^7/7-z^6+3z^5-5z^4+5z^3-3z^2+z)のジュリア集合
    画像
    ☝c(1/(2z^2-4z+2)-0.5)マンデルブロ集合(元は1/z^2+c)
    画像
    ☝(0.6+0.8i)(1/(2z^2-4z+2)-0.5)のジュリア集合

    なお、この方法は元の関数によってうまくいったりいかなかったりします。

    個人的には、元となる関数を変形していくよりは変形後の条件を満たす関数を適当に作って遊ぶ方が楽しいです。

    画像
    ☝c(z^2/4+1/(z-1)+1)のマンデルブロ集合(z_0=i)
    画像
    ☝(0.8+0.6i)(z^2/4+1/(z-1)+1)のジュリア集合
    画像
    ☝(-0.96+0.28i)(z^2/4+1/(z-1)+1)のジュリア集合

    さて、実はこんなことをしなくてもいい「無限周期ジュリア集合探し放題」な関数が見つかっています。

    画像
    ☝(-0.8+0.6i)(z+1/z)+cのマンデルブロ集合(z_0=1,x=-1~3,y=-2~2)
    画像
    ☝(-0.8+0.6i)(z+1/z)+2.2-1.6iのジュリア集合

    中央付近の四つ葉型の黒い領域は4周期の領域ですが、その外側は無限周期です。

    画像
    ☝z_{n+1}=(-0.8+0.6i)(z_n+1/z_n)+2.2-1.6iの、z_0=1(青)とz_0=-1(橙)のときの挙動
    画像
    ☝(-0.8+0.6i)(z+1/z)+1-iのジュリア集合
    画像
    ☝(-0.8+0.6i)(z+1/z)+3のジュリア集合

    どうやらc(z+1z)+dc(z+\frac{1}{z})+dという形の関数は、∣c∣=1|c|=1かつccが1の冪乗根でないとき、ddを適当に設定しても無限周期ジュリア集合が得られるボーナスタイム状態になるっぽいです。

    ちなみに、(−0.8+0.6i)(z+1z)+2.4−1.3i(-0.8+0.6i)(z+\frac{1}{z})+2.4-1.3iは無限周期領域に囲まれている内側の領域も無限周期になるようです。

    画像
    ☝(-0.8+0.6i)(z+1/z)+2.4-1.3iのジュリア集合

    こういったダブル無限周期ジュリア集合に関しては、簡単に見つけられるような方法はなさそうです。

    複素共役

    普通の複素関数f(z)f(z)を用いてf(con(z))f(\text{con}(z))(con(z)\text{con}(z)はzzの複素共役)と表せる関数の無限周期ジュリア集合については、どうやら今まで紹介してきたものとは事情が異なるようです。

    まず、c(con(z)+1con(z))c(\text{con}(z)+\frac{1}{\text{con}(z)})のマンデルブロ集合は以下のようになります。

    画像
    ☝c(con(z)+1/con(z))のマンデルブロ集合(z0=1,x=-2~2,y=-2~2)

    c(z+1z)c(z+\frac{1}{z})と同様に3つの円で構成されていますが、どうやらこの円のフチの値からは無限周期ジュリア集合は生成されないようです。

    画像
    ☝(0.8+0.6i)(con(z)+1/con(z))のジュリア集合
    画像
    ☝z_{n+1}=(0.8+0.6i)(con(z_n)+1/con(z_n))の、z_0=1のときの|z_n|^2の発散の様子(横軸が計算回数)

    ccが大きい円のフチにある場合、znz_nは非常にゆっくりと発散していくようです。

    画像
    ☝(0.3+0.9i)(con(z)+1/con(z))のジュリア集合
    画像
    ☝z_{n+1}=(0.3+0.9i)(con(z_n)+1/con(z_n))の、z_0=1のときの挙動

    小さい方の円のフチだと、非常にゆっくりと不動点や周期点に収束していくようです。

    ちなみにこのジュリア集合、赤黒じゃないほうの彩色法を使うとこうなります。

    画像

    どうやら赤黒の方で途切れている線を伸ばしたような模様になっているようですが、なぜこんな模様が現れるのかは謎です。

    さて、c(con(z)+1con(z))c(\text{con}(z)+\frac{1}{\text{con}(z)})のジュリア集合は無限周期にならないのかというと、全然そんなことはありません。

    画像
    ☝c(con(z)+1/con(z))のマンデルブロ集合(再掲)

    マンデルブロ集合の中央付近にある黒い部分の値を使うと、無限周期ジュリア集合が得られます。

    画像
    ☝(0.1+0.1i)(con(z)+1/con(z))のジュリア集合
    画像
    ☝(0.2+0.2i)(con(z)+1/con(z))のジュリア集合

    ただし、この無限周期ジュリア集合は今までのものとは少し違った特徴を持っています。

    まず、znz_nは2個の環を描くような挙動をするのですが、その2つの環は入れ子状の配置になります。

    画像
    ☝z_{n+1}=(0.1+0.1i)(con(z_n)+1/con(z_n))の、z_0=1のときの挙動
    画像
    ☝z_{n+1}=(0.2+0.2i)(con(z_n)+1/con(z_n))の、z_0=1のときの挙動

    そして、ジュリア集合の彩色方法を変えるとこんな見た目になります。

    画像
    ☝(0.1+0.1i)(con(z)+1/con(z))のジュリア集合
    画像
    ☝(0.2+0.2i)(con(z)+1/con(z))のジュリア集合

    縞模様が一点に集まる箇所が無く、かなり変わった見た目になりました。

    このような無限周期ジュリア集合は多項式関数を基にした関数では今のところ見たことは無いのですが、有理関数でならたまに見つかります。

    画像
    ☝c/(con(z)^2-1)+1のマンデルブロ集合(z_0=0,x=-1~3,y=-2~2)
    画像
    ☝0.1i/(con(z)^2-1)+1のジュリア集合
    画像
    ☝(0.4+0.1i)/(con(z)^2-1)+1のジュリア集合
    画像
    ☝c(con(z)^2/2+1/con(z))のマンデルブロ集合
    画像
    ☝(0.1+0.5i)(con(z)^2/2+1/con(z))のマンデルブロ集合
    画像
    ☝(0.1+0.1i)(con(z)^2/2+1/con(z))のマンデルブロ集合


     
     
    数学関係の記事を書きます。毎週日曜更新予定。

    あなたへのおすすめ