08-27-周三_17-09-29
This commit is contained in:
27
node_modules/graphlib/lib/alg/components.js
generated
vendored
Normal file
27
node_modules/graphlib/lib/alg/components.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
var _ = require("../lodash");
|
||||
|
||||
module.exports = components;
|
||||
|
||||
function components(g) {
|
||||
var visited = {};
|
||||
var cmpts = [];
|
||||
var cmpt;
|
||||
|
||||
function dfs(v) {
|
||||
if (_.has(visited, v)) return;
|
||||
visited[v] = true;
|
||||
cmpt.push(v);
|
||||
_.each(g.successors(v), dfs);
|
||||
_.each(g.predecessors(v), dfs);
|
||||
}
|
||||
|
||||
_.each(g.nodes(), function(v) {
|
||||
cmpt = [];
|
||||
dfs(v);
|
||||
if (cmpt.length) {
|
||||
cmpts.push(cmpt);
|
||||
}
|
||||
});
|
||||
|
||||
return cmpts;
|
||||
}
|
42
node_modules/graphlib/lib/alg/dfs.js
generated
vendored
Normal file
42
node_modules/graphlib/lib/alg/dfs.js
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
var _ = require("../lodash");
|
||||
|
||||
module.exports = dfs;
|
||||
|
||||
/*
|
||||
* A helper that preforms a pre- or post-order traversal on the input graph
|
||||
* and returns the nodes in the order they were visited. If the graph is
|
||||
* undirected then this algorithm will navigate using neighbors. If the graph
|
||||
* is directed then this algorithm will navigate using successors.
|
||||
*
|
||||
* Order must be one of "pre" or "post".
|
||||
*/
|
||||
function dfs(g, vs, order) {
|
||||
if (!_.isArray(vs)) {
|
||||
vs = [vs];
|
||||
}
|
||||
|
||||
var navigation = (g.isDirected() ? g.successors : g.neighbors).bind(g);
|
||||
|
||||
var acc = [];
|
||||
var visited = {};
|
||||
_.each(vs, function(v) {
|
||||
if (!g.hasNode(v)) {
|
||||
throw new Error("Graph does not have node: " + v);
|
||||
}
|
||||
|
||||
doDfs(g, v, order === "post", visited, navigation, acc);
|
||||
});
|
||||
return acc;
|
||||
}
|
||||
|
||||
function doDfs(g, v, postorder, visited, navigation, acc) {
|
||||
if (!_.has(visited, v)) {
|
||||
visited[v] = true;
|
||||
|
||||
if (!postorder) { acc.push(v); }
|
||||
_.each(navigation(v), function(w) {
|
||||
doDfs(g, w, postorder, visited, navigation, acc);
|
||||
});
|
||||
if (postorder) { acc.push(v); }
|
||||
}
|
||||
}
|
10
node_modules/graphlib/lib/alg/dijkstra-all.js
generated
vendored
Normal file
10
node_modules/graphlib/lib/alg/dijkstra-all.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
var dijkstra = require("./dijkstra");
|
||||
var _ = require("../lodash");
|
||||
|
||||
module.exports = dijkstraAll;
|
||||
|
||||
function dijkstraAll(g, weightFunc, edgeFunc) {
|
||||
return _.transform(g.nodes(), function(acc, v) {
|
||||
acc[v] = dijkstra(g, v, weightFunc, edgeFunc);
|
||||
}, {});
|
||||
}
|
54
node_modules/graphlib/lib/alg/dijkstra.js
generated
vendored
Normal file
54
node_modules/graphlib/lib/alg/dijkstra.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
var _ = require("../lodash");
|
||||
var PriorityQueue = require("../data/priority-queue");
|
||||
|
||||
module.exports = dijkstra;
|
||||
|
||||
var DEFAULT_WEIGHT_FUNC = _.constant(1);
|
||||
|
||||
function dijkstra(g, source, weightFn, edgeFn) {
|
||||
return runDijkstra(g, String(source),
|
||||
weightFn || DEFAULT_WEIGHT_FUNC,
|
||||
edgeFn || function(v) { return g.outEdges(v); });
|
||||
}
|
||||
|
||||
function runDijkstra(g, source, weightFn, edgeFn) {
|
||||
var results = {};
|
||||
var pq = new PriorityQueue();
|
||||
var v, vEntry;
|
||||
|
||||
var updateNeighbors = function(edge) {
|
||||
var w = edge.v !== v ? edge.v : edge.w;
|
||||
var wEntry = results[w];
|
||||
var weight = weightFn(edge);
|
||||
var distance = vEntry.distance + weight;
|
||||
|
||||
if (weight < 0) {
|
||||
throw new Error("dijkstra does not allow negative edge weights. " +
|
||||
"Bad edge: " + edge + " Weight: " + weight);
|
||||
}
|
||||
|
||||
if (distance < wEntry.distance) {
|
||||
wEntry.distance = distance;
|
||||
wEntry.predecessor = v;
|
||||
pq.decrease(w, distance);
|
||||
}
|
||||
};
|
||||
|
||||
g.nodes().forEach(function(v) {
|
||||
var distance = v === source ? 0 : Number.POSITIVE_INFINITY;
|
||||
results[v] = { distance: distance };
|
||||
pq.add(v, distance);
|
||||
});
|
||||
|
||||
while (pq.size() > 0) {
|
||||
v = pq.removeMin();
|
||||
vEntry = results[v];
|
||||
if (vEntry.distance === Number.POSITIVE_INFINITY) {
|
||||
break;
|
||||
}
|
||||
|
||||
edgeFn(v).forEach(updateNeighbors);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
10
node_modules/graphlib/lib/alg/find-cycles.js
generated
vendored
Normal file
10
node_modules/graphlib/lib/alg/find-cycles.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
var _ = require("../lodash");
|
||||
var tarjan = require("./tarjan");
|
||||
|
||||
module.exports = findCycles;
|
||||
|
||||
function findCycles(g) {
|
||||
return _.filter(tarjan(g), function(cmpt) {
|
||||
return cmpt.length > 1 || (cmpt.length === 1 && g.hasEdge(cmpt[0], cmpt[0]));
|
||||
});
|
||||
}
|
50
node_modules/graphlib/lib/alg/floyd-warshall.js
generated
vendored
Normal file
50
node_modules/graphlib/lib/alg/floyd-warshall.js
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
var _ = require("../lodash");
|
||||
|
||||
module.exports = floydWarshall;
|
||||
|
||||
var DEFAULT_WEIGHT_FUNC = _.constant(1);
|
||||
|
||||
function floydWarshall(g, weightFn, edgeFn) {
|
||||
return runFloydWarshall(g,
|
||||
weightFn || DEFAULT_WEIGHT_FUNC,
|
||||
edgeFn || function(v) { return g.outEdges(v); });
|
||||
}
|
||||
|
||||
function runFloydWarshall(g, weightFn, edgeFn) {
|
||||
var results = {};
|
||||
var nodes = g.nodes();
|
||||
|
||||
nodes.forEach(function(v) {
|
||||
results[v] = {};
|
||||
results[v][v] = { distance: 0 };
|
||||
nodes.forEach(function(w) {
|
||||
if (v !== w) {
|
||||
results[v][w] = { distance: Number.POSITIVE_INFINITY };
|
||||
}
|
||||
});
|
||||
edgeFn(v).forEach(function(edge) {
|
||||
var w = edge.v === v ? edge.w : edge.v;
|
||||
var d = weightFn(edge);
|
||||
results[v][w] = { distance: d, predecessor: v };
|
||||
});
|
||||
});
|
||||
|
||||
nodes.forEach(function(k) {
|
||||
var rowK = results[k];
|
||||
nodes.forEach(function(i) {
|
||||
var rowI = results[i];
|
||||
nodes.forEach(function(j) {
|
||||
var ik = rowI[k];
|
||||
var kj = rowK[j];
|
||||
var ij = rowI[j];
|
||||
var altDistance = ik.distance + kj.distance;
|
||||
if (altDistance < ij.distance) {
|
||||
ij.distance = altDistance;
|
||||
ij.predecessor = kj.predecessor;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
13
node_modules/graphlib/lib/alg/index.js
generated
vendored
Normal file
13
node_modules/graphlib/lib/alg/index.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
module.exports = {
|
||||
components: require("./components"),
|
||||
dijkstra: require("./dijkstra"),
|
||||
dijkstraAll: require("./dijkstra-all"),
|
||||
findCycles: require("./find-cycles"),
|
||||
floydWarshall: require("./floyd-warshall"),
|
||||
isAcyclic: require("./is-acyclic"),
|
||||
postorder: require("./postorder"),
|
||||
preorder: require("./preorder"),
|
||||
prim: require("./prim"),
|
||||
tarjan: require("./tarjan"),
|
||||
topsort: require("./topsort")
|
||||
};
|
15
node_modules/graphlib/lib/alg/is-acyclic.js
generated
vendored
Normal file
15
node_modules/graphlib/lib/alg/is-acyclic.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
var topsort = require("./topsort");
|
||||
|
||||
module.exports = isAcyclic;
|
||||
|
||||
function isAcyclic(g) {
|
||||
try {
|
||||
topsort(g);
|
||||
} catch (e) {
|
||||
if (e instanceof topsort.CycleException) {
|
||||
return false;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return true;
|
||||
}
|
7
node_modules/graphlib/lib/alg/postorder.js
generated
vendored
Normal file
7
node_modules/graphlib/lib/alg/postorder.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
var dfs = require("./dfs");
|
||||
|
||||
module.exports = postorder;
|
||||
|
||||
function postorder(g, vs) {
|
||||
return dfs(g, vs, "post");
|
||||
}
|
7
node_modules/graphlib/lib/alg/preorder.js
generated
vendored
Normal file
7
node_modules/graphlib/lib/alg/preorder.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
var dfs = require("./dfs");
|
||||
|
||||
module.exports = preorder;
|
||||
|
||||
function preorder(g, vs) {
|
||||
return dfs(g, vs, "pre");
|
||||
}
|
52
node_modules/graphlib/lib/alg/prim.js
generated
vendored
Normal file
52
node_modules/graphlib/lib/alg/prim.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
var _ = require("../lodash");
|
||||
var Graph = require("../graph");
|
||||
var PriorityQueue = require("../data/priority-queue");
|
||||
|
||||
module.exports = prim;
|
||||
|
||||
function prim(g, weightFunc) {
|
||||
var result = new Graph();
|
||||
var parents = {};
|
||||
var pq = new PriorityQueue();
|
||||
var v;
|
||||
|
||||
function updateNeighbors(edge) {
|
||||
var w = edge.v === v ? edge.w : edge.v;
|
||||
var pri = pq.priority(w);
|
||||
if (pri !== undefined) {
|
||||
var edgeWeight = weightFunc(edge);
|
||||
if (edgeWeight < pri) {
|
||||
parents[w] = v;
|
||||
pq.decrease(w, edgeWeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g.nodeCount() === 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
_.each(g.nodes(), function(v) {
|
||||
pq.add(v, Number.POSITIVE_INFINITY);
|
||||
result.setNode(v);
|
||||
});
|
||||
|
||||
// Start from an arbitrary node
|
||||
pq.decrease(g.nodes()[0], 0);
|
||||
|
||||
var init = false;
|
||||
while (pq.size() > 0) {
|
||||
v = pq.removeMin();
|
||||
if (_.has(parents, v)) {
|
||||
result.setEdge(v, parents[v]);
|
||||
} else if (init) {
|
||||
throw new Error("Input graph is not connected: " + g);
|
||||
} else {
|
||||
init = true;
|
||||
}
|
||||
|
||||
g.nodeEdges(v).forEach(updateNeighbors);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
47
node_modules/graphlib/lib/alg/tarjan.js
generated
vendored
Normal file
47
node_modules/graphlib/lib/alg/tarjan.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
var _ = require("../lodash");
|
||||
|
||||
module.exports = tarjan;
|
||||
|
||||
function tarjan(g) {
|
||||
var index = 0;
|
||||
var stack = [];
|
||||
var visited = {}; // node id -> { onStack, lowlink, index }
|
||||
var results = [];
|
||||
|
||||
function dfs(v) {
|
||||
var entry = visited[v] = {
|
||||
onStack: true,
|
||||
lowlink: index,
|
||||
index: index++
|
||||
};
|
||||
stack.push(v);
|
||||
|
||||
g.successors(v).forEach(function(w) {
|
||||
if (!_.has(visited, w)) {
|
||||
dfs(w);
|
||||
entry.lowlink = Math.min(entry.lowlink, visited[w].lowlink);
|
||||
} else if (visited[w].onStack) {
|
||||
entry.lowlink = Math.min(entry.lowlink, visited[w].index);
|
||||
}
|
||||
});
|
||||
|
||||
if (entry.lowlink === entry.index) {
|
||||
var cmpt = [];
|
||||
var w;
|
||||
do {
|
||||
w = stack.pop();
|
||||
visited[w].onStack = false;
|
||||
cmpt.push(w);
|
||||
} while (v !== w);
|
||||
results.push(cmpt);
|
||||
}
|
||||
}
|
||||
|
||||
g.nodes().forEach(function(v) {
|
||||
if (!_.has(visited, v)) {
|
||||
dfs(v);
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
35
node_modules/graphlib/lib/alg/topsort.js
generated
vendored
Normal file
35
node_modules/graphlib/lib/alg/topsort.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
var _ = require("../lodash");
|
||||
|
||||
module.exports = topsort;
|
||||
topsort.CycleException = CycleException;
|
||||
|
||||
function topsort(g) {
|
||||
var visited = {};
|
||||
var stack = {};
|
||||
var results = [];
|
||||
|
||||
function visit(node) {
|
||||
if (_.has(stack, node)) {
|
||||
throw new CycleException();
|
||||
}
|
||||
|
||||
if (!_.has(visited, node)) {
|
||||
stack[node] = true;
|
||||
visited[node] = true;
|
||||
_.each(g.predecessors(node), visit);
|
||||
delete stack[node];
|
||||
results.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
_.each(g.sinks(), visit);
|
||||
|
||||
if (_.size(visited) !== g.nodeCount()) {
|
||||
throw new CycleException();
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function CycleException() {}
|
||||
CycleException.prototype = new Error(); // must be an instance of Error to pass testing
|
Reference in New Issue
Block a user