Mandelbrot Set(曼徳勃罗特集)是复平面上的点集,以法国数学家“分形学之父” Beno`t Mandelbrot命名,因其图像精妙无比,被称为“上帝的指纹”,Mandelbrot集中的点满足从原点开始按照下面公式迭代下去,其模始终有界
z n + 1 = f ( z n ) = z n 2 + c z_{n+1}=f(z_n)=z_n^2+c zn+1=f(zn)=zn2+c
用集合的形式表示为
M = { c ∈ C : ∣ f ( z n ) ∣ ≤ m , ∀ n ∈ N , ∃ m ∈ [ 0 , ∞ ) } M = \{ c \in \mathbb{C} : |f(z_n)| \leq m, \forall n \in \mathbb{N},\exists m\in[0,\infty) \} M={c∈C:∣f(zn)∣≤m,∀n∈N,∃m∈[0,∞)}
复平面中一个点 c 属于 Mandelbrot 集合,当且仅当对于给定的正数m,对所有的正整数n都满足 ∣ z n ∣ ≤ m |z_n|≤m ∣zn∣≤m,即由 z n z_n zn构成的下列数列
0 , f c ( 0 ) , f c ( f c ( 0 ) ) , f c ( f c ( f c ( 0 ) ) ) , … 0,f_c(0),f_c(f_c(0)),f_c(f_c(f_c(0))),\dots 0,fc(0),fc(fc(0)),fc(fc(fc(0))),…
= 0 , c , c 2 + c , ( c 2 + c ) 2 + c , [ ( c 2 + c ) 2 + c ] 2 + c , ⋯ =0,c,c^2+c,(c^2+c)^2+c,[(c^2+c)^2+c]^2+c,\cdots =0,c,c2+c,(c2+c)2+c,[(c2+c)2+c]2+c,⋯
或者收敛某个确定的值,或者变得无穷大,这与初始选择的参数 c有关,而曼德勃罗特就是由那些能够使得上面数列收敛的c构成。
为了让这个公式更加直观,我们举4个例子具体算一算,
首先取一个特殊的c=0,此时对任意的n, 都有 z n = 0 z_n=0 zn=0。
然后再取c=0.1,此时
z 0 = 0 z_0=0 z0=0
z 1 = z 0 2 + c = 0 2 + 0.1 = 0.1 z_1=z_0^2+c=0^2+0.1=0.1 z1=z02+c=02+0.1=0.1
z 2 = z 1 2 + c = 0. 1 2 + 0.1 = 0.11 z_2=z_1^2+c=0.1^2+0.1=0.11 z2=z12+c=0.12+0.1=0.11
z 3 = z 2 2 + c = 0.0 1 2 + 0.1 = 0.101 z_3=z_2^2+c=0.01^2+0.1=0.101 z3=z22+c=0.012+0.1=0.101
z 4 = z 3 2 + c = 0.00 1 2 + 0.1 = 0.1001 z_4=z_3^2+c=0.001^2+0.1=0.1001 z4=z32+c=0.0012+0.1=0.1001
随着n增大, z n z_n zn与0.1的差距越来越小,最后可以小于任意给定的正数。
然后取c=0.5时,则
z 0 = 0 z_0=0 z0=0
z 1 = z 0 2 + c = 0 2 + 0.5 = 0.5 z_1=z_0^2+c=0^2+0.5=0.5 z1=z02+c=02+0.5=0.5
z 2 = z 1 2 + c = 0. 5 2 + 0.5 = 0.75 z_2=z_1^2+c=0.5^2+0.5=0.75 z2=z12+c=0.52+0.5=0.75
z 3 = z 2 2 + c = 0.7 5 2 + 0.5 = 1.0625 z_3=z_2^2+c=0.75^2+0.5=1.0625 z3=z22+c=0.752+0.5=1.0625
z 4 = z 3 2 + c = 1.062 5 2 + 0.5 = 1.3789 z_4=z_3^2+c=1.0625^2+0.5=1.3789 z4=z32+c=1.06252+0.5=1.3789
随着n增大, z n z_n zn的模越来越大,而不可能小于给定的正数。
最后取一个复数c=1+i, 此时
z 0 = 0 z_0=0 z0=0
z 1 = z 0 2 + c = 0 2 + ( 1 + i ) = 1 + i z_1=z_0^2+c=0^2+(1+i)=1+i z1=z02+c=02+(1+i)=1+i
z 2 = z 1 2 + c = ( 1 + i ) 2 + ( 1 + i ) = 1 + 3 i z_2=z_1^2+c=(1+i)^2+(1+i)=1+3i z2=z12+c=(1+i)2+(1+i)=1+3i
z 3 = z 2 2 + c = ( 1 + 3 i ) 2 + ( 1 + i ) = − 7 + 7 i z_3=z_2^2+c=(1+3i)^2+(1+i)=-7+7i z3=z22+c=(1+3i)2+(1+i)=−7+7i
z 4 = z 3 2 + c = ( − 7 + 7 i ) 2 + ( 1 + i ) = 1 − 97 i z_4=z_3^2+c=(-7+7i)^2+(1+i)=1-97i z4=z32+c=(−7+7i)2+(1+i)=1−97i
随着n增大, z n z_n zn的模越来越大,而不可能小于给定的正数。
一般的,对于复数 c = a + b i c=a+bi c=a+bi,其中a是复数c的实部,b为c的虚部,i为虚数单位,对于不同的a和b, 对应复平面上不同的点,公式迭代结果也不一样。对于有些c,数列取值约束在某一范围内;而对于另一些c,数列取值则发散到无穷大。如果我们把那些使得数列取值在某一范围内的c值收集起来,让其点缀在复平面上就会构成我们想要的Mandlebrot集合。这个性质也特别适合让我们通过迭代来判断一个点是否不属于 Mandelbrot 集合。 先来一睹效果图
# -*- coding: utf-8 -*-
"""
Created on Thu Aug 22 22:01:29 2019
project name:Mandelbrot set
@author: 帅帅de三叔
"""
import numpy as np
import matplotlib.pyplot as plt
def iterator(c,r,max_iter):#定义逃逸时间函数,c为初始值,r为收敛半径,max_iter为最大迭代次数,返回逃逸时间
z=c #初始值
for iter in range(0,max_iter,1):
if abs(z)>r:break
z=z**2+c
return iter
def plot_mandelbrot(): #定义绘制mandelbrot图像
X=np.linspace(-1.75,1.05,5000) #实部范围,5000这个数要量力而行
Y=np.linspace(-1.25,1.25,5000) #虚部范围,5000这个数要量力而行
real,image=np.meshgrid(X, Y) #生成网格点坐标矩阵。
c=real+image*1j #构造复数
mandelbrot_set = np.frompyfunc(iterator, 3, 1)(c, 1.5, 100).astype(np.float) #frompyfunc(func, nin, nout),其中func是需要转换的函数,nin是函数的输入参数的个数,nout是此函数的返回值的个数,frompyfunc把Python里的函数(可以是自写的)转化成ufunc
plt.figure(dpi=600) #dpi设置分辨率尽可能高,细节显示更炫
plt.imshow(mandelbrot_set,extent=[-1.35, 1.35, -1.25, 1.25]) #extent用来调节显示框大小比例
#plt.axis('off') #是否显示坐标轴
plt.show()
if __name__=="__main__":
plot_mandelbrot()
在绘制Mandelbrot集主要使用逃逸时间算法,逃逸时间指的是在指定范围(这里r=1.5)进行有限迭代,而不超出该区域的次数。逃逸时间算法通过定义色彩控制球,给出一种绘制三维分形图的方法,对于确定区域内的迭代初始点,首先将动力系统的迭代逃逸点或者非逃逸点映射到色彩控制球内,然后计算映射点到球心的距离,以该距离为参数,经由色彩控制函数确定迭代初始点的色彩,再以该色彩绘制迭代初始点域中的嵌入体表面,从而得到具有伪三维效果的分形图。
延伸阅读 python画3维爱心