Skip to content

Instantly share code, notes, and snippets.

@eliangcs
Created Jan 12, 2016
Embed
What would you like to do?
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.background {
fill: #e7e7e7;
}
.axis path,
.axis line {
fill: none;
stroke: #fff;
shape-rendering: crispEdges;
}
.line text {
font: bold 14px sans-serif;
}
.axis text {
font: 10px sans-serif;
}
.line path {
fill: none;
stroke: #000;
stroke-width: 1.2px;
stroke-linejoin: round;
}
.line:hover text {
fill: red;
}
.line:hover path {
stroke: red;
}
.point {
fill: #000;
}
.svg {
border: 1px solid #000;
}
.result {
color: #05c;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<div>
Mutation Function:
<select id="mutation">
<option value="wild" selected>Wild</option>
<option value="neighbor">I Love My Neighbor</option>
<option value="double">Double Personality</option>
</select>
</div>
<div>
Acceptance Probability:
<select id="acceptance">
<option value="one">Always One</option>
<option value="metropolis" selected>Metropolis</option>
</select>
</div>
<div>
<button type="button" id="start">Start</button>
</div>
<h2 class="result">Integral result: <span class="integral">-</span></h2>
<script>
var width = 540,
height = 320,
xmin = 0,
xmax = Math.PI,
ymin = 0,
ymax = 1.0,
xscale = d3.scale.linear(),
yscale = d3.scale.linear(),
sine = d3.svg.line(),
svg = d3.select('body').append('svg'),
decor = svg.append('g'),
graph = svg.append('g'),
sampleSize = 100,
sampleCount = 0,
delay = 10,
integral = 0.0,
mutationSelect = d3.select('#mutation'),
acceptanceSelect = d3.select('#acceptance'),
startButton = d3.select('#start'),
integralResult = d3.select('.integral');
function reset() {
integral = 0.0;
sampleCount = 0;
graph.selectAll('*').remove();
integralResult.text('-');
}
xscale.domain([xmin, xmax])
.range([0, width]);
yscale.domain([ymin, ymax])
.range([height, 0]);
svg.attr({
width: width,
height: height,
class: 'svg'
});
function draw(x, y, area) {
var h = y;
var w = area / h;
x = xscale(x - w * 0.5);
y = yscale(y);
w = xscale(w);
graph.append('rect').attr({
x: x,
y: y,
width: w,
height: height - y,
fill: '#06c',
opacity: 0.2
});
}
function f(x) {
if (x >= 0.0 && x <= Math.PI) {
return Math.sin(x);
}
return 0.0;
}
var mutationFunctions = {
wild: function(x) {
return [Math.random() * Math.PI, 1.0 / Math.PI];
},
neighbor: function(x) {
var delta = Math.random() - 0.5;
return [x + delta, 1];
},
double: function(x) {
var wild = mutationFunctions.wild;
var neighbor = mutationFunctions.neighbor;
var result, x2, pdf;
if (Math.random() > 0.1) {
result = neighbor(x);
pdf = 0.9;
} else {
result = wild(x);
pdf = 0.1;
}
return [result[0], result[1] * pdf];
}
};
var acceptanceProbabilities = {
one: function(x, x2) {
return 1.0;
},
metropolis: function(x, x2) {
return Math.min(1.0, f(x2) / f(x));
}
};
function sample(mutate, accept, x, pdf) {
var result = mutate(x);
var x2 = result[0],
pdf2 = result[1];
a = accept(x, x2);
if (Math.random() < a) {
x = x2;
pdf = pdf2;
}
y = f(x);
var d = y / (pdf * sampleSize);
integral += d;
draw(x, y, d);
sampleCount++;
if (sampleCount < sampleSize) {
setTimeout(function() {
sample(mutate, accept, x, pdf);
}, delay);
} else {
integralResult.text(integral);
}
}
function start() {
reset();
var mutate = mutationFunctions[mutationSelect.property('value')];
var accept = acceptanceProbabilities[acceptanceSelect.property('value')];
var x0 = Math.random() * Math.PI;
sample(mutate, accept, x0, 1.0 / Math.PI);
}
startButton.on('click', start);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment