browser/devtools/webaudioeditor/lib/dagre-d3.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 ;(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
     2 var global=self;/**
     3  * @license
     4  * Copyright (c) 2012-2013 Chris Pettitt
     5  *
     6  * Permission is hereby granted, free of charge, to any person obtaining a copy
     7  * of this software and associated documentation files (the "Software"), to deal
     8  * in the Software without restriction, including without limitation the rights
     9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    10  * copies of the Software, and to permit persons to whom the Software is
    11  * furnished to do so, subject to the following conditions:
    12  *
    13  * The above copyright notice and this permission notice shall be included in
    14  * all copies or substantial portions of the Software.
    15  *
    16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    22  * THE SOFTWARE.
    23  */
    24 global.dagreD3 = require('./index');
    26 },{"./index":2}],2:[function(require,module,exports){
    27 /**
    28  * @license
    29  * Copyright (c) 2012-2013 Chris Pettitt
    30  *
    31  * Permission is hereby granted, free of charge, to any person obtaining a copy
    32  * of this software and associated documentation files (the "Software"), to deal
    33  * in the Software without restriction, including without limitation the rights
    34  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    35  * copies of the Software, and to permit persons to whom the Software is
    36  * furnished to do so, subject to the following conditions:
    37  *
    38  * The above copyright notice and this permission notice shall be included in
    39  * all copies or substantial portions of the Software.
    40  *
    41  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    42  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    43  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    44  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    45  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    46  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    47  * THE SOFTWARE.
    48  */
    49 module.exports =  {
    50   Digraph: require('graphlib').Digraph,
    51   Renderer: require('./lib/Renderer'),
    52   json: require('graphlib').converter.json,
    53   layout: require('dagre').layout,
    54   version: require('./lib/version')
    55 };
    57 },{"./lib/Renderer":3,"./lib/version":4,"dagre":11,"graphlib":28}],3:[function(require,module,exports){
    58 var layout = require('dagre').layout;
    60 var d3;
    61 try { d3 = require('d3'); } catch (_) { d3 = window.d3; }
    63 module.exports = Renderer;
    65 function Renderer() {
    66   // Set up defaults...
    67   this._layout = layout();
    69   this.drawNodes(defaultDrawNodes);
    70   this.drawEdgeLabels(defaultDrawEdgeLabels);
    71   this.drawEdgePaths(defaultDrawEdgePaths);
    72   this.positionNodes(defaultPositionNodes);
    73   this.positionEdgeLabels(defaultPositionEdgeLabels);
    74   this.positionEdgePaths(defaultPositionEdgePaths);
    75   this.transition(defaultTransition);
    76   this.postLayout(defaultPostLayout);
    77   this.postRender(defaultPostRender);
    79   this.edgeInterpolate('bundle');
    80   this.edgeTension(0.95);
    81 }
    83 Renderer.prototype.layout = function(layout) {
    84   if (!arguments.length) { return this._layout; }
    85   this._layout = layout;
    86   return this;
    87 };
    89 Renderer.prototype.drawNodes = function(drawNodes) {
    90   if (!arguments.length) { return this._drawNodes; }
    91   this._drawNodes = bind(drawNodes, this);
    92   return this;
    93 };
    95 Renderer.prototype.drawEdgeLabels = function(drawEdgeLabels) {
    96   if (!arguments.length) { return this._drawEdgeLabels; }
    97   this._drawEdgeLabels = bind(drawEdgeLabels, this);
    98   return this;
    99 };
   101 Renderer.prototype.drawEdgePaths = function(drawEdgePaths) {
   102   if (!arguments.length) { return this._drawEdgePaths; }
   103   this._drawEdgePaths = bind(drawEdgePaths, this);
   104   return this;
   105 };
   107 Renderer.prototype.positionNodes = function(positionNodes) {
   108   if (!arguments.length) { return this._positionNodes; }
   109   this._positionNodes = bind(positionNodes, this);
   110   return this;
   111 };
   113 Renderer.prototype.positionEdgeLabels = function(positionEdgeLabels) {
   114   if (!arguments.length) { return this._positionEdgeLabels; }
   115   this._positionEdgeLabels = bind(positionEdgeLabels, this);
   116   return this;
   117 };
   119 Renderer.prototype.positionEdgePaths = function(positionEdgePaths) {
   120   if (!arguments.length) { return this._positionEdgePaths; }
   121   this._positionEdgePaths = bind(positionEdgePaths, this);
   122   return this;
   123 };
   125 Renderer.prototype.transition = function(transition) {
   126   if (!arguments.length) { return this._transition; }
   127   this._transition = bind(transition, this);
   128   return this;
   129 };
   131 Renderer.prototype.postLayout = function(postLayout) {
   132   if (!arguments.length) { return this._postLayout; }
   133   this._postLayout = bind(postLayout, this);
   134   return this;
   135 };
   137 Renderer.prototype.postRender = function(postRender) {
   138   if (!arguments.length) { return this._postRender; }
   139   this._postRender = bind(postRender, this);
   140   return this;
   141 };
   143 Renderer.prototype.edgeInterpolate = function(edgeInterpolate) {
   144   if (!arguments.length) { return this._edgeInterpolate; }
   145   this._edgeInterpolate = edgeInterpolate;
   146   return this;
   147 };
   149 Renderer.prototype.edgeTension = function(edgeTension) {
   150   if (!arguments.length) { return this._edgeTension; }
   151   this._edgeTension = edgeTension;
   152   return this;
   153 };
   155 Renderer.prototype.run = function(graph, svg) {
   156   // First copy the input graph so that it is not changed by the rendering
   157   // process.
   158   graph = copyAndInitGraph(graph);
   160   // Create layers
   161   svg
   162     .selectAll('g.edgePaths, g.edgeLabels, g.nodes')
   163     .data(['edgePaths', 'edgeLabels', 'nodes'])
   164     .enter()
   165       .append('g')
   166       .attr('class', function(d) { return d; });
   169   // Create node and edge roots, attach labels, and capture dimension
   170   // information for use with layout.
   171   var svgNodes = this._drawNodes(graph, svg.select('g.nodes'));
   172   var svgEdgeLabels = this._drawEdgeLabels(graph, svg.select('g.edgeLabels'));
   174   svgNodes.each(function(u) { calculateDimensions(this, graph.node(u)); });
   175   svgEdgeLabels.each(function(e) { calculateDimensions(this, graph.edge(e)); });
   177   // Now apply the layout function
   178   var result = runLayout(graph, this._layout);
   180   // Run any user-specified post layout processing
   181   this._postLayout(result, svg);
   183   var svgEdgePaths = this._drawEdgePaths(graph, svg.select('g.edgePaths'));
   185   // Apply the layout information to the graph
   186   this._positionNodes(result, svgNodes);
   187   this._positionEdgeLabels(result, svgEdgeLabels);
   188   this._positionEdgePaths(result, svgEdgePaths);
   190   this._postRender(result, svg);
   192   return result;
   193 };
   195 function copyAndInitGraph(graph) {
   196   var copy = graph.copy();
   198   // Init labels if they were not present in the source graph
   199   copy.nodes().forEach(function(u) {
   200     var value = copy.node(u);
   201     if (value === undefined) {
   202       value = {};
   203       copy.node(u, value);
   204     }
   205     if (!('label' in value)) { value.label = ''; }
   206   });
   208   copy.edges().forEach(function(e) {
   209     var value = copy.edge(e);
   210     if (value === undefined) {
   211       value = {};
   212       copy.edge(e, value);
   213     }
   214     if (!('label' in value)) { value.label = ''; }
   215   });
   217   return copy;
   218 }
   220 function calculateDimensions(group, value) {
   221   var bbox = group.getBBox();
   222   value.width = bbox.width;
   223   value.height = bbox.height;
   224 }
   226 function runLayout(graph, layout) {
   227   var result = layout.run(graph);
   229   // Copy labels to the result graph
   230   graph.eachNode(function(u, value) { result.node(u).label = value.label; });
   231   graph.eachEdge(function(e, u, v, value) { result.edge(e).label = value.label; });
   233   return result;
   234 }
   236 function defaultDrawNodes(g, root) {
   237   var nodes = g.nodes().filter(function(u) { return !isComposite(g, u); });
   239   var svgNodes = root
   240     .selectAll('g.node')
   241     .classed('enter', false)
   242     .data(nodes, function(u) { return u; });
   244   svgNodes.selectAll('*').remove();
   246   svgNodes
   247     .enter()
   248       .append('g')
   249         .style('opacity', 0)
   250         .attr('class', 'node enter');
   252   svgNodes.each(function(u) { addLabel(g.node(u), d3.select(this), 10, 10); });
   254   this._transition(svgNodes.exit())
   255       .style('opacity', 0)
   256       .remove();
   258   return svgNodes;
   259 }
   261 function defaultDrawEdgeLabels(g, root) {
   262   var svgEdgeLabels = root
   263     .selectAll('g.edgeLabel')
   264     .classed('enter', false)
   265     .data(g.edges(), function (e) { return e; });
   267   svgEdgeLabels.selectAll('*').remove();
   269   svgEdgeLabels
   270     .enter()
   271       .append('g')
   272         .style('opacity', 0)
   273         .attr('class', 'edgeLabel enter');
   275   svgEdgeLabels.each(function(e) { addLabel(g.edge(e), d3.select(this), 0, 0); });
   277   this._transition(svgEdgeLabels.exit())
   278       .style('opacity', 0)
   279       .remove();
   281   return svgEdgeLabels;
   282 }
   284 var defaultDrawEdgePaths = function(g, root) {
   285   var svgEdgePaths = root
   286     .selectAll('g.edgePath')
   287     .classed('enter', false)
   288     .data(g.edges(), function(e) { return e; });
   290   svgEdgePaths
   291     .enter()
   292       .append('g')
   293         .attr('class', 'edgePath enter')
   294         .append('path')
   295           .style('opacity', 0)
   296           .attr('marker-end', 'url(#arrowhead)');
   298   this._transition(svgEdgePaths.exit())
   299       .style('opacity', 0)
   300       .remove();
   302   return svgEdgePaths;
   303 };
   305 function defaultPositionNodes(g, svgNodes, svgNodesEnter) {
   306   function transform(u) {
   307     var value = g.node(u);
   308     return 'translate(' + value.x + ',' + value.y + ')';
   309   }
   311   // For entering nodes, position immediately without transition
   312   svgNodes.filter('.enter').attr('transform', transform);
   314   this._transition(svgNodes)
   315       .style('opacity', 1)
   316       .attr('transform', transform);
   317 }
   319 function defaultPositionEdgeLabels(g, svgEdgeLabels) {
   320   function transform(e) {
   321     var value = g.edge(e);
   322     var point = findMidPoint(value.points);
   323     return 'translate(' + point.x + ',' + point.y + ')';
   324   }
   326   // For entering edge labels, position immediately without transition
   327   svgEdgeLabels.filter('.enter').attr('transform', transform);
   329   this._transition(svgEdgeLabels)
   330     .style('opacity', 1)
   331     .attr('transform', transform);
   332 }
   334 function defaultPositionEdgePaths(g, svgEdgePaths) {
   335   var interpolate = this._edgeInterpolate,
   336       tension = this._edgeTension;
   338   function calcPoints(e) {
   339     var value = g.edge(e);
   340     var source = g.node(g.incidentNodes(e)[0]);
   341     var target = g.node(g.incidentNodes(e)[1]);
   342     var points = value.points.slice();
   344     var p0 = points.length === 0 ? target : points[0];
   345     var p1 = points.length === 0 ? source : points[points.length - 1];
   347     points.unshift(intersectRect(source, p0));
   348     // TODO: use bpodgursky's shortening algorithm here
   349     points.push(intersectRect(target, p1));
   351     return d3.svg.line()
   352       .x(function(d) { return d.x; })
   353       .y(function(d) { return d.y; })
   354       .interpolate(interpolate)
   355       .tension(tension)
   356       (points);
   357   }
   359   svgEdgePaths.filter('.enter').selectAll('path')
   360       .attr('d', calcPoints);
   362   this._transition(svgEdgePaths.selectAll('path'))
   363       .attr('d', calcPoints)
   364       .style('opacity', 1);
   365 }
   367 // By default we do not use transitions
   368 function defaultTransition(selection) {
   369   return selection;
   370 }
   372 function defaultPostLayout() {
   373   // Do nothing
   374 }
   376 function defaultPostRender(graph, root) {
   377   if (graph.isDirected() && root.select('#arrowhead').empty()) {
   378     root
   379       .append('svg:defs')
   380         .append('svg:marker')
   381           .attr('id', 'arrowhead')
   382           .attr('viewBox', '0 0 10 10')
   383           .attr('refX', 8)
   384           .attr('refY', 5)
   385           .attr('markerUnits', 'strokewidth')
   386           .attr('markerWidth', 8)
   387           .attr('markerHeight', 5)
   388           .attr('orient', 'auto')
   389           .attr('style', 'fill: #333')
   390           .append('svg:path')
   391             .attr('d', 'M 0 0 L 10 5 L 0 10 z');
   392   }
   393 }
   395 function addLabel(node, root, marginX, marginY) {
   396   // Add the rect first so that it appears behind the label
   397   var label = node.label;
   398   var rect = root.append('rect');
   399   var labelSvg = root.append('g');
   401   if (label[0] === '<') {
   402     addForeignObjectLabel(label, labelSvg);
   403     // No margin for HTML elements
   404     marginX = marginY = 0;
   405   } else {
   406     addTextLabel(label,
   407                  labelSvg,
   408                  Math.floor(node.labelCols),
   409                  node.labelCut);
   410   }
   412   var bbox = root.node().getBBox();
   414   labelSvg.attr('transform',
   415              'translate(' + (-bbox.width / 2) + ',' + (-bbox.height / 2) + ')');
   417   rect
   418     .attr('rx', 5)
   419     .attr('ry', 5)
   420     .attr('x', -(bbox.width / 2 + marginX))
   421     .attr('y', -(bbox.height / 2 + marginY))
   422     .attr('width', bbox.width + 2 * marginX)
   423     .attr('height', bbox.height + 2 * marginY);
   424 }
   426 function addForeignObjectLabel(label, root) {
   427   var fo = root
   428     .append('foreignObject')
   429       .attr('width', '100000');
   431   var w, h;
   432   fo
   433     .append('xhtml:div')
   434       .style('float', 'left')
   435       // TODO find a better way to get dimensions for foreignObjects...
   436       .html(function() { return label; })
   437       .each(function() {
   438         w = this.clientWidth;
   439         h = this.clientHeight;
   440       });
   442   fo
   443     .attr('width', w)
   444     .attr('height', h);
   445 }
   447 function addTextLabel(label, root, labelCols, labelCut) {
   448   if (labelCut === undefined) labelCut = "false";
   449   labelCut = (labelCut.toString().toLowerCase() === "true");
   451   var node = root
   452     .append('text')
   453     .attr('text-anchor', 'left');
   455   label = label.replace(/\\n/g, "\n");
   457   var arr = labelCols ? wordwrap(label, labelCols, labelCut) : label;
   458   arr = arr.split("\n");
   459   for (var i = 0; i < arr.length; i++) {
   460     node
   461       .append('tspan')
   462         .attr('dy', '1em')
   463         .attr('x', '1')
   464         .text(arr[i]);
   465   }
   466 }
   468 // Thanks to
   469 // http://james.padolsey.com/javascript/wordwrap-for-javascript/
   470 function wordwrap (str, width, cut, brk) {
   471      brk = brk || '\n';
   472      width = width || 75;
   473      cut = cut || false;
   475      if (!str) { return str; }
   477      var regex = '.{1,' +width+ '}(\\s|$)' + (cut ? '|.{' +width+ '}|.+$' : '|\\S+?(\\s|$)');
   479      return str.match( RegExp(regex, 'g') ).join( brk );
   480 }
   482 function findMidPoint(points) {
   483   var midIdx = points.length / 2;
   484   if (points.length % 2) {
   485     return points[Math.floor(midIdx)];
   486   } else {
   487     var p0 = points[midIdx - 1];
   488     var p1 = points[midIdx];
   489     return {x: (p0.x + p1.x) / 2, y: (p0.y + p1.y) / 2};
   490   }
   491 }
   493 function intersectRect(rect, point) {
   494   var x = rect.x;
   495   var y = rect.y;
   497   // For now we only support rectangles
   499   // Rectangle intersection algorithm from:
   500   // http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
   501   var dx = point.x - x;
   502   var dy = point.y - y;
   503   var w = rect.width / 2;
   504   var h = rect.height / 2;
   506   var sx, sy;
   507   if (Math.abs(dy) * w > Math.abs(dx) * h) {
   508     // Intersection is top or bottom of rect.
   509     if (dy < 0) {
   510       h = -h;
   511     }
   512     sx = dy === 0 ? 0 : h * dx / dy;
   513     sy = h;
   514   } else {
   515     // Intersection is left or right of rect.
   516     if (dx < 0) {
   517       w = -w;
   518     }
   519     sx = w;
   520     sy = dx === 0 ? 0 : w * dy / dx;
   521   }
   523   return {x: x + sx, y: y + sy};
   524 }
   526 function isComposite(g, u) {
   527   return 'children' in g && g.children(u).length;
   528 }
   530 function bind(func, thisArg) {
   531   // For some reason PhantomJS occassionally fails when using the builtin bind,
   532   // so we check if it is available and if not, use a degenerate polyfill.
   533   if (func.bind) {
   534     return func.bind(thisArg);
   535   }
   537   return function() {
   538     return func.apply(thisArg, arguments);
   539   };
   540 }
   542 },{"d3":10,"dagre":11}],4:[function(require,module,exports){
   543 module.exports = '0.1.5';
   545 },{}],5:[function(require,module,exports){
   546 exports.Set = require('./lib/Set');
   547 exports.PriorityQueue = require('./lib/PriorityQueue');
   548 exports.version = require('./lib/version');
   550 },{"./lib/PriorityQueue":6,"./lib/Set":7,"./lib/version":9}],6:[function(require,module,exports){
   551 module.exports = PriorityQueue;
   553 /**
   554  * A min-priority queue data structure. This algorithm is derived from Cormen,
   555  * et al., "Introduction to Algorithms". The basic idea of a min-priority
   556  * queue is that you can efficiently (in O(1) time) get the smallest key in
   557  * the queue. Adding and removing elements takes O(log n) time. A key can
   558  * have its priority decreased in O(log n) time.
   559  */
   560 function PriorityQueue() {
   561   this._arr = [];
   562   this._keyIndices = {};
   563 }
   565 /**
   566  * Returns the number of elements in the queue. Takes `O(1)` time.
   567  */
   568 PriorityQueue.prototype.size = function() {
   569   return this._arr.length;
   570 };
   572 /**
   573  * Returns the keys that are in the queue. Takes `O(n)` time.
   574  */
   575 PriorityQueue.prototype.keys = function() {
   576   return this._arr.map(function(x) { return x.key; });
   577 };
   579 /**
   580  * Returns `true` if **key** is in the queue and `false` if not.
   581  */
   582 PriorityQueue.prototype.has = function(key) {
   583   return key in this._keyIndices;
   584 };
   586 /**
   587  * Returns the priority for **key**. If **key** is not present in the queue
   588  * then this function returns `undefined`. Takes `O(1)` time.
   589  *
   590  * @param {Object} key
   591  */
   592 PriorityQueue.prototype.priority = function(key) {
   593   var index = this._keyIndices[key];
   594   if (index !== undefined) {
   595     return this._arr[index].priority;
   596   }
   597 };
   599 /**
   600  * Returns the key for the minimum element in this queue. If the queue is
   601  * empty this function throws an Error. Takes `O(1)` time.
   602  */
   603 PriorityQueue.prototype.min = function() {
   604   if (this.size() === 0) {
   605     throw new Error("Queue underflow");
   606   }
   607   return this._arr[0].key;
   608 };
   610 /**
   611  * Inserts a new key into the priority queue. If the key already exists in
   612  * the queue this function returns `false`; otherwise it will return `true`.
   613  * Takes `O(n)` time.
   614  *
   615  * @param {Object} key the key to add
   616  * @param {Number} priority the initial priority for the key
   617  */
   618 PriorityQueue.prototype.add = function(key, priority) {
   619   var keyIndices = this._keyIndices;
   620   if (!(key in keyIndices)) {
   621     var arr = this._arr;
   622     var index = arr.length;
   623     keyIndices[key] = index;
   624     arr.push({key: key, priority: priority});
   625     this._decrease(index);
   626     return true;
   627   }
   628   return false;
   629 };
   631 /**
   632  * Removes and returns the smallest key in the queue. Takes `O(log n)` time.
   633  */
   634 PriorityQueue.prototype.removeMin = function() {
   635   this._swap(0, this._arr.length - 1);
   636   var min = this._arr.pop();
   637   delete this._keyIndices[min.key];
   638   this._heapify(0);
   639   return min.key;
   640 };
   642 /**
   643  * Decreases the priority for **key** to **priority**. If the new priority is
   644  * greater than the previous priority, this function will throw an Error.
   645  *
   646  * @param {Object} key the key for which to raise priority
   647  * @param {Number} priority the new priority for the key
   648  */
   649 PriorityQueue.prototype.decrease = function(key, priority) {
   650   var index = this._keyIndices[key];
   651   if (priority > this._arr[index].priority) {
   652     throw new Error("New priority is greater than current priority. " +
   653         "Key: " + key + " Old: " + this._arr[index].priority + " New: " + priority);
   654   }
   655   this._arr[index].priority = priority;
   656   this._decrease(index);
   657 };
   659 PriorityQueue.prototype._heapify = function(i) {
   660   var arr = this._arr;
   661   var l = 2 * i,
   662       r = l + 1,
   663       largest = i;
   664   if (l < arr.length) {
   665     largest = arr[l].priority < arr[largest].priority ? l : largest;
   666     if (r < arr.length) {
   667       largest = arr[r].priority < arr[largest].priority ? r : largest;
   668     }
   669     if (largest !== i) {
   670       this._swap(i, largest);
   671       this._heapify(largest);
   672     }
   673   }
   674 };
   676 PriorityQueue.prototype._decrease = function(index) {
   677   var arr = this._arr;
   678   var priority = arr[index].priority;
   679   var parent;
   680   while (index !== 0) {
   681     parent = index >> 1;
   682     if (arr[parent].priority < priority) {
   683       break;
   684     }
   685     this._swap(index, parent);
   686     index = parent;
   687   }
   688 };
   690 PriorityQueue.prototype._swap = function(i, j) {
   691   var arr = this._arr;
   692   var keyIndices = this._keyIndices;
   693   var origArrI = arr[i];
   694   var origArrJ = arr[j];
   695   arr[i] = origArrJ;
   696   arr[j] = origArrI;
   697   keyIndices[origArrJ.key] = i;
   698   keyIndices[origArrI.key] = j;
   699 };
   701 },{}],7:[function(require,module,exports){
   702 var util = require('./util');
   704 module.exports = Set;
   706 /**
   707  * Constructs a new Set with an optional set of `initialKeys`.
   708  *
   709  * It is important to note that keys are coerced to String for most purposes
   710  * with this object, similar to the behavior of JavaScript's Object. For
   711  * example, the following will add only one key:
   712  *
   713  *     var s = new Set();
   714  *     s.add(1);
   715  *     s.add("1");
   716  *
   717  * However, the type of the key is preserved internally so that `keys` returns
   718  * the original key set uncoerced. For the above example, `keys` would return
   719  * `[1]`.
   720  */
   721 function Set(initialKeys) {
   722   this._size = 0;
   723   this._keys = {};
   725   if (initialKeys) {
   726     for (var i = 0, il = initialKeys.length; i < il; ++i) {
   727       this.add(initialKeys[i]);
   728     }
   729   }
   730 }
   732 /**
   733  * Returns a new Set that represents the set intersection of the array of given
   734  * sets.
   735  */
   736 Set.intersect = function(sets) {
   737   if (sets.length === 0) {
   738     return new Set();
   739   }
   741   var result = new Set(!util.isArray(sets[0]) ? sets[0].keys() : sets[0]);
   742   for (var i = 1, il = sets.length; i < il; ++i) {
   743     var resultKeys = result.keys(),
   744         other = !util.isArray(sets[i]) ? sets[i] : new Set(sets[i]);
   745     for (var j = 0, jl = resultKeys.length; j < jl; ++j) {
   746       var key = resultKeys[j];
   747       if (!other.has(key)) {
   748         result.remove(key);
   749       }
   750     }
   751   }
   753   return result;
   754 };
   756 /**
   757  * Returns a new Set that represents the set union of the array of given sets.
   758  */
   759 Set.union = function(sets) {
   760   var totalElems = util.reduce(sets, function(lhs, rhs) {
   761     return lhs + (rhs.size ? rhs.size() : rhs.length);
   762   }, 0);
   763   var arr = new Array(totalElems);
   765   var k = 0;
   766   for (var i = 0, il = sets.length; i < il; ++i) {
   767     var cur = sets[i],
   768         keys = !util.isArray(cur) ? cur.keys() : cur;
   769     for (var j = 0, jl = keys.length; j < jl; ++j) {
   770       arr[k++] = keys[j];
   771     }
   772   }
   774   return new Set(arr);
   775 };
   777 /**
   778  * Returns the size of this set in `O(1)` time.
   779  */
   780 Set.prototype.size = function() {
   781   return this._size;
   782 };
   784 /**
   785  * Returns the keys in this set. Takes `O(n)` time.
   786  */
   787 Set.prototype.keys = function() {
   788   return values(this._keys);
   789 };
   791 /**
   792  * Tests if a key is present in this Set. Returns `true` if it is and `false`
   793  * if not. Takes `O(1)` time.
   794  */
   795 Set.prototype.has = function(key) {
   796   return key in this._keys;
   797 };
   799 /**
   800  * Adds a new key to this Set if it is not already present. Returns `true` if
   801  * the key was added and `false` if it was already present. Takes `O(1)` time.
   802  */
   803 Set.prototype.add = function(key) {
   804   if (!(key in this._keys)) {
   805     this._keys[key] = key;
   806     ++this._size;
   807     return true;
   808   }
   809   return false;
   810 };
   812 /**
   813  * Removes a key from this Set. If the key was removed this function returns
   814  * `true`. If not, it returns `false`. Takes `O(1)` time.
   815  */
   816 Set.prototype.remove = function(key) {
   817   if (key in this._keys) {
   818     delete this._keys[key];
   819     --this._size;
   820     return true;
   821   }
   822   return false;
   823 };
   825 /*
   826  * Returns an array of all values for properties of **o**.
   827  */
   828 function values(o) {
   829   var ks = Object.keys(o),
   830       len = ks.length,
   831       result = new Array(len),
   832       i;
   833   for (i = 0; i < len; ++i) {
   834     result[i] = o[ks[i]];
   835   }
   836   return result;
   837 }
   839 },{"./util":8}],8:[function(require,module,exports){
   840 /*
   841  * This polyfill comes from
   842  * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
   843  */
   844 if(!Array.isArray) {
   845   exports.isArray = function (vArg) {
   846     return Object.prototype.toString.call(vArg) === '[object Array]';
   847   };
   848 } else {
   849   exports.isArray = Array.isArray;
   850 }
   852 /*
   853  * Slightly adapted polyfill from
   854  * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
   855  */
   856 if ('function' !== typeof Array.prototype.reduce) {
   857   exports.reduce = function(array, callback, opt_initialValue) {
   858     'use strict';
   859     if (null === array || 'undefined' === typeof array) {
   860       // At the moment all modern browsers, that support strict mode, have
   861       // native implementation of Array.prototype.reduce. For instance, IE8
   862       // does not support strict mode, so this check is actually useless.
   863       throw new TypeError(
   864           'Array.prototype.reduce called on null or undefined');
   865     }
   866     if ('function' !== typeof callback) {
   867       throw new TypeError(callback + ' is not a function');
   868     }
   869     var index, value,
   870         length = array.length >>> 0,
   871         isValueSet = false;
   872     if (1 < arguments.length) {
   873       value = opt_initialValue;
   874       isValueSet = true;
   875     }
   876     for (index = 0; length > index; ++index) {
   877       if (array.hasOwnProperty(index)) {
   878         if (isValueSet) {
   879           value = callback(value, array[index], index, array);
   880         }
   881         else {
   882           value = array[index];
   883           isValueSet = true;
   884         }
   885       }
   886     }
   887     if (!isValueSet) {
   888       throw new TypeError('Reduce of empty array with no initial value');
   889     }
   890     return value;
   891   };
   892 } else {
   893   exports.reduce = function(array, callback, opt_initialValue) {
   894     return array.reduce(callback, opt_initialValue);
   895   };
   896 }
   898 },{}],9:[function(require,module,exports){
   899 module.exports = '1.1.3';
   901 },{}],10:[function(require,module,exports){
   902 require("./d3");
   903 module.exports = d3;
   904 (function () { delete this.d3; })(); // unset global
   906 },{}],11:[function(require,module,exports){
   907 /*
   908 Copyright (c) 2012-2013 Chris Pettitt
   910 Permission is hereby granted, free of charge, to any person obtaining a copy
   911 of this software and associated documentation files (the "Software"), to deal
   912 in the Software without restriction, including without limitation the rights
   913 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   914 copies of the Software, and to permit persons to whom the Software is
   915 furnished to do so, subject to the following conditions:
   917 The above copyright notice and this permission notice shall be included in
   918 all copies or substantial portions of the Software.
   920 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   921 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   922 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   923 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   924 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   925 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   926 THE SOFTWARE.
   927 */
   928 exports.Digraph = require("graphlib").Digraph;
   929 exports.Graph = require("graphlib").Graph;
   930 exports.layout = require("./lib/layout");
   931 exports.version = require("./lib/version");
   933 },{"./lib/layout":12,"./lib/version":27,"graphlib":28}],12:[function(require,module,exports){
   934 var util = require('./util'),
   935     rank = require('./rank'),
   936     order = require('./order'),
   937     CGraph = require('graphlib').CGraph,
   938     CDigraph = require('graphlib').CDigraph;
   940 module.exports = function() {
   941   // External configuration
   942   var config = {
   943     // How much debug information to include?
   944     debugLevel: 0,
   945     // Max number of sweeps to perform in order phase
   946     orderMaxSweeps: order.DEFAULT_MAX_SWEEPS,
   947     // Use network simplex algorithm in ranking
   948     rankSimplex: false,
   949     // Rank direction. Valid values are (TB, LR)
   950     rankDir: 'TB'
   951   };
   953   // Phase functions
   954   var position = require('./position')();
   956   // This layout object
   957   var self = {};
   959   self.orderIters = util.propertyAccessor(self, config, 'orderMaxSweeps');
   961   self.rankSimplex = util.propertyAccessor(self, config, 'rankSimplex');
   963   self.nodeSep = delegateProperty(position.nodeSep);
   964   self.edgeSep = delegateProperty(position.edgeSep);
   965   self.universalSep = delegateProperty(position.universalSep);
   966   self.rankSep = delegateProperty(position.rankSep);
   967   self.rankDir = util.propertyAccessor(self, config, 'rankDir');
   968   self.debugAlignment = delegateProperty(position.debugAlignment);
   970   self.debugLevel = util.propertyAccessor(self, config, 'debugLevel', function(x) {
   971     util.log.level = x;
   972     position.debugLevel(x);
   973   });
   975   self.run = util.time('Total layout', run);
   977   self._normalize = normalize;
   979   return self;
   981   /*
   982    * Constructs an adjacency graph using the nodes and edges specified through
   983    * config. For each node and edge we add a property `dagre` that contains an
   984    * object that will hold intermediate and final layout information. Some of
   985    * the contents include:
   986    *
   987    *  1) A generated ID that uniquely identifies the object.
   988    *  2) Dimension information for nodes (copied from the source node).
   989    *  3) Optional dimension information for edges.
   990    *
   991    * After the adjacency graph is constructed the code no longer needs to use
   992    * the original nodes and edges passed in via config.
   993    */
   994   function initLayoutGraph(inputGraph) {
   995     var g = new CDigraph();
   997     inputGraph.eachNode(function(u, value) {
   998       if (value === undefined) value = {};
   999       g.addNode(u, {
  1000         width: value.width,
  1001         height: value.height
  1002       });
  1003       if (value.hasOwnProperty('rank')) {
  1004         g.node(u).prefRank = value.rank;
  1006     });
  1008     // Set up subgraphs
  1009     if (inputGraph.parent) {
  1010       inputGraph.nodes().forEach(function(u) {
  1011         g.parent(u, inputGraph.parent(u));
  1012       });
  1015     inputGraph.eachEdge(function(e, u, v, value) {
  1016       if (value === undefined) value = {};
  1017       var newValue = {
  1018         e: e,
  1019         minLen: value.minLen || 1,
  1020         width: value.width || 0,
  1021         height: value.height || 0,
  1022         points: []
  1023       };
  1025       g.addEdge(null, u, v, newValue);
  1026     });
  1028     // Initial graph attributes
  1029     var graphValue = inputGraph.graph() || {};
  1030     g.graph({
  1031       rankDir: graphValue.rankDir || config.rankDir,
  1032       orderRestarts: graphValue.orderRestarts
  1033     });
  1035     return g;
  1038   function run(inputGraph) {
  1039     var rankSep = self.rankSep();
  1040     var g;
  1041     try {
  1042       // Build internal graph
  1043       g = util.time('initLayoutGraph', initLayoutGraph)(inputGraph);
  1045       if (g.order() === 0) {
  1046         return g;
  1049       // Make space for edge labels
  1050       g.eachEdge(function(e, s, t, a) {
  1051         a.minLen *= 2;
  1052       });
  1053       self.rankSep(rankSep / 2);
  1055       // Determine the rank for each node. Nodes with a lower rank will appear
  1056       // above nodes of higher rank.
  1057       util.time('rank.run', rank.run)(g, config.rankSimplex);
  1059       // Normalize the graph by ensuring that every edge is proper (each edge has
  1060       // a length of 1). We achieve this by adding dummy nodes to long edges,
  1061       // thus shortening them.
  1062       util.time('normalize', normalize)(g);
  1064       // Order the nodes so that edge crossings are minimized.
  1065       util.time('order', order)(g, config.orderMaxSweeps);
  1067       // Find the x and y coordinates for every node in the graph.
  1068       util.time('position', position.run)(g);
  1070       // De-normalize the graph by removing dummy nodes and augmenting the
  1071       // original long edges with coordinate information.
  1072       util.time('undoNormalize', undoNormalize)(g);
  1074       // Reverses points for edges that are in a reversed state.
  1075       util.time('fixupEdgePoints', fixupEdgePoints)(g);
  1077       // Restore delete edges and reverse edges that were reversed in the rank
  1078       // phase.
  1079       util.time('rank.restoreEdges', rank.restoreEdges)(g);
  1081       // Construct final result graph and return it
  1082       return util.time('createFinalGraph', createFinalGraph)(g, inputGraph.isDirected());
  1083     } finally {
  1084       self.rankSep(rankSep);
  1088   /*
  1089    * This function is responsible for 'normalizing' the graph. The process of
  1090    * normalization ensures that no edge in the graph has spans more than one
  1091    * rank. To do this it inserts dummy nodes as needed and links them by adding
  1092    * dummy edges. This function keeps enough information in the dummy nodes and
  1093    * edges to ensure that the original graph can be reconstructed later.
  1095    * This method assumes that the input graph is cycle free.
  1096    */
  1097   function normalize(g) {
  1098     var dummyCount = 0;
  1099     g.eachEdge(function(e, s, t, a) {
  1100       var sourceRank = g.node(s).rank;
  1101       var targetRank = g.node(t).rank;
  1102       if (sourceRank + 1 < targetRank) {
  1103         for (var u = s, rank = sourceRank + 1, i = 0; rank < targetRank; ++rank, ++i) {
  1104           var v = '_D' + (++dummyCount);
  1105           var node = {
  1106             width: a.width,
  1107             height: a.height,
  1108             edge: { id: e, source: s, target: t, attrs: a },
  1109             rank: rank,
  1110             dummy: true
  1111           };
  1113           // If this node represents a bend then we will use it as a control
  1114           // point. For edges with 2 segments this will be the center dummy
  1115           // node. For edges with more than two segments, this will be the
  1116           // first and last dummy node.
  1117           if (i === 0) node.index = 0;
  1118           else if (rank + 1 === targetRank) node.index = 1;
  1120           g.addNode(v, node);
  1121           g.addEdge(null, u, v, {});
  1122           u = v;
  1124         g.addEdge(null, u, t, {});
  1125         g.delEdge(e);
  1127     });
  1130   /*
  1131    * Reconstructs the graph as it was before normalization. The positions of
  1132    * dummy nodes are used to build an array of points for the original 'long'
  1133    * edge. Dummy nodes and edges are removed.
  1134    */
  1135   function undoNormalize(g) {
  1136     g.eachNode(function(u, a) {
  1137       if (a.dummy) {
  1138         if ('index' in a) {
  1139           var edge = a.edge;
  1140           if (!g.hasEdge(edge.id)) {
  1141             g.addEdge(edge.id, edge.source, edge.target, edge.attrs);
  1143           var points = g.edge(edge.id).points;
  1144           points[a.index] = { x: a.x, y: a.y, ul: a.ul, ur: a.ur, dl: a.dl, dr: a.dr };
  1146         g.delNode(u);
  1148     });
  1151   /*
  1152    * For each edge that was reversed during the `acyclic` step, reverse its
  1153    * array of points.
  1154    */
  1155   function fixupEdgePoints(g) {
  1156     g.eachEdge(function(e, s, t, a) { if (a.reversed) a.points.reverse(); });
  1159   function createFinalGraph(g, isDirected) {
  1160     var out = isDirected ? new CDigraph() : new CGraph();
  1161     out.graph(g.graph());
  1162     g.eachNode(function(u, value) { out.addNode(u, value); });
  1163     g.eachNode(function(u) { out.parent(u, g.parent(u)); });
  1164     g.eachEdge(function(e, u, v, value) {
  1165       out.addEdge(value.e, u, v, value);
  1166     });
  1168     // Attach bounding box information
  1169     var maxX = 0, maxY = 0;
  1170     g.eachNode(function(u, value) {
  1171       if (!g.children(u).length) {
  1172         maxX = Math.max(maxX, value.x + value.width / 2);
  1173         maxY = Math.max(maxY, value.y + value.height / 2);
  1175     });
  1176     g.eachEdge(function(e, u, v, value) {
  1177       var maxXPoints = Math.max.apply(Math, value.points.map(function(p) { return p.x; }));
  1178       var maxYPoints = Math.max.apply(Math, value.points.map(function(p) { return p.y; }));
  1179       maxX = Math.max(maxX, maxXPoints + value.width / 2);
  1180       maxY = Math.max(maxY, maxYPoints + value.height / 2);
  1181     });
  1182     out.graph().width = maxX;
  1183     out.graph().height = maxY;
  1185     return out;
  1188   /*
  1189    * Given a function, a new function is returned that invokes the given
  1190    * function. The return value from the function is always the `self` object.
  1191    */
  1192   function delegateProperty(f) {
  1193     return function() {
  1194       if (!arguments.length) return f();
  1195       f.apply(null, arguments);
  1196       return self;
  1197     };
  1199 };
  1202 },{"./order":13,"./position":18,"./rank":19,"./util":26,"graphlib":28}],13:[function(require,module,exports){
  1203 var util = require('./util'),
  1204     crossCount = require('./order/crossCount'),
  1205     initLayerGraphs = require('./order/initLayerGraphs'),
  1206     initOrder = require('./order/initOrder'),
  1207     sortLayer = require('./order/sortLayer');
  1209 module.exports = order;
  1211 // The maximum number of sweeps to perform before finishing the order phase.
  1212 var DEFAULT_MAX_SWEEPS = 24;
  1213 order.DEFAULT_MAX_SWEEPS = DEFAULT_MAX_SWEEPS;
  1215 /*
  1216  * Runs the order phase with the specified `graph, `maxSweeps`, and
  1217  * `debugLevel`. If `maxSweeps` is not specified we use `DEFAULT_MAX_SWEEPS`.
  1218  * If `debugLevel` is not set we assume 0.
  1219  */
  1220 function order(g, maxSweeps) {
  1221   if (arguments.length < 2) {
  1222     maxSweeps = DEFAULT_MAX_SWEEPS;
  1225   var restarts = g.graph().orderRestarts || 0;
  1227   var layerGraphs = initLayerGraphs(g);
  1228   // TODO: remove this when we add back support for ordering clusters
  1229   layerGraphs.forEach(function(lg) {
  1230     lg = lg.filterNodes(function(u) { return !g.children(u).length; });
  1231   });
  1233   var iters = 0,
  1234       currentBestCC,
  1235       allTimeBestCC = Number.MAX_VALUE,
  1236       allTimeBest = {};
  1238   function saveAllTimeBest() {
  1239     g.eachNode(function(u, value) { allTimeBest[u] = value.order; });
  1242   for (var j = 0; j < Number(restarts) + 1 && allTimeBestCC !== 0; ++j) {
  1243     currentBestCC = Number.MAX_VALUE;
  1244     initOrder(g, restarts > 0);
  1246     util.log(2, 'Order phase start cross count: ' + g.graph().orderInitCC);
  1248     var i, lastBest, cc;
  1249     for (i = 0, lastBest = 0; lastBest < 4 && i < maxSweeps && currentBestCC > 0; ++i, ++lastBest, ++iters) {
  1250       sweep(g, layerGraphs, i);
  1251       cc = crossCount(g);
  1252       if (cc < currentBestCC) {
  1253         lastBest = 0;
  1254         currentBestCC = cc;
  1255         if (cc < allTimeBestCC) {
  1256           saveAllTimeBest();
  1257           allTimeBestCC = cc;
  1260       util.log(3, 'Order phase start ' + j + ' iter ' + i + ' cross count: ' + cc);
  1264   Object.keys(allTimeBest).forEach(function(u) {
  1265     if (!g.children || !g.children(u).length) {
  1266       g.node(u).order = allTimeBest[u];
  1268   });
  1269   g.graph().orderCC = allTimeBestCC;
  1271   util.log(2, 'Order iterations: ' + iters);
  1272   util.log(2, 'Order phase best cross count: ' + g.graph().orderCC);
  1275 function predecessorWeights(g, nodes) {
  1276   var weights = {};
  1277   nodes.forEach(function(u) {
  1278     weights[u] = g.inEdges(u).map(function(e) {
  1279       return g.node(g.source(e)).order;
  1280     });
  1281   });
  1282   return weights;
  1285 function successorWeights(g, nodes) {
  1286   var weights = {};
  1287   nodes.forEach(function(u) {
  1288     weights[u] = g.outEdges(u).map(function(e) {
  1289       return g.node(g.target(e)).order;
  1290     });
  1291   });
  1292   return weights;
  1295 function sweep(g, layerGraphs, iter) {
  1296   if (iter % 2 === 0) {
  1297     sweepDown(g, layerGraphs, iter);
  1298   } else {
  1299     sweepUp(g, layerGraphs, iter);
  1303 function sweepDown(g, layerGraphs) {
  1304   var cg;
  1305   for (i = 1; i < layerGraphs.length; ++i) {
  1306     cg = sortLayer(layerGraphs[i], cg, predecessorWeights(g, layerGraphs[i].nodes()));
  1310 function sweepUp(g, layerGraphs) {
  1311   var cg;
  1312   for (i = layerGraphs.length - 2; i >= 0; --i) {
  1313     sortLayer(layerGraphs[i], cg, successorWeights(g, layerGraphs[i].nodes()));
  1317 },{"./order/crossCount":14,"./order/initLayerGraphs":15,"./order/initOrder":16,"./order/sortLayer":17,"./util":26}],14:[function(require,module,exports){
  1318 var util = require('../util');
  1320 module.exports = crossCount;
  1322 /*
  1323  * Returns the cross count for the given graph.
  1324  */
  1325 function crossCount(g) {
  1326   var cc = 0;
  1327   var ordering = util.ordering(g);
  1328   for (var i = 1; i < ordering.length; ++i) {
  1329     cc += twoLayerCrossCount(g, ordering[i-1], ordering[i]);
  1331   return cc;
  1334 /*
  1335  * This function searches through a ranked and ordered graph and counts the
  1336  * number of edges that cross. This algorithm is derived from:
  1338  *    W. Barth et al., Bilayer Cross Counting, JGAA, 8(2) 179–194 (2004)
  1339  */
  1340 function twoLayerCrossCount(g, layer1, layer2) {
  1341   var indices = [];
  1342   layer1.forEach(function(u) {
  1343     var nodeIndices = [];
  1344     g.outEdges(u).forEach(function(e) { nodeIndices.push(g.node(g.target(e)).order); });
  1345     nodeIndices.sort(function(x, y) { return x - y; });
  1346     indices = indices.concat(nodeIndices);
  1347   });
  1349   var firstIndex = 1;
  1350   while (firstIndex < layer2.length) firstIndex <<= 1;
  1352   var treeSize = 2 * firstIndex - 1;
  1353   firstIndex -= 1;
  1355   var tree = [];
  1356   for (var i = 0; i < treeSize; ++i) { tree[i] = 0; }
  1358   var cc = 0;
  1359   indices.forEach(function(i) {
  1360     var treeIndex = i + firstIndex;
  1361     ++tree[treeIndex];
  1362     while (treeIndex > 0) {
  1363       if (treeIndex % 2) {
  1364         cc += tree[treeIndex + 1];
  1366       treeIndex = (treeIndex - 1) >> 1;
  1367       ++tree[treeIndex];
  1369   });
  1371   return cc;
  1374 },{"../util":26}],15:[function(require,module,exports){
  1375 var nodesFromList = require('graphlib').filter.nodesFromList,
  1376     /* jshint -W079 */
  1377     Set = require('cp-data').Set;
  1379 module.exports = initLayerGraphs;
  1381 /*
  1382  * This function takes a compound layered graph, g, and produces an array of
  1383  * layer graphs. Each entry in the array represents a subgraph of nodes
  1384  * relevant for performing crossing reduction on that layer.
  1385  */
  1386 function initLayerGraphs(g) {
  1387   var ranks = [];
  1389   function dfs(u) {
  1390     if (u === null) {
  1391       g.children(u).forEach(function(v) { dfs(v); });
  1392       return;
  1395     var value = g.node(u);
  1396     value.minRank = ('rank' in value) ? value.rank : Number.MAX_VALUE;
  1397     value.maxRank = ('rank' in value) ? value.rank : Number.MIN_VALUE;
  1398     var uRanks = new Set();
  1399     g.children(u).forEach(function(v) {
  1400       var rs = dfs(v);
  1401       uRanks = Set.union([uRanks, rs]);
  1402       value.minRank = Math.min(value.minRank, g.node(v).minRank);
  1403       value.maxRank = Math.max(value.maxRank, g.node(v).maxRank);
  1404     });
  1406     if ('rank' in value) uRanks.add(value.rank);
  1408     uRanks.keys().forEach(function(r) {
  1409       if (!(r in ranks)) ranks[r] = [];
  1410       ranks[r].push(u);
  1411     });
  1413     return uRanks;
  1415   dfs(null);
  1417   var layerGraphs = [];
  1418   ranks.forEach(function(us, rank) {
  1419     layerGraphs[rank] = g.filterNodes(nodesFromList(us));
  1420   });
  1422   return layerGraphs;
  1425 },{"cp-data":5,"graphlib":28}],16:[function(require,module,exports){
  1426 var crossCount = require('./crossCount'),
  1427     util = require('../util');
  1429 module.exports = initOrder;
  1431 /*
  1432  * Given a graph with a set of layered nodes (i.e. nodes that have a `rank`
  1433  * attribute) this function attaches an `order` attribute that uniquely
  1434  * arranges each node of each rank. If no constraint graph is provided the
  1435  * order of the nodes in each rank is entirely arbitrary.
  1436  */
  1437 function initOrder(g, random) {
  1438   var layers = [];
  1440   g.eachNode(function(u, value) {
  1441     var layer = layers[value.rank];
  1442     if (g.children && g.children(u).length > 0) return;
  1443     if (!layer) {
  1444       layer = layers[value.rank] = [];
  1446     layer.push(u);
  1447   });
  1449   layers.forEach(function(layer) {
  1450     if (random) {
  1451       util.shuffle(layer);
  1453     layer.forEach(function(u, i) {
  1454       g.node(u).order = i;
  1455     });
  1456   });
  1458   var cc = crossCount(g);
  1459   g.graph().orderInitCC = cc;
  1460   g.graph().orderCC = Number.MAX_VALUE;
  1463 },{"../util":26,"./crossCount":14}],17:[function(require,module,exports){
  1464 var util = require('../util');
  1465 /*
  1466     Digraph = require('graphlib').Digraph,
  1467     topsort = require('graphlib').alg.topsort,
  1468     nodesFromList = require('graphlib').filter.nodesFromList;
  1469 */
  1471 module.exports = sortLayer;
  1473 /*
  1474 function sortLayer(g, cg, weights) {
  1475   var result = sortLayerSubgraph(g, null, cg, weights);
  1476   result.list.forEach(function(u, i) {
  1477     g.node(u).order = i;
  1478   });
  1479   return result.constraintGraph;
  1481 */
  1483 function sortLayer(g, cg, weights) {
  1484   var ordering = [];
  1485   var bs = {};
  1486   g.eachNode(function(u, value) {
  1487     ordering[value.order] = u;
  1488     var ws = weights[u];
  1489     if (ws.length) {
  1490       bs[u] = util.sum(ws) / ws.length;
  1492   });
  1494   var toSort = g.nodes().filter(function(u) { return bs[u] !== undefined; });
  1495   toSort.sort(function(x, y) {
  1496     return bs[x] - bs[y] || g.node(x).order - g.node(y).order;
  1497   });
  1499   for (var i = 0, j = 0, jl = toSort.length; j < jl; ++i) {
  1500     if (bs[ordering[i]] !== undefined) {
  1501       g.node(toSort[j++]).order = i;
  1506 // TOOD: re-enable constrained sorting once we have a strategy for handling
  1507 // undefined barycenters.
  1508 /*
  1509 function sortLayerSubgraph(g, sg, cg, weights) {
  1510   cg = cg ? cg.filterNodes(nodesFromList(g.children(sg))) : new Digraph();
  1512   var nodeData = {};
  1513   g.children(sg).forEach(function(u) {
  1514     if (g.children(u).length) {
  1515       nodeData[u] = sortLayerSubgraph(g, u, cg, weights);
  1516       nodeData[u].firstSG = u;
  1517       nodeData[u].lastSG = u;
  1518     } else {
  1519       var ws = weights[u];
  1520       nodeData[u] = {
  1521         degree: ws.length,
  1522         barycenter: ws.length > 0 ? util.sum(ws) / ws.length : 0,
  1523         list: [u]
  1524       };
  1526   });
  1528   resolveViolatedConstraints(g, cg, nodeData);
  1530   var keys = Object.keys(nodeData);
  1531   keys.sort(function(x, y) {
  1532     return nodeData[x].barycenter - nodeData[y].barycenter;
  1533   });
  1535   var result =  keys.map(function(u) { return nodeData[u]; })
  1536                     .reduce(function(lhs, rhs) { return mergeNodeData(g, lhs, rhs); });
  1537   return result;
  1540 /*
  1541 function mergeNodeData(g, lhs, rhs) {
  1542   var cg = mergeDigraphs(lhs.constraintGraph, rhs.constraintGraph);
  1544   if (lhs.lastSG !== undefined && rhs.firstSG !== undefined) {
  1545     if (cg === undefined) {
  1546       cg = new Digraph();
  1548     if (!cg.hasNode(lhs.lastSG)) { cg.addNode(lhs.lastSG); }
  1549     cg.addNode(rhs.firstSG);
  1550     cg.addEdge(null, lhs.lastSG, rhs.firstSG);
  1553   return {
  1554     degree: lhs.degree + rhs.degree,
  1555     barycenter: (lhs.barycenter * lhs.degree + rhs.barycenter * rhs.degree) /
  1556                 (lhs.degree + rhs.degree),
  1557     list: lhs.list.concat(rhs.list),
  1558     firstSG: lhs.firstSG !== undefined ? lhs.firstSG : rhs.firstSG,
  1559     lastSG: rhs.lastSG !== undefined ? rhs.lastSG : lhs.lastSG,
  1560     constraintGraph: cg
  1561   };
  1564 function mergeDigraphs(lhs, rhs) {
  1565   if (lhs === undefined) return rhs;
  1566   if (rhs === undefined) return lhs;
  1568   lhs = lhs.copy();
  1569   rhs.nodes().forEach(function(u) { lhs.addNode(u); });
  1570   rhs.edges().forEach(function(e, u, v) { lhs.addEdge(null, u, v); });
  1571   return lhs;
  1574 function resolveViolatedConstraints(g, cg, nodeData) {
  1575   // Removes nodes `u` and `v` from `cg` and makes any edges incident on them
  1576   // incident on `w` instead.
  1577   function collapseNodes(u, v, w) {
  1578     // TODO original paper removes self loops, but it is not obvious when this would happen
  1579     cg.inEdges(u).forEach(function(e) {
  1580       cg.delEdge(e);
  1581       cg.addEdge(null, cg.source(e), w);
  1582     });
  1584     cg.outEdges(v).forEach(function(e) {
  1585       cg.delEdge(e);
  1586       cg.addEdge(null, w, cg.target(e));
  1587     });
  1589     cg.delNode(u);
  1590     cg.delNode(v);
  1593   var violated;
  1594   while ((violated = findViolatedConstraint(cg, nodeData)) !== undefined) {
  1595     var source = cg.source(violated),
  1596         target = cg.target(violated);
  1598     var v;
  1599     while ((v = cg.addNode(null)) && g.hasNode(v)) {
  1600       cg.delNode(v);
  1603     // Collapse barycenter and list
  1604     nodeData[v] = mergeNodeData(g, nodeData[source], nodeData[target]);
  1605     delete nodeData[source];
  1606     delete nodeData[target];
  1608     collapseNodes(source, target, v);
  1609     if (cg.incidentEdges(v).length === 0) { cg.delNode(v); }
  1613 function findViolatedConstraint(cg, nodeData) {
  1614   var us = topsort(cg);
  1615   for (var i = 0; i < us.length; ++i) {
  1616     var u = us[i];
  1617     var inEdges = cg.inEdges(u);
  1618     for (var j = 0; j < inEdges.length; ++j) {
  1619       var e = inEdges[j];
  1620       if (nodeData[cg.source(e)].barycenter >= nodeData[u].barycenter) {
  1621         return e;
  1626 */
  1628 },{"../util":26}],18:[function(require,module,exports){
  1629 var util = require('./util');
  1631 /*
  1632  * The algorithms here are based on Brandes and Köpf, "Fast and Simple
  1633  * Horizontal Coordinate Assignment".
  1634  */
  1635 module.exports = function() {
  1636   // External configuration
  1637   var config = {
  1638     nodeSep: 50,
  1639     edgeSep: 10,
  1640     universalSep: null,
  1641     rankSep: 30
  1642   };
  1644   var self = {};
  1646   self.nodeSep = util.propertyAccessor(self, config, 'nodeSep');
  1647   self.edgeSep = util.propertyAccessor(self, config, 'edgeSep');
  1648   // If not null this separation value is used for all nodes and edges
  1649   // regardless of their widths. `nodeSep` and `edgeSep` are ignored with this
  1650   // option.
  1651   self.universalSep = util.propertyAccessor(self, config, 'universalSep');
  1652   self.rankSep = util.propertyAccessor(self, config, 'rankSep');
  1653   self.debugLevel = util.propertyAccessor(self, config, 'debugLevel');
  1655   self.run = run;
  1657   return self;
  1659   function run(g) {
  1660     g = g.filterNodes(util.filterNonSubgraphs(g));
  1662     var layering = util.ordering(g);
  1664     var conflicts = findConflicts(g, layering);
  1666     var xss = {};
  1667     ['u', 'd'].forEach(function(vertDir) {
  1668       if (vertDir === 'd') layering.reverse();
  1670       ['l', 'r'].forEach(function(horizDir) {
  1671         if (horizDir === 'r') reverseInnerOrder(layering);
  1673         var dir = vertDir + horizDir;
  1674         var align = verticalAlignment(g, layering, conflicts, vertDir === 'u' ? 'predecessors' : 'successors');
  1675         xss[dir]= horizontalCompaction(g, layering, align.pos, align.root, align.align);
  1677         if (config.debugLevel >= 3)
  1678           debugPositioning(vertDir + horizDir, g, layering, xss[dir]);
  1680         if (horizDir === 'r') flipHorizontally(xss[dir]);
  1682         if (horizDir === 'r') reverseInnerOrder(layering);
  1683       });
  1685       if (vertDir === 'd') layering.reverse();
  1686     });
  1688     balance(g, layering, xss);
  1690     g.eachNode(function(v) {
  1691       var xs = [];
  1692       for (var alignment in xss) {
  1693         var alignmentX = xss[alignment][v];
  1694         posXDebug(alignment, g, v, alignmentX);
  1695         xs.push(alignmentX);
  1697       xs.sort(function(x, y) { return x - y; });
  1698       posX(g, v, (xs[1] + xs[2]) / 2);
  1699     });
  1701     // Align y coordinates with ranks
  1702     var y = 0, reverseY = g.graph().rankDir === 'BT' || g.graph().rankDir === 'RL';
  1703     layering.forEach(function(layer) {
  1704       var maxHeight = util.max(layer.map(function(u) { return height(g, u); }));
  1705       y += maxHeight / 2;
  1706       layer.forEach(function(u) {
  1707         posY(g, u, reverseY ? -y : y);
  1708       });
  1709       y += maxHeight / 2 + config.rankSep;
  1710     });
  1712     // Translate layout so that top left corner of bounding rectangle has
  1713     // coordinate (0, 0).
  1714     var minX = util.min(g.nodes().map(function(u) { return posX(g, u) - width(g, u) / 2; }));
  1715     var minY = util.min(g.nodes().map(function(u) { return posY(g, u) - height(g, u) / 2; }));
  1716     g.eachNode(function(u) {
  1717       posX(g, u, posX(g, u) - minX);
  1718       posY(g, u, posY(g, u) - minY);
  1719     });
  1722   /*
  1723    * Generate an ID that can be used to represent any undirected edge that is
  1724    * incident on `u` and `v`.
  1725    */
  1726   function undirEdgeId(u, v) {
  1727     return u < v
  1728       ? u.toString().length + ':' + u + '-' + v
  1729       : v.toString().length + ':' + v + '-' + u;
  1732   function findConflicts(g, layering) {
  1733     var conflicts = {}, // Set of conflicting edge ids
  1734         pos = {},       // Position of node in its layer
  1735         prevLayer,
  1736         currLayer,
  1737         k0,     // Position of the last inner segment in the previous layer
  1738         l,      // Current position in the current layer (for iteration up to `l1`)
  1739         k1;     // Position of the next inner segment in the previous layer or
  1740                 // the position of the last element in the previous layer
  1742     if (layering.length <= 2) return conflicts;
  1744     function updateConflicts(v) {
  1745       var k = pos[v];
  1746       if (k < k0 || k > k1) {
  1747         conflicts[undirEdgeId(currLayer[l], v)] = true;
  1751     layering[1].forEach(function(u, i) { pos[u] = i; });
  1752     for (var i = 1; i < layering.length - 1; ++i) {
  1753       prevLayer = layering[i];
  1754       currLayer = layering[i+1];
  1755       k0 = 0;
  1756       l = 0;
  1758       // Scan current layer for next node that is incident to an inner segement
  1759       // between layering[i+1] and layering[i].
  1760       for (var l1 = 0; l1 < currLayer.length; ++l1) {
  1761         var u = currLayer[l1]; // Next inner segment in the current layer or
  1762                                // last node in the current layer
  1763         pos[u] = l1;
  1764         k1 = undefined;
  1766         if (g.node(u).dummy) {
  1767           var uPred = g.predecessors(u)[0];
  1768           // Note: In the case of self loops and sideways edges it is possible
  1769           // for a dummy not to have a predecessor.
  1770           if (uPred !== undefined && g.node(uPred).dummy)
  1771             k1 = pos[uPred];
  1773         if (k1 === undefined && l1 === currLayer.length - 1)
  1774           k1 = prevLayer.length - 1;
  1776         if (k1 !== undefined) {
  1777           for (; l <= l1; ++l) {
  1778             g.predecessors(currLayer[l]).forEach(updateConflicts);
  1780           k0 = k1;
  1785     return conflicts;
  1788   function verticalAlignment(g, layering, conflicts, relationship) {
  1789     var pos = {},   // Position for a node in its layer
  1790         root = {},  // Root of the block that the node participates in
  1791         align = {}; // Points to the next node in the block or, if the last
  1792                     // element in the block, points to the first block's root
  1794     layering.forEach(function(layer) {
  1795       layer.forEach(function(u, i) {
  1796         root[u] = u;
  1797         align[u] = u;
  1798         pos[u] = i;
  1799       });
  1800     });
  1802     layering.forEach(function(layer) {
  1803       var prevIdx = -1;
  1804       layer.forEach(function(v) {
  1805         var related = g[relationship](v), // Adjacent nodes from the previous layer
  1806             mid;                          // The mid point in the related array
  1808         if (related.length > 0) {
  1809           related.sort(function(x, y) { return pos[x] - pos[y]; });
  1810           mid = (related.length - 1) / 2;
  1811           related.slice(Math.floor(mid), Math.ceil(mid) + 1).forEach(function(u) {
  1812             if (align[v] === v) {
  1813               if (!conflicts[undirEdgeId(u, v)] && prevIdx < pos[u]) {
  1814                 align[u] = v;
  1815                 align[v] = root[v] = root[u];
  1816                 prevIdx = pos[u];
  1819           });
  1821       });
  1822     });
  1824     return { pos: pos, root: root, align: align };
  1827   // This function deviates from the standard BK algorithm in two ways. First
  1828   // it takes into account the size of the nodes. Second it includes a fix to
  1829   // the original algorithm that is described in Carstens, "Node and Label
  1830   // Placement in a Layered Layout Algorithm".
  1831   function horizontalCompaction(g, layering, pos, root, align) {
  1832     var sink = {},       // Mapping of node id -> sink node id for class
  1833         maybeShift = {}, // Mapping of sink node id -> { class node id, min shift }
  1834         shift = {},      // Mapping of sink node id -> shift
  1835         pred = {},       // Mapping of node id -> predecessor node (or null)
  1836         xs = {};         // Calculated X positions
  1838     layering.forEach(function(layer) {
  1839       layer.forEach(function(u, i) {
  1840         sink[u] = u;
  1841         maybeShift[u] = {};
  1842         if (i > 0)
  1843           pred[u] = layer[i - 1];
  1844       });
  1845     });
  1847     function updateShift(toShift, neighbor, delta) {
  1848       if (!(neighbor in maybeShift[toShift])) {
  1849         maybeShift[toShift][neighbor] = delta;
  1850       } else {
  1851         maybeShift[toShift][neighbor] = Math.min(maybeShift[toShift][neighbor], delta);
  1855     function placeBlock(v) {
  1856       if (!(v in xs)) {
  1857         xs[v] = 0;
  1858         var w = v;
  1859         do {
  1860           if (pos[w] > 0) {
  1861             var u = root[pred[w]];
  1862             placeBlock(u);
  1863             if (sink[v] === v) {
  1864               sink[v] = sink[u];
  1866             var delta = sep(g, pred[w]) + sep(g, w);
  1867             if (sink[v] !== sink[u]) {
  1868               updateShift(sink[u], sink[v], xs[v] - xs[u] - delta);
  1869             } else {
  1870               xs[v] = Math.max(xs[v], xs[u] + delta);
  1873           w = align[w];
  1874         } while (w !== v);
  1878     // Root coordinates relative to sink
  1879     util.values(root).forEach(function(v) {
  1880       placeBlock(v);
  1881     });
  1883     // Absolute coordinates
  1884     // There is an assumption here that we've resolved shifts for any classes
  1885     // that begin at an earlier layer. We guarantee this by visiting layers in
  1886     // order.
  1887     layering.forEach(function(layer) {
  1888       layer.forEach(function(v) {
  1889         xs[v] = xs[root[v]];
  1890         if (v === root[v] && v === sink[v]) {
  1891           var minShift = 0;
  1892           if (v in maybeShift && Object.keys(maybeShift[v]).length > 0) {
  1893             minShift = util.min(Object.keys(maybeShift[v])
  1894                                  .map(function(u) {
  1895                                       return maybeShift[v][u] + (u in shift ? shift[u] : 0);
  1897                                  ));
  1899           shift[v] = minShift;
  1901       });
  1902     });
  1904     layering.forEach(function(layer) {
  1905       layer.forEach(function(v) {
  1906         xs[v] += shift[sink[root[v]]] || 0;
  1907       });
  1908     });
  1910     return xs;
  1913   function findMinCoord(g, layering, xs) {
  1914     return util.min(layering.map(function(layer) {
  1915       var u = layer[0];
  1916       return xs[u];
  1917     }));
  1920   function findMaxCoord(g, layering, xs) {
  1921     return util.max(layering.map(function(layer) {
  1922       var u = layer[layer.length - 1];
  1923       return xs[u];
  1924     }));
  1927   function balance(g, layering, xss) {
  1928     var min = {},                            // Min coordinate for the alignment
  1929         max = {},                            // Max coordinate for the alginment
  1930         smallestAlignment,
  1931         shift = {};                          // Amount to shift a given alignment
  1933     function updateAlignment(v) {
  1934       xss[alignment][v] += shift[alignment];
  1937     var smallest = Number.POSITIVE_INFINITY;
  1938     for (var alignment in xss) {
  1939       var xs = xss[alignment];
  1940       min[alignment] = findMinCoord(g, layering, xs);
  1941       max[alignment] = findMaxCoord(g, layering, xs);
  1942       var w = max[alignment] - min[alignment];
  1943       if (w < smallest) {
  1944         smallest = w;
  1945         smallestAlignment = alignment;
  1949     // Determine how much to adjust positioning for each alignment
  1950     ['u', 'd'].forEach(function(vertDir) {
  1951       ['l', 'r'].forEach(function(horizDir) {
  1952         var alignment = vertDir + horizDir;
  1953         shift[alignment] = horizDir === 'l'
  1954             ? min[smallestAlignment] - min[alignment]
  1955             : max[smallestAlignment] - max[alignment];
  1956       });
  1957     });
  1959     // Find average of medians for xss array
  1960     for (alignment in xss) {
  1961       g.eachNode(updateAlignment);
  1965   function flipHorizontally(xs) {
  1966     for (var u in xs) {
  1967       xs[u] = -xs[u];
  1971   function reverseInnerOrder(layering) {
  1972     layering.forEach(function(layer) {
  1973       layer.reverse();
  1974     });
  1977   function width(g, u) {
  1978     switch (g.graph().rankDir) {
  1979       case 'LR': return g.node(u).height;
  1980       case 'RL': return g.node(u).height;
  1981       default:   return g.node(u).width;
  1985   function height(g, u) {
  1986     switch(g.graph().rankDir) {
  1987       case 'LR': return g.node(u).width;
  1988       case 'RL': return g.node(u).width;
  1989       default:   return g.node(u).height;
  1993   function sep(g, u) {
  1994     if (config.universalSep !== null) {
  1995       return config.universalSep;
  1997     var w = width(g, u);
  1998     var s = g.node(u).dummy ? config.edgeSep : config.nodeSep;
  1999     return (w + s) / 2;
  2002   function posX(g, u, x) {
  2003     if (g.graph().rankDir === 'LR' || g.graph().rankDir === 'RL') {
  2004       if (arguments.length < 3) {
  2005         return g.node(u).y;
  2006       } else {
  2007         g.node(u).y = x;
  2009     } else {
  2010       if (arguments.length < 3) {
  2011         return g.node(u).x;
  2012       } else {
  2013         g.node(u).x = x;
  2018   function posXDebug(name, g, u, x) {
  2019     if (g.graph().rankDir === 'LR' || g.graph().rankDir === 'RL') {
  2020       if (arguments.length < 3) {
  2021         return g.node(u)[name];
  2022       } else {
  2023         g.node(u)[name] = x;
  2025     } else {
  2026       if (arguments.length < 3) {
  2027         return g.node(u)[name];
  2028       } else {
  2029         g.node(u)[name] = x;
  2034   function posY(g, u, y) {
  2035     if (g.graph().rankDir === 'LR' || g.graph().rankDir === 'RL') {
  2036       if (arguments.length < 3) {
  2037         return g.node(u).x;
  2038       } else {
  2039         g.node(u).x = y;
  2041     } else {
  2042       if (arguments.length < 3) {
  2043         return g.node(u).y;
  2044       } else {
  2045         g.node(u).y = y;
  2050   function debugPositioning(align, g, layering, xs) {
  2051     layering.forEach(function(l, li) {
  2052       var u, xU;
  2053       l.forEach(function(v) {
  2054         var xV = xs[v];
  2055         if (u) {
  2056           var s = sep(g, u) + sep(g, v);
  2057           if (xV - xU < s)
  2058             console.log('Position phase: sep violation. Align: ' + align + '. Layer: ' + li + '. ' +
  2059               'U: ' + u + ' V: ' + v + '. Actual sep: ' + (xV - xU) + ' Expected sep: ' + s);
  2061         u = v;
  2062         xU = xV;
  2063       });
  2064     });
  2066 };
  2068 },{"./util":26}],19:[function(require,module,exports){
  2069 var util = require('./util'),
  2070     acyclic = require('./rank/acyclic'),
  2071     initRank = require('./rank/initRank'),
  2072     feasibleTree = require('./rank/feasibleTree'),
  2073     constraints = require('./rank/constraints'),
  2074     simplex = require('./rank/simplex'),
  2075     components = require('graphlib').alg.components,
  2076     filter = require('graphlib').filter;
  2078 exports.run = run;
  2079 exports.restoreEdges = restoreEdges;
  2081 /*
  2082  * Heuristic function that assigns a rank to each node of the input graph with
  2083  * the intent of minimizing edge lengths, while respecting the `minLen`
  2084  * attribute of incident edges.
  2086  * Prerequisites:
  2088  *  * Each edge in the input graph must have an assigned 'minLen' attribute
  2089  */
  2090 function run(g, useSimplex) {
  2091   expandSelfLoops(g);
  2093   // If there are rank constraints on nodes, then build a new graph that
  2094   // encodes the constraints.
  2095   util.time('constraints.apply', constraints.apply)(g);
  2097   expandSidewaysEdges(g);
  2099   // Reverse edges to get an acyclic graph, we keep the graph in an acyclic
  2100   // state until the very end.
  2101   util.time('acyclic', acyclic)(g);
  2103   // Convert the graph into a flat graph for ranking
  2104   var flatGraph = g.filterNodes(util.filterNonSubgraphs(g));
  2106   // Assign an initial ranking using DFS.
  2107   initRank(flatGraph);
  2109   // For each component improve the assigned ranks.
  2110   components(flatGraph).forEach(function(cmpt) {
  2111     var subgraph = flatGraph.filterNodes(filter.nodesFromList(cmpt));
  2112     rankComponent(subgraph, useSimplex);
  2113   });
  2115   // Relax original constraints
  2116   util.time('constraints.relax', constraints.relax(g));
  2118   // When handling nodes with constrained ranks it is possible to end up with
  2119   // edges that point to previous ranks. Most of the subsequent algorithms assume
  2120   // that edges are pointing to successive ranks only. Here we reverse any "back
  2121   // edges" and mark them as such. The acyclic algorithm will reverse them as a
  2122   // post processing step.
  2123   util.time('reorientEdges', reorientEdges)(g);
  2126 function restoreEdges(g) {
  2127   acyclic.undo(g);
  2130 /*
  2131  * Expand self loops into three dummy nodes. One will sit above the incident
  2132  * node, one will be at the same level, and one below. The result looks like:
  2134  *         /--<--x--->--\
  2135  *     node              y
  2136  *         \--<--z--->--/
  2138  * Dummy nodes x, y, z give us the shape of a loop and node y is where we place
  2139  * the label.
  2141  * TODO: consolidate knowledge of dummy node construction.
  2142  * TODO: support minLen = 2
  2143  */
  2144 function expandSelfLoops(g) {
  2145   g.eachEdge(function(e, u, v, a) {
  2146     if (u === v) {
  2147       var x = addDummyNode(g, e, u, v, a, 0, false),
  2148           y = addDummyNode(g, e, u, v, a, 1, true),
  2149           z = addDummyNode(g, e, u, v, a, 2, false);
  2150       g.addEdge(null, x, u, {minLen: 1, selfLoop: true});
  2151       g.addEdge(null, x, y, {minLen: 1, selfLoop: true});
  2152       g.addEdge(null, u, z, {minLen: 1, selfLoop: true});
  2153       g.addEdge(null, y, z, {minLen: 1, selfLoop: true});
  2154       g.delEdge(e);
  2156   });
  2159 function expandSidewaysEdges(g) {
  2160   g.eachEdge(function(e, u, v, a) {
  2161     if (u === v) {
  2162       var origEdge = a.originalEdge,
  2163           dummy = addDummyNode(g, origEdge.e, origEdge.u, origEdge.v, origEdge.value, 0, true);
  2164       g.addEdge(null, u, dummy, {minLen: 1});
  2165       g.addEdge(null, dummy, v, {minLen: 1});
  2166       g.delEdge(e);
  2168   });
  2171 function addDummyNode(g, e, u, v, a, index, isLabel) {
  2172   return g.addNode(null, {
  2173     width: isLabel ? a.width : 0,
  2174     height: isLabel ? a.height : 0,
  2175     edge: { id: e, source: u, target: v, attrs: a },
  2176     dummy: true,
  2177     index: index
  2178   });
  2181 function reorientEdges(g) {
  2182   g.eachEdge(function(e, u, v, value) {
  2183     if (g.node(u).rank > g.node(v).rank) {
  2184       g.delEdge(e);
  2185       value.reversed = true;
  2186       g.addEdge(e, v, u, value);
  2188   });
  2191 function rankComponent(subgraph, useSimplex) {
  2192   var spanningTree = feasibleTree(subgraph);
  2194   if (useSimplex) {
  2195     util.log(1, 'Using network simplex for ranking');
  2196     simplex(subgraph, spanningTree);
  2198   normalize(subgraph);
  2201 function normalize(g) {
  2202   var m = util.min(g.nodes().map(function(u) { return g.node(u).rank; }));
  2203   g.eachNode(function(u, node) { node.rank -= m; });
  2206 },{"./rank/acyclic":20,"./rank/constraints":21,"./rank/feasibleTree":22,"./rank/initRank":23,"./rank/simplex":25,"./util":26,"graphlib":28}],20:[function(require,module,exports){
  2207 var util = require('../util');
  2209 module.exports = acyclic;
  2210 module.exports.undo = undo;
  2212 /*
  2213  * This function takes a directed graph that may have cycles and reverses edges
  2214  * as appropriate to break these cycles. Each reversed edge is assigned a
  2215  * `reversed` attribute with the value `true`.
  2217  * There should be no self loops in the graph.
  2218  */
  2219 function acyclic(g) {
  2220   var onStack = {},
  2221       visited = {},
  2222       reverseCount = 0;
  2224   function dfs(u) {
  2225     if (u in visited) return;
  2226     visited[u] = onStack[u] = true;
  2227     g.outEdges(u).forEach(function(e) {
  2228       var t = g.target(e),
  2229           value;
  2231       if (u === t) {
  2232         console.error('Warning: found self loop "' + e + '" for node "' + u + '"');
  2233       } else if (t in onStack) {
  2234         value = g.edge(e);
  2235         g.delEdge(e);
  2236         value.reversed = true;
  2237         ++reverseCount;
  2238         g.addEdge(e, t, u, value);
  2239       } else {
  2240         dfs(t);
  2242     });
  2244     delete onStack[u];
  2247   g.eachNode(function(u) { dfs(u); });
  2249   util.log(2, 'Acyclic Phase: reversed ' + reverseCount + ' edge(s)');
  2251   return reverseCount;
  2254 /*
  2255  * Given a graph that has had the acyclic operation applied, this function
  2256  * undoes that operation. More specifically, any edge with the `reversed`
  2257  * attribute is again reversed to restore the original direction of the edge.
  2258  */
  2259 function undo(g) {
  2260   g.eachEdge(function(e, s, t, a) {
  2261     if (a.reversed) {
  2262       delete a.reversed;
  2263       g.delEdge(e);
  2264       g.addEdge(e, t, s, a);
  2266   });
  2269 },{"../util":26}],21:[function(require,module,exports){
  2270 exports.apply = function(g) {
  2271   function dfs(sg) {
  2272     var rankSets = {};
  2273     g.children(sg).forEach(function(u) {
  2274       if (g.children(u).length) {
  2275         dfs(u);
  2276         return;
  2279       var value = g.node(u),
  2280           prefRank = value.prefRank;
  2281       if (prefRank !== undefined) {
  2282         if (!checkSupportedPrefRank(prefRank)) { return; }
  2284         if (!(prefRank in rankSets)) {
  2285           rankSets.prefRank = [u];
  2286         } else {
  2287           rankSets.prefRank.push(u);
  2290         var newU = rankSets[prefRank];
  2291         if (newU === undefined) {
  2292           newU = rankSets[prefRank] = g.addNode(null, { originalNodes: [] });
  2293           g.parent(newU, sg);
  2296         redirectInEdges(g, u, newU, prefRank === 'min');
  2297         redirectOutEdges(g, u, newU, prefRank === 'max');
  2299         // Save original node and remove it from reduced graph
  2300         g.node(newU).originalNodes.push({ u: u, value: value, parent: sg });
  2301         g.delNode(u);
  2303     });
  2305     addLightEdgesFromMinNode(g, sg, rankSets.min);
  2306     addLightEdgesToMaxNode(g, sg, rankSets.max);
  2309   dfs(null);
  2310 };
  2312 function checkSupportedPrefRank(prefRank) {
  2313   if (prefRank !== 'min' && prefRank !== 'max' && prefRank.indexOf('same_') !== 0) {
  2314     console.error('Unsupported rank type: ' + prefRank);
  2315     return false;
  2317   return true;
  2320 function redirectInEdges(g, u, newU, reverse) {
  2321   g.inEdges(u).forEach(function(e) {
  2322     var origValue = g.edge(e),
  2323         value;
  2324     if (origValue.originalEdge) {
  2325       value = origValue;
  2326     } else {
  2327       value =  {
  2328         originalEdge: { e: e, u: g.source(e), v: g.target(e), value: origValue },
  2329         minLen: g.edge(e).minLen
  2330       };
  2333     // Do not reverse edges for self-loops.
  2334     if (origValue.selfLoop) {
  2335       reverse = false;
  2338     if (reverse) {
  2339       // Ensure that all edges to min are reversed
  2340       g.addEdge(null, newU, g.source(e), value);
  2341       value.reversed = true;
  2342     } else {
  2343       g.addEdge(null, g.source(e), newU, value);
  2345   });
  2348 function redirectOutEdges(g, u, newU, reverse) {
  2349   g.outEdges(u).forEach(function(e) {
  2350     var origValue = g.edge(e),
  2351         value;
  2352     if (origValue.originalEdge) {
  2353       value = origValue;
  2354     } else {
  2355       value =  {
  2356         originalEdge: { e: e, u: g.source(e), v: g.target(e), value: origValue },
  2357         minLen: g.edge(e).minLen
  2358       };
  2361     // Do not reverse edges for self-loops.
  2362     if (origValue.selfLoop) {
  2363       reverse = false;
  2366     if (reverse) {
  2367       // Ensure that all edges from max are reversed
  2368       g.addEdge(null, g.target(e), newU, value);
  2369       value.reversed = true;
  2370     } else {
  2371       g.addEdge(null, newU, g.target(e), value);
  2373   });
  2376 function addLightEdgesFromMinNode(g, sg, minNode) {
  2377   if (minNode !== undefined) {
  2378     g.children(sg).forEach(function(u) {
  2379       // The dummy check ensures we don't add an edge if the node is involved
  2380       // in a self loop or sideways edge.
  2381       if (u !== minNode && !g.outEdges(minNode, u).length && !g.node(u).dummy) {
  2382         g.addEdge(null, minNode, u, { minLen: 0 });
  2384     });
  2388 function addLightEdgesToMaxNode(g, sg, maxNode) {
  2389   if (maxNode !== undefined) {
  2390     g.children(sg).forEach(function(u) {
  2391       // The dummy check ensures we don't add an edge if the node is involved
  2392       // in a self loop or sideways edge.
  2393       if (u !== maxNode && !g.outEdges(u, maxNode).length && !g.node(u).dummy) {
  2394         g.addEdge(null, u, maxNode, { minLen: 0 });
  2396     });
  2400 /*
  2401  * This function "relaxes" the constraints applied previously by the "apply"
  2402  * function. It expands any nodes that were collapsed and assigns the rank of
  2403  * the collapsed node to each of the expanded nodes. It also restores the
  2404  * original edges and removes any dummy edges pointing at the collapsed nodes.
  2406  * Note that the process of removing collapsed nodes also removes dummy edges
  2407  * automatically.
  2408  */
  2409 exports.relax = function(g) {
  2410   // Save original edges
  2411   var originalEdges = [];
  2412   g.eachEdge(function(e, u, v, value) {
  2413     var originalEdge = value.originalEdge;
  2414     if (originalEdge) {
  2415       originalEdges.push(originalEdge);
  2417   });
  2419   // Expand collapsed nodes
  2420   g.eachNode(function(u, value) {
  2421     var originalNodes = value.originalNodes;
  2422     if (originalNodes) {
  2423       originalNodes.forEach(function(originalNode) {
  2424         originalNode.value.rank = value.rank;
  2425         g.addNode(originalNode.u, originalNode.value);
  2426         g.parent(originalNode.u, originalNode.parent);
  2427       });
  2428       g.delNode(u);
  2430   });
  2432   // Restore original edges
  2433   originalEdges.forEach(function(edge) {
  2434     g.addEdge(edge.e, edge.u, edge.v, edge.value);
  2435   });
  2436 };
  2438 },{}],22:[function(require,module,exports){
  2439 /* jshint -W079 */
  2440 var Set = require('cp-data').Set,
  2441 /* jshint +W079 */
  2442     Digraph = require('graphlib').Digraph,
  2443     util = require('../util');
  2445 module.exports = feasibleTree;
  2447 /*
  2448  * Given an acyclic graph with each node assigned a `rank` attribute, this
  2449  * function constructs and returns a spanning tree. This function may reduce
  2450  * the length of some edges from the initial rank assignment while maintaining
  2451  * the `minLen` specified by each edge.
  2453  * Prerequisites:
  2455  * * The input graph is acyclic
  2456  * * Each node in the input graph has an assigned `rank` attribute
  2457  * * Each edge in the input graph has an assigned `minLen` attribute
  2459  * Outputs:
  2461  * A feasible spanning tree for the input graph (i.e. a spanning tree that
  2462  * respects each graph edge's `minLen` attribute) represented as a Digraph with
  2463  * a `root` attribute on graph.
  2465  * Nodes have the same id and value as that in the input graph.
  2467  * Edges in the tree have arbitrarily assigned ids. The attributes for edges
  2468  * include `reversed`. `reversed` indicates that the edge is a
  2469  * back edge in the input graph.
  2470  */
  2471 function feasibleTree(g) {
  2472   var remaining = new Set(g.nodes()),
  2473       tree = new Digraph();
  2475   if (remaining.size() === 1) {
  2476     var root = g.nodes()[0];
  2477     tree.addNode(root, {});
  2478     tree.graph({ root: root });
  2479     return tree;
  2482   function addTightEdges(v) {
  2483     var continueToScan = true;
  2484     g.predecessors(v).forEach(function(u) {
  2485       if (remaining.has(u) && !slack(g, u, v)) {
  2486         if (remaining.has(v)) {
  2487           tree.addNode(v, {});
  2488           remaining.remove(v);
  2489           tree.graph({ root: v });
  2492         tree.addNode(u, {});
  2493         tree.addEdge(null, u, v, { reversed: true });
  2494         remaining.remove(u);
  2495         addTightEdges(u);
  2496         continueToScan = false;
  2498     });
  2500     g.successors(v).forEach(function(w)  {
  2501       if (remaining.has(w) && !slack(g, v, w)) {
  2502         if (remaining.has(v)) {
  2503           tree.addNode(v, {});
  2504           remaining.remove(v);
  2505           tree.graph({ root: v });
  2508         tree.addNode(w, {});
  2509         tree.addEdge(null, v, w, {});
  2510         remaining.remove(w);
  2511         addTightEdges(w);
  2512         continueToScan = false;
  2514     });
  2515     return continueToScan;
  2518   function createTightEdge() {
  2519     var minSlack = Number.MAX_VALUE;
  2520     remaining.keys().forEach(function(v) {
  2521       g.predecessors(v).forEach(function(u) {
  2522         if (!remaining.has(u)) {
  2523           var edgeSlack = slack(g, u, v);
  2524           if (Math.abs(edgeSlack) < Math.abs(minSlack)) {
  2525             minSlack = -edgeSlack;
  2528       });
  2530       g.successors(v).forEach(function(w) {
  2531         if (!remaining.has(w)) {
  2532           var edgeSlack = slack(g, v, w);
  2533           if (Math.abs(edgeSlack) < Math.abs(minSlack)) {
  2534             minSlack = edgeSlack;
  2537       });
  2538     });
  2540     tree.eachNode(function(u) { g.node(u).rank -= minSlack; });
  2543   while (remaining.size()) {
  2544     var nodesToSearch = !tree.order() ? remaining.keys() : tree.nodes();
  2545     for (var i = 0, il = nodesToSearch.length;
  2546          i < il && addTightEdges(nodesToSearch[i]);
  2547          ++i);
  2548     if (remaining.size()) {
  2549       createTightEdge();
  2553   return tree;
  2556 function slack(g, u, v) {
  2557   var rankDiff = g.node(v).rank - g.node(u).rank;
  2558   var maxMinLen = util.max(g.outEdges(u, v)
  2559                             .map(function(e) { return g.edge(e).minLen; }));
  2560   return rankDiff - maxMinLen;
  2563 },{"../util":26,"cp-data":5,"graphlib":28}],23:[function(require,module,exports){
  2564 var util = require('../util'),
  2565     topsort = require('graphlib').alg.topsort;
  2567 module.exports = initRank;
  2569 /*
  2570  * Assigns a `rank` attribute to each node in the input graph and ensures that
  2571  * this rank respects the `minLen` attribute of incident edges.
  2573  * Prerequisites:
  2575  *  * The input graph must be acyclic
  2576  *  * Each edge in the input graph must have an assigned 'minLen' attribute
  2577  */
  2578 function initRank(g) {
  2579   var sorted = topsort(g);
  2581   sorted.forEach(function(u) {
  2582     var inEdges = g.inEdges(u);
  2583     if (inEdges.length === 0) {
  2584       g.node(u).rank = 0;
  2585       return;
  2588     var minLens = inEdges.map(function(e) {
  2589       return g.node(g.source(e)).rank + g.edge(e).minLen;
  2590     });
  2591     g.node(u).rank = util.max(minLens);
  2592   });
  2595 },{"../util":26,"graphlib":28}],24:[function(require,module,exports){
  2596 module.exports = {
  2597   slack: slack
  2598 };
  2600 /*
  2601  * A helper to calculate the slack between two nodes (`u` and `v`) given a
  2602  * `minLen` constraint. The slack represents how much the distance between `u`
  2603  * and `v` could shrink while maintaining the `minLen` constraint. If the value
  2604  * is negative then the constraint is currently violated.
  2606   This function requires that `u` and `v` are in `graph` and they both have a
  2607   `rank` attribute.
  2608  */
  2609 function slack(graph, u, v, minLen) {
  2610   return Math.abs(graph.node(u).rank - graph.node(v).rank) - minLen;
  2613 },{}],25:[function(require,module,exports){
  2614 var util = require('../util'),
  2615     rankUtil = require('./rankUtil');
  2617 module.exports = simplex;
  2619 function simplex(graph, spanningTree) {
  2620   // The network simplex algorithm repeatedly replaces edges of
  2621   // the spanning tree with negative cut values until no such
  2622   // edge exists.
  2623   initCutValues(graph, spanningTree);
  2624   while (true) {
  2625     var e = leaveEdge(spanningTree);
  2626     if (e === null) break;
  2627     var f = enterEdge(graph, spanningTree, e);
  2628     exchange(graph, spanningTree, e, f);
  2632 /*
  2633  * Set the cut values of edges in the spanning tree by a depth-first
  2634  * postorder traversal.  The cut value corresponds to the cost, in
  2635  * terms of a ranking's edge length sum, of lengthening an edge.
  2636  * Negative cut values typically indicate edges that would yield a
  2637  * smaller edge length sum if they were lengthened.
  2638  */
  2639 function initCutValues(graph, spanningTree) {
  2640   computeLowLim(spanningTree);
  2642   spanningTree.eachEdge(function(id, u, v, treeValue) {
  2643     treeValue.cutValue = 0;
  2644   });
  2646   // Propagate cut values up the tree.
  2647   function dfs(n) {
  2648     var children = spanningTree.successors(n);
  2649     for (var c in children) {
  2650       var child = children[c];
  2651       dfs(child);
  2653     if (n !== spanningTree.graph().root) {
  2654       setCutValue(graph, spanningTree, n);
  2657   dfs(spanningTree.graph().root);
  2660 /*
  2661  * Perform a DFS postorder traversal, labeling each node v with
  2662  * its traversal order 'lim(v)' and the minimum traversal number
  2663  * of any of its descendants 'low(v)'.  This provides an efficient
  2664  * way to test whether u is an ancestor of v since
  2665  * low(u) <= lim(v) <= lim(u) if and only if u is an ancestor.
  2666  */
  2667 function computeLowLim(tree) {
  2668   var postOrderNum = 0;
  2670   function dfs(n) {
  2671     var children = tree.successors(n);
  2672     var low = postOrderNum;
  2673     for (var c in children) {
  2674       var child = children[c];
  2675       dfs(child);
  2676       low = Math.min(low, tree.node(child).low);
  2678     tree.node(n).low = low;
  2679     tree.node(n).lim = postOrderNum++;
  2682   dfs(tree.graph().root);
  2685 /*
  2686  * To compute the cut value of the edge parent -> child, we consider
  2687  * it and any other graph edges to or from the child.
  2688  *          parent
  2689  *             |
  2690  *           child
  2691  *          /      \
  2692  *         u        v
  2693  */
  2694 function setCutValue(graph, tree, child) {
  2695   var parentEdge = tree.inEdges(child)[0];
  2697   // List of child's children in the spanning tree.
  2698   var grandchildren = [];
  2699   var grandchildEdges = tree.outEdges(child);
  2700   for (var gce in grandchildEdges) {
  2701     grandchildren.push(tree.target(grandchildEdges[gce]));
  2704   var cutValue = 0;
  2706   // TODO: Replace unit increment/decrement with edge weights.
  2707   var E = 0;    // Edges from child to grandchild's subtree.
  2708   var F = 0;    // Edges to child from grandchild's subtree.
  2709   var G = 0;    // Edges from child to nodes outside of child's subtree.
  2710   var H = 0;    // Edges from nodes outside of child's subtree to child.
  2712   // Consider all graph edges from child.
  2713   var outEdges = graph.outEdges(child);
  2714   var gc;
  2715   for (var oe in outEdges) {
  2716     var succ = graph.target(outEdges[oe]);
  2717     for (gc in grandchildren) {
  2718       if (inSubtree(tree, succ, grandchildren[gc])) {
  2719         E++;
  2722     if (!inSubtree(tree, succ, child)) {
  2723       G++;
  2727   // Consider all graph edges to child.
  2728   var inEdges = graph.inEdges(child);
  2729   for (var ie in inEdges) {
  2730     var pred = graph.source(inEdges[ie]);
  2731     for (gc in grandchildren) {
  2732       if (inSubtree(tree, pred, grandchildren[gc])) {
  2733         F++;
  2736     if (!inSubtree(tree, pred, child)) {
  2737       H++;
  2741   // Contributions depend on the alignment of the parent -> child edge
  2742   // and the child -> u or v edges.
  2743   var grandchildCutSum = 0;
  2744   for (gc in grandchildren) {
  2745     var cv = tree.edge(grandchildEdges[gc]).cutValue;
  2746     if (!tree.edge(grandchildEdges[gc]).reversed) {
  2747       grandchildCutSum += cv;
  2748     } else {
  2749       grandchildCutSum -= cv;
  2753   if (!tree.edge(parentEdge).reversed) {
  2754     cutValue += grandchildCutSum - E + F - G + H;
  2755   } else {
  2756     cutValue -= grandchildCutSum - E + F - G + H;
  2759   tree.edge(parentEdge).cutValue = cutValue;
  2762 /*
  2763  * Return whether n is a node in the subtree with the given
  2764  * root.
  2765  */
  2766 function inSubtree(tree, n, root) {
  2767   return (tree.node(root).low <= tree.node(n).lim &&
  2768           tree.node(n).lim <= tree.node(root).lim);
  2771 /*
  2772  * Return an edge from the tree with a negative cut value, or null if there
  2773  * is none.
  2774  */
  2775 function leaveEdge(tree) {
  2776   var edges = tree.edges();
  2777   for (var n in edges) {
  2778     var e = edges[n];
  2779     var treeValue = tree.edge(e);
  2780     if (treeValue.cutValue < 0) {
  2781       return e;
  2784   return null;
  2787 /*
  2788  * The edge e should be an edge in the tree, with an underlying edge
  2789  * in the graph, with a negative cut value.  Of the two nodes incident
  2790  * on the edge, take the lower one.  enterEdge returns an edge with
  2791  * minimum slack going from outside of that node's subtree to inside
  2792  * of that node's subtree.
  2793  */
  2794 function enterEdge(graph, tree, e) {
  2795   var source = tree.source(e);
  2796   var target = tree.target(e);
  2797   var lower = tree.node(target).lim < tree.node(source).lim ? target : source;
  2799   // Is the tree edge aligned with the graph edge?
  2800   var aligned = !tree.edge(e).reversed;
  2802   var minSlack = Number.POSITIVE_INFINITY;
  2803   var minSlackEdge;
  2804   if (aligned) {
  2805     graph.eachEdge(function(id, u, v, value) {
  2806       if (id !== e && inSubtree(tree, u, lower) && !inSubtree(tree, v, lower)) {
  2807         var slack = rankUtil.slack(graph, u, v, value.minLen);
  2808         if (slack < minSlack) {
  2809           minSlack = slack;
  2810           minSlackEdge = id;
  2813     });
  2814   } else {
  2815     graph.eachEdge(function(id, u, v, value) {
  2816       if (id !== e && !inSubtree(tree, u, lower) && inSubtree(tree, v, lower)) {
  2817         var slack = rankUtil.slack(graph, u, v, value.minLen);
  2818         if (slack < minSlack) {
  2819           minSlack = slack;
  2820           minSlackEdge = id;
  2823     });
  2826   if (minSlackEdge === undefined) {
  2827     var outside = [];
  2828     var inside = [];
  2829     graph.eachNode(function(id) {
  2830       if (!inSubtree(tree, id, lower)) {
  2831         outside.push(id);
  2832       } else {
  2833         inside.push(id);
  2835     });
  2836     throw new Error('No edge found from outside of tree to inside');
  2839   return minSlackEdge;
  2842 /*
  2843  * Replace edge e with edge f in the tree, recalculating the tree root,
  2844  * the nodes' low and lim properties and the edges' cut values.
  2845  */
  2846 function exchange(graph, tree, e, f) {
  2847   tree.delEdge(e);
  2848   var source = graph.source(f);
  2849   var target = graph.target(f);
  2851   // Redirect edges so that target is the root of its subtree.
  2852   function redirect(v) {
  2853     var edges = tree.inEdges(v);
  2854     for (var i in edges) {
  2855       var e = edges[i];
  2856       var u = tree.source(e);
  2857       var value = tree.edge(e);
  2858       redirect(u);
  2859       tree.delEdge(e);
  2860       value.reversed = !value.reversed;
  2861       tree.addEdge(e, v, u, value);
  2865   redirect(target);
  2867   var root = source;
  2868   var edges = tree.inEdges(root);
  2869   while (edges.length > 0) {
  2870     root = tree.source(edges[0]);
  2871     edges = tree.inEdges(root);
  2874   tree.graph().root = root;
  2876   tree.addEdge(null, source, target, {cutValue: 0});
  2878   initCutValues(graph, tree);
  2880   adjustRanks(graph, tree);
  2883 /*
  2884  * Reset the ranks of all nodes based on the current spanning tree.
  2885  * The rank of the tree's root remains unchanged, while all other
  2886  * nodes are set to the sum of minimum length constraints along
  2887  * the path from the root.
  2888  */
  2889 function adjustRanks(graph, tree) {
  2890   function dfs(p) {
  2891     var children = tree.successors(p);
  2892     children.forEach(function(c) {
  2893       var minLen = minimumLength(graph, p, c);
  2894       graph.node(c).rank = graph.node(p).rank + minLen;
  2895       dfs(c);
  2896     });
  2899   dfs(tree.graph().root);
  2902 /*
  2903  * If u and v are connected by some edges in the graph, return the
  2904  * minimum length of those edges, as a positive number if v succeeds
  2905  * u and as a negative number if v precedes u.
  2906  */
  2907 function minimumLength(graph, u, v) {
  2908   var outEdges = graph.outEdges(u, v);
  2909   if (outEdges.length > 0) {
  2910     return util.max(outEdges.map(function(e) {
  2911       return graph.edge(e).minLen;
  2912     }));
  2915   var inEdges = graph.inEdges(u, v);
  2916   if (inEdges.length > 0) {
  2917     return -util.max(inEdges.map(function(e) {
  2918       return graph.edge(e).minLen;
  2919     }));
  2923 },{"../util":26,"./rankUtil":24}],26:[function(require,module,exports){
  2924 /*
  2925  * Returns the smallest value in the array.
  2926  */
  2927 exports.min = function(values) {
  2928   return Math.min.apply(Math, values);
  2929 };
  2931 /*
  2932  * Returns the largest value in the array.
  2933  */
  2934 exports.max = function(values) {
  2935   return Math.max.apply(Math, values);
  2936 };
  2938 /*
  2939  * Returns `true` only if `f(x)` is `true` for all `x` in `xs`. Otherwise
  2940  * returns `false`. This function will return immediately if it finds a
  2941  * case where `f(x)` does not hold.
  2942  */
  2943 exports.all = function(xs, f) {
  2944   for (var i = 0; i < xs.length; ++i) {
  2945     if (!f(xs[i])) {
  2946       return false;
  2949   return true;
  2950 };
  2952 /*
  2953  * Accumulates the sum of elements in the given array using the `+` operator.
  2954  */
  2955 exports.sum = function(values) {
  2956   return values.reduce(function(acc, x) { return acc + x; }, 0);
  2957 };
  2959 /*
  2960  * Returns an array of all values in the given object.
  2961  */
  2962 exports.values = function(obj) {
  2963   return Object.keys(obj).map(function(k) { return obj[k]; });
  2964 };
  2966 exports.shuffle = function(array) {
  2967   for (i = array.length - 1; i > 0; --i) {
  2968     var j = Math.floor(Math.random() * (i + 1));
  2969     var aj = array[j];
  2970     array[j] = array[i];
  2971     array[i] = aj;
  2973 };
  2975 exports.propertyAccessor = function(self, config, field, setHook) {
  2976   return function(x) {
  2977     if (!arguments.length) return config[field];
  2978     config[field] = x;
  2979     if (setHook) setHook(x);
  2980     return self;
  2981   };
  2982 };
  2984 /*
  2985  * Given a layered, directed graph with `rank` and `order` node attributes,
  2986  * this function returns an array of ordered ranks. Each rank contains an array
  2987  * of the ids of the nodes in that rank in the order specified by the `order`
  2988  * attribute.
  2989  */
  2990 exports.ordering = function(g) {
  2991   var ordering = [];
  2992   g.eachNode(function(u, value) {
  2993     var rank = ordering[value.rank] || (ordering[value.rank] = []);
  2994     rank[value.order] = u;
  2995   });
  2996   return ordering;
  2997 };
  2999 /*
  3000  * A filter that can be used with `filterNodes` to get a graph that only
  3001  * includes nodes that do not contain others nodes.
  3002  */
  3003 exports.filterNonSubgraphs = function(g) {
  3004   return function(u) {
  3005     return g.children(u).length === 0;
  3006   };
  3007 };
  3009 /*
  3010  * Returns a new function that wraps `func` with a timer. The wrapper logs the
  3011  * time it takes to execute the function.
  3013  * The timer will be enabled provided `log.level >= 1`.
  3014  */
  3015 function time(name, func) {
  3016   return function() {
  3017     var start = new Date().getTime();
  3018     try {
  3019       return func.apply(null, arguments);
  3020     } finally {
  3021       log(1, name + ' time: ' + (new Date().getTime() - start) + 'ms');
  3023   };
  3025 time.enabled = false;
  3027 exports.time = time;
  3029 /*
  3030  * A global logger with the specification `log(level, message, ...)` that
  3031  * will log a message to the console if `log.level >= level`.
  3032  */
  3033 function log(level) {
  3034   if (log.level >= level) {
  3035     console.log.apply(console, Array.prototype.slice.call(arguments, 1));
  3038 log.level = 0;
  3040 exports.log = log;
  3042 },{}],27:[function(require,module,exports){
  3043 module.exports = '0.4.5';
  3045 },{}],28:[function(require,module,exports){
  3046 exports.Graph = require("./lib/Graph");
  3047 exports.Digraph = require("./lib/Digraph");
  3048 exports.CGraph = require("./lib/CGraph");
  3049 exports.CDigraph = require("./lib/CDigraph");
  3050 require("./lib/graph-converters");
  3052 exports.alg = {
  3053   isAcyclic: require("./lib/alg/isAcyclic"),
  3054   components: require("./lib/alg/components"),
  3055   dijkstra: require("./lib/alg/dijkstra"),
  3056   dijkstraAll: require("./lib/alg/dijkstraAll"),
  3057   findCycles: require("./lib/alg/findCycles"),
  3058   floydWarshall: require("./lib/alg/floydWarshall"),
  3059   postorder: require("./lib/alg/postorder"),
  3060   preorder: require("./lib/alg/preorder"),
  3061   prim: require("./lib/alg/prim"),
  3062   tarjan: require("./lib/alg/tarjan"),
  3063   topsort: require("./lib/alg/topsort")
  3064 };
  3066 exports.converter = {
  3067   json: require("./lib/converter/json.js")
  3068 };
  3070 var filter = require("./lib/filter");
  3071 exports.filter = {
  3072   all: filter.all,
  3073   nodesFromList: filter.nodesFromList
  3074 };
  3076 exports.version = require("./lib/version");
  3078 },{"./lib/CDigraph":30,"./lib/CGraph":31,"./lib/Digraph":32,"./lib/Graph":33,"./lib/alg/components":34,"./lib/alg/dijkstra":35,"./lib/alg/dijkstraAll":36,"./lib/alg/findCycles":37,"./lib/alg/floydWarshall":38,"./lib/alg/isAcyclic":39,"./lib/alg/postorder":40,"./lib/alg/preorder":41,"./lib/alg/prim":42,"./lib/alg/tarjan":43,"./lib/alg/topsort":44,"./lib/converter/json.js":46,"./lib/filter":47,"./lib/graph-converters":48,"./lib/version":50}],29:[function(require,module,exports){
  3079 /* jshint -W079 */
  3080 var Set = require("cp-data").Set;
  3081 /* jshint +W079 */
  3083 module.exports = BaseGraph;
  3085 function BaseGraph() {
  3086   // The value assigned to the graph itself.
  3087   this._value = undefined;
  3089   // Map of node id -> { id, value }
  3090   this._nodes = {};
  3092   // Map of edge id -> { id, u, v, value }
  3093   this._edges = {};
  3095   // Used to generate a unique id in the graph
  3096   this._nextId = 0;
  3099 // Number of nodes
  3100 BaseGraph.prototype.order = function() {
  3101   return Object.keys(this._nodes).length;
  3102 };
  3104 // Number of edges
  3105 BaseGraph.prototype.size = function() {
  3106   return Object.keys(this._edges).length;
  3107 };
  3109 // Accessor for graph level value
  3110 BaseGraph.prototype.graph = function(value) {
  3111   if (arguments.length === 0) {
  3112     return this._value;
  3114   this._value = value;
  3115 };
  3117 BaseGraph.prototype.hasNode = function(u) {
  3118   return u in this._nodes;
  3119 };
  3121 BaseGraph.prototype.node = function(u, value) {
  3122   var node = this._strictGetNode(u);
  3123   if (arguments.length === 1) {
  3124     return node.value;
  3126   node.value = value;
  3127 };
  3129 BaseGraph.prototype.nodes = function() {
  3130   var nodes = [];
  3131   this.eachNode(function(id) { nodes.push(id); });
  3132   return nodes;
  3133 };
  3135 BaseGraph.prototype.eachNode = function(func) {
  3136   for (var k in this._nodes) {
  3137     var node = this._nodes[k];
  3138     func(node.id, node.value);
  3140 };
  3142 BaseGraph.prototype.hasEdge = function(e) {
  3143   return e in this._edges;
  3144 };
  3146 BaseGraph.prototype.edge = function(e, value) {
  3147   var edge = this._strictGetEdge(e);
  3148   if (arguments.length === 1) {
  3149     return edge.value;
  3151   edge.value = value;
  3152 };
  3154 BaseGraph.prototype.edges = function() {
  3155   var es = [];
  3156   this.eachEdge(function(id) { es.push(id); });
  3157   return es;
  3158 };
  3160 BaseGraph.prototype.eachEdge = function(func) {
  3161   for (var k in this._edges) {
  3162     var edge = this._edges[k];
  3163     func(edge.id, edge.u, edge.v, edge.value);
  3165 };
  3167 BaseGraph.prototype.incidentNodes = function(e) {
  3168   var edge = this._strictGetEdge(e);
  3169   return [edge.u, edge.v];
  3170 };
  3172 BaseGraph.prototype.addNode = function(u, value) {
  3173   if (u === undefined || u === null) {
  3174     do {
  3175       u = "_" + (++this._nextId);
  3176     } while (this.hasNode(u));
  3177   } else if (this.hasNode(u)) {
  3178     throw new Error("Graph already has node '" + u + "'");
  3180   this._nodes[u] = { id: u, value: value };
  3181   return u;
  3182 };
  3184 BaseGraph.prototype.delNode = function(u) {
  3185   this._strictGetNode(u);
  3186   this.incidentEdges(u).forEach(function(e) { this.delEdge(e); }, this);
  3187   delete this._nodes[u];
  3188 };
  3190 // inMap and outMap are opposite sides of an incidence map. For example, for
  3191 // Graph these would both come from the _incidentEdges map, while for Digraph
  3192 // they would come from _inEdges and _outEdges.
  3193 BaseGraph.prototype._addEdge = function(e, u, v, value, inMap, outMap) {
  3194   this._strictGetNode(u);
  3195   this._strictGetNode(v);
  3197   if (e === undefined || e === null) {
  3198     do {
  3199       e = "_" + (++this._nextId);
  3200     } while (this.hasEdge(e));
  3202   else if (this.hasEdge(e)) {
  3203     throw new Error("Graph already has edge '" + e + "'");
  3206   this._edges[e] = { id: e, u: u, v: v, value: value };
  3207   addEdgeToMap(inMap[v], u, e);
  3208   addEdgeToMap(outMap[u], v, e);
  3210   return e;
  3211 };
  3213 // See note for _addEdge regarding inMap and outMap.
  3214 BaseGraph.prototype._delEdge = function(e, inMap, outMap) {
  3215   var edge = this._strictGetEdge(e);
  3216   delEdgeFromMap(inMap[edge.v], edge.u, e);
  3217   delEdgeFromMap(outMap[edge.u], edge.v, e);
  3218   delete this._edges[e];
  3219 };
  3221 BaseGraph.prototype.copy = function() {
  3222   var copy = new this.constructor();
  3223   copy.graph(this.graph());
  3224   this.eachNode(function(u, value) { copy.addNode(u, value); });
  3225   this.eachEdge(function(e, u, v, value) { copy.addEdge(e, u, v, value); });
  3226   copy._nextId = this._nextId;
  3227   return copy;
  3228 };
  3230 BaseGraph.prototype.filterNodes = function(filter) {
  3231   var copy = new this.constructor();
  3232   copy.graph(this.graph());
  3233   this.eachNode(function(u, value) {
  3234     if (filter(u)) {
  3235       copy.addNode(u, value);
  3237   });
  3238   this.eachEdge(function(e, u, v, value) {
  3239     if (copy.hasNode(u) && copy.hasNode(v)) {
  3240       copy.addEdge(e, u, v, value);
  3242   });
  3243   return copy;
  3244 };
  3246 BaseGraph.prototype._strictGetNode = function(u) {
  3247   var node = this._nodes[u];
  3248   if (node === undefined) {
  3249     throw new Error("Node '" + u + "' is not in graph");
  3251   return node;
  3252 };
  3254 BaseGraph.prototype._strictGetEdge = function(e) {
  3255   var edge = this._edges[e];
  3256   if (edge === undefined) {
  3257     throw new Error("Edge '" + e + "' is not in graph");
  3259   return edge;
  3260 };
  3262 function addEdgeToMap(map, v, e) {
  3263   (map[v] || (map[v] = new Set())).add(e);
  3266 function delEdgeFromMap(map, v, e) {
  3267   var vEntry = map[v];
  3268   vEntry.remove(e);
  3269   if (vEntry.size() === 0) {
  3270     delete map[v];
  3275 },{"cp-data":5}],30:[function(require,module,exports){
  3276 var Digraph = require("./Digraph"),
  3277     compoundify = require("./compoundify");
  3279 var CDigraph = compoundify(Digraph);
  3281 module.exports = CDigraph;
  3283 CDigraph.fromDigraph = function(src) {
  3284   var g = new CDigraph(),
  3285       graphValue = src.graph();
  3287   if (graphValue !== undefined) {
  3288     g.graph(graphValue);
  3291   src.eachNode(function(u, value) {
  3292     if (value === undefined) {
  3293       g.addNode(u);
  3294     } else {
  3295       g.addNode(u, value);
  3297   });
  3298   src.eachEdge(function(e, u, v, value) {
  3299     if (value === undefined) {
  3300       g.addEdge(null, u, v);
  3301     } else {
  3302       g.addEdge(null, u, v, value);
  3304   });
  3305   return g;
  3306 };
  3308 CDigraph.prototype.toString = function() {
  3309   return "CDigraph " + JSON.stringify(this, null, 2);
  3310 };
  3312 },{"./Digraph":32,"./compoundify":45}],31:[function(require,module,exports){
  3313 var Graph = require("./Graph"),
  3314     compoundify = require("./compoundify");
  3316 var CGraph = compoundify(Graph);
  3318 module.exports = CGraph;
  3320 CGraph.fromGraph = function(src) {
  3321   var g = new CGraph(),
  3322       graphValue = src.graph();
  3324   if (graphValue !== undefined) {
  3325     g.graph(graphValue);
  3328   src.eachNode(function(u, value) {
  3329     if (value === undefined) {
  3330       g.addNode(u);
  3331     } else {
  3332       g.addNode(u, value);
  3334   });
  3335   src.eachEdge(function(e, u, v, value) {
  3336     if (value === undefined) {
  3337       g.addEdge(null, u, v);
  3338     } else {
  3339       g.addEdge(null, u, v, value);
  3341   });
  3342   return g;
  3343 };
  3345 CGraph.prototype.toString = function() {
  3346   return "CGraph " + JSON.stringify(this, null, 2);
  3347 };
  3349 },{"./Graph":33,"./compoundify":45}],32:[function(require,module,exports){
  3350 /*
  3351  * This file is organized with in the following order:
  3353  * Exports
  3354  * Graph constructors
  3355  * Graph queries (e.g. nodes(), edges()
  3356  * Graph mutators
  3357  * Helper functions
  3358  */
  3360 var util = require("./util"),
  3361     BaseGraph = require("./BaseGraph"),
  3362 /* jshint -W079 */
  3363     Set = require("cp-data").Set;
  3364 /* jshint +W079 */
  3366 module.exports = Digraph;
  3368 /*
  3369  * Constructor to create a new directed multi-graph.
  3370  */
  3371 function Digraph() {
  3372   BaseGraph.call(this);
  3374   /*! Map of sourceId -> {targetId -> Set of edge ids} */
  3375   this._inEdges = {};
  3377   /*! Map of targetId -> {sourceId -> Set of edge ids} */
  3378   this._outEdges = {};
  3381 Digraph.prototype = new BaseGraph();
  3382 Digraph.prototype.constructor = Digraph;
  3384 /*
  3385  * Always returns `true`.
  3386  */
  3387 Digraph.prototype.isDirected = function() {
  3388   return true;
  3389 };
  3391 /*
  3392  * Returns all successors of the node with the id `u`. That is, all nodes
  3393  * that have the node `u` as their source are returned.
  3395  * If no node `u` exists in the graph this function throws an Error.
  3397  * @param {String} u a node id
  3398  */
  3399 Digraph.prototype.successors = function(u) {
  3400   this._strictGetNode(u);
  3401   return Object.keys(this._outEdges[u])
  3402                .map(function(v) { return this._nodes[v].id; }, this);
  3403 };
  3405 /*
  3406  * Returns all predecessors of the node with the id `u`. That is, all nodes
  3407  * that have the node `u` as their target are returned.
  3409  * If no node `u` exists in the graph this function throws an Error.
  3411  * @param {String} u a node id
  3412  */
  3413 Digraph.prototype.predecessors = function(u) {
  3414   this._strictGetNode(u);
  3415   return Object.keys(this._inEdges[u])
  3416                .map(function(v) { return this._nodes[v].id; }, this);
  3417 };
  3419 /*
  3420  * Returns all nodes that are adjacent to the node with the id `u`. In other
  3421  * words, this function returns the set of all successors and predecessors of
  3422  * node `u`.
  3424  * @param {String} u a node id
  3425  */
  3426 Digraph.prototype.neighbors = function(u) {
  3427   return Set.union([this.successors(u), this.predecessors(u)]).keys();
  3428 };
  3430 /*
  3431  * Returns all nodes in the graph that have no in-edges.
  3432  */
  3433 Digraph.prototype.sources = function() {
  3434   var self = this;
  3435   return this._filterNodes(function(u) {
  3436     // This could have better space characteristics if we had an inDegree function.
  3437     return self.inEdges(u).length === 0;
  3438   });
  3439 };
  3441 /*
  3442  * Returns all nodes in the graph that have no out-edges.
  3443  */
  3444 Digraph.prototype.sinks = function() {
  3445   var self = this;
  3446   return this._filterNodes(function(u) {
  3447     // This could have better space characteristics if we have an outDegree function.
  3448     return self.outEdges(u).length === 0;
  3449   });
  3450 };
  3452 /*
  3453  * Returns the source node incident on the edge identified by the id `e`. If no
  3454  * such edge exists in the graph this function throws an Error.
  3456  * @param {String} e an edge id
  3457  */
  3458 Digraph.prototype.source = function(e) {
  3459   return this._strictGetEdge(e).u;
  3460 };
  3462 /*
  3463  * Returns the target node incident on the edge identified by the id `e`. If no
  3464  * such edge exists in the graph this function throws an Error.
  3466  * @param {String} e an edge id
  3467  */
  3468 Digraph.prototype.target = function(e) {
  3469   return this._strictGetEdge(e).v;
  3470 };
  3472 /*
  3473  * Returns an array of ids for all edges in the graph that have the node
  3474  * `target` as their target. If the node `target` is not in the graph this
  3475  * function raises an Error.
  3477  * Optionally a `source` node can also be specified. This causes the results
  3478  * to be filtered such that only edges from `source` to `target` are included.
  3479  * If the node `source` is specified but is not in the graph then this function
  3480  * raises an Error.
  3482  * @param {String} target the target node id
  3483  * @param {String} [source] an optional source node id
  3484  */
  3485 Digraph.prototype.inEdges = function(target, source) {
  3486   this._strictGetNode(target);
  3487   var results = Set.union(util.values(this._inEdges[target])).keys();
  3488   if (arguments.length > 1) {
  3489     this._strictGetNode(source);
  3490     results = results.filter(function(e) { return this.source(e) === source; }, this);
  3492   return results;
  3493 };
  3495 /*
  3496  * Returns an array of ids for all edges in the graph that have the node
  3497  * `source` as their source. If the node `source` is not in the graph this
  3498  * function raises an Error.
  3500  * Optionally a `target` node may also be specified. This causes the results
  3501  * to be filtered such that only edges from `source` to `target` are included.
  3502  * If the node `target` is specified but is not in the graph then this function
  3503  * raises an Error.
  3505  * @param {String} source the source node id
  3506  * @param {String} [target] an optional target node id
  3507  */
  3508 Digraph.prototype.outEdges = function(source, target) {
  3509   this._strictGetNode(source);
  3510   var results = Set.union(util.values(this._outEdges[source])).keys();
  3511   if (arguments.length > 1) {
  3512     this._strictGetNode(target);
  3513     results = results.filter(function(e) { return this.target(e) === target; }, this);
  3515   return results;
  3516 };
  3518 /*
  3519  * Returns an array of ids for all edges in the graph that have the `u` as
  3520  * their source or their target. If the node `u` is not in the graph this
  3521  * function raises an Error.
  3523  * Optionally a `v` node may also be specified. This causes the results to be
  3524  * filtered such that only edges between `u` and `v` - in either direction -
  3525  * are included. IF the node `v` is specified but not in the graph then this
  3526  * function raises an Error.
  3528  * @param {String} u the node for which to find incident edges
  3529  * @param {String} [v] option node that must be adjacent to `u`
  3530  */
  3531 Digraph.prototype.incidentEdges = function(u, v) {
  3532   if (arguments.length > 1) {
  3533     return Set.union([this.outEdges(u, v), this.outEdges(v, u)]).keys();
  3534   } else {
  3535     return Set.union([this.inEdges(u), this.outEdges(u)]).keys();
  3537 };
  3539 /*
  3540  * Returns a string representation of this graph.
  3541  */
  3542 Digraph.prototype.toString = function() {
  3543   return "Digraph " + JSON.stringify(this, null, 2);
  3544 };
  3546 /*
  3547  * Adds a new node with the id `u` to the graph and assigns it the value
  3548  * `value`. If a node with the id is already a part of the graph this function
  3549  * throws an Error.
  3551  * @param {String} u a node id
  3552  * @param {Object} [value] an optional value to attach to the node
  3553  */
  3554 Digraph.prototype.addNode = function(u, value) {
  3555   u = BaseGraph.prototype.addNode.call(this, u, value);
  3556   this._inEdges[u] = {};
  3557   this._outEdges[u] = {};
  3558   return u;
  3559 };
  3561 /*
  3562  * Removes a node from the graph that has the id `u`. Any edges incident on the
  3563  * node are also removed. If the graph does not contain a node with the id this
  3564  * function will throw an Error.
  3566  * @param {String} u a node id
  3567  */
  3568 Digraph.prototype.delNode = function(u) {
  3569   BaseGraph.prototype.delNode.call(this, u);
  3570   delete this._inEdges[u];
  3571   delete this._outEdges[u];
  3572 };
  3574 /*
  3575  * Adds a new edge to the graph with the id `e` from a node with the id `source`
  3576  * to a node with an id `target` and assigns it the value `value`. This graph
  3577  * allows more than one edge from `source` to `target` as long as the id `e`
  3578  * is unique in the set of edges. If `e` is `null` the graph will assign a
  3579  * unique identifier to the edge.
  3581  * If `source` or `target` are not present in the graph this function will
  3582  * throw an Error.
  3584  * @param {String} [e] an edge id
  3585  * @param {String} source the source node id
  3586  * @param {String} target the target node id
  3587  * @param {Object} [value] an optional value to attach to the edge
  3588  */
  3589 Digraph.prototype.addEdge = function(e, source, target, value) {
  3590   return BaseGraph.prototype._addEdge.call(this, e, source, target, value,
  3591                                            this._inEdges, this._outEdges);
  3592 };
  3594 /*
  3595  * Removes an edge in the graph with the id `e`. If no edge in the graph has
  3596  * the id `e` this function will throw an Error.
  3598  * @param {String} e an edge id
  3599  */
  3600 Digraph.prototype.delEdge = function(e) {
  3601   BaseGraph.prototype._delEdge.call(this, e, this._inEdges, this._outEdges);
  3602 };
  3604 // Unlike BaseGraph.filterNodes, this helper just returns nodes that
  3605 // satisfy a predicate.
  3606 Digraph.prototype._filterNodes = function(pred) {
  3607   var filtered = [];
  3608   this.eachNode(function(u) {
  3609     if (pred(u)) {
  3610       filtered.push(u);
  3612   });
  3613   return filtered;
  3614 };
  3617 },{"./BaseGraph":29,"./util":49,"cp-data":5}],33:[function(require,module,exports){
  3618 /*
  3619  * This file is organized with in the following order:
  3621  * Exports
  3622  * Graph constructors
  3623  * Graph queries (e.g. nodes(), edges()
  3624  * Graph mutators
  3625  * Helper functions
  3626  */
  3628 var util = require("./util"),
  3629     BaseGraph = require("./BaseGraph"),
  3630 /* jshint -W079 */
  3631     Set = require("cp-data").Set;
  3632 /* jshint +W079 */
  3634 module.exports = Graph;
  3636 /*
  3637  * Constructor to create a new undirected multi-graph.
  3638  */
  3639 function Graph() {
  3640   BaseGraph.call(this);
  3642   /*! Map of nodeId -> { otherNodeId -> Set of edge ids } */
  3643   this._incidentEdges = {};
  3646 Graph.prototype = new BaseGraph();
  3647 Graph.prototype.constructor = Graph;
  3649 /*
  3650  * Always returns `false`.
  3651  */
  3652 Graph.prototype.isDirected = function() {
  3653   return false;
  3654 };
  3656 /*
  3657  * Returns all nodes that are adjacent to the node with the id `u`.
  3659  * @param {String} u a node id
  3660  */
  3661 Graph.prototype.neighbors = function(u) {
  3662   this._strictGetNode(u);
  3663   return Object.keys(this._incidentEdges[u])
  3664                .map(function(v) { return this._nodes[v].id; }, this);
  3665 };
  3667 /*
  3668  * Returns an array of ids for all edges in the graph that are incident on `u`.
  3669  * If the node `u` is not in the graph this function raises an Error.
  3671  * Optionally a `v` node may also be specified. This causes the results to be
  3672  * filtered such that only edges between `u` and `v` are included. If the node
  3673  * `v` is specified but not in the graph then this function raises an Error.
  3675  * @param {String} u the node for which to find incident edges
  3676  * @param {String} [v] option node that must be adjacent to `u`
  3677  */
  3678 Graph.prototype.incidentEdges = function(u, v) {
  3679   this._strictGetNode(u);
  3680   if (arguments.length > 1) {
  3681     this._strictGetNode(v);
  3682     return v in this._incidentEdges[u] ? this._incidentEdges[u][v].keys() : [];
  3683   } else {
  3684     return Set.union(util.values(this._incidentEdges[u])).keys();
  3686 };
  3688 /*
  3689  * Returns a string representation of this graph.
  3690  */
  3691 Graph.prototype.toString = function() {
  3692   return "Graph " + JSON.stringify(this, null, 2);
  3693 };
  3695 /*
  3696  * Adds a new node with the id `u` to the graph and assigns it the value
  3697  * `value`. If a node with the id is already a part of the graph this function
  3698  * throws an Error.
  3700  * @param {String} u a node id
  3701  * @param {Object} [value] an optional value to attach to the node
  3702  */
  3703 Graph.prototype.addNode = function(u, value) {
  3704   u = BaseGraph.prototype.addNode.call(this, u, value);
  3705   this._incidentEdges[u] = {};
  3706   return u;
  3707 };
  3709 /*
  3710  * Removes a node from the graph that has the id `u`. Any edges incident on the
  3711  * node are also removed. If the graph does not contain a node with the id this
  3712  * function will throw an Error.
  3714  * @param {String} u a node id
  3715  */
  3716 Graph.prototype.delNode = function(u) {
  3717   BaseGraph.prototype.delNode.call(this, u);
  3718   delete this._incidentEdges[u];
  3719 };
  3721 /*
  3722  * Adds a new edge to the graph with the id `e` between a node with the id `u`
  3723  * and a node with an id `v` and assigns it the value `value`. This graph
  3724  * allows more than one edge between `u` and `v` as long as the id `e`
  3725  * is unique in the set of edges. If `e` is `null` the graph will assign a
  3726  * unique identifier to the edge.
  3728  * If `u` or `v` are not present in the graph this function will throw an
  3729  * Error.
  3731  * @param {String} [e] an edge id
  3732  * @param {String} u the node id of one of the adjacent nodes
  3733  * @param {String} v the node id of the other adjacent node
  3734  * @param {Object} [value] an optional value to attach to the edge
  3735  */
  3736 Graph.prototype.addEdge = function(e, u, v, value) {
  3737   return BaseGraph.prototype._addEdge.call(this, e, u, v, value,
  3738                                            this._incidentEdges, this._incidentEdges);
  3739 };
  3741 /*
  3742  * Removes an edge in the graph with the id `e`. If no edge in the graph has
  3743  * the id `e` this function will throw an Error.
  3745  * @param {String} e an edge id
  3746  */
  3747 Graph.prototype.delEdge = function(e) {
  3748   BaseGraph.prototype._delEdge.call(this, e, this._incidentEdges, this._incidentEdges);
  3749 };
  3752 },{"./BaseGraph":29,"./util":49,"cp-data":5}],34:[function(require,module,exports){
  3753 /* jshint -W079 */
  3754 var Set = require("cp-data").Set;
  3755 /* jshint +W079 */
  3757 module.exports = components;
  3759 /**
  3760  * Finds all [connected components][] in a graph and returns an array of these
  3761  * components. Each component is itself an array that contains the ids of nodes
  3762  * in the component.
  3764  * This function only works with undirected Graphs.
  3766  * [connected components]: http://en.wikipedia.org/wiki/Connected_component_(graph_theory)
  3768  * @param {Graph} g the graph to search for components
  3769  */
  3770 function components(g) {
  3771   var results = [];
  3772   var visited = new Set();
  3774   function dfs(v, component) {
  3775     if (!visited.has(v)) {
  3776       visited.add(v);
  3777       component.push(v);
  3778       g.neighbors(v).forEach(function(w) {
  3779         dfs(w, component);
  3780       });
  3784   g.nodes().forEach(function(v) {
  3785     var component = [];
  3786     dfs(v, component);
  3787     if (component.length > 0) {
  3788       results.push(component);
  3790   });
  3792   return results;
  3795 },{"cp-data":5}],35:[function(require,module,exports){
  3796 var PriorityQueue = require("cp-data").PriorityQueue;
  3798 module.exports = dijkstra;
  3800 /**
  3801  * This function is an implementation of [Dijkstra's algorithm][] which finds
  3802  * the shortest path from **source** to all other nodes in **g**. This
  3803  * function returns a map of `u -> { distance, predecessor }`. The distance
  3804  * property holds the sum of the weights from **source** to `u` along the
  3805  * shortest path or `Number.POSITIVE_INFINITY` if there is no path from
  3806  * **source**. The predecessor property can be used to walk the individual
  3807  * elements of the path from **source** to **u** in reverse order.
  3809  * This function takes an optional `weightFunc(e)` which returns the
  3810  * weight of the edge `e`. If no weightFunc is supplied then each edge is
  3811  * assumed to have a weight of 1. This function throws an Error if any of
  3812  * the traversed edges have a negative edge weight.
  3814  * This function takes an optional `incidentFunc(u)` which returns the ids of
  3815  * all edges incident to the node `u` for the purposes of shortest path
  3816  * traversal. By default this function uses the `g.outEdges` for Digraphs and
  3817  * `g.incidentEdges` for Graphs.
  3819  * This function takes `O((|E| + |V|) * log |V|)` time.
  3821  * [Dijkstra's algorithm]: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
  3823  * @param {Graph} g the graph to search for shortest paths from **source**
  3824  * @param {Object} source the source from which to start the search
  3825  * @param {Function} [weightFunc] optional weight function
  3826  * @param {Function} [incidentFunc] optional incident function
  3827  */
  3828 function dijkstra(g, source, weightFunc, incidentFunc) {
  3829   var results = {},
  3830       pq = new PriorityQueue();
  3832   function updateNeighbors(e) {
  3833     var incidentNodes = g.incidentNodes(e),
  3834         v = incidentNodes[0] !== u ? incidentNodes[0] : incidentNodes[1],
  3835         vEntry = results[v],
  3836         weight = weightFunc(e),
  3837         distance = uEntry.distance + weight;
  3839     if (weight < 0) {
  3840       throw new Error("dijkstra does not allow negative edge weights. Bad edge: " + e + " Weight: " + weight);
  3843     if (distance < vEntry.distance) {
  3844       vEntry.distance = distance;
  3845       vEntry.predecessor = u;
  3846       pq.decrease(v, distance);
  3850   weightFunc = weightFunc || function() { return 1; };
  3851   incidentFunc = incidentFunc || (g.isDirected()
  3852       ? function(u) { return g.outEdges(u); }
  3853       : function(u) { return g.incidentEdges(u); });
  3855   g.eachNode(function(u) {
  3856     var distance = u === source ? 0 : Number.POSITIVE_INFINITY;
  3857     results[u] = { distance: distance };
  3858     pq.add(u, distance);
  3859   });
  3861   var u, uEntry;
  3862   while (pq.size() > 0) {
  3863     u = pq.removeMin();
  3864     uEntry = results[u];
  3865     if (uEntry.distance === Number.POSITIVE_INFINITY) {
  3866       break;
  3869     incidentFunc(u).forEach(updateNeighbors);
  3872   return results;
  3875 },{"cp-data":5}],36:[function(require,module,exports){
  3876 var dijkstra = require("./dijkstra");
  3878 module.exports = dijkstraAll;
  3880 /**
  3881  * This function finds the shortest path from each node to every other
  3882  * reachable node in the graph. It is similar to [alg.dijkstra][], but
  3883  * instead of returning a single-source array, it returns a mapping of
  3884  * of `source -> alg.dijksta(g, source, weightFunc, incidentFunc)`.
  3886  * This function takes an optional `weightFunc(e)` which returns the
  3887  * weight of the edge `e`. If no weightFunc is supplied then each edge is
  3888  * assumed to have a weight of 1. This function throws an Error if any of
  3889  * the traversed edges have a negative edge weight.
  3891  * This function takes an optional `incidentFunc(u)` which returns the ids of
  3892  * all edges incident to the node `u` for the purposes of shortest path
  3893  * traversal. By default this function uses the `outEdges` function on the
  3894  * supplied graph.
  3896  * This function takes `O(|V| * (|E| + |V|) * log |V|)` time.
  3898  * [alg.dijkstra]: dijkstra.js.html#dijkstra
  3900  * @param {Graph} g the graph to search for shortest paths from **source**
  3901  * @param {Function} [weightFunc] optional weight function
  3902  * @param {Function} [incidentFunc] optional incident function
  3903  */
  3904 function dijkstraAll(g, weightFunc, incidentFunc) {
  3905   var results = {};
  3906   g.eachNode(function(u) {
  3907     results[u] = dijkstra(g, u, weightFunc, incidentFunc);
  3908   });
  3909   return results;
  3912 },{"./dijkstra":35}],37:[function(require,module,exports){
  3913 var tarjan = require("./tarjan");
  3915 module.exports = findCycles;
  3917 /*
  3918  * Given a Digraph **g** this function returns all nodes that are part of a
  3919  * cycle. Since there may be more than one cycle in a graph this function
  3920  * returns an array of these cycles, where each cycle is itself represented
  3921  * by an array of ids for each node involved in that cycle.
  3923  * [alg.isAcyclic][] is more efficient if you only need to determine whether
  3924  * a graph has a cycle or not.
  3926  * [alg.isAcyclic]: isAcyclic.js.html#isAcyclic
  3928  * @param {Digraph} g the graph to search for cycles.
  3929  */
  3930 function findCycles(g) {
  3931   return tarjan(g).filter(function(cmpt) { return cmpt.length > 1; });
  3934 },{"./tarjan":43}],38:[function(require,module,exports){
  3935 module.exports = floydWarshall;
  3937 /**
  3938  * This function is an implementation of the [Floyd-Warshall algorithm][],
  3939  * which finds the shortest path from each node to every other reachable node
  3940  * in the graph. It is similar to [alg.dijkstraAll][], but it handles negative
  3941  * edge weights and is more efficient for some types of graphs. This function
  3942  * returns a map of `source -> { target -> { distance, predecessor }`. The
  3943  * distance property holds the sum of the weights from `source` to `target`
  3944  * along the shortest path of `Number.POSITIVE_INFINITY` if there is no path
  3945  * from `source`. The predecessor property can be used to walk the individual
  3946  * elements of the path from `source` to `target` in reverse order.
  3948  * This function takes an optional `weightFunc(e)` which returns the
  3949  * weight of the edge `e`. If no weightFunc is supplied then each edge is
  3950  * assumed to have a weight of 1.
  3952  * This function takes an optional `incidentFunc(u)` which returns the ids of
  3953  * all edges incident to the node `u` for the purposes of shortest path
  3954  * traversal. By default this function uses the `outEdges` function on the
  3955  * supplied graph.
  3957  * This algorithm takes O(|V|^3) time.
  3959  * [Floyd-Warshall algorithm]: https://en.wikipedia.org/wiki/Floyd-Warshall_algorithm
  3960  * [alg.dijkstraAll]: dijkstraAll.js.html#dijkstraAll
  3962  * @param {Graph} g the graph to search for shortest paths from **source**
  3963  * @param {Function} [weightFunc] optional weight function
  3964  * @param {Function} [incidentFunc] optional incident function
  3965  */
  3966 function floydWarshall(g, weightFunc, incidentFunc) {
  3967   var results = {},
  3968       nodes = g.nodes();
  3970   weightFunc = weightFunc || function() { return 1; };
  3971   incidentFunc = incidentFunc || (g.isDirected()
  3972       ? function(u) { return g.outEdges(u); }
  3973       : function(u) { return g.incidentEdges(u); });
  3975   nodes.forEach(function(u) {
  3976     results[u] = {};
  3977     results[u][u] = { distance: 0 };
  3978     nodes.forEach(function(v) {
  3979       if (u !== v) {
  3980         results[u][v] = { distance: Number.POSITIVE_INFINITY };
  3982     });
  3983     incidentFunc(u).forEach(function(e) {
  3984       var incidentNodes = g.incidentNodes(e),
  3985           v = incidentNodes[0] !== u ? incidentNodes[0] : incidentNodes[1],
  3986           d = weightFunc(e);
  3987       if (d < results[u][v].distance) {
  3988         results[u][v] = { distance: d, predecessor: u };
  3990     });
  3991   });
  3993   nodes.forEach(function(k) {
  3994     var rowK = results[k];
  3995     nodes.forEach(function(i) {
  3996       var rowI = results[i];
  3997       nodes.forEach(function(j) {
  3998         var ik = rowI[k];
  3999         var kj = rowK[j];
  4000         var ij = rowI[j];
  4001         var altDistance = ik.distance + kj.distance;
  4002         if (altDistance < ij.distance) {
  4003           ij.distance = altDistance;
  4004           ij.predecessor = kj.predecessor;
  4006       });
  4007     });
  4008   });
  4010   return results;
  4013 },{}],39:[function(require,module,exports){
  4014 var topsort = require("./topsort");
  4016 module.exports = isAcyclic;
  4018 /*
  4019  * Given a Digraph **g** this function returns `true` if the graph has no
  4020  * cycles and returns `false` if it does. This algorithm returns as soon as it
  4021  * detects the first cycle.
  4023  * Use [alg.findCycles][] if you need the actual list of cycles in a graph.
  4025  * [alg.findCycles]: findCycles.js.html#findCycles
  4027  * @param {Digraph} g the graph to test for cycles
  4028  */
  4029 function isAcyclic(g) {
  4030   try {
  4031     topsort(g);
  4032   } catch (e) {
  4033     if (e instanceof topsort.CycleException) return false;
  4034     throw e;
  4036   return true;
  4039 },{"./topsort":44}],40:[function(require,module,exports){
  4040 /* jshint -W079 */
  4041 var Set = require("cp-data").Set;
  4042 /* jshint +W079 */
  4044 module.exports = postorder;
  4046 // Postorder traversal of g, calling f for each visited node. Assumes the graph
  4047 // is a tree.
  4048 function postorder(g, root, f) {
  4049   var visited = new Set();
  4050   if (g.isDirected()) {
  4051     throw new Error("This function only works for undirected graphs");
  4053   function dfs(u, prev) {
  4054     if (visited.has(u)) {
  4055       throw new Error("The input graph is not a tree: " + g);
  4057     visited.add(u);
  4058     g.neighbors(u).forEach(function(v) {
  4059       if (v !== prev) dfs(v, u);
  4060     });
  4061     f(u);
  4063   dfs(root);
  4066 },{"cp-data":5}],41:[function(require,module,exports){
  4067 /* jshint -W079 */
  4068 var Set = require("cp-data").Set;
  4069 /* jshint +W079 */
  4071 module.exports = preorder;
  4073 // Preorder traversal of g, calling f for each visited node. Assumes the graph
  4074 // is a tree.
  4075 function preorder(g, root, f) {
  4076   var visited = new Set();
  4077   if (g.isDirected()) {
  4078     throw new Error("This function only works for undirected graphs");
  4080   function dfs(u, prev) {
  4081     if (visited.has(u)) {
  4082       throw new Error("The input graph is not a tree: " + g);
  4084     visited.add(u);
  4085     f(u);
  4086     g.neighbors(u).forEach(function(v) {
  4087       if (v !== prev) dfs(v, u);
  4088     });
  4090   dfs(root);
  4093 },{"cp-data":5}],42:[function(require,module,exports){
  4094 var Graph = require("../Graph"),
  4095     PriorityQueue = require("cp-data").PriorityQueue;
  4097 module.exports = prim;
  4099 /**
  4100  * [Prim's algorithm][] takes a connected undirected graph and generates a
  4101  * [minimum spanning tree][]. This function returns the minimum spanning
  4102  * tree as an undirected graph. This algorithm is derived from the description
  4103  * in "Introduction to Algorithms", Third Edition, Cormen, et al., Pg 634.
  4105  * This function takes a `weightFunc(e)` which returns the weight of the edge
  4106  * `e`. It throws an Error if the graph is not connected.
  4108  * This function takes `O(|E| log |V|)` time.
  4110  * [Prim's algorithm]: https://en.wikipedia.org/wiki/Prim's_algorithm
  4111  * [minimum spanning tree]: https://en.wikipedia.org/wiki/Minimum_spanning_tree
  4113  * @param {Graph} g the graph used to generate the minimum spanning tree
  4114  * @param {Function} weightFunc the weight function to use
  4115  */
  4116 function prim(g, weightFunc) {
  4117   var result = new Graph(),
  4118       parents = {},
  4119       pq = new PriorityQueue(),
  4120       u;
  4122   function updateNeighbors(e) {
  4123     var incidentNodes = g.incidentNodes(e),
  4124         v = incidentNodes[0] !== u ? incidentNodes[0] : incidentNodes[1],
  4125         pri = pq.priority(v);
  4126     if (pri !== undefined) {
  4127       var edgeWeight = weightFunc(e);
  4128       if (edgeWeight < pri) {
  4129         parents[v] = u;
  4130         pq.decrease(v, edgeWeight);
  4135   if (g.order() === 0) {
  4136     return result;
  4139   g.eachNode(function(u) {
  4140     pq.add(u, Number.POSITIVE_INFINITY);
  4141     result.addNode(u);
  4142   });
  4144   // Start from an arbitrary node
  4145   pq.decrease(g.nodes()[0], 0);
  4147   var init = false;
  4148   while (pq.size() > 0) {
  4149     u = pq.removeMin();
  4150     if (u in parents) {
  4151       result.addEdge(null, u, parents[u]);
  4152     } else if (init) {
  4153       throw new Error("Input graph is not connected: " + g);
  4154     } else {
  4155       init = true;
  4158     g.incidentEdges(u).forEach(updateNeighbors);
  4161   return result;
  4164 },{"../Graph":33,"cp-data":5}],43:[function(require,module,exports){
  4165 module.exports = tarjan;
  4167 /**
  4168  * This function is an implementation of [Tarjan's algorithm][] which finds
  4169  * all [strongly connected components][] in the directed graph **g**. Each
  4170  * strongly connected component is composed of nodes that can reach all other
  4171  * nodes in the component via directed edges. A strongly connected component
  4172  * can consist of a single node if that node cannot both reach and be reached
  4173  * by any other specific node in the graph. Components of more than one node
  4174  * are guaranteed to have at least one cycle.
  4176  * This function returns an array of components. Each component is itself an
  4177  * array that contains the ids of all nodes in the component.
  4179  * [Tarjan's algorithm]: http://en.wikipedia.org/wiki/Tarjan's_strongly_connected_components_algorithm
  4180  * [strongly connected components]: http://en.wikipedia.org/wiki/Strongly_connected_component
  4182  * @param {Digraph} g the graph to search for strongly connected components
  4183  */
  4184 function tarjan(g) {
  4185   if (!g.isDirected()) {
  4186     throw new Error("tarjan can only be applied to a directed graph. Bad input: " + g);
  4189   var index = 0,
  4190       stack = [],
  4191       visited = {}, // node id -> { onStack, lowlink, index }
  4192       results = [];
  4194   function dfs(u) {
  4195     var entry = visited[u] = {
  4196       onStack: true,
  4197       lowlink: index,
  4198       index: index++
  4199     };
  4200     stack.push(u);
  4202     g.successors(u).forEach(function(v) {
  4203       if (!(v in visited)) {
  4204         dfs(v);
  4205         entry.lowlink = Math.min(entry.lowlink, visited[v].lowlink);
  4206       } else if (visited[v].onStack) {
  4207         entry.lowlink = Math.min(entry.lowlink, visited[v].index);
  4209     });
  4211     if (entry.lowlink === entry.index) {
  4212       var cmpt = [],
  4213           v;
  4214       do {
  4215         v = stack.pop();
  4216         visited[v].onStack = false;
  4217         cmpt.push(v);
  4218       } while (u !== v);
  4219       results.push(cmpt);
  4223   g.nodes().forEach(function(u) {
  4224     if (!(u in visited)) {
  4225       dfs(u);
  4227   });
  4229   return results;
  4232 },{}],44:[function(require,module,exports){
  4233 module.exports = topsort;
  4234 topsort.CycleException = CycleException;
  4236 /*
  4237  * Given a graph **g**, this function returns an ordered list of nodes such
  4238  * that for each edge `u -> v`, `u` appears before `v` in the list. If the
  4239  * graph has a cycle it is impossible to generate such a list and
  4240  * **CycleException** is thrown.
  4242  * See [topological sorting](https://en.wikipedia.org/wiki/Topological_sorting)
  4243  * for more details about how this algorithm works.
  4245  * @param {Digraph} g the graph to sort
  4246  */
  4247 function topsort(g) {
  4248   if (!g.isDirected()) {
  4249     throw new Error("topsort can only be applied to a directed graph. Bad input: " + g);
  4252   var visited = {};
  4253   var stack = {};
  4254   var results = [];
  4256   function visit(node) {
  4257     if (node in stack) {
  4258       throw new CycleException();
  4261     if (!(node in visited)) {
  4262       stack[node] = true;
  4263       visited[node] = true;
  4264       g.predecessors(node).forEach(function(pred) {
  4265         visit(pred);
  4266       });
  4267       delete stack[node];
  4268       results.push(node);
  4272   var sinks = g.sinks();
  4273   if (g.order() !== 0 && sinks.length === 0) {
  4274     throw new CycleException();
  4277   g.sinks().forEach(function(sink) {
  4278     visit(sink);
  4279   });
  4281   return results;
  4284 function CycleException() {}
  4286 CycleException.prototype.toString = function() {
  4287   return "Graph has at least one cycle";
  4288 };
  4290 },{}],45:[function(require,module,exports){
  4291 // This file provides a helper function that mixes-in Dot behavior to an
  4292 // existing graph prototype.
  4294 /* jshint -W079 */
  4295 var Set = require("cp-data").Set;
  4296 /* jshint +W079 */
  4298 module.exports = compoundify;
  4300 // Extends the given SuperConstructor with the ability for nodes to contain
  4301 // other nodes. A special node id `null` is used to indicate the root graph.
  4302 function compoundify(SuperConstructor) {
  4303   function Constructor() {
  4304     SuperConstructor.call(this);
  4306     // Map of object id -> parent id (or null for root graph)
  4307     this._parents = {};
  4309     // Map of id (or null) -> children set
  4310     this._children = {};
  4311     this._children[null] = new Set();
  4314   Constructor.prototype = new SuperConstructor();
  4315   Constructor.prototype.constructor = Constructor;
  4317   Constructor.prototype.parent = function(u, parent) {
  4318     this._strictGetNode(u);
  4320     if (arguments.length < 2) {
  4321       return this._parents[u];
  4324     if (u === parent) {
  4325       throw new Error("Cannot make " + u + " a parent of itself");
  4327     if (parent !== null) {
  4328       this._strictGetNode(parent);
  4331     this._children[this._parents[u]].remove(u);
  4332     this._parents[u] = parent;
  4333     this._children[parent].add(u);
  4334   };
  4336   Constructor.prototype.children = function(u) {
  4337     if (u !== null) {
  4338       this._strictGetNode(u);
  4340     return this._children[u].keys();
  4341   };
  4343   Constructor.prototype.addNode = function(u, value) {
  4344     u = SuperConstructor.prototype.addNode.call(this, u, value);
  4345     this._parents[u] = null;
  4346     this._children[u] = new Set();
  4347     this._children[null].add(u);
  4348     return u;
  4349   };
  4351   Constructor.prototype.delNode = function(u) {
  4352     // Promote all children to the parent of the subgraph
  4353     var parent = this.parent(u);
  4354     this._children[u].keys().forEach(function(child) {
  4355       this.parent(child, parent);
  4356     }, this);
  4358     this._children[parent].remove(u);
  4359     delete this._parents[u];
  4360     delete this._children[u];
  4362     return SuperConstructor.prototype.delNode.call(this, u);
  4363   };
  4365   Constructor.prototype.copy = function() {
  4366     var copy = SuperConstructor.prototype.copy.call(this);
  4367     this.nodes().forEach(function(u) {
  4368       copy.parent(u, this.parent(u));
  4369     }, this);
  4370     return copy;
  4371   };
  4373   Constructor.prototype.filterNodes = function(filter) {
  4374     var self = this,
  4375         copy = SuperConstructor.prototype.filterNodes.call(this, filter);
  4377     var parents = {};
  4378     function findParent(u) {
  4379       var parent = self.parent(u);
  4380       if (parent === null || copy.hasNode(parent)) {
  4381         parents[u] = parent;
  4382         return parent;
  4383       } else if (parent in parents) {
  4384         return parents[parent];
  4385       } else {
  4386         return findParent(parent);
  4390     copy.eachNode(function(u) { copy.parent(u, findParent(u)); });
  4392     return copy;
  4393   };
  4395   return Constructor;
  4398 },{"cp-data":5}],46:[function(require,module,exports){
  4399 var Graph = require("../Graph"),
  4400     Digraph = require("../Digraph"),
  4401     CGraph = require("../CGraph"),
  4402     CDigraph = require("../CDigraph");
  4404 exports.decode = function(nodes, edges, Ctor) {
  4405   Ctor = Ctor || Digraph;
  4407   if (typeOf(nodes) !== "Array") {
  4408     throw new Error("nodes is not an Array");
  4411   if (typeOf(edges) !== "Array") {
  4412     throw new Error("edges is not an Array");
  4415   if (typeof Ctor === "string") {
  4416     switch(Ctor) {
  4417       case "graph": Ctor = Graph; break;
  4418       case "digraph": Ctor = Digraph; break;
  4419       case "cgraph": Ctor = CGraph; break;
  4420       case "cdigraph": Ctor = CDigraph; break;
  4421       default: throw new Error("Unrecognized graph type: " + Ctor);
  4425   var graph = new Ctor();
  4427   nodes.forEach(function(u) {
  4428     graph.addNode(u.id, u.value);
  4429   });
  4431   // If the graph is compound, set up children...
  4432   if (graph.parent) {
  4433     nodes.forEach(function(u) {
  4434       if (u.children) {
  4435         u.children.forEach(function(v) {
  4436           graph.parent(v, u.id);
  4437         });
  4439     });
  4442   edges.forEach(function(e) {
  4443     graph.addEdge(e.id, e.u, e.v, e.value);
  4444   });
  4446   return graph;
  4447 };
  4449 exports.encode = function(graph) {
  4450   var nodes = [];
  4451   var edges = [];
  4453   graph.eachNode(function(u, value) {
  4454     var node = {id: u, value: value};
  4455     if (graph.children) {
  4456       var children = graph.children(u);
  4457       if (children.length) {
  4458         node.children = children;
  4461     nodes.push(node);
  4462   });
  4464   graph.eachEdge(function(e, u, v, value) {
  4465     edges.push({id: e, u: u, v: v, value: value});
  4466   });
  4468   var type;
  4469   if (graph instanceof CDigraph) {
  4470     type = "cdigraph";
  4471   } else if (graph instanceof CGraph) {
  4472     type = "cgraph";
  4473   } else if (graph instanceof Digraph) {
  4474     type = "digraph";
  4475   } else if (graph instanceof Graph) {
  4476     type = "graph";
  4477   } else {
  4478     throw new Error("Couldn't determine type of graph: " + graph);
  4481   return { nodes: nodes, edges: edges, type: type };
  4482 };
  4484 function typeOf(obj) {
  4485   return Object.prototype.toString.call(obj).slice(8, -1);
  4488 },{"../CDigraph":30,"../CGraph":31,"../Digraph":32,"../Graph":33}],47:[function(require,module,exports){
  4489 /* jshint -W079 */
  4490 var Set = require("cp-data").Set;
  4491 /* jshint +W079 */
  4493 exports.all = function() {
  4494   return function() { return true; };
  4495 };
  4497 exports.nodesFromList = function(nodes) {
  4498   var set = new Set(nodes);
  4499   return function(u) {
  4500     return set.has(u);
  4501   };
  4502 };
  4504 },{"cp-data":5}],48:[function(require,module,exports){
  4505 var Graph = require("./Graph"),
  4506     Digraph = require("./Digraph");
  4508 // Side-effect based changes are lousy, but node doesn't seem to resolve the
  4509 // requires cycle.
  4511 /**
  4512  * Returns a new directed graph using the nodes and edges from this graph. The
  4513  * new graph will have the same nodes, but will have twice the number of edges:
  4514  * each edge is split into two edges with opposite directions. Edge ids,
  4515  * consequently, are not preserved by this transformation.
  4516  */
  4517 Graph.prototype.toDigraph =
  4518 Graph.prototype.asDirected = function() {
  4519   var g = new Digraph();
  4520   this.eachNode(function(u, value) { g.addNode(u, value); });
  4521   this.eachEdge(function(e, u, v, value) {
  4522     g.addEdge(null, u, v, value);
  4523     g.addEdge(null, v, u, value);
  4524   });
  4525   return g;
  4526 };
  4528 /**
  4529  * Returns a new undirected graph using the nodes and edges from this graph.
  4530  * The new graph will have the same nodes, but the edges will be made
  4531  * undirected. Edge ids are preserved in this transformation.
  4532  */
  4533 Digraph.prototype.toGraph =
  4534 Digraph.prototype.asUndirected = function() {
  4535   var g = new Graph();
  4536   this.eachNode(function(u, value) { g.addNode(u, value); });
  4537   this.eachEdge(function(e, u, v, value) {
  4538     g.addEdge(e, u, v, value);
  4539   });
  4540   return g;
  4541 };
  4543 },{"./Digraph":32,"./Graph":33}],49:[function(require,module,exports){
  4544 // Returns an array of all values for properties of **o**.
  4545 exports.values = function(o) {
  4546   var ks = Object.keys(o),
  4547       len = ks.length,
  4548       result = new Array(len),
  4549       i;
  4550   for (i = 0; i < len; ++i) {
  4551     result[i] = o[ks[i]];
  4553   return result;
  4554 };
  4556 },{}],50:[function(require,module,exports){
  4557 module.exports = '0.7.4';
  4559 },{}]},{},[1])

mercurial