用Python设置的简单Mandelbrot

时间:2017-07-28 16:06:34

标签: python numpy mandelbrot

我已经看过其他有关此事的问题,但我似乎无法弄清楚我哪里出错了。目标是“编写一个程序,通过对跨越-2≤x≤2和-2≤y的区域的N×N网格执行c = x + iy的所有值的迭代来制作Mandelbrot集的图像≤2。制作一个密度图,其中Mandelbrot集内的网格点为黑色,外部的网格点为白色。如果在Mandelbrot集合中,则当z'= z ^ 2 + c迭代时,z的大小永远不会大于2。

我的代码生成的网格几乎全黑,只有一小块白色。

from pylab import imshow,show,gray
from numpy import zeros,linspace

z = 0 + 0j
n=100

M = zeros([n,n],int)
xvalues = linspace(-2,2,n)
yvalues = linspace(-2,2,n)

for x in xvalues:
    for y in yvalues:
        c = complex(x,y)
        for i in range(100):
            z = z*z + c
            if abs(z) > 2.0:
                M[y,x] = 1
                break

imshow(M,origin="lower")
gray()
show()

对于任何未来的读者,以下是我的新代码最终的结果:

from pylab import imshow,show,gray
from numpy import zeros,linspace

n=1000

M = zeros([n,n],int)
xvalues = linspace(-2,2,n)
yvalues = linspace(-2,2,n)

for u,x in enumerate(xvalues):
    for v,y in enumerate(yvalues):
        z = 0 + 0j
        c = complex(x,y)
        for i in range(100):
            z = z*z + c
            if abs(z) > 2.0:
                M[v,u] = 1
                break

imshow(M,origin="lower")
gray()
show()

2 个答案:

答案 0 :(得分:2)

您的代码存在一些问题。

首先,您使用xvaluesyvalues来索引M,但这些索引应该是0 ..(n-1)范围内的像素索引整数。 Numpy会将xvaluesyvalues中的浮点数转换为整数,但结果数字将在-2..2中,因此不会绘制很多像素,图像会很小由于负索引在Python中的工作方式,你会得到包装。

获取所需像素索引的一种简单方法是使用内置的Python函数enumerate,但是可能有一种方法可以使用Numpy函数重新组织代码来执行此操作。

另一个问题是您需要为每个像素将z重置为零。目前,您的代码重复使用前一个像素的最后z,如果该像素位于Mandelbrot集中,那么z将会过大。

这是修复后的代码版本。我没有pylab,所以我用PIL编写了一个简单的位图查看器。您可以通过调用img.save(filename)函数中的show将图像保存到文件中; PIL将从文件扩展名中找出正确的文件格式。

import numpy as np
from PIL import Image

def show(data):
    img = Image.frombytes('1', data.shape[::-1], np.packbits(data, 1))
    img.show()

n = 100
maxiter = 100

M = np.zeros([n, n], np.uint8)
xvalues = np.linspace(-2, 2, n)
yvalues = np.linspace(-2, 2, n)

for u, x in enumerate(xvalues):
    for v, y in enumerate(yvalues):
        z = 0
        c = complex(x, y)
        for i in range(maxiter):
            z = z*z + c
            if abs(z) > 2.0:
                M[v, u] = 1
                break

show(M)

这是输出图像:

B&W Mandelbrot

当然,每当你发现自己在迭代Numpy数组索引时,这就表明你做错了。使用Numpy的要点是它可以通过在C速度内部迭代它们来同时对整个数组执行操作;上面的代码也可能使用普通的Python列表而不是Numpy数组。

这是一个让Numpy完成大部分循环的版本。它使用了更多的RAM,但它比以前的版本快了大约2.5倍,并且它有点短。

此代码使用多个2D数组。 c包含所有复杂的种子数,我们在z中执行核心Mandelbrot计算,该计算初始化为零。 mask是一个布尔数组,用于控制需要执行Mandelbrot计算的位置。其所有项目最初都设置为True,并且在每次迭代Truemask中与z中与Mandelbrot集合中转义的项目对应的项目设置为{ {1}}。

要测试某个点是否已转义,我们使用False而非z.real**2 + z.imag**2 > 4.0,这会节省一点时间,因为它可以避免昂贵的平方根计算和abs(z) > 2.0函数调用。

我们可以使用abs的最终值来绘制Mandelbrot集合,但为了使Mandelbrot中的点设置为黑色,我们需要反转其值,我们可以使用mask。< / p>

1 - mask

答案 1 :(得分:-1)

from pylab import imshow,show,gray
from numpy import zeros,linspace
N=1000
A=zeros([N+1,N+1],float)
def mandler(x,y):
    c=complex(x,y)
    z=c
    n=0
    while n<N:
        z=z*z+c
        if abs(z)>2:
            return 0
        n+=1
    else:
        return 1
for x in linspace(-2,2,N):
    for y in linspace(2,-2,N):
        a=mandler(x,y)
        s=int(((x+2)*N)/4)
        t=int(((y+2)*N)/4)
        A[s,t]=a
imshow(A)
gray()
show()