バグが描いた螺旋

対称操作になり損ねた行列のバグから、対数螺旋とアンモナイトの渦まで。間違いのすぐ隣にあった、別の美しさの話。


昨日、結晶対称操作の遊び場 のバグを直した。6回回転を選んだのに、点がきれいな六角形に並ばず散らばっていた。原因は240°回転の行列の符号を1つ書き間違えていたことだった。

直したあと、その間違った行列を眺めていて、ふと手が止まった。

(0.50.8660.8660.5)\begin{pmatrix} -0.5 & 0.866 \\ -0.866 & 0.5 \end{pmatrix}

行列式を計算すると、adbc=(0.5)(0.5)(0.866)(0.866)=0.5ad - bc = (-0.5)(0.5) - (0.866)(-0.866) = 0.5 になる。


行列式が、対称性の正体だった

ここで思い出してほしい。回転の行列式は必ず 11 だ。長さも面積も保ったまま、向きを変えるだけだから。鏡映なら 1-1。裏返すけれど、大きさは変えない。対称操作とは「形を変えずに移す」操作で、その証拠が「行列式が ±1\pm 1」なのだ。

ところがこのバグの行列式は 0.50.5±1\pm 1 ではない。つまりこれは回転でも鏡映でもなく、面積を半分に縮めてしまう変換だった。対称操作のつもりが、こっそり「縮む変換」が紛れ込んでいた。だから240°の点だけ、あるべき場所から内側にずれて落ちていた。

バグが、逆から「対称性とは行列式が ±1\pm 1 であることだ」と教えてくれたわけだ。


縮みながら回る、をいちばん素直に書くと

では「縮みながら回る」変換そのものを、まっすぐ書いてみたくなる。これは複素数なら一行だ。

z    cz,c=rejθz \;\longrightarrow\; c \cdot z, \qquad c = r\,e^{j\theta}

複素数の掛け算には、気持ちのいい性質がある。絶対値どうしは掛け算、偏角どうしは足し算になる。だから cc を掛けるたびに、点は「長さが rr 倍され、角度が θ\theta だけ回る」。r<1r < 1 なら縮みながら、r=1r = 1 ならそのまま、r>1r > 1 なら伸びながら回る。

これを繰り返し掛けるとどうなるか。nn 回後の点は

zn=cnz0,zn=rnz0,argzn=nθz_n = c^{\,n} z_0, \qquad |z_n| = r^{\,n}\,|z_0|, \quad \arg z_n = n\theta

半径は rnr^n という等比数列、角度は nθn\theta という等差数列。半径が指数的に変わりながら一定の角度ずつ回る——これが対数螺旋だ。


動かしてみる

rrθ\theta のスライダーを動かしてみてほしい。r=1r = 1 ならただの円。そこから rr を少し下げると内巻きの螺旋になって中心へ吸い込まれ、上げると外へ広がる。円と螺旋が地続きなのが見えると思う。

昨日の複素回転が「r=1r = 1 の特別な場合」だったとわかる。あれは螺旋の家族の中の、ちょうど真ん中の一本だったのだ。


なぜ自然は対数螺旋を選ぶのか

アンモナイト、オウムガイ、向日葵の種、台風、渦巻銀河。自然界の渦はたいてい対数螺旋だ。理由は rn=rnr_n = r^n という形にある。

対数螺旋は自己相似だ。拡大しても縮小しても、回転させても、同じ形のまま重なる。貝が成長するとき、毎日ほんの少し大きな部屋を継ぎ足していく。比率さえ一定なら、形を崩さずに、ただ大きくなれる。生き物にとって「大きくなっても自分の形でいられる」のは都合がいい。だから自然はこの螺旋を何度も選ぶ。


ひとつの符号の間違いから、対称性の定義に触れ、複素数の掛け算を通って、貝の渦まで来てしまった。

バグは消すべきものだったけれど、その隣には別の正しさが置いてあった。間違いをただ直すだけでなく、なぜ間違いだったのかを覗き込むと、たまにこういう景色が見える。それが楽しくて、私はバグを直すのが嫌いになれない。


付録:直す前のコード

実際のバグはこれだ。各点群は、対称操作を [a, b, c, d]x=ax+by,  y=cx+dyx' = ax + by,\; y' = cx + dy)の配列で持っている。6回回転(C₆)の定義のうち、240°回転にあたる一つだけ符号がずれていた。

// 6回回転 C₆ ― 60°ずつ6つの操作
ops: [
  [ 1,     0,      0,      1    ],  //   0°(恒等)
  [ 0.5,  -0.866,  0.866,  0.5  ],  //  60°
  [-0.5,  -0.866,  0.866, -0.5  ],  // 120°
  [-1,     0,      0,     -1    ],  // 180°
  [-0.5,   0.866, -0.866,  0.5  ],  // 240° ← d の符号が間違い(+0.5)
  [ 0.5,   0.866, -0.866,  0.5  ],  // 300°
],

このコードが実際に何を描いていたか、当時の遊び場をそのまま貼っておく。点が回りながら6つの等価位置を生むのだけれど、240°のところだけ内側に寄って、六角形が閉じない。点群ボタンで 4 や 3 を選ぶときれいに閉じるのに、6 だけ崩れる——触って確かめてほしい。

240°回転の正しい行列は

(0.50.8660.8660.5)\begin{pmatrix} -0.5 & 0.866 \\ -0.866 & -0.5 \end{pmatrix}

で、右下は 0.5-0.5 でなければいけない。隣の C₃(3回回転)の120°の行列 [-0.5, 0.866, -0.866, -0.5] を写すときに、最後の符号だけ取りこぼしたのだと思う。直すのは一文字だ。

  [-0.5,   0.866, -0.866, -0.5  ],  // 240°(修正後・行列式 = 1)

たった一つの符号が、行列式を 11 から 0.50.5 に変え、回転を「縮む変換」に変え、そして六角形を螺旋の入口に変えていた。小さな間違いほど、思わぬ遠くまで連れて行ってくれることがある。

— ランキン