ricma / transfer_operator_logistic_map

A code-along example for the Frobenius-Perron operator of the Logistic Map

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Outlook

We are going to implement the logistic map and the transfer operator for it.

Let $r ∈ [0, 4]$. The logisitic map is given by

$f_r : [0, 1] → [0, 1]$

$x \mapsto r ⋅ x ⋅ (1-x)$

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:

figures/example_logistic_map.svg

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("")
itervalue
00.4500000
10.8761500
20.3841296
30.8374721
40.4818385

Using reduce to Iterate the Map

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]))

Introduction to Transfer Operators

We have our map $f_r:[0, 1] → [0, 1]$

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. $L^1$)

What happens under one iteration of \(f_r\)? Answer is the Frobenius-Perron operator $T$

A$(Tρ)(y) := ∫\limits_0^1 δ(y - f_r(x)) ρ(x)\mathrm{d}x$

One common trick: $δ(g(x)) = ∑\limits_{x_0: g(x_0) = 0} \frac{1}{|g’(x_0)|}δ(x - x_0)$

For us this means: $(Tρ)(y) = ∑\limits_{x_0: f_r(x_0) = y}∫\limits_{0}^{1} \frac{1}{|f_r’(x_0)|}δ(x - x_0)ρ(x)\mathrm{d}x$

This means: $(Tρ)(y) = ∑\limits_{x_0: f_r(x_0) = y} \frac{1}{|f_r’(x_0)|}ρ(x_0)$

Side Note: If $f_r$ would be bijective then we could simplify the above to: Using $x_0 = f_r^{-1}(y)$: $(Tρ)(y) = \frac{1}{|f_r’(f_r^{-1}(y))|}ρ(f_r^{-1}(y))$ Furthermore, if the mapping would be volume preserving (in other words, the Jacobian is 1), then $(Tρ)(y) = ρ(f_r^{-1}(y)) = (ρ\circ f_r^{-1})(y)$

Transfer Operator for the Logistic Map

Our aim now is to implement $(Tρ)(y) = ∑\limits_{x_0: f_r(x_0) = y} \frac{1}{|f_r’(x_0)|}ρ(x_0)$

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}]]")

figures/example_plot_T_operator_r=03.5400.svg

Implementation

About

A code-along example for the Frobenius-Perron operator of the Logistic Map

License:GNU General Public License v3.0