提交 87b0ed54 authored 作者: Christof Angermueller's avatar Christof Angermueller

Improve OpFromGraph nodes and mapping inputs/outputs

上级 ae83230d
......@@ -36,3 +36,7 @@ Theano.suo
*.DS_Store
*.bak
.ipynb_checkpoints
doc/d3printing/GSoC/150724_opfrom/bundle/
doc/d3printing/GSoC/150724_opfrom/bundle2/
......@@ -82,4 +82,9 @@ svg {
border: 1px solid black;
border-radius: 8px;
pointer-events: none;
}
path.hull {
fill: lightsteelblue;
fill-opacity: 0.3;
}
\ No newline at end of file
......@@ -13,54 +13,49 @@ function flipAxes(nodes) {
function processDotGraph(dotGraph) {
// Merge and remove subgraph nodes
dotGraph.rnodes = {};
for (var nodeId in dotGraph._nodes) {
if (!exists(dotGraph._nodes[nodeId])) {
continue;
}
if (nodeId.startsWith('cluster_')) {
var id = nodeId.replace('cluster_', '');
assert(exists(dotGraph._nodes[id]));
var parent = dotGraph.node(id);
var childIds = dotGraph.children(nodeId);
for (var i in childIds) {
var childId = childIds[i];
dotGraph.setParent(childId, id);
dotGraph.setEdge(childId, id, {'label': 'opfrom'});
var child = dotGraph.node(childId);
}
dotGraph.removeNode(nodeId);
var node = dotGraph._nodes[nodeId];
node.id = nodeId;
node.isCluster = nodeId.startsWith('cluster');
if (!node.isCluster) {
dotGraph.rnodes[nodeId] = node;
}
}
var i = 0;
for (var nodeId in dotGraph._nodes) {
for (var nodeId in dotGraph.rnodes) {
var node = dotGraph._nodes[nodeId];
node.id = nodeId;
node.pos = node.pos.split(',').map(function(d) {return parseInt(d);});
var size = textSize(node.label, {'class': 'nodeText'});
node.width = size.width + 2 * pad;
node.height = size.height + 2 * pad;
node.cx = node.width / 2;
node.cy = node.height / 2;
node.hasChilds = dotGraph.children(nodeId).length > 0;
node.hasChilds = exists(node.subg);
node.showChilds = false;
node.profile = parseProfile(node.profile);
if (node.profile.length) {
isProfiled = true;
}
if (exists(node.subg_map_inputs)) {
node.subg_map_inputs = eval(node.subg_map_inputs)
}
if (exists(node.subg_map_outputs)) {
node.subg_map_outputs = eval(node.subg_map_outputs)
}
}
flipAxes(dotGraph._nodes);
flipAxes(dotGraph.rnodes);
// Offset and scale positions
var posMin = [Infinity, Infinity];
for (var i in dotGraph._nodes) {
for (var i in dotGraph.rnodes) {
var node = dotGraph._nodes[i];
posMin[0] = Math.min(posMin[0], node.pos[0]);
posMin[1] = Math.min(posMin[1], node.pos[1]);
}
for (var i in dotGraph._nodes) {
for (var i in dotGraph.rnodes) {
var node = dotGraph._nodes[i];
var pos = node.pos;
pos[0] -= posMin[0];
......@@ -91,146 +86,214 @@ function processDotGraph(dotGraph) {
}
}
function makeNode(dotGraph, dotNode) {
var node = {};
node.value = dotNode;
node.fixed = true;
return node;
}
function traverseChilds(dotGraph, parent) {
var childs = dotGraph.children(parent);
var nodes = [];
function traverseChilds(dotGraph, nodes, groups, parent) {
var preId = '';
var ref = undefined;
var group = {'id': groups.length, 'nodes': [], 'parent': parent};
if (exists(parent)) {
ref = parent.value.subg;
group.parent = parent;
group.nodes.push(parent);
parent.group = group;
}
groups.push(group);
var childs = dotGraph.children(ref);
for (var i in childs) {
var child = dotGraph.node(childs[i]);
nodes.push(makeNode(dotGraph, child));
if (child.isCluster) {
continue;
}
var node = {
'id': child.id,
'value': child,
'index': nodes.length,
'fixed': true,
'group': group,
'isParent': child.showChilds,
'parent': parent
};
nodes.push(node);
if (child.showChilds) {
nodes = nodes.concat(traverseChilds(dotGraph, child.id));
traverseChilds(dotGraph, nodes, groups, node);
} else {
group.nodes.push(node);
}
}
return nodes;
}
function groupSize(nodes) {
var minPos = [Infinity, Infinity];
var maxPos = [-Infinity, -Infinity];
for (var i in nodes) {
var node = nodes[i];
if (node.isParent) {
continue;
}
minPos[0] = Math.min(minPos[0], node.value.pos[0]);
minPos[1] = Math.min(minPos[1], node.value.pos[1]);
maxPos[0] = Math.max(maxPos[0], node.value.pos[0] + node.value.width);
maxPos[1] = Math.max(maxPos[1], node.value.pos[1] + node.value.height);
}
return [maxPos[0] - minPos[0], maxPos[1] - minPos[1]];
}
function forceGraph(dotGraph, prevGraph) {
// Parse nodes
var graph = {};
graph.nodes = traverseChilds(dotGraph);
var graph = {'nodes': [], 'groups': []};
traverseChilds(dotGraph, graph.nodes, graph.groups);
graph.nodesd = {};
for (var i in graph.nodes) {
var node = graph.nodes[i];
node.index = i;
graph.nodesd[node.value.id] = node;
graph.nodesd[node.id] = node;
}
var groups = {};
for (var i in graph.nodes) {
var node = graph.nodes[i];
var parentId = dotGraph.parent(node.value.id);
if (exists(parentId)) {
if (!(parentId in groups)) {
groups[parentId] = [];
}
groups[parentId].push(node.value.id);
}
}
graph.nodesp = graph.nodes.filter(function(d) {return d.isParent;});
graph.nodesn = graph.nodes.filter(function(d) {return !d.isParent;});
// Compute group centroids
var groupsMeta = {};
for (var i in groups) {
var group = groups[i];
var cx = 0, cy = 0;
for (var j in group) {
var node = graph.nodesd[group[j]];
cx += node.value.pos[0];
cy += node.value.pos[1];
for (i in graph.groups) {
var group = graph.groups[i];
group.size = groupSize(group.nodes);
var parent = group.parent;
if (exists(parent)) {
var prevParent = prevGraph.nodesd[group.parent.id];
if (exists(prevParent)) {
group.pos = [prevParent.x, prevParent.y];
} else {
group.pos = parent.pos.slice(0);
}
group.pos[0] += parent.value.cx;
group.pos[1] += parent.value.cy;
} else {
group.pos = [group.size[0] / 2, group.size[1] / 2];
}
var n = groups[i].length;
cx /= n;
cy /= n;
groupsMeta[i] = {'cx': cx, 'cy': cy, 'n': n};
}
// Reuse previous positions
for (var i in graph.nodes) {
var node = graph.nodes[i];
var prevNode;
if (exists(prevGraph)) {
prevNode = prevGraph.nodesd[node.value.id];
var min = [Infinity, Infinity];
for (var j in group.nodes) {
var node = group.nodes[j];
if (!node.isParent) {
min[0] = Math.min(min[0], node.value.pos[0]);
min[1] = Math.min(min[0], node.value.pos[1]);
}
}
if (exists(prevNode)) {
node.x = prevNode.x;
node.y = prevNode.y;
node.fixed = prevNode.fixed;
} else {
var parentId = dotGraph.parent(node.value.id);
if (exists(parentId)) {
var parentPos;
var parent = prevGraph.nodesd[parentId];
if (exists(parent)) {
parentPos = [parent.x, parent.y];
} else {
parent = graph.nodesd[parentId];
parentPos = parent.value.pos;
}
var g = groupsMeta[parentId];
node.x = parentPos[0] + node.value.pos[0] - g.cx;
node.y = parentPos[1] - 100 + node.value.pos[1] - g.cy;
node.fixed = true;
for (var j in group.nodes) {
var node = group.nodes[j];
if (node.isParent) {
node.x = group.pos[0];
node.y = group.pos[1];
} else {
node.x = node.value.pos[0];
node.y = node.value.pos[1];
node.x = group.pos[0] - group.size[0] / 2 + node.value.pos[0] - min[0];
node.y = group.pos[1] - group.size[1] / 2 + node.value.pos[1] - min[1];
}
}
}
// Offset graph on initialization
if (!exists(prevGraph)) {
var posMin = [Infinity, Infinity];
for (var i in graph.nodes) {
var node = graph.nodes[i];
posMin[0] = Math.min(posMin[0], node.x);
posMin[1] = Math.min(posMin[1], node.y);
}
graph.size = graph.groups[0].size;
// Reuse previous positions
if (exists(prevGraph)) {
for (var i in graph.nodes) {
var node = graph.nodes[i];
node.x -= posMin[0];
node.y -= posMin[1];
var prevNode;
prevNode = prevGraph.nodesd[node.id];
if (exists(prevNode)) {
node.x = prevNode.x;
node.y = prevNode.y;
node.fixed = prevNode.fixed;
} else {
for (var j in prevGraph.groups) {
var group = prevGraph.groups[j];
if (exists(group.parent) && group.parent.id == node.id) {
node.x = group.pos[0] + group.size[0] / 2;
node.y = group.pos[1] + group.size[1] / 2;
}
}
}
}
}
// Compute dimension of graph
var minPos = [Infinity, Infinity];
var maxPos = [-Infinity, -Infinity];
for (var i in graph.nodes) {
var node = graph.nodes[i];
minPos[0] = Math.min(minPos[0], node.x);
minPos[1] = Math.min(minPos[1], node.y);
maxPos[0] = Math.max(maxPos[0], node.x + node.value.width);
maxPos[1] = Math.max(maxPos[1], node.y + node.value.height);
}
graph.dim = {'minPos': minPos, 'maxPos': maxPos,
'size': [maxPos[0] - minPos[0], maxPos[1] - minPos[0]]};
// Edges
graph.edges = [];
for (var i in graph.nodes) {
for (var j in graph.nodes) {
var sourceId = graph.nodes[i].value.id;
var targetId = graph.nodes[j].value.id;
var dotEdge = dotGraph.edge(sourceId, targetId);
for (var i in graph.nodesn) {
for (var j in graph.nodesn) {
var source = graph.nodesn[i];
var target = graph.nodesn[j];
var dotEdge = dotGraph.edge(source.value.id, target.value.id);
if (exists(dotEdge)) {
var edge = {};
edge.source = parseInt(graph.nodes[i].index);
edge.target = parseInt(graph.nodes[j].index);
edge.source = parseInt(source.index);
edge.target = parseInt(target.index);
edge.value = dotEdge;
graph.edges.push(edge);
}
function redirectEdges(map, dotEdge) {
for (var k in map) {
var kmap = map[k];
if (kmap[0] == source.id && kmap[1] == target.id) {
var edge = {};
edge.source = parseInt(source.index);
edge.target = parseInt(target.index);
edge.value = dotEdge;
graph.edges.push(edge);
}
}
}
var map = undefined;
if (exists(target.parent)) {
var parent = target.parent;
var dotEdge = dotGraph.edge(source.id, parent.id);
if (exists(dotEdge)) {
map = parent.value.subg_map_inputs;
redirectEdges(map, dotEdge);
}
}
if (exists(source.parent)) {
var parent = source.parent;
var dotEdge = dotGraph.edge(parent.id, target.id);
if (exists(dotEdge)) {
map = parent.value.subg_map_outputs;
redirectEdges(map, dotEdge);
}
}
}
}
return graph;
}
function convexHulls(graph, offset) {
var hulls = [];
offset = offset || 20;
for (var i in graph.groups) {
var group = graph.groups[i];
if (!exists(group.parent)) {
continue;
}
var points = [];
for (var j in group.nodes) {
var node = group.nodes[j];
if (node.isParent) {
points.push([node.x, node.y]);
} else {
points.push([node.x - node.value.cx - offset, node.y - node.value.cy - offset]);
points.push([node.x - node.value.cx - offset, node.y + node.value.cy + offset]);
points.push([node.x + node.value.cx + offset, node.y - node.value.cy - offset]);
points.push([node.x + node.value.cx + offset, node.y + node.value.cy + offset]);
}
}
hulls.push({group: i, path: d3.geom.hull(points)});
}
return hulls;
}
function drawCluster(d) {
return curve(d.path); // 0.8
}
function setupGraph() {
if (isProfiled) {
d3.select('body').select('#menu').append('input')
......@@ -251,6 +314,23 @@ function setupGraph() {
var isEdgeOver = false;
var isEdgeLabelOver = false;
graph.hulls = convexHulls(graph);
hulls = pane.selectAll('#hulls').remove();
hulls = pane.append('g').attr('id', 'hulls')
.selectAll('path')
.data(graph.hulls).enter()
.append('path')
.attr('class', 'hull')
.attr('d', drawCluster);
hulls.on('dblclick', function(d) {
var parent = graph.groups[d.group].parent;
parent.value.showChilds = !parent.value.showChilds;
graph = forceGraph(dotGraph, graph);
setupGraph();
});
// Add edges
edges = pane.selectAll('#edges').remove();
edges = pane.append('g').attr('id', 'edges')
......@@ -287,7 +367,7 @@ function setupGraph() {
// Add nodes
pane.selectAll('#nodes').remove();
nodes = pane.append('g').attr('id', 'nodes')
.selectAll('g').data(graph.nodes).enter().append('g');
.selectAll('g').data(graph.nodesn).enter().append('g');
updateNodes();
updateGraph();
......@@ -341,9 +421,9 @@ function setupGraph() {
layout = d3.layout.force()
.nodes(graph.nodes)
.links(graph.edges)
.size(graph.dim.size)
.size(graph.size)
.charge(-300)
.linkDistance(300)
.linkDistance(400)
.linkStrength(0.4)
.gravity(0)
.on('tick', updateGraph);
......@@ -373,6 +453,10 @@ function pathPos(x1, y1, x2, y2, c) {
}
function updateGraph() {
graph.hulls = convexHulls(graph);
hulls.data(graph.hulls)
.attr('d', drawCluster);
// Update nodes
nodes.attr('transform', function(d) { return 'translate(' + (d.x - d.value.cx) + ' ' + (d.y - d.value.cy) + ')'; });
// Update edges
......
......@@ -22,7 +22,7 @@
</div>
<script type="text/javascript">
var path='opfrom.dot'; // '%% DOT_FILE %%'
var path = 'opfrom.dot'; // '%% DOT_FILE %%';
var dotGraph;
var graph = {};
var nodes = [];
......@@ -85,13 +85,6 @@
.attr("d", "M0,0 L4,2 L0,4 Z")
.attr('fill', function(d) { return d.color;});
d3.text(path, function(data) {
dotGraph = graphlibDot.read(data);
processDotGraph(dotGraph);
graph = forceGraph(dotGraph);
setupGraph();
});
// Zoom behaviour
function zoom(d) {
var trans = d3.event.translate;
......@@ -107,6 +100,18 @@
bZoom.event(svg);
svg.on("dblclick.zoom", null);
var curve = d3.svg.line()
.interpolate("cardinal-closed")
.tension(.85);
// Read and initialize graph
d3.text(path, function(data) {
dotGraph = graphlibDot.read(data);
processDotGraph(dotGraph);
graph = forceGraph(dotGraph);
setupGraph();
});
</script>
</body>
</html>
......@@ -55,7 +55,7 @@
},
{
"cell_type": "code",
"execution_count": 35,
"execution_count": 169,
"metadata": {
"collapsed": false
},
......@@ -70,29 +70,1368 @@
},
{
"cell_type": "code",
"execution_count": 36,
"execution_count": 170,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"gf = d3p.GraphFormatter()\n",
"g = gf.to_pydot(f)"
]
},
{
"cell_type": "code",
"execution_count": 171,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 171,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"g.write_dot('opfrom.dot')"
]
},
{
"cell_type": "code",
"execution_count": 168,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"#SVG(g.create_svg())"
]
},
{
"cell_type": "code",
"execution_count": 162,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"digraph G {\n",
"\tgraph [bb=\"0,0,2604,316\"];\n",
"\tnode [label=\"\\N\"];\n",
"\tsubgraph cluster_n1 {\n",
"\t\tgraph [bb=\"1158,80,1873,308\"];\n",
"\t\tn11\t\t [fillcolor=\"#FFAABB\",\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"Elemwise{Composite{(i0 + (i1 * i2))}}\",\n",
"\t\t\tpos=\"1508,194\",\n",
"\t\t\tshape=ellipse,\n",
"\t\t\tstyle=filled,\n",
"\t\t\ttype=colored,\n",
"\t\t\twidth=4.3102];\n",
"\t\tn15\t\t [fillcolor=dodgerblue,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"1508,106\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=2.3889];\n",
"\t\tn11 -> n15\t\t [label=\"TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"1586,150\",\n",
"\t\t\tpos=\"e,1508,124.08 1508,175.6 1508,163.75 1508,147.82 1508,134.29\"];\n",
"\t\tn12\t\t [fillcolor=limegreen,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"name=x TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"1754,282\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=3.0625];\n",
"\t\tn12 -> n11\t\t [label=\"0 TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"1789.5,238\",\n",
"\t\t\tpos=\"e,1602.7,208.31 1732.7,263.92 1717.7,252.69 1696.6,238.53 1676,230 1656.1,221.75 1634,215.37 1612.5,210.46\"];\n",
"\t\tn13\t\t [fillcolor=limegreen,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"name=y TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"1515,282\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=3.0625];\n",
"\t\tn13 -> n11\t\t [label=\"1 TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"1592.5,238\",\n",
"\t\t\tpos=\"e,1507.7,212.04 1511.6,263.98 1510.5,258.29 1509.6,251.89 1509,246 1508.3,238.24 1507.9,229.79 1507.8,222.04\"];\n",
"\t\tn14\t\t [fillcolor=limegreen,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"name=z TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"1276,282\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=3.0556];\n",
"\t\tn14 -> n11\t\t [label=\"2 TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"1421.5,238\",\n",
"\t\t\tpos=\"e,1406,207.64 1292.3,263.77 1304,252.46 1320.6,238.29 1338,230 1356.1,221.35 1376.3,214.83 1396.3,209.92\"];\n",
"\t}\n",
"\tsubgraph cluster_n6 {\n",
"\t\tgraph [bb=\"1881,80,2596,308\"];\n",
"\t\tn61\t\t [fillcolor=\"#FFAABB\",\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"Elemwise{Composite{(i0 + (i1 * i2))}}\",\n",
"\t\t\tpos=\"2231,194\",\n",
"\t\t\tshape=ellipse,\n",
"\t\t\tstyle=filled,\n",
"\t\t\ttype=colored,\n",
"\t\t\twidth=4.3102];\n",
"\t\tn65\t\t [fillcolor=dodgerblue,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"2231,106\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=2.3889];\n",
"\t\tn61 -> n65\t\t [label=\"TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"2309,150\",\n",
"\t\t\tpos=\"e,2231,124.08 2231,175.6 2231,163.75 2231,147.82 2231,134.29\"];\n",
"\t\tn62\t\t [fillcolor=limegreen,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"name=x TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"2477,282\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=3.0625];\n",
"\t\tn62 -> n61\t\t [label=\"0 TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"2511.5,238\",\n",
"\t\t\tpos=\"e,2325.7,208.31 2455.7,263.92 2440.7,252.69 2419.6,238.53 2399,230 2379.1,221.75 2357,215.37 2335.5,210.46\"];\n",
"\t\tn63\t\t [fillcolor=limegreen,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"name=y TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"2238,282\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=3.0625];\n",
"\t\tn63 -> n61\t\t [label=\"1 TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"2315.5,238\",\n",
"\t\t\tpos=\"e,2230.7,212.04 2234.6,263.98 2233.5,258.29 2232.6,251.89 2232,246 2231.3,238.24 2230.9,229.79 2230.8,222.04\"];\n",
"\t\tn64\t\t [fillcolor=limegreen,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"name=z TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"1999,282\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=3.0556];\n",
"\t\tn64 -> n61\t\t [label=\"2 TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"2144.5,238\",\n",
"\t\t\tpos=\"e,2129,207.64 2015.3,263.77 2027,252.46 2043.6,238.29 2061,230 2079.1,221.35 2099.3,214.83 2119.3,209.92\"];\n",
"\t}\n",
"\tn1\t [height=0.5,\n",
"\t\tlabel=\"theano.compile.builders.OpFromGraph object at 0x10c95ca50\",\n",
"\t\tpos=\"237,194\",\n",
"\t\tshape=ellipse,\n",
"\t\tsubg=cluster_n1,\n",
"\t\tsubg_map_inputs=\"[['n2', 'n12'], ['n3', 'n13'], ['n3', 'n14']]\",\n",
"\t\tsubg_map_outputs=\"[['n5', 'n15']]\",\n",
"\t\twidth=6.5955];\n",
"\tn5\t [fillcolor=\"#FFAABB\",\n",
"\t\theight=0.5,\n",
"\t\tlabel=\"Elemwise{Add}[(0, 0)]\",\n",
"\t\tpos=\"551,106\",\n",
"\t\tshape=ellipse,\n",
"\t\tstyle=filled,\n",
"\t\ttype=colored,\n",
"\t\twidth=2.6784];\n",
"\tn1 -> n5\t [label=\"1 TensorType(float32, scalar)\",\n",
"\t\tlp=\"506.5,150\",\n",
"\t\tpos=\"e,499.1,121.21 297.17,176.52 352.36,161.41 433.73,139.12 489.37,123.88\"];\n",
"\tn2\t [fillcolor=limegreen,\n",
"\t\theight=0.5,\n",
"\t\tlabel=\"name=z TensorType(float32, scalar)\",\n",
"\t\tpos=\"673,282\",\n",
"\t\tshape=box,\n",
"\t\tstyle=filled,\n",
"\t\twidth=3.0556];\n",
"\tn2 -> n1\t [label=\"0 TensorType(float32, scalar)\",\n",
"\t\tlp=\"683.5,238\",\n",
"\t\tpos=\"e,428.7,204.68 632.61,263.87 621.72,258.66 610.15,252.56 600,246 590.73,240.01 591.17,234.31 581,230 554.15,218.63 498.16,210.85 \\\n",
"439,205.57\"];\n",
"\tn6\t [height=0.5,\n",
"\t\tlabel=\"theano.compile.builders.OpFromGraph object at 0x10c95ca50 id=1\",\n",
"\t\tpos=\"778,194\",\n",
"\t\tshape=ellipse,\n",
"\t\tsubg=cluster_n6,\n",
"\t\tsubg_map_inputs=\"[['n7', 'n62'], ['n3', 'n63'], ['n2', 'n64']]\",\n",
"\t\tsubg_map_outputs=\"[['n5', 'n65']]\",\n",
"\t\twidth=7.1441];\n",
"\tn2 -> n6\t [label=\"2 TensorType(float32, scalar)\",\n",
"\t\tlp=\"862.5,238\",\n",
"\t\tpos=\"e,779.89,212.37 748.75,263.9 757.23,259.29 764.96,253.43 771,246 776.31,239.46 778.66,230.83 779.51,222.53\"];\n",
"\tn3\t [fillcolor=limegreen,\n",
"\t\theight=0.5,\n",
"\t\tlabel=\"name=y TensorType(float32, scalar)\",\n",
"\t\tpos=\"223,282\",\n",
"\t\tshape=box,\n",
"\t\tstyle=filled,\n",
"\t\twidth=3.0625];\n",
"\tn3 -> n1\t [label=\"1 TensorType(float32, scalar)\",\n",
"\t\tlp=\"307.5,238\",\n",
"\t\tpos=\"e,229.34,212.12 221.91,263.85 221.64,253.89 221.89,241.14 224,230 224.51,227.29 225.22,224.51 226.03,221.76\"];\n",
"\tn3 -> n1\t [label=\"2 TensorType(float32, scalar)\",\n",
"\t\tlp=\"135.5,238\",\n",
"\t\tpos=\"e,101.14,208.8 112.52,277.73 66.058,272.21 27.738,259.28 52,230 58.571,222.07 73.117,215.92 91.313,211.16\"];\n",
"\tn3 -> n6\t [label=\"1 TensorType(float32, scalar)\",\n",
"\t\tlp=\"493.5,238\",\n",
"\t\tpos=\"e,567.06,204.36 333.59,266.1 353.29,261.19 373.18,254.66 391,246 400.93,241.17 399.82,234.27 410,230 437.96,218.27 495.41,210.43 \\\n",
"556.78,205.2\"];\n",
"\tn6 -> n5\t [color=red,\n",
"\t\tlabel=\"0 TensorType(float32, scalar)\",\n",
"\t\tlp=\"768.5,150\",\n",
"\t\tpos=\"e,591.76,122.44 733.69,176.21 695.67,161.81 640.89,141.06 601.24,126.03\"];\n",
"\tn7\t [fillcolor=limegreen,\n",
"\t\theight=0.5,\n",
"\t\tlabel=\"name=x TensorType(float32, scalar)\",\n",
"\t\tpos=\"983,282\",\n",
"\t\tshape=box,\n",
"\t\tstyle=filled,\n",
"\t\twidth=3.0625];\n",
"\tn7 -> n6\t [label=\"0 TensorType(float32, scalar)\",\n",
"\t\tlp=\"1049.5,238\",\n",
"\t\tpos=\"e,907.99,209.69 976.09,263.71 970.67,252.38 962.02,238.2 950,230 940.07,223.23 929.11,217.71 917.68,213.22\"];\n",
"\tn9\t [fillcolor=dodgerblue,\n",
"\t\theight=0.5,\n",
"\t\tlabel=\"TensorType(float32, scalar) id=5\",\n",
"\t\tpos=\"551,18\",\n",
"\t\tshape=box,\n",
"\t\tstyle=filled,\n",
"\t\twidth=2.7847];\n",
"\tn5 -> n9\t [label=\"TensorType(float32, scalar)\",\n",
"\t\tlp=\"629,62\",\n",
"\t\tpos=\"e,551,36.084 551,87.597 551,75.746 551,59.817 551,46.292\"];\n",
"}\n",
"\n"
]
}
],
"source": [
"print(g.create_dot())"
]
},
{
"cell_type": "code",
"execution_count": 110,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[<theano.compile.builders.OpFromGraph object at 0x10c9dadd0>(z, y, y),\n",
" <theano.compile.builders.OpFromGraph object at 0x10c9dadd0>(x, y, z),\n",
" Elemwise{Add}[(0, 0)](<theano.compile.builders.OpFromGraph object at 0x10c9dadd0>.0, <theano.compile.builders.OpFromGraph object at 0x10c9dadd0>.0)]"
]
},
"execution_count": 110,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"topo = f.maker.fgraph.toposort()\n",
"topo"
]
},
{
"cell_type": "code",
"execution_count": 146,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"a = ['1', '2']\n",
"b = ['11', '22']\n",
"m = zip(a, b)\n",
"m = [list(x) for x in m]"
]
},
{
"cell_type": "code",
"execution_count": 147,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[['1', '11'], ['2', '22']]"
]
},
"execution_count": 147,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m"
]
},
{
"cell_type": "code",
"execution_count": 111,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"op = topo[0]"
]
},
{
"cell_type": "code",
"execution_count": 118,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Elemwise{Add}[(0, 0)].0"
]
},
"execution_count": 118,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"out = f.maker.fgraph.outputs[0]\n",
"out"
]
},
{
"cell_type": "code",
"execution_count": 122,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"TensorType(float32, scalar)"
]
},
"execution_count": 122,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"op.op.fn.maker.fgraph.outputs[0].type"
]
},
{
"cell_type": "code",
"execution_count": 119,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"TensorType(float32, scalar)"
]
},
"execution_count": 119,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"out.type"
]
},
{
"cell_type": "code",
"execution_count": 91,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Out(Elemwise{add,no_inplace}.0,False)"
]
},
"execution_count": 91,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"op.op.fn.outputs[0]"
]
},
{
"cell_type": "code",
"execution_count": 92,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[Out(Elemwise{add,no_inplace}.0,False)]"
]
},
"execution_count": 92,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f.outputs"
]
},
{
"cell_type": "code",
"execution_count": 95,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[Out(Elemwise{add,no_inplace}.0,False)]"
]
},
"execution_count": 95,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f.outputs"
]
},
{
"cell_type": "code",
"execution_count": 94,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[Elemwise{Add}[(0, 0)].0]"
]
},
"execution_count": 94,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f.maker.fgraph.outputs"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[<theano.compile.builders.OpFromGraph object at 0x10c782f90>.0]"
]
},
"execution_count": 76,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"op.outputs"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'n10'"
]
},
"execution_count": 69,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gf.node_id(op1.outputs[0])"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"digraph G {\n",
"\tgraph [bb=\"0,0,2605,316\"];\n",
"\tnode [label=\"\\N\"];\n",
"\tsubgraph cluster_n1 {\n",
"\t\tgraph [bb=\"1159,80,1874,308\"];\n",
"\t\tn11\t\t [fillcolor=\"#FFAABB\",\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"Elemwise{Composite{(i0 + (i1 * i2))}}\",\n",
"\t\t\tpos=\"1509,194\",\n",
"\t\t\tshape=ellipse,\n",
"\t\t\tstyle=filled,\n",
"\t\t\ttype=colored,\n",
"\t\t\twidth=4.3102];\n",
"\t\tn15\t\t [fillcolor=dodgerblue,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"1509,106\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=2.3889];\n",
"\t\tn11 -> n15\t\t [label=\"TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"1587,150\",\n",
"\t\t\tpos=\"e,1509,124.08 1509,175.6 1509,163.75 1509,147.82 1509,134.29\"];\n",
"\t\tn12\t\t [fillcolor=limegreen,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"name=x TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"1755,282\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=3.0625];\n",
"\t\tn12 -> n11\t\t [label=\"0 TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"1790.5,238\",\n",
"\t\t\tpos=\"e,1603.7,208.31 1733.7,263.92 1718.7,252.69 1697.6,238.53 1677,230 1657.1,221.75 1635,215.37 1613.5,210.46\"];\n",
"\t\tn13\t\t [fillcolor=limegreen,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"name=y TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"1516,282\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=3.0625];\n",
"\t\tn13 -> n11\t\t [label=\"1 TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"1593.5,238\",\n",
"\t\t\tpos=\"e,1508.7,212.04 1512.6,263.98 1511.5,258.29 1510.6,251.89 1510,246 1509.3,238.24 1508.9,229.79 1508.8,222.04\"];\n",
"\t\tn14\t\t [fillcolor=limegreen,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"name=z TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"1277,282\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=3.0556];\n",
"\t\tn14 -> n11\t\t [label=\"2 TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"1422.5,238\",\n",
"\t\t\tpos=\"e,1407,207.64 1293.3,263.77 1305,252.46 1321.6,238.29 1339,230 1357.1,221.35 1377.3,214.83 1397.3,209.92\"];\n",
"\t}\n",
"\tsubgraph cluster_n5 {\n",
"\t\tgraph [bb=\"1882,80,2597,308\"];\n",
"\t\tn51\t\t [fillcolor=\"#FFAABB\",\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"Elemwise{Composite{(i0 + (i1 * i2))}}\",\n",
"\t\t\tpos=\"2232,194\",\n",
"\t\t\tshape=ellipse,\n",
"\t\t\tstyle=filled,\n",
"\t\t\ttype=colored,\n",
"\t\t\twidth=4.3102];\n",
"\t\tn55\t\t [fillcolor=dodgerblue,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"2232,106\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=2.3889];\n",
"\t\tn51 -> n55\t\t [label=\"TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"2310,150\",\n",
"\t\t\tpos=\"e,2232,124.08 2232,175.6 2232,163.75 2232,147.82 2232,134.29\"];\n",
"\t\tn52\t\t [fillcolor=limegreen,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"name=x TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"2478,282\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=3.0625];\n",
"\t\tn52 -> n51\t\t [label=\"0 TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"2512.5,238\",\n",
"\t\t\tpos=\"e,2326.7,208.31 2456.7,263.92 2441.7,252.69 2420.6,238.53 2400,230 2380.1,221.75 2358,215.37 2336.5,210.46\"];\n",
"\t\tn53\t\t [fillcolor=limegreen,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"name=y TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"2239,282\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=3.0625];\n",
"\t\tn53 -> n51\t\t [label=\"1 TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"2316.5,238\",\n",
"\t\t\tpos=\"e,2231.7,212.04 2235.6,263.98 2234.5,258.29 2233.6,251.89 2233,246 2232.3,238.24 2231.9,229.79 2231.8,222.04\"];\n",
"\t\tn54\t\t [fillcolor=limegreen,\n",
"\t\t\theight=0.5,\n",
"\t\t\tlabel=\"name=z TensorType(float32, scalar)\",\n",
"\t\t\tpos=\"2000,282\",\n",
"\t\t\tshape=box,\n",
"\t\t\tstyle=filled,\n",
"\t\t\twidth=3.0556];\n",
"\t\tn54 -> n51\t\t [label=\"2 TensorType(float32, scalar)\",\n",
"\t\t\tlp=\"2145.5,238\",\n",
"\t\t\tpos=\"e,2130,207.64 2016.3,263.77 2028,252.46 2044.6,238.29 2062,230 2080.1,221.35 2100.3,214.83 2120.3,209.92\"];\n",
"\t}\n",
"\tn1\t [height=0.5,\n",
"\t\tlabel=\"theano.compile.builders.OpFromGraph object at 0x10c7b0e90\",\n",
"\t\tpos=\"238,194\",\n",
"\t\tshape=ellipse,\n",
"\t\tsubg=cluster_n1,\n",
"\t\twidth=6.6185];\n",
"\tn8\t [fillcolor=\"#FFAABB\",\n",
"\t\theight=0.5,\n",
"\t\tlabel=\"Elemwise{Add}[(0, 0)]\",\n",
"\t\tpos=\"553,106\",\n",
"\t\tshape=ellipse,\n",
"\t\tstyle=filled,\n",
"\t\ttype=colored,\n",
"\t\twidth=2.6784];\n",
"\tn1 -> n8\t [label=\"1 TensorType(float32, scalar)\",\n",
"\t\tlp=\"507.5,150\",\n",
"\t\tpos=\"e,500.93,121.21 298.36,176.52 353.72,161.41 435.35,139.12 491.17,123.88\"];\n",
"\tn2\t [fillcolor=limegreen,\n",
"\t\theight=0.5,\n",
"\t\tlabel=\"name=z TensorType(float32, scalar)\",\n",
"\t\tpos=\"674,282\",\n",
"\t\tshape=box,\n",
"\t\tstyle=filled,\n",
"\t\twidth=3.0556];\n",
"\tn2 -> n1\t [label=\"0 TensorType(float32, scalar)\",\n",
"\t\tlp=\"684.5,238\",\n",
"\t\tpos=\"e,430.16,204.72 633.61,263.87 622.72,258.66 611.15,252.56 601,246 591.73,240.01 592.17,234.31 582,230 555.22,218.66 499.43,210.89 \\\n",
"440.43,205.61\"];\n",
"\tn5\t [height=0.5,\n",
"\t\tlabel=\"theano.compile.builders.OpFromGraph object at 0x10c7b0e90 id=1\",\n",
"\t\tpos=\"780,194\",\n",
"\t\tshape=ellipse,\n",
"\t\tsubg=cluster_n5,\n",
"\t\twidth=7.1441];\n",
"\tn2 -> n5\t [label=\"2 TensorType(float32, scalar)\",\n",
"\t\tlp=\"863.5,238\",\n",
"\t\tpos=\"e,781.5,212.41 749.62,263.79 758.11,259.2 765.89,253.37 772,246 777.39,239.5 779.89,230.87 780.91,222.57\"];\n",
"\tn3\t [fillcolor=limegreen,\n",
"\t\theight=0.5,\n",
"\t\tlabel=\"name=y TensorType(float32, scalar)\",\n",
"\t\tpos=\"224,282\",\n",
"\t\tshape=box,\n",
"\t\tstyle=filled,\n",
"\t\twidth=3.0625];\n",
"\tn3 -> n1\t [label=\"1 TensorType(float32, scalar)\",\n",
"\t\tlp=\"308.5,238\",\n",
"\t\tpos=\"e,230.34,212.12 222.91,263.85 222.64,253.89 222.89,241.14 225,230 225.51,227.29 226.22,224.51 227.03,221.76\"];\n",
"\tn3 -> n1\t [label=\"2 TensorType(float32, scalar)\",\n",
"\t\tlp=\"136.5,238\",\n",
"\t\tpos=\"e,102.14,208.8 113.52,277.73 67.058,272.21 28.738,259.28 53,230 59.571,222.07 74.117,215.92 92.313,211.16\"];\n",
"\tn3 -> n5\t [label=\"1 TensorType(float32, scalar)\",\n",
"\t\tlp=\"494.5,238\",\n",
"\t\tpos=\"e,568.49,204.32 334.59,266.1 354.29,261.19 374.18,254.66 392,246 401.93,241.17 400.82,234.27 411,230 439.03,218.24 496.65,210.39 \\\n",
"558.18,205.17\"];\n",
"\tn5 -> n8\t [color=red,\n",
"\t\tlabel=\"0 TensorType(float32, scalar)\",\n",
"\t\tlp=\"770.5,150\",\n",
"\t\tpos=\"e,593.76,122.44 735.69,176.21 697.67,161.81 642.89,141.06 603.24,126.03\"];\n",
"\tn6\t [fillcolor=limegreen,\n",
"\t\theight=0.5,\n",
"\t\tlabel=\"name=x TensorType(float32, scalar)\",\n",
"\t\tpos=\"984,282\",\n",
"\t\tshape=box,\n",
"\t\tstyle=filled,\n",
"\t\twidth=3.0625];\n",
"\tn6 -> n5\t [label=\"0 TensorType(float32, scalar)\",\n",
"\t\tlp=\"1050.5,238\",\n",
"\t\tpos=\"e,908.79,209.62 977.09,263.71 971.67,252.39 963.02,238.21 951,230 941.03,223.19 930.02,217.65 918.54,213.16\"];\n",
"\tn9\t [fillcolor=dodgerblue,\n",
"\t\theight=0.5,\n",
"\t\tlabel=\"TensorType(float32, scalar) id=5\",\n",
"\t\tpos=\"553,18\",\n",
"\t\tshape=box,\n",
"\t\tstyle=filled,\n",
"\t\twidth=2.7847];\n",
"\tn8 -> n9\t [label=\"TensorType(float32, scalar)\",\n",
"\t\tlp=\"631,62\",\n",
"\t\tpos=\"e,553,36.084 553,87.597 553,75.746 553,59.817 553,46.292\"];\n",
"}\n",
"\n"
]
}
],
"source": [
"print(g.create_dot())"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"op1.inputs[0] is inputs[2]"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"op1.inputs[1] is inputs[1]"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"op1.inputs[2] is inputs[1]"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[<theano.compile.builders.OpFromGraph object at 0x10c1ed0d0>.0]"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"op1.outputs"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"ofg.fgraph"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"theano.gof.graph.Apply"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(topo[0])"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"theano.tensor.var.TensorVariable"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(topo[2].inputs[0])"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"topo[2].outputs[0].owner is topo[2]"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"theano.gof.graph.Apply"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(o.owner)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"i = topo[2].inputs[0]"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"theano.gof.graph.Apply"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(i.owner)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"<theano.compile.builders.OpFromGraph object at 0x112c970d0>.0"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"topo[2].inputs[0]"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[Elemwise{Add}[(0, 0)].0]"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fg.outputs"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[x, y, z]"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fg.inputs"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'x'"
]
},
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fg.inputs[0].name"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"x = tht.scalar()\n",
"y = tht.scalar()\n",
"z = x + y\n",
"f = th.function([x, y], z)"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"fg = f.maker.fgraph"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 54,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fg.inputs[0] is fg.inputs[1]"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"topo = f.maker.fgraph.toposort()"
"t = fg.toposort()"
]
},
{
"cell_type": "code",
"execution_count": 38,
"execution_count": 74,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"of = topo[0]"
"a, b = t[0].inputs"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"b.owner"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"h = fg.inputs[0]"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {
"collapsed": false
},
"outputs": [
{
"ename": "AttributeError",
"evalue": "'TensorVariable' object has no attribute '__'",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-67-476d32041683>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mh\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m: 'TensorVariable' object has no attribute '__'"
]
}
],
"source": [
"h.__"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"220pt\" viewBox=\"0.00 0.00 722.00 220.00\" width=\"722pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 216)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-216 718,-216 718,4 -4,4\" stroke=\"none\"/>\n",
"<!-- _1 -->\n",
"<g class=\"node\" id=\"node1\"><title>_1</title>\n",
"<ellipse cx=\"349\" cy=\"-106\" fill=\"#ffaabb\" rx=\"155.005\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"349\" y=\"-102.3\">Elemwise{Composite{(i0 + (i1 * i2))}}</text>\n",
"</g>\n",
"<!-- _5 -->\n",
"<g class=\"node\" id=\"node5\"><title>_5</title>\n",
"<polygon fill=\"dodgerblue\" points=\"435,-36 263,-36 263,-0 435,-0 435,-36\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"349\" y=\"-14.3\">TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _1&#45;&gt;_5 -->\n",
"<g class=\"edge\" id=\"edge4\"><title>_1-&gt;_5</title>\n",
"<path d=\"M349,-87.5966C349,-75.7459 349,-59.8169 349,-46.2917\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"352.5,-46.084 349,-36.084 345.5,-46.084 352.5,-46.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"427\" y=\"-58.3\">TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _2 -->\n",
"<g class=\"node\" id=\"node2\"><title>_2</title>\n",
"<polygon fill=\"limegreen\" points=\"220.25,-212 -0.25,-212 -0.25,-176 220.25,-176 220.25,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"110\" y=\"-190.3\">name=x TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _2&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge1\"><title>_2-&gt;_1</title>\n",
"<path d=\"M128.186,-175.807C141.119,-164.521 159.428,-150.354 178,-142 197.086,-133.415 218.319,-126.915 239.152,-121.999\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"240.022,-125.391 249.01,-119.781 238.486,-118.562 240.022,-125.391\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"261.5\" y=\"-146.3\">0 TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _3 -->\n",
"<g class=\"node\" id=\"node3\"><title>_3</title>\n",
"<polygon fill=\"limegreen\" points=\"459.25,-212 238.75,-212 238.75,-176 459.25,-176 459.25,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"349\" y=\"-190.3\">name=y TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _3&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge2\"><title>_3-&gt;_1</title>\n",
"<path d=\"M349,-175.597C349,-163.746 349,-147.817 349,-134.292\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"352.5,-134.084 349,-124.084 345.5,-134.084 352.5,-134.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"432.5\" y=\"-146.3\">1 TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _4 -->\n",
"<g class=\"node\" id=\"node4\"><title>_4</title>\n",
"<polygon fill=\"limegreen\" points=\"698,-212 478,-212 478,-176 698,-176 698,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"588\" y=\"-190.3\">name=z TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _4&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge3\"><title>_4-&gt;_1</title>\n",
"<path d=\"M569.814,-175.807C556.881,-164.521 538.572,-150.354 520,-142 500.914,-133.415 479.681,-126.915 458.848,-121.999\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"459.514,-118.562 448.99,-119.781 457.978,-125.391 459.514,-118.562\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"630.5\" y=\"-146.3\">2 TensorType(float32, scalar)</text>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"g = gf.to_pydot(topo[0].op.fn)\n",
"SVG(g.create_svg())"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"220pt\" viewBox=\"0.00 0.00 722.00 220.00\" width=\"722pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 216)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-216 718,-216 718,4 -4,4\" stroke=\"none\"/>\n",
"<!-- _1 -->\n",
"<g class=\"node\" id=\"node1\"><title>_1</title>\n",
"<ellipse cx=\"349\" cy=\"-106\" fill=\"#ffaabb\" rx=\"155.005\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"349\" y=\"-102.3\">Elemwise{Composite{(i0 + (i1 * i2))}}</text>\n",
"</g>\n",
"<!-- _5 -->\n",
"<g class=\"node\" id=\"node5\"><title>_5</title>\n",
"<polygon fill=\"dodgerblue\" points=\"435,-36 263,-36 263,-0 435,-0 435,-36\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"349\" y=\"-14.3\">TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _1&#45;&gt;_5 -->\n",
"<g class=\"edge\" id=\"edge4\"><title>_1-&gt;_5</title>\n",
"<path d=\"M349,-87.5966C349,-75.7459 349,-59.8169 349,-46.2917\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"352.5,-46.084 349,-36.084 345.5,-46.084 352.5,-46.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"427\" y=\"-58.3\">TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _2 -->\n",
"<g class=\"node\" id=\"node2\"><title>_2</title>\n",
"<polygon fill=\"limegreen\" points=\"220.25,-212 -0.25,-212 -0.25,-176 220.25,-176 220.25,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"110\" y=\"-190.3\">name=x TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _2&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge1\"><title>_2-&gt;_1</title>\n",
"<path d=\"M128.186,-175.807C141.119,-164.521 159.428,-150.354 178,-142 197.086,-133.415 218.319,-126.915 239.152,-121.999\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"240.022,-125.391 249.01,-119.781 238.486,-118.562 240.022,-125.391\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"261.5\" y=\"-146.3\">0 TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _3 -->\n",
"<g class=\"node\" id=\"node3\"><title>_3</title>\n",
"<polygon fill=\"limegreen\" points=\"459.25,-212 238.75,-212 238.75,-176 459.25,-176 459.25,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"349\" y=\"-190.3\">name=y TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _3&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge2\"><title>_3-&gt;_1</title>\n",
"<path d=\"M349,-175.597C349,-163.746 349,-147.817 349,-134.292\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"352.5,-134.084 349,-124.084 345.5,-134.084 352.5,-134.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"432.5\" y=\"-146.3\">1 TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _4 -->\n",
"<g class=\"node\" id=\"node4\"><title>_4</title>\n",
"<polygon fill=\"limegreen\" points=\"698,-212 478,-212 478,-176 698,-176 698,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"588\" y=\"-190.3\">name=z TensorType(float32, scalar)</text>\n",
"</g>\n",
"<!-- _4&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge3\"><title>_4-&gt;_1</title>\n",
"<path d=\"M569.814,-175.807C556.881,-164.521 538.572,-150.354 520,-142 500.914,-133.415 479.681,-126.915 458.848,-121.999\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"459.514,-118.562 448.99,-119.781 457.978,-125.391 459.514,-118.562\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"630.5\" y=\"-146.3\">2 TensorType(float32, scalar)</text>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"g = gf.to_pydot(topo[1].op.fn)\n",
"SVG(g.create_svg())"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[z, y, y]"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"topo[0].inputs"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[x, y, z]"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"topo[1].inputs"
]
},
{
"cell_type": "code",
"execution_count": 46,
"execution_count": 7,
"metadata": {
"collapsed": false
},
......@@ -101,6 +1440,28 @@
"fo = of.op.fn"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[Elemwise{Composite{(i0 + (i1 * i2))}}(x, y, z)]"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fo.maker.fgraph.toposort()"
]
},
{
"cell_type": "code",
"execution_count": 47,
......
digraph G {
graph [bb="0,0,2478,251"];
graph [bb="0,0,2605,316"];
node [label="\N"];
subgraph cluster__1 {
graph [bb="8,168,723,243",
label="theano.compile.builders.OpFromGraph object at 0x1141d3a50",
lheight=0.21,
lp="365.5,231.5",
lwidth=4.89
];
_2 [fillcolor=limegreen,
subgraph cluster_n1 {
graph [bb="1159,80,1874,308"];
n11 [fillcolor="#FFAABB",
height=0.5,
label="name=z TensorType(float64, scalar)",
pos="605,194",
label="Elemwise{Composite{(i0 + (i1 * i2))}}",
pos="1509,194",
shape=ellipse,
style=filled,
type=colored,
width=4.3102];
n15 [fillcolor=dodgerblue,
height=0.5,
label="TensorType(float32, scalar)",
pos="1509,106",
shape=box,
style=filled,
width=3.0556];
_3 [fillcolor=limegreen,
width=2.3889];
n11 -> n15 [label="TensorType(float32, scalar)",
lp="1587,150",
pos="e,1509,124.08 1509,175.6 1509,163.75 1509,147.82 1509,134.29"];
n12 [fillcolor=limegreen,
height=0.5,
label="name=y TensorType(float64, scalar)",
pos="366,194",
label="name=x TensorType(float32, scalar)",
pos="1755,282",
shape=box,
style=filled,
width=3.0625];
_4 [fillcolor=limegreen,
n12 -> n11 [label="0 TensorType(float32, scalar)",
lp="1790.5,238",
pos="e,1603.7,208.31 1733.7,263.92 1718.7,252.69 1697.6,238.53 1677,230 1657.1,221.75 1635,215.37 1613.5,210.46"];
n13 [fillcolor=limegreen,
height=0.5,
label="name=y TensorType(float64, scalar)",
pos="127,194",
label="name=y TensorType(float32, scalar)",
pos="1516,282",
shape=box,
style=filled,
width=3.0625];
n13 -> n11 [label="1 TensorType(float32, scalar)",
lp="1593.5,238",
pos="e,1508.7,212.04 1512.6,263.98 1511.5,258.29 1510.6,251.89 1510,246 1509.3,238.24 1508.9,229.79 1508.8,222.04"];
n14 [fillcolor=limegreen,
height=0.5,
label="name=z TensorType(float32, scalar)",
pos="1277,282",
shape=box,
style=filled,
width=3.0556];
n14 -> n11 [label="2 TensorType(float32, scalar)",
lp="1422.5,238",
pos="e,1407,207.64 1293.3,263.77 1305,252.46 1321.6,238.29 1339,230 1357.1,221.35 1377.3,214.83 1397.3,209.92"];
}
subgraph cluster__5 {
graph [bb="1755,168,2470,243",
label="theano.compile.builders.OpFromGraph object at 0x1141d3a50 id=1",
lheight=0.21,
lp="2112.5,231.5",
lwidth=5.29
];
_6 [fillcolor=limegreen,
subgraph cluster_n6 {
graph [bb="1882,80,2597,308"];
n61 [fillcolor="#FFAABB",
height=0.5,
label="Elemwise{Composite{(i0 + (i1 * i2))}}",
pos="2232,194",
shape=ellipse,
style=filled,
type=colored,
width=4.3102];
n65 [fillcolor=dodgerblue,
height=0.5,
label="name=x TensorType(float64, scalar)",
pos="2351,194",
label="TensorType(float32, scalar)",
pos="2232,106",
shape=box,
style=filled,
width=2.3889];
n61 -> n65 [label="TensorType(float32, scalar)",
lp="2310,150",
pos="e,2232,124.08 2232,175.6 2232,163.75 2232,147.82 2232,134.29"];
n62 [fillcolor=limegreen,
height=0.5,
label="name=x TensorType(float32, scalar)",
pos="2478,282",
shape=box,
style=filled,
width=3.0625];
_7 [fillcolor=limegreen,
n62 -> n61 [label="0 TensorType(float32, scalar)",
lp="2512.5,238",
pos="e,2326.7,208.31 2456.7,263.92 2441.7,252.69 2420.6,238.53 2400,230 2380.1,221.75 2358,215.37 2336.5,210.46"];
n63 [fillcolor=limegreen,
height=0.5,
label="name=y TensorType(float64, scalar)",
pos="2112,194",
label="name=y TensorType(float32, scalar)",
pos="2239,282",
shape=box,
style=filled,
width=3.0625];
_8 [fillcolor=limegreen,
n63 -> n61 [label="1 TensorType(float32, scalar)",
lp="2316.5,238",
pos="e,2231.7,212.04 2235.6,263.98 2234.5,258.29 2233.6,251.89 2233,246 2232.3,238.24 2231.9,229.79 2231.8,222.04"];
n64 [fillcolor=limegreen,
height=0.5,
label="name=z TensorType(float64, scalar)",
pos="1873,194",
label="name=z TensorType(float32, scalar)",
pos="2000,282",
shape=box,
style=filled,
width=3.0556];
n64 -> n61 [label="2 TensorType(float32, scalar)",
lp="2145.5,238",
pos="e,2130,207.64 2016.3,263.77 2028,252.46 2044.6,238.29 2062,230 2080.1,221.35 2100.3,214.83 2120.3,209.92"];
}
_1 [height=0.5,
label="theano.compile.builders.OpFromGraph object at 0x1141d3a50",
pos="972,194",
n1 [height=0.5,
label="theano.compile.builders.OpFromGraph object at 0x10cc0bb90",
pos="238,194",
shape=ellipse,
width=6.6414];
_9 [fillcolor="#FFAABB",
subg=cluster_n1,
subg_map_inputs="[['n2', 'n12'], ['n3', 'n13'], ['n3', 'n14']]",
subg_map_outputs="[['n15', 'n5']]",
width=6.6185];
n5 [fillcolor="#FFAABB",
height=0.5,
label="Elemwise{Add}[(0, 0)]",
pos="1229,106",
pos="553,106",
shape=ellipse,
style=filled,
type=colored,
width=2.6784];
_1 -> _9 [label="1 TensorType(float64, scalar)",
lp="1207.5,150",
pos="e,1184,122.05 1021.9,176.32 1065.6,161.66 1129.2,140.38 1174.4,125.28"];
_5 [height=0.5,
label="theano.compile.builders.OpFromGraph object at 0x1141d3a50 id=1",
pos="1487,194",
n1 -> n5 [label="1 TensorType(float32, scalar)",
lp="507.5,150",
pos="e,500.93,121.21 298.36,176.52 353.72,161.41 435.35,139.12 491.17,123.88"];
n2 [fillcolor=limegreen,
height=0.5,
label="name=z TensorType(float32, scalar)",
pos="674,282",
shape=box,
style=filled,
width=3.0556];
n2 -> n1 [label="0 TensorType(float32, scalar)",
lp="684.5,238",
pos="e,430.16,204.72 633.61,263.87 622.72,258.66 611.15,252.56 601,246 591.73,240.01 592.17,234.31 582,230 555.22,218.66 499.43,210.89 \
440.43,205.61"];
n6 [height=0.5,
label="theano.compile.builders.OpFromGraph object at 0x10cc0bb90 id=1",
pos="780,194",
shape=ellipse,
width=7.167];
_5 -> _9 [color=red,
label="0 TensorType(float64, scalar)",
lp="1464.5,150",
pos="e,1274.2,122.05 1436.9,176.32 1393,161.66 1329.2,140.38 1283.8,125.28"];
_10 [fillcolor=dodgerblue,
subg=cluster_n6,
subg_map_inputs="[['n7', 'n62'], ['n3', 'n63'], ['n2', 'n64']]",
subg_map_outputs="[['n65', 'n5']]",
width=7.1441];
n2 -> n6 [label="2 TensorType(float32, scalar)",
lp="863.5,238",
pos="e,781.5,212.41 749.62,263.79 758.11,259.2 765.89,253.37 772,246 777.39,239.5 779.89,230.87 780.91,222.57"];
n3 [fillcolor=limegreen,
height=0.5,
label="name=y TensorType(float32, scalar)",
pos="224,282",
shape=box,
style=filled,
width=3.0625];
n3 -> n1 [label="1 TensorType(float32, scalar)",
lp="308.5,238",
pos="e,230.34,212.12 222.91,263.85 222.64,253.89 222.89,241.14 225,230 225.51,227.29 226.22,224.51 227.03,221.76"];
n3 -> n1 [label="2 TensorType(float32, scalar)",
lp="136.5,238",
pos="e,102.14,208.8 113.52,277.73 67.058,272.21 28.738,259.28 53,230 59.571,222.07 74.117,215.92 92.313,211.16"];
n3 -> n6 [label="1 TensorType(float32, scalar)",
lp="494.5,238",
pos="e,568.49,204.32 334.59,266.1 354.29,261.19 374.18,254.66 392,246 401.93,241.17 400.82,234.27 411,230 439.03,218.24 496.65,210.39 \
558.18,205.17"];
n6 -> n5 [color=red,
label="0 TensorType(float32, scalar)",
lp="770.5,150",
pos="e,593.76,122.44 735.69,176.21 697.67,161.81 642.89,141.06 603.24,126.03"];
n7 [fillcolor=limegreen,
height=0.5,
label="name=x TensorType(float32, scalar)",
pos="984,282",
shape=box,
style=filled,
width=3.0625];
n7 -> n6 [label="0 TensorType(float32, scalar)",
lp="1050.5,238",
pos="e,908.79,209.62 977.09,263.71 971.67,252.39 963.02,238.21 951,230 941.03,223.19 930.02,217.65 918.54,213.16"];
n9 [fillcolor=dodgerblue,
height=0.5,
label="TensorType(float64, scalar) id=5",
pos="1229,18",
label="TensorType(float32, scalar) id=5",
pos="553,18",
shape=box,
style=filled,
width=2.7847];
_9 -> _10 [label="TensorType(float64, scalar)",
lp="1307,62",
pos="e,1229,36.084 1229,87.597 1229,75.746 1229,59.817 1229,46.292"];
n5 -> n9 [label="TensorType(float32, scalar)",
lp="631,62",
pos="e,553,36.084 553,87.597 553,75.746 553,59.817 553,46.292"];
}
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Couldn't import dot_parser, loading of dot files will not be possible.\n"
]
}
],
"source": [
"import pydot as pd\n",
"from IPython.display import SVG"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"g = pd.Dot(graph_type='digraph')\n",
"g.add_node(pd.Node('A', fillcolor='blue', style='filled', shape='box', label='A Label', time=''))\n",
"g.add_node(pd.Node('B', fillcolor='green', shape='ellipse'))\n",
"g.add_edge(pd.Edge('A', 'B', labels='A -> B'))"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"116pt\" viewBox=\"0.00 0.00 70.00 116.00\" width=\"70pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 112)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-112 66,-112 66,4 -4,4\" stroke=\"none\"/>\n",
"<!-- A -->\n",
"<g class=\"node\" id=\"node1\"><title>A</title>\n",
"<polygon fill=\"blue\" points=\"62,-108 0,-108 0,-72 62,-72 62,-108\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"31\" y=\"-86.3\">A Label</text>\n",
"</g>\n",
"<!-- B -->\n",
"<g class=\"node\" id=\"node2\"><title>B</title>\n",
"<ellipse cx=\"31\" cy=\"-18\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"31\" y=\"-14.3\">B</text>\n",
"</g>\n",
"<!-- A&#45;&gt;B -->\n",
"<g class=\"edge\" id=\"edge1\"><title>A-&gt;B</title>\n",
"<path d=\"M31,-71.6966C31,-63.9827 31,-54.7125 31,-46.1124\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"34.5001,-46.1043 31,-36.1043 27.5001,-46.1044 34.5001,-46.1043\" stroke=\"black\"/>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"SVG(g.create_svg())"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"g = pd.Dot(graph_type='digraph')\n",
"\n",
"c1 = pd.Cluster('c1')\n",
"c1.add_node(pd.Node('A'))\n",
"c1.add_node(pd.Node('B'))\n",
"c1.add_edge(pd.Edge('A', 'B'))\n",
"g.add_subgraph(c1)\n",
"\n",
"c2 = pd.Cluster('c2')\n",
"c2.add_node(pd.Node('C'))\n",
"c2.add_node(pd.Node('D'))\n",
"c2.add_edge(pd.Edge('C', 'D'))\n",
"g.add_subgraph(c2)\n",
"\n",
"g.add_edge(pd.Edge('A', 'C'))"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"220pt\" viewBox=\"0.00 0.00 172.00 220.00\" width=\"172pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 216)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-216 168,-216 168,4 -4,4\" stroke=\"none\"/>\n",
"<g class=\"cluster\" id=\"clust1\"><title>cluster_c1</title>\n",
"<polygon fill=\"none\" points=\"8,-80 8,-204 78,-204 78,-80 8,-80\" stroke=\"black\"/>\n",
"</g>\n",
"<g class=\"cluster\" id=\"clust2\"><title>cluster_c2</title>\n",
"<polygon fill=\"none\" points=\"86,-8 86,-132 156,-132 156,-8 86,-8\" stroke=\"black\"/>\n",
"</g>\n",
"<!-- A -->\n",
"<g class=\"node\" id=\"node1\"><title>A</title>\n",
"<ellipse cx=\"43\" cy=\"-178\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"43\" y=\"-174.3\">A</text>\n",
"</g>\n",
"<!-- B -->\n",
"<g class=\"node\" id=\"node2\"><title>B</title>\n",
"<ellipse cx=\"43\" cy=\"-106\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"43\" y=\"-102.3\">B</text>\n",
"</g>\n",
"<!-- A&#45;&gt;B -->\n",
"<g class=\"edge\" id=\"edge1\"><title>A-&gt;B</title>\n",
"<path d=\"M43,-159.697C43,-151.983 43,-142.712 43,-134.112\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"46.5001,-134.104 43,-124.104 39.5001,-134.104 46.5001,-134.104\" stroke=\"black\"/>\n",
"</g>\n",
"<!-- C -->\n",
"<g class=\"node\" id=\"node3\"><title>C</title>\n",
"<ellipse cx=\"121\" cy=\"-106\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"121\" y=\"-102.3\">C</text>\n",
"</g>\n",
"<!-- A&#45;&gt;C -->\n",
"<g class=\"edge\" id=\"edge3\"><title>A-&gt;C</title>\n",
"<path d=\"M58.4103,-163.17C69.7345,-153.008 85.309,-139.03 98.0887,-127.561\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"100.517,-130.085 105.622,-120.801 95.8416,-124.875 100.517,-130.085\" stroke=\"black\"/>\n",
"</g>\n",
"<!-- D -->\n",
"<g class=\"node\" id=\"node4\"><title>D</title>\n",
"<ellipse cx=\"121\" cy=\"-34\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"121\" y=\"-30.3\">D</text>\n",
"</g>\n",
"<!-- C&#45;&gt;D -->\n",
"<g class=\"edge\" id=\"edge2\"><title>C-&gt;D</title>\n",
"<path d=\"M121,-87.6966C121,-79.9827 121,-70.7125 121,-62.1124\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"124.5,-62.1043 121,-52.1043 117.5,-62.1044 124.5,-62.1043\" stroke=\"black\"/>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"SVG(g.create_svg())"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"g = pd.Dot(graph_type='digraph')\n",
"\n",
"c1 = pd.Cluster('c1')\n",
"c1.add_node(pd.Node('A'))\n",
"c1.add_node(pd.Node('B'))\n",
"c1.add_edge(pd.Edge('A', 'B'))\n",
"g.add_subgraph(c1)\n",
"\n",
"c2 = pd.Cluster('c2')\n",
"c2.add_node(pd.Node('AA'))\n",
"c2.add_node(pd.Node('BB'))\n",
"c2.add_edge(pd.Edge('AA', 'BB'))\n",
"g.add_subgraph(c2)"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"digraph G {\n",
"\tgraph [bb=\"0,0,164,140\"];\n",
"\tnode [label=\"\\N\"];\n",
"\tsubgraph cluster_c1 {\n",
"\t\tgraph [bb=\"8,8,78,132\"];\n",
"\t\tA\t\t [height=0.5,\n",
"\t\t\tpos=\"43,106\",\n",
"\t\t\twidth=0.75];\n",
"\t\tB\t\t [height=0.5,\n",
"\t\t\tpos=\"43,34\",\n",
"\t\t\twidth=0.75];\n",
"\t\tA -> B\t\t [pos=\"e,43,52.104 43,87.697 43,79.983 43,70.712 43,62.112\"];\n",
"\t}\n",
"\tsubgraph cluster_c2 {\n",
"\t\tgraph [bb=\"86,8,156,132\"];\n",
"\t\tAA\t\t [height=0.5,\n",
"\t\t\tpos=\"121,106\",\n",
"\t\t\twidth=0.75];\n",
"\t\tBB\t\t [height=0.5,\n",
"\t\t\tpos=\"121,34\",\n",
"\t\t\twidth=0.75];\n",
"\t\tAA -> BB\t\t [pos=\"e,121,52.104 121,87.697 121,79.983 121,70.712 121,62.112\"];\n",
"\t}\n",
"}\n",
"\n"
]
}
],
"source": [
"print(g.create_dot())"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'cluster_c1'"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"c1.get_name()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"ename": "NameError",
"evalue": "global name 'sgraph' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-9-04d3aa97a139>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_subgraph\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'c1'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m/Users/angermue/python/venv/theano/lib/python2.7/site-packages/pydot.pyc\u001b[0m in \u001b[0;36mget_subgraph\u001b[0;34m(self, name)\u001b[0m\n\u001b[1;32m 1328\u001b[0m \u001b[0mmatch\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1329\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1330\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mobj_dict\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'subgraphs'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhas_key\u001b[0m\u001b[0;34m(\u001b[0m \u001b[0msgraph\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_name\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1331\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1332\u001b[0m \u001b[0msgraphs_obj_dict\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mobj_dict\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'subgraphs'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m \u001b[0msgraph\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_name\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mNameError\u001b[0m: global name 'sgraph' is not defined"
]
}
],
"source": [
"g.get_subgraph('c1')"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"n = pd.Node('a', param1='p1')"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"n.get_attributes()['p2'] = 10"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"g.write_dot('nested.dot')"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"220pt\" viewBox=\"0.00 0.00 172.00 220.00\" width=\"172pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 216)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-216 168,-216 168,4 -4,4\" stroke=\"none\"/>\n",
"<g class=\"cluster\" id=\"clust1\"><title>cluster_c1</title>\n",
"<polygon fill=\"none\" points=\"8,-80 8,-204 78,-204 78,-80 8,-80\" stroke=\"black\"/>\n",
"</g>\n",
"<g class=\"cluster\" id=\"clust2\"><title>cluster_c2</title>\n",
"<polygon fill=\"none\" points=\"86,-8 86,-132 156,-132 156,-8 86,-8\" stroke=\"black\"/>\n",
"</g>\n",
"<!-- A -->\n",
"<g class=\"node\" id=\"node1\"><title>A</title>\n",
"<ellipse cx=\"43\" cy=\"-178\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"43\" y=\"-174.3\">A</text>\n",
"</g>\n",
"<!-- B -->\n",
"<g class=\"node\" id=\"node2\"><title>B</title>\n",
"<ellipse cx=\"43\" cy=\"-106\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"43\" y=\"-102.3\">B</text>\n",
"</g>\n",
"<!-- A&#45;&gt;B -->\n",
"<g class=\"edge\" id=\"edge1\"><title>A-&gt;B</title>\n",
"<path d=\"M43,-159.697C43,-151.983 43,-142.712 43,-134.112\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"46.5001,-134.104 43,-124.104 39.5001,-134.104 46.5001,-134.104\" stroke=\"black\"/>\n",
"</g>\n",
"<!-- C -->\n",
"<g class=\"node\" id=\"node3\"><title>C</title>\n",
"<ellipse cx=\"121\" cy=\"-106\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"121\" y=\"-102.3\">C</text>\n",
"</g>\n",
"<!-- A&#45;&gt;C -->\n",
"<g class=\"edge\" id=\"edge3\"><title>A-&gt;C</title>\n",
"<path d=\"M58.4103,-163.17C69.7345,-153.008 85.309,-139.03 98.0887,-127.561\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"100.517,-130.085 105.622,-120.801 95.8416,-124.875 100.517,-130.085\" stroke=\"black\"/>\n",
"</g>\n",
"<!-- D -->\n",
"<g class=\"node\" id=\"node4\"><title>D</title>\n",
"<ellipse cx=\"121\" cy=\"-34\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"121\" y=\"-30.3\">D</text>\n",
"</g>\n",
"<!-- C&#45;&gt;D -->\n",
"<g class=\"edge\" id=\"edge2\"><title>C-&gt;D</title>\n",
"<path d=\"M121,-87.6966C121,-79.9827 121,-70.7125 121,-62.1124\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"124.5,-62.1043 121,-52.1043 117.5,-62.1044 124.5,-62.1043\" stroke=\"black\"/>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"SVG(g.create_svg())"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"g = pd.Dot(graph_type='digraph')\n",
"g.add_node(pd.Node('A', fillcolor='lightblue', style='filled', shape='box', label='A Label', foo='1'))\n",
"g.add_node(pd.Node('B', fillcolor='green', shape='ellipse'))\n",
"g.add_edge(pd.Edge('A', 'B', labels='A -> B'))"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"116pt\" viewBox=\"0.00 0.00 70.00 116.00\" width=\"70pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 112)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-112 66,-112 66,4 -4,4\" stroke=\"none\"/>\n",
"<!-- A -->\n",
"<g class=\"node\" id=\"node1\"><title>A</title>\n",
"<polygon fill=\"lightblue\" points=\"62,-108 0,-108 0,-72 62,-72 62,-108\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"31\" y=\"-86.3\">A Label</text>\n",
"</g>\n",
"<!-- B -->\n",
"<g class=\"node\" id=\"node2\"><title>B</title>\n",
"<ellipse cx=\"31\" cy=\"-18\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"31\" y=\"-14.3\">B</text>\n",
"</g>\n",
"<!-- A&#45;&gt;B -->\n",
"<g class=\"edge\" id=\"edge1\"><title>A-&gt;B</title>\n",
"<path d=\"M31,-71.6966C31,-63.9827 31,-54.7125 31,-46.1124\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"34.5001,-46.1043 31,-36.1043 27.5001,-46.1044 34.5001,-46.1043\" stroke=\"black\"/>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"SVG(g.create_svg())"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"digraph G {\n",
"\tgraph [bb=\"0,0,62,108\"];\n",
"\tnode [label=\"\\N\"];\n",
"\tA\t [fillcolor=lightblue,\n",
"\t\tfoo=1,\n",
"\t\theight=0.5,\n",
"\t\tlabel=\"A Label\",\n",
"\t\tpos=\"31,90\",\n",
"\t\tshape=box,\n",
"\t\tstyle=filled,\n",
"\t\twidth=0.86111];\n",
"\tB\t [fillcolor=green,\n",
"\t\theight=0.5,\n",
"\t\tpos=\"31,18\",\n",
"\t\tshape=ellipse,\n",
"\t\twidth=0.75];\n",
"\tA -> B\t [labels=\"A -> B\",\n",
"\t\tpos=\"e,31,36.104 31,71.697 31,63.983 31,54.712 31,46.112\"];\n",
"}\n",
"\n"
]
}
],
"source": [
"print(g.create_dot())"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.10"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
......@@ -82,4 +82,9 @@ svg {
border: 1px solid black;
border-radius: 8px;
pointer-events: none;
}
\ No newline at end of file
}
path.hull {
fill: lightsteelblue;
fill-opacity: 0.3;
}
......@@ -13,54 +13,49 @@ function flipAxes(nodes) {
function processDotGraph(dotGraph) {
// Merge and remove subgraph nodes
dotGraph.rnodes = {};
for (var nodeId in dotGraph._nodes) {
if (!exists(dotGraph._nodes[nodeId])) {
continue;
}
if (nodeId.startsWith('cluster_')) {
var id = nodeId.replace('cluster_', '');
assert(exists(dotGraph._nodes[id]));
var parent = dotGraph.node(id);
var childIds = dotGraph.children(nodeId);
for (var i in childIds) {
var childId = childIds[i];
dotGraph.setParent(childId, id);
dotGraph.setEdge(childId, id, {'label': 'opfrom'});
var child = dotGraph.node(childId);
}
dotGraph.removeNode(nodeId);
var node = dotGraph._nodes[nodeId];
node.id = nodeId;
node.isCluster = nodeId.startsWith('cluster');
if (!node.isCluster) {
dotGraph.rnodes[nodeId] = node;
}
}
var i = 0;
for (var nodeId in dotGraph._nodes) {
for (var nodeId in dotGraph.rnodes) {
var node = dotGraph._nodes[nodeId];
node.id = nodeId;
node.pos = node.pos.split(',').map(function(d) {return parseInt(d);});
var size = textSize(node.label, {'class': 'nodeText'});
node.width = size.width + 2 * pad;
node.height = size.height + 2 * pad;
node.cx = node.width / 2;
node.cy = node.height / 2;
node.hasChilds = dotGraph.children(nodeId).length > 0;
node.hasChilds = exists(node.subg);
node.showChilds = false;
node.profile = parseProfile(node.profile);
if (node.profile.length) {
isProfiled = true;
}
if (exists(node.subg_map_inputs)) {
node.subg_map_inputs = eval(node.subg_map_inputs)
}
if (exists(node.subg_map_outputs)) {
node.subg_map_outputs = eval(node.subg_map_outputs)
}
}
flipAxes(dotGraph._nodes);
flipAxes(dotGraph.rnodes);
// Offset and scale positions
var posMin = [Infinity, Infinity];
for (var i in dotGraph._nodes) {
for (var i in dotGraph.rnodes) {
var node = dotGraph._nodes[i];
posMin[0] = Math.min(posMin[0], node.pos[0]);
posMin[1] = Math.min(posMin[1], node.pos[1]);
}
for (var i in dotGraph._nodes) {
for (var i in dotGraph.rnodes) {
var node = dotGraph._nodes[i];
var pos = node.pos;
pos[0] -= posMin[0];
......@@ -91,146 +86,214 @@ function processDotGraph(dotGraph) {
}
}
function makeNode(dotGraph, dotNode) {
var node = {};
node.value = dotNode;
node.fixed = true;
return node;
}
function traverseChilds(dotGraph, parent) {
var childs = dotGraph.children(parent);
var nodes = [];
function traverseChilds(dotGraph, nodes, groups, parent) {
var preId = '';
var ref = undefined;
var group = {'id': groups.length, 'nodes': [], 'parent': parent};
if (exists(parent)) {
ref = parent.value.subg;
group.parent = parent;
group.nodes.push(parent);
parent.group = group;
}
groups.push(group);
var childs = dotGraph.children(ref);
for (var i in childs) {
var child = dotGraph.node(childs[i]);
nodes.push(makeNode(dotGraph, child));
if (child.isCluster) {
continue;
}
var node = {
'id': child.id,
'value': child,
'index': nodes.length,
'fixed': true,
'group': group,
'isParent': child.showChilds,
'parent': parent
};
nodes.push(node);
if (child.showChilds) {
nodes = nodes.concat(traverseChilds(dotGraph, child.id));
traverseChilds(dotGraph, nodes, groups, node);
} else {
group.nodes.push(node);
}
}
return nodes;
}
function groupSize(nodes) {
var minPos = [Infinity, Infinity];
var maxPos = [-Infinity, -Infinity];
for (var i in nodes) {
var node = nodes[i];
if (node.isParent) {
continue;
}
minPos[0] = Math.min(minPos[0], node.value.pos[0]);
minPos[1] = Math.min(minPos[1], node.value.pos[1]);
maxPos[0] = Math.max(maxPos[0], node.value.pos[0] + node.value.width);
maxPos[1] = Math.max(maxPos[1], node.value.pos[1] + node.value.height);
}
return [maxPos[0] - minPos[0], maxPos[1] - minPos[1]];
}
function forceGraph(dotGraph, prevGraph) {
// Parse nodes
var graph = {};
graph.nodes = traverseChilds(dotGraph);
var graph = {'nodes': [], 'groups': []};
traverseChilds(dotGraph, graph.nodes, graph.groups);
graph.nodesd = {};
for (var i in graph.nodes) {
var node = graph.nodes[i];
node.index = i;
graph.nodesd[node.value.id] = node;
graph.nodesd[node.id] = node;
}
var groups = {};
for (var i in graph.nodes) {
var node = graph.nodes[i];
var parentId = dotGraph.parent(node.value.id);
if (exists(parentId)) {
if (!(parentId in groups)) {
groups[parentId] = [];
}
groups[parentId].push(node.value.id);
}
}
graph.nodesp = graph.nodes.filter(function(d) {return d.isParent;});
graph.nodesn = graph.nodes.filter(function(d) {return !d.isParent;});
// Compute group centroids
var groupsMeta = {};
for (var i in groups) {
var group = groups[i];
var cx = 0, cy = 0;
for (var j in group) {
var node = graph.nodesd[group[j]];
cx += node.value.pos[0];
cy += node.value.pos[1];
for (i in graph.groups) {
var group = graph.groups[i];
group.size = groupSize(group.nodes);
var parent = group.parent;
if (exists(parent)) {
var prevParent = prevGraph.nodesd[group.parent.id];
if (exists(prevParent)) {
group.pos = [prevParent.x, prevParent.y];
} else {
group.pos = parent.pos.slice(0);
}
group.pos[0] += parent.value.cx;
group.pos[1] += parent.value.cy;
} else {
group.pos = [group.size[0] / 2, group.size[1] / 2];
}
var n = groups[i].length;
cx /= n;
cy /= n;
groupsMeta[i] = {'cx': cx, 'cy': cy, 'n': n};
}
// Reuse previous positions
for (var i in graph.nodes) {
var node = graph.nodes[i];
var prevNode;
if (exists(prevGraph)) {
prevNode = prevGraph.nodesd[node.value.id];
var min = [Infinity, Infinity];
for (var j in group.nodes) {
var node = group.nodes[j];
if (!node.isParent) {
min[0] = Math.min(min[0], node.value.pos[0]);
min[1] = Math.min(min[0], node.value.pos[1]);
}
}
if (exists(prevNode)) {
node.x = prevNode.x;
node.y = prevNode.y;
node.fixed = prevNode.fixed;
} else {
var parentId = dotGraph.parent(node.value.id);
if (exists(parentId)) {
var parentPos;
var parent = prevGraph.nodesd[parentId];
if (exists(parent)) {
parentPos = [parent.x, parent.y];
} else {
parent = graph.nodesd[parentId];
parentPos = parent.value.pos;
}
var g = groupsMeta[parentId];
node.x = parentPos[0] + node.value.pos[0] - g.cx;
node.y = parentPos[1] - 100 + node.value.pos[1] - g.cy;
node.fixed = true;
for (var j in group.nodes) {
var node = group.nodes[j];
if (node.isParent) {
node.x = group.pos[0];
node.y = group.pos[1];
} else {
node.x = node.value.pos[0];
node.y = node.value.pos[1];
node.x = group.pos[0] - group.size[0] / 2 + node.value.pos[0] - min[0];
node.y = group.pos[1] - group.size[1] / 2 + node.value.pos[1] - min[1];
}
}
}
// Offset graph on initialization
if (!exists(prevGraph)) {
var posMin = [Infinity, Infinity];
for (var i in graph.nodes) {
var node = graph.nodes[i];
posMin[0] = Math.min(posMin[0], node.x);
posMin[1] = Math.min(posMin[1], node.y);
}
graph.size = graph.groups[0].size;
// Reuse previous positions
if (exists(prevGraph)) {
for (var i in graph.nodes) {
var node = graph.nodes[i];
node.x -= posMin[0];
node.y -= posMin[1];
var prevNode;
prevNode = prevGraph.nodesd[node.id];
if (exists(prevNode)) {
node.x = prevNode.x;
node.y = prevNode.y;
node.fixed = prevNode.fixed;
} else {
for (var j in prevGraph.groups) {
var group = prevGraph.groups[j];
if (exists(group.parent) && group.parent.id == node.id) {
node.x = group.pos[0] + group.size[0] / 2;
node.y = group.pos[1] + group.size[1] / 2;
}
}
}
}
}
// Compute dimension of graph
var minPos = [Infinity, Infinity];
var maxPos = [-Infinity, -Infinity];
for (var i in graph.nodes) {
var node = graph.nodes[i];
minPos[0] = Math.min(minPos[0], node.x);
minPos[1] = Math.min(minPos[1], node.y);
maxPos[0] = Math.max(maxPos[0], node.x + node.value.width);
maxPos[1] = Math.max(maxPos[1], node.y + node.value.height);
}
graph.dim = {'minPos': minPos, 'maxPos': maxPos,
'size': [maxPos[0] - minPos[0], maxPos[1] - minPos[0]]};
// Edges
graph.edges = [];
for (var i in graph.nodes) {
for (var j in graph.nodes) {
var sourceId = graph.nodes[i].value.id;
var targetId = graph.nodes[j].value.id;
var dotEdge = dotGraph.edge(sourceId, targetId);
for (var i in graph.nodesn) {
for (var j in graph.nodesn) {
var source = graph.nodesn[i];
var target = graph.nodesn[j];
var dotEdge = dotGraph.edge(source.value.id, target.value.id);
if (exists(dotEdge)) {
var edge = {};
edge.source = parseInt(graph.nodes[i].index);
edge.target = parseInt(graph.nodes[j].index);
edge.source = parseInt(source.index);
edge.target = parseInt(target.index);
edge.value = dotEdge;
graph.edges.push(edge);
}
function redirectEdges(map, dotEdge) {
for (var k in map) {
var kmap = map[k];
if (kmap[0] == source.id && kmap[1] == target.id) {
var edge = {};
edge.source = parseInt(source.index);
edge.target = parseInt(target.index);
edge.value = dotEdge;
graph.edges.push(edge);
}
}
}
var map = undefined;
if (exists(target.parent)) {
var parent = target.parent;
var dotEdge = dotGraph.edge(source.id, parent.id);
if (exists(dotEdge)) {
map = parent.value.subg_map_inputs;
redirectEdges(map, dotEdge);
}
}
if (exists(source.parent)) {
var parent = source.parent;
var dotEdge = dotGraph.edge(parent.id, target.id);
if (exists(dotEdge)) {
map = parent.value.subg_map_outputs;
redirectEdges(map, dotEdge);
}
}
}
}
return graph;
}
function convexHulls(graph, offset) {
var hulls = [];
offset = offset || 20;
for (var i in graph.groups) {
var group = graph.groups[i];
if (!exists(group.parent)) {
continue;
}
var points = [];
for (var j in group.nodes) {
var node = group.nodes[j];
if (node.isParent) {
points.push([node.x, node.y]);
} else {
points.push([node.x - node.value.cx - offset, node.y - node.value.cy - offset]);
points.push([node.x - node.value.cx - offset, node.y + node.value.cy + offset]);
points.push([node.x + node.value.cx + offset, node.y - node.value.cy - offset]);
points.push([node.x + node.value.cx + offset, node.y + node.value.cy + offset]);
}
}
hulls.push({group: i, path: d3.geom.hull(points)});
}
return hulls;
}
function drawCluster(d) {
return curve(d.path); // 0.8
}
function setupGraph() {
if (isProfiled) {
d3.select('body').select('#menu').append('input')
......@@ -251,6 +314,23 @@ function setupGraph() {
var isEdgeOver = false;
var isEdgeLabelOver = false;
graph.hulls = convexHulls(graph);
hulls = pane.selectAll('#hulls').remove();
hulls = pane.append('g').attr('id', 'hulls')
.selectAll('path')
.data(graph.hulls).enter()
.append('path')
.attr('class', 'hull')
.attr('d', drawCluster);
hulls.on('dblclick', function(d) {
var parent = graph.groups[d.group].parent;
parent.value.showChilds = !parent.value.showChilds;
graph = forceGraph(dotGraph, graph);
setupGraph();
});
// Add edges
edges = pane.selectAll('#edges').remove();
edges = pane.append('g').attr('id', 'edges')
......@@ -287,7 +367,7 @@ function setupGraph() {
// Add nodes
pane.selectAll('#nodes').remove();
nodes = pane.append('g').attr('id', 'nodes')
.selectAll('g').data(graph.nodes).enter().append('g');
.selectAll('g').data(graph.nodesn).enter().append('g');
updateNodes();
updateGraph();
......@@ -341,9 +421,9 @@ function setupGraph() {
layout = d3.layout.force()
.nodes(graph.nodes)
.links(graph.edges)
.size(graph.dim.size)
.size(graph.size)
.charge(-300)
.linkDistance(300)
.linkDistance(400)
.linkStrength(0.4)
.gravity(0)
.on('tick', updateGraph);
......@@ -373,6 +453,10 @@ function pathPos(x1, y1, x2, y2, c) {
}
function updateGraph() {
graph.hulls = convexHulls(graph);
hulls.data(graph.hulls)
.attr('d', drawCluster);
// Update nodes
nodes.attr('transform', function(d) { return 'translate(' + (d.x - d.value.cx) + ' ' + (d.y - d.value.cy) + ')'; });
// Update edges
......
digraph G {
graph [bb="0,0,2482,251"];
graph [bb="0,0,2606,316"];
node [label="\N"];
subgraph cluster__1 {
graph [bb="8,168,723,243",
label="theano.compile.builders.OpFromGraph object at 0x114552bd0",
lheight=0.21,
lp="365.5,231.5",
lwidth=4.90
];
_2 [fillcolor=limegreen,
subgraph cluster_n1 {
graph [bb="1160,80,1875,308"];
n11 [fillcolor="#FFAABB",
height=0.5,
label="name=z TensorType(float64, scalar)",
pos="605,194",
label="Elemwise{Composite{(i0 + (i1 * i2))}}",
pos="1510,194",
shape=ellipse,
style=filled,
type=colored,
width=4.3102];
n15 [fillcolor=dodgerblue,
height=0.5,
label="TensorType(float32, scalar)",
pos="1510,106",
shape=box,
style=filled,
width=3.0556];
_3 [fillcolor=limegreen,
width=2.3889];
n11 -> n15 [label="TensorType(float32, scalar)",
lp="1588,150",
pos="e,1510,124.08 1510,175.6 1510,163.75 1510,147.82 1510,134.29"];
n12 [fillcolor=limegreen,
height=0.5,
label="name=y TensorType(float64, scalar)",
pos="366,194",
label="name=x TensorType(float32, scalar)",
pos="1756,282",
shape=box,
style=filled,
width=3.0625];
_4 [fillcolor=limegreen,
n12 -> n11 [label="0 TensorType(float32, scalar)",
lp="1791.5,238",
pos="e,1604.7,208.31 1734.7,263.92 1719.7,252.69 1698.6,238.53 1678,230 1658.1,221.75 1636,215.37 1614.5,210.46"];
n13 [fillcolor=limegreen,
height=0.5,
label="name=y TensorType(float64, scalar)",
pos="127,194",
label="name=y TensorType(float32, scalar)",
pos="1517,282",
shape=box,
style=filled,
width=3.0625];
n13 -> n11 [label="1 TensorType(float32, scalar)",
lp="1594.5,238",
pos="e,1509.7,212.04 1513.6,263.98 1512.5,258.29 1511.6,251.89 1511,246 1510.3,238.24 1509.9,229.79 1509.8,222.04"];
n14 [fillcolor=limegreen,
height=0.5,
label="name=z TensorType(float32, scalar)",
pos="1278,282",
shape=box,
style=filled,
width=3.0556];
n14 -> n11 [label="2 TensorType(float32, scalar)",
lp="1423.5,238",
pos="e,1408,207.64 1294.3,263.77 1306,252.46 1322.6,238.29 1340,230 1358.1,221.35 1378.3,214.83 1398.3,209.92"];
}
subgraph cluster__5 {
graph [bb="1759,168,2474,243",
label="theano.compile.builders.OpFromGraph object at 0x114552bd0 id=1",
lheight=0.21,
lp="2116.5,231.5",
lwidth=5.31
];
_6 [fillcolor=limegreen,
subgraph cluster_n6 {
graph [bb="1883,80,2598,308"];
n61 [fillcolor="#FFAABB",
height=0.5,
label="Elemwise{Composite{(i0 + (i1 * i2))}}",
pos="2233,194",
shape=ellipse,
style=filled,
type=colored,
width=4.3102];
n65 [fillcolor=dodgerblue,
height=0.5,
label="name=x TensorType(float64, scalar)",
pos="2355,194",
label="TensorType(float32, scalar)",
pos="2233,106",
shape=box,
style=filled,
width=2.3889];
n61 -> n65 [label="TensorType(float32, scalar)",
lp="2311,150",
pos="e,2233,124.08 2233,175.6 2233,163.75 2233,147.82 2233,134.29"];
n62 [fillcolor=limegreen,
height=0.5,
label="name=x TensorType(float32, scalar)",
pos="2479,282",
shape=box,
style=filled,
width=3.0625];
_7 [fillcolor=limegreen,
n62 -> n61 [label="0 TensorType(float32, scalar)",
lp="2513.5,238",
pos="e,2327.7,208.31 2457.7,263.92 2442.7,252.69 2421.6,238.53 2401,230 2381.1,221.75 2359,215.37 2337.5,210.46"];
n63 [fillcolor=limegreen,
height=0.5,
label="name=y TensorType(float64, scalar)",
pos="2116,194",
label="name=y TensorType(float32, scalar)",
pos="2240,282",
shape=box,
style=filled,
width=3.0625];
_8 [fillcolor=limegreen,
n63 -> n61 [label="1 TensorType(float32, scalar)",
lp="2317.5,238",
pos="e,2232.7,212.04 2236.6,263.98 2235.5,258.29 2234.6,251.89 2234,246 2233.3,238.24 2232.9,229.79 2232.8,222.04"];
n64 [fillcolor=limegreen,
height=0.5,
label="name=z TensorType(float64, scalar)",
pos="1877,194",
label="name=z TensorType(float32, scalar)",
pos="2001,282",
shape=box,
style=filled,
width=3.0556];
n64 -> n61 [label="2 TensorType(float32, scalar)",
lp="2146.5,238",
pos="e,2131,207.64 2017.3,263.77 2029,252.46 2045.6,238.29 2063,230 2081.1,221.35 2101.3,214.83 2121.3,209.92"];
}
_1 [height=0.5,
label="theano.compile.builders.OpFromGraph object at 0x114552bd0",
pos="973,194",
n1 [height=0.5,
label="theano.compile.builders.OpFromGraph object at 0x1100c70d0",
pos="239,194",
shape=ellipse,
width=6.6504];
_9 [fillcolor="#FFAABB",
subg=cluster_n1,
subg_map_inputs="[['n2', 'n12'], ['n3', 'n13'], ['n3', 'n14']]",
subg_map_outputs="[['n15', 'n5']]",
width=6.6414];
n5 [fillcolor="#FFAABB",
height=0.5,
label="Elemwise{Add}[(0, 0)]",
pos="1231,106",
pos="554,106",
shape=ellipse,
style=filled,
type=colored,
width=2.6784];
_1 -> _9 [label="1 TensorType(float64, scalar)",
lp="1209.5,150",
pos="e,1185.8,122.05 1023.1,176.32 1067,161.66 1130.8,140.38 1176.2,125.28"];
_5 [height=0.5,
label="theano.compile.builders.OpFromGraph object at 0x114552bd0 id=1",
pos="1490,194",
n1 -> n5 [label="1 TensorType(float32, scalar)",
lp="508.5,150",
pos="e,501.93,121.21 299.36,176.52 354.72,161.41 436.35,139.12 492.17,123.88"];
n2 [fillcolor=limegreen,
height=0.5,
label="name=z TensorType(float32, scalar)",
pos="675,282",
shape=box,
style=filled,
width=3.0556];
n2 -> n1 [label="0 TensorType(float32, scalar)",
lp="685.5,238",
pos="e,431.16,204.72 634.61,263.87 623.72,258.66 612.15,252.56 602,246 592.73,240.01 593.17,234.31 583,230 556.22,218.66 500.43,210.89 \
441.43,205.61"];
n6 [height=0.5,
label="theano.compile.builders.OpFromGraph object at 0x1100c70d0 id=1",
pos="781,194",
shape=ellipse,
width=7.1761];
_5 -> _9 [color=red,
label="0 TensorType(float64, scalar)",
lp="1466.5,150",
pos="e,1276.3,122.05 1439.8,176.32 1395.6,161.66 1331.5,140.38 1286,125.28"];
_10 [fillcolor=dodgerblue,
subg=cluster_n6,
subg_map_inputs="[['n7', 'n62'], ['n3', 'n63'], ['n2', 'n64']]",
subg_map_outputs="[['n65', 'n5']]",
width=7.167];
n2 -> n6 [label="2 TensorType(float32, scalar)",
lp="864.5,238",
pos="e,782.5,212.41 750.62,263.79 759.11,259.2 766.89,253.37 773,246 778.39,239.5 780.89,230.87 781.91,222.57"];
n3 [fillcolor=limegreen,
height=0.5,
label="name=y TensorType(float32, scalar)",
pos="225,282",
shape=box,
style=filled,
width=3.0625];
n3 -> n1 [label="1 TensorType(float32, scalar)",
lp="309.5,238",
pos="e,231.34,212.12 223.91,263.85 223.64,253.89 223.89,241.14 226,230 226.51,227.29 227.22,224.51 228.03,221.76"];
n3 -> n1 [label="2 TensorType(float32, scalar)",
lp="137.5,238",
pos="e,102.68,208.9 114.52,277.73 68.058,272.21 29.738,259.28 54,230 60.527,222.12 74.92,216.01 92.944,211.26"];
n3 -> n6 [label="1 TensorType(float32, scalar)",
lp="495.5,238",
pos="e,569.49,204.32 335.59,266.1 355.29,261.19 375.18,254.66 393,246 402.93,241.17 401.82,234.27 412,230 440.03,218.24 497.65,210.39 \
559.18,205.17"];
n6 -> n5 [color=red,
label="0 TensorType(float32, scalar)",
lp="771.5,150",
pos="e,594.76,122.44 736.69,176.21 698.67,161.81 643.89,141.06 604.24,126.03"];
n7 [fillcolor=limegreen,
height=0.5,
label="name=x TensorType(float32, scalar)",
pos="985,282",
shape=box,
style=filled,
width=3.0625];
n7 -> n6 [label="0 TensorType(float32, scalar)",
lp="1051.5,238",
pos="e,909.79,209.62 978.09,263.71 972.67,252.39 964.02,238.21 952,230 942.03,223.19 931.02,217.65 919.54,213.16"];
n9 [fillcolor=dodgerblue,
height=0.5,
label="TensorType(float64, scalar) id=5",
pos="1231,18",
label="TensorType(float32, scalar) id=5",
pos="554,18",
shape=box,
style=filled,
width=2.7847];
_9 -> _10 [label="TensorType(float64, scalar)",
lp="1309,62",
pos="e,1231,36.084 1231,87.597 1231,75.746 1231,59.817 1231,46.292"];
n5 -> n9 [label="TensorType(float32, scalar)",
lp="632,62",
pos="e,554,36.084 554,87.597 554,75.746 554,59.817 554,46.292"];
}
......@@ -22,7 +22,7 @@
</div>
<script type="text/javascript">
var path = 'index.dot'
var path = 'index.dot';
var dotGraph;
var graph = {};
var nodes = [];
......@@ -85,13 +85,6 @@
.attr("d", "M0,0 L4,2 L0,4 Z")
.attr('fill', function(d) { return d.color;});
d3.text(path, function(data) {
dotGraph = graphlibDot.read(data);
processDotGraph(dotGraph);
graph = forceGraph(dotGraph);
setupGraph();
});
// Zoom behaviour
function zoom(d) {
var trans = d3.event.translate;
......@@ -107,6 +100,18 @@
bZoom.event(svg);
svg.on("dblclick.zoom", null);
var curve = d3.svg.line()
.interpolate("cardinal-closed")
.tension(.85);
// Read and initialize graph
d3.text(path, function(data) {
dotGraph = graphlibDot.read(data);
processDotGraph(dotGraph);
graph = forceGraph(dotGraph);
setupGraph();
});
</script>
</body>
</html>
......@@ -82,4 +82,9 @@ svg {
border: 1px solid black;
border-radius: 8px;
pointer-events: none;
}
\ No newline at end of file
}
path.hull {
fill: lightsteelblue;
fill-opacity: 0.3;
}
......@@ -13,54 +13,49 @@ function flipAxes(nodes) {
function processDotGraph(dotGraph) {
// Merge and remove subgraph nodes
dotGraph.rnodes = {};
for (var nodeId in dotGraph._nodes) {
if (!exists(dotGraph._nodes[nodeId])) {
continue;
}
if (nodeId.startsWith('cluster_')) {
var id = nodeId.replace('cluster_', '');
assert(exists(dotGraph._nodes[id]));
var parent = dotGraph.node(id);
var childIds = dotGraph.children(nodeId);
for (var i in childIds) {
var childId = childIds[i];
dotGraph.setParent(childId, id);
dotGraph.setEdge(childId, id, {'label': 'opfrom'});
var child = dotGraph.node(childId);
}
dotGraph.removeNode(nodeId);
var node = dotGraph._nodes[nodeId];
node.id = nodeId;
node.isCluster = nodeId.startsWith('cluster');
if (!node.isCluster) {
dotGraph.rnodes[nodeId] = node;
}
}
var i = 0;
for (var nodeId in dotGraph._nodes) {
for (var nodeId in dotGraph.rnodes) {
var node = dotGraph._nodes[nodeId];
node.id = nodeId;
node.pos = node.pos.split(',').map(function(d) {return parseInt(d);});
var size = textSize(node.label, {'class': 'nodeText'});
node.width = size.width + 2 * pad;
node.height = size.height + 2 * pad;
node.cx = node.width / 2;
node.cy = node.height / 2;
node.hasChilds = dotGraph.children(nodeId).length > 0;
node.hasChilds = exists(node.subg);
node.showChilds = false;
node.profile = parseProfile(node.profile);
if (node.profile.length) {
isProfiled = true;
}
if (exists(node.subg_map_inputs)) {
node.subg_map_inputs = eval(node.subg_map_inputs)
}
if (exists(node.subg_map_outputs)) {
node.subg_map_outputs = eval(node.subg_map_outputs)
}
}
flipAxes(dotGraph._nodes);
flipAxes(dotGraph.rnodes);
// Offset and scale positions
var posMin = [Infinity, Infinity];
for (var i in dotGraph._nodes) {
for (var i in dotGraph.rnodes) {
var node = dotGraph._nodes[i];
posMin[0] = Math.min(posMin[0], node.pos[0]);
posMin[1] = Math.min(posMin[1], node.pos[1]);
}
for (var i in dotGraph._nodes) {
for (var i in dotGraph.rnodes) {
var node = dotGraph._nodes[i];
var pos = node.pos;
pos[0] -= posMin[0];
......@@ -91,146 +86,214 @@ function processDotGraph(dotGraph) {
}
}
function makeNode(dotGraph, dotNode) {
var node = {};
node.value = dotNode;
node.fixed = true;
return node;
}
function traverseChilds(dotGraph, parent) {
var childs = dotGraph.children(parent);
var nodes = [];
function traverseChilds(dotGraph, nodes, groups, parent) {
var preId = '';
var ref = undefined;
var group = {'id': groups.length, 'nodes': [], 'parent': parent};
if (exists(parent)) {
ref = parent.value.subg;
group.parent = parent;
group.nodes.push(parent);
parent.group = group;
}
groups.push(group);
var childs = dotGraph.children(ref);
for (var i in childs) {
var child = dotGraph.node(childs[i]);
nodes.push(makeNode(dotGraph, child));
if (child.isCluster) {
continue;
}
var node = {
'id': child.id,
'value': child,
'index': nodes.length,
'fixed': true,
'group': group,
'isParent': child.showChilds,
'parent': parent
};
nodes.push(node);
if (child.showChilds) {
nodes = nodes.concat(traverseChilds(dotGraph, child.id));
traverseChilds(dotGraph, nodes, groups, node);
} else {
group.nodes.push(node);
}
}
return nodes;
}
function groupSize(nodes) {
var minPos = [Infinity, Infinity];
var maxPos = [-Infinity, -Infinity];
for (var i in nodes) {
var node = nodes[i];
if (node.isParent) {
continue;
}
minPos[0] = Math.min(minPos[0], node.value.pos[0]);
minPos[1] = Math.min(minPos[1], node.value.pos[1]);
maxPos[0] = Math.max(maxPos[0], node.value.pos[0] + node.value.width);
maxPos[1] = Math.max(maxPos[1], node.value.pos[1] + node.value.height);
}
return [maxPos[0] - minPos[0], maxPos[1] - minPos[1]];
}
function forceGraph(dotGraph, prevGraph) {
// Parse nodes
var graph = {};
graph.nodes = traverseChilds(dotGraph);
var graph = {'nodes': [], 'groups': []};
traverseChilds(dotGraph, graph.nodes, graph.groups);
graph.nodesd = {};
for (var i in graph.nodes) {
var node = graph.nodes[i];
node.index = i;
graph.nodesd[node.value.id] = node;
graph.nodesd[node.id] = node;
}
var groups = {};
for (var i in graph.nodes) {
var node = graph.nodes[i];
var parentId = dotGraph.parent(node.value.id);
if (exists(parentId)) {
if (!(parentId in groups)) {
groups[parentId] = [];
}
groups[parentId].push(node.value.id);
}
}
graph.nodesp = graph.nodes.filter(function(d) {return d.isParent;});
graph.nodesn = graph.nodes.filter(function(d) {return !d.isParent;});
// Compute group centroids
var groupsMeta = {};
for (var i in groups) {
var group = groups[i];
var cx = 0, cy = 0;
for (var j in group) {
var node = graph.nodesd[group[j]];
cx += node.value.pos[0];
cy += node.value.pos[1];
for (i in graph.groups) {
var group = graph.groups[i];
group.size = groupSize(group.nodes);
var parent = group.parent;
if (exists(parent)) {
var prevParent = prevGraph.nodesd[group.parent.id];
if (exists(prevParent)) {
group.pos = [prevParent.x, prevParent.y];
} else {
group.pos = parent.pos.slice(0);
}
group.pos[0] += parent.value.cx;
group.pos[1] += parent.value.cy;
} else {
group.pos = [group.size[0] / 2, group.size[1] / 2];
}
var n = groups[i].length;
cx /= n;
cy /= n;
groupsMeta[i] = {'cx': cx, 'cy': cy, 'n': n};
}
// Reuse previous positions
for (var i in graph.nodes) {
var node = graph.nodes[i];
var prevNode;
if (exists(prevGraph)) {
prevNode = prevGraph.nodesd[node.value.id];
var min = [Infinity, Infinity];
for (var j in group.nodes) {
var node = group.nodes[j];
if (!node.isParent) {
min[0] = Math.min(min[0], node.value.pos[0]);
min[1] = Math.min(min[0], node.value.pos[1]);
}
}
if (exists(prevNode)) {
node.x = prevNode.x;
node.y = prevNode.y;
node.fixed = prevNode.fixed;
} else {
var parentId = dotGraph.parent(node.value.id);
if (exists(parentId)) {
var parentPos;
var parent = prevGraph.nodesd[parentId];
if (exists(parent)) {
parentPos = [parent.x, parent.y];
} else {
parent = graph.nodesd[parentId];
parentPos = parent.value.pos;
}
var g = groupsMeta[parentId];
node.x = parentPos[0] + node.value.pos[0] - g.cx;
node.y = parentPos[1] - 100 + node.value.pos[1] - g.cy;
node.fixed = true;
for (var j in group.nodes) {
var node = group.nodes[j];
if (node.isParent) {
node.x = group.pos[0];
node.y = group.pos[1];
} else {
node.x = node.value.pos[0];
node.y = node.value.pos[1];
node.x = group.pos[0] - group.size[0] / 2 + node.value.pos[0] - min[0];
node.y = group.pos[1] - group.size[1] / 2 + node.value.pos[1] - min[1];
}
}
}
// Offset graph on initialization
if (!exists(prevGraph)) {
var posMin = [Infinity, Infinity];
for (var i in graph.nodes) {
var node = graph.nodes[i];
posMin[0] = Math.min(posMin[0], node.x);
posMin[1] = Math.min(posMin[1], node.y);
}
graph.size = graph.groups[0].size;
// Reuse previous positions
if (exists(prevGraph)) {
for (var i in graph.nodes) {
var node = graph.nodes[i];
node.x -= posMin[0];
node.y -= posMin[1];
var prevNode;
prevNode = prevGraph.nodesd[node.id];
if (exists(prevNode)) {
node.x = prevNode.x;
node.y = prevNode.y;
node.fixed = prevNode.fixed;
} else {
for (var j in prevGraph.groups) {
var group = prevGraph.groups[j];
if (exists(group.parent) && group.parent.id == node.id) {
node.x = group.pos[0] + group.size[0] / 2;
node.y = group.pos[1] + group.size[1] / 2;
}
}
}
}
}
// Compute dimension of graph
var minPos = [Infinity, Infinity];
var maxPos = [-Infinity, -Infinity];
for (var i in graph.nodes) {
var node = graph.nodes[i];
minPos[0] = Math.min(minPos[0], node.x);
minPos[1] = Math.min(minPos[1], node.y);
maxPos[0] = Math.max(maxPos[0], node.x + node.value.width);
maxPos[1] = Math.max(maxPos[1], node.y + node.value.height);
}
graph.dim = {'minPos': minPos, 'maxPos': maxPos,
'size': [maxPos[0] - minPos[0], maxPos[1] - minPos[0]]};
// Edges
graph.edges = [];
for (var i in graph.nodes) {
for (var j in graph.nodes) {
var sourceId = graph.nodes[i].value.id;
var targetId = graph.nodes[j].value.id;
var dotEdge = dotGraph.edge(sourceId, targetId);
for (var i in graph.nodesn) {
for (var j in graph.nodesn) {
var source = graph.nodesn[i];
var target = graph.nodesn[j];
var dotEdge = dotGraph.edge(source.value.id, target.value.id);
if (exists(dotEdge)) {
var edge = {};
edge.source = parseInt(graph.nodes[i].index);
edge.target = parseInt(graph.nodes[j].index);
edge.source = parseInt(source.index);
edge.target = parseInt(target.index);
edge.value = dotEdge;
graph.edges.push(edge);
}
function redirectEdges(map, dotEdge) {
for (var k in map) {
var kmap = map[k];
if (kmap[0] == source.id && kmap[1] == target.id) {
var edge = {};
edge.source = parseInt(source.index);
edge.target = parseInt(target.index);
edge.value = dotEdge;
graph.edges.push(edge);
}
}
}
var map = undefined;
if (exists(target.parent)) {
var parent = target.parent;
var dotEdge = dotGraph.edge(source.id, parent.id);
if (exists(dotEdge)) {
map = parent.value.subg_map_inputs;
redirectEdges(map, dotEdge);
}
}
if (exists(source.parent)) {
var parent = source.parent;
var dotEdge = dotGraph.edge(parent.id, target.id);
if (exists(dotEdge)) {
map = parent.value.subg_map_outputs;
redirectEdges(map, dotEdge);
}
}
}
}
return graph;
}
function convexHulls(graph, offset) {
var hulls = [];
offset = offset || 20;
for (var i in graph.groups) {
var group = graph.groups[i];
if (!exists(group.parent)) {
continue;
}
var points = [];
for (var j in group.nodes) {
var node = group.nodes[j];
if (node.isParent) {
points.push([node.x, node.y]);
} else {
points.push([node.x - node.value.cx - offset, node.y - node.value.cy - offset]);
points.push([node.x - node.value.cx - offset, node.y + node.value.cy + offset]);
points.push([node.x + node.value.cx + offset, node.y - node.value.cy - offset]);
points.push([node.x + node.value.cx + offset, node.y + node.value.cy + offset]);
}
}
hulls.push({group: i, path: d3.geom.hull(points)});
}
return hulls;
}
function drawCluster(d) {
return curve(d.path); // 0.8
}
function setupGraph() {
if (isProfiled) {
d3.select('body').select('#menu').append('input')
......@@ -251,6 +314,23 @@ function setupGraph() {
var isEdgeOver = false;
var isEdgeLabelOver = false;
graph.hulls = convexHulls(graph);
hulls = pane.selectAll('#hulls').remove();
hulls = pane.append('g').attr('id', 'hulls')
.selectAll('path')
.data(graph.hulls).enter()
.append('path')
.attr('class', 'hull')
.attr('d', drawCluster);
hulls.on('dblclick', function(d) {
var parent = graph.groups[d.group].parent;
parent.value.showChilds = !parent.value.showChilds;
graph = forceGraph(dotGraph, graph);
setupGraph();
});
// Add edges
edges = pane.selectAll('#edges').remove();
edges = pane.append('g').attr('id', 'edges')
......@@ -287,7 +367,7 @@ function setupGraph() {
// Add nodes
pane.selectAll('#nodes').remove();
nodes = pane.append('g').attr('id', 'nodes')
.selectAll('g').data(graph.nodes).enter().append('g');
.selectAll('g').data(graph.nodesn).enter().append('g');
updateNodes();
updateGraph();
......@@ -341,9 +421,9 @@ function setupGraph() {
layout = d3.layout.force()
.nodes(graph.nodes)
.links(graph.edges)
.size(graph.dim.size)
.size(graph.size)
.charge(-300)
.linkDistance(300)
.linkDistance(400)
.linkStrength(0.4)
.gravity(0)
.on('tick', updateGraph);
......@@ -373,6 +453,10 @@ function pathPos(x1, y1, x2, y2, c) {
}
function updateGraph() {
graph.hulls = convexHulls(graph);
hulls.data(graph.hulls)
.attr('d', drawCluster);
// Update nodes
nodes.attr('transform', function(d) { return 'translate(' + (d.x - d.value.cx) + ' ' + (d.y - d.value.cy) + ')'; });
// Update edges
......
digraph G {
graph [bb="0,0,1450,251"];
graph [bb="0,0,1998,340"];
node [label="\N"];
subgraph cluster__1 {
graph [bb="8,168,723,243",
label="theano.compile.builders.OpFromGraph object at 0x114648450",
lheight=0.21,
lp="365.5,231.5",
lwidth=4.90
];
_2 [fillcolor=limegreen,
subgraph cluster_n1 {
graph [bb="773,8,1990,332"];
subgraph cluster_n11 {
graph [bb="1505,96,1982,324"];
n111 [fillcolor="#FFAABB",
height=0.5,
label="Elemwise{mul,no_inplace}",
pos="1717,210",
shape=ellipse,
style=filled,
type=colored,
width=3.0943];
n114 [fillcolor=dodgerblue,
height=0.5,
label="TensorType(float32, scalar)",
pos="1717,122",
shape=box,
style=filled,
width=2.3889];
n111 -> n114 [label="TensorType(float32, scalar)",
lp="1795,166",
pos="e,1717,140.08 1717,191.6 1717,179.75 1717,163.82 1717,150.29"];
n112 [fillcolor=limegreen,
height=0.5,
label="name=x TensorType(float32, scalar)",
pos="1863,298",
shape=box,
style=filled,
width=3.0625];
n112 -> n111 [label="0 TensorType(float32, scalar)",
lp="1892.5,254",
pos="e,1750.2,227.23 1838.1,279.79 1823,269.57 1803.2,256.58 1785,246 1776.8,241.24 1767.9,236.42 1759.4,231.94"];
n113 [fillcolor=limegreen,
height=0.5,
label="name=y TensorType(float32, scalar)",
pos="1624,298",
shape=box,
style=filled,
width=3.0625];
n113 -> n111 [label="1 TensorType(float32, scalar)",
lp="1701.5,254",
pos="e,1645.8,223.99 1616.5,279.94 1613.1,269.27 1611.1,255.75 1618,246 1623,238.94 1629.5,233.29 1636.9,228.78"];
}
n11 [height=0.5,
label="theano.compile.builders.OpFromGraph object at 0x1105b0c50",
pos="1258,210",
shape=ellipse,
subg=cluster_n11,
subg_map_inputs="[['n12', 'n112'], ['n13', 'n113']]",
subg_map_outputs="[['n114', 'n15']]",
width=6.6414];
n15 [fillcolor="#FFAABB",
height=0.5,
label="name=x TensorType(float64, scalar)",
pos="604,194",
label="Elemwise{Add}[(0, 0)]",
pos="1030,122",
shape=ellipse,
style=filled,
type=colored,
width=2.6784];
n11 -> n15 [color=red,
label="0 TensorType(float32, scalar)",
lp="1266.5,166",
pos="e,1081.2,137.27 1223.3,192.13 1200.9,181.61 1171.1,168.18 1144,158 1127.1,151.64 1108.4,145.55 1091.2,140.28"];
n12 [fillcolor=limegreen,
height=0.5,
label="name=x TensorType(float32, scalar)",
pos="1307,298",
shape=box,
style=filled,
width=3.0625];
_3 [fillcolor=limegreen,
n12 -> n11 [label="0 TensorType(float32, scalar)",
lp="1370.5,254",
pos="e,1267.7,228.08 1297.1,279.6 1290.1,267.39 1280.7,250.87 1272.9,237.09"];
n13 [fillcolor=limegreen,
height=0.5,
label="name=y TensorType(float64, scalar)",
pos="365,194",
label="name=y TensorType(float32, scalar)",
pos="1068,298",
shape=box,
style=filled,
width=3.0625];
_4 [fillcolor=limegreen,
n13 -> n11 [label="1 TensorType(float32, scalar)",
lp="1191.5,254",
pos="e,1151.9,226.21 1077.3,279.8 1084.3,268.51 1094.9,254.35 1108,246 1118.5,239.31 1130.1,233.89 1142.2,229.51"];
n17 [fillcolor=dodgerblue,
height=0.5,
label="name=z TensorType(float64, scalar)",
pos="126,194",
label="TensorType(float32, scalar) id=4",
pos="1030,34",
shape=box,
style=filled,
width=2.7847];
n15 -> n17 [label="TensorType(float32, scalar)",
lp="1108,78",
pos="e,1030,52.084 1030,103.6 1030,91.746 1030,75.817 1030,62.292"];
n16 [fillcolor=limegreen,
height=0.5,
label="name=z TensorType(float32, scalar)",
pos="891,210",
shape=box,
style=filled,
width=3.0556];
n16 -> n15 [label="1 TensorType(float32, scalar)",
lp="1056.5,166",
pos="e,1003.2,139.58 918.79,191.8 940.57,178.33 971.02,159.49 994.55,144.93"];
}
_1 [height=0.5,
label="theano.compile.builders.OpFromGraph object at 0x114648450",
pos="972,194",
n1 [height=0.5,
label="theano.compile.builders.OpFromGraph object at 0x1105a91d0",
pos="524,210",
shape=ellipse,
width=6.6504];
_5 [fillcolor="#FFAABB",
subg=cluster_n1,
subg_map_inputs="[['n2', 'n12'], ['n3', 'n13'], ['n4', 'n16']]",
subg_map_outputs="[['n17', 'n6']]",
width=6.6414];
n6 [fillcolor="#FFAABB",
height=0.5,
label="Elemwise{Add}[(0, 0)]",
pos="1156,106",
pos="214,122",
shape=ellipse,
style=filled,
type=colored,
width=2.6784];
_1 -> _5 [color=red,
label="0 TensorType(float64, scalar)",
lp="1164.5,150",
pos="e,1121.9,122.94 1008.4,176.01 1038.4,161.97 1081.1,142.02 1112.8,127.18"];
_7 [fillcolor=dodgerblue,
n1 -> n6 [color=red,
label="0 TensorType(float32, scalar)",
lp="480.5,166",
pos="e,265.49,137.28 464.6,192.52 410.31,177.46 330.36,155.28 275.44,140.04"];
n2 [fillcolor=limegreen,
height=0.5,
label="TensorType(float64, scalar) id=4",
pos="1156,18",
label="name=x TensorType(float32, scalar)",
pos="354,298",
shape=box,
style=filled,
width=2.7847];
_5 -> _7 [label="TensorType(float64, scalar)",
lp="1234,62",
pos="e,1156,36.084 1156,87.597 1156,75.746 1156,59.817 1156,46.292"];
_6 [fillcolor=limegreen,
width=3.0625];
n2 -> n1 [label="0 TensorType(float32, scalar)",
lp="465.5,254",
pos="e,418.96,226.25 359.32,279.9 363.67,268.65 370.95,254.49 382,246 390.32,239.61 399.64,234.37 409.44,230.08"];
n3 [fillcolor=limegreen,
height=0.5,
label="name=z TensorType(float64, scalar)",
pos="1340,194",
label="name=y TensorType(float32, scalar)",
pos="593,298",
shape=box,
style=filled,
width=3.0625];
n3 -> n1 [label="1 TensorType(float32, scalar)",
lp="648.5,254",
pos="e,537.71,228.08 579.04,279.6 568.96,267.04 555.22,249.91 543.98,235.91"];
n4 [fillcolor=limegreen,
height=0.5,
label="name=z TensorType(float32, scalar)",
pos="110,298",
shape=box,
style=filled,
width=3.0556];
_6 -> _5 [label="1 TensorType(float64, scalar)",
lp="1364.5,150",
pos="e,1202.1,121.95 1313.3,175.88 1296.2,165.33 1273.3,151.95 1252,142 1239.2,136.01 1225.1,130.36 1211.7,125.42"];
n4 -> n1 [label="2 TensorType(float32, scalar)",
lp="281.5,254",
pos="e,355.01,222.75 133.36,279.81 150.39,268.22 174.5,253.68 198,246 226.06,236.82 284.9,229.34 344.97,223.68"];
n4 -> n6 [label="1 TensorType(float32, scalar)",
lp="192.5,210",
pos="e,173.05,138.3 105.03,279.8 99.747,257.95 94.027,219.76 109,192 120.82,170.09 142.96,154.01 163.88,142.9"];
n7 [fillcolor=dodgerblue,
height=0.5,
label="TensorType(float32, scalar) id=4",
pos="214,34",
shape=box,
style=filled,
width=2.7847];
n6 -> n7 [label="TensorType(float32, scalar)",
lp="292,78",
pos="e,214,52.084 214,103.6 214,91.746 214,75.817 214,62.292"];
}
......@@ -22,7 +22,7 @@
</div>
<script type="text/javascript">
var path = 'index.dot'
var path = 'index.dot';
var dotGraph;
var graph = {};
var nodes = [];
......@@ -85,13 +85,6 @@
.attr("d", "M0,0 L4,2 L0,4 Z")
.attr('fill', function(d) { return d.color;});
d3.text(path, function(data) {
dotGraph = graphlibDot.read(data);
processDotGraph(dotGraph);
graph = forceGraph(dotGraph);
setupGraph();
});
// Zoom behaviour
function zoom(d) {
var trans = d3.event.translate;
......@@ -107,6 +100,18 @@
bZoom.event(svg);
svg.on("dblclick.zoom", null);
var curve = d3.svg.line()
.interpolate("cardinal-closed")
.tension(.85);
// Read and initialize graph
d3.text(path, function(data) {
dotGraph = graphlibDot.read(data);
processDotGraph(dotGraph);
graph = forceGraph(dotGraph);
setupGraph();
});
</script>
</body>
</html>
......@@ -46,21 +46,6 @@
"import theano.d3printing as d3p"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def viz_ofg(ofg):\n",
" fo = ofg.op.fn\n",
" gf = d3p.GraphFormatter()\n",
" g = gf.to_pydot(fo)\n",
" return g.create_svg()"
]
},
{
"cell_type": "markdown",
"metadata": {},
......@@ -70,7 +55,7 @@
},
{
"cell_type": "code",
"execution_count": 27,
"execution_count": 4,
"metadata": {
"collapsed": false
},
......@@ -85,7 +70,7 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": 5,
"metadata": {
"collapsed": false
},
......@@ -101,253 +86,15 @@
"[Open](./example1/index.html)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## OFG node 1"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"220pt\" viewBox=\"0.00 0.00 722.00 220.00\" width=\"722pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 216)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-216 718,-216 718,4 -4,4\" stroke=\"none\"/>\n",
"<!-- _1 -->\n",
"<g class=\"node\" id=\"node1\"><title>_1</title>\n",
"<ellipse cx=\"349\" cy=\"-106\" fill=\"#ffaabb\" rx=\"155.005\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"349\" y=\"-102.3\">Elemwise{Composite{(i0 + (i1 * i2))}}</text>\n",
"</g>\n",
"<!-- _5 -->\n",
"<g class=\"node\" id=\"node5\"><title>_5</title>\n",
"<polygon fill=\"dodgerblue\" points=\"435,-36 263,-36 263,-0 435,-0 435,-36\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"349\" y=\"-14.3\">TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _1&#45;&gt;_5 -->\n",
"<g class=\"edge\" id=\"edge4\"><title>_1-&gt;_5</title>\n",
"<path d=\"M349,-87.5966C349,-75.7459 349,-59.8169 349,-46.2917\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"352.5,-46.084 349,-36.084 345.5,-46.084 352.5,-46.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"427\" y=\"-58.3\">TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _2 -->\n",
"<g class=\"node\" id=\"node2\"><title>_2</title>\n",
"<polygon fill=\"limegreen\" points=\"220.25,-212 -0.25,-212 -0.25,-176 220.25,-176 220.25,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"110\" y=\"-190.3\">name=x TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _2&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge1\"><title>_2-&gt;_1</title>\n",
"<path d=\"M128.186,-175.807C141.119,-164.521 159.428,-150.354 178,-142 197.086,-133.415 218.319,-126.915 239.152,-121.999\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"240.022,-125.391 249.01,-119.781 238.486,-118.562 240.022,-125.391\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"261.5\" y=\"-146.3\">0 TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _3 -->\n",
"<g class=\"node\" id=\"node3\"><title>_3</title>\n",
"<polygon fill=\"limegreen\" points=\"459.25,-212 238.75,-212 238.75,-176 459.25,-176 459.25,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"349\" y=\"-190.3\">name=y TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _3&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge2\"><title>_3-&gt;_1</title>\n",
"<path d=\"M349,-175.597C349,-163.746 349,-147.817 349,-134.292\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"352.5,-134.084 349,-124.084 345.5,-134.084 352.5,-134.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"432.5\" y=\"-146.3\">1 TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _4 -->\n",
"<g class=\"node\" id=\"node4\"><title>_4</title>\n",
"<polygon fill=\"limegreen\" points=\"698,-212 478,-212 478,-176 698,-176 698,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"588\" y=\"-190.3\">name=z TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _4&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge3\"><title>_4-&gt;_1</title>\n",
"<path d=\"M569.814,-175.807C556.881,-164.521 538.572,-150.354 520,-142 500.914,-133.415 479.681,-126.915 458.848,-121.999\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"459.514,-118.562 448.99,-119.781 457.978,-125.391 459.514,-118.562\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"630.5\" y=\"-146.3\">2 TensorType(float64, scalar)</text>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"SVG(viz_ofg(f.maker.fgraph.toposort()[0]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## OFG node 2"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"220pt\" viewBox=\"0.00 0.00 722.00 220.00\" width=\"722pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 216)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-216 718,-216 718,4 -4,4\" stroke=\"none\"/>\n",
"<!-- _1 -->\n",
"<g class=\"node\" id=\"node1\"><title>_1</title>\n",
"<ellipse cx=\"349\" cy=\"-106\" fill=\"#ffaabb\" rx=\"155.005\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"349\" y=\"-102.3\">Elemwise{Composite{(i0 + (i1 * i2))}}</text>\n",
"</g>\n",
"<!-- _5 -->\n",
"<g class=\"node\" id=\"node5\"><title>_5</title>\n",
"<polygon fill=\"dodgerblue\" points=\"435,-36 263,-36 263,-0 435,-0 435,-36\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"349\" y=\"-14.3\">TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _1&#45;&gt;_5 -->\n",
"<g class=\"edge\" id=\"edge4\"><title>_1-&gt;_5</title>\n",
"<path d=\"M349,-87.5966C349,-75.7459 349,-59.8169 349,-46.2917\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"352.5,-46.084 349,-36.084 345.5,-46.084 352.5,-46.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"427\" y=\"-58.3\">TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _2 -->\n",
"<g class=\"node\" id=\"node2\"><title>_2</title>\n",
"<polygon fill=\"limegreen\" points=\"220.25,-212 -0.25,-212 -0.25,-176 220.25,-176 220.25,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"110\" y=\"-190.3\">name=x TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _2&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge1\"><title>_2-&gt;_1</title>\n",
"<path d=\"M128.186,-175.807C141.119,-164.521 159.428,-150.354 178,-142 197.086,-133.415 218.319,-126.915 239.152,-121.999\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"240.022,-125.391 249.01,-119.781 238.486,-118.562 240.022,-125.391\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"261.5\" y=\"-146.3\">0 TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _3 -->\n",
"<g class=\"node\" id=\"node3\"><title>_3</title>\n",
"<polygon fill=\"limegreen\" points=\"459.25,-212 238.75,-212 238.75,-176 459.25,-176 459.25,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"349\" y=\"-190.3\">name=y TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _3&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge2\"><title>_3-&gt;_1</title>\n",
"<path d=\"M349,-175.597C349,-163.746 349,-147.817 349,-134.292\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"352.5,-134.084 349,-124.084 345.5,-134.084 352.5,-134.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"432.5\" y=\"-146.3\">1 TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _4 -->\n",
"<g class=\"node\" id=\"node4\"><title>_4</title>\n",
"<polygon fill=\"limegreen\" points=\"698,-212 478,-212 478,-176 698,-176 698,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"588\" y=\"-190.3\">name=z TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _4&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge3\"><title>_4-&gt;_1</title>\n",
"<path d=\"M569.814,-175.807C556.881,-164.521 538.572,-150.354 520,-142 500.914,-133.415 479.681,-126.915 458.848,-121.999\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"459.514,-118.562 448.99,-119.781 457.978,-125.391 459.514,-118.562\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"630.5\" y=\"-146.3\">2 TensorType(float64, scalar)</text>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"SVG(viz_ofg(f.maker.fgraph.toposort()[1]))"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"ofg2 = f.maker.fgraph.toposort()[1]"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[x, y, z]"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ofg2.inputs"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[Elemwise{Composite{(i0 + (i1 * i2))}}(x, y, z)]"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ofg2.op.fn.maker.fgraph.toposort()"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[x, y, z]"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ofg2.op.fn.maker.fgraph.toposort()[0].inputs"
"topo = f.maker.fgraph.toposort()"
]
},
{
......@@ -359,7 +106,7 @@
},
{
"cell_type": "code",
"execution_count": 24,
"execution_count": 7,
"metadata": {
"collapsed": false
},
......@@ -376,7 +123,7 @@
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": 8,
"metadata": {
"collapsed": false
},
......@@ -391,261 +138,6 @@
"source": [
"[Open](./example2/index.html)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## OFG node 1 "
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"topo = f.maker.fgraph.toposort()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[<theano.compile.builders.OpFromGraph object at 0x112538910>(x, y, z),\n",
" Elemwise{Add}[(0, 0)](<theano.compile.builders.OpFromGraph object at 0x112538910>.0, z)]"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"topo"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"259pt\" viewBox=\"0.00 0.00 1220.00 259.00\" width=\"1220pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 255)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-255 1216,-255 1216,4 -4,4\" stroke=\"none\"/>\n",
"<g class=\"cluster\" id=\"clust1\"><title>cluster__1</title>\n",
"<polygon fill=\"none\" points=\"8,-168 8,-243 485,-243 485,-168 8,-168\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"246.5\" y=\"-227.8\">theano.compile.builders.OpFromGraph object at 0x112538390</text>\n",
"</g>\n",
"<!-- _2 -->\n",
"<g class=\"node\" id=\"node1\"><title>_2</title>\n",
"<polygon fill=\"limegreen\" points=\"476.25,-212 255.75,-212 255.75,-176 476.25,-176 476.25,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"366\" y=\"-190.3\">name=x TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _3 -->\n",
"<g class=\"node\" id=\"node2\"><title>_3</title>\n",
"<polygon fill=\"limegreen\" points=\"237.25,-212 16.75,-212 16.75,-176 237.25,-176 237.25,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"127\" y=\"-190.3\">name=y TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _1 -->\n",
"<g class=\"node\" id=\"node3\"><title>_1</title>\n",
"<ellipse cx=\"734\" cy=\"-194\" fill=\"none\" rx=\"239.243\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"734\" y=\"-190.3\">theano.compile.builders.OpFromGraph object at 0x112538390</text>\n",
"</g>\n",
"<!-- _4 -->\n",
"<g class=\"node\" id=\"node4\"><title>_4</title>\n",
"<ellipse cx=\"918\" cy=\"-106\" fill=\"#ffaabb\" rx=\"96.2631\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"918\" y=\"-102.3\">Elemwise{Add}[(0, 0)]</text>\n",
"</g>\n",
"<!-- _1&#45;&gt;_4 -->\n",
"<g class=\"edge\" id=\"edge1\"><title>_1-&gt;_4</title>\n",
"<path d=\"M770.352,-176.009C800.379,-161.975 843.074,-142.02 874.835,-127.175\" fill=\"none\" stroke=\"red\"/>\n",
"<polygon fill=\"red\" points=\"876.321,-130.344 883.898,-122.939 873.357,-124.003 876.321,-130.344\" stroke=\"red\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"926.5\" y=\"-146.3\">0 TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _6 -->\n",
"<g class=\"node\" id=\"node6\"><title>_6</title>\n",
"<polygon fill=\"dodgerblue\" points=\"1018.25,-36 817.75,-36 817.75,-0 1018.25,-0 1018.25,-36\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"918\" y=\"-14.3\">TensorType(float64, scalar) id=4</text>\n",
"</g>\n",
"<!-- _4&#45;&gt;_6 -->\n",
"<g class=\"edge\" id=\"edge3\"><title>_4-&gt;_6</title>\n",
"<path d=\"M918,-87.5966C918,-75.7459 918,-59.8169 918,-46.2917\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"921.5,-46.084 918,-36.084 914.5,-46.084 921.5,-46.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"996\" y=\"-58.3\">TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _5 -->\n",
"<g class=\"node\" id=\"node5\"><title>_5</title>\n",
"<polygon fill=\"limegreen\" points=\"1212,-212 992,-212 992,-176 1212,-176 1212,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"1102\" y=\"-190.3\">name=z TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _5&#45;&gt;_4 -->\n",
"<g class=\"edge\" id=\"edge2\"><title>_5-&gt;_4</title>\n",
"<path d=\"M1075.31,-175.883C1058.2,-165.325 1035.27,-151.949 1014,-142 1001.2,-136.013 987.068,-130.363 973.675,-125.42\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"974.677,-122.061 964.083,-121.951 972.296,-128.644 974.677,-122.061\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"1126.5\" y=\"-146.3\">1 TensorType(float64, scalar)</text>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ofg1 = f.maker.fgraph.toposort()[0]\n",
"SVG(viz_ofg(ofg1))"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"ofg2 = f.maker.fgraph.toposort()[1]"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[<theano.compile.builders.OpFromGraph object at 0x1124a4f90>.0, z]"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ofg2.inputs"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[x, y, z]"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ofg1.inputs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## OFG node 2"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"220pt\" viewBox=\"0.00 0.00 513.00 220.00\" width=\"513pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 216)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-216 509,-216 509,4 -4,4\" stroke=\"none\"/>\n",
"<!-- _1 -->\n",
"<g class=\"node\" id=\"node1\"><title>_1</title>\n",
"<ellipse cx=\"229\" cy=\"-106\" fill=\"#ffaabb\" rx=\"111.186\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"229\" y=\"-102.3\">Elemwise{mul,no_inplace}</text>\n",
"</g>\n",
"<!-- _4 -->\n",
"<g class=\"node\" id=\"node4\"><title>_4</title>\n",
"<polygon fill=\"dodgerblue\" points=\"315,-36 143,-36 143,-0 315,-0 315,-36\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"229\" y=\"-14.3\">TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _1&#45;&gt;_4 -->\n",
"<g class=\"edge\" id=\"edge3\"><title>_1-&gt;_4</title>\n",
"<path d=\"M229,-87.5966C229,-75.7459 229,-59.8169 229,-46.2917\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"232.5,-46.084 229,-36.084 225.5,-46.084 232.5,-46.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"307\" y=\"-58.3\">TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _2 -->\n",
"<g class=\"node\" id=\"node2\"><title>_2</title>\n",
"<polygon fill=\"limegreen\" points=\"220.25,-212 -0.25,-212 -0.25,-176 220.25,-176 220.25,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"110\" y=\"-190.3\">name=x TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _2&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge1\"><title>_2-&gt;_1</title>\n",
"<path d=\"M124.112,-175.983C133.526,-165.334 146.597,-151.821 160,-142 167.085,-136.809 175.052,-131.986 182.989,-127.682\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"184.633,-130.772 191.889,-123.051 181.402,-124.562 184.633,-130.772\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"243.5\" y=\"-146.3\">0 TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _3 -->\n",
"<g class=\"node\" id=\"node3\"><title>_3</title>\n",
"<polygon fill=\"limegreen\" points=\"459.25,-212 238.75,-212 238.75,-176 459.25,-176 459.25,-212\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"349\" y=\"-190.3\">name=y TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- _3&#45;&gt;_1 -->\n",
"<g class=\"edge\" id=\"edge2\"><title>_3-&gt;_1</title>\n",
"<path d=\"M345.336,-175.801C342.177,-164.804 336.566,-150.971 327,-142 319.637,-135.095 310.819,-129.537 301.533,-125.066\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"302.691,-121.753 292.126,-120.949 299.884,-128.165 302.691,-121.753\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"421.5\" y=\"-146.3\">1 TensorType(float64, scalar)</text>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ofg2 = ofg1.op.fn.maker.fgraph.toposort()[0]\n",
"SVG(viz_ofg(ofg2))"
]
}
],
"metadata": {
......
......@@ -56,18 +56,33 @@ class GraphFormatter(object):
'unused': 'lightgrey'
}
self.max_label_size = 70
self.node_prefix = 'n'
def get_node_id(self):
self.nnodes += 1
id_ = '_%d' % (self.nnodes)
return id_
def add_node(self, node):
assert not node in self.nodes
_id = '%s%d' % (self.node_prefix, len(self.nodes) + 1)
self.nodes[node] = _id
return _id
def to_pydot(self, fct):
def node_id(self, node):
if node in self.nodes:
return self.nodes[node]
else:
return self.add_node(node)
def to_pydot(self, fct, graph=None):
"""Create pydot graph from function.
:param fct: a compiled Theano function, a Variable, an Apply or
a list of Variable.
"""
if graph is None:
graph = pd.Dot()
self.nodes = {}
self.var_str = {}
self.all_strings = set()
self.apply_name_cache = {}
if isinstance(fct, Function):
mode = fct.maker.mode
......@@ -99,13 +114,6 @@ class GraphFormatter(object):
raise RuntimeError("Failed to import pydot. You must install pydot"
" for `pydotprint` to work.")
g = pd.Dot()
self.var_str = {}
self.all_strings = set()
self.apply_name_cache = {}
self.nnodes = 0
# Update the inputs that have an update function
self.input_update = {}
......@@ -119,15 +127,9 @@ class GraphFormatter(object):
apply_shape = 'ellipse'
var_shape = 'box'
for node_idx, node in enumerate(topo):
aid, astr, aprof = self.apply_name(node, fct, topo, mode, profile)
is_opfrom = isinstance(node.op, builders.OpFromGraph)
if is_opfrom:
parent = pd.Cluster(aid, label=astr)
g.add_subgraph(parent)
else:
parent = g
for node in topo:
node_id = self.node_id(node)
astr, aprof = self.apply_name(node, fct, topo, mode, profile)
use_color = None
for opName, color in self.colorCodes.items():
......@@ -135,62 +137,91 @@ class GraphFormatter(object):
use_color = color
if use_color is None:
nw_node = pd.Node(aid, label=astr, shape=apply_shape, profile=aprof)
pd_node = pd.Node(node_id, label=astr, shape=apply_shape, profile=aprof)
else:
nw_node = pd.Node(aid, label=astr, style='filled', fillcolor=use_color,
pd_node = pd.Node(node_id, label=astr, style='filled', fillcolor=use_color,
shape=apply_shape, type='colored', profile=aprof)
g.add_node(nw_node)
graph.add_node(pd_node)
def make_node(label, **kwargs):
def make_node(_id, label, **kwargs):
t = {k:v for k,v in kwargs.items() if v is not None}
return pd.Node(self.get_node_id(), label=label, **t)
return pd.Node(_id, label=label, **t)
for id, var in enumerate(node.inputs):
param = {}
if hasattr(node.op, 'view_map') and id in reduce(
list.__add__, node.op.view_map.values(), []):
param['color'] = self.node_colors['output']
edge_params = {}
if hasattr(node.op, 'view_map') and id in reduce(list.__add__, node.op.view_map.values(), []):
edge_params['color'] = self.node_colors['output']
elif hasattr(node.op, 'destroy_map') and id in reduce(
list.__add__, node.op.destroy_map.values(), []):
param['color'] = 'red'
edge_params['color'] = 'red'
edge_label = str(var.type)
if len(node.inputs) > 1:
edge_label = str(id) + ' ' + edge_label
var_id = self.node_id(var.owner if var.owner else var)
if var.owner is None:
id_ = self.var_name(var)
n = make_node(id_, style='filled',
var_name = self.var_name(var)
n = make_node(var_id, var_name, style='filled',
fillcolor=self.node_colors['input'],
shape=var_shape, profile=aprof)
parent.add_node(n)
if not is_opfrom:
g.add_edge(pd.Edge(n.get_name(), aid, label=edge_label, **param))
elif not is_opfrom:
id_, name, prof = self.apply_name(var.owner, fct, topo, mode, profile)
g.add_edge(pd.Edge(id_, aid,
label=edge_label, **param))
graph.add_node(n)
graph.add_edge(pd.Edge(var_id, node_id, label=edge_label, **edge_params))
for id, var in enumerate(node.outputs):
varstr = self.var_name(var)
var_id = self.node_id(var)
var_name = self.var_name(var)
edge_label = str(var.type)
if var in outputs:
n = make_node(varstr, style='filled',
n = make_node(var_id, var_name, style='filled',
fillcolor=self.node_colors['output'],
shape=var_shape, profile=aprof)
g.add_node(n)
g.add_edge(pd.Edge(aid, n.get_name(), label=edge_label))
graph.add_node(n)
graph.add_edge(pd.Edge(node_id, var_id, label=edge_label))
elif len(var.clients) == 0:
n = make_node(varstr, style='filled',
n = make_node(var_id, var_name, style='filled',
fillcolor=self.node_colors['unused'],
shape=var_shape, profile=aprof)
g.add_node(n)
g.add_edge(pd.Edge(aid, n.get_name(), label=edge_label))
graph.add_node(n)
graph.add_edge(pd.Edge(node_id, var_id, label=edge_label))
elif var.name or not self.compact:
id_, name, prof = self.apply_name(var.owner, fct, topo, mode, profile)
g.add_edge(pd.Edge(aid, id_, label=edge_label))
return g
graph.add_edge(pd.Edge(node_id, var_id, label=edge_label))
if isinstance(node.op, builders.OpFromGraph):
subgraph = pd.Cluster(node_id)
gf = GraphFormatter()
gf.node_prefix = node_id
gf.to_pydot(node.op.fn, subgraph)
graph.add_subgraph(subgraph)
pd_node.get_attributes()['subg'] = subgraph.get_name()
def format_map(m):
return str([list(x) for x in m])
# Inputs mapping
ext_inputs = [self.node_id(x) for x in node.inputs]
int_inputs = [gf.node_id(x) for x in node.op.fn.maker.fgraph.inputs]
assert len(ext_inputs) == len(int_inputs)
h = format_map(zip(ext_inputs, int_inputs))
pd_node.get_attributes()['subg_map_inputs'] = h
# Outputs mapping
ext_outputs = []
for n in topo:
for i in n.inputs:
h = i.owner if i.owner else i
if h is node:
ext_outputs.append(self.node_id(n))
int_outputs = node.op.fn.maker.fgraph.outputs
int_outputs = [gf.node_id(x) for x in int_outputs]
assert len(ext_outputs) == len(int_outputs)
h = format_map(zip(int_outputs, ext_outputs))
pd_node.get_attributes()['subg_map_outputs'] = h
return graph
......@@ -272,6 +303,6 @@ class GraphFormatter(object):
suffix)
self.all_strings.add(applystr)
rv = (self.get_node_id(), applystr, prof)
rv = (applystr, prof)
self.apply_name_cache[node] = rv
return rv
......@@ -82,4 +82,9 @@ svg {
border: 1px solid black;
border-radius: 8px;
pointer-events: none;
}
\ No newline at end of file
}
path.hull {
fill: lightsteelblue;
fill-opacity: 0.3;
}
......@@ -13,54 +13,49 @@ function flipAxes(nodes) {
function processDotGraph(dotGraph) {
// Merge and remove subgraph nodes
dotGraph.rnodes = {};
for (var nodeId in dotGraph._nodes) {
if (!exists(dotGraph._nodes[nodeId])) {
continue;
}
if (nodeId.startsWith('cluster_')) {
var id = nodeId.replace('cluster_', '');
assert(exists(dotGraph._nodes[id]));
var parent = dotGraph.node(id);
var childIds = dotGraph.children(nodeId);
for (var i in childIds) {
var childId = childIds[i];
dotGraph.setParent(childId, id);
dotGraph.setEdge(childId, id, {'label': 'opfrom'});
var child = dotGraph.node(childId);
}
dotGraph.removeNode(nodeId);
var node = dotGraph._nodes[nodeId];
node.id = nodeId;
node.isCluster = nodeId.startsWith('cluster');
if (!node.isCluster) {
dotGraph.rnodes[nodeId] = node;
}
}
var i = 0;
for (var nodeId in dotGraph._nodes) {
for (var nodeId in dotGraph.rnodes) {
var node = dotGraph._nodes[nodeId];
node.id = nodeId;
node.pos = node.pos.split(',').map(function(d) {return parseInt(d);});
var size = textSize(node.label, {'class': 'nodeText'});
node.width = size.width + 2 * pad;
node.height = size.height + 2 * pad;
node.cx = node.width / 2;
node.cy = node.height / 2;
node.hasChilds = dotGraph.children(nodeId).length > 0;
node.hasChilds = exists(node.subg);
node.showChilds = false;
node.profile = parseProfile(node.profile);
if (node.profile.length) {
isProfiled = true;
}
if (exists(node.subg_map_inputs)) {
node.subg_map_inputs = eval(node.subg_map_inputs)
}
if (exists(node.subg_map_outputs)) {
node.subg_map_outputs = eval(node.subg_map_outputs)
}
}
flipAxes(dotGraph._nodes);
flipAxes(dotGraph.rnodes);
// Offset and scale positions
var posMin = [Infinity, Infinity];
for (var i in dotGraph._nodes) {
for (var i in dotGraph.rnodes) {
var node = dotGraph._nodes[i];
posMin[0] = Math.min(posMin[0], node.pos[0]);
posMin[1] = Math.min(posMin[1], node.pos[1]);
}
for (var i in dotGraph._nodes) {
for (var i in dotGraph.rnodes) {
var node = dotGraph._nodes[i];
var pos = node.pos;
pos[0] -= posMin[0];
......@@ -91,146 +86,214 @@ function processDotGraph(dotGraph) {
}
}
function makeNode(dotGraph, dotNode) {
var node = {};
node.value = dotNode;
node.fixed = true;
return node;
}
function traverseChilds(dotGraph, parent) {
var childs = dotGraph.children(parent);
var nodes = [];
function traverseChilds(dotGraph, nodes, groups, parent) {
var preId = '';
var ref = undefined;
var group = {'id': groups.length, 'nodes': [], 'parent': parent};
if (exists(parent)) {
ref = parent.value.subg;
group.parent = parent;
group.nodes.push(parent);
parent.group = group;
}
groups.push(group);
var childs = dotGraph.children(ref);
for (var i in childs) {
var child = dotGraph.node(childs[i]);
nodes.push(makeNode(dotGraph, child));
if (child.isCluster) {
continue;
}
var node = {
'id': child.id,
'value': child,
'index': nodes.length,
'fixed': true,
'group': group,
'isParent': child.showChilds,
'parent': parent
};
nodes.push(node);
if (child.showChilds) {
nodes = nodes.concat(traverseChilds(dotGraph, child.id));
traverseChilds(dotGraph, nodes, groups, node);
} else {
group.nodes.push(node);
}
}
return nodes;
}
function groupSize(nodes) {
var minPos = [Infinity, Infinity];
var maxPos = [-Infinity, -Infinity];
for (var i in nodes) {
var node = nodes[i];
if (node.isParent) {
continue;
}
minPos[0] = Math.min(minPos[0], node.value.pos[0]);
minPos[1] = Math.min(minPos[1], node.value.pos[1]);
maxPos[0] = Math.max(maxPos[0], node.value.pos[0] + node.value.width);
maxPos[1] = Math.max(maxPos[1], node.value.pos[1] + node.value.height);
}
return [maxPos[0] - minPos[0], maxPos[1] - minPos[1]];
}
function forceGraph(dotGraph, prevGraph) {
// Parse nodes
var graph = {};
graph.nodes = traverseChilds(dotGraph);
var graph = {'nodes': [], 'groups': []};
traverseChilds(dotGraph, graph.nodes, graph.groups);
graph.nodesd = {};
for (var i in graph.nodes) {
var node = graph.nodes[i];
node.index = i;
graph.nodesd[node.value.id] = node;
graph.nodesd[node.id] = node;
}
var groups = {};
for (var i in graph.nodes) {
var node = graph.nodes[i];
var parentId = dotGraph.parent(node.value.id);
if (exists(parentId)) {
if (!(parentId in groups)) {
groups[parentId] = [];
}
groups[parentId].push(node.value.id);
}
}
graph.nodesp = graph.nodes.filter(function(d) {return d.isParent;});
graph.nodesn = graph.nodes.filter(function(d) {return !d.isParent;});
// Compute group centroids
var groupsMeta = {};
for (var i in groups) {
var group = groups[i];
var cx = 0, cy = 0;
for (var j in group) {
var node = graph.nodesd[group[j]];
cx += node.value.pos[0];
cy += node.value.pos[1];
for (i in graph.groups) {
var group = graph.groups[i];
group.size = groupSize(group.nodes);
var parent = group.parent;
if (exists(parent)) {
var prevParent = prevGraph.nodesd[group.parent.id];
if (exists(prevParent)) {
group.pos = [prevParent.x, prevParent.y];
} else {
group.pos = parent.pos.slice(0);
}
group.pos[0] += parent.value.cx;
group.pos[1] += parent.value.cy;
} else {
group.pos = [group.size[0] / 2, group.size[1] / 2];
}
var n = groups[i].length;
cx /= n;
cy /= n;
groupsMeta[i] = {'cx': cx, 'cy': cy, 'n': n};
}
// Reuse previous positions
for (var i in graph.nodes) {
var node = graph.nodes[i];
var prevNode;
if (exists(prevGraph)) {
prevNode = prevGraph.nodesd[node.value.id];
var min = [Infinity, Infinity];
for (var j in group.nodes) {
var node = group.nodes[j];
if (!node.isParent) {
min[0] = Math.min(min[0], node.value.pos[0]);
min[1] = Math.min(min[0], node.value.pos[1]);
}
}
if (exists(prevNode)) {
node.x = prevNode.x;
node.y = prevNode.y;
node.fixed = prevNode.fixed;
} else {
var parentId = dotGraph.parent(node.value.id);
if (exists(parentId)) {
var parentPos;
var parent = prevGraph.nodesd[parentId];
if (exists(parent)) {
parentPos = [parent.x, parent.y];
} else {
parent = graph.nodesd[parentId];
parentPos = parent.value.pos;
}
var g = groupsMeta[parentId];
node.x = parentPos[0] + node.value.pos[0] - g.cx;
node.y = parentPos[1] - 100 + node.value.pos[1] - g.cy;
node.fixed = true;
for (var j in group.nodes) {
var node = group.nodes[j];
if (node.isParent) {
node.x = group.pos[0];
node.y = group.pos[1];
} else {
node.x = node.value.pos[0];
node.y = node.value.pos[1];
node.x = group.pos[0] - group.size[0] / 2 + node.value.pos[0] - min[0];
node.y = group.pos[1] - group.size[1] / 2 + node.value.pos[1] - min[1];
}
}
}
// Offset graph on initialization
if (!exists(prevGraph)) {
var posMin = [Infinity, Infinity];
for (var i in graph.nodes) {
var node = graph.nodes[i];
posMin[0] = Math.min(posMin[0], node.x);
posMin[1] = Math.min(posMin[1], node.y);
}
graph.size = graph.groups[0].size;
// Reuse previous positions
if (exists(prevGraph)) {
for (var i in graph.nodes) {
var node = graph.nodes[i];
node.x -= posMin[0];
node.y -= posMin[1];
var prevNode;
prevNode = prevGraph.nodesd[node.id];
if (exists(prevNode)) {
node.x = prevNode.x;
node.y = prevNode.y;
node.fixed = prevNode.fixed;
} else {
for (var j in prevGraph.groups) {
var group = prevGraph.groups[j];
if (exists(group.parent) && group.parent.id == node.id) {
node.x = group.pos[0] + group.size[0] / 2;
node.y = group.pos[1] + group.size[1] / 2;
}
}
}
}
}
// Compute dimension of graph
var minPos = [Infinity, Infinity];
var maxPos = [-Infinity, -Infinity];
for (var i in graph.nodes) {
var node = graph.nodes[i];
minPos[0] = Math.min(minPos[0], node.x);
minPos[1] = Math.min(minPos[1], node.y);
maxPos[0] = Math.max(maxPos[0], node.x + node.value.width);
maxPos[1] = Math.max(maxPos[1], node.y + node.value.height);
}
graph.dim = {'minPos': minPos, 'maxPos': maxPos,
'size': [maxPos[0] - minPos[0], maxPos[1] - minPos[0]]};
// Edges
graph.edges = [];
for (var i in graph.nodes) {
for (var j in graph.nodes) {
var sourceId = graph.nodes[i].value.id;
var targetId = graph.nodes[j].value.id;
var dotEdge = dotGraph.edge(sourceId, targetId);
for (var i in graph.nodesn) {
for (var j in graph.nodesn) {
var source = graph.nodesn[i];
var target = graph.nodesn[j];
var dotEdge = dotGraph.edge(source.value.id, target.value.id);
if (exists(dotEdge)) {
var edge = {};
edge.source = parseInt(graph.nodes[i].index);
edge.target = parseInt(graph.nodes[j].index);
edge.source = parseInt(source.index);
edge.target = parseInt(target.index);
edge.value = dotEdge;
graph.edges.push(edge);
}
function redirectEdges(map, dotEdge) {
for (var k in map) {
var kmap = map[k];
if (kmap[0] == source.id && kmap[1] == target.id) {
var edge = {};
edge.source = parseInt(source.index);
edge.target = parseInt(target.index);
edge.value = dotEdge;
graph.edges.push(edge);
}
}
}
var map = undefined;
if (exists(target.parent)) {
var parent = target.parent;
var dotEdge = dotGraph.edge(source.id, parent.id);
if (exists(dotEdge)) {
map = parent.value.subg_map_inputs;
redirectEdges(map, dotEdge);
}
}
if (exists(source.parent)) {
var parent = source.parent;
var dotEdge = dotGraph.edge(parent.id, target.id);
if (exists(dotEdge)) {
map = parent.value.subg_map_outputs;
redirectEdges(map, dotEdge);
}
}
}
}
return graph;
}
function convexHulls(graph, offset) {
var hulls = [];
offset = offset || 20;
for (var i in graph.groups) {
var group = graph.groups[i];
if (!exists(group.parent)) {
continue;
}
var points = [];
for (var j in group.nodes) {
var node = group.nodes[j];
if (node.isParent) {
points.push([node.x, node.y]);
} else {
points.push([node.x - node.value.cx - offset, node.y - node.value.cy - offset]);
points.push([node.x - node.value.cx - offset, node.y + node.value.cy + offset]);
points.push([node.x + node.value.cx + offset, node.y - node.value.cy - offset]);
points.push([node.x + node.value.cx + offset, node.y + node.value.cy + offset]);
}
}
hulls.push({group: i, path: d3.geom.hull(points)});
}
return hulls;
}
function drawCluster(d) {
return curve(d.path); // 0.8
}
function setupGraph() {
if (isProfiled) {
d3.select('body').select('#menu').append('input')
......@@ -251,6 +314,23 @@ function setupGraph() {
var isEdgeOver = false;
var isEdgeLabelOver = false;
graph.hulls = convexHulls(graph);
hulls = pane.selectAll('#hulls').remove();
hulls = pane.append('g').attr('id', 'hulls')
.selectAll('path')
.data(graph.hulls).enter()
.append('path')
.attr('class', 'hull')
.attr('d', drawCluster);
hulls.on('dblclick', function(d) {
var parent = graph.groups[d.group].parent;
parent.value.showChilds = !parent.value.showChilds;
graph = forceGraph(dotGraph, graph);
setupGraph();
});
// Add edges
edges = pane.selectAll('#edges').remove();
edges = pane.append('g').attr('id', 'edges')
......@@ -287,7 +367,7 @@ function setupGraph() {
// Add nodes
pane.selectAll('#nodes').remove();
nodes = pane.append('g').attr('id', 'nodes')
.selectAll('g').data(graph.nodes).enter().append('g');
.selectAll('g').data(graph.nodesn).enter().append('g');
updateNodes();
updateGraph();
......@@ -341,9 +421,9 @@ function setupGraph() {
layout = d3.layout.force()
.nodes(graph.nodes)
.links(graph.edges)
.size(graph.dim.size)
.size(graph.size)
.charge(-300)
.linkDistance(300)
.linkDistance(400)
.linkStrength(0.4)
.gravity(0)
.on('tick', updateGraph);
......@@ -373,6 +453,10 @@ function pathPos(x1, y1, x2, y2, c) {
}
function updateGraph() {
graph.hulls = convexHulls(graph);
hulls.data(graph.hulls)
.attr('d', drawCluster);
// Update nodes
nodes.attr('transform', function(d) { return 'translate(' + (d.x - d.value.cx) + ' ' + (d.y - d.value.cy) + ')'; });
// Update edges
......
......@@ -22,7 +22,7 @@
</div>
<script type="text/javascript">
var path = '%% DOT_FILE %%'
var path = '%% DOT_FILE %%';
var dotGraph;
var graph = {};
var nodes = [];
......@@ -85,13 +85,6 @@
.attr("d", "M0,0 L4,2 L0,4 Z")
.attr('fill', function(d) { return d.color;});
d3.text(path, function(data) {
dotGraph = graphlibDot.read(data);
processDotGraph(dotGraph);
graph = forceGraph(dotGraph);
setupGraph();
});
// Zoom behaviour
function zoom(d) {
var trans = d3.event.translate;
......@@ -107,6 +100,18 @@
bZoom.event(svg);
svg.on("dblclick.zoom", null);
var curve = d3.svg.line()
.interpolate("cardinal-closed")
.tension(.85);
// Read and initialize graph
d3.text(path, function(data) {
dotGraph = graphlibDot.read(data);
processDotGraph(dotGraph);
graph = forceGraph(dotGraph);
setupGraph();
});
</script>
</body>
</html>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论