Digraph.prototype.incidentEdges = function(u, v) { if (arguments.length > 1) { return Set.union([this.outEdges(u, v), this.outEdges(v, u)]).keys(); } else { return Set.union([this.inEdges(u), this.outEdges(u)]).keys(); } };
/* * Given an acyclic graph with each node assigned a `rank` attribute, this * function constructs and returns a spanning tree. This function may reduce * the length of some edges from the initial rank assignment while maintaining * the `minLen` specified by each edge. * * Prerequisites: * * * The input graph is acyclic * * Each node in the input graph has an assigned `rank` attribute * * Each edge in the input graph has an assigned `minLen` attribute * * Outputs: * * A spanning tree of the graph, represented as a Digraph with a `root` * attribute on the graph. Each node in the input graph has an associated node * in the spanning tree, where the ids and values are the same. Each edge in * the spanning tree has an associated edge in the input graph with the same * id. The edge values in the spanning tree are empty objects. */ function feasibleTree(g) { var remaining = new Set(g.nodes()), minLen = [], // Array of {u, v, len} tree = new Digraph(); // Collapse multi-edges and precompute the minLen, which will be the // max value of minLen for any edge in the multi-edge. var minLenMap = {}; g.eachEdge(function(e, u, v, edge) { var id = incidenceId(u, v); if (!(id in minLenMap)) { minLen.push(minLenMap[id] = { e: e, u: u, v: v, len: 0 }); } minLenMap[id].len = Math.max(minLenMap[id].len, edge.minLen); }); // Remove arbitrary node - it is effectively the root of the spanning tree. var root = g.nodes()[0]; remaining.remove(root); var nodeVal = g.node(root); tree.addNode(root, nodeVal); tree.graph({root: root}); // Finds the next edge with the minimum slack. function findMinSlack() { var result, eSlack = Number.POSITIVE_INFINITY; minLen.forEach(function(mle /* minLen entry */) { if (remaining.has(mle.u) !== remaining.has(mle.v)) { var mleSlack = rankUtil.slack(g, mle.u, mle.v, mle.len); if (mleSlack < eSlack) { if (!remaining.has(mle.u)) { result = { mle: mle, treeNode: mle.u, graphNode: mle.v, len: mle.len}; } else { result = { mle: mle, treeNode: mle.v, graphNode: mle.u, len: -mle.len }; } eSlack = mleSlack; } } }); return result; } while (remaining.size() > 0) { var result = findMinSlack(); nodeVal = g.node(result.graphNode); remaining.remove(result.graphNode); tree.addNode(result.graphNode, nodeVal); tree.addEdge(result.mle.e, result.treeNode, result.graphNode, {}); nodeVal.rank = g.node(result.treeNode).rank + result.len; } return tree; }
Digraph.prototype.outEdges = function(source, target) { this._strictGetNode(source); var results = Set.union(util.values(this._outEdges[source])).keys(); if (arguments.length > 1) { this._strictGetNode(target); results = results.filter(function(e) { return this.target(e) === target; }, this); } return results; };
Digraph.prototype.inEdges = function(target, source) { this._strictGetNode(target); var results = Set.union(util.values(this._inEdges[target])).keys(); if (arguments.length > 1) { this._strictGetNode(source); results = results.filter(function(e) { return this.source(e) === source; }, this); } return results; };
Digraph.prototype.neighbors = function(u) { return Set.union([this.successors(u), this.predecessors(u)]).keys(); };
return function(u) { return set.has(u); };
exports.nodesFromList = function(nodes) { var set = new Set(nodes); return function(u) { return set.has(u); }; };