def test_mandel_transform(): assert np.isclose(chaos.Mandelbrot_disp(0,0,10,50,100).mandel_transform(lambda x,c: x**4-x**2+c**2)[10,10], 1.2833333333333332)
""" Creating the classic Mandelbrot set ====================================== """ ######################## # Some setup # -------------- import chaoseverywhere as chaos ################################## # Classic Mandelbrot # -------------------------------- # # First, let's compute the classic version of the mandelbrot set in black and white. # It is well known that the Mandelbrot set is contained in the origin disk of radius 2 :math:`D((0,0),2)`, so we just iterate the formula : # # .. math:: # # z_{n+1}=z_n^2+c,\ c\in\mathbb{C}, # # with :math:`z_0=0\in\mathbb{C}`. chaos.Mandelbrot_disp(0,0,2,t_max=150).disp_mandel()
def test_mandel(): test = chaos.Mandelbrot_disp(-.5, 0, 1,t_max=10,precision=20).mandelbrot() assert test[0,0] == True
def test_mandel_loop(): test = chaos.Mandelbrot_disp(-.5, 0, 1).mandel_loop()[0,0] assert np.isclose(test,1.5198773448773448)
# It is well known that the Mandelbrot set is contained in the origin disk of radius 2 :math:`D((0,0),2)`, so we just iterate the formula : # # .. math:: # # z_{n+1}=z_n^2+c,\ c\in\mathbb{C}, # # with :math:`z_0=0\in\mathbb{C}`. And the twist here is to change the value of the points whose modulus is beyond 2. Let's consider that we affect it with the value of the current iteration. # For that and because it can be time consuming to calculate the modulus of numbers in an array (mainly because of the square root), we use the formula : # # .. math:: # # \forall\ z \in\mathbb{C},\ |z|^2=z\bar{z}. # # And then, we don't compare it with 2, but :math:`2^2`. mandel = chaos.Mandelbrot_disp(0, 0, 2, t_max=150).mandel_loop(go_up=False) fig, ax = plt.subplots() pict = ax.imshow(mandel, cmap='cool') fig.colorbar(pict, extend='both') plt.show() ######################################## # A little better... # ------------------------- # # The issue here is that chosing the iteration number creates jumps that may be not the smoothest and because :math:`z_0=0` and some points take a lot of iterations to make the sequence diverge (the one near the boundary), the constrast is not really visible. # In order to correct that, we have a lot of choices, let's take :math:`\frac{1}{2+n}`, where :math:`n` is the current iteration of the sequence. # We can also see that the Mandelbrot set is symmetric with respect to the real axis. mandel = chaos.Mandelbrot_disp(0, 0, 2, t_max=150).mandel_loop(go_up=True) fig, ax = plt.subplots()
import chaoseverywhere as chaos import matplotlib.pyplot as plt import matplotlib.animation as animation ################################# # See a self-similar structure # ----------------------------------- # The Mandelbrot set is clearly not a self-similar object. But inside it, we can see structures repeating themselves. # plt.figure() plt.axis('off') plt.imshow(chaos.Mandelbrot_disp(-1, -.3, 0.4-110/300, t_max=100, precision=400).mandelbrot(), cmap='bone') plt.show() ###################################### # One way to animate a zoom # ----------------------------------- # # .. code-block:: python # # im_init = chaos.Mandelbrot_disp(-.5,0,1.5) # im_init = im_init.mandelbrot() # fig = plt.figure() # im = plt.imshow(im_init, cmap='bone', animated=True)
""" ######################## # Some setup # -------------- import matplotlib.pyplot as plt import chaoseverywhere as chaos ########################### # Sparsity # -------------------- # # The use of projecting non-zeros values over an area to determine its area is very well known (it's even how most of us learn the Monte-Carlo algorithm to calculate an approximation of pi). # Let's say someone needs to do the same process with the Mandelbrot set. Then, a simple way to graphically overset the two objets is like below. fig = plt.figure() mandel = chaos.Mandelbrot_disp(-.5, 0, 1.5).mandel_loop(go_up=True) plt.imshow(mandel, cmap='Spectral') chaos.sparse_matrix(400, 400, .02) plt.show() #################### # Some values # ---------------------- # It can be estimated that the Mandelbrot set has an area between :math:`1.50` and :math:`1.51`. # It was proved by Mitsuhiro Shishikura that the Haussdorf dimension of the boundary of the Mandelbrot set equals :math:`2`. # # #
# Before we begin, a reminder of the 2D convolution between two matrix can be useful. # In our case, we will use a :math:`3\times 3` kernel. So, the convolution of a kernel with a matrix is defined as the # sum of the conter-row-wise by row-wise product of the elements ie the last element of the kernel is multiplied by the first of the matrix, # the penultimate of the kernel (at the left of the last) is multiplied by the seconde one of the matrix (at the right of the first) and so # on from the antepenultimate to the first one. In a formula we have : # # .. math:: # # \begin{bmatrix} k_1 & k_2 & k_3 \\ k_4 & k_5 & k_6 \\ k_7 & k_8 & k_9 \\ \end{bmatrix} \star # \begin{bmatrix} c_1 & c_2 & c_3 \\ c_4 & c_5 & c_6 \\ c_7 & c_8 & c_9 \\ \end{bmatrix} = # k_1 c_9 + k_2c_8 + \dots + k_9c_1 # # There are mutliple ways to get the edges of a shape using this method. We chose to use a kernel with only :math:`-1` on its borders # and a value :math:`k_5=8=-\sum_{i=1,\ i\neq 5}^9 k_i`. We also need to pad the image in order to get all the pixels in it, and not # forget the borders. Let's take a look at the result. import chaoseverywhere as chaos import numpy as np import matplotlib.pyplot as plt from scipy.signal import convolve2d mandel = chaos.Mandelbrot_disp(-.5, 0, 1.5).mandelbrot() kernel_edge_detect = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]]) pad_mandel = np.pad(mandel, ((1, 1), (1, 1)), "maximum") bound = convolve2d(pad_mandel, kernel_edge_detect, mode='valid').astype(bool) * mandel plt.imshow(bound, cmap='bone') plt.axis('off') plt.show()
import os import sys sys.path.append( os.path.dirname(os.path.abspath(__file__)) + (os.path.sep + '..')) import chaoseverywhere as chaos chaos.Mandelbrot_disp(-.5, 0, 1, t_max=300).mandelbrot() chaos.Mandelbrot_disp(-.5, 0, 1, t_max=300).mandel_loop() chaos.bifurcation(show=False)