2

Inspired by 3blue1brown I'm trying to graph the escape (divergence) of the Tetration function with Python –– something akin to this beautiful graphic on Wikipedia.

def tetration_com(base, tol=10**-15, max_step=10**6):
  # returns t, the infinite tetration of base.
  # if t does not converge, the function returns an escape value, aka how fast it diverges..

  t = 1.0
  step = 0
  escape = None
  ln_base = cmath.log(base)

  t_last = 0
  try:
    while(abs(t - t_last) > tol):
      if(step > max_step):
        raise OverflowError
      t_last = t
      t = cmath.exp(ln_base*t)   # [ base^t == e^(ln(base)*t) ]
      step += 1

  except(OverflowError):
    t = None
    escape = 1000/step
    # the escape value is is inversely related to the number of steps it took
    # us to diverge to infinity

  return t, escape

I'm trying to make it work with a meshgrid in order to graph the escape on the x-y plane. Python doesn't like that the output is 2 unpacked variables (the limit, or the escape) – this I can definitely solve by splitting into two functions.

But another issue is that the complex-math operations (cmath.log, cmath.exp) are only working well with scalars...

I tried to vectorize the function:

nx, ny = 700, 500
x, y = np.linspace(-3.5, 3.5, nx), np.linspace(-2.5, 2.5, ny)
xv, yv = np.meshgrid(x, y)

tetration_vec = np.vectorize(tetration_com)
t, escape = tetration_vec(xv + yv*1j, max_step=500)

But it's running forever.

Any advice on how to deal with the complex-math operations and the vectorization?

  • Why aren't you using the functions provided by numpy for exp and log? – amzon-ex May 20 '20 at 20:21
  • this [How to express tetration function, for complex numbers](https://stackoverflow.com/a/56735614/2521214) might interests you , its GLSL based fractal render you are aiming for... the links inside are also worth looking into as they deals with histogram based coloring to achieve best image colorfulness possible... – Spektre May 21 '20 at 12:55
  • glad to be of help... it was really fun derive and code that ... GLSL is massively parallel granting RT speeds for this (I can smoothly zoom with high enough fps) however brings up a lot of accuracy and debugging problems and limitations so sometimes even simple math does not work as intended. – Spektre May 24 '20 at 06:42

1 Answers1

2

Here is how I graphed my escape in the end:

def tetration_com(base, tol=10**-15, max_step=10**6, max_val=10**2):
  # returns t, the infinite tetration of base.
  # if t does not converge, the function returns an escape value
  # aka how fast it diverges..

  t = 1.0
  step = 0
  escape = None

  t_last = 0
  try:
    while(abs(t - t_last) > tol):
      if(step > max_step or abs(t) > max_val):
        raise OverflowError
      t_last = t
      t = pow(base, t)
      step += 1
  except(OverflowError):
    t = None
    escape = 1000/step
    # the escape value is is inversely related to the number of steps it took
    # us to diverge to infinity

  return t, escape

Vectorized helper function:

def tetra_graph_escape(real, imag, tol=10**-15, max_step=10**3, max_val=10**2):
  return np.array([np.array([tetration_com(r + im*1j, tol=tol, max_step=max_step, max_val=max_val)[1]
                             for im in imag]) for r in real])

Graphing:

# graph our escape:
nx, ny = 700, 500
x, y = np.linspace(-3.5, 3.5, nx), np.linspace(-2.5, 2.5, ny)

val, escape = tetra_graph_conv(x, y), tetra_graph_escape(x, y)

import matplotlib.pyplot as plt

for r in range(len(escape)):
  for c in range(len(escape[0])):
    if escape[r][c] is None:
      escape[r][c] = -100

escape[460][250]

plt.contour(escape)

Contour graph of Tetration escape:

img

Spektre
  • 49,595
  • 11
  • 110
  • 380