Skip to content

Instantly share code, notes, and snippets.

@emilbayes
Created September 26, 2012 14:42
Show Gist options
  • Save emilbayes/3788444 to your computer and use it in GitHub Desktop.
Save emilbayes/3788444 to your computer and use it in GitHub Desktop.
Acyclic Graphs for PGM Course
class window.AcyclicGraph
color: d3.scale.category20()
constructor: (width, height, elm, data) ->
@svg = d3.select(elm).append("svg")
.attr("width", width)
.attr("height", height)
@defineArrowMarker()
@processData(if typeof data isnt "string" then data else JSON.parse(data))
@force = d3.layout.force()
.nodes(d3.values(@nodes))
.links(@links)
.charge(-500)
.linkDistance(120)
.size([width, height])
.on("tick", @tick)
.start()
@path = @svg.append("g")
.selectAll("path")
.data(@force.links())
.enter()
.append("path")
.style("stroke", "#666")
.style("stroke-width", "3px")
.attr("marker-end", "url(#link)")
@circle = @svg.append("g")
.selectAll("ellipse")
.data(@force.nodes())
.enter()
.append("ellipse")
.attr("class", "node")
.attr("ry", 20)
.attr("rx", 20)
.style("fill", (d) => @color d.index % 20)
.call(@force.drag)
@text = @svg.append("g")
.selectAll("g")
.data(@force.nodes())
.enter()
.append("g")
@text.append("text")
.attr("text-anchor", "middle")
.style("dominant-baseline", "central")
.text((d) -> d.name)
.style("stroke", (d) => @color d.index % 20)
.style("stroke-width", ".5em")
.style("font", '1.1em/1em Optima, Segoe, "Segoe UI", Candara, Calibri, Arial, sans-serif')
@text.append("text")
.attr("text-anchor", "middle")
.style("dominant-baseline", "central")
.text((d) -> d.name)
.style("font", '1.1em/1em Optima, Segoe, "Segoe UI", Candara, Calibri, Arial, sans-serif')
processData: (data) =>
@links = data
@nodes = {}
for link in data
if link.source?
link.source = @nodes[link.source] ? do () => @nodes[link.source] = {name: link.source}
if link.target? and link.target != ""
link.target = @nodes[link.target] ? do () => @nodes[link.target] = {name: link.target}
defineArrowMarker: () ->
@svg.append("defs")
.selectAll("marker")
.data(["link", "highlight"])
.enter()
.append("marker")
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 20)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.style("fill", (d) -> if String(d) == "link" then "#666" else "#ff7f0e")
.append("path")
.attr("d", "M0,-5L10,0L0,5")
tick: () =>
@path.attr "d", (d) ->
dx = d.target.x - d.source.x
dy = d.target.y - d.source.y
dr = Math.sqrt dx * dx + dy * dy
"M#{d.source.x},#{d.source.y} L#{d.target.x},#{d.target.y}"
@circle.attr "transform", (d) -> "translate(#{ d.x } , #{ d.y })"
@text.attr "transform", (d) -> "translate(#{ d.x } , #{ d.y })"
// Generated by IcedCoffeeScript 1.3.3f
(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
window.AcyclicGraph = (function() {
AcyclicGraph.prototype.color = d3.scale.category20();
function AcyclicGraph(width, height, elm, data) {
this.tick = __bind(this.tick, this);
this.processData = __bind(this.processData, this);
var _this = this;
this.svg = d3.select(elm).append("svg").attr("width", width).attr("height", height);
this.defineArrowMarker();
this.processData(typeof data !== "string" ? data : JSON.parse(data));
this.force = d3.layout.force().nodes(d3.values(this.nodes)).links(this.links).charge(-500).linkDistance(120).size([width, height]).on("tick", this.tick).start();
this.path = this.svg.append("g").selectAll("path").data(this.force.links()).enter().append("path").style("stroke", "#666").style("stroke-width", "3px").attr("marker-end", "url(#link)");
this.circle = this.svg.append("g").selectAll("ellipse").data(this.force.nodes()).enter().append("ellipse").attr("class", "node").attr("ry", 20).attr("rx", 20).style("fill", function(d) {
return _this.color(d.index % 20);
}).call(this.force.drag);
this.text = this.svg.append("g").selectAll("g").data(this.force.nodes()).enter().append("g");
this.text.append("text").attr("text-anchor", "middle").style("dominant-baseline", "central").text(function(d) {
return d.name;
}).style("stroke", function(d) {
return _this.color(d.index % 20);
}).style("stroke-width", ".5em").style("font", '1.1em/1em Optima, Segoe, "Segoe UI", Candara, Calibri, Arial, sans-serif');
this.text.append("text").attr("text-anchor", "middle").style("dominant-baseline", "central").text(function(d) {
return d.name;
}).style("font", '1.1em/1em Optima, Segoe, "Segoe UI", Candara, Calibri, Arial, sans-serif');
}
AcyclicGraph.prototype.processData = function(data) {
var link, _i, _len, _ref, _ref1, _results,
_this = this;
this.links = data;
this.nodes = {};
_results = [];
for (_i = 0, _len = data.length; _i < _len; _i++) {
link = data[_i];
if (link.source != null) {
link.source = (_ref = this.nodes[link.source]) != null ? _ref : (function() {
return _this.nodes[link.source] = {
name: link.source
};
})();
}
if ((link.target != null) && link.target !== "") {
_results.push(link.target = (_ref1 = this.nodes[link.target]) != null ? _ref1 : (function() {
return _this.nodes[link.target] = {
name: link.target
};
})());
} else {
_results.push(void 0);
}
}
return _results;
};
AcyclicGraph.prototype.defineArrowMarker = function() {
return this.svg.append("defs").selectAll("marker").data(["link", "highlight"]).enter().append("marker").attr("id", String).attr("viewBox", "0 -5 10 10").attr("refX", 20).attr("markerWidth", 6).attr("markerHeight", 6).attr("orient", "auto").style("fill", function(d) {
if (String(d) === "link") {
return "#666";
} else {
return "#ff7f0e";
}
}).append("path").attr("d", "M0,-5L10,0L0,5");
};
AcyclicGraph.prototype.tick = function() {
this.path.attr("d", function(d) {
var dr, dx, dy;
dx = d.target.x - d.source.x;
dy = d.target.y - d.source.y;
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + " L" + d.target.x + "," + d.target.y;
});
this.circle.attr("transform", function(d) {
return "translate(" + d.x + " , " + d.y + ")";
});
return this.text.attr("transform", function(d) {
return "translate(" + d.x + " , " + d.y + ")";
});
};
return AcyclicGraph;
})();
}).call(this);

HTML header: <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> HTML header: <script type="text/javascript" src="http://d3js.org/d3.v2.min.js"></script> HTML header: <script type="text/javascript" src="https://raw.github.com/gist/3788444/AcyclicGraph.js"></script>

Bayesian Network Fundamentals

Semantics and Factorization

Lets start by looking at a running example, the student example. It consists of the following random variables:

  • Grade
  • Course Difficulty
  • Student Intelligence
  • Student SAT
  • Referece Letter

Here we vil simplify every random variable to be binary, except for Grade, which will have 3.

Now to construct the graph, we’ll start with the random variable Grade. We can intuitively infer that G will depend on Intelligence and Difficulty. We can also apply the other random variables. The SAT score of the student doesn’t depend on the difficulty of the course, but does depend on the intelligence of the student, which is the only relevant variable in the context of this model.

<script type="text/javascript"> new AcyclicGraph(610, 260, document.getElementById("graph1"),'[{"source":"Intelligence", "target":"Grade"}, {"source":"Intelligence","target":"SAT"}, {"source":"Difficulty", "target":"Grade"}, {"source":"Grade", "target":"Letter"}]'); </script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment