Simulates the long term behavior of the logistic map, xn+1 = rxn(1-xn).
x-axis varies the parameter r, y-axis shows the value of the function
This visual is known as the bifrucation diagram of the logistic map
Every click iterates the function one time
I like this version because it gives you a better sense for the actual behavior of the function and the cycles it creates.
Try double or quadruple clicking to see which points remain fixed (i.e. what points are a part of 2 or 4 cycles)
This the transitions also give you a sense of how a point in a cycle gets moved to the next point in the cycle
Last active
January 8, 2017 01:34
-
-
Save topologicallytony/f95a2c9f89c387409707eba0c5602844 to your computer and use it in GitHub Desktop.
Animated Logistic Map Bifurcation Diagram
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>Animated Logistic Map Bifurcation Diagram</title> | |
<!-- D3.js --> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<!-- Latest compiled and minified CSS --> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> | |
<style type="text/css"> | |
.point { | |
r: 2; | |
fill: steelblue; | |
} | |
</style> | |
</head> | |
<body> | |
<div> | |
Click to Iterate | |
</div> | |
<script type="text/javascript"> | |
//Width and height of the visualization. Smaller numbers will zoom in, larger numbers zoom out | |
var w = 3000; | |
var h = 1500; | |
//padding creates a buffer of white space around the chart to make it a little easier to look at | |
var padding = 150; | |
//Generate Base Dataset | |
//This will hold the final simulated data | |
var dataset = []; | |
//This is used for holding an individual iteration | |
var dataset_temp = []; | |
//How finely to partition [1,4] | |
var numDataPoints = 5000; | |
//Generate a random sample of the space | |
for (var i = 0; i < numDataPoints; i++) { | |
//Partition [1,4] into 4000 buckets | |
var x = ((i * 3) / (numDataPoints - 1)) + 1; | |
//Initialize the input as random numbers. This will iterate over time, so it doesn't matter what it holds | |
var y = Math.random(); | |
dataset.push([x, y]); | |
dataset_temp.push([x, y]); | |
} | |
var xScale = d3.scaleLinear() | |
.domain([1, 4]) | |
.range([padding, w - padding]); | |
var yScale = d3.scaleLinear() | |
.domain([0, 1]) | |
.range([h - padding, padding]); | |
//Create a canvas to display the chart on | |
var svg = d3.select("body") | |
.append("svg") | |
.attr("viewBox", "0 0 " + w + " " + h) | |
//Make the background of the canvas white | |
svg.append("rect") | |
.attr("width", "100%") | |
.attr("height", "100%") | |
.attr("fill", "#fff"); | |
//Create group elements to layer the svg | |
//This is an easy way to make sure things you want on top are on top, and things you want behind stay behind | |
var layer1 = svg.append('g'); | |
var layer2 = svg.append('g'); | |
function iterate(numRecords) { | |
//Load the dataset with a simulation of 64 calls to the logistic map | |
//This will pick up on any cycles <=64 or display chaotic behavior | |
dataset_temp = dataset; | |
dataset = []; | |
for (var j = 0; j < numRecords; j++) { | |
for (var i = 0; i < numDataPoints; i++) { | |
var x = dataset_temp[i][0]; | |
var y = dataset_temp[i][1]; | |
var y_new = x * y * (1 - y); | |
dataset_temp[i][1] = y_new; | |
dataset.push([x, y_new]); | |
} | |
} | |
} | |
function display() { | |
//Plot the data | |
var selected_points = layer2.selectAll(".point") | |
.data(dataset, function(d, i) { | |
return i; | |
}); | |
selected_points.transition().duration(2500).delay(5) | |
.attr("transform", function(d) { | |
return "translate(" + xScale(d[0]) + "," + yScale(d[1]) + ")"; | |
}) | |
selected_points.enter() | |
.append("circle") | |
.attr("class", "point") | |
.attr("transform", function(d) { | |
return "translate(" + xScale(d[0]) + "," + yScale(d[1]) + ")"; | |
}); | |
selected_points.exit().remove(); | |
var text = layer2.selectAll(".text").data([it_no]); | |
text.text(it_no); | |
text.enter() | |
.append("text") | |
.attr("x", padding) | |
.attr("y", 30) | |
.attr("dy", ".5em") | |
.attr("font-size", "64px") | |
.text("0") | |
.attr("class", "text"); | |
} | |
display(); | |
var it_no = 0; | |
// on click transition states | |
function update() { | |
it_no++; | |
dataset = dataset_temp; | |
iterate(1); | |
display(); | |
} | |
d3.select("body") | |
.on("click", update); | |
d3.select("body") | |
.on("touchstart", update); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment