Skip to the content.

Bifurcations

While trying Mathematica 12.0 on the Raspberry Pi 4 I noticed the performance improvements. Since a calculation of a bifurcation was the screenshot for the wikipedia page I tried to replicate the output. I was looking for this:

Mathematica bifurcation

Rendered in 40 seconds with Mathematica 8.0.0 in 2011. But the 40 seconds didn’t compute for my little ARM CPU in Mathematica. Jupyter just took 4 seconds … Here are the results by language:

Mathematica

I tried to copy this code, but the CPU run hot to 85 °C on all 4 cores. And several minutes later it produced error messages, but no graph. Error messages like this

(kernel 2) Set::write: Tag Times in (logistic (Drop[#1,10000]&))[{0.6586014743446188, logistic[3.5228,0.6586014743446188], logistic[3.5228,logistic[3.5228,0.6586014743446188]], <<46>>, logistic[3.5228,logistic[3.5228,logistic[3.5228, logistic[3.5228,logistic[3.5228,logistic[<<2>>]]]]]],<<10050>>}] is Protected.

That’s the code. We went to Initial k: 10000

bifurcate[f_, a0_, k0_, k_, while_: (True &)] := 
  NestWhileList[f, a0, while, 2, k0 + k - 1] // 
    Drop[#, k0] & logistic = {r, y} -> ry (1 - y);

Row@{"Inital value: ", a0 = RandomReal[{0.1, 0.9}]}
Row@{"Points per r: ", density = 10^2}
Row@{"Inital k: ", k0 = 10^4}
Row@{"Time taken: ", 
  Timing[plotdata = 
      ParallelTable[{ConstantArray[r, density], 
          bifurcate[logistic[r, #] &, a0, k0, density]}^T, {r, 3.5, 
         4, 0.0001}] // Flatten[#, 1] &; ][[1]], " s"}
Row@{"Data length: ", plotData // Length}
ListPlot[plotData, PlotStyle -> {Pointsize[0], Opacity[0.1]}, 
 ImageSize -> 800, PlotRange -> {All, {0, 1}}; LabelStyle -> 16]

Jupyter notebook

import numpy as np
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 9))

# Logistic function implementation
def logistic_eq(r,x):
    return r*x*(1-x)

# Create the bifurcation diagram
def bifurcation_diagram(seed, n_skip, n_iter, step=0.0001, r_min=0):
    print("Starting with x0 seed {0}, skip plotting first {1} iterations, then plot next {2} iterations.".format(seed, n_skip, n_iter));
    # Array of r values, the x axis of the bifurcation plot
    R = []
    # Array of x_t values, the y axis of the bifurcation plot
    X = []
    
    # Create the r values to loop. For each r value we will plot n_iter points
    r_range = np.linspace(r_min, 4, int(1/step))

    for r in r_range:
        x = seed;
        # For each r, iterate the logistic function and collect datapoint if n_skip iterations have occurred
        for i in range(n_iter+n_skip+1):
            if i >= n_skip:
                R.append(r)
                X.append(x)
                
            x = logistic_eq(r,x);
    # Plot the data    
    plt.plot(R, X, ls='', marker=',')
    plt.ylim(0, 1)
    plt.xlim(r_min, 4)
    plt.xlabel('r')
    plt.ylabel('X')
    plt.show()

bifurcation_diagram(0.2, 100, 10, r_min=3.55)

4 seconds later I got the results:

Starting with x0 seed 0.2, skip plotting first 100 iterations, then plot next 10 iterations.

bifurcation

Matlab