Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download

Lecture slides for UCLA LS 30B, Spring 2020

Views: 14466
License: GPL3
Image: ubuntu2004
Kernel: SageMath 9.3
import numpy as np import plotly.graph_objects from ipywidgets import interactive_output, VBox, HBox, Button, SelectionSlider
mydefault = plotly.graph_objects.layout.Template() mydefault.layout.xaxis.showgrid = False mydefault.layout.yaxis.showgrid = False mydefault.layout.xaxis.showline = True mydefault.layout.yaxis.showline = True mydefault.layout.yaxis.linewidth = 2 mydefault.layout.xaxis.ticks = "outside" mydefault.layout.yaxis.ticks = "outside" mydefault.layout.hovermode = False mydefault.layout.dragmode = "pan" mydefault.layout.scene.hovermode = False mydefault.layout.xaxis.showspikes = False mydefault.layout.yaxis.showspikes = False mydefault.layout.scene.xaxis.showspikes = False mydefault.layout.scene.yaxis.showspikes = False mydefault.layout.scene.zaxis.showspikes = False plotly.io.templates["mydefault"] = mydefault plotly.io.templates.default = "mydefault"

Learning goals:

  • Know what a period-doubling bifurcation is.

  • Know that in a dynamical system with chaotic behavior, the system often undergoes a series of bifurcations as a parameter is changed, causing its behavior to change from stable equilibrium to stable oscillations to chaos.

The discrete-time logistic model: Xt+1=4Xt(1Xt) X_{t+1} = 4 X_t \cdot ( 1 - X_t )

def logistic_interactive(): X_next(X) = 4*X*(1 - X) t_range = srange(1001) solution = [0.42] for t in t_range[:-1]: solution.append(X_next(solution[-1])) solution = np.array(solution, dtype=float) fig = plotly.graph_objects.FigureWidget() fig.layout.showlegend = False fig.layout.margin.update(t=30, r=0) fig.layout.xaxis.title.text = "t" fig.layout.yaxis.title.text = "X" fig.layout.xaxis.range = (0, 51) fig.layout.yaxis.range = (0, 1.02) fig.add_scatter(x=[], y=[], marker_color="blue", line_color="gray") timeseries = fig.data[-1] def update(n, connect): with fig.batch_update(): timeseries.mode = "markers+lines" if connect else "markers" timeseries.x = t_range if isinstance(n, str) else t_range[:n+1] timeseries.y = solution if isinstance(n, str) else solution[:n+1] n = slider(srange(51) + ["∞"], label="Iterations:") connect = checkbox(True, label="Connect the dots") output = interactive_output(update, dict(n=n, connect=connect)) display(HBox((n, connect)), fig, output) return fig
widget0 = logistic_interactive()

The discrete-time logistic model:

Xt+1=rXt(1Xt)X_{t+1} = r X_t \cdot ( 1 - X_t )

We have been only considering the case where r=4r = 4.

But what if we vary rr?

def logistic_bifurcations(): t_range = srange(1000) discard = 100 show = 150 t_axis_range = (0, 50) r_values = [round(r, 2) for r in srange(1, 3.4, 0.1) + srange(3.45, 4.001, 0.01)] initial_state = 0.42 fig = plotly.subplots.make_subplots(rows=int(1), cols=int(2), subplot_titles=("Time series", "")) fig = plotly.graph_objects.FigureWidget(fig) fig.layout.showlegend = False fig.layout.margin.update(t=30, r=0) fig.layout.xaxis.title.text = "t" fig.layout.yaxis.title.text = "X" fig.layout.xaxis.range = t_axis_range fig.layout.yaxis.range = (0, 1.02) fig.layout.xaxis2.visible = False fig.layout.yaxis2.visible = False fig.add_scatter(row=int(1), col=int(1), x=t_range, marker_color="blue", line_color="gray") timeseries = fig.data[-1] def update(r, connect): X_next = fast_float(r*x*(1 - x), x) X = initial_state solution = np.zeros([len(t_range)], dtype=float) for t in t_range: solution[t] = X X = X_next(X) with fig.batch_update(): timeseries.mode = "markers+lines" if connect else "markers" timeseries.y = solution r = slider(r_values, default=1) connect = checkbox(True, label="Connect the dots") output = interactive_output(update, dict(r=r, connect=connect)) display(HBox((r, connect)), fig, output) return fig
widget1 = logistic_bifurcations()
def logistic_bifurcation_diagram(): t_range = srange(1000) discard = 875 show = 150 t_axis_range = (0, 50) r_values = [round(r, 2) for r in srange(2.5, 3.41, 0.1) + srange(3.43, 4.001, 0.01)] r_finished = set() initial_state = 0.42 fig = plotly.subplots.make_subplots(rows=int(1), cols=int(2), subplot_titles=("Time series", "Bifurcation diagram")) fig = plotly.graph_objects.FigureWidget(fig) fig.layout.showlegend = False fig.layout.margin.update(t=50, r=0) fig.layout.xaxis.title.text = "t" fig.layout.yaxis.title.text = "X" fig.layout.xaxis2.title.text = "r" fig.layout.yaxis2.title.text = "X" fig.layout.xaxis.range = t_axis_range fig.layout.yaxis.range = (0, 1.02) fig.layout.xaxis2.range = (r_values[0] - 0.03, r_values[-1] + 0.03) fig.layout.yaxis2.range = (0, 1.02) fig.add_scatter(row=int(1), col=int(1), x=t_range, mode="markers+lines", marker_color="blue", line_color="gray") timeseries = fig.data[-1] fig.add_scatter(row=int(1), col=int(2), x=[], y=[], mode="markers", marker_color="blue", marker_symbol="square", marker_size=2) bifurcation_diagram = fig.data[-1] fig.add_scatter(row=int(1), col=int(2), x=[], y=[], mode="markers", marker_color="red", marker_size=4) bifurcation_new = fig.data[-1] def update_r(change=None): X_next = fast_float(r.value*x*(1 - x), x) X = initial_state solution = np.zeros([len(t_range)], dtype=float) for t in t_range: solution[t] = X X = X_next(X) with fig.batch_update(): timeseries.y = solution if len(bifurcation_new.x) and bifurcation_new.x[0] not in r_finished: bifurcation_diagram.x = np.append(bifurcation_diagram.x, bifurcation_new.x) bifurcation_diagram.y = np.append(bifurcation_diagram.y, bifurcation_new.y) r_finished.add(bifurcation_new.x[0]) if auto_checkbox.value: add_to_diagram(solution) else: bifurcation_new.x = [] bifurcation_new.y = [] def add_to_diagram(values): X_values = set(values[discard:].round(3)) bifurcation_new.x = [r.value] * len(X_values) bifurcation_new.y = list(X_values) def show_lines(change): with fig.batch_update(): timeseries.mode = "markers+lines" if connect_checkbox.value else "markers" timeseries.marker.size = 6 if connect_checkbox.value else 3 # Default is 6 def button_clicked(button): with fig.batch_update(): add_to_diagram(timeseries.y) r = SelectionSlider(options=r_values, value=r_values[0], description="r", continuous_update=False) r.observe(update_r, "value") connect_checkbox = checkbox(True, label="Connect the dots") connect_checkbox.observe(show_lines, "value") add_button = Button(description="Add to diagram") add_button.on_click(button_clicked) auto_checkbox = checkbox(False, label="Auto mode") update_r() display(HBox((r, connect_checkbox, add_button, auto_checkbox)), fig) return fig
widget2 = logistic_bifurcation_diagram()

Bifurcation diagram of the discrete-time logistic model

Conclusions:

  • A period-doubling bifurcation is a bifurcation that occurs in a system that is already experiencing oscillatory behavior: as a parameter is changed, the period of the oscillations suddenly doubles.

  • A system that exhibits chaotic behavior often has a parameter that can be changed, resulting in the following sequence of behavior types: equilibriumoscillationcomplex oscillationchaos \text{equilibrium} \to \text{oscillation} \to \text{complex oscillation} \to \text{chaos}

  • The above sequence is visualized in the type of bifurcation diagram shown in the previous slide.