# Multibrot
Generalisation of Mandelbrot set to arbitrary power \(N\).
\[f_c(z) = z^N + c\]
Here only integer \(N \ge 2\) are considered.
# 1 Critical Point
\[f_c'(z) = N z^{N-1} = 0\]
has the solution
\[z_0 = 0\]
which is where iteration should start from to determine the number of components that the filled-in Julia set has (1 if it remains bounded, infinitely many if it escapes to infinity).
# 2 Escape To Infinity
Suppose \(|z_n| > R \ge \max(|c|, 1)\) If that implies \(|z_{n+1}| > (1 + \epsilon) R\) with some \(\epsilon > 0\), then \(|z_{n + m}| > (1 + \epsilon)^m R \to \infty\) as \(m \to \infty\).
Calculating, \[\begin{aligned} |z_{n+1}| &= |z_n^N+c| \\ &> \left||z_n^N| - |c|\right| \\ &= |z_n^N| - |c| \\ &> R^N - |c| \\ &\ge R^N - R \\ &= (R^{N-1} - 1) R \end{aligned}\]
Therefore, setting \[1 + \epsilon = R^{N-1} - 1\] gives \[R = \sqrt[N-1]{2 + \epsilon}.\] \(\epsilon\) is arbitrarily small, so this gives bounds: \[R > \sqrt[N-1]{2} \ge |c|\]
That is, \[|z_n| > \sqrt[N-1]{2}\] will escape to infinity, and the whole set is contained in the ball of radius \(\sqrt[N-1]{2}\) centered on the origin.
# 3 Boundedness
See:
“Cross-sections of multibrot sets”, Line Baribeau, Thomas Ransford https://arxiv.org/abs/1701.05535
Relevant result:
If \(|c| \le (N-1)/N^{N/(N-1)}\) then \(|z_n| \le 1/N^{1/(N-1)}\), that is, \(z_n\) remains bounded.
# 4 Fast Exponentiation
Simply multiplying by \(z\) \(N\) times is inefficient. Much better is exponentiation by squaring:
\[\begin{aligned} z^{2 N + 1} &= z^{2 N} \times z \\ z^{2 N} &= \left(z^N\right)^2 \end{aligned}\]
This takes \(O(\log(N))\) operations instead of \(O(N)\), which is a big improvement.
The recursive description gives the operations in the reverse order to which they need to be performed.
The execution opcodes can be captured in a table, or in unrolled inner loops of generated code. The opcodes for one iteration of \(z \to z^N + c\) are \(\cdot \times z\), \(\cdot^2\), and \(\cdot + c\).
# 5 Perturbation
Perturbing \(z^N+c\) gives an expression with \(O(N)\) terms: \[((Z+z)^N+(C+c)) - (Z^N+C) = c + \sum_{k=1}^N \begin{pmatrix} N \\ k \end{pmatrix} Z^{N-k} z^k\] This is inefficient in terms of number of operations.
Images also can have glitches if care is not taken: the glitch test is no longer \(|Z+z| < |z|\) but needs to be more like \(|Z+z| < N |z|\) (to be verified).
For greater efficiency and robustness, combine with fast exponentiation: store the reference \(Z\) before opcode step, that is, store \(O(\log(N))\) values per iteration.
Then check and rebase pixel iterations using Zhuoran’s trick before each opcode step: whenever \(|Z+z|<|z|\), set \(z=Z+z\) and \(Z=0\) (the latter by resetting the iteration index into the reference orbit; don’t reset the reference’s step index).
This works so easily because 0 is the only critical point, and \(0 = 0^2 = z \times 0\) so the initial portion of the reference orbit is a sequence of \(0\) steps in the first iteration until the first \(c\) at the start of the second iteration. For non-zero or multiple critical points it would be more complicated.
# 6 Implementation
Example implementation:
git clone https://code.mathr.co.uk/fractal-bits.git
cd fractal-bits/mandelbrot-arbitrary-power
make
./znc >100.pgm
display 100.pgm
Browse source: znc.c.