再谈Julia集与Mandelbrot集

    很早以前,我简单介绍过 Julia 集和 Mandelbrot 集,文章在此。这可以说是数学中最神秘、最令人敬畏的研究对象之一。不过,那时我对这个话题了解还不太深。今天见到这个网页,让我对 Julia 集和 Mandelbrot 集有了更深的了解。我查阅了一些其他的资料,然后写下这篇长文,与大家一同分享。继续阅读以前,建议先看看我原来那篇文章(很短),那里面有很多漂亮的 Julia 集和 Mandelbrot 集的图片,这篇文章就不再展示了。

 
    还是让我们先来简单复习一下复数吧。由于承认“负数也能开平方”将会带来很多幽雅和便利的结论,因此我们发明了虚数,用 i 来表示 -1 的平方根(即虚数单位),并把实数扩展为复数(即一切形如 a + b i 的数)。正如实数可以用数轴上的点来表示一样,复数可以用平面直角坐标系上的点来表示。令 x 轴表示复数的实数部分,令 y 轴表示复数的虚数部分,则 a + b i 就对应了平面上的点 (a, b) 。我们把这个平面直角坐标系叫做“复平面”。


    复数与复数之间不但可以相加相减,还可以相乘相除。(a + b i) + (c + d i) 就等于 (a + c) + (b + d) i ,而 (a + b i) (c + d i) 则等于 (ac – bd) + (bc + ad) i 。需要注意的是,我们不能讨论一个复数乘以另一个复数后是变大了还是变小了,因为复数根本没有大小之分。如果真的要比较它们的大小,我们可以比较它们的模。复数 a + b i 的模就是 a2 + b2 的平方根,也就是它到复平面原点的距离。如果我们用不同的颜色来表示不同大小的模,那么整个复平面大致就是这样:

      

    如果我们用 |z| 来表示复数 z 的模,那么上面这个图也就是函数 f(z) = |z| 的“等高线地图”。复数的模有一个重要的性质,大家可以自行验证:乘积的模等于模的乘积,即 |a·b| = |a|·|b| 。现在,我们对复平面上的所有点都进行平方,画出 f(z) = |z2| 的等高线地图:

      

    可以看到,这一操作让模的变化更剧烈了,等高线变得更加密集了。外面浩瀚的蓝色空间,就对应着那些模已经相当大了的复数。

    有趣的事情开始了。如果对上图中的每个点再加上某个数,比如 0.3 ,那么整个图会怎样变化呢?容易想到,对于模相同的复数来说,给实数部分加上 0.3 ,这对实数部分本来就较大的数影响会更大一些。因此,上图将会变得更扁,整个图形会在水平方向上压缩。这也就是 f(z) = |z2 + 0.3| 的等高线地形图:

      

    接下来,我们再对所得的图形进行平方,继续加剧模的变化:

      

    然后,再给每个点的实数部分加上 0.3 ,于是得到 f(z) = |(z2 + 0.3)2 + 0.3| 的图像:

      

    再平方:

      

    再加上 0.3 ,此时图形已经开始变得有意思起来了:

      

    再平方一次:

      

    再加上 0.3 :

      

    这也就是函数 f(z) = |(((z2 + 0.3)2 + 0.3)2 + 0.3)2 + 0.3| 的图像,它反映了对复平面上的各个复数“平方再加 0.3 ”迭代 4 次后模的大小情况。随着迭代次数的增加,整个图形将会变得越来越复杂。下图显示的就是迭代 12 次后的结果,可以看见整个图形已经具有了分形图形的复杂程度(图形的“黑边”其实是密集的等高线):

      

    上图中,大部分区域内的数都变得越来越大,直达无穷。而原点附近这个四叶草形区域内的数,至少目前还不算太大。这给出了上图的另外一种解读方法:随着迭代次数的增加,复平面上各个点的模的发散速度。有没有什么复数,随着迭代次数的增加,最终并不会趋于无穷呢?当然有。比如方程 z2 + 0.3 = z 的两个复数解,它是这个迭代下的不动点,每次迭代后都维持原来的值,自然不会趋于无穷。我们把所有这种迭代后不会趋于无穷的点所组成的集合就叫做 Julia 集,它是以法国数学家 Gaston Julia 命名的。只可惜, z → z2 + 0.3 的 Julia 集是由一些孤点组成的,我们无法把它画出来。上图中的四叶草形区域也只是那些发散比较慢的点,但再多迭代几次,最终也会趋于无穷。

 
 
    是否存在适当的常数 c ,使得迭代 z → z2 + c 的 Julia 集能够形成一块连通的区域呢?答案是肯定的。下图是对复平面上的点执行 12 次 z → z2 – 1 迭代后的结果,中间这些紫色和黄色的点已经稳定下来,不会发散了,它们构成了一块连通的 Julia 集:

      

    常数 c 还可以是复数。下图则是迭代过程 z → z2 + (0.2 + 0.5 i) 迭代 12 次的结果,其中也有一些模非常小的点,它们不会发散,构成了连通的 Julia 集:

      

    难以置信的是,每取一个不同的 c ,我们都能得到一个不同的 Julia 集,这些 Julia 集大小不同,形状各异,可谓是百花齐放,各有各的美丽。在我的那篇旧文章里,可以找到更多的 Julia 集图片。

 
 
    在 Julia 集相关领域中,有一个非常漂亮而且非常重要的定理叫做 fundamental dichotomy theorem ,它告诉我们,一个 Julia 集要么是完全连通的,任意两点间都有一条通路;要么是完全不连通的,整个图形全是一个个孤立的点。

    随着常数 c 的变化,对应的 Julia 集也会连续地发生变化。我们比较关心的一个问题就是,哪些 c 值会让对应的 Julia 集形成一个连通的区域?为了回答这个问题,让我们来看看 Julia 集的另外一种计算方法。

    在研究 Julia 集时,我们通常假设 c 的模总是小于 2 的。注意到,对任意一个满足 |z| > 2 的复数 z ,都有 |z2| = |z|2 > 2·|z| ,也就是说,对这样的 z 进行平方后,它的模至少都会变成原来的两倍。即使常数 c 的方向和 z2 的方向完全相反,也不足以把 z2 的模抵消到原来的水平。因此,在迭代运算过程中,一旦某一步结果的模大于 2 了,可以断定它必将发散到无穷。

    因此,我们有了 Julia 集合的另一个定义。 z → z2 + c 对应的 Julia 集,就是无限迭代下去后模仍然不超过 2 的点。于是,我们立即有了 Julia 集的另一种生成方法。我们可以从复平面上模不超过 2 的所有点,也就是以原点为中心半径为 2 的圆盘出发,看看哪些点的平方加 c 后会落在这个圆盘内,进而考察哪些点平方加 c 再平方加 c 后将会落在这个圆盘内,如此反向迭代,不断找出原象,反推出符合要求的点集。我们先用 c = -1 来试验一下。

    这就是复平面上模小于 2 的所有复数所组成的点集,即一个半径为 2 的圆盘:

      

    我们把上图右移一个单位,得到所有加上 -1 后模小于 2 的点:

      

    我们再找出上图区域中的每个点的平方根(别忘了,每个数都有两个平方根,因此每个点都有两个原象),于是得到所有平方再加 -1 后模仍然小于 2 的点。由于开平方是一个连续函数,而每个点都有一正一负两个平方根,因此整个图像本该变为两个关于原点对称的连通区域。不过,这两个连通区域有所重合,它们将会并在一起成为一整块连通区域。为了看出这一点,只需要注意到,0 是一个非常特殊的数,它的原象只有一个,就是它本身。由于上图中的区域内包含零点,因此它的两组原象也都包含原点,这就表明两个区域是有重合的,结果就像下图这样:

      

    再将上图右移一个单位:

      

    再作出平方根:

      

    再次右移:

      

    再次找平方根,由于零点始终没有跑出去,因此图像始终是一整块连通区域:

      

    再次右移:

      

    再次找平方根,图像仍然连通:

      

    可以看到,此时得到的点集已经非常接近之前给出的 z → z2 – 1 的 Julia 集了。下图则是反推 12 次后的结果,它基本上可以看作是 z → z2 – 1 的 Julia 集了:

      

    让我们再来看一个无法构成连通区域的 Julia 集的例子。取 c = – 1 – 0.9 i ,让我们来看看逆推的过程。还是先画出半径为 2 的圆盘:

      

    现在,找出所有加上 – 1 – 0.9 i 后会落进该圆盘的点,实际上相当于把圆盘右移 1 个单位,再上移 0.9 个单位:

      

    寻找上图中的点的平方根:

      

    再平移:

      

    再找平方根:

      

    再次平移:

      

    这里发生了一个非常值得注意的现象:原点现在跑到了灰色区域的外边。也就是说,这个点在若干次迭代之后不能落入那个半径为 2 的圆盘里,表明这个点的模最终将会发散。换句话说, 0 不属于 c = – 1 – 0.9 i 时的 Julia 集。

    由于 0 的原象还是 0 ,因此当我们考察哪些点的平方会落入上图中的区域时,0 继续排除在外。此时注意,灰色区域内不包含原点,说明这个图形不见得仍然连通了。事实上,我们可以证明,一个不包含原点的区域,开平方后必然会得到两块不连通的区域。为了证明这一点,我们在上图中画一条过原点的回路,把整个图形围起来。对这个回路上的所有点开平方后,将会得到一个过原点的、关于原点对称的封闭曲线。容易想到,这条闭曲线一定是一个 8 字形。而上图灰色区域的两个原象,则只能分居在 8 字形的两个圆圈中:

      

    我们把上图再次平移:

      

    再取平方根。注意到,上图中的两块区域都不含零点,因此由前面的结论,每个区域都将会再分成两个更小的连通区域,从而使得整个图中出现四个连通块:

      

    如此逆推下去,连通块的数量将会越来越多,它们的总面积则会越来越小,最后就只剩下一些孤立的点了,就如同我们最早所说的 z → z2 + 0.3 的 Julia 集一样。只不过,要想看出 z → z2 + 0.3 所对应的 Julia 集并不连通,我们需要的逆推次数更多一些。下图中可以看到,直到第 12 次逆推,零点仍然还在候选区域中;到了第 13 次逆推,才把零点排除在 Julia 集之外。此后,图形很快便收缩为了一堆离散的点。

      

 
 
    也就是说,为了判断 z → z2 + c 的 Julia 集是否连通,我们只需要测试一下,看对初始值 0 迭代无穷多次,所得的模是否会趋于无穷大。我们自然希望知道,能够使 Julia 集连通的常数值 c 在复平面上组成了一个什么样的图形。为此,我们只需要固定初始值为 0 ,把复平面上不同的点当作 c ,画出迭代过程中模的发散速度(和最开始制作 Julia 集一样,我们用不同的颜色来表示不同的发散速度):

      

    神奇的是,这本身竟然又是一个漂亮的分形图形!数学家 Benoît B. Mandelbrot 是最早对其进行系统研究的人之一,因此我们就把所有不会让零点发散的复数 c 组成的集合叫做 Mandelbrot 集。更多 Mandelbrot 集细节的惊人图片,也可以参见那篇老文章。整个 Mandelbrot 集可以包含于一个以原点为圆心,半径为 2 的圆里。这也就是我们在考虑 Julia 集时往往假设常数 c 的模小于 2 的原因。

    生成 Mandelbrot 集的算法和生成 Julia 集的算法完全一样,只是这一次我们固定的是初始值,而把 c 当作了变量。Mandelbrot 集内的每一个点就对应了一个连通的 Julia 集,Mandelbrot 集合外的点则对应了不连通的 Julia 集,并且很容易想到,越靠近 Mandelbrot 集的边界,对应的 Julia 集形状就越诡异。因此, Mandelbrot 集还有另外一种解读方法:它就是 Julia 集的缩略图!完全没有比喻的意思,它真的就是 Julia 集的缩略图:

      

    因此, Mandelbrot 集可以说是所有无穷多个 Julia 集的一个高度总结。究其原因,还是因为 Julia 集的零点太重要了。Julia 集的零点的迭代结果,很大程度上决定了 Julia 集的形状,就好像这个零点“知道” Julia 集是什么样子似的。而 Mandelbrot 集则把所有的零点信息都汇聚在了一起,自然高度归纳出了所有的 Julia 集。

 
 
    让我们总结一下 Julia 集和 Mandelbrot 集的关系。在迭代过程 z → z2 + c 中,我们有四个参数: z 的初始值的实部、虚部,以及 c 的实部、虚部。 Julia 集就是给定 c 的实部、虚部后所得的结果,而 Mandelbrot 集则是限定 z 的实部和虚部均为 0 后的结果。大家可能想到,任意限定其中两个参数,把另外两个参数当作变量,我们还能得到很多不同的图形。事实上,如果把所有不同的 Julia 集重合起来,我们将会得到一个四维图形,它的其中两个维度是不同的初始值 z 构成的复平面,另外两个维度则是不同的常数 c 构成的复平面。这个四维空间就包含了所有不同的初始值在所有不同的常数 c 之下迭代的发散情况。而 Mandelbrot 集,则是这个四维图形在 c = 0 处的一个切片,并且是最具有概括力的一个切片。

    因此,我们相当于有了 Mandelbrot 集的一个四维扩展,从这个四维图形中,我们可以切出很多二维的或者三维的切片,得到更多惊人而漂亮的图形。Mandelbrot 集还有另外一种高维扩展,即用四元数 a + b i + c j + d k 来代替复数,从而得到另一种四维 Mandelbrot 集。可惜,这些扩展都是四维的,我们只能从它们的切片中获取三维图形。要想欣赏真正的三维版 Mandelbrot 集,我们还得想想别的方法。数学家们创造了很多漂亮的三维版 Mandelbrot 集,不过它们的定义有些生硬,并不自然。另外还有一个叫做 Multibrot 集的东西,它就是把 Mandelbrot 集产生规则中的 z2 一般化,用 zn 代替。随着 n 的连续变化, Multibrot 集也会连续地变化。如果把不同 n 所对应的 Multibrot 集重叠在一起,我们就会得到一个三维图形(如下图, n 从 1 取到 5 )。这也勉强算得上是 Mandelbrot 的三维扩展吧。

      

    Gaston Julia 和 Benoît B. Mandelbrot 两人的研究并未就此结束,这一系列研究直接导致了复动力学(complex dynamics)这一新学科的诞生。如果大家对这个感兴趣的话,不妨从 Wikipedia 相关页面的 references 出发,深入阅读下去。

36 条评论

发表评论