This software has been developed as part of the (optional) homeworks of the MOOC Introduction to Dynamical Systems and Chaos (Summer, 2016), leaded by David Feldman, Professor of Physics and Mathematics at College of the Atlantic.
For more details about the chaos and sync theories, see the Steven Strogatz's books Sync and Nonlinear Dynamics and Chaos. Or the David Feldman's introductory book Chaos and Fractals: An Elementary Introduction.
We start by considering a very simple model of a population where there is some limit to growth:
f(x) = rx(1-x)
r is a growth parameter, x is measured as a fraction of the annihilation parameter (the variable x is thus always between 0 and 1), and f(x) gives the population next year given x, the population this year.
By iterating this function we can create a dynamical system, that is, a system that evolves in time according to a well-defined, unchanging rule. The number we start with is called the seed or initial condition. The resulting sequence of numbers
x0
x1 = f(x0)
...
xn = f(xn-1)
is called the itinerary or orbit (or sometimes a time series or a trajectory).
The software is written in Python and compatible with both Python 2 and 3 (tested on Fedora 24 through Fedora 30 Workstation), but if you want to run it under Python 2, you need to modify the shebang line of each Python script.
- legraph.py -- Plot Logistic, Cube, and Sine orbits
- Iterate a logistic, cube, or sine equation for different r and x0 values and make time series plots;
- finalstate.py -- Plot Final State Diagrams
- Iterate a logistic, cube, or sine equation for different r and x0 values and plot the final state diagram;
- bifurcation.py -- Plot Bifurcations Diagrams
- Plot the bifurcation diagram of a cubic, logistic (default), or sine maps;
- lelib.py -- Object-oriented core library for computing and plotting
- A simple object-oriented Python library for computing time series and plotting orbits, final state and bifurcations diagrams.
The core library requires the (widely-available and very popular) Python libraries NumPy
and matplotlib
.
When testing dynamic-systems-and-chaos
it's easier to use a virtual environment.
Python 3 presents a few steps to ensure you are actually installing and working with files inside of your virtual environment.
Refer to the original Python documentation
Installing Packages Using pip and virtualenv
for the official instructions on this topic.
Create a virtual environment named .venv
inside the git repository root:
$ git clone https://github.com/madrisan/dynamic-systems-and-chaos.git
$ cd dynamic-systems-and-chaos
$ python3 -m venv .venv
Now that a virtualenv has been created in our .venv
folder we should activate the virtual environment.
$ source .venv/bin/activate
(.venv)$
The virtual environment contains no extra modules needed to run dynamic-systems-and-chaos
.
Therefore, we want to install the dependencies from the requirements.txt
file.
However, we want to specify that we're using the virtual environment pip3
:
(.venv)$ pip install --upgrade pip
(.venv)$ .venv/bin/pip3 install -r ../requirements.txt
If you get a compilation error because ft2build.h
is missing
src/checkdep_freetype2.c:1:10: fatal error: ft2build.h: No such file or directory
1 | #include <ft2build.h>
| ^~~~~~~~~~~~
compilation terminated.
error: command '/usr/bin/gcc' failed with exit code 1
you need to install the development package of freetype (sudo dnf install freetype-devel
on Fedora).
You are now ready to start running and testing dynamic-systems-and-chaos
with a virtual environment using Python 3.
(.venv)$ python3 ./legraph.py --help
usage: legraph.py [-h] -0 X0 [-1 X1] [-d] -r R [-s S] -n N
[-m {logistic,cubic,sine}]
Plot of Logistic Equation Time Series v.4 (stable)
Copyright (C) 2016-2018 Davide Madrisan <[email protected]>
License: Apache License 2.0 (Apache-2.0)
optional arguments:
-h, --help show this help message and exit
-0 X0, --x0 X0 1st initial condition
-1 X1, --x1 X1 2nd initial condition (optional)
-d, --dots-only do not connect the dots with lines (default: False)
-r R, --rate R growth rate parameter
-s S, --skip S skip plotting the first 's' iterations
-n N, --steps N number of iterations
-m {logistic,cubic,sine}, --map {logistic,cubic,sine}
select the desired map (logistic, cubic, or sine)
Examples:
# time series with a stable fixed point
legraph.py -0 0.4 -r 3.2 -n 50
legraph.py -0 0.4 -1 0.45 -r 3.2 -n 50
# chaotic results (randon output)
legraph.py --x0 0.2 --x1 0.2000001 -r 4.0 -n 50
legraph.py -0 0.2 -r 3.6 -n 5000 --dots-only
legraph.py -0 0.9 -r 4.5 -n 50 --map=cubic
legraph.py -0 0.4 -r 0.8 -n 50 --map=sine
$ (.venv)$ python3 ./finalstate.py --help
usage: finalstate.py [-h] [-0 X0] -r R [-s S] [-n N]
[-m {logistic,cubic,sine}]
Plot of the Final State Diagram v.4 (stable)
Copyright (C) 2016-2018 Davide Madrisan <[email protected]>
License: Apache License 2.0 (Apache-2.0)
optional arguments:
-h, --help show this help message and exit
-0 X0, --x0 X0 initial condition (default: 0.5)
-r R, --rate R growth rate parameter
-s S, --skip S skip plotting the first 's' iterations (default: 2000)
-n N, --steps N number of iterations (default: 1000)
-m {logistic,cubic,sine}, --map {logistic,cubic,sine}
select the desired map (logistic, cubic, or sine)
Examples:
finalstate.py -r 3.492
finalstate.py -r 3.614 -s 200 -n 300
finalstate.py -0 0.4 -r 3.2 -s 10 -n 50
finalstate.py -0 0.8 -r 6.2 -n 20 --map=cubic
$ (.venv)$ python3 ./bifurcations.py --help
Plot the Bifurcation Diagram of Logistic, Cubic, and Sine Maps v.4 (stable)
Copyright (C) 2016-2018 Davide Madrisan <[email protected]>
License: Apache License 2.0 (Apache-2.0)
usage: bifurcations.py [-h] [-r R] [-y Y] [-s S] [-n N]
[-m {logistic,cubic,sine}]
optional arguments:
-h, --help show this help message and exit
-r R, --rate R range of the growth rate parameter (default: the
entire range)
-y Y, --people Y normalized range of the population (default: the
entire range)
-s S, --skip S skip plotting the first 's' iterations (default: 200)
-n N, --steps N number of iterations (default: 100)
-m {logistic,cubic,sine}, --map {logistic,cubic,sine}
select the desired map (logistic, cubic, or sine)
Examples:
bifurcations.py -r 1:4
bifurcations.py -r 4:6.5 --map=cubic
bifurcations.py --map=sine -s 200 -n 200
bifurcations.py -r 3.:4. -s 500 -n 600
bifurcations.py -r 3.5:3.6 -y .3:.6 -s 800 -n 1000
The following example shows a periodic orbit with two fixed points.
In mathematics, a fixed point of a function is an element of the function's domain that is mapped to itself by the function. That is to say, c is a fixed point of the function f(x) if and only if f(c) = c
# initial condition: 0.4 - growth rate: 3.2 - 50 iterations starting from 0 (x0)
(.venv)$ python3 ./legraph.py --x0 0.4 -r 3.2 -n 50
For r = 4 (and other values), the orbit is aperiodic: it never repeats. Applying the same function over and over again does not result in periodic behavior.
We can use legraph.py
to compare time series for two different initial conditions.
(.venv)$ python3 ./legraph.py --x0 0.2 --x1 0.2000001 -r 4.0 -n 50
The bottom plot is the difference between the two time series in the top plot.
You can note that the two orbits start very close together and eventually end up far apart. This is known as sensitive dependence on initial conditions (SDIC), or the butterfly effect.
The latter name cames from the title of a 1979 paper by Ed Lorenz called "Predictability: Does the Flap of a Butterfly's Wings in Brazil Set Off a Tornado in Texas?". The idea is that in a chaotic system, small disturbances grow exponenfially fast, rendering long-term prediction impossible.
More precisely, for any initial condition x there is another initial condition very near to it that eventually ends up far away. To predict the behavior of a system with SDIC requires knowing the initial condition with impossible accuracy. Systems with SDIC are deterministic yet unpredictable in the long run.
The aperiodic orbits are always bounded but do not necessarily cover all the domain. They can present one or more holes.
(.venv)$ python3 ./legraph.py --x0 0.2 -r 3.6 -n 500
We can increase the number of iterations and add the command line switch --dots-only
in order to better visualize this
behaviour.
(.venv)$ python3 ./legraph.py --x0 0.2 -r 3.6 -n 5000 --dots-only
For a given r value, the program finalstate.py
will iterate 1000 times by default (-s
),
then plot the next 2000 iterates (-n
) on the unit interval.
The resulting plot is called a final-state diagram.
The number of skipped (-s
) and plotted (-n
) iterations can be manually tuned as shown in the following example.
(.venv)$ python3 ./finalstate.py -r 3.614 -s 200 -n 300
Here you can find an example of a final-state diagram generated by a periodic orbit.
(.venv)$ python3 ./finalstate.py -r 3.2 -s 10 -n 50
We can "glue" together the final state diagrams made for different values of the parameter r to make a bifurcation diagram, that lets us see, all at once, all the different behaviour exhibited by a dynamical system as we vary the parameter r.
The script bifurcations.py
lets us plot the bifurcation diagram of the logistic map (the map selected by default)
f(x) = rx(1-x)
(.venv)$ python3 ./bifurcations.py -r 2:4 -n 300 -s 400
We can plot the bifurcation diagram of the cubic map
f(x) = rx2(1-x)
by adding the command-line switch --map=cubic
(.venv)$ python3 ./bifurcations.py -r 4:6.5 --map=cubic
And finally plot the bifurcation diagram of the sine map
f(x) = r sin(ฯxโ2)
by using the command-line switch --map=sine
(.venv)$ python3 ./bifurcations.py --map=sine -s 200 -n 200
You can note the similarities between the three bifurcation diagrams (and all the ones generated by the class of iterated functions that map an interval to itself and have a single quadratic maximum.)
This is a well known result that came from the amazing phenomenon of the universality of the period-doubling route to chaos (also known as Feigenbaum's constant). The physicist Mitchell Feigenbaum in fact showed that there are certain universal laws governing the transition from regular to chaotic behaviour. His predictions were confirmed in experiments on electronic circuits, swirling fluids, chemical reactions, semiconductors, and heart cells. Feigenbaum's laws transcended the superficial differences between heart cells and and silicon semiconductors. Different materials, the same laws of chaos!