We are going to implement the logistic map and the transfer operator for it.
Let
A python implementation would look like this:
def logistic_map(r, x):
"""
Returns the next value for the logistic map with parameter r.
fᵣ(x) = r·x·(1 - x)
Paramters
---------
r : double
Parameter of the logistic map, r∈[0, 4]
x : double or ndarray
points to evaluate fᵣ(x) at
Returns
-------
fx : double or ndarray
values of fᵣ(x)
"""
return r * x * (1 - x)
A plot of the function can be seen here:
We can use it iteratively:
x_0 = 0.45
print("| iter | value |\n|---|")
for j in range(5):
print(f"| {j: 4d} | {x_0: .7f} |")
# update the value
x_0 = f_r(x_0)
print("")
iter | value |
---|---|
0 | 0.4500000 |
1 | 0.8761500 |
2 | 0.3841296 |
3 | 0.8374721 |
4 | 0.4818385 |
x_0 = 0.45
# You can use reduce for repeated function evaluation
orbit = np.array(functools.reduce(
lambda result, next_item: result + [f_r(result[-1])],
range(10), [x_0]))
We have our map
But we want to think of densities of initial conditions. So think of a function
\(ρ ∈ X([0, 1])\) where we don’t want to be precise about what X is (e.g.
What happens under one iteration of \(f_r\)? Answer is the Frobenius-Perron operator
A$(Tρ)(y) := ∫\limits_0^1 δ(y - f_r(x)) ρ(x)\mathrm{d}x$
One common trick:
For us this means:
This means:
Side Note: If
Our aim now is to implement
def const_density(x):
"""
Return the constant density
"""
return np.ones_like(x)
def transfer_operator_logistic_map(r, rho):
"""
Return Tρ for logistic map at r
"""
def mapped_density(y):
"""
Value of (Tρ)(y)
Parameters
----------
y : ndarray
points to evaluate Tρ at
"""
results = np.zeros_like(y)
where_valid = (y < r / 4)
valid_y = y[where_valid]
# 0 = -x(1-x) + y/r = x² - x + y/r
# ½ ± √(¼ - y / r)
x_1 = 0.5 + np.sqrt(0.25 - valid_y / r)
x_2 = 0.5 - np.sqrt(0.25 - valid_y / r)
# dfᵣ / dx = d(rx - rx²)/dx = r - 2·x·r
df_r1 = r - 2 * x_1 * r
df_r2 = r - 2 * x_2 * r
results[where_valid] += (
rho(x_1) / abs(df_r1) + rho(x_2) / abs(df_r2))
return results
return mapped_density
# Try a few iterations:
# note: for r = 3.54, the max is at 0.885
Trho = transfer_operator_logistic_map(r, const_density)
# Trho(0.885 + 1e-9)
# Trho(0.885 - 1e-9)
# print(Trho(np.array([0.4, 0.5, 0.9])))
x = np.linspace(0, 1, 350)
Trho2 = transfer_operator_logistic_map(r, Trho)
Trho3 = transfer_operator_logistic_map(r, Trho2)
Trho4 = transfer_operator_logistic_map(r, Trho3)
plt.grid(True)
plt.xlabel("$x$")
plt.plot(x, Trho4(x))
filename = f"figures/example_plot_T_operator_r={r:07.4f}.svg"
plt.savefig(filename, transparent=True)
print(f"[[file:{filename}]]")