# Battle of the bears

## Preparing the data set used for the benchmark

For the benchmarks, we generate a reference data set which when written to disk as a csv file, will occupy ~1.5GB.

Some of its columns are related to the [Mandelbrot set](https://en.wikipedia.org/wiki/Mandelbrot_set) and require some computational power to compute.
To not have to wait for hours, a fortran extension will jump in here.
The extension will be automatically called by [benchmark.py](benchmark.py).

To build the fortran extension, run

```sh
python -m numpy.f2py -c -m mandelbrot --f2cmap .f2py_f2cmap mandelbrot.f90
```

## Run the benchmarks

```sh
./benchmark.py
```

This will output the results to `results.json` which can be plotted to a svg using
[examples/plot-benchmark.py](../../examples/plot-benchmark.py):

``` sh
../../examples/plot-benchmark.py --n-cols=2 --scale-font=2.0 results.json
```

## So what are those "Mandelbrot" columns?

The dataset will contain the following columns:

- 3 columns for `x`, `y`, `z` coordinates of points in a 3D 200 x 200 x 200 grid in the box [-1, 1]³
- `rho`: cylindrical radius, i.e. x²+y² of the point represented by the row
- `r`: spherical radius, i.e. x²+y²+z² of the point represented by the row
- `theta`, `phi`: spherical angular coordinates of the point represented by the row
- `u`, `v`: hyperbolical coordinates of the point represented by the row
- `octant`: 0 for x,y,z >= 0, 1 for x<0, y,z>=0, ...
- `xy_quadrant`: 0 for x,y >= 0, 1 for x<0, y>=0, ...
- `xz_quadrant`, `yz_quadrant`: analogous to `xy_quadrant`
- `mandelbrot_cycle_length`, `mandelbrot_divergence_count`: see below

As we are in 3D, the usual 2D Mandelbrot set is not enough. We will use [Quaternions](https://en.wikipedia.org/wiki/Quaternion)
instead of complex numbers to extend the Mandelbrot set to 4D (but only make use of 3 dimensions).

To each 3D point (x,y,z), we associate a quaternion c = x + iy + jz and examine the convergence of the Mandelbrot sequence
$$q_{n+1} = q^2 + c, q_0 = 0$$.

**Case 1: The sequence diverges** Then `mandelbrot_divergence_count` will be set to the number `n`
such that $q_n > 1000$.

[plot_mandelbrot.py](plot_mandelbrot.py) plots this number `n` in the plane z=0 mapping different values
of `n` to different colors.

**Case 2: The sequence converges or stays finite** It turns out that in this case, the sequence
will have a certain number $n$ of accumulation points (depending on the choice of $c$),
called attracting cycle of period $n$.
`mandelbrot_cycle_length` will be set to this number.

If the sequence diverges, `mandelbrot_divergence_count` is set to 0 and
`mandelbrot_cycle_length := 0` otherwise.
