Wed, 31 Dec 2014 06:09:35 +0100
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;
1005 }
1006 });
1008 // Set up subgraphs
1009 if (inputGraph.parent) {
1010 inputGraph.nodes().forEach(function(u) {
1011 g.parent(u, inputGraph.parent(u));
1012 });
1013 }
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;
1036 }
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;
1047 }
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);
1085 }
1086 }
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.
1094 *
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;
1123 }
1124 g.addEdge(null, u, t, {});
1125 g.delEdge(e);
1126 }
1127 });
1128 }
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);
1142 }
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 };
1145 }
1146 g.delNode(u);
1147 }
1148 });
1149 }
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(); });
1157 }
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);
1174 }
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;
1186 }
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 };
1198 }
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;
1223 }
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; });
1240 }
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;
1258 }
1259 }
1260 util.log(3, 'Order phase start ' + j + ' iter ' + i + ' cross count: ' + cc);
1261 }
1262 }
1264 Object.keys(allTimeBest).forEach(function(u) {
1265 if (!g.children || !g.children(u).length) {
1266 g.node(u).order = allTimeBest[u];
1267 }
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);
1273 }
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;
1283 }
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;
1293 }
1295 function sweep(g, layerGraphs, iter) {
1296 if (iter % 2 === 0) {
1297 sweepDown(g, layerGraphs, iter);
1298 } else {
1299 sweepUp(g, layerGraphs, iter);
1300 }
1301 }
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()));
1307 }
1308 }
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()));
1314 }
1315 }
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]);
1330 }
1331 return cc;
1332 }
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:
1337 *
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];
1365 }
1366 treeIndex = (treeIndex - 1) >> 1;
1367 ++tree[treeIndex];
1368 }
1369 });
1371 return cc;
1372 }
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;
1393 }
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;
1414 }
1415 dfs(null);
1417 var layerGraphs = [];
1418 ranks.forEach(function(us, rank) {
1419 layerGraphs[rank] = g.filterNodes(nodesFromList(us));
1420 });
1422 return layerGraphs;
1423 }
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] = [];
1445 }
1446 layer.push(u);
1447 });
1449 layers.forEach(function(layer) {
1450 if (random) {
1451 util.shuffle(layer);
1452 }
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;
1461 }
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;
1480 }
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;
1491 }
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;
1502 }
1503 }
1504 }
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 };
1525 }
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;
1538 }
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();
1547 }
1548 if (!cg.hasNode(lhs.lastSG)) { cg.addNode(lhs.lastSG); }
1549 cg.addNode(rhs.firstSG);
1550 cg.addEdge(null, lhs.lastSG, rhs.firstSG);
1551 }
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 };
1562 }
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;
1572 }
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);
1591 }
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);
1601 }
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); }
1610 }
1611 }
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;
1622 }
1623 }
1624 }
1625 }
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);
1696 }
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 });
1720 }
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;
1730 }
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;
1748 }
1749 }
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];
1772 }
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);
1779 }
1780 k0 = k1;
1781 }
1782 }
1783 }
1785 return conflicts;
1786 }
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];
1817 }
1818 }
1819 });
1820 }
1821 });
1822 });
1824 return { pos: pos, root: root, align: align };
1825 }
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);
1852 }
1853 }
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];
1865 }
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);
1871 }
1872 }
1873 w = align[w];
1874 } while (w !== v);
1875 }
1876 }
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);
1896 }
1897 ));
1898 }
1899 shift[v] = minShift;
1900 }
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;
1911 }
1913 function findMinCoord(g, layering, xs) {
1914 return util.min(layering.map(function(layer) {
1915 var u = layer[0];
1916 return xs[u];
1917 }));
1918 }
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 }));
1925 }
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];
1935 }
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;
1946 }
1947 }
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);
1962 }
1963 }
1965 function flipHorizontally(xs) {
1966 for (var u in xs) {
1967 xs[u] = -xs[u];
1968 }
1969 }
1971 function reverseInnerOrder(layering) {
1972 layering.forEach(function(layer) {
1973 layer.reverse();
1974 });
1975 }
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;
1982 }
1983 }
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;
1990 }
1991 }
1993 function sep(g, u) {
1994 if (config.universalSep !== null) {
1995 return config.universalSep;
1996 }
1997 var w = width(g, u);
1998 var s = g.node(u).dummy ? config.edgeSep : config.nodeSep;
1999 return (w + s) / 2;
2000 }
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;
2008 }
2009 } else {
2010 if (arguments.length < 3) {
2011 return g.node(u).x;
2012 } else {
2013 g.node(u).x = x;
2014 }
2015 }
2016 }
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;
2024 }
2025 } else {
2026 if (arguments.length < 3) {
2027 return g.node(u)[name];
2028 } else {
2029 g.node(u)[name] = x;
2030 }
2031 }
2032 }
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;
2040 }
2041 } else {
2042 if (arguments.length < 3) {
2043 return g.node(u).y;
2044 } else {
2045 g.node(u).y = y;
2046 }
2047 }
2048 }
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);
2060 }
2061 u = v;
2062 xU = xV;
2063 });
2064 });
2065 }
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.
2085 *
2086 * Prerequisites:
2087 *
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);
2124 }
2126 function restoreEdges(g) {
2127 acyclic.undo(g);
2128 }
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:
2133 *
2134 * /--<--x--->--\
2135 * node y
2136 * \--<--z--->--/
2137 *
2138 * Dummy nodes x, y, z give us the shape of a loop and node y is where we place
2139 * the label.
2140 *
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);
2155 }
2156 });
2157 }
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);
2167 }
2168 });
2169 }
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 });
2179 }
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);
2187 }
2188 });
2189 }
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);
2197 }
2198 normalize(subgraph);
2199 }
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; });
2204 }
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`.
2216 *
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);
2241 }
2242 });
2244 delete onStack[u];
2245 }
2247 g.eachNode(function(u) { dfs(u); });
2249 util.log(2, 'Acyclic Phase: reversed ' + reverseCount + ' edge(s)');
2251 return reverseCount;
2252 }
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);
2265 }
2266 });
2267 }
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;
2277 }
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);
2288 }
2290 var newU = rankSets[prefRank];
2291 if (newU === undefined) {
2292 newU = rankSets[prefRank] = g.addNode(null, { originalNodes: [] });
2293 g.parent(newU, sg);
2294 }
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);
2302 }
2303 });
2305 addLightEdgesFromMinNode(g, sg, rankSets.min);
2306 addLightEdgesToMaxNode(g, sg, rankSets.max);
2307 }
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;
2316 }
2317 return true;
2318 }
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 };
2331 }
2333 // Do not reverse edges for self-loops.
2334 if (origValue.selfLoop) {
2335 reverse = false;
2336 }
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);
2344 }
2345 });
2346 }
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 };
2359 }
2361 // Do not reverse edges for self-loops.
2362 if (origValue.selfLoop) {
2363 reverse = false;
2364 }
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);
2372 }
2373 });
2374 }
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 });
2383 }
2384 });
2385 }
2386 }
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 });
2395 }
2396 });
2397 }
2398 }
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.
2405 *
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);
2416 }
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);
2429 }
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.
2452 *
2453 * Prerequisites:
2454 *
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
2458 *
2459 * Outputs:
2460 *
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.
2464 *
2465 * Nodes have the same id and value as that in the input graph.
2466 *
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;
2480 }
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 });
2490 }
2492 tree.addNode(u, {});
2493 tree.addEdge(null, u, v, { reversed: true });
2494 remaining.remove(u);
2495 addTightEdges(u);
2496 continueToScan = false;
2497 }
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 });
2506 }
2508 tree.addNode(w, {});
2509 tree.addEdge(null, v, w, {});
2510 remaining.remove(w);
2511 addTightEdges(w);
2512 continueToScan = false;
2513 }
2514 });
2515 return continueToScan;
2516 }
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;
2526 }
2527 }
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;
2535 }
2536 }
2537 });
2538 });
2540 tree.eachNode(function(u) { g.node(u).rank -= minSlack; });
2541 }
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();
2550 }
2551 }
2553 return tree;
2554 }
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;
2561 }
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.
2572 *
2573 * Prerequisites:
2574 *
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;
2586 }
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 });
2593 }
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.
2605 *
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;
2611 }
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);
2629 }
2630 }
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);
2652 }
2653 if (n !== spanningTree.graph().root) {
2654 setCutValue(graph, spanningTree, n);
2655 }
2656 }
2657 dfs(spanningTree.graph().root);
2658 }
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);
2677 }
2678 tree.node(n).low = low;
2679 tree.node(n).lim = postOrderNum++;
2680 }
2682 dfs(tree.graph().root);
2683 }
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]));
2702 }
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++;
2720 }
2721 }
2722 if (!inSubtree(tree, succ, child)) {
2723 G++;
2724 }
2725 }
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++;
2734 }
2735 }
2736 if (!inSubtree(tree, pred, child)) {
2737 H++;
2738 }
2739 }
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;
2750 }
2751 }
2753 if (!tree.edge(parentEdge).reversed) {
2754 cutValue += grandchildCutSum - E + F - G + H;
2755 } else {
2756 cutValue -= grandchildCutSum - E + F - G + H;
2757 }
2759 tree.edge(parentEdge).cutValue = cutValue;
2760 }
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);
2769 }
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;
2782 }
2783 }
2784 return null;
2785 }
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;
2811 }
2812 }
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;
2821 }
2822 }
2823 });
2824 }
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);
2834 }
2835 });
2836 throw new Error('No edge found from outside of tree to inside');
2837 }
2839 return minSlackEdge;
2840 }
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);
2862 }
2863 }
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);
2872 }
2874 tree.graph().root = root;
2876 tree.addEdge(null, source, target, {cutValue: 0});
2878 initCutValues(graph, tree);
2880 adjustRanks(graph, tree);
2881 }
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 });
2897 }
2899 dfs(tree.graph().root);
2900 }
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 }));
2913 }
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 }));
2920 }
2921 }
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;
2947 }
2948 }
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;
2972 }
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.
3012 *
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');
3022 }
3023 };
3024 }
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));
3036 }
3037 }
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;
3097 }
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;
3113 }
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;
3125 }
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);
3139 }
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;
3150 }
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);
3164 }
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 + "'");
3179 }
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));
3201 }
3202 else if (this.hasEdge(e)) {
3203 throw new Error("Graph already has edge '" + e + "'");
3204 }
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);
3236 }
3237 });
3238 this.eachEdge(function(e, u, v, value) {
3239 if (copy.hasNode(u) && copy.hasNode(v)) {
3240 copy.addEdge(e, u, v, value);
3241 }
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");
3250 }
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");
3258 }
3259 return edge;
3260 };
3262 function addEdgeToMap(map, v, e) {
3263 (map[v] || (map[v] = new Set())).add(e);
3264 }
3266 function delEdgeFromMap(map, v, e) {
3267 var vEntry = map[v];
3268 vEntry.remove(e);
3269 if (vEntry.size() === 0) {
3270 delete map[v];
3271 }
3272 }
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);
3289 }
3291 src.eachNode(function(u, value) {
3292 if (value === undefined) {
3293 g.addNode(u);
3294 } else {
3295 g.addNode(u, value);
3296 }
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);
3303 }
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);
3326 }
3328 src.eachNode(function(u, value) {
3329 if (value === undefined) {
3330 g.addNode(u);
3331 } else {
3332 g.addNode(u, value);
3333 }
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);
3340 }
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:
3352 *
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 = {};
3379 }
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.
3394 *
3395 * If no node `u` exists in the graph this function throws an Error.
3396 *
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.
3408 *
3409 * If no node `u` exists in the graph this function throws an Error.
3410 *
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`.
3423 *
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.
3455 *
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.
3465 *
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.
3476 *
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.
3481 *
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);
3491 }
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.
3499 *
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.
3504 *
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);
3514 }
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.
3522 *
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.
3527 *
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();
3536 }
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.
3550 *
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.
3565 *
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.
3580 *
3581 * If `source` or `target` are not present in the graph this function will
3582 * throw an Error.
3583 *
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.
3597 *
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);
3611 }
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:
3620 *
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 = {};
3644 }
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`.
3658 *
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.
3670 *
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.
3674 *
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();
3685 }
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.
3699 *
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.
3713 *
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.
3727 *
3728 * If `u` or `v` are not present in the graph this function will throw an
3729 * Error.
3730 *
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.
3744 *
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.
3763 *
3764 * This function only works with undirected Graphs.
3765 *
3766 * [connected components]: http://en.wikipedia.org/wiki/Connected_component_(graph_theory)
3767 *
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 });
3781 }
3782 }
3784 g.nodes().forEach(function(v) {
3785 var component = [];
3786 dfs(v, component);
3787 if (component.length > 0) {
3788 results.push(component);
3789 }
3790 });
3792 return results;
3793 }
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.
3808 *
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.
3813 *
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.
3818 *
3819 * This function takes `O((|E| + |V|) * log |V|)` time.
3820 *
3821 * [Dijkstra's algorithm]: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
3822 *
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);
3841 }
3843 if (distance < vEntry.distance) {
3844 vEntry.distance = distance;
3845 vEntry.predecessor = u;
3846 pq.decrease(v, distance);
3847 }
3848 }
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;
3867 }
3869 incidentFunc(u).forEach(updateNeighbors);
3870 }
3872 return results;
3873 }
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)`.
3885 *
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.
3890 *
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.
3895 *
3896 * This function takes `O(|V| * (|E| + |V|) * log |V|)` time.
3897 *
3898 * [alg.dijkstra]: dijkstra.js.html#dijkstra
3899 *
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;
3910 }
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.
3922 *
3923 * [alg.isAcyclic][] is more efficient if you only need to determine whether
3924 * a graph has a cycle or not.
3925 *
3926 * [alg.isAcyclic]: isAcyclic.js.html#isAcyclic
3927 *
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; });
3932 }
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.
3947 *
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.
3951 *
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.
3956 *
3957 * This algorithm takes O(|V|^3) time.
3958 *
3959 * [Floyd-Warshall algorithm]: https://en.wikipedia.org/wiki/Floyd-Warshall_algorithm
3960 * [alg.dijkstraAll]: dijkstraAll.js.html#dijkstraAll
3961 *
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 };
3981 }
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 };
3989 }
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;
4005 }
4006 });
4007 });
4008 });
4010 return results;
4011 }
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.
4022 *
4023 * Use [alg.findCycles][] if you need the actual list of cycles in a graph.
4024 *
4025 * [alg.findCycles]: findCycles.js.html#findCycles
4026 *
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;
4035 }
4036 return true;
4037 }
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");
4052 }
4053 function dfs(u, prev) {
4054 if (visited.has(u)) {
4055 throw new Error("The input graph is not a tree: " + g);
4056 }
4057 visited.add(u);
4058 g.neighbors(u).forEach(function(v) {
4059 if (v !== prev) dfs(v, u);
4060 });
4061 f(u);
4062 }
4063 dfs(root);
4064 }
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");
4079 }
4080 function dfs(u, prev) {
4081 if (visited.has(u)) {
4082 throw new Error("The input graph is not a tree: " + g);
4083 }
4084 visited.add(u);
4085 f(u);
4086 g.neighbors(u).forEach(function(v) {
4087 if (v !== prev) dfs(v, u);
4088 });
4089 }
4090 dfs(root);
4091 }
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.
4104 *
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.
4107 *
4108 * This function takes `O(|E| log |V|)` time.
4109 *
4110 * [Prim's algorithm]: https://en.wikipedia.org/wiki/Prim's_algorithm
4111 * [minimum spanning tree]: https://en.wikipedia.org/wiki/Minimum_spanning_tree
4112 *
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);
4131 }
4132 }
4133 }
4135 if (g.order() === 0) {
4136 return result;
4137 }
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;
4156 }
4158 g.incidentEdges(u).forEach(updateNeighbors);
4159 }
4161 return result;
4162 }
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.
4175 *
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.
4178 *
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
4181 *
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);
4187 }
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);
4208 }
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);
4220 }
4221 }
4223 g.nodes().forEach(function(u) {
4224 if (!(u in visited)) {
4225 dfs(u);
4226 }
4227 });
4229 return results;
4230 }
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.
4241 *
4242 * See [topological sorting](https://en.wikipedia.org/wiki/Topological_sorting)
4243 * for more details about how this algorithm works.
4244 *
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);
4250 }
4252 var visited = {};
4253 var stack = {};
4254 var results = [];
4256 function visit(node) {
4257 if (node in stack) {
4258 throw new CycleException();
4259 }
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);
4269 }
4270 }
4272 var sinks = g.sinks();
4273 if (g.order() !== 0 && sinks.length === 0) {
4274 throw new CycleException();
4275 }
4277 g.sinks().forEach(function(sink) {
4278 visit(sink);
4279 });
4281 return results;
4282 }
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();
4312 }
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];
4322 }
4324 if (u === parent) {
4325 throw new Error("Cannot make " + u + " a parent of itself");
4326 }
4327 if (parent !== null) {
4328 this._strictGetNode(parent);
4329 }
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);
4339 }
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);
4387 }
4388 }
4390 copy.eachNode(function(u) { copy.parent(u, findParent(u)); });
4392 return copy;
4393 };
4395 return Constructor;
4396 }
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");
4409 }
4411 if (typeOf(edges) !== "Array") {
4412 throw new Error("edges is not an Array");
4413 }
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);
4422 }
4423 }
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 });
4438 }
4439 });
4440 }
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;
4459 }
4460 }
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);
4479 }
4481 return { nodes: nodes, edges: edges, type: type };
4482 };
4484 function typeOf(obj) {
4485 return Object.prototype.toString.call(obj).slice(8, -1);
4486 }
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]];
4552 }
4553 return result;
4554 };
4556 },{}],50:[function(require,module,exports){
4557 module.exports = '0.7.4';
4559 },{}]},{},[1])
4560 ;