** Note this visualization takes 60s to execute **
Chaotic dynamics can be easily simulated using the Logistic Map. Given the equation:
f(x) = \lambda x (1 - x)
Define the discrete dynamics by:
This visualization looks at these dynamics in two ways:
As we vary the value of \lambda in the equation above and examine the long term value of f^n(x0) (see plot on left, the x-axis is \lambda), around \lambda = 3 the value goes from converging to a fixed point to going between two numbers (period 2). As we further increase \lambda the period goes from 4, 8, 16, ..., to all over the place (chaos). Every once in awhile you will see it go periodic again, and this number can even be odd (1,3,5,..). The diagram on the left illustrates this behavior and is called the bifurcation diagram. There are many properties for this diagram that are fun to explore.
xxxxxxxxxx
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
fill: #000;
}
.curve {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
.line {
fill: none;
stroke: orange;
stroke-width: 1.5px;
}
.chaos {
fill: none;
stroke: #000;
stroke-width: 1.5px;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.js"></script>
<script>
var margin = {top: 20, right: 40, bottom: 30, left: 50},
w1 = 480 - margin.left - margin.right,
w2 = 480 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
x = d3.range(0,1.001,0.001),
y = [],
bifur = [];
// Unscaled logistic map
x.forEach(function (d){
y.push(d*(1-d));
});
var svg = d3.select("body").append("svg")
.attr("width", w1 + w2 + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
// The Cobweb Map
var g1 = svg
.append("g").attr("class","logistic")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g1
.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(" + 0 + "," + height + ")");
g1
.append("svg:g")
.attr("class", "y axis");
var xScale = d3.scale.linear().domain([0,1]).range([0, w1]),
yScale = d3.scale.linear().domain([0,1]).range([height, 0]),
xAxis = d3.svg.axis().scale(xScale).orient("bottom"),
yAxis = d3.svg.axis().scale(yScale).orient("left");
g1.select("g.x.axis").call(xAxis);
g1.select("g.y.axis").call(yAxis);
// The Bifurcation Diagram
var g2 = svg.append("g").attr("class","bifur")
.attr("transform","translate(" + (margin.left + margin.right + w1) + "," + margin.top + ")");
g2
.append("svg:g")
.attr("class", "x2 axis")
.attr("transform", "translate(0," + height + ")");
g2
.append("svg:g")
.attr("class", "y2 axis");
var x2Scale = d3.scale.linear().domain([1,4]).range([0, w2]),
y2Scale = yScale,
x2Axis = d3.svg.axis().scale(x2Scale).orient("bottom"),
y2Axis = d3.svg.axis().scale(y2Scale).orient("left");
g2.select("g.x2.axis").call(x2Axis);
g2.select("g.y2.axis").call(y2Axis);
// The Lines
var line = d3.svg.line()
.x(function(d) { return xScale(d); })
.y(function(d) { return yScale(d); });
var curve = d3.svg.line()
.x(function(d,i) { return xScale(x[i]); })
.y(function(d) { return yScale(d); });
var lcurve = g1.selectAll("path.curve").data([y]);
lcurve.enter().append("path")
.attr("class", "curve")
.attr("d", curve);
var xy = g1.selectAll("path.line").data([x]);
xy.enter().append("path")
.attr("class", "line")
.attr("d", line);
var chaos = d3.svg.line()
.x(function(d) { return xScale(d.x); })
.y(function(d) { return yScale(d.y); });
d3.transition()
.duration(60000)
.tween("chaos", function() {
var λ = d3.interpolate(1,4);
return function(k) {
var N = bifur.length-1,
x0 = 0.2,
dynamics = [];
// Redraw logistic map curve
lcurve.attr("d",curve);
// Logistic Map Curve
curve
.y(function(d) { return yScale(λ(k)*d); });
// Calculate the dynamics f(f(f...(x))) = λ*x*(1-x)
var f = [{x: x0, y:0}]
for (var i=1; i<100 ;i++){
var last = f[f.length-1],
fx = λ(k)*last.x*(1-last.x);
f.push({x: last.x, y: fx }) ;
f.push({
x: fx,
y: fx
})
dynamics.push({x:λ(k), y:fx});
if (Math.abs(fx - last.x) < 0.001) break;
}
if (dynamics.length >= 50) dynamics.slice(dynamics.length-50,dynamics.length);
bifur = bifur.concat(dynamics);
// Bifurcation Diagram
var bf = g2.selectAll("circle").data(bifur);
bf.enter().append("circle")
.attr("r",function (d) { return 0.3;})
.attr("cx",function (d) {return x2Scale(d.x);})
.attr("cy",function (d) {return y2Scale(d.y);});
// Cobweb line
var l = g1.selectAll("path.chaos").data([f]);
l.enter().append("path")
.attr("class", "chaos")
.attr("d", chaos);
l.attr("d", chaos);
l.exit().remove();
}
});
</script>
Modified http://d3js.org/d3.v3.js to a secure url
https://d3js.org/d3.v3.js