Fractals
Fractals: escape-time sets, chaos-game attractors, and words and patches of named curves and sets.
CantorElement(label, tiles=None, *, ratio=1 / 3, prototiles=(), filled=False, max_size=10000000, bounds=None, visual=None)
Bases: PatchElement
Patch of intervals, each replaced by its first and its last part of the length ratio.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the patch. |
required |
tiles
|
Sequence[tuple[str, AffineSpec]] | None
|
Pairs of a prototile name and its placement at generation 0, or |
None
|
ratio
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The length of each kept part relative to its interval. |
1 / 3
|
prototiles
|
Sequence[PrototileSpec]
|
The prototiles of the patch. |
()
|
filled
|
bool
|
Whether the geometry visual draws polygons as a filled image instead of outlines. |
False
|
max_size
|
int
|
The largest number of tiles a generation may produce. |
10000000
|
bounds
|
Sequence[float] | None
|
The box |
None
|
visual
|
VisualSpec | None
|
How the patch is drawn, or |
None
|
Examples:
>>> from skcomplex.systems.mathematics.fractals import CantorElement
>>> CantorElement('cantor', ratio=0.25).ratio
0.25
Source code in src/skcomplex/systems/mathematics/fractals/_substitution.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | |
ChaosPointElement(label, visual=VisualSpec('points', {'position': 'p', 'radius': 0.004, 'states': ()}), *, p=0.0)
Bases: Element
Point of the plane whose position a random affine map moves at every step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the point or the group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
VisualSpec('points', {'position': 'p', 'radius': 0.004, 'states': ()})
|
p
|
Annotated[object, StateSpec(vector=True)]
|
The initial position. |
0.0
|
Examples:
>>> from skcomplex.systems.mathematics.fractals import ChaosPointElement
>>> ChaosPointElement('point', p=(0.5, 0.5)).p
(0.5, 0.5)
Source code in src/skcomplex/systems/mathematics/fractals/_chaos_game.py
51 52 53 54 55 56 57 58 59 | |
InverseJuliaPointElement(label, visual=None, *, z=0.5, omega=0.0, p=0.5)
Bases: Element
Point of the inverse iteration of z -> z² + omega, which moves to a square root of z - omega drawn at random.
The point moves to +√(z - omega) with probability p and to -√(z - omega) otherwise, with the principal
square root.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the element or the group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
z
|
Annotated[object, StateSpec(domain=CC)]
|
The initial point. |
0.5
|
omega
|
Annotated[object, ParameterSpec(domain=CC)]
|
The constant of the quadratic map. |
0.0
|
p
|
Annotated[object, ParameterSpec(domain=closed(0, 1))]
|
The probability of the positive square root. |
0.5
|
Examples:
>>> from skcomplex.systems.mathematics.fractals import InverseJuliaPointElement
>>> InverseJuliaPointElement('point', p=0.3).p
0.3
Source code in src/skcomplex/systems/mathematics/fractals/_quadratic.py
53 54 55 56 57 58 59 60 61 62 63 64 65 | |
KochElement(label, axiom='', *, alphabet=None, ignore='', geometry=None, max_size=10000000, bounds=None, visual=None)
Bases: WordElement
Word rewritten by the production F → F+F--F+F of the Koch curve.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the word. |
required |
axiom
|
Annotated[Letters, StateSpec(domain=None)]
|
The word at generation 0. |
''
|
geometry
|
GeometrySpec | None
|
How the word is drawn as line segments, or |
None
|
Examples:
>>> from skcomplex.systems.mathematics.fractals import KochElement
>>> KochElement('koch', axiom='F')._get_laws(None)[0].successor
'F+F--F+F'
Source code in src/skcomplex/core/components/elements/_word.py
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | |
QuadraticMapElement(label, visual=None, *, z=0.0, n=0.0, c=0.0, radius=2.0)
Bases: Element
Complex quadratic map z' = z^2 + c while |z| stays within the escape radius, with a count of its steps.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the element. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
z
|
Annotated[object, StateSpec(domain=CC)]
|
The initial point. |
0.0
|
n
|
Annotated[object, StateSpec(domain=NN)]
|
The initial number of steps within the escape radius. |
0.0
|
c
|
Annotated[object, ParameterSpec(domain=CC)]
|
The constant of the map. |
0.0
|
radius
|
Annotated[object, ParameterSpec(domain=open(0, oo))]
|
The escape radius. |
2.0
|
Examples:
>>> from skcomplex.systems.mathematics.fractals import QuadraticMapElement
>>> QuadraticMapElement('point', c=0.25).c
0.25
Source code in src/skcomplex/systems/mathematics/fractals/_quadratic.py
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | |
RandomAffineMapInteraction(label, *, target, state='p', maps=SIERPINSKI_MAPS, weights=(1.0, 1.0, 1.0))
Bases: MapInteraction
Map of a point of the plane by one affine map of an iterated function system, drawn anew at every step.
Map k takes (x, y) to (a x + b y + e, c x + d y + f) for its coefficients (a, b, c, d, e, f), and is drawn
with a probability proportional to its weight, independently for every member of a bound group.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction, unique among the parts of its system. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the element or group whose position the map sets. |
required |
state
|
str
|
The name of the vector state of the target that holds the position. |
'p'
|
maps
|
Sequence[AffineMap]
|
The coefficients |
SIERPINSKI_MAPS
|
weights
|
Sequence[float]
|
The weight of every map. |
(1.0, 1.0, 1.0)
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
The number of weights differs from the number of maps, or a map does not have six coefficients. |
Examples:
>>> from skcomplex.systems.mathematics.fractals import RandomAffineMapInteraction
>>> game = RandomAffineMapInteraction('game', target='points', maps=[(0.5, 0, 0, 0.5, 0, 0)], weights=[1.0])
>>> game.maps
[(0.5, 0, 0, 0.5, 0, 0)]
Source code in src/skcomplex/systems/mathematics/fractals/_chaos_game.py
95 96 97 98 99 100 101 102 103 104 105 106 | |
SierpinskiElement(label, tiles=None, *, shape='triangle', prototiles=(), filled=False, max_size=10000000, bounds=None, visual=None)
Bases: PatchElement
Patch of triangles or squares, each replaced by the scaled copies of the Sierpiński triangle or carpet.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the patch. |
required |
tiles
|
Sequence[tuple[str, AffineSpec]] | None
|
Pairs of a prototile name and its placement at generation 0, or |
None
|
shape
|
str
|
|
'triangle'
|
prototiles
|
Sequence[PrototileSpec]
|
The prototiles of the patch. |
()
|
filled
|
bool
|
Whether the geometry visual draws polygons as a filled image instead of outlines. |
False
|
max_size
|
int
|
The largest number of tiles a generation may produce. |
10000000
|
bounds
|
Sequence[float] | None
|
The box |
None
|
visual
|
VisualSpec | None
|
How the patch is drawn, or |
None
|
Examples:
>>> from skcomplex.systems.mathematics.fractals import SierpinskiElement
>>> len(SierpinskiElement('sierpinski', shape='carpet')._get_laws(None)[0].pieces)
8
Source code in src/skcomplex/systems/mathematics/fractals/_substitution.py
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | |
cantor_set(ratio=1 / 3)
Return the Cantor set as the substitution of every interval by its two outer parts.
Every generation keeps the first and the last part of each interval, each ratio of its length, and removes the
middle. With the ratio of one third, generation n has 2^n intervals of total length (2/3)^n, and the limit set
has the similarity dimension log 2 / log 3, about 0.631.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ratio
|
float
|
The length of each kept part relative to its interval, below one half. |
1 / 3
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the patch |
Raises:
| Type | Description |
|---|---|
ValidationError
|
The ratio is not between 0 and 1/2. |
Examples:
>>> from skcomplex.systems import create_simulation
>>> create_simulation('cantor_set').prepare().run(until=3).trajectory_.values('cantor.size').tolist()
[1.0, 2.0, 4.0, 8.0]
Source code in src/skcomplex/systems/mathematics/fractals/_substitution.py
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | |
chaos_game(preset='sierpinski', *, maps=None, weights=None, n_points=20000, random_state=0)
Return points that draw the attractor of an iterated function system by the chaos game.
At every step each point moves by one of the affine maps of the system, drawn with probabilities proportional to
the weights. The maps contract, so after a few steps the cloud of points covers the attractor, the unique compact
set that the union of the maps leaves unchanged. The Sierpiński triangle of three maps of ratio 1/2 has the
box-counting dimension log 3 / log 2, and the Barnsley fern is the attractor of four maps.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preset
|
str
|
|
'sierpinski'
|
maps
|
Sequence[AffineMap] | None
|
The coefficients |
None
|
weights
|
Sequence[float] | None
|
The weight of every map, or |
None
|
n_points
|
int
|
The number of points, started uniformly in the unit square. |
20000
|
random_state
|
int | Generator | None
|
The seed or generator of the initial points. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the positions |
Raises:
| Type | Description |
|---|---|
ValidationError
|
The preset is unknown. |
Examples:
>>> from skcomplex.systems.mathematics.fractals import chaos_game
>>> len(chaos_game('barnsley', n_points=10).interactions[0].maps)
4
Source code in src/skcomplex/systems/mathematics/fractals/_chaos_game.py
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | |
inverse_julia(omega=-0.123 + 0.745j, *, p=0.5, n_points=5000, random_state=0)
Return the random function system z -> ±√(z - omega), whose points settle on the Julia set of z² + omega.
At every step each point moves to the positive square root of z - omega with probability p and to the
negative one otherwise (Dilão 2023, Exercise 5.8). Both branches invert the quadratic map z -> z² + omega, which
repels its Julia set, so the inverse branches attract the points onto the Julia set, drawn by the chaos game with
weights p and 1 - p. For omega = 0 the Julia set is the unit circle, and the default is Douady's rabbit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
omega
|
complex
|
The constant of the quadratic map. |
-0.123 + 0.745j
|
p
|
float
|
The probability of the positive square root. |
0.5
|
n_points
|
int
|
The number of points, started uniformly in the square of side 2 about the origin. |
5000
|
random_state
|
int | Generator | None
|
The seed or generator of the initial points. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the points |
Examples:
>>> from skcomplex.systems.mathematics.fractals import inverse_julia
>>> inverse_julia(0.0, n_points=10).elements[0].prepare().size_
10
Source code in src/skcomplex/systems/mathematics/fractals/_quadratic.py
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 | |
julia(c=-0.8 + 0.156j, shape=(240, 320), *, window=JULIA_WINDOW, radius=2.0)
Return the filled Julia set of z -> z^2 + c, the starting points whose orbit stays bounded (Dilão 2023 §5.5).
Every site holds one starting point z of the window and iterates the map with the same constant c, and n
counts the steps the orbit stays within the escape radius. For c in the Mandelbrot set the filled Julia set is
connected, and outside it the set breaks into dust.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
c
|
complex
|
The constant of the map. |
-0.8 + 0.156j
|
shape
|
Sequence[int]
|
The number of sites along the imaginary and the real axis. |
(240, 320)
|
window
|
Window
|
The smallest and largest real part, then the smallest and largest imaginary part, of the starting points. |
JULIA_WINDOW
|
radius
|
float
|
The escape radius, at least 2 and at least |
2.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the field |
Examples:
>>> from skcomplex.systems.mathematics.fractals import julia
>>> julia(0.0, (3, 3), window=(-1, 1, -1, 1)).elements[0].values['z'][0].tolist()
[(-1+1j), 1j, (1+1j)]
Source code in src/skcomplex/systems/mathematics/fractals/_quadratic.py
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | |
koch_curve(angle=60.0)
Return the Koch curve as the L-system F → F+F--F+F drawn by a turtle.
Every generation replaces each segment by four segments of a third of its length, with a bump of the turning angle
in the middle. With the angle of 60 degrees the curve keeps its endpoints at (0, 0) and (1, 0), its length is
(4/3)^n at generation n, and its similarity dimension is log 4 / log 3, about 1.262.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
angle
|
float
|
The turning angle of the turtle in degrees. |
60.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the word |
Examples:
>>> from skcomplex.systems import create_simulation
>>> create_simulation('koch_curve').prepare().run(until=3).trajectory_.values('koch.F').tolist()
[1.0, 4.0, 16.0, 64.0]
Source code in src/skcomplex/systems/mathematics/fractals/_substitution.py
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | |
mandelbrot(shape=(240, 300), *, window=MANDELBROT_WINDOW, radius=2.0)
Return the Mandelbrot set, the points c whose orbit of z -> z^2 + c from 0 stays bounded (Dilão 2023 §5.5).
Every site holds one point c of the window and iterates the map, and n counts the steps the orbit stays within
the escape radius. The points of the set never escape, so their count grows with every step, while the count of an
escaped point stops at its escape time and colors the bands around the set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shape
|
Sequence[int]
|
The number of sites along the imaginary and the real axis. |
(240, 300)
|
window
|
Window
|
The smallest and largest real part, then the smallest and largest imaginary part, of the points. |
MANDELBROT_WINDOW
|
radius
|
float
|
The escape radius, 2 for the quadratic map. |
2.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the field |
Examples:
>>> from skcomplex.systems.mathematics.fractals import mandelbrot
>>> mandelbrot((3, 3), window=(-1, 1, -1, 1)).elements[0].values['c'][1].tolist()
[(-1+0j), 0j, (1+0j)]
Source code in src/skcomplex/systems/mathematics/fractals/_quadratic.py
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
sierpinski_substitution(shape='triangle', *, filled=True)
Return the Sierpiński triangle or carpet as the substitution of a polygon by scaled copies of itself.
The triangle is replaced by its three corner copies of half its side, so generation n has 3^n triangles of
total area (3/4)^n times the first, and the gasket has the similarity dimension log 3 / log 2, about 1.585. The
square is replaced by the eight copies of a third of its side around its middle, so generation n has 8^n
squares of area (8/9)^n, and the carpet has the dimension log 8 / log 3, about 1.893.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shape
|
str
|
|
'triangle'
|
filled
|
bool
|
Whether the geometry visual draws the polygons as a filled image instead of outlines. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the patch |
Raises:
| Type | Description |
|---|---|
ValidationError
|
The shape is unknown. |
Examples:
>>> from skcomplex.systems import create_simulation
>>> simulation = create_simulation('sierpinski_substitution').prepare().run(until=2)
>>> simulation.trajectory_.values('sierpinski.size').tolist()
[1.0, 3.0, 9.0]
Source code in src/skcomplex/systems/mathematics/fractals/_substitution.py
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | |