Skip to content

Julia sets

The filled Julia set of z -> z^2 + c, the starting points whose orbit stays bounded (Dilão 2023 §5.5).

  • Name: julia
  • Field: mathematics/fractals
  • Formalism: discrete map
  • References: Dilão 2023

The julia example

Example

Factory

@register_model(
    field='mathematics/fractals',
    tags=('fractal', 'complex', 'map', 'lattice', 'escape time'),
    references=('Dilão 2023',),
    defaults={'until': 100, 'dt': 1},
)
def julia(
    c: complex = -0.8 + 0.156j,
    shape: Sequence[int] = (240, 320),
    *,
    window: Window = JULIA_WINDOW,
    radius: float = 2.0,
) -> System:
    """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.

    Args:
        c:
            The constant of the map.

        shape:
            The number of sites along the imaginary and the real axis.

        window:
            The smallest and largest real part, then the smallest and largest imaginary part, of the starting points.

        radius:
            The escape radius, at least 2 and at least `|c|`, so escaped orbits never return.

    Returns:
        system:
            The model, with the field `plane`, its orbits `plane.z`, and its escape times `plane.n`.

    Examples:
        >>> from skcomplex.models.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)]
    """
    points = _plane(shape, window)
    return _escape_field(shape, points, complex(c), radius)

Components

class QuadraticMapElement(Element):
    """Complex quadratic map `z' = z^2 + c` while `|z|` stays within the escape radius, with a count of its steps.

    Args:
        label:
            The label of the element.

        visual:
            How the element is drawn, or `None` for `default_visual_`.

        z:
            The initial point.

        n:
            The initial number of steps within the escape radius.

        c:
            The constant of the map.

        radius:
            The escape radius.

    Examples:
        >>> from skcomplex.models.mathematics.fractals import QuadraticMapElement
        >>> QuadraticMapElement('point', c=0.25).c
        0.25
    """

    def __init__(
        self,
        label: str,
        visual: VisualSpec | None = None,
        *,
        z: Annotated[object, StateSpec(domain=CC)] = 0.0,
        n: Annotated[object, StateSpec(domain=NN)] = 0.0,
        c: Annotated[object, ParameterSpec(domain=CC)] = 0.0,
        radius: Annotated[object, ParameterSpec(domain=RealSet.open(0, oo))] = 2.0,
    ) -> None:
        super().__init__(label, visual=visual)
        self.z = z
        self.n = n
        self.c = c
        self.radius = radius

    def _get_laws(self, s: SimpleNamespace) -> list[BaseLaw]:
        """Return the next point, which stays once it escaped, and the next count.

        Args:
            s:
                The namespace of the symbols the laws can use.

        Returns:
            laws:
                The laws of the element.
        """
        return [
            UpdateLaw(s.z, where(abs(s.z) <= s.radius, s.z**2 + s.c, s.z)),
            UpdateLaw(s.n, s.n + where(abs(s.z) <= s.radius, 1, 0)),
        ]

Equations

plane.z[i].real: z_plane_re(t + 1) == where(sqrt(z_plane_im(t)^2 + z_plane_re(t)^2) <= radius_plane, -z_plane_im(t)^2 + z_plane_re(t)^2 + c_plane_re, z_plane_re(t))
plane.z[i].imag: z_plane_im(t + 1) == where(sqrt(z_plane_im(t)^2 + z_plane_re(t)^2) <= radius_plane, 2*z_plane_im(t)*z_plane_re(t) + c_plane_im, z_plane_im(t))
plane.n[i]: n_plane(t + 1) == n_plane(t) + where(sqrt(z_plane_im(t)^2 + z_plane_re(t)^2) <= radius_plane, 1, 0)