passagemath-symbolics 10.6.40__cp314-cp314t-macosx_13_0_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-symbolics might be problematic. Click here for more details.
- passagemath_symbolics/.dylibs/libgmp.10.dylib +0 -0
- passagemath_symbolics/__init__.py +3 -0
- passagemath_symbolics-10.6.40.dist-info/METADATA +187 -0
- passagemath_symbolics-10.6.40.dist-info/RECORD +172 -0
- passagemath_symbolics-10.6.40.dist-info/WHEEL +6 -0
- passagemath_symbolics-10.6.40.dist-info/top_level.txt +3 -0
- sage/all__sagemath_symbolics.py +17 -0
- sage/calculus/all.py +14 -0
- sage/calculus/calculus.py +2826 -0
- sage/calculus/desolvers.py +1866 -0
- sage/calculus/predefined.py +51 -0
- sage/calculus/tests.py +225 -0
- sage/calculus/var.cpython-314t-darwin.so +0 -0
- sage/calculus/var.pyx +401 -0
- sage/dynamics/all__sagemath_symbolics.py +6 -0
- sage/dynamics/complex_dynamics/all.py +5 -0
- sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-314t-darwin.so +0 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1035 -0
- sage/ext/all__sagemath_symbolics.py +1 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/ext_data/magma/latex/latex.m +1021 -0
- sage/ext_data/magma/latex/latex.spec +1 -0
- sage/ext_data/magma/sage/basic.m +356 -0
- sage/ext_data/magma/sage/sage.spec +1 -0
- sage/ext_data/magma/spec +9 -0
- sage/geometry/all__sagemath_symbolics.py +8 -0
- sage/geometry/hyperbolic_space/all.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_coercion.py +743 -0
- sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2409 -0
- sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
- sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1082 -0
- sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
- sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
- sage/geometry/riemannian_manifolds/all.py +7 -0
- sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
- sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
- sage/interfaces/all__sagemath_symbolics.py +1 -0
- sage/interfaces/magma.py +3017 -0
- sage/interfaces/magma_free.py +92 -0
- sage/interfaces/maple.py +1397 -0
- sage/interfaces/mathematica.py +1345 -0
- sage/interfaces/mathics.py +1312 -0
- sage/interfaces/sympy.py +1398 -0
- sage/interfaces/sympy_wrapper.py +197 -0
- sage/interfaces/tides.py +938 -0
- sage/libs/all__sagemath_symbolics.py +6 -0
- sage/manifolds/all.py +7 -0
- sage/manifolds/calculus_method.py +555 -0
- sage/manifolds/catalog.py +437 -0
- sage/manifolds/chart.py +4019 -0
- sage/manifolds/chart_func.py +3419 -0
- sage/manifolds/continuous_map.py +2183 -0
- sage/manifolds/continuous_map_image.py +155 -0
- sage/manifolds/differentiable/affine_connection.py +2475 -0
- sage/manifolds/differentiable/all.py +1 -0
- sage/manifolds/differentiable/automorphismfield.py +1383 -0
- sage/manifolds/differentiable/automorphismfield_group.py +604 -0
- sage/manifolds/differentiable/bundle_connection.py +1445 -0
- sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
- sage/manifolds/differentiable/chart.py +1241 -0
- sage/manifolds/differentiable/curve.py +1028 -0
- sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
- sage/manifolds/differentiable/degenerate.py +559 -0
- sage/manifolds/differentiable/degenerate_submanifold.py +1671 -0
- sage/manifolds/differentiable/diff_form.py +1658 -0
- sage/manifolds/differentiable/diff_form_module.py +1062 -0
- sage/manifolds/differentiable/diff_map.py +1315 -0
- sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
- sage/manifolds/differentiable/examples/all.py +1 -0
- sage/manifolds/differentiable/examples/euclidean.py +2517 -0
- sage/manifolds/differentiable/examples/real_line.py +897 -0
- sage/manifolds/differentiable/examples/sphere.py +1186 -0
- sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
- sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
- sage/manifolds/differentiable/integrated_curve.py +4035 -0
- sage/manifolds/differentiable/levi_civita_connection.py +841 -0
- sage/manifolds/differentiable/manifold.py +4254 -0
- sage/manifolds/differentiable/manifold_homset.py +1826 -0
- sage/manifolds/differentiable/metric.py +3032 -0
- sage/manifolds/differentiable/mixed_form.py +1507 -0
- sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
- sage/manifolds/differentiable/multivector_module.py +800 -0
- sage/manifolds/differentiable/multivectorfield.py +1520 -0
- sage/manifolds/differentiable/poisson_tensor.py +268 -0
- sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
- sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
- sage/manifolds/differentiable/scalarfield.py +1343 -0
- sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
- sage/manifolds/differentiable/symplectic_form.py +910 -0
- sage/manifolds/differentiable/symplectic_form_test.py +220 -0
- sage/manifolds/differentiable/tangent_space.py +412 -0
- sage/manifolds/differentiable/tangent_vector.py +616 -0
- sage/manifolds/differentiable/tensorfield.py +4665 -0
- sage/manifolds/differentiable/tensorfield_module.py +963 -0
- sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
- sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
- sage/manifolds/differentiable/vector_bundle.py +1728 -0
- sage/manifolds/differentiable/vectorfield.py +1717 -0
- sage/manifolds/differentiable/vectorfield_module.py +2445 -0
- sage/manifolds/differentiable/vectorframe.py +1832 -0
- sage/manifolds/family.py +270 -0
- sage/manifolds/local_frame.py +1490 -0
- sage/manifolds/manifold.py +3090 -0
- sage/manifolds/manifold_homset.py +452 -0
- sage/manifolds/operators.py +359 -0
- sage/manifolds/point.py +994 -0
- sage/manifolds/scalarfield.py +3718 -0
- sage/manifolds/scalarfield_algebra.py +629 -0
- sage/manifolds/section.py +3111 -0
- sage/manifolds/section_module.py +831 -0
- sage/manifolds/structure.py +229 -0
- sage/manifolds/subset.py +2764 -0
- sage/manifolds/subsets/all.py +1 -0
- sage/manifolds/subsets/closure.py +131 -0
- sage/manifolds/subsets/pullback.py +885 -0
- sage/manifolds/topological_submanifold.py +891 -0
- sage/manifolds/trivialization.py +733 -0
- sage/manifolds/utilities.py +1348 -0
- sage/manifolds/vector_bundle.py +1342 -0
- sage/manifolds/vector_bundle_fiber.py +332 -0
- sage/manifolds/vector_bundle_fiber_element.py +111 -0
- sage/matrix/all__sagemath_symbolics.py +1 -0
- sage/matrix/matrix_symbolic_dense.cpython-314t-darwin.so +0 -0
- sage/matrix/matrix_symbolic_dense.pxd +6 -0
- sage/matrix/matrix_symbolic_dense.pyx +1022 -0
- sage/matrix/matrix_symbolic_sparse.cpython-314t-darwin.so +0 -0
- sage/matrix/matrix_symbolic_sparse.pxd +6 -0
- sage/matrix/matrix_symbolic_sparse.pyx +1029 -0
- sage/modules/all__sagemath_symbolics.py +1 -0
- sage/modules/vector_callable_symbolic_dense.py +105 -0
- sage/modules/vector_symbolic_dense.py +116 -0
- sage/modules/vector_symbolic_sparse.py +118 -0
- sage/rings/all__sagemath_symbolics.py +4 -0
- sage/rings/asymptotic/all.py +6 -0
- sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
- sage/rings/asymptotic/asymptotic_ring.py +4858 -0
- sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4153 -0
- sage/rings/asymptotic/growth_group.py +5373 -0
- sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
- sage/rings/asymptotic/term_monoid.py +5237 -0
- sage/rings/function_field/all__sagemath_symbolics.py +2 -0
- sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
- sage/symbolic/all.py +15 -0
- sage/symbolic/assumptions.py +985 -0
- sage/symbolic/benchmark.py +93 -0
- sage/symbolic/callable.py +459 -0
- sage/symbolic/complexity_measures.py +35 -0
- sage/symbolic/constants.py +1287 -0
- sage/symbolic/expression_conversion_algebraic.py +310 -0
- sage/symbolic/expression_conversion_sympy.py +317 -0
- sage/symbolic/expression_conversions.py +1713 -0
- sage/symbolic/function_factory.py +355 -0
- sage/symbolic/integration/all.py +1 -0
- sage/symbolic/integration/external.py +270 -0
- sage/symbolic/integration/integral.py +1115 -0
- sage/symbolic/maxima_wrapper.py +162 -0
- sage/symbolic/operators.py +267 -0
- sage/symbolic/random_tests.py +462 -0
- sage/symbolic/relation.py +1907 -0
- sage/symbolic/ring.cpython-314t-darwin.so +0 -0
- sage/symbolic/ring.pxd +5 -0
- sage/symbolic/ring.pyx +1396 -0
- sage/symbolic/subring.py +1025 -0
- sage/symbolic/symengine.py +19 -0
- sage/symbolic/tests.py +40 -0
- sage/symbolic/units.py +1470 -0
|
@@ -0,0 +1,765 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
r"""
|
|
3
|
+
Mandelbrot and Julia sets
|
|
4
|
+
|
|
5
|
+
Plots the Mandelbrot and Julia sets for general polynomial maps in the complex
|
|
6
|
+
plane.
|
|
7
|
+
|
|
8
|
+
The Mandelbrot set is the set of complex numbers `c` for which the map
|
|
9
|
+
`f_c(z)` does not diverge when iterated from `z = 0`. This set of complex
|
|
10
|
+
numbers can be visualized by plotting each value for `c` in the complex plane.
|
|
11
|
+
The Mandelbrot set is often an example of a fractal when plotted in the complex
|
|
12
|
+
plane. For general one parameter families of polynomials, the mandelbrot set
|
|
13
|
+
is the parameter values for which the orbits of all critical points remains
|
|
14
|
+
bounded.
|
|
15
|
+
|
|
16
|
+
The Julia set for a given parameter `c` is the set of complex numbers for which
|
|
17
|
+
the function `f_c(z)` is bounded under iteration.
|
|
18
|
+
|
|
19
|
+
AUTHORS:
|
|
20
|
+
|
|
21
|
+
- Ben Barros
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
#*****************************************************************************
|
|
25
|
+
# Copyright (C) 2017 BEN BARROS <bbarros@slu.edu>
|
|
26
|
+
#
|
|
27
|
+
# This program is free software: you can redistribute it and/or modify
|
|
28
|
+
# it under the terms of the GNU General Public License as published by
|
|
29
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
30
|
+
# (at your option) any later version.
|
|
31
|
+
# http://www.gnu.org/licenses/
|
|
32
|
+
#*****************************************************************************
|
|
33
|
+
|
|
34
|
+
from sage.misc.lazy_import import lazy_import
|
|
35
|
+
lazy_import("sage.plot.colors", "Color")
|
|
36
|
+
lazy_import("sage.repl.image", "Image")
|
|
37
|
+
from sage.functions.log import logb
|
|
38
|
+
from sage.functions.other import floor
|
|
39
|
+
from sage.rings.rational_field import QQ
|
|
40
|
+
from sage.rings.cc import CC
|
|
41
|
+
from sage.rings.complex_double import CDF
|
|
42
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
43
|
+
from sage.schemes.projective.projective_space import ProjectiveSpace
|
|
44
|
+
from sage.misc.prandom import randint
|
|
45
|
+
from sage.calculus.var import var
|
|
46
|
+
from sage.rings.fraction_field import FractionField_generic
|
|
47
|
+
from sage.categories.function_fields import FunctionFields
|
|
48
|
+
|
|
49
|
+
lazy_import('sage.dynamics.arithmetic_dynamics.generic_ds', 'DynamicalSystem')
|
|
50
|
+
lazy_import('sage.dynamics.complex_dynamics.mandel_julia_helper', (
|
|
51
|
+
'fast_mandelbrot_plot',
|
|
52
|
+
'fast_external_ray',
|
|
53
|
+
'convert_to_pixels',
|
|
54
|
+
'get_line',
|
|
55
|
+
'fast_julia_plot',
|
|
56
|
+
'general_julia',
|
|
57
|
+
'polynomial_mandelbrot',
|
|
58
|
+
'julia_helper'
|
|
59
|
+
))
|
|
60
|
+
|
|
61
|
+
EPS = 0.00001
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def mandelbrot_plot(f=None, **kwds):
|
|
65
|
+
r"""
|
|
66
|
+
Plot of the Mandelbrot set for a one parameter family of polynomial maps.
|
|
67
|
+
|
|
68
|
+
The family `f_c(z)` must have parent ``R`` of the
|
|
69
|
+
form ``R.<z,c> = CC[]``.
|
|
70
|
+
|
|
71
|
+
REFERENCE:
|
|
72
|
+
|
|
73
|
+
[Dev2005]_
|
|
74
|
+
|
|
75
|
+
INPUT:
|
|
76
|
+
|
|
77
|
+
- ``f`` -- map (default: ``z^2 + c``); polynomial family used to
|
|
78
|
+
plot the Mandelbrot set
|
|
79
|
+
|
|
80
|
+
- ``parameter`` -- variable (default: ``c``); parameter variable
|
|
81
|
+
used to plot the Mandelbrot set
|
|
82
|
+
|
|
83
|
+
- ``x_center`` -- double (default: ``-1.0``); Real part of center
|
|
84
|
+
point
|
|
85
|
+
|
|
86
|
+
- ``y_center`` -- double (default: ``0.0``); Imaginary part of
|
|
87
|
+
center point
|
|
88
|
+
|
|
89
|
+
- ``image_width`` -- double (default: ``4.0``); width of image
|
|
90
|
+
in the complex plane
|
|
91
|
+
|
|
92
|
+
- ``max_iteration`` -- long (default: ``500``); maximum number of
|
|
93
|
+
iterations the map ``f_c(z)``
|
|
94
|
+
|
|
95
|
+
- ``pixel_count`` -- long (default: ``500``); side length of
|
|
96
|
+
image in number of pixels
|
|
97
|
+
|
|
98
|
+
- ``base_color`` -- RGB color (default: ``[40, 40, 40]``); color
|
|
99
|
+
used to determine the coloring of set
|
|
100
|
+
|
|
101
|
+
- ``level_sep`` -- long (default: 1); number of iterations
|
|
102
|
+
between each color level
|
|
103
|
+
|
|
104
|
+
- ``number_of_colors`` -- long (default: 30); number of colors
|
|
105
|
+
used to plot image
|
|
106
|
+
|
|
107
|
+
- ``interact`` -- boolean (default: ``False``); controls whether
|
|
108
|
+
plot will have interactive functionality
|
|
109
|
+
|
|
110
|
+
OUTPUT: 24-bit RGB image of the Mandelbrot set in the complex plane
|
|
111
|
+
|
|
112
|
+
EXAMPLES:
|
|
113
|
+
|
|
114
|
+
::
|
|
115
|
+
|
|
116
|
+
sage: mandelbrot_plot() # needs sage.plot
|
|
117
|
+
500x500px 24-bit RGB image
|
|
118
|
+
|
|
119
|
+
::
|
|
120
|
+
|
|
121
|
+
sage: mandelbrot_plot(pixel_count=1000) # needs sage.plot
|
|
122
|
+
1000x1000px 24-bit RGB image
|
|
123
|
+
|
|
124
|
+
::
|
|
125
|
+
|
|
126
|
+
sage: mandelbrot_plot(x_center=-1.11, y_center=0.2283, # long time, needs sage.plot
|
|
127
|
+
....: image_width=1/128, max_iteration=2000,
|
|
128
|
+
....: number_of_colors=500, base_color=[40, 100, 100])
|
|
129
|
+
500x500px 24-bit RGB image
|
|
130
|
+
|
|
131
|
+
To display an interactive plot of the Mandelbrot in the Notebook, set
|
|
132
|
+
``interact`` to ``True``. (This is only implemented for ``z^2 + c``)::
|
|
133
|
+
|
|
134
|
+
sage: mandelbrot_plot(interact=True) # needs sage.plot
|
|
135
|
+
...interactive(children=(FloatSlider(value=0.0, description='Real center', max=1.0, min=-1.0, step=1e-05),
|
|
136
|
+
FloatSlider(value=0.0, description='Imag center', max=1.0, min=-1.0, step=1e-05),
|
|
137
|
+
FloatSlider(value=4.0, description='Width', max=4.0, min=1e-05, step=1e-05),
|
|
138
|
+
IntSlider(value=500, description='Iterations', max=1000),
|
|
139
|
+
IntSlider(value=500, description='Pixels', max=1000, min=10),
|
|
140
|
+
IntSlider(value=1, description='Color sep', max=20, min=1),
|
|
141
|
+
IntSlider(value=30, description='# Colors', min=1),
|
|
142
|
+
ColorPicker(value='#ff6347', description='Base color'), Output()),
|
|
143
|
+
_dom_classes=('widget-interact',))
|
|
144
|
+
|
|
145
|
+
::
|
|
146
|
+
|
|
147
|
+
sage: mandelbrot_plot(interact=True, x_center=-0.75, y_center=0.25, # needs sage.plot
|
|
148
|
+
....: image_width=1/2, number_of_colors=75)
|
|
149
|
+
...interactive(children=(FloatSlider(value=-0.75, description='Real center', max=1.0, min=-1.0, step=1e-05),
|
|
150
|
+
FloatSlider(value=0.25, description='Imag center', max=1.0, min=-1.0, step=1e-05),
|
|
151
|
+
FloatSlider(value=0.5, description='Width', max=4.0, min=1e-05, step=1e-05),
|
|
152
|
+
IntSlider(value=500, description='Iterations', max=1000),
|
|
153
|
+
IntSlider(value=500, description='Pixels', max=1000, min=10),
|
|
154
|
+
IntSlider(value=1, description='Color sep', max=20, min=1),
|
|
155
|
+
IntSlider(value=75, description='# Colors', min=1),
|
|
156
|
+
ColorPicker(value='#ff6347', description='Base color'), Output()),
|
|
157
|
+
_dom_classes=('widget-interact',))
|
|
158
|
+
|
|
159
|
+
Polynomial maps can be defined over a multivariate polynomial ring or a
|
|
160
|
+
univariate polynomial ring tower::
|
|
161
|
+
|
|
162
|
+
sage: R.<z,c> = CC[]
|
|
163
|
+
sage: f = z^2 + c
|
|
164
|
+
sage: mandelbrot_plot(f) # needs sage.plot
|
|
165
|
+
500x500px 24-bit RGB image
|
|
166
|
+
|
|
167
|
+
::
|
|
168
|
+
|
|
169
|
+
sage: B.<c> = CC[]
|
|
170
|
+
sage: R.<z> = B[]
|
|
171
|
+
sage: f = z^5 + c
|
|
172
|
+
sage: mandelbrot_plot(f) # long time # needs sage.plot
|
|
173
|
+
500x500px 24-bit RGB image
|
|
174
|
+
|
|
175
|
+
When the polynomial is defined over a multivariate polynomial ring it is
|
|
176
|
+
necessary to specify the parameter variable (default parameter is ``c``)::
|
|
177
|
+
|
|
178
|
+
sage: R.<a,b> = CC[]
|
|
179
|
+
sage: f = a^2 + b^3
|
|
180
|
+
sage: mandelbrot_plot(f, parameter=b) # long time # needs sage.plot
|
|
181
|
+
500x500px 24-bit RGB image
|
|
182
|
+
|
|
183
|
+
Interact functionality is not implemented for general polynomial maps::
|
|
184
|
+
|
|
185
|
+
sage: R.<z,c> = CC[]
|
|
186
|
+
sage: f = z^3 + c
|
|
187
|
+
sage: mandelbrot_plot(f, interact=True) # needs sage.plot
|
|
188
|
+
Traceback (most recent call last):
|
|
189
|
+
...
|
|
190
|
+
NotImplementedError: interact only implemented for z^2 + c
|
|
191
|
+
"""
|
|
192
|
+
parameter = kwds.pop("parameter", None)
|
|
193
|
+
x_center = kwds.pop("x_center", 0.0)
|
|
194
|
+
y_center = kwds.pop("y_center", 0.0)
|
|
195
|
+
image_width = kwds.pop("image_width", 4.0)
|
|
196
|
+
max_iteration = kwds.pop("max_iteration", None)
|
|
197
|
+
pixel_count = kwds.pop("pixel_count", 500)
|
|
198
|
+
level_sep = kwds.pop("level_sep", 1)
|
|
199
|
+
number_of_colors = kwds.pop("number_of_colors", 30)
|
|
200
|
+
interacts = kwds.pop("interact", False)
|
|
201
|
+
base_color = kwds.pop("base_color", Color('tomato'))
|
|
202
|
+
# Check if user specified maximum number of iterations
|
|
203
|
+
given_iterations = True
|
|
204
|
+
if max_iteration is None:
|
|
205
|
+
# Set default to 500 for z^2 + c map
|
|
206
|
+
max_iteration = 500
|
|
207
|
+
given_iterations = False
|
|
208
|
+
|
|
209
|
+
from ipywidgets.widgets import FloatSlider, IntSlider, ColorPicker, interact
|
|
210
|
+
widgets = dict(
|
|
211
|
+
x_center=FloatSlider(min=-1.0, max=1.0, step=EPS,
|
|
212
|
+
value=x_center, description="Real center"),
|
|
213
|
+
y_center=FloatSlider(min=-1.0, max=1.0, step=EPS,
|
|
214
|
+
value=y_center, description="Imag center"),
|
|
215
|
+
image_width=FloatSlider(min=EPS, max=4.0, step=EPS,
|
|
216
|
+
value=image_width, description='Width'),
|
|
217
|
+
max_iteration=IntSlider(min=0, max=1000,
|
|
218
|
+
value=max_iteration, description='Iterations'),
|
|
219
|
+
pixel_count=IntSlider(min=10, max=1000,
|
|
220
|
+
value=pixel_count, description='Pixels'),
|
|
221
|
+
level_sep=IntSlider(min=1, max=20,
|
|
222
|
+
value=level_sep, description="Color sep"),
|
|
223
|
+
color_num=IntSlider(min=1, max=100,
|
|
224
|
+
value=number_of_colors, description="# Colors"),
|
|
225
|
+
base_color=ColorPicker(value=Color(base_color).html_color(),
|
|
226
|
+
description="Base color"),
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
if f is None:
|
|
230
|
+
# Quadratic map f = z^2 + c
|
|
231
|
+
|
|
232
|
+
if interacts:
|
|
233
|
+
return interact(**widgets).widget(fast_mandelbrot_plot)
|
|
234
|
+
|
|
235
|
+
else:
|
|
236
|
+
return fast_mandelbrot_plot(x_center, y_center, image_width,
|
|
237
|
+
max_iteration, pixel_count, level_sep, number_of_colors,
|
|
238
|
+
base_color)
|
|
239
|
+
|
|
240
|
+
else:
|
|
241
|
+
if parameter is None:
|
|
242
|
+
c = var('c')
|
|
243
|
+
parameter = c
|
|
244
|
+
|
|
245
|
+
P = f.parent()
|
|
246
|
+
|
|
247
|
+
if P.base_ring() is CC or P.base_ring() is CDF:
|
|
248
|
+
if isinstance(P, FractionField_generic):
|
|
249
|
+
raise NotImplementedError("coefficients must be polynomials in the parameter")
|
|
250
|
+
gen_list = list(P.gens())
|
|
251
|
+
parameter = gen_list.pop(gen_list.index(parameter))
|
|
252
|
+
variable = gen_list.pop()
|
|
253
|
+
|
|
254
|
+
elif P.base_ring().base_ring() is CC or P.base_ring().base_ring() is CDF:
|
|
255
|
+
if isinstance(P.base_ring(), FractionField_generic):
|
|
256
|
+
raise NotImplementedError("coefficients must be polynomials in the parameter")
|
|
257
|
+
phi = P.flattening_morphism()
|
|
258
|
+
f = phi(f)
|
|
259
|
+
gen_list = list(f.parent().gens())
|
|
260
|
+
parameter = gen_list.pop(gen_list.index(parameter))
|
|
261
|
+
variable = gen_list.pop()
|
|
262
|
+
|
|
263
|
+
elif P.base_ring() in FunctionFields():
|
|
264
|
+
raise NotImplementedError("coefficients must be polynomials in the parameter")
|
|
265
|
+
|
|
266
|
+
else:
|
|
267
|
+
raise ValueError("base ring must be a complex field")
|
|
268
|
+
|
|
269
|
+
if f == variable**2 + parameter:
|
|
270
|
+
# Quadratic map f = z^2 + c
|
|
271
|
+
if interacts:
|
|
272
|
+
return interact(**widgets).widget(fast_mandelbrot_plot)
|
|
273
|
+
|
|
274
|
+
else:
|
|
275
|
+
return fast_mandelbrot_plot(x_center, y_center, image_width,
|
|
276
|
+
max_iteration, pixel_count, level_sep, number_of_colors,
|
|
277
|
+
base_color)
|
|
278
|
+
else:
|
|
279
|
+
if interacts:
|
|
280
|
+
raise NotImplementedError("interact only implemented for z^2 + c")
|
|
281
|
+
else:
|
|
282
|
+
# Set default of max_iteration to 50 for general polynomial maps
|
|
283
|
+
# This prevents the function from being very slow by default
|
|
284
|
+
if not given_iterations:
|
|
285
|
+
max_iteration = 50
|
|
286
|
+
|
|
287
|
+
# Mandelbrot of General Polynomial Map
|
|
288
|
+
return polynomial_mandelbrot(f, parameter, x_center, y_center,
|
|
289
|
+
image_width, max_iteration, pixel_count, level_sep,
|
|
290
|
+
number_of_colors, base_color)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def external_ray(theta, **kwds):
|
|
294
|
+
r"""
|
|
295
|
+
Draws the external ray(s) of a given angle (or list of angles)
|
|
296
|
+
by connecting a finite number of points that were approximated using
|
|
297
|
+
Newton's method. The algorithm used is described in a paper by
|
|
298
|
+
Tomoki Kawahira.
|
|
299
|
+
|
|
300
|
+
REFERENCE:
|
|
301
|
+
|
|
302
|
+
[Kaw2009]_
|
|
303
|
+
|
|
304
|
+
INPUT:
|
|
305
|
+
|
|
306
|
+
- ``theta`` -- double or list of doubles, angles between 0 and 1 inclusive
|
|
307
|
+
|
|
308
|
+
kwds:
|
|
309
|
+
|
|
310
|
+
- ``image`` -- 24-bit RGB image (default: ``None``); user specified
|
|
311
|
+
image of Mandelbrot set
|
|
312
|
+
|
|
313
|
+
- ``D`` -- long (default: ``25``); depth of the approximation.
|
|
314
|
+
As ``D`` increases, the external ray gets closer to the boundary of the
|
|
315
|
+
Mandelbrot set. If the ray doesn't reach the boundary of the Mandelbrot
|
|
316
|
+
set, increase ``D``.
|
|
317
|
+
|
|
318
|
+
- ``S`` -- long (default: ``10``); sharpness of the approximation.
|
|
319
|
+
Adjusts the number of points used to approximate the external ray (number
|
|
320
|
+
of points is equal to ``S*D``). If ray looks jagged, increase ``S``.
|
|
321
|
+
|
|
322
|
+
- ``R`` -- long (default: ``100``); radial parameter. If ``R`` is
|
|
323
|
+
large, the external ray reaches sufficiently close to infinity. If ``R`` is
|
|
324
|
+
too small, Newton's method may not converge to the correct ray.
|
|
325
|
+
|
|
326
|
+
- ``prec`` -- long (default: ``300``); specifies the bits of
|
|
327
|
+
precision used by the Complex Field when using Newton's method to compute
|
|
328
|
+
points on the external ray
|
|
329
|
+
|
|
330
|
+
- ``ray_color`` -- RGB color (default: ``[255, 255, 255]``) color
|
|
331
|
+
of the external ray(s)
|
|
332
|
+
|
|
333
|
+
OUTPUT: 24-bit RGB image of external ray(s) on the Mandelbrot set
|
|
334
|
+
|
|
335
|
+
EXAMPLES::
|
|
336
|
+
|
|
337
|
+
sage: external_ray(1/3) # needs sage.plot
|
|
338
|
+
500x500px 24-bit RGB image
|
|
339
|
+
|
|
340
|
+
::
|
|
341
|
+
|
|
342
|
+
sage: external_ray(0.6, ray_color=[255, 0, 0]) # needs sage.plot
|
|
343
|
+
500x500px 24-bit RGB image
|
|
344
|
+
|
|
345
|
+
::
|
|
346
|
+
|
|
347
|
+
sage: external_ray([0, 0.2, 0.4, 0.7]) # needs sage.plot
|
|
348
|
+
500x500px 24-bit RGB image
|
|
349
|
+
|
|
350
|
+
::
|
|
351
|
+
|
|
352
|
+
sage: external_ray([i/5 for i in range(1,5)]) # needs sage.plot
|
|
353
|
+
500x500px 24-bit RGB image
|
|
354
|
+
|
|
355
|
+
WARNING:
|
|
356
|
+
|
|
357
|
+
If you are passing in an image, make sure you specify
|
|
358
|
+
which parameters to use when drawing the external ray.
|
|
359
|
+
For example, the following is incorrect::
|
|
360
|
+
|
|
361
|
+
sage: M = mandelbrot_plot(x_center=0) # not tested # needs sage.plot
|
|
362
|
+
sage: external_ray(5/7, image=M) # not tested # needs sage.plot
|
|
363
|
+
500x500px 24-bit RGB image
|
|
364
|
+
|
|
365
|
+
To get the correct external ray, we adjust our parameters::
|
|
366
|
+
|
|
367
|
+
sage: M = mandelbrot_plot(x_center=0) # needs sage.plot
|
|
368
|
+
sage: external_ray(5/7, x_center=0, image=M) # needs sage.plot
|
|
369
|
+
500x500px 24-bit RGB image
|
|
370
|
+
|
|
371
|
+
.. TODO::
|
|
372
|
+
|
|
373
|
+
The ``copy()`` function for bitmap images needs to be implemented
|
|
374
|
+
in Sage.
|
|
375
|
+
"""
|
|
376
|
+
x_0 = kwds.get("x_center", -1)
|
|
377
|
+
y_0 = kwds.get("y_center", 0)
|
|
378
|
+
plot_width = kwds.get("image_width", 4)
|
|
379
|
+
pixel_width = kwds.get("pixel_count", 500)
|
|
380
|
+
depth = kwds.get("D", 25)
|
|
381
|
+
sharpness = kwds.get("S", 10)
|
|
382
|
+
radial_parameter = kwds.get("R", 100)
|
|
383
|
+
precision = kwds.get("prec", 300)
|
|
384
|
+
precision = max(precision, -logb(pixel_width * 0.001, 2).round() + 10)
|
|
385
|
+
ray_color = kwds.get("ray_color", [255] * 3)
|
|
386
|
+
image = kwds.get("image", None)
|
|
387
|
+
if image is None:
|
|
388
|
+
image = mandelbrot_plot(x_center=x_0, **kwds)
|
|
389
|
+
|
|
390
|
+
# Make a copy of the bitmap image.
|
|
391
|
+
old_pixel = image.pixels()
|
|
392
|
+
M = Image('RGB', (pixel_width, pixel_width))
|
|
393
|
+
pixel = M.pixels()
|
|
394
|
+
for i in range(pixel_width):
|
|
395
|
+
for j in range(pixel_width):
|
|
396
|
+
pixel[i, j] = old_pixel[i, j]
|
|
397
|
+
|
|
398
|
+
# Make sure that theta is a list so loop below works
|
|
399
|
+
if not isinstance(theta, list):
|
|
400
|
+
theta = [theta]
|
|
401
|
+
|
|
402
|
+
# Check if theta is in the interval [0,1]
|
|
403
|
+
for angle in theta:
|
|
404
|
+
if angle < 0 or angle > 1:
|
|
405
|
+
raise ValueError("values for theta must be in "
|
|
406
|
+
"the closed interval [0,1].")
|
|
407
|
+
|
|
408
|
+
# Loop through each value for theta in list and plot the external ray.
|
|
409
|
+
for angle in theta:
|
|
410
|
+
E = fast_external_ray(angle, D=depth, S=sharpness, R=radial_parameter,
|
|
411
|
+
prec=precision, image_width=plot_width,
|
|
412
|
+
pixel_count=pixel_width)
|
|
413
|
+
|
|
414
|
+
# Convert points to pixel coordinates.
|
|
415
|
+
pixel_list = convert_to_pixels(E, x_0, y_0, plot_width, pixel_width)
|
|
416
|
+
|
|
417
|
+
# Find the pixels between points in pixel_list.
|
|
418
|
+
extra_points = []
|
|
419
|
+
for i in range(len(pixel_list) - 1):
|
|
420
|
+
if min(pixel_list[i + 1]) >= 0 and max(pixel_list[i + 1]) < pixel_width:
|
|
421
|
+
for j in get_line(pixel_list[i], pixel_list[i + 1]):
|
|
422
|
+
extra_points.append(j)
|
|
423
|
+
|
|
424
|
+
# Add these points to pixel_list to fill in gaps in the ray.
|
|
425
|
+
pixel_list += extra_points
|
|
426
|
+
|
|
427
|
+
# Remove duplicates from list.
|
|
428
|
+
pixel_list = list(set(pixel_list))
|
|
429
|
+
|
|
430
|
+
# Check if point is in window and if it is, plot it on the image to
|
|
431
|
+
# create an external ray.
|
|
432
|
+
for k in pixel_list:
|
|
433
|
+
if max(k) < pixel_width and min(k) >= 0:
|
|
434
|
+
pixel[int(k[0]), int(k[1])] = tuple(ray_color)
|
|
435
|
+
return M
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def kneading_sequence(theta):
|
|
439
|
+
r"""
|
|
440
|
+
Determines the kneading sequence for an angle theta in RR/ZZ which
|
|
441
|
+
is periodic under doubling. We use the definition for the kneading
|
|
442
|
+
sequence given in Definition 3.2 of [LS1994]_.
|
|
443
|
+
|
|
444
|
+
INPUT:
|
|
445
|
+
|
|
446
|
+
- ``theta`` -- a rational number with odd denominator
|
|
447
|
+
|
|
448
|
+
OUTPUT: string representing the kneading sequence of theta in RR/ZZ
|
|
449
|
+
|
|
450
|
+
REFERENCES:
|
|
451
|
+
|
|
452
|
+
[LS1994]_
|
|
453
|
+
|
|
454
|
+
EXAMPLES::
|
|
455
|
+
|
|
456
|
+
sage: kneading_sequence(0)
|
|
457
|
+
'*'
|
|
458
|
+
|
|
459
|
+
::
|
|
460
|
+
|
|
461
|
+
sage: kneading_sequence(1/3)
|
|
462
|
+
'1*'
|
|
463
|
+
|
|
464
|
+
Since 1/3 and 7/3 are the same in RR/ZZ, they have the same kneading sequence::
|
|
465
|
+
|
|
466
|
+
sage: kneading_sequence(7/3)
|
|
467
|
+
'1*'
|
|
468
|
+
|
|
469
|
+
We can also use (finite) decimal inputs, as long as the denominator in reduced form is odd::
|
|
470
|
+
|
|
471
|
+
sage: kneading_sequence(1.2)
|
|
472
|
+
'110*'
|
|
473
|
+
|
|
474
|
+
Since rationals with even denominator are not periodic under doubling, we have not implemented kneading sequences for such rationals::
|
|
475
|
+
|
|
476
|
+
sage: kneading_sequence(1/4)
|
|
477
|
+
Traceback (most recent call last):
|
|
478
|
+
...
|
|
479
|
+
ValueError: input must be a rational number with odd denominator
|
|
480
|
+
"""
|
|
481
|
+
|
|
482
|
+
if theta not in QQ:
|
|
483
|
+
raise TypeError('input must be a rational number with odd denominator')
|
|
484
|
+
elif QQ(theta).valuation(2) < 0:
|
|
485
|
+
raise ValueError('input must be a rational number with odd denominator')
|
|
486
|
+
else:
|
|
487
|
+
theta = QQ(theta)
|
|
488
|
+
theta = theta - floor(theta)
|
|
489
|
+
KS = []
|
|
490
|
+
not_done = True
|
|
491
|
+
left = theta/2
|
|
492
|
+
right = (theta + 1)/2
|
|
493
|
+
y = theta
|
|
494
|
+
while not_done:
|
|
495
|
+
if ((y < left) or (y > right)):
|
|
496
|
+
KS.append('0')
|
|
497
|
+
elif ((y > left) and (y < right)):
|
|
498
|
+
KS.append('1')
|
|
499
|
+
else:
|
|
500
|
+
not_done = False
|
|
501
|
+
y = 2*y - floor(2*y)
|
|
502
|
+
KS_str = ''.join(KS) + '*'
|
|
503
|
+
return KS_str
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
def julia_plot(f=None, **kwds):
|
|
507
|
+
r"""
|
|
508
|
+
Plots the Julia set of a given polynomial ``f``. Users can specify whether
|
|
509
|
+
they would like to display the Mandelbrot side by side with the Julia set
|
|
510
|
+
with the ``mandelbrot`` argument. If ``f`` is not specified, this method
|
|
511
|
+
defaults to `f(z) = z^2-1`.
|
|
512
|
+
|
|
513
|
+
The Julia set of a polynomial ``f`` is the set of complex numbers `z` for
|
|
514
|
+
which the function `f(z)` is bounded under iteration. The Julia set can
|
|
515
|
+
be visualized by plotting each point in the set in the complex plane.
|
|
516
|
+
Julia sets are examples of fractals when plotted in the complex plane.
|
|
517
|
+
|
|
518
|
+
ALGORITHM:
|
|
519
|
+
|
|
520
|
+
Let `R_c = \bigl(1 + \sqrt{1 + 4|c|}\bigr)/2` if the polynomial is of the
|
|
521
|
+
form `f(z) = z^2 + c`; otherwise, let `R_c = 2`.
|
|
522
|
+
For every `p \in \mathbb{C}`, if `|f^{k}(p)| > R_c` for some `k \geq 0`,
|
|
523
|
+
then `f^{n}(p) \to \infty`. Let `N` be the maximum number of iterations.
|
|
524
|
+
Compute the first `N` points on the orbit of `p` under `f`. If for
|
|
525
|
+
any `k < N`, `|f^{k}(p)| > R_c`, we stop the iteration and assign a color
|
|
526
|
+
to the point `p` based on how quickly `p` escaped to infinity under
|
|
527
|
+
iteration of `f`. If `|f^{i}(p)| \leq R_c` for all `i \leq N`, we assume
|
|
528
|
+
`p` is in the Julia set and assign the point `p` the color black.
|
|
529
|
+
|
|
530
|
+
INPUT:
|
|
531
|
+
|
|
532
|
+
- ``f`` -- input polynomial (default: ``z^2 - 1``)
|
|
533
|
+
|
|
534
|
+
- ``period`` -- list (default: ``None``); returns the Julia set
|
|
535
|
+
for a random `c` value with the given (formal) cycle structure
|
|
536
|
+
|
|
537
|
+
- ``mandelbrot`` -- boolean (default: ``True``); when set to
|
|
538
|
+
``True``, an image of the Mandelbrot set is appended to the right of the
|
|
539
|
+
Julia set
|
|
540
|
+
|
|
541
|
+
- ``point_color`` -- RGB color (default: ``'tomato'``);
|
|
542
|
+
color of the point `c` in the Mandelbrot set (any valid input for Color)
|
|
543
|
+
|
|
544
|
+
- ``x_center`` -- double (default: ``-1.0``); real part
|
|
545
|
+
of center point
|
|
546
|
+
|
|
547
|
+
- ``y_center`` -- double (default: ``0.0``); imaginary part
|
|
548
|
+
of center point
|
|
549
|
+
|
|
550
|
+
- ``image_width`` -- double (default: ``4.0``); width of image
|
|
551
|
+
in the complex plane
|
|
552
|
+
|
|
553
|
+
- ``max_iteration`` -- long (default: ``500``); maximum number
|
|
554
|
+
of iterations the map `f(z)`
|
|
555
|
+
|
|
556
|
+
- ``pixel_count`` -- long (default: ``500``); side length of
|
|
557
|
+
image in number of pixels
|
|
558
|
+
|
|
559
|
+
- ``base_color`` -- hex color (default: ``'steelblue'``); color
|
|
560
|
+
used to determine the coloring of set (any valid input for Color)
|
|
561
|
+
|
|
562
|
+
- ``level_sep`` -- long (default: 1); number of iterations
|
|
563
|
+
between each color level
|
|
564
|
+
|
|
565
|
+
- ``number_of_colors`` -- long (default: 30); number of colors
|
|
566
|
+
used to plot image
|
|
567
|
+
|
|
568
|
+
- ``interact`` -- boolean (default: ``False``); controls whether
|
|
569
|
+
plot will have interactive functionality
|
|
570
|
+
|
|
571
|
+
OUTPUT: 24-bit RGB image of the Julia set in the complex plane
|
|
572
|
+
|
|
573
|
+
.. TODO::
|
|
574
|
+
|
|
575
|
+
Implement the side-by-side Mandelbrot-Julia plots for general one-parameter families
|
|
576
|
+
of polynomials.
|
|
577
|
+
|
|
578
|
+
EXAMPLES:
|
|
579
|
+
|
|
580
|
+
The default ``f`` is `z^2 - 1`::
|
|
581
|
+
|
|
582
|
+
sage: julia_plot() # needs sage.plot
|
|
583
|
+
1001x500px 24-bit RGB image
|
|
584
|
+
|
|
585
|
+
To display only the Julia set, set ``mandelbrot`` to ``False``::
|
|
586
|
+
|
|
587
|
+
sage: julia_plot(mandelbrot=False) # needs sage.plot
|
|
588
|
+
500x500px 24-bit RGB image
|
|
589
|
+
|
|
590
|
+
::
|
|
591
|
+
|
|
592
|
+
sage: R.<z> = CC[]
|
|
593
|
+
sage: f = z^3 - z + 1
|
|
594
|
+
sage: julia_plot(f) # long time # needs sage.plot
|
|
595
|
+
500x500px 24-bit RGB image
|
|
596
|
+
|
|
597
|
+
To display an interactive plot of the Julia set in the Notebook,
|
|
598
|
+
set ``interact`` to ``True``. (This is only implemented for polynomials of
|
|
599
|
+
the form ``f = z^2 + c``)::
|
|
600
|
+
|
|
601
|
+
sage: julia_plot(interact=True) # needs sage.plot
|
|
602
|
+
...interactive(children=(FloatSlider(value=-1.0, description='Real c'...
|
|
603
|
+
|
|
604
|
+
::
|
|
605
|
+
|
|
606
|
+
sage: R.<z> = CC[]
|
|
607
|
+
sage: f = z^2 + 1/2
|
|
608
|
+
sage: julia_plot(f, interact=True) # needs sage.plot
|
|
609
|
+
...interactive(children=(FloatSlider(value=0.5, description='Real c'...
|
|
610
|
+
|
|
611
|
+
To return the Julia set of a random `c` value with (formal) cycle structure
|
|
612
|
+
`(2,3)`, set ``period = [2,3]``::
|
|
613
|
+
|
|
614
|
+
sage: julia_plot(period=[2,3]) # needs sage.plot
|
|
615
|
+
1001x500px 24-bit RGB image
|
|
616
|
+
|
|
617
|
+
To return all of the Julia sets of `c` values with (formal) cycle structure
|
|
618
|
+
`(2,3)`::
|
|
619
|
+
|
|
620
|
+
sage: period = [2,3] # not tested
|
|
621
|
+
....: R.<c> = QQ[]
|
|
622
|
+
....: P.<x,y> = ProjectiveSpace(R,1)
|
|
623
|
+
....: f = DynamicalSystem([x^2+c*y^2, y^2])
|
|
624
|
+
....: L = f.dynatomic_polynomial(period).subs({x:0,y:1}).roots(ring=CC)
|
|
625
|
+
....: c_values = [k[0] for k in L]
|
|
626
|
+
....: for c in c_values:
|
|
627
|
+
....: julia_plot(c)
|
|
628
|
+
|
|
629
|
+
Polynomial maps can be defined over a polynomial ring or a fraction field,
|
|
630
|
+
so long as ``f`` is polynomial::
|
|
631
|
+
|
|
632
|
+
sage: R.<z> = CC[]
|
|
633
|
+
sage: f = z^2 - 1
|
|
634
|
+
sage: julia_plot(f) # needs sage.plot
|
|
635
|
+
1001x500px 24-bit RGB image
|
|
636
|
+
|
|
637
|
+
::
|
|
638
|
+
|
|
639
|
+
sage: R.<z> = CC[]
|
|
640
|
+
sage: K = R.fraction_field(); z = K.gen()
|
|
641
|
+
sage: f = z^2 - 1
|
|
642
|
+
sage: julia_plot(f) # needs sage.plot
|
|
643
|
+
1001x500px 24-bit RGB image
|
|
644
|
+
|
|
645
|
+
Interact functionality is not implemented if the polynomial is not of the
|
|
646
|
+
form `f = z^2 + c`::
|
|
647
|
+
|
|
648
|
+
sage: R.<z> = CC[]
|
|
649
|
+
sage: f = z^3 + 1
|
|
650
|
+
sage: julia_plot(f, interact=True) # needs sage.plot
|
|
651
|
+
Traceback (most recent call last):
|
|
652
|
+
...
|
|
653
|
+
NotImplementedError: The interactive plot is only implemented for ...
|
|
654
|
+
"""
|
|
655
|
+
|
|
656
|
+
# extract keyword arguments
|
|
657
|
+
period = kwds.pop("period", None)
|
|
658
|
+
mandelbrot = kwds.pop("mandelbrot", True)
|
|
659
|
+
point_color = kwds.pop("point_color", 'tomato')
|
|
660
|
+
x_center = kwds.pop("x_center", 0.0)
|
|
661
|
+
y_center = kwds.pop("y_center", 0.0)
|
|
662
|
+
image_width = kwds.pop("image_width", 4.0)
|
|
663
|
+
max_iteration = kwds.pop("max_iteration", 500)
|
|
664
|
+
pixel_count = kwds.pop("pixel_count", 500)
|
|
665
|
+
base_color = kwds.pop("base_color", 'steelblue')
|
|
666
|
+
level_sep = kwds.pop("level_sep", 1)
|
|
667
|
+
number_of_colors = kwds.pop("number_of_colors", 30)
|
|
668
|
+
interacts = kwds.pop("interact", False)
|
|
669
|
+
|
|
670
|
+
f_is_default_after_all = None
|
|
671
|
+
|
|
672
|
+
if period: # pick a random c with the specified period
|
|
673
|
+
R = PolynomialRing(CC, 'c')
|
|
674
|
+
c = R.gen()
|
|
675
|
+
x, y = ProjectiveSpace(R, 1, 'x,y').gens()
|
|
676
|
+
F = DynamicalSystem([x**2 + c * y**2, y**2])
|
|
677
|
+
L = F.dynatomic_polynomial(period).subs({x: 0, y: 1}).roots(ring=CC)
|
|
678
|
+
c = L[randint(0, len(L) - 1)][0]
|
|
679
|
+
|
|
680
|
+
base_color = Color(base_color)
|
|
681
|
+
point_color = Color(point_color)
|
|
682
|
+
|
|
683
|
+
EPS = 0.00001
|
|
684
|
+
|
|
685
|
+
if f is not None and period is None: # f user-specified and no period given
|
|
686
|
+
|
|
687
|
+
# try to coerce f to live in a polynomial ring
|
|
688
|
+
S = PolynomialRing(CC, names='z')
|
|
689
|
+
z = S.gen()
|
|
690
|
+
try:
|
|
691
|
+
f_poly = S(f)
|
|
692
|
+
except TypeError:
|
|
693
|
+
R = f.parent()
|
|
694
|
+
if not (R.is_integral_domain() and
|
|
695
|
+
(CC.is_subring(R) or CDF.is_subring(R))):
|
|
696
|
+
raise ValueError('given `f` must be a complex polynomial')
|
|
697
|
+
raise NotImplementedError(
|
|
698
|
+
'Julia sets not implemented for rational functions')
|
|
699
|
+
|
|
700
|
+
if (f_poly - z*z) in CC: # f is specified and of the form z^2 + c.
|
|
701
|
+
f_is_default_after_all = True
|
|
702
|
+
c = f_poly - z*z
|
|
703
|
+
else: # f is specified and not of the form z^2 + c
|
|
704
|
+
if interacts:
|
|
705
|
+
raise NotImplementedError(
|
|
706
|
+
"The interactive plot is only implemented for "
|
|
707
|
+
"polynomials of the form f = z^2 + c."
|
|
708
|
+
)
|
|
709
|
+
else:
|
|
710
|
+
return general_julia(f_poly, x_center, y_center,
|
|
711
|
+
image_width, max_iteration,
|
|
712
|
+
pixel_count, level_sep,
|
|
713
|
+
number_of_colors, base_color)
|
|
714
|
+
|
|
715
|
+
# otherwise we can use fast_julia_plot for z^2 + c
|
|
716
|
+
if f_is_default_after_all or f is None or period is not None:
|
|
717
|
+
|
|
718
|
+
# specify default c = -1 value if f and period were not specified
|
|
719
|
+
if not f_is_default_after_all and period is None:
|
|
720
|
+
c = -1
|
|
721
|
+
|
|
722
|
+
c = CC(c)
|
|
723
|
+
c_real = c.real()
|
|
724
|
+
c_imag = c.imag()
|
|
725
|
+
|
|
726
|
+
if interacts: # set widgets
|
|
727
|
+
from ipywidgets.widgets import FloatSlider, IntSlider, \
|
|
728
|
+
ColorPicker, interact
|
|
729
|
+
widgets = dict(
|
|
730
|
+
c_real=FloatSlider(min=-2.0, max=2.0, step=EPS,
|
|
731
|
+
value=c_real, description="Real c"),
|
|
732
|
+
c_imag=FloatSlider(min=-2.0, max=2.0, step=EPS,
|
|
733
|
+
value=c_imag, description="Imag c"),
|
|
734
|
+
x_center=FloatSlider(min=-1.0, max=1.0, step=EPS,
|
|
735
|
+
value=x_center, description="Real center"),
|
|
736
|
+
y_center=FloatSlider(min=-1.0, max=1.0, step=EPS,
|
|
737
|
+
value=y_center, description="Imag center"),
|
|
738
|
+
image_width=FloatSlider(min=EPS, max=4.0, step=EPS,
|
|
739
|
+
value=image_width, description='Width'),
|
|
740
|
+
max_iteration=IntSlider(min=0, max=1000,
|
|
741
|
+
value=max_iteration, description='Iterations'),
|
|
742
|
+
pixel_count=IntSlider(min=10, max=1000,
|
|
743
|
+
value=pixel_count, description='Pixels'),
|
|
744
|
+
level_sep=IntSlider(min=1, max=20,
|
|
745
|
+
value=level_sep, description="Color sep"),
|
|
746
|
+
color_num=IntSlider(min=1, max=100,
|
|
747
|
+
value=number_of_colors, description="# Colors"),
|
|
748
|
+
base_color=ColorPicker(value=base_color.html_color(),
|
|
749
|
+
description="Base color"),
|
|
750
|
+
)
|
|
751
|
+
if mandelbrot:
|
|
752
|
+
widgets["point_color"] = ColorPicker(value=point_color.html_color(),
|
|
753
|
+
description="Point color")
|
|
754
|
+
return interact(**widgets).widget(julia_helper)
|
|
755
|
+
else:
|
|
756
|
+
return interact(**widgets).widget(fast_julia_plot)
|
|
757
|
+
elif mandelbrot: # non-interactive with mandelbrot
|
|
758
|
+
return julia_helper(c_real, c_imag, x_center, y_center,
|
|
759
|
+
image_width, max_iteration, pixel_count,
|
|
760
|
+
level_sep, number_of_colors, base_color,
|
|
761
|
+
point_color)
|
|
762
|
+
else: # non-interactive without mandelbrot
|
|
763
|
+
return fast_julia_plot(c_real, c_imag, x_center, y_center,
|
|
764
|
+
image_width, max_iteration, pixel_count,
|
|
765
|
+
level_sep, number_of_colors, base_color)
|