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

ニュートンフラクタル×マンデルブロ集合

    どうも、108Hassiumです。

    最近、こんなフラクタル図形を発見しました。

    画像

    z2+cz^2+cのマンデルブロ集合っぽいシルエットが見えますが、

    画像

    細部をよく見るとニュートンフラクタルのような複雑な模様が見えます。

    この記事では、このフラクタル図形の生成方法や関連するほかの図形を紹介します。

    生成方法

    あのフラクタル図形は、簡単にいうと「f10(z)f^{10}(z)のニュートンフラクタルのマンデルブロ集合」みたいなものです。

    ただし、

    •  f(z)=z2+cf(z)=z^2+c

    • fm(z)=f(f(f(…f(⏟mz)…)))f^m(z)=\underbrace{f(f(f(…f(}_mz)…)))

    です。

    もう少し正確に言うと、複素数ccに対して以下のような操作をしたものです。

    1. zn+1=zn−f10(zn)f10(zn)′,z0=cz_{n+1}=z_n-\frac{f^{10}(z_n)}{f^{10}(z_n)'},z_{0}=cという数列を計算する。

    2. znz_nとzn−1z_{n-1}の差が小さくなったら収束したと見做して、nnの値を使ってccを彩色する。

    ちなみに、fm(z)fm(z)′\frac{f^m(z)}{f^m(z)'}は以下の漸化式で求められます。

    am=12am−1+(2am−1−am−2)28cam−1,a0=z,a1=z2+c2za_{m}=\frac{1}{2}a_{m-1}+\frac{(2a_{m-1}-a_{m-2})^2}{8ca_{m-1}},a_0=z,a_1=\frac{z^2+c}{2z}

    ※この式の導出方法の説明は割愛します。

    Processingで実装したコードは以下の通りです。

    void setup(){
      size(2000,2000);
      background(0);
      noStroke();
      double x,y,px,py,cx,cy,ax,ay,pax,pay,ppax,ppay;
      boolean o;
      for(int a=0;a<2000;a++){
        for(int b=0;b<2000;b++){
          cx=(double)a/500.0-2.0;
          cy=(double)b/500.0-2.0;
          x=cx;
          y=cy;
          o=true;
          for(int c=0;c<5000000&&o;c++){
            px=x;
            py=y;
            pax=x;
            pay=y;
            ax=divx(x*x-y*y+cx,2.0*x*y+cy,2.0*x,2.0*y);
            ay=divy(x*x-y*y+cx,2.0*x*y+cy,2.0*x,2.0*y);
            for(int d=0;d<10;d++){
              ppax=pax;
              ppay=pay;
              pax=ax;
              pay=ay;
              ax=pax/2.0+divx((2.0*pax-ppax)*(2.0*pax-ppax)-(2.0*pay-ppay)*(2.0*pay-ppay),2.0*(2.0*pax-ppax)*(2.0*pay-ppay),cx*pax-cy*pay,cx*pay+cy*pax)/8.0;
              ay=pay/2.0+divy((2.0*pax-ppax)*(2.0*pax-ppax)-(2.0*pay-ppay)*(2.0*pay-ppay),2.0*(2.0*pax-ppax)*(2.0*pay-ppay),cx*pax-cy*pay,cx*pay+cy*pax)/8.0;
            }
            x=px-ax;
            y=py-ay;
            if((x-px)*(x-px)+(y-py)*(y-py)<1e-10){
              o=false;
              fill(cr(sqrt(c)*17.0),cr(sqrt(c)*18.0)/256.0,cr(sqrt(c)*19.0));
              rect(a,b,1,1);
            }
          }
        }
      }
    }
    
    float cr(float c){
      return (c%256)*(256-(c%256))/65;
    }
    
    double divx(double a,double b,double x,double y){
      return (a*x+b*y)/(x*x+y*y);
    }
    
    double divy(double a,double b,double x,double y){
      return (-a*y+b*x)/(x*x+y*y);
    }

    応用

    画像
    ☝f(z)=z^2+cのf^5(z)のニュートンフラクタルのマンデルブロ集合

    f(z)f(z)の計算回数を減らすと、z2+cz^2+cのマンデルブロ集合っぽさが薄まる代わりにニュートンフラクタルっぽい線のディティールが目立つようになります。

    画像
    ☝f(z)=z^2+0.25のf^5(z)のニュートンフラクタル
    画像
    ☝f(z)=z^2-0.1+0.7iのf^5(z)のニュートンフラクタル
    画像
    ☝f(z)=z^2-0.1+0.7iのf^10(z)のニュートンフラクタル

    コードを少し書き換えるだけで、ジュリア集合も描画できます。

    ちなみに上の3枚の画像では彩色方法も変えてあって、収束するまでの計算回数nnのほかに収束先の値の絶対値も色の決定に使っています。(パラメータは画像ごとに個別に微調整してあります)

    画像
    ☝f(z)=z^2+cのf^10(z)のニュートンフラクタルのマンデルブロ集合

    収束先の絶対値を使った彩色法をマンデルブロ集合の方に適用すると、ジュリア集合では見られなかった繊細で美しいグラデーションが現れます。

    しかし、生成された画像をnoteに貼り付けると、何故か上のようにグラデーションがガビガビに崩壊した汚い画像に変換されてしまいます。

    画像
    ☝f(z)=z^2+cのf^11(z)-zのニュートンフラクタルのマンデルブロ集合

    fm(z)−zf^{m}(z)-zの根(の内のmm個)は、z2+cz^2+cのジュリア集合のmm周期サイクルを構成する点になっています。

    なので「fm(z)−zf^{m}(z)-zのニュートンフラクタルを描画したらz2+cz^2+cのジュリア集合かマンデルブロ集合と関係ある特徴が現れるのでは?」ということを思いつき、fm(z)f^m(z)のやつよりも先にこっちを発見しました。

    この画像の描画には、以下の数列を利用しました。

    • an+1=bn2(an−z)2+(c−z)(an−bn)22bn(an−z)2−(an−bn)2a_{n+1}=\frac{b_n^2(a_n-z)^2+(c-z)(a_n-b_n)^2}{2b_n(a_n-z)^2-(a_n-b_n)^2}

    • bn+1=12bn+c(an−bn)22bn(an−z)2b_{n+1}=\frac{1}{2}b_n+\frac{c(a_n-b_n)^2}{2b_n(a_n-z)^2}

    私の計算が正しければ、an=fn(z)−zfn(z)′−1a_n=\frac{f^n(z)-z}{f^n(z)'-1}が成り立ちます。

    余談ですが、上記の数列を計算するコードを書くのがあまりにも面倒臭かったので、今まで使ったことが無かった「クラス」という機能の使い方をわざわざ調べました。(複素数の乗法・除法を愚直に書くとana_nの式はめちゃくちゃ長くなり、書き間違いが発生しやすいうえに間違っている場所を探すのが困難になります)

    画像
    ☝f(z)=z^2-0.4+0.6iのf^9(z)-zのニュートンフラクタル
    画像
    ☝f(z)=z^2+0.3のf^9(z)-zのニュートンフラクタル

    fm(z)f^m(z)のニュートンフラクタルは点対称でしたが、fm(z)−zf^m(z)-zだと非対称になるようです。

    画像
    ☝f(z)=z^2+cのf^5(z)のニュートンフラクタルのマンデルブロ集合(z_0=1)
    画像
    ☝f(z)=z^2+cのf^10(z)のニュートンフラクタルのマンデルブロ集合(z_0=1)
    画像
    ☝f(z)=z^2+cのf^5(z)のニュートンフラクタルのマンデルブロ集合(z_0=i)
    画像
    ☝f(z)=z^2+cのf^10(z)のニュートンフラクタルのマンデルブロ集合(z_0=i)

    同じ式でも初期値を変えると違うシルエットが現れるようです。

    「もしかして」と思って確認してみたところ、これらはそれぞれz0=1z_0=1とz0=iz_0=iとしたときのz2+cz^2+cのマンデルブロ集合とそっくりでした。

    画像
    ☝参考:z_0=1,iのz^2+cのマンデルブロ集合
    画像
    ☝f(z)=2z/3+1/(3z^2)のf^5(z)のニュートンフラクタルのマンデルブロ集合
    画像
    ☝f(z)=2z/3+1/(3z^2)+cのf^5(z)のニュートンフラクタルのマンデルブロ集合

    計算が楽な式は無いかと考え、Nova fractalの式を試してみました。

    ※☟Nova fractalの説明

    そもそも何故今までfm(z)f^m(z)とfm(z)′f^m(z)'を直接計算せずに面倒な漸化式を使っていたのかというと、直接計算すると大抵オーバーフローしてしまうからです。

    しかしf(z)=23z+13z2+cf(z)=\frac{2}{3}z+\frac{1}{3z^2}+cであれば、特異点をうっかり踏んだりしない限りオーバーフローの危険性は無いはずです。

    実際に生成された画像を見る限り発散している様子はないのですが、見た目はこれまでのものとは大きく違うものとなり、元のマンデルブロ集合のシルエットは現れませんでした。

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

    あなたへのおすすめ