отображение набора Мандельброта в python с использованием matplotlib.pyplot и numpy - PullRequest
2 голосов
/ 29 февраля 2020

Я пытаюсь получить сюжет из набора Мандельброта, но у меня возникают проблемы с построением ожидаемого сюжета.

Как я понимаю, множество Мандельброта состоит из значений c, которые бы сходились, если бы повторялись с помощью следующего уравнения z = z ** 2 + c. Я использовал начальное значение z = 0.

Изначально я получал прямую линию. Я ищу решения онлайн, чтобы увидеть, где я ошибся. В частности, используя следующую ссылку, я попытался улучшить свой код:

https://scipy-lectures.org/intro/numpy/auto_examples/plot_mandelbrot.html

Вот мой улучшенный код. Я не очень понимаю причину использования np.newaxis и почему я строю окончательные значения z, которые сходятся. Я неправильно понимаю определение множества Мандельброта?

# initial values 
loop = 50 # number of interations
div = 600 # divisions
# all possible values of c
c = np.linspace(-2,2,div)[:,np.newaxis] + 1j*np.linspace(-2,2,div)[np.newaxis,:] 
z = 0 
for n in range(0,loop):
      z = z**2 + c

plt.rcParams['figure.figsize'] = [12, 7.5]
z = z[abs(z) < 2] # removing z values that diverge 
plt.scatter(z.real, z.imag, color = "black" ) # plotting points
plt.xlabel("Real")
plt.ylabel("i (imaginary)")
plt.xlim(-2,2)
plt.ylim(-1.5,1.5)
plt.savefig("plot.png")
plt.show()

и получил следующее изображение, которое выглядит ближе к набору Мандельброта, чем все, что я получил до сих пор. Но это больше похоже на звезду sh с разбросанными точками вокруг него. Изображение

Для справки, вот мой исходный код до улучшения:

# initial values 
loop = 50
div = 50
clist = np.linspace(-2,2,div) + 1j*np.linspace(-1.5,1.5,div) # range of c values 
all_results = []

for c in clist: # for each value of c
    z = 0 # starting point
    for a in range(0,loop): 
        negative = 0 # unstable

        z = z**2 + c 

        if np.abs(z) > 2: 
            negative +=1
        if negative > 2: 
            break

    if negative == 0:
        all_results.append([c,"blue"]) #converging
    else:
        all_results.append([c,"black"]) # not converging

Ответы [ 2 ]

3 голосов
/ 01 марта 2020

В качестве альтернативы, с другим небольшим изменением кода в вопросе, можно использовать значения z для раскрашивания графика. Можно сохранить значение n, когда абсолютное значение ряда становится больше 2 (что означает, что оно расходится), и закрасить точки за пределами набора Мандельброта:

import pylab as plt
import numpy as np
# initial values 
loop = 50 # number of interations
div = 600 # divisions
# all possible values of c
c = np.linspace(-2,2,div)[:,np.newaxis] + 1j*np.linspace(-2,2,div)[np.newaxis,:] 
# array of ones of same dimensions as c
ones = np.ones(np.shape(c), np.int)
# Array that will hold colors for plot, initial value set here will be
# the color of the points in the mandelbrot set, i.e. where the series
# converges.
# For the code below to work, this initial value must at least be 'loop'.
# Here it is loop + 5
color = ones * loop + 5
z = 0
for n in range(0,loop):
      z = z**2 + c
      diverged = np.abs(z)>2
      # Store value of n at which series was detected to diverge.
      # The later the series is detected to diverge, the higher
      # the 'color' value.
      color[diverged] = np.minimum(color[diverged], ones[diverged]*n)

plt.rcParams['figure.figsize'] = [12, 7.5]
# contour plot with real and imaginary parts of c as axes
# and colored according to 'color'
plt.contourf(c.real, c.imag, color)
plt.xlabel("Real($c$)")
plt.ylabel("Imag($c$)")
plt.xlim(-2,2)
plt.ylim(-1.5,1.5)
plt.savefig("plot.png")
plt.show()

Colorized Mandelbrot plot.

3 голосов
/ 01 марта 2020

График не выглядит правильным, потому что в коде в вопросе z (то есть повторяющаяся переменная). Итерируя z = z*z + c, множество Мандельброта задается теми действительными, воображаемыми парами частей c, для которых ряд не расходится. Следовательно, небольшое изменение кода, показанное ниже, дает правильный график Мандельброта:

import pylab as plt
import numpy as np
# initial values 
loop = 50 # number of interations
div = 600 # divisions
# all possible values of c
c = np.linspace(-2,2,div)[:,np.newaxis] + 1j*np.linspace(-2,2,div)[np.newaxis,:] 
z = 0 
for n in range(0,loop):
      z = z**2 + c

plt.rcParams['figure.figsize'] = [12, 7.5]
p = c[abs(z) < 2] # removing c values for which z has diverged 
plt.scatter(p.real, p.imag, color = "black" ) # plotting points
plt.xlabel("Real")
plt.ylabel("i (imaginary)")
plt.xlim(-2,2)
plt.ylim(-1.5,1.5)
plt.savefig("plot.png")
plt.show()

mandel output from above code

...