Mandelbrot and Julia sets#
Plots the Mandelbrot and Julia sets for general polynomial maps in the complex plane.
The Mandelbrot set is the set of complex numbers \(c\) for which the map \(f_c(z)\) does not diverge when iterated from \(z = 0\). This set of complex numbers can be visualized by plotting each value for \(c\) in the complex plane. The Mandelbrot set is often an example of a fractal when plotted in the complex plane. For general one parameter families of polynomials, the mandelbrot set is the parameter values for which the orbits of all critical points remains bounded.
The Julia set for a given parameter \(c\) is the set of complex numbers for which the function \(f_c(z)\) is bounded under iteration.
AUTHORS:
Ben Barros
- sage.dynamics.complex_dynamics.mandel_julia.external_ray(theta, **kwds)[source]#
Draws the external ray(s) of a given angle (or list of angles) by connecting a finite number of points that were approximated using Newton’s method. The algorithm used is described in a paper by Tomoki Kawahira.
REFERENCE:
INPUT:
theta
– double or list of doubles, angles between 0 and 1 inclusive.
kwds:
image
– 24-bit RGB image (default: None) user specified image of Mandelbrot set.D
– long (default:25
) depth of the approximation. AsD
increases, the external ray gets closer to the boundary of the Mandelbrot set. If the ray doesn’t reach the boundary of the Mandelbrot set, increaseD
.S
– long (default:10
) sharpness of the approximation. Adjusts the number of points used to approximate the external ray (number of points is equal toS*D
). If ray looks jagged, increaseS
.R
– long (default:100
) radial parameter. IfR
is large, the external ray reaches sufficiently close to infinity. IfR
is too small, Newton’s method may not converge to the correct ray.prec
– long (default:300
) specifies the bits of precision used by the Complex Field when using Newton’s method to compute points on the external ray.ray_color
– RGB color (default:[255, 255, 255]
) color of the external ray(s).
OUTPUT:
24-bit RGB image of external ray(s) on the Mandelbrot set.
EXAMPLES:
sage: external_ray(1/3) 500x500px 24-bit RGB image
>>> from sage.all import * >>> external_ray(Integer(1)/Integer(3)) 500x500px 24-bit RGB image
sage: external_ray(0.6, ray_color=[255, 0, 0]) 500x500px 24-bit RGB image
>>> from sage.all import * >>> external_ray(RealNumber('0.6'), ray_color=[Integer(255), Integer(0), Integer(0)]) 500x500px 24-bit RGB image
sage: external_ray([0, 0.2, 0.4, 0.7]) 500x500px 24-bit RGB image
>>> from sage.all import * >>> external_ray([Integer(0), RealNumber('0.2'), RealNumber('0.4'), RealNumber('0.7')]) 500x500px 24-bit RGB image
sage: external_ray([i/5 for i in range(1,5)]) 500x500px 24-bit RGB image
>>> from sage.all import * >>> external_ray([i/Integer(5) for i in range(Integer(1),Integer(5))]) 500x500px 24-bit RGB image
WARNING:
If you are passing in an image, make sure you specify which parameters to use when drawing the external ray. For example, the following is incorrect:
sage: M = mandelbrot_plot(x_center=0) # not tested sage: external_ray(5/7, image=M) # not tested 500x500px 24-bit RGB image
>>> from sage.all import * >>> M = mandelbrot_plot(x_center=Integer(0)) # not tested >>> external_ray(Integer(5)/Integer(7), image=M) # not tested 500x500px 24-bit RGB image
To get the correct external ray, we adjust our parameters:
sage: M = mandelbrot_plot(x_center=0) sage: external_ray(5/7, x_center=0, image=M) 500x500px 24-bit RGB image
>>> from sage.all import * >>> M = mandelbrot_plot(x_center=Integer(0)) >>> external_ray(Integer(5)/Integer(7), x_center=Integer(0), image=M) 500x500px 24-bit RGB image
Todo
The
copy()
function for bitmap images needs to be implemented in Sage.
- sage.dynamics.complex_dynamics.mandel_julia.julia_plot(f=None, **kwds)[source]#
Plots the Julia set of a given polynomial
f
. Users can specify whether they would like to display the Mandelbrot side by side with the Julia set with themandelbrot
argument. Iff
is not specified, this method defaults to \(f(z) = z^2-1\).The Julia set of a polynomial
f
is the set of complex numbers \(z\) for which the function \(f(z)\) is bounded under iteration. The Julia set can be visualized by plotting each point in the set in the complex plane. Julia sets are examples of fractals when plotted in the complex plane.ALGORITHM:
Let \(R_c = \bigl(1 + \sqrt{1 + 4|c|}\bigr)/2\) if the polynomial is of the form \(f(z) = z^2 + c\); otherwise, let \(R_c = 2\). For every \(p \in \mathbb{C}\), if \(|f^{k}(p)| > R_c\) for some \(k \geq 0\), then \(f^{n}(p) \to \infty\). Let \(N\) be the maximum number of iterations. Compute the first \(N\) points on the orbit of \(p\) under \(f\). If for any \(k < N\), \(|f^{k}(p)| > R_c\), we stop the iteration and assign a color to the point \(p\) based on how quickly \(p\) escaped to infinity under iteration of \(f\). If \(|f^{i}(p)| \leq R_c\) for all \(i \leq N\), we assume \(p\) is in the Julia set and assign the point \(p\) the color black.
INPUT:
f
– input polynomial (default:z^2 - 1
).period
– list (default:None
), returns the Julia set for a random \(c\) value with the given (formal) cycle structure.mandelbrot
– boolean (default:True
), when set toTrue
, an image of the Mandelbrot set is appended to the right of the Julia set.point_color
– RGB color (default:'tomato'
), color of the point \(c\) in the Mandelbrot set (any valid input for Color).x_center
– double (default:-1.0
), Real part of center point.y_center
– double (default:0.0
), Imaginary part of center point.image_width
– double (default:4.0
), width of image in the complex plane.max_iteration
– long (default:500
), maximum number of iterations the map \(f(z)\).pixel_count
– long (default:500
), side length of image in number of pixels.base_color
– hex color (default:'steelblue'
), color used to determine the coloring of set (any valid input for Color).level_sep
– long (default: 1), number of iterations between each color level.number_of_colors
– long (default: 30), number of colors used to plot image.interact
– boolean (default:False
), controls whether plot will have interactive functionality.
OUTPUT:
24-bit RGB image of the Julia set in the complex plane.
Todo
Implement the side-by-side Mandelbrot-Julia plots for general one-parameter families of polynomials.
EXAMPLES:
The default
f
is \(z^2 - 1\):sage: julia_plot() 1001x500px 24-bit RGB image
>>> from sage.all import * >>> julia_plot() 1001x500px 24-bit RGB image
To display only the Julia set, set
mandelbrot
toFalse
:sage: julia_plot(mandelbrot=False) 500x500px 24-bit RGB image
>>> from sage.all import * >>> julia_plot(mandelbrot=False) 500x500px 24-bit RGB image
sage: R.<z> = CC[] sage: f = z^3 - z + 1 sage: julia_plot(f) # long time 500x500px 24-bit RGB image
>>> from sage.all import * >>> R = CC['z']; (z,) = R._first_ngens(1) >>> f = z**Integer(3) - z + Integer(1) >>> julia_plot(f) # long time 500x500px 24-bit RGB image
To display an interactive plot of the Julia set in the Notebook, set
interact
toTrue
. (This is only implemented for polynomials of the formf = z^2 + c
):sage: julia_plot(interact=True) ...interactive(children=(FloatSlider(value=-1.0, description='Real c'... :: sage: R.<z> = CC[] sage: f = z^2 + 1/2 sage: julia_plot(f,interact=True) ...interactive(children=(FloatSlider(value=0.5, description='Real c'...
>>> from sage.all import * >>> julia_plot(interact=True) ...interactive(children=(FloatSlider(value=-1.0, description='Real c'... :: >>> R = CC['z']; (z,) = R._first_ngens(1) >>> f = z**Integer(2) + Integer(1)/Integer(2) >>> julia_plot(f,interact=True) ...interactive(children=(FloatSlider(value=0.5, description='Real c'...
To return the Julia set of a random \(c\) value with (formal) cycle structure \((2,3)\), set
period = [2,3]
:sage: julia_plot(period=[2,3]) 1001x500px 24-bit RGB image
>>> from sage.all import * >>> julia_plot(period=[Integer(2),Integer(3)]) 1001x500px 24-bit RGB image
To return all of the Julia sets of \(c\) values with (formal) cycle structure \((2,3)\):
sage: period = [2,3] # not tested ....: R.<c> = QQ[] ....: P.<x,y> = ProjectiveSpace(R,1) ....: f = DynamicalSystem([x^2+c*y^2, y^2]) ....: L = f.dynatomic_polynomial(period).subs({x:0,y:1}).roots(ring=CC) ....: c_values = [k[0] for k in L] ....: for c in c_values: ....: julia_plot(c)
>>> from sage.all import * >>> period = [Integer(2),Integer(3)] # not tested ... R = QQ['c']; (c,) = R._first_ngens(1) ... P = ProjectiveSpace(R,Integer(1), names=('x', 'y',)); (x, y,) = P._first_ngens(2) ... f = DynamicalSystem([x**Integer(2)+c*y**Integer(2), y**Integer(2)]) ... L = f.dynatomic_polynomial(period).subs({x:Integer(0),y:Integer(1)}).roots(ring=CC) ... c_values = [k[Integer(0)] for k in L] ... for c in c_values: ... julia_plot(c)
Polynomial maps can be defined over a polynomial ring or a fraction field, so long as
f
is polynomial:sage: R.<z> = CC[] sage: f = z^2 - 1 sage: julia_plot(f) 1001x500px 24-bit RGB image
>>> from sage.all import * >>> R = CC['z']; (z,) = R._first_ngens(1) >>> f = z**Integer(2) - Integer(1) >>> julia_plot(f) 1001x500px 24-bit RGB image
sage: R.<z> = CC[] sage: K = R.fraction_field(); z = K.gen() sage: f = z^2-1 sage: julia_plot(f) 1001x500px 24-bit RGB image
>>> from sage.all import * >>> R = CC['z']; (z,) = R._first_ngens(1) >>> K = R.fraction_field(); z = K.gen() >>> f = z**Integer(2)-Integer(1) >>> julia_plot(f) 1001x500px 24-bit RGB image
Interact functionality is not implemented if the polynomial is not of the form \(f = z^2 + c\):
sage: R.<z> = CC[] sage: f = z^3 + 1 sage: julia_plot(f, interact=True) Traceback (most recent call last): ... NotImplementedError: The interactive plot is only implemented for ...
>>> from sage.all import * >>> R = CC['z']; (z,) = R._first_ngens(1) >>> f = z**Integer(3) + Integer(1) >>> julia_plot(f, interact=True) Traceback (most recent call last): ... NotImplementedError: The interactive plot is only implemented for ...
- sage.dynamics.complex_dynamics.mandel_julia.kneading_sequence(theta)[source]#
Determines the kneading sequence for an angle theta in RR/ZZ which is periodic under doubling. We use the definition for the kneading sequence given in Definition 3.2 of [LS1994].
INPUT:
theta
– a rational number with odd denominator
OUTPUT:
a string representing the kneading sequence of theta in RR/ZZ
REFERENCES:
EXAMPLES:
sage: kneading_sequence(0) '*'
>>> from sage.all import * >>> kneading_sequence(Integer(0)) '*'
sage: kneading_sequence(1/3) '1*'
>>> from sage.all import * >>> kneading_sequence(Integer(1)/Integer(3)) '1*'
Since 1/3 and 7/3 are the same in RR/ZZ, they have the same kneading sequence:
sage: kneading_sequence(7/3) '1*'
>>> from sage.all import * >>> kneading_sequence(Integer(7)/Integer(3)) '1*'
We can also use (finite) decimal inputs, as long as the denominator in reduced form is odd:
sage: kneading_sequence(1.2) '110*'
>>> from sage.all import * >>> kneading_sequence(RealNumber('1.2')) '110*'
Since rationals with even denominator are not periodic under doubling, we have not implemented kneading sequences for such rationals:
sage: kneading_sequence(1/4) Traceback (most recent call last): ... ValueError: input must be a rational number with odd denominator
>>> from sage.all import * >>> kneading_sequence(Integer(1)/Integer(4)) Traceback (most recent call last): ... ValueError: input must be a rational number with odd denominator
- sage.dynamics.complex_dynamics.mandel_julia.mandelbrot_plot(f=None, **kwds)[source]#
Plot of the Mandelbrot set for a one parameter family of polynomial maps.
The family \(f_c(z)\) must have parent
R
of the formR.<z,c> = CC[]
.REFERENCE:
INPUT:
f
– map (default:z^2 + c
), polynomial family used to plot the Mandelbrot set.parameter
– variable (default:c
), parameter variable used to plot the Mandelbrot set.x_center
– double (default:-1.0
), Real part of center point.y_center
– double (default:0.0
), Imaginary part of center point.image_width
– double (default:4.0
), width of image in the complex plane.max_iteration
– long (default:500
), maximum number of iterations the mapf_c(z)
.pixel_count
– long (default:500
), side length of image in number of pixels.base_color
– RGB color (default:[40, 40, 40]
) color used to determine the coloring of set.level_sep
– long (default: 1) number of iterations between each color level.number_of_colors
– long (default: 30) number of colors used to plot image.interact
– boolean (default:False
), controls whether plot will have interactive functionality.
OUTPUT:
24-bit RGB image of the Mandelbrot set in the complex plane.
EXAMPLES:
sage: mandelbrot_plot() 500x500px 24-bit RGB image
>>> from sage.all import * >>> mandelbrot_plot() 500x500px 24-bit RGB image
sage: mandelbrot_plot(pixel_count=1000) 1000x1000px 24-bit RGB image
>>> from sage.all import * >>> mandelbrot_plot(pixel_count=Integer(1000)) 1000x1000px 24-bit RGB image
sage: mandelbrot_plot(x_center=-1.11, y_center=0.2283, image_width=1/128, # long time ....: max_iteration=2000, number_of_colors=500, base_color=[40, 100, 100]) 500x500px 24-bit RGB image
>>> from sage.all import * >>> mandelbrot_plot(x_center=-RealNumber('1.11'), y_center=RealNumber('0.2283'), image_width=Integer(1)/Integer(128), # long time ... max_iteration=Integer(2000), number_of_colors=Integer(500), base_color=[Integer(40), Integer(100), Integer(100)]) 500x500px 24-bit RGB image
To display an interactive plot of the Mandelbrot in the Notebook, set
interact
toTrue
. (This is only implemented forz^2 + c
):sage: mandelbrot_plot(interact=True) ...interactive(children=(FloatSlider(value=0.0, description='Real center', max=1.0, min=-1.0, step=1e-05), FloatSlider(value=0.0, description='Imag center', max=1.0, min=-1.0, step=1e-05), FloatSlider(value=4.0, description='Width', max=4.0, min=1e-05, step=1e-05), IntSlider(value=500, description='Iterations', max=1000), IntSlider(value=500, description='Pixels', max=1000, min=10), IntSlider(value=1, description='Color sep', max=20, min=1), IntSlider(value=30, description='# Colors', min=1), ColorPicker(value='#ff6347', description='Base color'), Output()), _dom_classes=('widget-interact',))
>>> from sage.all import * >>> mandelbrot_plot(interact=True) ...interactive(children=(FloatSlider(value=0.0, description='Real center', max=1.0, min=-1.0, step=1e-05), FloatSlider(value=0.0, description='Imag center', max=1.0, min=-1.0, step=1e-05), FloatSlider(value=4.0, description='Width', max=4.0, min=1e-05, step=1e-05), IntSlider(value=500, description='Iterations', max=1000), IntSlider(value=500, description='Pixels', max=1000, min=10), IntSlider(value=1, description='Color sep', max=20, min=1), IntSlider(value=30, description='# Colors', min=1), ColorPicker(value='#ff6347', description='Base color'), Output()), _dom_classes=('widget-interact',))
sage: mandelbrot_plot(interact=True, x_center=-0.75, y_center=0.25, ....: image_width=1/2, number_of_colors=75) ...interactive(children=(FloatSlider(value=-0.75, description='Real center', max=1.0, min=-1.0, step=1e-05), FloatSlider(value=0.25, description='Imag center', max=1.0, min=-1.0, step=1e-05), FloatSlider(value=0.5, description='Width', max=4.0, min=1e-05, step=1e-05), IntSlider(value=500, description='Iterations', max=1000), IntSlider(value=500, description='Pixels', max=1000, min=10), IntSlider(value=1, description='Color sep', max=20, min=1), IntSlider(value=75, description='# Colors', min=1), ColorPicker(value='#ff6347', description='Base color'), Output()), _dom_classes=('widget-interact',))
>>> from sage.all import * >>> mandelbrot_plot(interact=True, x_center=-RealNumber('0.75'), y_center=RealNumber('0.25'), ... image_width=Integer(1)/Integer(2), number_of_colors=Integer(75)) ...interactive(children=(FloatSlider(value=-0.75, description='Real center', max=1.0, min=-1.0, step=1e-05), FloatSlider(value=0.25, description='Imag center', max=1.0, min=-1.0, step=1e-05), FloatSlider(value=0.5, description='Width', max=4.0, min=1e-05, step=1e-05), IntSlider(value=500, description='Iterations', max=1000), IntSlider(value=500, description='Pixels', max=1000, min=10), IntSlider(value=1, description='Color sep', max=20, min=1), IntSlider(value=75, description='# Colors', min=1), ColorPicker(value='#ff6347', description='Base color'), Output()), _dom_classes=('widget-interact',))
Polynomial maps can be defined over a multivariate polynomial ring or a univariate polynomial ring tower:
sage: R.<z,c> = CC[] sage: f = z^2 + c sage: mandelbrot_plot(f) 500x500px 24-bit RGB image
>>> from sage.all import * >>> R = CC['z, c']; (z, c,) = R._first_ngens(2) >>> f = z**Integer(2) + c >>> mandelbrot_plot(f) 500x500px 24-bit RGB image
sage: B.<c> = CC[] sage: R.<z> = B[] sage: f = z^5 + c sage: mandelbrot_plot(f) # long time 500x500px 24-bit RGB image
>>> from sage.all import * >>> B = CC['c']; (c,) = B._first_ngens(1) >>> R = B['z']; (z,) = R._first_ngens(1) >>> f = z**Integer(5) + c >>> mandelbrot_plot(f) # long time 500x500px 24-bit RGB image
When the polynomial is defined over a multivariate polynomial ring it is necessary to specify the parameter variable (default parameter is
c
):sage: R.<a,b> = CC[] sage: f = a^2 + b^3 sage: mandelbrot_plot(f, parameter=b) # long time 500x500px 24-bit RGB image
>>> from sage.all import * >>> R = CC['a, b']; (a, b,) = R._first_ngens(2) >>> f = a**Integer(2) + b**Integer(3) >>> mandelbrot_plot(f, parameter=b) # long time 500x500px 24-bit RGB image
Interact functionality is not implemented for general polynomial maps:
sage: R.<z,c> = CC[] sage: f = z^3 + c sage: mandelbrot_plot(f, interact=True) Traceback (most recent call last): ... NotImplementedError: interact only implemented for z^2 + c
>>> from sage.all import * >>> R = CC['z, c']; (z, c,) = R._first_ngens(2) >>> f = z**Integer(3) + c >>> mandelbrot_plot(f, interact=True) Traceback (most recent call last): ... NotImplementedError: interact only implemented for z^2 + c