Getting started

Consider the Hénon map [1]

julia> const a, b = 1.35, 0.3(1.35, 0.3)
julia> f((x,y)) = ( 1 - a*x^2 + y, b*x )f (generic function with 1 method)

Iterating some random intial point exhibits a strange attractor

julia> orbit = NTuple{2, Float64}[]Tuple{Float64, Float64}[]
julia> x = (1, 1)(1, 1)
julia> for k in 1:10000 x = f(x) push!(orbit, x) end
julia> using Plots
julia> p = scatter(orbit)Plot{Plots.GRBackend() n=1}

Hénon attractor

This map is chaotic [2], [3], it has sensitive dependence on initial conditions. That is, small perturbations (as unavoidable on a computer) during the computation grow exponentially during the iteration. Thus, apart from a few iterates at the beginning, the computed trajectory does not (necessarily) follow a true trajectory. One might therefore question how reliable this figure is.

Instead of trying to approximate the attractor by a long forward trajectory, we will capture it by computing a collection of boxes (i.e. cubes) covering the attractor.

Start by loading the GAIO package

julia> using GAIO

A Box is descibed by its center and its radius

julia> box_center, box_radius = (0,0), (3,3)((0, 0), (3, 3))
julia> Q = Box(box_center, box_radius)Box{2, Float64}: center: [0.0, 0.0] radius: [3.0, 3.0]

This box will serve as the domain for our computation. The box covering which we will compute is a subset of a partition of Q into smaller boxes. The command

julia> P = BoxPartition(Q, (4,4))4 x 4 - element BoxPartition

yields a partition of Q into a grid of 4 x 4 equally sized smaller boxes. Note that this command does not explicitly construct the partition (as a set of subsets covering the domain Q) but rather serves as a $\sigma$-algebra for constructing sets of boxes later. For example, the commands

julia> test_points = [
           (1, 1),
           (2, 1)
       ];
julia> B = cover(P, test_points)2 - element BoxSet in 4 x 4 - element BoxPartition

yields a BoxSet containing boxes from the partition P which cover each of test_points. Similarly,

julia> B = cover(P, :)16 - element BoxSet in 4 x 4 - element BoxPartition

yields a BoxSet containing all boxes from the partition P (i.e. a set containing 16 boxes).

In order to deal with the Hénon map f as a map over box sets, we have to turn it into a BoxMap on the domain Q

julia> F = BoxMap(f, Q)SampledBoxMap with 5 sample points

We can now compute a covering of the attractor in Q, starting with the full box set B, by applying 15 steps of the subdivison algorithm described in [4]:

julia> A = relative_attractor(F, B, steps = 19)21055 - element BoxSet in 2048 x 4096 - element BoxPartition
julia> p = plot(A)Plot{Plots.GRBackend() n=1}

box covering of the Hénon attractor

In addition to covering the attractor, this box collection also covers an unstable fixed point near (-1,-0.3) and its unstabe manifold (cf. [4]).