@statewalker/fsm-charts 0.0.1
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/CHANGELOG.md +1 -0
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/dist/StateChart-DNGQd1XG.d.ts +53 -0
- package/dist/chunk-3GGM3ZWL.js +2685 -0
- package/dist/chunk-NXWOFQMO.js +10 -0
- package/dist/chunk-TPNWHU7Y.js +437 -0
- package/dist/index-layout.d.ts +96 -0
- package/dist/index-layout.js +2 -0
- package/dist/index-svg.d.ts +25 -0
- package/dist/index-svg.js +2 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/package.json +60 -0
- package/src/FsmStateConfig.ts +5 -0
- package/src/dagre/acyclic.d.ts +2 -0
- package/src/dagre/acyclic.js +60 -0
- package/src/dagre/add-border-segments.d.ts +1 -0
- package/src/dagre/add-border-segments.js +36 -0
- package/src/dagre/coordinate-system.d.ts +2 -0
- package/src/dagre/coordinate-system.js +75 -0
- package/src/dagre/data/list.d.ts +12 -0
- package/src/dagre/data/list.js +55 -0
- package/src/dagre/debug.d.ts +2 -0
- package/src/dagre/debug.js +32 -0
- package/src/dagre/greedy-fas.d.ts +1 -0
- package/src/dagre/greedy-fas.js +126 -0
- package/src/dagre/index.d.ts +5 -0
- package/src/dagre/index.js +6 -0
- package/src/dagre/layout.d.ts +1 -0
- package/src/dagre/layout.js +466 -0
- package/src/dagre/nesting-graph.d.ts +2 -0
- package/src/dagre/nesting-graph.js +137 -0
- package/src/dagre/normalize.d.ts +2 -0
- package/src/dagre/normalize.js +91 -0
- package/src/dagre/order/add-subgraph-constraints.d.ts +1 -0
- package/src/dagre/order/add-subgraph-constraints.js +53 -0
- package/src/dagre/order/barycenter.d.ts +15 -0
- package/src/dagre/order/barycenter.js +31 -0
- package/src/dagre/order/build-layer-graph.d.ts +2 -0
- package/src/dagre/order/build-layer-graph.js +76 -0
- package/src/dagre/order/cross-count.d.ts +1 -0
- package/src/dagre/order/cross-count.js +82 -0
- package/src/dagre/order/index.d.ts +1 -0
- package/src/dagre/order/index.js +77 -0
- package/src/dagre/order/init-order.d.ts +1 -0
- package/src/dagre/order/init-order.js +44 -0
- package/src/dagre/order/resolve-conflicts.d.ts +1 -0
- package/src/dagre/order/resolve-conflicts.js +128 -0
- package/src/dagre/order/sort-subgraph.d.ts +8 -0
- package/src/dagre/order/sort-subgraph.js +78 -0
- package/src/dagre/order/sort.d.ts +6 -0
- package/src/dagre/order/sort.js +59 -0
- package/src/dagre/parent-dummy-chains.d.ts +1 -0
- package/src/dagre/parent-dummy-chains.js +86 -0
- package/src/dagre/position/bk.d.ts +31 -0
- package/src/dagre/position/bk.js +423 -0
- package/src/dagre/position/index.d.ts +1 -0
- package/src/dagre/position/index.js +31 -0
- package/src/dagre/rank/feasible-tree.d.ts +2 -0
- package/src/dagre/rank/feasible-tree.js +87 -0
- package/src/dagre/rank/index.d.ts +1 -0
- package/src/dagre/rank/index.js +52 -0
- package/src/dagre/rank/network-simplex.d.ts +16 -0
- package/src/dagre/rank/network-simplex.js +236 -0
- package/src/dagre/rank/util.d.ts +2 -0
- package/src/dagre/rank/util.js +63 -0
- package/src/dagre/util.d.ts +27 -0
- package/src/dagre/util.js +250 -0
- package/src/graphlib/alg/components.d.ts +1 -0
- package/src/graphlib/alg/components.js +27 -0
- package/src/graphlib/alg/dfs.d.ts +1 -0
- package/src/graphlib/alg/dfs.js +46 -0
- package/src/graphlib/alg/dijkstra-all.d.ts +1 -0
- package/src/graphlib/alg/dijkstra-all.js +14 -0
- package/src/graphlib/alg/dijkstra.d.ts +1 -0
- package/src/graphlib/alg/dijkstra.js +65 -0
- package/src/graphlib/alg/find-cycles.d.ts +1 -0
- package/src/graphlib/alg/find-cycles.js +10 -0
- package/src/graphlib/alg/floyd-warshall.d.ts +1 -0
- package/src/graphlib/alg/floyd-warshall.js +55 -0
- package/src/graphlib/alg/index.d.ts +24 -0
- package/src/graphlib/alg/index.js +25 -0
- package/src/graphlib/alg/is-acyclic.d.ts +1 -0
- package/src/graphlib/alg/is-acyclic.js +15 -0
- package/src/graphlib/alg/postorder.d.ts +1 -0
- package/src/graphlib/alg/postorder.js +7 -0
- package/src/graphlib/alg/preorder.d.ts +1 -0
- package/src/graphlib/alg/preorder.js +7 -0
- package/src/graphlib/alg/prim.d.ts +2 -0
- package/src/graphlib/alg/prim.js +52 -0
- package/src/graphlib/alg/tarjan.d.ts +1 -0
- package/src/graphlib/alg/tarjan.js +47 -0
- package/src/graphlib/alg/topsort.d.ts +5 -0
- package/src/graphlib/alg/topsort.js +36 -0
- package/src/graphlib/data/priority-queue.d.ts +59 -0
- package/src/graphlib/data/priority-queue.js +152 -0
- package/src/graphlib/graph.d.ts +55 -0
- package/src/graphlib/graph.js +510 -0
- package/src/graphlib/index.d.ts +3 -0
- package/src/graphlib/index.js +7 -0
- package/src/graphlib/json.d.ts +16 -0
- package/src/graphlib/json.js +63 -0
- package/src/index-layout.ts +1 -0
- package/src/index-svg.ts +1 -0
- package/src/index.ts +2 -0
- package/src/layout/Dimensions.ts +8 -0
- package/src/layout/GraphParamsProvider.ts +17 -0
- package/src/layout/Padding.ts +10 -0
- package/src/layout/Position.ts +4 -0
- package/src/layout/StateChart.ts +8 -0
- package/src/layout/StateGraphEdge.ts +14 -0
- package/src/layout/StateGraphNode.ts +12 -0
- package/src/layout/Transition.ts +5 -0
- package/src/layout/TransitionsGraph.ts +13 -0
- package/src/layout/buildCharts.ts +74 -0
- package/src/layout/buildFlatCharts.ts +142 -0
- package/src/layout/getGraphParamsProvider.ts +63 -0
- package/src/layout/getLabelDimensions.ts +59 -0
- package/src/layout/index.ts +15 -0
- package/src/lodash-es/_deleteme.js +291 -0
- package/src/lodash-es/index.ts +9 -0
- package/src/lodash-es/types.ts +35 -0
- package/src/svg/buildStatechartCss.ts +120 -0
- package/src/svg/buildStatechartSvg.ts +256 -0
- package/src/svg/buildStatechartsPanel.ts +38 -0
- package/src/svg/index.ts +3 -0
- package/src/utils/BasisCurve.ts +89 -0
- package/src/utils/getPadding.ts +13 -0
- package/src/utils/serializeAttrs.ts +28 -0
- package/src/utils/serializeStyle.ts +11 -0
- package/src/utils/toKebabCase.ts +18 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { _ } from '../lodash-es/index.ts';
|
|
2
|
+
import { greedyFAS } from './greedy-fas.js';
|
|
3
|
+
|
|
4
|
+
export { run, undo };
|
|
5
|
+
|
|
6
|
+
function run(g) {
|
|
7
|
+
var fas = g.graph().acyclicer === 'greedy' ? greedyFAS(g, weightFn(g)) : dfsFAS(g);
|
|
8
|
+
_.forEach(fas, function (e) {
|
|
9
|
+
var label = g.edge(e);
|
|
10
|
+
g.removeEdge(e);
|
|
11
|
+
label.forwardName = e.name;
|
|
12
|
+
label.reversed = true;
|
|
13
|
+
g.setEdge(e.w, e.v, label, _.uniqueId('rev'));
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
function weightFn(g) {
|
|
17
|
+
return function (e) {
|
|
18
|
+
return g.edge(e).weight;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function dfsFAS(g) {
|
|
24
|
+
var fas = [];
|
|
25
|
+
var stack = {};
|
|
26
|
+
var visited = {};
|
|
27
|
+
|
|
28
|
+
function dfs(v) {
|
|
29
|
+
if (_.has(visited, v)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
visited[v] = true;
|
|
33
|
+
stack[v] = true;
|
|
34
|
+
_.forEach(g.outEdges(v), function (e) {
|
|
35
|
+
if (_.has(stack, e.w)) {
|
|
36
|
+
fas.push(e);
|
|
37
|
+
} else {
|
|
38
|
+
dfs(e.w);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
delete stack[v];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
_.forEach(g.nodes(), dfs);
|
|
45
|
+
return fas;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function undo(g) {
|
|
49
|
+
_.forEach(g.edges(), function (e) {
|
|
50
|
+
var label = g.edge(e);
|
|
51
|
+
if (label.reversed) {
|
|
52
|
+
g.removeEdge(e);
|
|
53
|
+
|
|
54
|
+
var forwardName = label.forwardName;
|
|
55
|
+
delete label.reversed;
|
|
56
|
+
delete label.forwardName;
|
|
57
|
+
g.setEdge(e.w, e.v, label, forwardName);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function addBorderSegments(g: any): void;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { _ } from '../lodash-es/index.ts';
|
|
2
|
+
import * as util from './util.js';
|
|
3
|
+
|
|
4
|
+
export { addBorderSegments };
|
|
5
|
+
|
|
6
|
+
function addBorderSegments(g) {
|
|
7
|
+
function dfs(v) {
|
|
8
|
+
var children = g.children(v);
|
|
9
|
+
var node = g.node(v);
|
|
10
|
+
if (children.length) {
|
|
11
|
+
_.forEach(children, dfs);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (_.has(node, 'minRank')) {
|
|
15
|
+
node.borderLeft = [];
|
|
16
|
+
node.borderRight = [];
|
|
17
|
+
for (var rank = node.minRank, maxRank = node.maxRank + 1; rank < maxRank; ++rank) {
|
|
18
|
+
addBorderNode(g, 'borderLeft', '_bl', v, node, rank);
|
|
19
|
+
addBorderNode(g, 'borderRight', '_br', v, node, rank);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
_.forEach(g.children(), dfs);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function addBorderNode(g, prop, prefix, sg, sgNode, rank) {
|
|
28
|
+
var label = { width: 0, height: 0, rank: rank, borderType: prop };
|
|
29
|
+
var prev = sgNode[prop][rank - 1];
|
|
30
|
+
var curr = util.addDummyNode(g, 'border', label, prefix);
|
|
31
|
+
sgNode[prop][rank] = curr;
|
|
32
|
+
g.setParent(curr, sg);
|
|
33
|
+
if (prev) {
|
|
34
|
+
g.setEdge(prev, curr, { weight: 1 });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { _ } from '../lodash-es/index.ts';
|
|
2
|
+
|
|
3
|
+
export { adjust, undo };
|
|
4
|
+
|
|
5
|
+
function adjust(g) {
|
|
6
|
+
var rankDir = g.graph().rankdir.toLowerCase();
|
|
7
|
+
if (rankDir === 'lr' || rankDir === 'rl') {
|
|
8
|
+
swapWidthHeight(g);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function undo(g) {
|
|
13
|
+
var rankDir = g.graph().rankdir.toLowerCase();
|
|
14
|
+
if (rankDir === 'bt' || rankDir === 'rl') {
|
|
15
|
+
reverseY(g);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (rankDir === 'lr' || rankDir === 'rl') {
|
|
19
|
+
swapXY(g);
|
|
20
|
+
swapWidthHeight(g);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function swapWidthHeight(g) {
|
|
25
|
+
_.forEach(g.nodes(), function (v) {
|
|
26
|
+
swapWidthHeightOne(g.node(v));
|
|
27
|
+
});
|
|
28
|
+
_.forEach(g.edges(), function (e) {
|
|
29
|
+
swapWidthHeightOne(g.edge(e));
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function swapWidthHeightOne(attrs) {
|
|
34
|
+
var w = attrs.width;
|
|
35
|
+
attrs.width = attrs.height;
|
|
36
|
+
attrs.height = w;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function reverseY(g) {
|
|
40
|
+
_.forEach(g.nodes(), function (v) {
|
|
41
|
+
reverseYOne(g.node(v));
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
_.forEach(g.edges(), function (e) {
|
|
45
|
+
var edge = g.edge(e);
|
|
46
|
+
_.forEach(edge.points, reverseYOne);
|
|
47
|
+
if (_.has(edge, 'y')) {
|
|
48
|
+
reverseYOne(edge);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function reverseYOne(attrs) {
|
|
54
|
+
attrs.y = -attrs.y;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function swapXY(g) {
|
|
58
|
+
_.forEach(g.nodes(), function (v) {
|
|
59
|
+
swapXYOne(g.node(v));
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
_.forEach(g.edges(), function (e) {
|
|
63
|
+
var edge = g.edge(e);
|
|
64
|
+
_.forEach(edge.points, swapXYOne);
|
|
65
|
+
if (_.has(edge, 'x')) {
|
|
66
|
+
swapXYOne(edge);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function swapXYOne(attrs) {
|
|
72
|
+
var x = attrs.x;
|
|
73
|
+
attrs.x = attrs.y;
|
|
74
|
+
attrs.y = x;
|
|
75
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Simple doubly linked list implementation derived from Cormen, et al.,
|
|
3
|
+
* "Introduction to Algorithms".
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { List };
|
|
7
|
+
|
|
8
|
+
class List {
|
|
9
|
+
constructor() {
|
|
10
|
+
var sentinel = {};
|
|
11
|
+
sentinel._next = sentinel._prev = sentinel;
|
|
12
|
+
this._sentinel = sentinel;
|
|
13
|
+
}
|
|
14
|
+
dequeue() {
|
|
15
|
+
var sentinel = this._sentinel;
|
|
16
|
+
var entry = sentinel._prev;
|
|
17
|
+
if (entry !== sentinel) {
|
|
18
|
+
unlink(entry);
|
|
19
|
+
return entry;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
enqueue(entry) {
|
|
23
|
+
var sentinel = this._sentinel;
|
|
24
|
+
if (entry._prev && entry._next) {
|
|
25
|
+
unlink(entry);
|
|
26
|
+
}
|
|
27
|
+
entry._next = sentinel._next;
|
|
28
|
+
sentinel._next._prev = entry;
|
|
29
|
+
sentinel._next = entry;
|
|
30
|
+
entry._prev = sentinel;
|
|
31
|
+
}
|
|
32
|
+
toString() {
|
|
33
|
+
var strs = [];
|
|
34
|
+
var sentinel = this._sentinel;
|
|
35
|
+
var curr = sentinel._prev;
|
|
36
|
+
while (curr !== sentinel) {
|
|
37
|
+
strs.push(JSON.stringify(curr, filterOutLinks));
|
|
38
|
+
curr = curr._prev;
|
|
39
|
+
}
|
|
40
|
+
return '[' + strs.join(', ') + ']';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function unlink(entry) {
|
|
45
|
+
entry._prev._next = entry._next;
|
|
46
|
+
entry._next._prev = entry._prev;
|
|
47
|
+
delete entry._next;
|
|
48
|
+
delete entry._prev;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function filterOutLinks(k, v) {
|
|
52
|
+
if (k !== '_next' && k !== '_prev') {
|
|
53
|
+
return v;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { _ } from '../lodash-es/index.ts';
|
|
2
|
+
import { Graph } from '../graphlib/index.js';
|
|
3
|
+
import * as util from './util.js';
|
|
4
|
+
|
|
5
|
+
export { debugOrdering };
|
|
6
|
+
|
|
7
|
+
/* istanbul ignore next */
|
|
8
|
+
function debugOrdering(g) {
|
|
9
|
+
var layerMatrix = util.buildLayerMatrix(g);
|
|
10
|
+
|
|
11
|
+
var h = new Graph({ compound: true, multigraph: true }).setGraph({});
|
|
12
|
+
|
|
13
|
+
_.forEach(g.nodes(), function (v) {
|
|
14
|
+
h.setNode(v, { label: v });
|
|
15
|
+
h.setParent(v, 'layer' + g.node(v).rank);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
_.forEach(g.edges(), function (e) {
|
|
19
|
+
h.setEdge(e.v, e.w, {}, e.name);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
_.forEach(layerMatrix, function (layer, i) {
|
|
23
|
+
var layerV = 'layer' + i;
|
|
24
|
+
h.setNode(layerV, { rank: 'same' });
|
|
25
|
+
_.reduce(layer, function (u, v) {
|
|
26
|
+
h.setEdge(u, v, { style: 'invis' });
|
|
27
|
+
return v;
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
return h;
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function greedyFAS(g: any, weightFn: any): any[];
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { _ } from '../lodash-es/index.ts';
|
|
2
|
+
import { Graph } from '../graphlib/index.js';
|
|
3
|
+
import { List } from './data/list.js';
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* A greedy heuristic for finding a feedback arc set for a graph. A feedback
|
|
7
|
+
* arc set is a set of edges that can be removed to make a graph acyclic.
|
|
8
|
+
* The algorithm comes from: P. Eades, X. Lin, and W. F. Smyth, "A fast and
|
|
9
|
+
* effective heuristic for the feedback arc set problem." This implementation
|
|
10
|
+
* adjusts that from the paper to allow for weighted edges.
|
|
11
|
+
*/
|
|
12
|
+
export { greedyFAS };
|
|
13
|
+
|
|
14
|
+
var DEFAULT_WEIGHT_FN = _.constant(1);
|
|
15
|
+
|
|
16
|
+
function greedyFAS(g, weightFn) {
|
|
17
|
+
if (g.nodeCount() <= 1) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
var state = buildState(g, weightFn || DEFAULT_WEIGHT_FN);
|
|
21
|
+
var results = doGreedyFAS(state.graph, state.buckets, state.zeroIdx);
|
|
22
|
+
|
|
23
|
+
// Expand multi-edges
|
|
24
|
+
return _.flatten(
|
|
25
|
+
_.map(results, function (e) {
|
|
26
|
+
return g.outEdges(e.v, e.w);
|
|
27
|
+
})
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function doGreedyFAS(g, buckets, zeroIdx) {
|
|
32
|
+
var results = [];
|
|
33
|
+
var sources = buckets[buckets.length - 1];
|
|
34
|
+
var sinks = buckets[0];
|
|
35
|
+
|
|
36
|
+
var entry;
|
|
37
|
+
while (g.nodeCount()) {
|
|
38
|
+
while ((entry = sinks.dequeue())) {
|
|
39
|
+
removeNode(g, buckets, zeroIdx, entry);
|
|
40
|
+
}
|
|
41
|
+
while ((entry = sources.dequeue())) {
|
|
42
|
+
removeNode(g, buckets, zeroIdx, entry);
|
|
43
|
+
}
|
|
44
|
+
if (g.nodeCount()) {
|
|
45
|
+
for (var i = buckets.length - 2; i > 0; --i) {
|
|
46
|
+
entry = buckets[i].dequeue();
|
|
47
|
+
if (entry) {
|
|
48
|
+
results = results.concat(removeNode(g, buckets, zeroIdx, entry, true));
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return results;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function removeNode(g, buckets, zeroIdx, entry, collectPredecessors) {
|
|
59
|
+
var results = collectPredecessors ? [] : undefined;
|
|
60
|
+
|
|
61
|
+
_.forEach(g.inEdges(entry.v), function (edge) {
|
|
62
|
+
var weight = g.edge(edge);
|
|
63
|
+
var uEntry = g.node(edge.v);
|
|
64
|
+
|
|
65
|
+
if (collectPredecessors) {
|
|
66
|
+
results.push({ v: edge.v, w: edge.w });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
uEntry.out -= weight;
|
|
70
|
+
assignBucket(buckets, zeroIdx, uEntry);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
_.forEach(g.outEdges(entry.v), function (edge) {
|
|
74
|
+
var weight = g.edge(edge);
|
|
75
|
+
var w = edge.w;
|
|
76
|
+
var wEntry = g.node(w);
|
|
77
|
+
wEntry['in'] -= weight;
|
|
78
|
+
assignBucket(buckets, zeroIdx, wEntry);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
g.removeNode(entry.v);
|
|
82
|
+
|
|
83
|
+
return results;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function buildState(g, weightFn) {
|
|
87
|
+
var fasGraph = new Graph();
|
|
88
|
+
var maxIn = 0;
|
|
89
|
+
var maxOut = 0;
|
|
90
|
+
|
|
91
|
+
_.forEach(g.nodes(), function (v) {
|
|
92
|
+
fasGraph.setNode(v, { v: v, in: 0, out: 0 });
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Aggregate weights on nodes, but also sum the weights across multi-edges
|
|
96
|
+
// into a single edge for the fasGraph.
|
|
97
|
+
_.forEach(g.edges(), function (e) {
|
|
98
|
+
var prevWeight = fasGraph.edge(e.v, e.w) || 0;
|
|
99
|
+
var weight = weightFn(e);
|
|
100
|
+
var edgeWeight = prevWeight + weight;
|
|
101
|
+
fasGraph.setEdge(e.v, e.w, edgeWeight);
|
|
102
|
+
maxOut = Math.max(maxOut, (fasGraph.node(e.v).out += weight));
|
|
103
|
+
maxIn = Math.max(maxIn, (fasGraph.node(e.w)['in'] += weight));
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
var buckets = _.range(maxOut + maxIn + 3).map(function () {
|
|
107
|
+
return new List();
|
|
108
|
+
});
|
|
109
|
+
var zeroIdx = maxIn + 1;
|
|
110
|
+
|
|
111
|
+
_.forEach(fasGraph.nodes(), function (v) {
|
|
112
|
+
assignBucket(buckets, zeroIdx, fasGraph.node(v));
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return { graph: fasGraph, buckets: buckets, zeroIdx: zeroIdx };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function assignBucket(buckets, zeroIdx, entry) {
|
|
119
|
+
if (!entry.out) {
|
|
120
|
+
buckets[0].enqueue(entry);
|
|
121
|
+
} else if (!entry['in']) {
|
|
122
|
+
buckets[buckets.length - 1].enqueue(entry);
|
|
123
|
+
} else {
|
|
124
|
+
buckets[entry.out - entry['in'] + zeroIdx].enqueue(entry);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function layout(g: any, opts: any): void;
|