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

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:2050b7f3aae5
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');
25
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 };
56
57 },{"./lib/Renderer":3,"./lib/version":4,"dagre":11,"graphlib":28}],3:[function(require,module,exports){
58 var layout = require('dagre').layout;
59
60 var d3;
61 try { d3 = require('d3'); } catch (_) { d3 = window.d3; }
62
63 module.exports = Renderer;
64
65 function Renderer() {
66 // Set up defaults...
67 this._layout = layout();
68
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);
78
79 this.edgeInterpolate('bundle');
80 this.edgeTension(0.95);
81 }
82
83 Renderer.prototype.layout = function(layout) {
84 if (!arguments.length) { return this._layout; }
85 this._layout = layout;
86 return this;
87 };
88
89 Renderer.prototype.drawNodes = function(drawNodes) {
90 if (!arguments.length) { return this._drawNodes; }
91 this._drawNodes = bind(drawNodes, this);
92 return this;
93 };
94
95 Renderer.prototype.drawEdgeLabels = function(drawEdgeLabels) {
96 if (!arguments.length) { return this._drawEdgeLabels; }
97 this._drawEdgeLabels = bind(drawEdgeLabels, this);
98 return this;
99 };
100
101 Renderer.prototype.drawEdgePaths = function(drawEdgePaths) {
102 if (!arguments.length) { return this._drawEdgePaths; }
103 this._drawEdgePaths = bind(drawEdgePaths, this);
104 return this;
105 };
106
107 Renderer.prototype.positionNodes = function(positionNodes) {
108 if (!arguments.length) { return this._positionNodes; }
109 this._positionNodes = bind(positionNodes, this);
110 return this;
111 };
112
113 Renderer.prototype.positionEdgeLabels = function(positionEdgeLabels) {
114 if (!arguments.length) { return this._positionEdgeLabels; }
115 this._positionEdgeLabels = bind(positionEdgeLabels, this);
116 return this;
117 };
118
119 Renderer.prototype.positionEdgePaths = function(positionEdgePaths) {
120 if (!arguments.length) { return this._positionEdgePaths; }
121 this._positionEdgePaths = bind(positionEdgePaths, this);
122 return this;
123 };
124
125 Renderer.prototype.transition = function(transition) {
126 if (!arguments.length) { return this._transition; }
127 this._transition = bind(transition, this);
128 return this;
129 };
130
131 Renderer.prototype.postLayout = function(postLayout) {
132 if (!arguments.length) { return this._postLayout; }
133 this._postLayout = bind(postLayout, this);
134 return this;
135 };
136
137 Renderer.prototype.postRender = function(postRender) {
138 if (!arguments.length) { return this._postRender; }
139 this._postRender = bind(postRender, this);
140 return this;
141 };
142
143 Renderer.prototype.edgeInterpolate = function(edgeInterpolate) {
144 if (!arguments.length) { return this._edgeInterpolate; }
145 this._edgeInterpolate = edgeInterpolate;
146 return this;
147 };
148
149 Renderer.prototype.edgeTension = function(edgeTension) {
150 if (!arguments.length) { return this._edgeTension; }
151 this._edgeTension = edgeTension;
152 return this;
153 };
154
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);
159
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; });
167
168
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'));
173
174 svgNodes.each(function(u) { calculateDimensions(this, graph.node(u)); });
175 svgEdgeLabels.each(function(e) { calculateDimensions(this, graph.edge(e)); });
176
177 // Now apply the layout function
178 var result = runLayout(graph, this._layout);
179
180 // Run any user-specified post layout processing
181 this._postLayout(result, svg);
182
183 var svgEdgePaths = this._drawEdgePaths(graph, svg.select('g.edgePaths'));
184
185 // Apply the layout information to the graph
186 this._positionNodes(result, svgNodes);
187 this._positionEdgeLabels(result, svgEdgeLabels);
188 this._positionEdgePaths(result, svgEdgePaths);
189
190 this._postRender(result, svg);
191
192 return result;
193 };
194
195 function copyAndInitGraph(graph) {
196 var copy = graph.copy();
197
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 });
207
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 });
216
217 return copy;
218 }
219
220 function calculateDimensions(group, value) {
221 var bbox = group.getBBox();
222 value.width = bbox.width;
223 value.height = bbox.height;
224 }
225
226 function runLayout(graph, layout) {
227 var result = layout.run(graph);
228
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; });
232
233 return result;
234 }
235
236 function defaultDrawNodes(g, root) {
237 var nodes = g.nodes().filter(function(u) { return !isComposite(g, u); });
238
239 var svgNodes = root
240 .selectAll('g.node')
241 .classed('enter', false)
242 .data(nodes, function(u) { return u; });
243
244 svgNodes.selectAll('*').remove();
245
246 svgNodes
247 .enter()
248 .append('g')
249 .style('opacity', 0)
250 .attr('class', 'node enter');
251
252 svgNodes.each(function(u) { addLabel(g.node(u), d3.select(this), 10, 10); });
253
254 this._transition(svgNodes.exit())
255 .style('opacity', 0)
256 .remove();
257
258 return svgNodes;
259 }
260
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; });
266
267 svgEdgeLabels.selectAll('*').remove();
268
269 svgEdgeLabels
270 .enter()
271 .append('g')
272 .style('opacity', 0)
273 .attr('class', 'edgeLabel enter');
274
275 svgEdgeLabels.each(function(e) { addLabel(g.edge(e), d3.select(this), 0, 0); });
276
277 this._transition(svgEdgeLabels.exit())
278 .style('opacity', 0)
279 .remove();
280
281 return svgEdgeLabels;
282 }
283
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; });
289
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)');
297
298 this._transition(svgEdgePaths.exit())
299 .style('opacity', 0)
300 .remove();
301
302 return svgEdgePaths;
303 };
304
305 function defaultPositionNodes(g, svgNodes, svgNodesEnter) {
306 function transform(u) {
307 var value = g.node(u);
308 return 'translate(' + value.x + ',' + value.y + ')';
309 }
310
311 // For entering nodes, position immediately without transition
312 svgNodes.filter('.enter').attr('transform', transform);
313
314 this._transition(svgNodes)
315 .style('opacity', 1)
316 .attr('transform', transform);
317 }
318
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 }
325
326 // For entering edge labels, position immediately without transition
327 svgEdgeLabels.filter('.enter').attr('transform', transform);
328
329 this._transition(svgEdgeLabels)
330 .style('opacity', 1)
331 .attr('transform', transform);
332 }
333
334 function defaultPositionEdgePaths(g, svgEdgePaths) {
335 var interpolate = this._edgeInterpolate,
336 tension = this._edgeTension;
337
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();
343
344 var p0 = points.length === 0 ? target : points[0];
345 var p1 = points.length === 0 ? source : points[points.length - 1];
346
347 points.unshift(intersectRect(source, p0));
348 // TODO: use bpodgursky's shortening algorithm here
349 points.push(intersectRect(target, p1));
350
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 }
358
359 svgEdgePaths.filter('.enter').selectAll('path')
360 .attr('d', calcPoints);
361
362 this._transition(svgEdgePaths.selectAll('path'))
363 .attr('d', calcPoints)
364 .style('opacity', 1);
365 }
366
367 // By default we do not use transitions
368 function defaultTransition(selection) {
369 return selection;
370 }
371
372 function defaultPostLayout() {
373 // Do nothing
374 }
375
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 }
394
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');
400
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 }
411
412 var bbox = root.node().getBBox();
413
414 labelSvg.attr('transform',
415 'translate(' + (-bbox.width / 2) + ',' + (-bbox.height / 2) + ')');
416
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 }
425
426 function addForeignObjectLabel(label, root) {
427 var fo = root
428 .append('foreignObject')
429 .attr('width', '100000');
430
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 });
441
442 fo
443 .attr('width', w)
444 .attr('height', h);
445 }
446
447 function addTextLabel(label, root, labelCols, labelCut) {
448 if (labelCut === undefined) labelCut = "false";
449 labelCut = (labelCut.toString().toLowerCase() === "true");
450
451 var node = root
452 .append('text')
453 .attr('text-anchor', 'left');
454
455 label = label.replace(/\\n/g, "\n");
456
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 }
467
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;
474
475 if (!str) { return str; }
476
477 var regex = '.{1,' +width+ '}(\\s|$)' + (cut ? '|.{' +width+ '}|.+$' : '|\\S+?(\\s|$)');
478
479 return str.match( RegExp(regex, 'g') ).join( brk );
480 }
481
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 }
492
493 function intersectRect(rect, point) {
494 var x = rect.x;
495 var y = rect.y;
496
497 // For now we only support rectangles
498
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;
505
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 }
522
523 return {x: x + sx, y: y + sy};
524 }
525
526 function isComposite(g, u) {
527 return 'children' in g && g.children(u).length;
528 }
529
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 }
536
537 return function() {
538 return func.apply(thisArg, arguments);
539 };
540 }
541
542 },{"d3":10,"dagre":11}],4:[function(require,module,exports){
543 module.exports = '0.1.5';
544
545 },{}],5:[function(require,module,exports){
546 exports.Set = require('./lib/Set');
547 exports.PriorityQueue = require('./lib/PriorityQueue');
548 exports.version = require('./lib/version');
549
550 },{"./lib/PriorityQueue":6,"./lib/Set":7,"./lib/version":9}],6:[function(require,module,exports){
551 module.exports = PriorityQueue;
552
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 }
564
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 };
571
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 };
578
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 };
585
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 };
598
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 };
609
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 };
630
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 };
641
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 };
658
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 };
675
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 };
689
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 };
700
701 },{}],7:[function(require,module,exports){
702 var util = require('./util');
703
704 module.exports = Set;
705
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 = {};
724
725 if (initialKeys) {
726 for (var i = 0, il = initialKeys.length; i < il; ++i) {
727 this.add(initialKeys[i]);
728 }
729 }
730 }
731
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 }
740
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 }
752
753 return result;
754 };
755
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);
764
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 }
773
774 return new Set(arr);
775 };
776
777 /**
778 * Returns the size of this set in `O(1)` time.
779 */
780 Set.prototype.size = function() {
781 return this._size;
782 };
783
784 /**
785 * Returns the keys in this set. Takes `O(n)` time.
786 */
787 Set.prototype.keys = function() {
788 return values(this._keys);
789 };
790
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 };
798
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 };
811
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 };
824
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 }
838
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 }
851
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 }
897
898 },{}],9:[function(require,module,exports){
899 module.exports = '1.1.3';
900
901 },{}],10:[function(require,module,exports){
902 require("./d3");
903 module.exports = d3;
904 (function () { delete this.d3; })(); // unset global
905
906 },{}],11:[function(require,module,exports){
907 /*
908 Copyright (c) 2012-2013 Chris Pettitt
909
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:
916
917 The above copyright notice and this permission notice shall be included in
918 all copies or substantial portions of the Software.
919
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");
932
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;
939
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 };
952
953 // Phase functions
954 var position = require('./position')();
955
956 // This layout object
957 var self = {};
958
959 self.orderIters = util.propertyAccessor(self, config, 'orderMaxSweeps');
960
961 self.rankSimplex = util.propertyAccessor(self, config, 'rankSimplex');
962
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);
969
970 self.debugLevel = util.propertyAccessor(self, config, 'debugLevel', function(x) {
971 util.log.level = x;
972 position.debugLevel(x);
973 });
974
975 self.run = util.time('Total layout', run);
976
977 self._normalize = normalize;
978
979 return self;
980
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();
996
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 });
1007
1008 // Set up subgraphs
1009 if (inputGraph.parent) {
1010 inputGraph.nodes().forEach(function(u) {
1011 g.parent(u, inputGraph.parent(u));
1012 });
1013 }
1014
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 };
1024
1025 g.addEdge(null, u, v, newValue);
1026 });
1027
1028 // Initial graph attributes
1029 var graphValue = inputGraph.graph() || {};
1030 g.graph({
1031 rankDir: graphValue.rankDir || config.rankDir,
1032 orderRestarts: graphValue.orderRestarts
1033 });
1034
1035 return g;
1036 }
1037
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);
1044
1045 if (g.order() === 0) {
1046 return g;
1047 }
1048
1049 // Make space for edge labels
1050 g.eachEdge(function(e, s, t, a) {
1051 a.minLen *= 2;
1052 });
1053 self.rankSep(rankSep / 2);
1054
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);
1058
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);
1063
1064 // Order the nodes so that edge crossings are minimized.
1065 util.time('order', order)(g, config.orderMaxSweeps);
1066
1067 // Find the x and y coordinates for every node in the graph.
1068 util.time('position', position.run)(g);
1069
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);
1073
1074 // Reverses points for edges that are in a reversed state.
1075 util.time('fixupEdgePoints', fixupEdgePoints)(g);
1076
1077 // Restore delete edges and reverse edges that were reversed in the rank
1078 // phase.
1079 util.time('rank.restoreEdges', rank.restoreEdges)(g);
1080
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 }
1087
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 };
1112
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;
1119
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 }
1129
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 }
1150
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 }
1158
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 });
1167
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;
1184
1185 return out;
1186 }
1187
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 };
1200
1201
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');
1208
1209 module.exports = order;
1210
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;
1214
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 }
1224
1225 var restarts = g.graph().orderRestarts || 0;
1226
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 });
1232
1233 var iters = 0,
1234 currentBestCC,
1235 allTimeBestCC = Number.MAX_VALUE,
1236 allTimeBest = {};
1237
1238 function saveAllTimeBest() {
1239 g.eachNode(function(u, value) { allTimeBest[u] = value.order; });
1240 }
1241
1242 for (var j = 0; j < Number(restarts) + 1 && allTimeBestCC !== 0; ++j) {
1243 currentBestCC = Number.MAX_VALUE;
1244 initOrder(g, restarts > 0);
1245
1246 util.log(2, 'Order phase start cross count: ' + g.graph().orderInitCC);
1247
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 }
1263
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;
1270
1271 util.log(2, 'Order iterations: ' + iters);
1272 util.log(2, 'Order phase best cross count: ' + g.graph().orderCC);
1273 }
1274
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 }
1284
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 }
1294
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 }
1302
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 }
1309
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 }
1316
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');
1319
1320 module.exports = crossCount;
1321
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 }
1333
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 });
1348
1349 var firstIndex = 1;
1350 while (firstIndex < layer2.length) firstIndex <<= 1;
1351
1352 var treeSize = 2 * firstIndex - 1;
1353 firstIndex -= 1;
1354
1355 var tree = [];
1356 for (var i = 0; i < treeSize; ++i) { tree[i] = 0; }
1357
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 });
1370
1371 return cc;
1372 }
1373
1374 },{"../util":26}],15:[function(require,module,exports){
1375 var nodesFromList = require('graphlib').filter.nodesFromList,
1376 /* jshint -W079 */
1377 Set = require('cp-data').Set;
1378
1379 module.exports = initLayerGraphs;
1380
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 = [];
1388
1389 function dfs(u) {
1390 if (u === null) {
1391 g.children(u).forEach(function(v) { dfs(v); });
1392 return;
1393 }
1394
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 });
1405
1406 if ('rank' in value) uRanks.add(value.rank);
1407
1408 uRanks.keys().forEach(function(r) {
1409 if (!(r in ranks)) ranks[r] = [];
1410 ranks[r].push(u);
1411 });
1412
1413 return uRanks;
1414 }
1415 dfs(null);
1416
1417 var layerGraphs = [];
1418 ranks.forEach(function(us, rank) {
1419 layerGraphs[rank] = g.filterNodes(nodesFromList(us));
1420 });
1421
1422 return layerGraphs;
1423 }
1424
1425 },{"cp-data":5,"graphlib":28}],16:[function(require,module,exports){
1426 var crossCount = require('./crossCount'),
1427 util = require('../util');
1428
1429 module.exports = initOrder;
1430
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 = [];
1439
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 });
1448
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 });
1457
1458 var cc = crossCount(g);
1459 g.graph().orderInitCC = cc;
1460 g.graph().orderCC = Number.MAX_VALUE;
1461 }
1462
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 */
1470
1471 module.exports = sortLayer;
1472
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 */
1482
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 });
1493
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 });
1498
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 }
1505
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();
1511
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 });
1527
1528 resolveViolatedConstraints(g, cg, nodeData);
1529
1530 var keys = Object.keys(nodeData);
1531 keys.sort(function(x, y) {
1532 return nodeData[x].barycenter - nodeData[y].barycenter;
1533 });
1534
1535 var result = keys.map(function(u) { return nodeData[u]; })
1536 .reduce(function(lhs, rhs) { return mergeNodeData(g, lhs, rhs); });
1537 return result;
1538 }
1539
1540 /*
1541 function mergeNodeData(g, lhs, rhs) {
1542 var cg = mergeDigraphs(lhs.constraintGraph, rhs.constraintGraph);
1543
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 }
1552
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 }
1563
1564 function mergeDigraphs(lhs, rhs) {
1565 if (lhs === undefined) return rhs;
1566 if (rhs === undefined) return lhs;
1567
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 }
1573
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 });
1583
1584 cg.outEdges(v).forEach(function(e) {
1585 cg.delEdge(e);
1586 cg.addEdge(null, w, cg.target(e));
1587 });
1588
1589 cg.delNode(u);
1590 cg.delNode(v);
1591 }
1592
1593 var violated;
1594 while ((violated = findViolatedConstraint(cg, nodeData)) !== undefined) {
1595 var source = cg.source(violated),
1596 target = cg.target(violated);
1597
1598 var v;
1599 while ((v = cg.addNode(null)) && g.hasNode(v)) {
1600 cg.delNode(v);
1601 }
1602
1603 // Collapse barycenter and list
1604 nodeData[v] = mergeNodeData(g, nodeData[source], nodeData[target]);
1605 delete nodeData[source];
1606 delete nodeData[target];
1607
1608 collapseNodes(source, target, v);
1609 if (cg.incidentEdges(v).length === 0) { cg.delNode(v); }
1610 }
1611 }
1612
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 */
1627
1628 },{"../util":26}],18:[function(require,module,exports){
1629 var util = require('./util');
1630
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 };
1643
1644 var self = {};
1645
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');
1654
1655 self.run = run;
1656
1657 return self;
1658
1659 function run(g) {
1660 g = g.filterNodes(util.filterNonSubgraphs(g));
1661
1662 var layering = util.ordering(g);
1663
1664 var conflicts = findConflicts(g, layering);
1665
1666 var xss = {};
1667 ['u', 'd'].forEach(function(vertDir) {
1668 if (vertDir === 'd') layering.reverse();
1669
1670 ['l', 'r'].forEach(function(horizDir) {
1671 if (horizDir === 'r') reverseInnerOrder(layering);
1672
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);
1676
1677 if (config.debugLevel >= 3)
1678 debugPositioning(vertDir + horizDir, g, layering, xss[dir]);
1679
1680 if (horizDir === 'r') flipHorizontally(xss[dir]);
1681
1682 if (horizDir === 'r') reverseInnerOrder(layering);
1683 });
1684
1685 if (vertDir === 'd') layering.reverse();
1686 });
1687
1688 balance(g, layering, xss);
1689
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 });
1700
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 });
1711
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 }
1721
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 }
1731
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
1741
1742 if (layering.length <= 2) return conflicts;
1743
1744 function updateConflicts(v) {
1745 var k = pos[v];
1746 if (k < k0 || k > k1) {
1747 conflicts[undirEdgeId(currLayer[l], v)] = true;
1748 }
1749 }
1750
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;
1757
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;
1765
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;
1775
1776 if (k1 !== undefined) {
1777 for (; l <= l1; ++l) {
1778 g.predecessors(currLayer[l]).forEach(updateConflicts);
1779 }
1780 k0 = k1;
1781 }
1782 }
1783 }
1784
1785 return conflicts;
1786 }
1787
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
1793
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 });
1801
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
1807
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 });
1823
1824 return { pos: pos, root: root, align: align };
1825 }
1826
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
1837
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 });
1846
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 }
1854
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 }
1877
1878 // Root coordinates relative to sink
1879 util.values(root).forEach(function(v) {
1880 placeBlock(v);
1881 });
1882
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 });
1903
1904 layering.forEach(function(layer) {
1905 layer.forEach(function(v) {
1906 xs[v] += shift[sink[root[v]]] || 0;
1907 });
1908 });
1909
1910 return xs;
1911 }
1912
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 }
1919
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 }
1926
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
1932
1933 function updateAlignment(v) {
1934 xss[alignment][v] += shift[alignment];
1935 }
1936
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 }
1948
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 });
1958
1959 // Find average of medians for xss array
1960 for (alignment in xss) {
1961 g.eachNode(updateAlignment);
1962 }
1963 }
1964
1965 function flipHorizontally(xs) {
1966 for (var u in xs) {
1967 xs[u] = -xs[u];
1968 }
1969 }
1970
1971 function reverseInnerOrder(layering) {
1972 layering.forEach(function(layer) {
1973 layer.reverse();
1974 });
1975 }
1976
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 }
1984
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 }
1992
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 }
2001
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 }
2017
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 }
2033
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 }
2049
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 };
2067
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;
2077
2078 exports.run = run;
2079 exports.restoreEdges = restoreEdges;
2080
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);
2092
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);
2096
2097 expandSidewaysEdges(g);
2098
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);
2102
2103 // Convert the graph into a flat graph for ranking
2104 var flatGraph = g.filterNodes(util.filterNonSubgraphs(g));
2105
2106 // Assign an initial ranking using DFS.
2107 initRank(flatGraph);
2108
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 });
2114
2115 // Relax original constraints
2116 util.time('constraints.relax', constraints.relax(g));
2117
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 }
2125
2126 function restoreEdges(g) {
2127 acyclic.undo(g);
2128 }
2129
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 }
2158
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 }
2170
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 }
2180
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 }
2190
2191 function rankComponent(subgraph, useSimplex) {
2192 var spanningTree = feasibleTree(subgraph);
2193
2194 if (useSimplex) {
2195 util.log(1, 'Using network simplex for ranking');
2196 simplex(subgraph, spanningTree);
2197 }
2198 normalize(subgraph);
2199 }
2200
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 }
2205
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');
2208
2209 module.exports = acyclic;
2210 module.exports.undo = undo;
2211
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;
2223
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;
2230
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 });
2243
2244 delete onStack[u];
2245 }
2246
2247 g.eachNode(function(u) { dfs(u); });
2248
2249 util.log(2, 'Acyclic Phase: reversed ' + reverseCount + ' edge(s)');
2250
2251 return reverseCount;
2252 }
2253
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 }
2268
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 }
2278
2279 var value = g.node(u),
2280 prefRank = value.prefRank;
2281 if (prefRank !== undefined) {
2282 if (!checkSupportedPrefRank(prefRank)) { return; }
2283
2284 if (!(prefRank in rankSets)) {
2285 rankSets.prefRank = [u];
2286 } else {
2287 rankSets.prefRank.push(u);
2288 }
2289
2290 var newU = rankSets[prefRank];
2291 if (newU === undefined) {
2292 newU = rankSets[prefRank] = g.addNode(null, { originalNodes: [] });
2293 g.parent(newU, sg);
2294 }
2295
2296 redirectInEdges(g, u, newU, prefRank === 'min');
2297 redirectOutEdges(g, u, newU, prefRank === 'max');
2298
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 });
2304
2305 addLightEdgesFromMinNode(g, sg, rankSets.min);
2306 addLightEdgesToMaxNode(g, sg, rankSets.max);
2307 }
2308
2309 dfs(null);
2310 };
2311
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 }
2319
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 }
2332
2333 // Do not reverse edges for self-loops.
2334 if (origValue.selfLoop) {
2335 reverse = false;
2336 }
2337
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 }
2347
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 }
2360
2361 // Do not reverse edges for self-loops.
2362 if (origValue.selfLoop) {
2363 reverse = false;
2364 }
2365
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 }
2375
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 }
2387
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 }
2399
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 });
2418
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 });
2431
2432 // Restore original edges
2433 originalEdges.forEach(function(edge) {
2434 g.addEdge(edge.e, edge.u, edge.v, edge.value);
2435 });
2436 };
2437
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');
2444
2445 module.exports = feasibleTree;
2446
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();
2474
2475 if (remaining.size() === 1) {
2476 var root = g.nodes()[0];
2477 tree.addNode(root, {});
2478 tree.graph({ root: root });
2479 return tree;
2480 }
2481
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 }
2491
2492 tree.addNode(u, {});
2493 tree.addEdge(null, u, v, { reversed: true });
2494 remaining.remove(u);
2495 addTightEdges(u);
2496 continueToScan = false;
2497 }
2498 });
2499
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 }
2507
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 }
2517
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 });
2529
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 });
2539
2540 tree.eachNode(function(u) { g.node(u).rank -= minSlack; });
2541 }
2542
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 }
2552
2553 return tree;
2554 }
2555
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 }
2562
2563 },{"../util":26,"cp-data":5,"graphlib":28}],23:[function(require,module,exports){
2564 var util = require('../util'),
2565 topsort = require('graphlib').alg.topsort;
2566
2567 module.exports = initRank;
2568
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);
2580
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 }
2587
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 }
2594
2595 },{"../util":26,"graphlib":28}],24:[function(require,module,exports){
2596 module.exports = {
2597 slack: slack
2598 };
2599
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 }
2612
2613 },{}],25:[function(require,module,exports){
2614 var util = require('../util'),
2615 rankUtil = require('./rankUtil');
2616
2617 module.exports = simplex;
2618
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 }
2631
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);
2641
2642 spanningTree.eachEdge(function(id, u, v, treeValue) {
2643 treeValue.cutValue = 0;
2644 });
2645
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 }
2659
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;
2669
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 }
2681
2682 dfs(tree.graph().root);
2683 }
2684
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];
2696
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 }
2703
2704 var cutValue = 0;
2705
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.
2711
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 }
2726
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 }
2740
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 }
2752
2753 if (!tree.edge(parentEdge).reversed) {
2754 cutValue += grandchildCutSum - E + F - G + H;
2755 } else {
2756 cutValue -= grandchildCutSum - E + F - G + H;
2757 }
2758
2759 tree.edge(parentEdge).cutValue = cutValue;
2760 }
2761
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 }
2770
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 }
2786
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;
2798
2799 // Is the tree edge aligned with the graph edge?
2800 var aligned = !tree.edge(e).reversed;
2801
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 }
2825
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 }
2838
2839 return minSlackEdge;
2840 }
2841
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);
2850
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 }
2864
2865 redirect(target);
2866
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 }
2873
2874 tree.graph().root = root;
2875
2876 tree.addEdge(null, source, target, {cutValue: 0});
2877
2878 initCutValues(graph, tree);
2879
2880 adjustRanks(graph, tree);
2881 }
2882
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 }
2898
2899 dfs(tree.graph().root);
2900 }
2901
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 }
2914
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 }
2922
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 };
2930
2931 /*
2932 * Returns the largest value in the array.
2933 */
2934 exports.max = function(values) {
2935 return Math.max.apply(Math, values);
2936 };
2937
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 };
2951
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 };
2958
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 };
2965
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 };
2974
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 };
2983
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 };
2998
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 };
3008
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;
3026
3027 exports.time = time;
3028
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;
3039
3040 exports.log = log;
3041
3042 },{}],27:[function(require,module,exports){
3043 module.exports = '0.4.5';
3044
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");
3051
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 };
3065
3066 exports.converter = {
3067 json: require("./lib/converter/json.js")
3068 };
3069
3070 var filter = require("./lib/filter");
3071 exports.filter = {
3072 all: filter.all,
3073 nodesFromList: filter.nodesFromList
3074 };
3075
3076 exports.version = require("./lib/version");
3077
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 */
3082
3083 module.exports = BaseGraph;
3084
3085 function BaseGraph() {
3086 // The value assigned to the graph itself.
3087 this._value = undefined;
3088
3089 // Map of node id -> { id, value }
3090 this._nodes = {};
3091
3092 // Map of edge id -> { id, u, v, value }
3093 this._edges = {};
3094
3095 // Used to generate a unique id in the graph
3096 this._nextId = 0;
3097 }
3098
3099 // Number of nodes
3100 BaseGraph.prototype.order = function() {
3101 return Object.keys(this._nodes).length;
3102 };
3103
3104 // Number of edges
3105 BaseGraph.prototype.size = function() {
3106 return Object.keys(this._edges).length;
3107 };
3108
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 };
3116
3117 BaseGraph.prototype.hasNode = function(u) {
3118 return u in this._nodes;
3119 };
3120
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 };
3128
3129 BaseGraph.prototype.nodes = function() {
3130 var nodes = [];
3131 this.eachNode(function(id) { nodes.push(id); });
3132 return nodes;
3133 };
3134
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 };
3141
3142 BaseGraph.prototype.hasEdge = function(e) {
3143 return e in this._edges;
3144 };
3145
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 };
3153
3154 BaseGraph.prototype.edges = function() {
3155 var es = [];
3156 this.eachEdge(function(id) { es.push(id); });
3157 return es;
3158 };
3159
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 };
3166
3167 BaseGraph.prototype.incidentNodes = function(e) {
3168 var edge = this._strictGetEdge(e);
3169 return [edge.u, edge.v];
3170 };
3171
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 };
3183
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 };
3189
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);
3196
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 }
3205
3206 this._edges[e] = { id: e, u: u, v: v, value: value };
3207 addEdgeToMap(inMap[v], u, e);
3208 addEdgeToMap(outMap[u], v, e);
3209
3210 return e;
3211 };
3212
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 };
3220
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 };
3229
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 };
3245
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 };
3253
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 };
3261
3262 function addEdgeToMap(map, v, e) {
3263 (map[v] || (map[v] = new Set())).add(e);
3264 }
3265
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 }
3273
3274
3275 },{"cp-data":5}],30:[function(require,module,exports){
3276 var Digraph = require("./Digraph"),
3277 compoundify = require("./compoundify");
3278
3279 var CDigraph = compoundify(Digraph);
3280
3281 module.exports = CDigraph;
3282
3283 CDigraph.fromDigraph = function(src) {
3284 var g = new CDigraph(),
3285 graphValue = src.graph();
3286
3287 if (graphValue !== undefined) {
3288 g.graph(graphValue);
3289 }
3290
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 };
3307
3308 CDigraph.prototype.toString = function() {
3309 return "CDigraph " + JSON.stringify(this, null, 2);
3310 };
3311
3312 },{"./Digraph":32,"./compoundify":45}],31:[function(require,module,exports){
3313 var Graph = require("./Graph"),
3314 compoundify = require("./compoundify");
3315
3316 var CGraph = compoundify(Graph);
3317
3318 module.exports = CGraph;
3319
3320 CGraph.fromGraph = function(src) {
3321 var g = new CGraph(),
3322 graphValue = src.graph();
3323
3324 if (graphValue !== undefined) {
3325 g.graph(graphValue);
3326 }
3327
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 };
3344
3345 CGraph.prototype.toString = function() {
3346 return "CGraph " + JSON.stringify(this, null, 2);
3347 };
3348
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 */
3359
3360 var util = require("./util"),
3361 BaseGraph = require("./BaseGraph"),
3362 /* jshint -W079 */
3363 Set = require("cp-data").Set;
3364 /* jshint +W079 */
3365
3366 module.exports = Digraph;
3367
3368 /*
3369 * Constructor to create a new directed multi-graph.
3370 */
3371 function Digraph() {
3372 BaseGraph.call(this);
3373
3374 /*! Map of sourceId -> {targetId -> Set of edge ids} */
3375 this._inEdges = {};
3376
3377 /*! Map of targetId -> {sourceId -> Set of edge ids} */
3378 this._outEdges = {};
3379 }
3380
3381 Digraph.prototype = new BaseGraph();
3382 Digraph.prototype.constructor = Digraph;
3383
3384 /*
3385 * Always returns `true`.
3386 */
3387 Digraph.prototype.isDirected = function() {
3388 return true;
3389 };
3390
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 };
3404
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 };
3418
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 };
3429
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 };
3440
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 };
3451
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 };
3461
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 };
3471
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 };
3494
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 };
3517
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 };
3538
3539 /*
3540 * Returns a string representation of this graph.
3541 */
3542 Digraph.prototype.toString = function() {
3543 return "Digraph " + JSON.stringify(this, null, 2);
3544 };
3545
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 };
3560
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 };
3573
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 };
3593
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 };
3603
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 };
3615
3616
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 */
3627
3628 var util = require("./util"),
3629 BaseGraph = require("./BaseGraph"),
3630 /* jshint -W079 */
3631 Set = require("cp-data").Set;
3632 /* jshint +W079 */
3633
3634 module.exports = Graph;
3635
3636 /*
3637 * Constructor to create a new undirected multi-graph.
3638 */
3639 function Graph() {
3640 BaseGraph.call(this);
3641
3642 /*! Map of nodeId -> { otherNodeId -> Set of edge ids } */
3643 this._incidentEdges = {};
3644 }
3645
3646 Graph.prototype = new BaseGraph();
3647 Graph.prototype.constructor = Graph;
3648
3649 /*
3650 * Always returns `false`.
3651 */
3652 Graph.prototype.isDirected = function() {
3653 return false;
3654 };
3655
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 };
3666
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 };
3687
3688 /*
3689 * Returns a string representation of this graph.
3690 */
3691 Graph.prototype.toString = function() {
3692 return "Graph " + JSON.stringify(this, null, 2);
3693 };
3694
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 };
3708
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 };
3720
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 };
3740
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 };
3750
3751
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 */
3756
3757 module.exports = components;
3758
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();
3773
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 }
3783
3784 g.nodes().forEach(function(v) {
3785 var component = [];
3786 dfs(v, component);
3787 if (component.length > 0) {
3788 results.push(component);
3789 }
3790 });
3791
3792 return results;
3793 }
3794
3795 },{"cp-data":5}],35:[function(require,module,exports){
3796 var PriorityQueue = require("cp-data").PriorityQueue;
3797
3798 module.exports = dijkstra;
3799
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();
3831
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;
3838
3839 if (weight < 0) {
3840 throw new Error("dijkstra does not allow negative edge weights. Bad edge: " + e + " Weight: " + weight);
3841 }
3842
3843 if (distance < vEntry.distance) {
3844 vEntry.distance = distance;
3845 vEntry.predecessor = u;
3846 pq.decrease(v, distance);
3847 }
3848 }
3849
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); });
3854
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 });
3860
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 }
3868
3869 incidentFunc(u).forEach(updateNeighbors);
3870 }
3871
3872 return results;
3873 }
3874
3875 },{"cp-data":5}],36:[function(require,module,exports){
3876 var dijkstra = require("./dijkstra");
3877
3878 module.exports = dijkstraAll;
3879
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 }
3911
3912 },{"./dijkstra":35}],37:[function(require,module,exports){
3913 var tarjan = require("./tarjan");
3914
3915 module.exports = findCycles;
3916
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 }
3933
3934 },{"./tarjan":43}],38:[function(require,module,exports){
3935 module.exports = floydWarshall;
3936
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();
3969
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); });
3974
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 });
3992
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 });
4009
4010 return results;
4011 }
4012
4013 },{}],39:[function(require,module,exports){
4014 var topsort = require("./topsort");
4015
4016 module.exports = isAcyclic;
4017
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 }
4038
4039 },{"./topsort":44}],40:[function(require,module,exports){
4040 /* jshint -W079 */
4041 var Set = require("cp-data").Set;
4042 /* jshint +W079 */
4043
4044 module.exports = postorder;
4045
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 }
4065
4066 },{"cp-data":5}],41:[function(require,module,exports){
4067 /* jshint -W079 */
4068 var Set = require("cp-data").Set;
4069 /* jshint +W079 */
4070
4071 module.exports = preorder;
4072
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 }
4092
4093 },{"cp-data":5}],42:[function(require,module,exports){
4094 var Graph = require("../Graph"),
4095 PriorityQueue = require("cp-data").PriorityQueue;
4096
4097 module.exports = prim;
4098
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;
4121
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 }
4134
4135 if (g.order() === 0) {
4136 return result;
4137 }
4138
4139 g.eachNode(function(u) {
4140 pq.add(u, Number.POSITIVE_INFINITY);
4141 result.addNode(u);
4142 });
4143
4144 // Start from an arbitrary node
4145 pq.decrease(g.nodes()[0], 0);
4146
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 }
4157
4158 g.incidentEdges(u).forEach(updateNeighbors);
4159 }
4160
4161 return result;
4162 }
4163
4164 },{"../Graph":33,"cp-data":5}],43:[function(require,module,exports){
4165 module.exports = tarjan;
4166
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 }
4188
4189 var index = 0,
4190 stack = [],
4191 visited = {}, // node id -> { onStack, lowlink, index }
4192 results = [];
4193
4194 function dfs(u) {
4195 var entry = visited[u] = {
4196 onStack: true,
4197 lowlink: index,
4198 index: index++
4199 };
4200 stack.push(u);
4201
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 });
4210
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 }
4222
4223 g.nodes().forEach(function(u) {
4224 if (!(u in visited)) {
4225 dfs(u);
4226 }
4227 });
4228
4229 return results;
4230 }
4231
4232 },{}],44:[function(require,module,exports){
4233 module.exports = topsort;
4234 topsort.CycleException = CycleException;
4235
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 }
4251
4252 var visited = {};
4253 var stack = {};
4254 var results = [];
4255
4256 function visit(node) {
4257 if (node in stack) {
4258 throw new CycleException();
4259 }
4260
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 }
4271
4272 var sinks = g.sinks();
4273 if (g.order() !== 0 && sinks.length === 0) {
4274 throw new CycleException();
4275 }
4276
4277 g.sinks().forEach(function(sink) {
4278 visit(sink);
4279 });
4280
4281 return results;
4282 }
4283
4284 function CycleException() {}
4285
4286 CycleException.prototype.toString = function() {
4287 return "Graph has at least one cycle";
4288 };
4289
4290 },{}],45:[function(require,module,exports){
4291 // This file provides a helper function that mixes-in Dot behavior to an
4292 // existing graph prototype.
4293
4294 /* jshint -W079 */
4295 var Set = require("cp-data").Set;
4296 /* jshint +W079 */
4297
4298 module.exports = compoundify;
4299
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);
4305
4306 // Map of object id -> parent id (or null for root graph)
4307 this._parents = {};
4308
4309 // Map of id (or null) -> children set
4310 this._children = {};
4311 this._children[null] = new Set();
4312 }
4313
4314 Constructor.prototype = new SuperConstructor();
4315 Constructor.prototype.constructor = Constructor;
4316
4317 Constructor.prototype.parent = function(u, parent) {
4318 this._strictGetNode(u);
4319
4320 if (arguments.length < 2) {
4321 return this._parents[u];
4322 }
4323
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 }
4330
4331 this._children[this._parents[u]].remove(u);
4332 this._parents[u] = parent;
4333 this._children[parent].add(u);
4334 };
4335
4336 Constructor.prototype.children = function(u) {
4337 if (u !== null) {
4338 this._strictGetNode(u);
4339 }
4340 return this._children[u].keys();
4341 };
4342
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 };
4350
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);
4357
4358 this._children[parent].remove(u);
4359 delete this._parents[u];
4360 delete this._children[u];
4361
4362 return SuperConstructor.prototype.delNode.call(this, u);
4363 };
4364
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 };
4372
4373 Constructor.prototype.filterNodes = function(filter) {
4374 var self = this,
4375 copy = SuperConstructor.prototype.filterNodes.call(this, filter);
4376
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 }
4389
4390 copy.eachNode(function(u) { copy.parent(u, findParent(u)); });
4391
4392 return copy;
4393 };
4394
4395 return Constructor;
4396 }
4397
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");
4403
4404 exports.decode = function(nodes, edges, Ctor) {
4405 Ctor = Ctor || Digraph;
4406
4407 if (typeOf(nodes) !== "Array") {
4408 throw new Error("nodes is not an Array");
4409 }
4410
4411 if (typeOf(edges) !== "Array") {
4412 throw new Error("edges is not an Array");
4413 }
4414
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 }
4424
4425 var graph = new Ctor();
4426
4427 nodes.forEach(function(u) {
4428 graph.addNode(u.id, u.value);
4429 });
4430
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 }
4441
4442 edges.forEach(function(e) {
4443 graph.addEdge(e.id, e.u, e.v, e.value);
4444 });
4445
4446 return graph;
4447 };
4448
4449 exports.encode = function(graph) {
4450 var nodes = [];
4451 var edges = [];
4452
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 });
4463
4464 graph.eachEdge(function(e, u, v, value) {
4465 edges.push({id: e, u: u, v: v, value: value});
4466 });
4467
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 }
4480
4481 return { nodes: nodes, edges: edges, type: type };
4482 };
4483
4484 function typeOf(obj) {
4485 return Object.prototype.toString.call(obj).slice(8, -1);
4486 }
4487
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 */
4492
4493 exports.all = function() {
4494 return function() { return true; };
4495 };
4496
4497 exports.nodesFromList = function(nodes) {
4498 var set = new Set(nodes);
4499 return function(u) {
4500 return set.has(u);
4501 };
4502 };
4503
4504 },{"cp-data":5}],48:[function(require,module,exports){
4505 var Graph = require("./Graph"),
4506 Digraph = require("./Digraph");
4507
4508 // Side-effect based changes are lousy, but node doesn't seem to resolve the
4509 // requires cycle.
4510
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 };
4527
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 };
4542
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 };
4555
4556 },{}],50:[function(require,module,exports){
4557 module.exports = '0.7.4';
4558
4559 },{}]},{},[1])
4560 ;

mercurial