Metropolis-Hastings Example in Javascript
by jrab227
HTML
<div id="vis"></div>
CSS
rect {
fill: steelblue;
shape-rendering: crispEdges;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
JavaScript
// Taking 1 million simulations of the standard normal
var values = []
var state = 0
for (var i = 0; i < 1000000; i++) {
state = MetropolisHastings(stdNormal, state, createNewStateFrom);
values.push(state)
}
//Drawing the data
drawData(values)
function drawData(values){
var width = 300,
height = 400,
padding = 30;
var svg = d3.select("#vis")
.append("svg")
.attr("height", height)
.attr("width", width)
var data = d3.layout.histogram()(values);
var x = d3.scale.linear()
.domain([-4, 4])
.range([padding, width-padding]);
var y = d3.scale.linear()
.domain([0, d3.max(data, function(d) { return d.y; })])
.range([height, 0]);
var bar = svg.selectAll("rect")
.data(data)
.enter().append("rect")
.classed("bar", true)
.attr("x", function(d){
return x(d.x)
})
.attr("y", function(d) {
return y(d.y)
})
.attr("width", (x(data[0].dx) - x(0)) * .95 )
.attr("height", function(d) {
return height - y(d.y) - padding;
});
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height - padding) + ")")
.call(xAxis);
}
//Utility functions
function MetropolisHastings(probability, state, generateAState) {
var aPossibleState = generateAState(state);
var transitionOdds = probability(aPossibleState) / probability(state);
var newState
if (Math.random() <= transitionOdds) {
newState = aPossibleState;
} else {
newState = state;
}
return newState;
}
function stdNormal(X) {
var v = (1/Math.sqrt(Math.PI * 2)) * Math.exp( -X * X / 2)
return v
}
function createNewStateFrom(X){
var newState
if (Math.random() <= .5) {
newState = X + .1
} else {
newState = X - .1
}
return...