@dagrejs/dagre 0.7.5 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -8
- package/dist/dagre.js +1520 -13628
- package/dist/dagre.min.js +355 -7520
- package/index.js +1 -1
- package/lib/acyclic.js +14 -14
- package/lib/add-border-segments.js +11 -12
- package/lib/coordinate-system.js +10 -12
- package/lib/data/list.js +5 -5
- package/lib/debug.js +6 -7
- package/lib/greedy-fas.js +33 -27
- package/lib/layout.js +115 -102
- package/lib/nesting-graph.js +20 -25
- package/lib/normalize.js +13 -14
- package/lib/order/add-subgraph-constraints.js +6 -8
- package/lib/order/barycenter.js +4 -6
- package/lib/order/build-layer-graph.js +11 -11
- package/lib/order/cross-count.js +10 -14
- package/lib/order/index.js +15 -22
- package/lib/order/init-order.js +9 -11
- package/lib/order/resolve-conflicts.js +17 -22
- package/lib/order/sort-subgraph.js +18 -21
- package/lib/order/sort.js +10 -11
- package/lib/parent-dummy-chains.js +19 -21
- package/lib/position/bk.js +125 -101
- package/lib/position/index.js +16 -14
- package/lib/rank/feasible-tree.js +21 -15
- package/lib/rank/index.js +8 -8
- package/lib/rank/network-simplex.js +46 -45
- package/lib/rank/util.js +7 -5
- package/lib/util.js +121 -51
- package/lib/version.js +1 -1
- package/package.json +34 -25
- package/.jscsrc +0 -6
- package/.jshintrc +0 -24
- package/.travis.yml +0 -7
- package/bower.json +0 -26
- package/dist/dagre.core.js +0 -2904
- package/dist/dagre.core.min.js +0 -470
- package/karma.conf.js +0 -68
- package/karma.core.conf.js +0 -70
- package/lib/graphlib.js +0 -15
- package/lib/lodash.js +0 -15
package/lib/position/bk.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
util = require("../util");
|
|
3
|
+
var Graph = require("@dagrejs/graphlib").Graph;
|
|
4
|
+
var util = require("../util");
|
|
6
5
|
|
|
7
6
|
/*
|
|
8
7
|
* This module provides coordinate assignment based on Brandes and Köpf, "Fast
|
|
@@ -51,17 +50,17 @@ function findType1Conflicts(g, layering) {
|
|
|
51
50
|
// segment.
|
|
52
51
|
scanPos = 0,
|
|
53
52
|
prevLayerLength = prevLayer.length,
|
|
54
|
-
lastNode =
|
|
53
|
+
lastNode = layer[layer.length - 1];
|
|
55
54
|
|
|
56
|
-
|
|
55
|
+
layer.forEach(function(v, i) {
|
|
57
56
|
var w = findOtherInnerSegmentNode(g, v),
|
|
58
|
-
|
|
57
|
+
k1 = w ? g.node(w).order : prevLayerLength;
|
|
59
58
|
|
|
60
59
|
if (w || v === lastNode) {
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
layer.slice(scanPos, i+1).forEach(function(scanNode) {
|
|
61
|
+
g.predecessors(scanNode).forEach(function(u) {
|
|
63
62
|
var uLabel = g.node(u),
|
|
64
|
-
|
|
63
|
+
uPos = uLabel.order;
|
|
65
64
|
if ((uPos < k0 || k1 < uPos) &&
|
|
66
65
|
!(uLabel.dummy && g.node(scanNode).dummy)) {
|
|
67
66
|
addConflict(conflicts, u, scanNode);
|
|
@@ -76,7 +75,7 @@ function findType1Conflicts(g, layering) {
|
|
|
76
75
|
return layer;
|
|
77
76
|
}
|
|
78
77
|
|
|
79
|
-
|
|
78
|
+
layering.reduce(visitLayer);
|
|
80
79
|
return conflicts;
|
|
81
80
|
}
|
|
82
81
|
|
|
@@ -85,10 +84,10 @@ function findType2Conflicts(g, layering) {
|
|
|
85
84
|
|
|
86
85
|
function scan(south, southPos, southEnd, prevNorthBorder, nextNorthBorder) {
|
|
87
86
|
var v;
|
|
88
|
-
|
|
87
|
+
util.range(southPos, southEnd).forEach(function(i) {
|
|
89
88
|
v = south[i];
|
|
90
89
|
if (g.node(v).dummy) {
|
|
91
|
-
|
|
90
|
+
g.predecessors(v).forEach(function(u) {
|
|
92
91
|
var uNode = g.node(u);
|
|
93
92
|
if (uNode.dummy &&
|
|
94
93
|
(uNode.order < prevNorthBorder || uNode.order > nextNorthBorder)) {
|
|
@@ -102,10 +101,10 @@ function findType2Conflicts(g, layering) {
|
|
|
102
101
|
|
|
103
102
|
function visitLayer(north, south) {
|
|
104
103
|
var prevNorthPos = -1,
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
nextNorthPos,
|
|
105
|
+
southPos = 0;
|
|
107
106
|
|
|
108
|
-
|
|
107
|
+
south.forEach(function(v, southLookahead) {
|
|
109
108
|
if (g.node(v).dummy === "border") {
|
|
110
109
|
var predecessors = g.predecessors(v);
|
|
111
110
|
if (predecessors.length) {
|
|
@@ -121,15 +120,13 @@ function findType2Conflicts(g, layering) {
|
|
|
121
120
|
return south;
|
|
122
121
|
}
|
|
123
122
|
|
|
124
|
-
|
|
123
|
+
layering.reduce(visitLayer);
|
|
125
124
|
return conflicts;
|
|
126
125
|
}
|
|
127
126
|
|
|
128
127
|
function findOtherInnerSegmentNode(g, v) {
|
|
129
128
|
if (g.node(v).dummy) {
|
|
130
|
-
return
|
|
131
|
-
return g.node(u).dummy;
|
|
132
|
-
});
|
|
129
|
+
return g.predecessors(v).find(u => g.node(u).dummy);
|
|
133
130
|
}
|
|
134
131
|
}
|
|
135
132
|
|
|
@@ -153,7 +150,7 @@ function hasConflict(conflicts, v, w) {
|
|
|
153
150
|
v = w;
|
|
154
151
|
w = tmp;
|
|
155
152
|
}
|
|
156
|
-
return
|
|
153
|
+
return !!conflicts[v] && conflicts[v].hasOwnProperty(w);
|
|
157
154
|
}
|
|
158
155
|
|
|
159
156
|
/*
|
|
@@ -166,26 +163,26 @@ function hasConflict(conflicts, v, w) {
|
|
|
166
163
|
*/
|
|
167
164
|
function verticalAlignment(g, layering, conflicts, neighborFn) {
|
|
168
165
|
var root = {},
|
|
169
|
-
|
|
170
|
-
|
|
166
|
+
align = {},
|
|
167
|
+
pos = {};
|
|
171
168
|
|
|
172
169
|
// We cache the position here based on the layering because the graph and
|
|
173
170
|
// layering may be out of sync. The layering matrix is manipulated to
|
|
174
171
|
// generate different extreme alignments.
|
|
175
|
-
|
|
176
|
-
|
|
172
|
+
layering.forEach(function(layer) {
|
|
173
|
+
layer.forEach(function(v, order) {
|
|
177
174
|
root[v] = v;
|
|
178
175
|
align[v] = v;
|
|
179
176
|
pos[v] = order;
|
|
180
177
|
});
|
|
181
178
|
});
|
|
182
179
|
|
|
183
|
-
|
|
180
|
+
layering.forEach(function(layer) {
|
|
184
181
|
var prevIdx = -1;
|
|
185
|
-
|
|
182
|
+
layer.forEach(function(v) {
|
|
186
183
|
var ws = neighborFn(v);
|
|
187
184
|
if (ws.length) {
|
|
188
|
-
ws =
|
|
185
|
+
ws = ws.sort((a, b) => pos[a] - pos[b]);
|
|
189
186
|
var mp = (ws.length - 1) / 2;
|
|
190
187
|
for (var i = Math.floor(mp), il = Math.ceil(mp); i <= il; ++i) {
|
|
191
188
|
var w = ws[i];
|
|
@@ -211,41 +208,50 @@ function horizontalCompaction(g, layering, root, align, reverseSep) {
|
|
|
211
208
|
// coordinates. The second sweep removes unused space by moving blocks to the
|
|
212
209
|
// greatest coordinates without violating separation.
|
|
213
210
|
var xs = {},
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
211
|
+
blockG = buildBlockGraph(g, layering, root, reverseSep),
|
|
212
|
+
borderType = reverseSep ? "borderLeft" : "borderRight";
|
|
213
|
+
|
|
214
|
+
function iterate(setXsFunc, nextNodesFunc) {
|
|
215
|
+
var stack = blockG.nodes();
|
|
216
|
+
var elem = stack.pop();
|
|
217
|
+
var visited = {};
|
|
218
|
+
while (elem) {
|
|
219
|
+
if (visited[elem]) {
|
|
220
|
+
setXsFunc(elem);
|
|
221
|
+
} else {
|
|
222
|
+
visited[elem] = true;
|
|
223
|
+
stack.push(elem);
|
|
224
|
+
stack = stack.concat(nextNodesFunc(elem));
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
elem = stack.pop();
|
|
225
228
|
}
|
|
226
229
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
230
|
+
|
|
231
|
+
// First pass, assign smallest coordinates
|
|
232
|
+
function pass1(elem) {
|
|
233
|
+
xs[elem] = blockG.inEdges(elem).reduce(function(acc, e) {
|
|
234
|
+
return Math.max(acc, xs[e.v] + blockG.edge(e));
|
|
235
|
+
}, 0);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Second pass, assign greatest coordinates
|
|
239
|
+
function pass2(elem) {
|
|
240
|
+
var min = blockG.outEdges(elem).reduce(function(acc, e) {
|
|
241
|
+
return Math.min(acc, xs[e.w] - blockG.edge(e));
|
|
242
|
+
}, Number.POSITIVE_INFINITY);
|
|
243
|
+
|
|
244
|
+
var node = g.node(elem);
|
|
245
|
+
if (min !== Number.POSITIVE_INFINITY && node.borderType !== borderType) {
|
|
246
|
+
xs[elem] = Math.max(xs[elem], min);
|
|
241
247
|
}
|
|
242
248
|
}
|
|
243
|
-
|
|
249
|
+
|
|
250
|
+
iterate(pass1, blockG.predecessors.bind(blockG));
|
|
251
|
+
iterate(pass2, blockG.successors.bind(blockG));
|
|
244
252
|
|
|
245
253
|
// Assign x coordinates to all nodes
|
|
246
|
-
|
|
247
|
-
xs[v] = xs[root[v]];
|
|
248
|
-
});
|
|
254
|
+
Object.keys(align).forEach(v => xs[v] = xs[root[v]]);
|
|
249
255
|
|
|
250
256
|
return xs;
|
|
251
257
|
}
|
|
@@ -253,17 +259,17 @@ function horizontalCompaction(g, layering, root, align, reverseSep) {
|
|
|
253
259
|
|
|
254
260
|
function buildBlockGraph(g, layering, root, reverseSep) {
|
|
255
261
|
var blockGraph = new Graph(),
|
|
256
|
-
|
|
257
|
-
|
|
262
|
+
graphLabel = g.graph(),
|
|
263
|
+
sepFn = sep(graphLabel.nodesep, graphLabel.edgesep, reverseSep);
|
|
258
264
|
|
|
259
|
-
|
|
265
|
+
layering.forEach(function(layer) {
|
|
260
266
|
var u;
|
|
261
|
-
|
|
267
|
+
layer.forEach(function(v) {
|
|
262
268
|
var vRoot = root[v];
|
|
263
269
|
blockGraph.setNode(vRoot);
|
|
264
270
|
if (u) {
|
|
265
271
|
var uRoot = root[u],
|
|
266
|
-
|
|
272
|
+
prevMax = blockGraph.edge(uRoot, vRoot);
|
|
267
273
|
blockGraph.setEdge(uRoot, vRoot, Math.max(sepFn(g, v, u), prevMax || 0));
|
|
268
274
|
}
|
|
269
275
|
u = v;
|
|
@@ -277,11 +283,23 @@ function buildBlockGraph(g, layering, root, reverseSep) {
|
|
|
277
283
|
* Returns the alignment that has the smallest width of the given alignments.
|
|
278
284
|
*/
|
|
279
285
|
function findSmallestWidthAlignment(g, xss) {
|
|
280
|
-
return
|
|
281
|
-
var
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
286
|
+
return Object.values(xss).reduce((currentMinAndXs, xs) => {
|
|
287
|
+
var max = Number.NEGATIVE_INFINITY;
|
|
288
|
+
var min = Number.POSITIVE_INFINITY;
|
|
289
|
+
|
|
290
|
+
Object.entries(xs).forEach(([v, x]) => {
|
|
291
|
+
var halfWidth = width(g, v) / 2;
|
|
292
|
+
|
|
293
|
+
max = Math.max(x + halfWidth, max);
|
|
294
|
+
min = Math.min(x - halfWidth, min);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
const newMin = max - min;
|
|
298
|
+
if (newMin < currentMinAndXs[0]) {
|
|
299
|
+
currentMinAndXs = [newMin, xs];
|
|
300
|
+
}
|
|
301
|
+
return currentMinAndXs;
|
|
302
|
+
}, [Number.POSITIVE_INFINITY, null])[1];
|
|
285
303
|
}
|
|
286
304
|
|
|
287
305
|
/*
|
|
@@ -292,64 +310,70 @@ function findSmallestWidthAlignment(g, xss) {
|
|
|
292
310
|
* coordinate of the smallest width alignment.
|
|
293
311
|
*/
|
|
294
312
|
function alignCoordinates(xss, alignTo) {
|
|
295
|
-
var
|
|
296
|
-
|
|
313
|
+
var alignToVals = Object.values(alignTo),
|
|
314
|
+
alignToMin = Math.min(...alignToVals),
|
|
315
|
+
alignToMax = Math.max(...alignToVals);
|
|
297
316
|
|
|
298
|
-
|
|
299
|
-
|
|
317
|
+
["u", "d"].forEach(function(vert) {
|
|
318
|
+
["l", "r"].forEach(function(horiz) {
|
|
300
319
|
var alignment = vert + horiz,
|
|
301
|
-
|
|
302
|
-
|
|
320
|
+
xs = xss[alignment];
|
|
321
|
+
|
|
303
322
|
if (xs === alignTo) return;
|
|
304
323
|
|
|
305
|
-
|
|
324
|
+
var xsVals = Object.values(xs);
|
|
325
|
+
let delta = alignToMin - Math.min(...xsVals);
|
|
326
|
+
if (horiz !== "l") {
|
|
327
|
+
delta = alignToMax - Math.max(...xsVals);
|
|
328
|
+
}
|
|
306
329
|
|
|
307
330
|
if (delta) {
|
|
308
|
-
xss[alignment] =
|
|
331
|
+
xss[alignment] = util.mapValues(xs, x => x + delta);
|
|
309
332
|
}
|
|
310
333
|
});
|
|
311
334
|
});
|
|
312
335
|
}
|
|
313
336
|
|
|
314
337
|
function balance(xss, align) {
|
|
315
|
-
return
|
|
338
|
+
return util.mapValues(xss.ul, function(num, v) {
|
|
316
339
|
if (align) {
|
|
317
340
|
return xss[align.toLowerCase()][v];
|
|
318
341
|
} else {
|
|
319
|
-
var xs =
|
|
342
|
+
var xs = Object.values(xss).map(xs => xs[v]).sort((a, b) => a - b);
|
|
320
343
|
return (xs[1] + xs[2]) / 2;
|
|
321
344
|
}
|
|
322
345
|
});
|
|
323
346
|
}
|
|
324
347
|
|
|
325
348
|
function positionX(g) {
|
|
326
|
-
var layering = util.buildLayerMatrix(g)
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
349
|
+
var layering = util.buildLayerMatrix(g);
|
|
350
|
+
var conflicts = Object.assign(
|
|
351
|
+
findType1Conflicts(g, layering),
|
|
352
|
+
findType2Conflicts(g, layering));
|
|
353
|
+
|
|
354
|
+
var xss = {};
|
|
355
|
+
var adjustedLayering;
|
|
356
|
+
["u", "d"].forEach(function(vert) {
|
|
357
|
+
adjustedLayering = vert === "u" ? layering : Object.values(layering).reverse();
|
|
358
|
+
["l", "r"].forEach(function(horiz) {
|
|
335
359
|
if (horiz === "r") {
|
|
336
|
-
adjustedLayering =
|
|
337
|
-
return
|
|
360
|
+
adjustedLayering = adjustedLayering.map(inner => {
|
|
361
|
+
return Object.values(inner).reverse();
|
|
338
362
|
});
|
|
339
363
|
}
|
|
340
364
|
|
|
341
|
-
var neighborFn =
|
|
365
|
+
var neighborFn = (vert === "u" ? g.predecessors : g.successors).bind(g);
|
|
342
366
|
var align = verticalAlignment(g, adjustedLayering, conflicts, neighborFn);
|
|
343
367
|
var xs = horizontalCompaction(g, adjustedLayering,
|
|
344
|
-
|
|
345
|
-
horiz === "r");
|
|
368
|
+
align.root, align.align, horiz === "r");
|
|
346
369
|
if (horiz === "r") {
|
|
347
|
-
xs =
|
|
370
|
+
xs = util.mapValues(xs, x => -x);
|
|
348
371
|
}
|
|
349
372
|
xss[vert + horiz] = xs;
|
|
350
373
|
});
|
|
351
374
|
});
|
|
352
375
|
|
|
376
|
+
|
|
353
377
|
var smallestWidth = findSmallestWidthAlignment(g, xss);
|
|
354
378
|
alignCoordinates(xss, smallestWidth);
|
|
355
379
|
return balance(xss, g.graph().align);
|
|
@@ -357,16 +381,16 @@ function positionX(g) {
|
|
|
357
381
|
|
|
358
382
|
function sep(nodeSep, edgeSep, reverseSep) {
|
|
359
383
|
return function(g, v, w) {
|
|
360
|
-
var vLabel = g.node(v)
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
384
|
+
var vLabel = g.node(v);
|
|
385
|
+
var wLabel = g.node(w);
|
|
386
|
+
var sum = 0;
|
|
387
|
+
var delta;
|
|
364
388
|
|
|
365
389
|
sum += vLabel.width / 2;
|
|
366
|
-
if (
|
|
390
|
+
if (vLabel.hasOwnProperty("labelpos")) {
|
|
367
391
|
switch (vLabel.labelpos.toLowerCase()) {
|
|
368
|
-
|
|
369
|
-
|
|
392
|
+
case "l": delta = -vLabel.width / 2; break;
|
|
393
|
+
case "r": delta = vLabel.width / 2; break;
|
|
370
394
|
}
|
|
371
395
|
}
|
|
372
396
|
if (delta) {
|
|
@@ -378,10 +402,10 @@ function sep(nodeSep, edgeSep, reverseSep) {
|
|
|
378
402
|
sum += (wLabel.dummy ? edgeSep : nodeSep) / 2;
|
|
379
403
|
|
|
380
404
|
sum += wLabel.width / 2;
|
|
381
|
-
if (
|
|
405
|
+
if (wLabel.hasOwnProperty("labelpos")) {
|
|
382
406
|
switch (wLabel.labelpos.toLowerCase()) {
|
|
383
|
-
|
|
384
|
-
|
|
407
|
+
case "l": delta = wLabel.width / 2; break;
|
|
408
|
+
case "r": delta = -wLabel.width / 2; break;
|
|
385
409
|
}
|
|
386
410
|
}
|
|
387
411
|
if (delta) {
|
package/lib/position/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
positionX = require("./bk").positionX;
|
|
3
|
+
var util = require("../util");
|
|
4
|
+
var positionX = require("./bk").positionX;
|
|
6
5
|
|
|
7
6
|
module.exports = position;
|
|
8
7
|
|
|
@@ -10,20 +9,23 @@ function position(g) {
|
|
|
10
9
|
g = util.asNonCompoundGraph(g);
|
|
11
10
|
|
|
12
11
|
positionY(g);
|
|
13
|
-
|
|
14
|
-
g.node(v).x = x;
|
|
15
|
-
});
|
|
12
|
+
Object.entries(positionX(g)).forEach(([v, x]) => g.node(v).x = x);
|
|
16
13
|
}
|
|
17
14
|
|
|
18
15
|
function positionY(g) {
|
|
19
|
-
var layering = util.buildLayerMatrix(g)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
var layering = util.buildLayerMatrix(g);
|
|
17
|
+
var rankSep = g.graph().ranksep;
|
|
18
|
+
var prevY = 0;
|
|
19
|
+
layering.forEach(function(layer) {
|
|
20
|
+
const maxHeight = layer.reduce((acc, v) => {
|
|
21
|
+
const height = g.node(v).height;
|
|
22
|
+
if (acc > height) {
|
|
23
|
+
return acc;
|
|
24
|
+
} else {
|
|
25
|
+
return height;
|
|
26
|
+
}
|
|
27
|
+
}, 0);
|
|
28
|
+
layer.forEach(v => g.node(v).y = prevY + maxHeight / 2);
|
|
27
29
|
prevY += maxHeight + rankSep;
|
|
28
30
|
});
|
|
29
31
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
slack = require("./util").slack;
|
|
3
|
+
var Graph = require("@dagrejs/graphlib").Graph;
|
|
4
|
+
var slack = require("./util").slack;
|
|
6
5
|
|
|
7
6
|
module.exports = feasibleTree;
|
|
8
7
|
|
|
@@ -35,8 +34,8 @@ function feasibleTree(g) {
|
|
|
35
34
|
var t = new Graph({ directed: false });
|
|
36
35
|
|
|
37
36
|
// Choose arbitrary node from which to start our tree
|
|
38
|
-
var start = g.nodes()[0]
|
|
39
|
-
|
|
37
|
+
var start = g.nodes()[0];
|
|
38
|
+
var size = g.nodeCount();
|
|
40
39
|
t.setNode(start, {});
|
|
41
40
|
|
|
42
41
|
var edge, delta;
|
|
@@ -55,9 +54,9 @@ function feasibleTree(g) {
|
|
|
55
54
|
*/
|
|
56
55
|
function tightTree(t, g) {
|
|
57
56
|
function dfs(v) {
|
|
58
|
-
|
|
57
|
+
g.nodeEdges(v).forEach(function(e) {
|
|
59
58
|
var edgeV = e.v,
|
|
60
|
-
|
|
59
|
+
w = (v === edgeV) ? e.w : edgeV;
|
|
61
60
|
if (!t.hasNode(w) && !slack(g, e)) {
|
|
62
61
|
t.setNode(w, {});
|
|
63
62
|
t.setEdge(v, w, {});
|
|
@@ -66,7 +65,7 @@ function tightTree(t, g) {
|
|
|
66
65
|
});
|
|
67
66
|
}
|
|
68
67
|
|
|
69
|
-
|
|
68
|
+
t.nodes().forEach(dfs);
|
|
70
69
|
return t.nodeCount();
|
|
71
70
|
}
|
|
72
71
|
|
|
@@ -75,15 +74,22 @@ function tightTree(t, g) {
|
|
|
75
74
|
* it.
|
|
76
75
|
*/
|
|
77
76
|
function findMinSlackEdge(t, g) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
const edges = g.edges();
|
|
78
|
+
|
|
79
|
+
return edges.reduce((acc, edge) => {
|
|
80
|
+
let edgeSlack = Number.POSITIVE_INFINITY;
|
|
81
|
+
if (t.hasNode(edge.v) !== t.hasNode(edge.w)) {
|
|
82
|
+
edgeSlack = slack(g, edge);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (edgeSlack < acc[0]) {
|
|
86
|
+
return [edgeSlack, edge];
|
|
81
87
|
}
|
|
82
|
-
|
|
88
|
+
|
|
89
|
+
return acc;
|
|
90
|
+
}, [Number.POSITIVE_INFINITY, null])[1];
|
|
83
91
|
}
|
|
84
92
|
|
|
85
93
|
function shiftRanks(t, g, delta) {
|
|
86
|
-
|
|
87
|
-
g.node(v).rank += delta;
|
|
88
|
-
});
|
|
94
|
+
t.nodes().forEach(v => g.node(v).rank += delta);
|
|
89
95
|
}
|
package/lib/rank/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var rankUtil = require("./util")
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
var rankUtil = require("./util");
|
|
4
|
+
var longestPath = rankUtil.longestPath;
|
|
5
|
+
var feasibleTree = require("./feasible-tree");
|
|
6
|
+
var networkSimplex = require("./network-simplex");
|
|
7
7
|
|
|
8
8
|
module.exports = rank;
|
|
9
9
|
|
|
@@ -28,10 +28,10 @@ module.exports = rank;
|
|
|
28
28
|
*/
|
|
29
29
|
function rank(g) {
|
|
30
30
|
switch(g.graph().ranker) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
case "network-simplex": networkSimplexRanker(g); break;
|
|
32
|
+
case "tight-tree": tightTreeRanker(g); break;
|
|
33
|
+
case "longest-path": longestPathRanker(g); break;
|
|
34
|
+
default: networkSimplexRanker(g);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|