From 6052bcf5bd03307ba62a4e7e02fe71500f3bda67 Mon Sep 17 00:00:00 2001 From: osvalds Date: Fri, 29 Sep 2023 10:21:50 +0300 Subject: [PATCH] v1.0.5-whim --- bower.json | 4 +- dist/dagre.js | 1358 ++++++++++++++++++++++----------------------- dist/dagre.min.js | 420 +++++++------- lib/version.js | 2 +- package-lock.json | 18 +- package.json | 4 +- 6 files changed, 878 insertions(+), 928 deletions(-) diff --git a/bower.json b/bower.json index f8beddfc..b927ec17 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "dagre", - "version": "1.0.6", + "version": "1.0.5-whim", "main": [ "dist/dagre.core.js" ], @@ -20,6 +20,6 @@ "test/**" ], "dependencies": { - "@dagrejs/graphlib": "2.1.13" + "@dagrejs/graphlib": "2.1.10" } } diff --git a/dist/dagre.js b/dist/dagre.js index 2d6257c8..c500011d 100644 --- a/dist/dagre.js +++ b/dist/dagre.js @@ -2979,7 +2979,7 @@ function zipObject(props, values) { } },{"@dagrejs/graphlib":29}],28:[function(require,module,exports){ -module.exports = "1.0.6"; +module.exports = "1.0.5-whim"; },{}],29:[function(require,module,exports){ /** @@ -3057,64 +3057,37 @@ module.exports = dfs; * undirected then this algorithm will navigate using neighbors. If the graph * is directed then this algorithm will navigate using successors. * - * If the order is not "post", it will be treated as "pre". + * Order must be one of "pre" or "post". */ function dfs(g, vs, order) { if (!Array.isArray(vs)) { vs = [vs]; } - var navigation = g.isDirected() ? v => g.successors(v) : v => g.neighbors(v); - var orderFunc = order === "post" ? postOrderDfs : preOrderDfs; + var navigation = (g.isDirected() ? g.successors : g.neighbors).bind(g); var acc = []; var visited = {}; - vs.forEach(v => { + vs.forEach(function(v) { if (!g.hasNode(v)) { throw new Error("Graph does not have node: " + v); } - orderFunc(v, navigation, visited, acc); + doDfs(g, v, order === "post", visited, navigation, acc); }); - return acc; } -function postOrderDfs(v, navigation, visited, acc) { - var stack = [[v, false]]; - while (stack.length > 0) { - var curr = stack.pop(); - if (curr[1]) { - acc.push(curr[0]); - } else { - if (!visited.hasOwnProperty(curr[0])) { - visited[curr[0]] = true; - stack.push([curr[0], true]); - forEachRight(navigation(curr[0]), w => stack.push([w, false])); - } - } - } -} - -function preOrderDfs(v, navigation, visited, acc) { - var stack = [v]; - while (stack.length > 0) { - var curr = stack.pop(); - if (!visited.hasOwnProperty(curr)) { - visited[curr] = true; - acc.push(curr); - forEachRight(navigation(curr), w => stack.push(w)); - } - } -} +function doDfs(g, v, postorder, visited, navigation, acc) { + if (!visited.hasOwnProperty(v)) { + visited[v] = true; -function forEachRight(array, iteratee) { - var length = array.length; - while (length--) { - iteratee(array[length], length, array); + if (!postorder) { acc.push(v); } + navigation(v).forEach(function(w) { + doDfs(g, w, postorder, visited, navigation, acc); + }); + if (postorder) { acc.push(v); } } - - return array; } },{}],32:[function(require,module,exports){ @@ -3396,6 +3369,9 @@ function tarjan(g) { } },{}],42:[function(require,module,exports){ +module.exports = topsort; +topsort.CycleException = CycleException; + function topsort(g) { var visited = {}; var stack = {}; @@ -3424,16 +3400,12 @@ function topsort(g) { return results; } -class CycleException extends Error { - constructor() { - super(...arguments); - } -} - -module.exports = topsort; -topsort.CycleException = CycleException; +function CycleException() {} +CycleException.prototype = new Error(); // must be an instance of Error to pass testing },{}],43:[function(require,module,exports){ +module.exports = PriorityQueue; + /** * A min-priority queue data structure. This algorithm is derived from Cormen, * et al., "Introduction to Algorithms". The basic idea of a min-priority @@ -3441,153 +3413,153 @@ topsort.CycleException = CycleException; * the queue. Adding and removing elements takes O(log n) time. A key can * have its priority decreased in O(log n) time. */ -class PriorityQueue { - #arr = []; - #keyIndices = {}; - - /** - * Returns the number of elements in the queue. Takes `O(1)` time. - */ - size() { - return this.#arr.length; - } +function PriorityQueue() { + this._arr = []; + this._keyIndices = {}; +} - /** - * Returns the keys that are in the queue. Takes `O(n)` time. - */ - keys() { - return this.#arr.map(function(x) { return x.key; }); - } +/** + * Returns the number of elements in the queue. Takes `O(1)` time. + */ +PriorityQueue.prototype.size = function() { + return this._arr.length; +}; - /** - * Returns `true` if **key** is in the queue and `false` if not. - */ - has(key) { - return this.#keyIndices.hasOwnProperty(key); - } +/** + * Returns the keys that are in the queue. Takes `O(n)` time. + */ +PriorityQueue.prototype.keys = function() { + return this._arr.map(function(x) { return x.key; }); +}; - /** - * Returns the priority for **key**. If **key** is not present in the queue - * then this function returns `undefined`. Takes `O(1)` time. - * - * @param {Object} key - */ - priority(key) { - var index = this.#keyIndices[key]; - if (index !== undefined) { - return this.#arr[index].priority; - } - } +/** + * Returns `true` if **key** is in the queue and `false` if not. + */ +PriorityQueue.prototype.has = function(key) { + return this._keyIndices.hasOwnProperty(key); +}; - /** - * Returns the key for the minimum element in this queue. If the queue is - * empty this function throws an Error. Takes `O(1)` time. - */ - min() { - if (this.size() === 0) { - throw new Error("Queue underflow"); - } - return this.#arr[0].key; +/** + * Returns the priority for **key**. If **key** is not present in the queue + * then this function returns `undefined`. Takes `O(1)` time. + * + * @param {Object} key + */ +PriorityQueue.prototype.priority = function(key) { + var index = this._keyIndices[key]; + if (index !== undefined) { + return this._arr[index].priority; } +}; - /** - * Inserts a new key into the priority queue. If the key already exists in - * the queue this function returns `false`; otherwise it will return `true`. - * Takes `O(n)` time. - * - * @param {Object} key the key to add - * @param {Number} priority the initial priority for the key - */ - add(key, priority) { - var keyIndices = this.#keyIndices; - key = String(key); - if (!keyIndices.hasOwnProperty(key)) { - var arr = this.#arr; - var index = arr.length; - keyIndices[key] = index; - arr.push({key: key, priority: priority}); - this.#decrease(index); - return true; - } - return false; +/** + * Returns the key for the minimum element in this queue. If the queue is + * empty this function throws an Error. Takes `O(1)` time. + */ +PriorityQueue.prototype.min = function() { + if (this.size() === 0) { + throw new Error("Queue underflow"); } + return this._arr[0].key; +}; - /** - * Removes and returns the smallest key in the queue. Takes `O(log n)` time. - */ - removeMin() { - this.#swap(0, this.#arr.length - 1); - var min = this.#arr.pop(); - delete this.#keyIndices[min.key]; - this.#heapify(0); - return min.key; - } +/** + * Inserts a new key into the priority queue. If the key already exists in + * the queue this function returns `false`; otherwise it will return `true`. + * Takes `O(n)` time. + * + * @param {Object} key the key to add + * @param {Number} priority the initial priority for the key + */ +PriorityQueue.prototype.add = function(key, priority) { + var keyIndices = this._keyIndices; + key = String(key); + if (!keyIndices.hasOwnProperty(key)) { + var arr = this._arr; + var index = arr.length; + keyIndices[key] = index; + arr.push({key: key, priority: priority}); + this._decrease(index); + return true; + } + return false; +}; - /** - * Decreases the priority for **key** to **priority**. If the new priority is - * greater than the previous priority, this function will throw an Error. - * - * @param {Object} key the key for which to raise priority - * @param {Number} priority the new priority for the key - */ - decrease(key, priority) { - var index = this.#keyIndices[key]; - if (priority > this.#arr[index].priority) { - throw new Error("New priority is greater than current priority. " + - "Key: " + key + " Old: " + this.#arr[index].priority + " New: " + priority); - } - this.#arr[index].priority = priority; - this.#decrease(index); - } +/** + * Removes and returns the smallest key in the queue. Takes `O(log n)` time. + */ +PriorityQueue.prototype.removeMin = function() { + this._swap(0, this._arr.length - 1); + var min = this._arr.pop(); + delete this._keyIndices[min.key]; + this._heapify(0); + return min.key; +}; - #heapify(i) { - var arr = this.#arr; - var l = 2 * i; - var r = l + 1; - var largest = i; - if (l < arr.length) { - largest = arr[l].priority < arr[largest].priority ? l : largest; - if (r < arr.length) { - largest = arr[r].priority < arr[largest].priority ? r : largest; - } - if (largest !== i) { - this.#swap(i, largest); - this.#heapify(largest); - } - } - } +/** + * Decreases the priority for **key** to **priority**. If the new priority is + * greater than the previous priority, this function will throw an Error. + * + * @param {Object} key the key for which to raise priority + * @param {Number} priority the new priority for the key + */ +PriorityQueue.prototype.decrease = function(key, priority) { + var index = this._keyIndices[key]; + if (priority > this._arr[index].priority) { + throw new Error("New priority is greater than current priority. " + + "Key: " + key + " Old: " + this._arr[index].priority + " New: " + priority); + } + this._arr[index].priority = priority; + this._decrease(index); +}; - #decrease(index) { - var arr = this.#arr; - var priority = arr[index].priority; - var parent; - while (index !== 0) { - parent = index >> 1; - if (arr[parent].priority < priority) { - break; - } - this.#swap(index, parent); - index = parent; +PriorityQueue.prototype._heapify = function(i) { + var arr = this._arr; + var l = 2 * i; + var r = l + 1; + var largest = i; + if (l < arr.length) { + largest = arr[l].priority < arr[largest].priority ? l : largest; + if (r < arr.length) { + largest = arr[r].priority < arr[largest].priority ? r : largest; + } + if (largest !== i) { + this._swap(i, largest); + this._heapify(largest); } } +}; - #swap(i, j) { - var arr = this.#arr; - var keyIndices = this.#keyIndices; - var origArrI = arr[i]; - var origArrJ = arr[j]; - arr[i] = origArrJ; - arr[j] = origArrI; - keyIndices[origArrJ.key] = i; - keyIndices[origArrI.key] = j; +PriorityQueue.prototype._decrease = function(index) { + var arr = this._arr; + var priority = arr[index].priority; + var parent; + while (index !== 0) { + parent = index >> 1; + if (arr[parent].priority < priority) { + break; + } + this._swap(index, parent); + index = parent; } -} +}; -module.exports = PriorityQueue; +PriorityQueue.prototype._swap = function(i, j) { + var arr = this._arr; + var keyIndices = this._keyIndices; + var origArrI = arr[i]; + var origArrJ = arr[j]; + arr[i] = origArrJ; + arr[j] = origArrI; + keyIndices[origArrJ.key] = i; + keyIndices[origArrI.key] = j; +}; },{}],44:[function(require,module,exports){ "use strict"; +module.exports = Graph; + var DEFAULT_EDGE_NAME = "\x00"; var GRAPH_NODE = "\x00"; var EDGE_KEY_DELIM = "\x01"; @@ -3602,641 +3574,625 @@ var EDGE_KEY_DELIM = "\x01"; // edges up and, object properties, which have string keys, are the closest // we're going to get to a performant hashtable in JavaScript. -class Graph { - #isDirected = true; - #isMultigraph = false; - #isCompound = false; +function Graph(opts) { + this._isDirected = true; + this._isMultigraph = false; + this._isCompound = false; + + if (opts) { + this._isDirected = opts.hasOwnProperty("directed") ? opts.directed : true; + this._isMultigraph = opts.hasOwnProperty("multigraph") ? opts.multigraph : false; + this._isCompound = opts.hasOwnProperty("compound") ? opts.compound : false; + } // Label for the graph itself - #label; + this._label = undefined; // Defaults to be set when creating a new node - #defaultNodeLabelFn = () => undefined; + this._defaultNodeLabelFn = () => undefined; // Defaults to be set when creating a new edge - #defaultEdgeLabelFn = () => undefined; + this._defaultEdgeLabelFn = () => undefined; // v -> label - #nodes = {}; + this._nodes = {}; + + if (this._isCompound) { + // v -> parent + this._parent = {}; + + // v -> children + this._children = {}; + this._children[GRAPH_NODE] = {}; + } // v -> edgeObj - #in = {}; + this._in = {}; // u -> v -> Number - #preds = {}; + this._preds = {}; // v -> edgeObj - #out = {}; + this._out = {}; // v -> w -> Number - #sucs = {}; + this._sucs = {}; // e -> edgeObj - #edgeObjs = {}; + this._edgeObjs = {}; // e -> label - #edgeLabels = {}; + this._edgeLabels = {}; +} - /* Number of nodes in the graph. Should only be changed by the implementation. */ - #nodeCount = 0; +/* Number of nodes in the graph. Should only be changed by the implementation. */ +Graph.prototype._nodeCount = 0; - /* Number of edges in the graph. Should only be changed by the implementation. */ - #edgeCount = 0; +/* Number of edges in the graph. Should only be changed by the implementation. */ +Graph.prototype._edgeCount = 0; - #parent; - #children; +/* === Graph functions ========= */ - constructor(opts) { - if (opts) { - this.#isDirected = opts.hasOwnProperty("directed") ? opts.directed : true; - this.#isMultigraph = opts.hasOwnProperty("multigraph") ? opts.multigraph : false; - this.#isCompound = opts.hasOwnProperty("compound") ? opts.compound : false; - } +/** + * Whether graph was created with 'directed' flag set to true or not. + */ +Graph.prototype.isDirected = function() { + return this._isDirected; +}; - if (this.#isCompound) { - // v -> parent - this.#parent = {}; +/** + * Whether graph was created with 'multigraph' flag set to true or not. + */ +Graph.prototype.isMultigraph = function() { + return this._isMultigraph; +}; - // v -> children - this.#children = {}; - this.#children[GRAPH_NODE] = {}; - } - } +/** + * Whether graph was created with 'compound' flag set to true or not. + */ +Graph.prototype.isCompound = function() { + return this._isCompound; +}; - /* === Graph functions ========= */ +/** + * Sets the label of the graph. + */ +Graph.prototype.setGraph = function(label) { + this._label = label; + return this; +}; - /** - * Whether graph was created with 'directed' flag set to true or not. - */ - isDirected() { - return this.#isDirected; - } +/** + * Gets the graph label. + */ +Graph.prototype.graph = function() { + return this._label; +}; - /** - * Whether graph was created with 'multigraph' flag set to true or not. - */ - isMultigraph() { - return this.#isMultigraph; - } - /** - * Whether graph was created with 'compound' flag set to true or not. - */ - isCompound() { - return this.#isCompound; - } +/* === Node functions ========== */ - /** - * Sets the label of the graph. - */ - setGraph(label) { - this.#label = label; - return this; +/** + * Sets the default node label. If newDefault is a function, it will be + * invoked ach time when setting a label for a node. Otherwise, this label + * will be assigned as default label in case if no label was specified while + * setting a node. + * Complexity: O(1). + */ +Graph.prototype.setDefaultNodeLabel = function(newDefault) { + this._defaultNodeLabelFn = newDefault; + if (typeof newDefault !== 'function') { + this._defaultNodeLabelFn = () => newDefault; } - /** - * Gets the graph label. - */ - graph() { - return this.#label; - } + return this; +}; + +/** + * Gets the number of nodes in the graph. + * Complexity: O(1). + */ +Graph.prototype.nodeCount = function() { + return this._nodeCount; +}; + +/** + * Gets all nodes of the graph. Note, the in case of compound graph subnodes are + * not included in list. + * Complexity: O(1). + */ +Graph.prototype.nodes = function() { + return Object.keys(this._nodes); +}; +/** + * Gets list of nodes without in-edges. + * Complexity: O(|V|). + */ +Graph.prototype.sources = function() { + var self = this; + return this.nodes().filter(v => Object.keys(self._in[v]).length === 0); +}; - /* === Node functions ========== */ +/** + * Gets list of nodes without out-edges. + * Complexity: O(|V|). + */ +Graph.prototype.sinks = function() { + var self = this; + return this.nodes().filter(v => Object.keys(self._out[v]).length === 0); +}; - /** - * Sets the default node label. If newDefault is a function, it will be - * invoked ach time when setting a label for a node. Otherwise, this label - * will be assigned as default label in case if no label was specified while - * setting a node. - * Complexity: O(1). - */ - setDefaultNodeLabel(newDefault) { - this.#defaultNodeLabelFn = newDefault; - if (typeof newDefault !== 'function') { - this.#defaultNodeLabelFn = () => newDefault; +/** + * Invokes setNode method for each node in names list. + * Complexity: O(|names|). + */ +Graph.prototype.setNodes = function(vs, value) { + var args = arguments; + var self = this; + vs.forEach(function(v) { + if (args.length > 1) { + self.setNode(v, value); + } else { + self.setNode(v); } + }); + return this; +}; +/** + * Creates or updates the value for the node v in the graph. If label is supplied + * it is set as the value for the node. If label is not supplied and the node was + * created by this call then the default node label will be assigned. + * Complexity: O(1). + */ +Graph.prototype.setNode = function(v, value) { + if (this._nodes.hasOwnProperty(v)) { + if (arguments.length > 1) { + this._nodes[v] = value; + } return this; } - /** - * Gets the number of nodes in the graph. - * Complexity: O(1). - */ - nodeCount() { - return this.#nodeCount; + this._nodes[v] = arguments.length > 1 ? value : this._defaultNodeLabelFn(v); + if (this._isCompound) { + this._parent[v] = GRAPH_NODE; + this._children[v] = {}; + this._children[GRAPH_NODE][v] = true; } + this._in[v] = {}; + this._preds[v] = {}; + this._out[v] = {}; + this._sucs[v] = {}; + ++this._nodeCount; + return this; +}; - /** - * Gets all nodes of the graph. Note, the in case of compound graph subnodes are - * not included in list. - * Complexity: O(1). - */ - nodes() { - return Object.keys(this.#nodes); - } +/** + * Gets the label of node with specified name. + * Complexity: O(|V|). + */ +Graph.prototype.node = function(v) { + return this._nodes[v]; +}; - /** - * Gets list of nodes without in-edges. - * Complexity: O(|V|). - */ - sources() { - var self = this; - return this.nodes().filter(v => Object.keys(self.#in[v]).length === 0); - } +/** + * Detects whether graph has a node with specified name or not. + */ +Graph.prototype.hasNode = function(v) { + return this._nodes.hasOwnProperty(v); +}; - /** - * Gets list of nodes without out-edges. - * Complexity: O(|V|). - */ - sinks() { - var self = this; - return this.nodes().filter(v => Object.keys(self.#out[v]).length === 0); - } +/** + * Remove the node with the name from the graph or do nothing if the node is not in + * the graph. If the node was removed this function also removes any incident + * edges. + * Complexity: O(1). + */ +Graph.prototype.removeNode = function(v) { + var self = this; + if (this._nodes.hasOwnProperty(v)) { + var removeEdge = e => self.removeEdge(self._edgeObjs[e]); + delete this._nodes[v]; + if (this._isCompound) { + this._removeFromParentsChildList(v); + delete this._parent[v]; + this.children(v).forEach(function(child) { + self.setParent(child); + }); + delete this._children[v]; + } + Object.keys(this._in[v]).forEach(removeEdge); + delete this._in[v]; + delete this._preds[v]; + Object.keys(this._out[v]).forEach(removeEdge); + delete this._out[v]; + delete this._sucs[v]; + --this._nodeCount; + } + return this; +}; - /** - * Invokes setNode method for each node in names list. - * Complexity: O(|names|). - */ - setNodes(vs, value) { - var args = arguments; - var self = this; - vs.forEach(function(v) { - if (args.length > 1) { - self.setNode(v, value); - } else { - self.setNode(v); - } - }); - return this; +/** + * Sets node p as a parent for node v if it is defined, or removes the + * parent for v if p is undefined. Method throws an exception in case of + * invoking it in context of noncompound graph. + * Average-case complexity: O(1). + */ +Graph.prototype.setParent = function(v, parent) { + if (!this._isCompound) { + throw new Error("Cannot set parent in a non-compound graph"); } - /** - * Creates or updates the value for the node v in the graph. If label is supplied - * it is set as the value for the node. If label is not supplied and the node was - * created by this call then the default node label will be assigned. - * Complexity: O(1). - */ - setNode(v, value) { - if (this.#nodes.hasOwnProperty(v)) { - if (arguments.length > 1) { - this.#nodes[v] = value; + if (parent === undefined) { + parent = GRAPH_NODE; + } else { + // Coerce parent to string + parent += ""; + for (var ancestor = parent; + ancestor !== undefined; + ancestor = this.parent(ancestor)) { + if (ancestor === v) { + throw new Error("Setting " + parent+ " as parent of " + v + + " would create a cycle"); } - return this; } - this.#nodes[v] = arguments.length > 1 ? value : this.#defaultNodeLabelFn(v); - if (this.#isCompound) { - this.#parent[v] = GRAPH_NODE; - this.#children[v] = {}; - this.#children[GRAPH_NODE][v] = true; - } - this.#in[v] = {}; - this.#preds[v] = {}; - this.#out[v] = {}; - this.#sucs[v] = {}; - ++this.#nodeCount; - return this; + this.setNode(parent); } - /** - * Gets the label of node with specified name. - * Complexity: O(|V|). - */ - node(v) { - return this.#nodes[v]; - } + this.setNode(v); + this._removeFromParentsChildList(v); + this._parent[v] = parent; + this._children[parent][v] = true; + return this; +}; - /** - * Detects whether graph has a node with specified name or not. - */ - hasNode(v) { - return this.#nodes.hasOwnProperty(v); - } +Graph.prototype._removeFromParentsChildList = function(v) { + delete this._children[this._parent[v]][v]; +}; - /** - * Remove the node with the name from the graph or do nothing if the node is not in - * the graph. If the node was removed this function also removes any incident - * edges. - * Complexity: O(1). - */ - removeNode(v) { - var self = this; - if (this.#nodes.hasOwnProperty(v)) { - var removeEdge = e => self.removeEdge(self.#edgeObjs[e]); - delete this.#nodes[v]; - if (this.#isCompound) { - this.#removeFromParentsChildList(v); - delete this.#parent[v]; - this.children(v).forEach(function(child) { - self.setParent(child); - }); - delete this.#children[v]; - } - Object.keys(this.#in[v]).forEach(removeEdge); - delete this.#in[v]; - delete this.#preds[v]; - Object.keys(this.#out[v]).forEach(removeEdge); - delete this.#out[v]; - delete this.#sucs[v]; - --this.#nodeCount; +/** + * Gets parent node for node v. + * Complexity: O(1). + */ +Graph.prototype.parent = function(v) { + if (this._isCompound) { + var parent = this._parent[v]; + if (parent !== GRAPH_NODE) { + return parent; } - return this; } +}; - /** - * Sets node p as a parent for node v if it is defined, or removes the - * parent for v if p is undefined. Method throws an exception in case of - * invoking it in context of noncompound graph. - * Average-case complexity: O(1). - */ - setParent(v, parent) { - if (!this.#isCompound) { - throw new Error("Cannot set parent in a non-compound graph"); - } - - if (parent === undefined) { - parent = GRAPH_NODE; - } else { - // Coerce parent to string - parent += ""; - for (var ancestor = parent; ancestor !== undefined; ancestor = this.parent(ancestor)) { - if (ancestor === v) { - throw new Error("Setting " + parent+ " as parent of " + v + - " would create a cycle"); - } - } - - this.setNode(parent); +/** + * Gets list of direct children of node v. + * Complexity: O(1). + */ +Graph.prototype.children = function(v = GRAPH_NODE) { + if (this._isCompound) { + var children = this._children[v]; + if (children) { + return Object.keys(children); } - - this.setNode(v); - this.#removeFromParentsChildList(v); - this.#parent[v] = parent; - this.#children[parent][v] = true; - return this; + } else if (v === GRAPH_NODE) { + return this.nodes(); + } else if (this.hasNode(v)) { + return []; } +}; - #removeFromParentsChildList(v) { - delete this.#children[this.#parent[v]][v]; +/** + * Return all nodes that are predecessors of the specified node or undefined if node v is not in + * the graph. Behavior is undefined for undirected graphs - use neighbors instead. + * Complexity: O(|V|). + */ +Graph.prototype.predecessors = function(v) { + var predsV = this._preds[v]; + if (predsV) { + return Object.keys(predsV); } +}; - /** - * Gets parent node for node v. - * Complexity: O(1). - */ - parent(v) { - if (this.#isCompound) { - var parent = this.#parent[v]; - if (parent !== GRAPH_NODE) { - return parent; - } - } +/** + * Return all nodes that are successors of the specified node or undefined if node v is not in + * the graph. Behavior is undefined for undirected graphs - use neighbors instead. + * Complexity: O(|V|). + */ +Graph.prototype.successors = function(v) { + var sucsV = this._sucs[v]; + if (sucsV) { + return Object.keys(sucsV); } +}; - /** - * Gets list of direct children of node v. - * Complexity: O(1). - */ - children(v = GRAPH_NODE) { - if (this.#isCompound) { - var children = this.#children[v]; - if (children) { - return Object.keys(children); - } - } else if (v === GRAPH_NODE) { - return this.nodes(); - } else if (this.hasNode(v)) { - return []; +/** + * Return all nodes that are predecessors or successors of the specified node or undefined if + * node v is not in the graph. + * Complexity: O(|V|). + */ +Graph.prototype.neighbors = function(v) { + var preds = this.predecessors(v); + if (preds) { + const union = new Set(preds); + for (var succ of this.successors(v)) { + union.add(succ); } - } - /** - * Return all nodes that are predecessors of the specified node or undefined if node v is not in - * the graph. Behavior is undefined for undirected graphs - use neighbors instead. - * Complexity: O(|V|). - */ - predecessors(v) { - var predsV = this.#preds[v]; - if (predsV) { - return Object.keys(predsV); - } + return Array.from(union.values()); } +}; - /** - * Return all nodes that are successors of the specified node or undefined if node v is not in - * the graph. Behavior is undefined for undirected graphs - use neighbors instead. - * Complexity: O(|V|). - */ - successors(v) { - var sucsV = this.#sucs[v]; - if (sucsV) { - return Object.keys(sucsV); - } +Graph.prototype.isLeaf = function (v) { + var neighbors; + if (this.isDirected()) { + neighbors = this.successors(v); + } else { + neighbors = this.neighbors(v); } + return neighbors.length === 0; +}; - /** - * Return all nodes that are predecessors or successors of the specified node or undefined if - * node v is not in the graph. - * Complexity: O(|V|). - */ - neighbors(v) { - var preds = this.predecessors(v); - if (preds) { - const union = new Set(preds); - for (var succ of this.successors(v)) { - union.add(succ); - } +/** + * Creates new graph with nodes filtered via filter. Edges incident to rejected node + * are also removed. In case of compound graph, if parent is rejected by filter, + * than all its children are rejected too. + * Average-case complexity: O(|E|+|V|). + */ +Graph.prototype.filterNodes = function(filter) { + var copy = new this.constructor({ + directed: this._isDirected, + multigraph: this._isMultigraph, + compound: this._isCompound + }); - return Array.from(union.values()); - } - } + copy.setGraph(this.graph()); - isLeaf(v) { - var neighbors; - if (this.isDirected()) { - neighbors = this.successors(v); - } else { - neighbors = this.neighbors(v); + var self = this; + Object.entries(this._nodes).forEach(function([v, value]) { + if (filter(v)) { + copy.setNode(v, value); } - return neighbors.length === 0; - } - - /** - * Creates new graph with nodes filtered via filter. Edges incident to rejected node - * are also removed. In case of compound graph, if parent is rejected by filter, - * than all its children are rejected too. - * Average-case complexity: O(|E|+|V|). - */ - filterNodes(filter) { - var copy = new this.constructor({ - directed: this.#isDirected, - multigraph: this.#isMultigraph, - compound: this.#isCompound - }); - - copy.setGraph(this.graph()); - - var self = this; - Object.entries(this.#nodes).forEach(function([v, value]) { - if (filter(v)) { - copy.setNode(v, value); - } - }); - - Object.values(this.#edgeObjs).forEach(function(e) { - if (copy.hasNode(e.v) && copy.hasNode(e.w)) { - copy.setEdge(e, self.edge(e)); - } - }); + }); - var parents = {}; - function findParent(v) { - var parent = self.parent(v); - if (parent === undefined || copy.hasNode(parent)) { - parents[v] = parent; - return parent; - } else if (parent in parents) { - return parents[parent]; - } else { - return findParent(parent); - } + Object.values(this._edgeObjs).forEach(function(e) { + if (copy.hasNode(e.v) && copy.hasNode(e.w)) { + copy.setEdge(e, self.edge(e)); } + }); - if (this.#isCompound) { - copy.nodes().forEach(v => copy.setParent(v, findParent(v))); + var parents = {}; + function findParent(v) { + var parent = self.parent(v); + if (parent === undefined || copy.hasNode(parent)) { + parents[v] = parent; + return parent; + } else if (parent in parents) { + return parents[parent]; + } else { + return findParent(parent); } + } - return copy; + if (this._isCompound) { + copy.nodes().forEach(v => copy.setParent(v, findParent(v))); } - /* === Edge functions ========== */ - - /** - * Sets the default edge label or factory function. This label will be - * assigned as default label in case if no label was specified while setting - * an edge or this function will be invoked each time when setting an edge - * with no label specified and returned value * will be used as a label for edge. - * Complexity: O(1). - */ - setDefaultEdgeLabel(newDefault) { - this.#defaultEdgeLabelFn = newDefault; - if (typeof newDefault !== 'function') { - this.#defaultEdgeLabelFn = () => newDefault; - } + return copy; +}; - return this; - } +/* === Edge functions ========== */ - /** - * Gets the number of edges in the graph. - * Complexity: O(1). - */ - edgeCount() { - return this.#edgeCount; +/** + * Sets the default edge label or factory function. This label will be + * assigned as default label in case if no label was specified while setting + * an edge or this function will be invoked each time when setting an edge + * with no label specified and returned value * will be used as a label for edge. + * Complexity: O(1). + */ +Graph.prototype.setDefaultEdgeLabel = function(newDefault) { + this._defaultEdgeLabelFn = newDefault; + if (typeof newDefault !== 'function') { + this._defaultEdgeLabelFn = () => newDefault; } - /** - * Gets edges of the graph. In case of compound graph subgraphs are not considered. - * Complexity: O(|E|). - */ - edges() { - return Object.values(this.#edgeObjs); - } + return this; +}; - /** - * Establish an edges path over the nodes in nodes list. If some edge is already - * exists, it will update its label, otherwise it will create an edge between pair - * of nodes with label provided or default label if no label provided. - * Complexity: O(|nodes|). - */ - setPath(vs, value) { - var self = this; - var args = arguments; - vs.reduce(function(v, w) { - if (args.length > 1) { - self.setEdge(v, w, value); - } else { - self.setEdge(v, w); - } - return w; - }); - return this; - } +/** + * Gets the number of edges in the graph. + * Complexity: O(1). + */ +Graph.prototype.edgeCount = function() { + return this._edgeCount; +}; - /** - * Creates or updates the label for the edge (v, w) with the optionally supplied - * name. If label is supplied it is set as the value for the edge. If label is not - * supplied and the edge was created by this call then the default edge label will - * be assigned. The name parameter is only useful with multigraphs. - */ - setEdge() { - var v, w, name, value; - var valueSpecified = false; - var arg0 = arguments[0]; - - if (typeof arg0 === "object" && arg0 !== null && "v" in arg0) { - v = arg0.v; - w = arg0.w; - name = arg0.name; - if (arguments.length === 2) { - value = arguments[1]; - valueSpecified = true; - } +/** + * Gets edges of the graph. In case of compound graph subgraphs are not considered. + * Complexity: O(|E|). + */ +Graph.prototype.edges = function() { + return Object.values(this._edgeObjs); +}; + +/** + * Establish an edges path over the nodes in nodes list. If some edge is already + * exists, it will update its label, otherwise it will create an edge between pair + * of nodes with label provided or default label if no label provided. + * Complexity: O(|nodes|). + */ +Graph.prototype.setPath = function(vs, value) { + var self = this; + var args = arguments; + vs.reduce(function(v, w) { + if (args.length > 1) { + self.setEdge(v, w, value); } else { - v = arg0; - w = arguments[1]; - name = arguments[3]; - if (arguments.length > 2) { - value = arguments[2]; - valueSpecified = true; - } + self.setEdge(v, w); } + return w; + }); + return this; +}; - v = "" + v; - w = "" + w; - if (name !== undefined) { - name = "" + name; +/** + * Creates or updates the label for the edge (v, w) with the optionally supplied + * name. If label is supplied it is set as the value for the edge. If label is not + * supplied and the edge was created by this call then the default edge label will + * be assigned. The name parameter is only useful with multigraphs. + */ +Graph.prototype.setEdge = function() { + var v, w, name, value; + var valueSpecified = false; + var arg0 = arguments[0]; + + if (typeof arg0 === "object" && arg0 !== null && "v" in arg0) { + v = arg0.v; + w = arg0.w; + name = arg0.name; + if (arguments.length === 2) { + value = arguments[1]; + valueSpecified = true; } - - var e = edgeArgsToId(this.#isDirected, v, w, name); - if (this.#edgeLabels.hasOwnProperty(e)) { - if (valueSpecified) { - this.#edgeLabels[e] = value; - } - return this; + } else { + v = arg0; + w = arguments[1]; + name = arguments[3]; + if (arguments.length > 2) { + value = arguments[2]; + valueSpecified = true; } + } - if (name !== undefined && !this.#isMultigraph) { - throw new Error("Cannot set a named edge when isMultigraph = false"); - } + v = "" + v; + w = "" + w; + if (name !== undefined) { + name = "" + name; + } - // It didn't exist, so we need to create it. - // First ensure the nodes exist. - this.setNode(v); - this.setNode(w); - - this.#edgeLabels[e] = valueSpecified ? value : this.#defaultEdgeLabelFn(v, w, name); - - var edgeObj = edgeArgsToObj(this.#isDirected, v, w, name); - // Ensure we add undirected edges in a consistent way. - v = edgeObj.v; - w = edgeObj.w; - - Object.freeze(edgeObj); - this.#edgeObjs[e] = edgeObj; - incrementOrInitEntry(this.#preds[w], v); - incrementOrInitEntry(this.#sucs[v], w); - this.#in[w][e] = edgeObj; - this.#out[v][e] = edgeObj; - this.#edgeCount++; + var e = edgeArgsToId(this._isDirected, v, w, name); + if (this._edgeLabels.hasOwnProperty(e)) { + if (valueSpecified) { + this._edgeLabels[e] = value; + } return this; } - /** - * Gets the label for the specified edge. - * Complexity: O(1). - */ - edge(v, w, name) { - var e = (arguments.length === 1 - ? edgeObjToId(this.#isDirected, arguments[0]) - : edgeArgsToId(this.#isDirected, v, w, name)); - return this.#edgeLabels[e]; + if (name !== undefined && !this._isMultigraph) { + throw new Error("Cannot set a named edge when isMultigraph = false"); } - /** - * Gets the label for the specified edge and converts it to an object. - * Complexity: O(1) - */ - edgeAsObj() { - const edge = this.edge(...arguments); - if (typeof edge !== "object") { - return {label: edge}; - } + // It didn't exist, so we need to create it. + // First ensure the nodes exist. + this.setNode(v); + this.setNode(w); - return edge; - } + this._edgeLabels[e] = valueSpecified ? value : this._defaultEdgeLabelFn(v, w, name); - /** - * Detects whether the graph contains specified edge or not. No subgraphs are considered. - * Complexity: O(1). - */ - hasEdge(v, w, name) { - var e = (arguments.length === 1 - ? edgeObjToId(this.#isDirected, arguments[0]) - : edgeArgsToId(this.#isDirected, v, w, name)); - return this.#edgeLabels.hasOwnProperty(e); - } + var edgeObj = edgeArgsToObj(this._isDirected, v, w, name); + // Ensure we add undirected edges in a consistent way. + v = edgeObj.v; + w = edgeObj.w; - /** - * Removes the specified edge from the graph. No subgraphs are considered. - * Complexity: O(1). - */ - removeEdge(v, w, name) { - var e = (arguments.length === 1 - ? edgeObjToId(this.#isDirected, arguments[0]) - : edgeArgsToId(this.#isDirected, v, w, name)); - var edge = this.#edgeObjs[e]; - if (edge) { - v = edge.v; - w = edge.w; - delete this.#edgeLabels[e]; - delete this.#edgeObjs[e]; - decrementOrRemoveEntry(this.#preds[w], v); - decrementOrRemoveEntry(this.#sucs[v], w); - delete this.#in[w][e]; - delete this.#out[v][e]; - this.#edgeCount--; - } - return this; - } + Object.freeze(edgeObj); + this._edgeObjs[e] = edgeObj; + incrementOrInitEntry(this._preds[w], v); + incrementOrInitEntry(this._sucs[v], w); + this._in[w][e] = edgeObj; + this._out[v][e] = edgeObj; + this._edgeCount++; + return this; +}; - /** - * Return all edges that point to the node v. Optionally filters those edges down to just those - * coming from node u. Behavior is undefined for undirected graphs - use nodeEdges instead. - * Complexity: O(|E|). - */ - inEdges(v, u) { - var inV = this.#in[v]; - if (inV) { - var edges = Object.values(inV); - if (!u) { - return edges; - } - return edges.filter(edge => edge.v === u); +/** + * Gets the label for the specified edge. + * Complexity: O(1). + */ +Graph.prototype.edge = function(v, w, name) { + var e = (arguments.length === 1 + ? edgeObjToId(this._isDirected, arguments[0]) + : edgeArgsToId(this._isDirected, v, w, name)); + return this._edgeLabels[e]; +}; + +/** + * Detects whether the graph contains specified edge or not. No subgraphs are considered. + * Complexity: O(1). + */ +Graph.prototype.hasEdge = function(v, w, name) { + var e = (arguments.length === 1 + ? edgeObjToId(this._isDirected, arguments[0]) + : edgeArgsToId(this._isDirected, v, w, name)); + return this._edgeLabels.hasOwnProperty(e); +}; + +/** + * Removes the specified edge from the graph. No subgraphs are considered. + * Complexity: O(1). + */ +Graph.prototype.removeEdge = function(v, w, name) { + var e = (arguments.length === 1 + ? edgeObjToId(this._isDirected, arguments[0]) + : edgeArgsToId(this._isDirected, v, w, name)); + var edge = this._edgeObjs[e]; + if (edge) { + v = edge.v; + w = edge.w; + delete this._edgeLabels[e]; + delete this._edgeObjs[e]; + decrementOrRemoveEntry(this._preds[w], v); + decrementOrRemoveEntry(this._sucs[v], w); + delete this._in[w][e]; + delete this._out[v][e]; + this._edgeCount--; + } + return this; +}; + +/** + * Return all edges that point to the node v. Optionally filters those edges down to just those + * coming from node u. Behavior is undefined for undirected graphs - use nodeEdges instead. + * Complexity: O(|E|). + */ +Graph.prototype.inEdges = function(v, u) { + var inV = this._in[v]; + if (inV) { + var edges = Object.values(inV); + if (!u) { + return edges; } + return edges.filter(edge => edge.v === u); } +}; - /** - * Return all edges that are pointed at by node v. Optionally filters those edges down to just - * those point to w. Behavior is undefined for undirected graphs - use nodeEdges instead. - * Complexity: O(|E|). - */ - outEdges(v, w) { - var outV = this.#out[v]; - if (outV) { - var edges = Object.values(outV); - if (!w) { - return edges; - } - return edges.filter(edge => edge.w === w); +/** + * Return all edges that are pointed at by node v. Optionally filters those edges down to just + * those point to w. Behavior is undefined for undirected graphs - use nodeEdges instead. + * Complexity: O(|E|). + */ +Graph.prototype.outEdges = function(v, w) { + var outV = this._out[v]; + if (outV) { + var edges = Object.values(outV); + if (!w) { + return edges; } + return edges.filter(edge => edge.w === w); } +}; - /** - * Returns all edges to or from node v regardless of direction. Optionally filters those edges - * down to just those between nodes v and w regardless of direction. - * Complexity: O(|E|). - */ - nodeEdges(v, w) { - var inEdges = this.inEdges(v, w); - if (inEdges) { - return inEdges.concat(this.outEdges(v, w)); - } +/** + * Returns all edges to or from node v regardless of direction. Optionally filters those edges + * down to just those between nodes v and w regardless of direction. + * Complexity: O(|E|). + */ +Graph.prototype.nodeEdges = function(v, w) { + var inEdges = this.inEdges(v, w); + if (inEdges) { + return inEdges.concat(this.outEdges(v, w)); } -} +}; function incrementOrInitEntry(map, k) { if (map[k]) { @@ -4281,8 +4237,6 @@ function edgeObjToId(isDirected, edgeObj) { return edgeArgsToId(isDirected, edgeObj.v, edgeObj.w, edgeObj.name); } -module.exports = Graph; - },{}],45:[function(require,module,exports){ // Includes only the "core" of graphlib module.exports = { @@ -4373,7 +4327,7 @@ function read(json) { } },{"./graph":44}],47:[function(require,module,exports){ -module.exports = '2.1.13'; +module.exports = '2.1.9'; },{}]},{},[1])(1) }); diff --git a/dist/dagre.min.js b/dist/dagre.min.js index 02cc10c8..c83fc933 100644 --- a/dist/dagre.min.js +++ b/dist/dagre.min.js @@ -502,7 +502,7 @@ function addWhimBorderNode(g,prefix,labelHeight){const node={width:0,height:0,wh /* * Returns a new function that wraps `fn` with a timer. The wrapper logs the * time it takes to execute the function. - */function time(name,fn){let start=Date.now();try{return fn()}finally{console.log(name+" time: "+(Date.now()-start)+"ms")}}function notime(name,fn){return fn()}let idCounter=0;function uniqueId(prefix){var id=++idCounter;return toString(prefix)+id}function range(start,limit,step=1){if(limit==null){limit=start;start=0}let endCon=i=>ilimitval[funcOrProp]}return Object.entries(obj).reduce((acc,[k,v])=>{acc[k]=func(v,k);return acc},{})}function zipObject(props,values){return props.reduce((acc,key,i)=>{acc[key]=values[i];return acc},{})}},{"@dagrejs/graphlib":29}],28:[function(require,module,exports){module.exports="1.0.6"},{}],29:[function(require,module,exports){ + */function time(name,fn){let start=Date.now();try{return fn()}finally{console.log(name+" time: "+(Date.now()-start)+"ms")}}function notime(name,fn){return fn()}let idCounter=0;function uniqueId(prefix){var id=++idCounter;return toString(prefix)+id}function range(start,limit,step=1){if(limit==null){limit=start;start=0}let endCon=i=>ilimitval[funcOrProp]}return Object.entries(obj).reduce((acc,[k,v])=>{acc[k]=func(v,k);return acc},{})}function zipObject(props,values){return props.reduce((acc,key,i)=>{acc[key]=values[i];return acc},{})}},{"@dagrejs/graphlib":29}],28:[function(require,module,exports){module.exports="1.0.5-whim"},{}],29:[function(require,module,exports){ /** * Copyright (c) 2014, Chris Pettitt * All rights reserved. @@ -539,56 +539,56 @@ var lib=require("./lib");module.exports={Graph:lib.Graph,json:require("./lib/jso * undirected then this algorithm will navigate using neighbors. If the graph * is directed then this algorithm will navigate using successors. * - * If the order is not "post", it will be treated as "pre". - */function dfs(g,vs,order){if(!Array.isArray(vs)){vs=[vs]}var navigation=g.isDirected()?v=>g.successors(v):v=>g.neighbors(v);var orderFunc=order==="post"?postOrderDfs:preOrderDfs;var acc=[];var visited={};vs.forEach(v=>{if(!g.hasNode(v)){throw new Error("Graph does not have node: "+v)}orderFunc(v,navigation,visited,acc)});return acc}function postOrderDfs(v,navigation,visited,acc){var stack=[[v,false]];while(stack.length>0){var curr=stack.pop();if(curr[1]){acc.push(curr[0])}else{if(!visited.hasOwnProperty(curr[0])){visited[curr[0]]=true;stack.push([curr[0],true]);forEachRight(navigation(curr[0]),w=>stack.push([w,false]))}}}}function preOrderDfs(v,navigation,visited,acc){var stack=[v];while(stack.length>0){var curr=stack.pop();if(!visited.hasOwnProperty(curr)){visited[curr]=true;acc.push(curr);forEachRight(navigation(curr),w=>stack.push(w))}}}function forEachRight(array,iteratee){var length=array.length;while(length--){iteratee(array[length],length,array)}return array}},{}],32:[function(require,module,exports){var dijkstra=require("./dijkstra");module.exports=dijkstraAll;function dijkstraAll(g,weightFunc,edgeFunc){return g.nodes().reduce(function(acc,v){acc[v]=dijkstra(g,v,weightFunc,edgeFunc);return acc},{})}},{"./dijkstra":33}],33:[function(require,module,exports){var PriorityQueue=require("../data/priority-queue");module.exports=dijkstra;var DEFAULT_WEIGHT_FUNC=()=>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(distance0){v=pq.removeMin();vEntry=results[v];if(vEntry.distance===Number.POSITIVE_INFINITY){break}edgeFn(v).forEach(updateNeighbors)}return results}},{"../data/priority-queue":43}],34:[function(require,module,exports){var tarjan=require("./tarjan");module.exports=findCycles;function findCycles(g){return tarjan(g).filter(function(cmpt){return cmpt.length>1||cmpt.length===1&&g.hasEdge(cmpt[0],cmpt[0])})}},{"./tarjan":41}],35:[function(require,module,exports){module.exports=floydWarshall;var DEFAULT_WEIGHT_FUNC=()=>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(altDistance1;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(distance0){v=pq.removeMin();vEntry=results[v];if(vEntry.distance===Number.POSITIVE_INFINITY){break}edgeFn(v).forEach(updateNeighbors)}return results}},{"../data/priority-queue":43}],34:[function(require,module,exports){var tarjan=require("./tarjan");module.exports=findCycles;function findCycles(g){return tarjan(g).filter(function(cmpt){return cmpt.length>1||cmpt.length===1&&g.hasEdge(cmpt[0],cmpt[0])})}},{"./tarjan":41}],35:[function(require,module,exports){module.exports=floydWarshall;var DEFAULT_WEIGHT_FUNC=()=>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(altDistance0){v=pq.removeMin();if(parents.hasOwnProperty(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}},{"../data/priority-queue":43,"../graph":44}],41:[function(require,module,exports){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(!visited.hasOwnProperty(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(!visited.hasOwnProperty(v)){dfs(v)}});return results}},{}],42:[function(require,module,exports){function topsort(g){var visited={};var stack={};var results=[];function visit(node){if(stack.hasOwnProperty(node)){throw new CycleException}if(!visited.hasOwnProperty(node)){stack[node]=true;visited[node]=true;g.predecessors(node).forEach(visit);delete stack[node];results.push(node)}}g.sinks().forEach(visit);if(Object.keys(visited).length!==g.nodeCount()){throw new CycleException}return results}class CycleException extends Error{constructor(){super(...arguments)}}module.exports=topsort;topsort.CycleException=CycleException},{}],43:[function(require,module,exports){ +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(!visited.hasOwnProperty(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(!visited.hasOwnProperty(v)){dfs(v)}});return results}},{}],42:[function(require,module,exports){module.exports=topsort;topsort.CycleException=CycleException;function topsort(g){var visited={};var stack={};var results=[];function visit(node){if(stack.hasOwnProperty(node)){throw new CycleException}if(!visited.hasOwnProperty(node)){stack[node]=true;visited[node]=true;g.predecessors(node).forEach(visit);delete stack[node];results.push(node)}}g.sinks().forEach(visit);if(Object.keys(visited).length!==g.nodeCount()){throw new CycleException}return results}function CycleException(){}CycleException.prototype=new Error;// must be an instance of Error to pass testing +},{}],43:[function(require,module,exports){module.exports=PriorityQueue; /** * A min-priority queue data structure. This algorithm is derived from Cormen, * et al., "Introduction to Algorithms". The basic idea of a min-priority * queue is that you can efficiently (in O(1) time) get the smallest key in * the queue. Adding and removing elements takes O(log n) time. A key can * have its priority decreased in O(log n) time. - */ -class PriorityQueue{#arr=[];#keyIndices={}; -/** - * Returns the number of elements in the queue. Takes `O(1)` time. - */size(){return this.#arr.length} -/** - * Returns the keys that are in the queue. Takes `O(n)` time. - */keys(){return this.#arr.map(function(x){return x.key})} -/** - * Returns `true` if **key** is in the queue and `false` if not. - */has(key){return this.#keyIndices.hasOwnProperty(key)} -/** - * Returns the priority for **key**. If **key** is not present in the queue - * then this function returns `undefined`. Takes `O(1)` time. - * - * @param {Object} key - */priority(key){var index=this.#keyIndices[key];if(index!==undefined){return this.#arr[index].priority}} -/** - * Returns the key for the minimum element in this queue. If the queue is - * empty this function throws an Error. Takes `O(1)` time. - */min(){if(this.size()===0){throw new Error("Queue underflow")}return this.#arr[0].key} -/** - * Inserts a new key into the priority queue. If the key already exists in - * the queue this function returns `false`; otherwise it will return `true`. - * Takes `O(n)` time. - * - * @param {Object} key the key to add - * @param {Number} priority the initial priority for the key - */add(key,priority){var keyIndices=this.#keyIndices;key=String(key);if(!keyIndices.hasOwnProperty(key)){var arr=this.#arr;var index=arr.length;keyIndices[key]=index;arr.push({key:key,priority:priority});this.#decrease(index);return true}return false} -/** - * Removes and returns the smallest key in the queue. Takes `O(log n)` time. - */removeMin(){this.#swap(0,this.#arr.length-1);var min=this.#arr.pop();delete this.#keyIndices[min.key];this.#heapify(0);return min.key} -/** - * Decreases the priority for **key** to **priority**. If the new priority is - * greater than the previous priority, this function will throw an Error. - * - * @param {Object} key the key for which to raise priority - * @param {Number} priority the new priority for the key - */decrease(key,priority){var index=this.#keyIndices[key];if(priority>this.#arr[index].priority){throw new Error("New priority is greater than current priority. "+"Key: "+key+" Old: "+this.#arr[index].priority+" New: "+priority)}this.#arr[index].priority=priority;this.#decrease(index)}#heapify(i){var arr=this.#arr;var l=2*i;var r=l+1;var largest=i;if(l>1;if(arr[parent].prioritythis._arr[index].priority){throw new Error("New priority is greater than current priority. "+"Key: "+key+" Old: "+this._arr[index].priority+" New: "+priority)}this._arr[index].priority=priority;this._decrease(index)};PriorityQueue.prototype._heapify=function(i){var arr=this._arr;var l=2*i;var r=l+1;var largest=i;if(l>1;if(arr[parent].priorityundefined; +this._defaultNodeLabelFn=()=>undefined; // Defaults to be set when creating a new edge -#defaultEdgeLabelFn=()=>undefined; +this._defaultEdgeLabelFn=()=>undefined; // v -> label -#nodes={}; +this._nodes={};if(this._isCompound){ +// v -> parent +this._parent={}; +// v -> children +this._children={};this._children[GRAPH_NODE]={}} // v -> edgeObj -#in={}; +this._in={}; // u -> v -> Number -#preds={}; +this._preds={}; // v -> edgeObj -#out={}; +this._out={}; // v -> w -> Number -#sucs={}; +this._sucs={}; // e -> edgeObj -#edgeObjs={}; +this._edgeObjs={}; // e -> label -#edgeLabels={}; -/* Number of nodes in the graph. Should only be changed by the implementation. */#nodeCount=0; -/* Number of edges in the graph. Should only be changed by the implementation. */#edgeCount=0;#parent;#children;constructor(opts){if(opts){this.#isDirected=opts.hasOwnProperty("directed")?opts.directed:true;this.#isMultigraph=opts.hasOwnProperty("multigraph")?opts.multigraph:false;this.#isCompound=opts.hasOwnProperty("compound")?opts.compound:false}if(this.#isCompound){ -// v -> parent -this.#parent={}; -// v -> children -this.#children={};this.#children[GRAPH_NODE]={}}} +this._edgeLabels={}} +/* Number of nodes in the graph. Should only be changed by the implementation. */Graph.prototype._nodeCount=0; +/* Number of edges in the graph. Should only be changed by the implementation. */Graph.prototype._edgeCount=0; /* === Graph functions ========= */ /** - * Whether graph was created with 'directed' flag set to true or not. - */isDirected(){return this.#isDirected} + * Whether graph was created with 'directed' flag set to true or not. + */Graph.prototype.isDirected=function(){return this._isDirected}; /** - * Whether graph was created with 'multigraph' flag set to true or not. - */isMultigraph(){return this.#isMultigraph} + * Whether graph was created with 'multigraph' flag set to true or not. + */Graph.prototype.isMultigraph=function(){return this._isMultigraph}; /** - * Whether graph was created with 'compound' flag set to true or not. - */isCompound(){return this.#isCompound} + * Whether graph was created with 'compound' flag set to true or not. + */Graph.prototype.isCompound=function(){return this._isCompound}; /** - * Sets the label of the graph. - */setGraph(label){this.#label=label;return this} + * Sets the label of the graph. + */Graph.prototype.setGraph=function(label){this._label=label;return this}; /** - * Gets the graph label. - */graph(){return this.#label} + * Gets the graph label. + */Graph.prototype.graph=function(){return this._label}; /* === Node functions ========== */ /** - * Sets the default node label. If newDefault is a function, it will be - * invoked ach time when setting a label for a node. Otherwise, this label - * will be assigned as default label in case if no label was specified while - * setting a node. - * Complexity: O(1). - */setDefaultNodeLabel(newDefault){this.#defaultNodeLabelFn=newDefault;if(typeof newDefault!=="function"){this.#defaultNodeLabelFn=()=>newDefault}return this} -/** - * Gets the number of nodes in the graph. - * Complexity: O(1). - */nodeCount(){return this.#nodeCount} -/** - * Gets all nodes of the graph. Note, the in case of compound graph subnodes are - * not included in list. - * Complexity: O(1). - */nodes(){return Object.keys(this.#nodes)} -/** - * Gets list of nodes without in-edges. - * Complexity: O(|V|). - */sources(){var self=this;return this.nodes().filter(v=>Object.keys(self.#in[v]).length===0)} -/** - * Gets list of nodes without out-edges. - * Complexity: O(|V|). - */sinks(){var self=this;return this.nodes().filter(v=>Object.keys(self.#out[v]).length===0)} -/** - * Invokes setNode method for each node in names list. - * Complexity: O(|names|). - */setNodes(vs,value){var args=arguments;var self=this;vs.forEach(function(v){if(args.length>1){self.setNode(v,value)}else{self.setNode(v)}});return this} -/** - * Creates or updates the value for the node v in the graph. If label is supplied - * it is set as the value for the node. If label is not supplied and the node was - * created by this call then the default node label will be assigned. - * Complexity: O(1). - */setNode(v,value){if(this.#nodes.hasOwnProperty(v)){if(arguments.length>1){this.#nodes[v]=value}return this}this.#nodes[v]=arguments.length>1?value:this.#defaultNodeLabelFn(v);if(this.#isCompound){this.#parent[v]=GRAPH_NODE;this.#children[v]={};this.#children[GRAPH_NODE][v]=true}this.#in[v]={};this.#preds[v]={};this.#out[v]={};this.#sucs[v]={};++this.#nodeCount;return this} -/** - * Gets the label of node with specified name. - * Complexity: O(|V|). - */node(v){return this.#nodes[v]} -/** - * Detects whether graph has a node with specified name or not. - */hasNode(v){return this.#nodes.hasOwnProperty(v)} -/** - * Remove the node with the name from the graph or do nothing if the node is not in - * the graph. If the node was removed this function also removes any incident - * edges. - * Complexity: O(1). - */removeNode(v){var self=this;if(this.#nodes.hasOwnProperty(v)){var removeEdge=e=>self.removeEdge(self.#edgeObjs[e]);delete this.#nodes[v];if(this.#isCompound){this.#removeFromParentsChildList(v);delete this.#parent[v];this.children(v).forEach(function(child){self.setParent(child)});delete this.#children[v]}Object.keys(this.#in[v]).forEach(removeEdge);delete this.#in[v];delete this.#preds[v];Object.keys(this.#out[v]).forEach(removeEdge);delete this.#out[v];delete this.#sucs[v];--this.#nodeCount}return this} -/** - * Sets node p as a parent for node v if it is defined, or removes the - * parent for v if p is undefined. Method throws an exception in case of - * invoking it in context of noncompound graph. - * Average-case complexity: O(1). - */setParent(v,parent){if(!this.#isCompound){throw new Error("Cannot set parent in a non-compound graph")}if(parent===undefined){parent=GRAPH_NODE}else{ + * Sets the default node label. If newDefault is a function, it will be + * invoked ach time when setting a label for a node. Otherwise, this label + * will be assigned as default label in case if no label was specified while + * setting a node. + * Complexity: O(1). + */Graph.prototype.setDefaultNodeLabel=function(newDefault){this._defaultNodeLabelFn=newDefault;if(typeof newDefault!=="function"){this._defaultNodeLabelFn=()=>newDefault}return this}; +/** + * Gets the number of nodes in the graph. + * Complexity: O(1). + */Graph.prototype.nodeCount=function(){return this._nodeCount}; +/** + * Gets all nodes of the graph. Note, the in case of compound graph subnodes are + * not included in list. + * Complexity: O(1). + */Graph.prototype.nodes=function(){return Object.keys(this._nodes)}; +/** + * Gets list of nodes without in-edges. + * Complexity: O(|V|). + */Graph.prototype.sources=function(){var self=this;return this.nodes().filter(v=>Object.keys(self._in[v]).length===0)}; +/** + * Gets list of nodes without out-edges. + * Complexity: O(|V|). + */Graph.prototype.sinks=function(){var self=this;return this.nodes().filter(v=>Object.keys(self._out[v]).length===0)}; +/** + * Invokes setNode method for each node in names list. + * Complexity: O(|names|). + */Graph.prototype.setNodes=function(vs,value){var args=arguments;var self=this;vs.forEach(function(v){if(args.length>1){self.setNode(v,value)}else{self.setNode(v)}});return this}; +/** + * Creates or updates the value for the node v in the graph. If label is supplied + * it is set as the value for the node. If label is not supplied and the node was + * created by this call then the default node label will be assigned. + * Complexity: O(1). + */Graph.prototype.setNode=function(v,value){if(this._nodes.hasOwnProperty(v)){if(arguments.length>1){this._nodes[v]=value}return this}this._nodes[v]=arguments.length>1?value:this._defaultNodeLabelFn(v);if(this._isCompound){this._parent[v]=GRAPH_NODE;this._children[v]={};this._children[GRAPH_NODE][v]=true}this._in[v]={};this._preds[v]={};this._out[v]={};this._sucs[v]={};++this._nodeCount;return this}; +/** + * Gets the label of node with specified name. + * Complexity: O(|V|). + */Graph.prototype.node=function(v){return this._nodes[v]}; +/** + * Detects whether graph has a node with specified name or not. + */Graph.prototype.hasNode=function(v){return this._nodes.hasOwnProperty(v)}; +/** + * Remove the node with the name from the graph or do nothing if the node is not in + * the graph. If the node was removed this function also removes any incident + * edges. + * Complexity: O(1). + */Graph.prototype.removeNode=function(v){var self=this;if(this._nodes.hasOwnProperty(v)){var removeEdge=e=>self.removeEdge(self._edgeObjs[e]);delete this._nodes[v];if(this._isCompound){this._removeFromParentsChildList(v);delete this._parent[v];this.children(v).forEach(function(child){self.setParent(child)});delete this._children[v]}Object.keys(this._in[v]).forEach(removeEdge);delete this._in[v];delete this._preds[v];Object.keys(this._out[v]).forEach(removeEdge);delete this._out[v];delete this._sucs[v];--this._nodeCount}return this}; +/** + * Sets node p as a parent for node v if it is defined, or removes the + * parent for v if p is undefined. Method throws an exception in case of + * invoking it in context of noncompound graph. + * Average-case complexity: O(1). + */Graph.prototype.setParent=function(v,parent){if(!this._isCompound){throw new Error("Cannot set parent in a non-compound graph")}if(parent===undefined){parent=GRAPH_NODE}else{ // Coerce parent to string -parent+="";for(var ancestor=parent;ancestor!==undefined;ancestor=this.parent(ancestor)){if(ancestor===v){throw new Error("Setting "+parent+" as parent of "+v+" would create a cycle")}}this.setNode(parent)}this.setNode(v);this.#removeFromParentsChildList(v);this.#parent[v]=parent;this.#children[parent][v]=true;return this}#removeFromParentsChildList(v){delete this.#children[this.#parent[v]][v]} -/** - * Gets parent node for node v. - * Complexity: O(1). - */parent(v){if(this.#isCompound){var parent=this.#parent[v];if(parent!==GRAPH_NODE){return parent}}} -/** - * Gets list of direct children of node v. - * Complexity: O(1). - */children(v=GRAPH_NODE){if(this.#isCompound){var children=this.#children[v];if(children){return Object.keys(children)}}else if(v===GRAPH_NODE){return this.nodes()}else if(this.hasNode(v)){return[]}} -/** - * Return all nodes that are predecessors of the specified node or undefined if node v is not in - * the graph. Behavior is undefined for undirected graphs - use neighbors instead. - * Complexity: O(|V|). - */predecessors(v){var predsV=this.#preds[v];if(predsV){return Object.keys(predsV)}} -/** - * Return all nodes that are successors of the specified node or undefined if node v is not in - * the graph. Behavior is undefined for undirected graphs - use neighbors instead. - * Complexity: O(|V|). - */successors(v){var sucsV=this.#sucs[v];if(sucsV){return Object.keys(sucsV)}} -/** - * Return all nodes that are predecessors or successors of the specified node or undefined if - * node v is not in the graph. - * Complexity: O(|V|). - */neighbors(v){var preds=this.predecessors(v);if(preds){const union=new Set(preds);for(var succ of this.successors(v)){union.add(succ)}return Array.from(union.values())}}isLeaf(v){var neighbors;if(this.isDirected()){neighbors=this.successors(v)}else{neighbors=this.neighbors(v)}return neighbors.length===0} -/** - * Creates new graph with nodes filtered via filter. Edges incident to rejected node - * are also removed. In case of compound graph, if parent is rejected by filter, - * than all its children are rejected too. - * Average-case complexity: O(|E|+|V|). - */filterNodes(filter){var copy=new this.constructor({directed:this.#isDirected,multigraph:this.#isMultigraph,compound:this.#isCompound});copy.setGraph(this.graph());var self=this;Object.entries(this.#nodes).forEach(function([v,value]){if(filter(v)){copy.setNode(v,value)}});Object.values(this.#edgeObjs).forEach(function(e){if(copy.hasNode(e.v)&©.hasNode(e.w)){copy.setEdge(e,self.edge(e))}});var parents={};function findParent(v){var parent=self.parent(v);if(parent===undefined||copy.hasNode(parent)){parents[v]=parent;return parent}else if(parent in parents){return parents[parent]}else{return findParent(parent)}}if(this.#isCompound){copy.nodes().forEach(v=>copy.setParent(v,findParent(v)))}return copy} +parent+="";for(var ancestor=parent;ancestor!==undefined;ancestor=this.parent(ancestor)){if(ancestor===v){throw new Error("Setting "+parent+" as parent of "+v+" would create a cycle")}}this.setNode(parent)}this.setNode(v);this._removeFromParentsChildList(v);this._parent[v]=parent;this._children[parent][v]=true;return this};Graph.prototype._removeFromParentsChildList=function(v){delete this._children[this._parent[v]][v]}; +/** + * Gets parent node for node v. + * Complexity: O(1). + */Graph.prototype.parent=function(v){if(this._isCompound){var parent=this._parent[v];if(parent!==GRAPH_NODE){return parent}}}; +/** + * Gets list of direct children of node v. + * Complexity: O(1). + */Graph.prototype.children=function(v=GRAPH_NODE){if(this._isCompound){var children=this._children[v];if(children){return Object.keys(children)}}else if(v===GRAPH_NODE){return this.nodes()}else if(this.hasNode(v)){return[]}}; +/** + * Return all nodes that are predecessors of the specified node or undefined if node v is not in + * the graph. Behavior is undefined for undirected graphs - use neighbors instead. + * Complexity: O(|V|). + */Graph.prototype.predecessors=function(v){var predsV=this._preds[v];if(predsV){return Object.keys(predsV)}}; +/** + * Return all nodes that are successors of the specified node or undefined if node v is not in + * the graph. Behavior is undefined for undirected graphs - use neighbors instead. + * Complexity: O(|V|). + */Graph.prototype.successors=function(v){var sucsV=this._sucs[v];if(sucsV){return Object.keys(sucsV)}}; +/** + * Return all nodes that are predecessors or successors of the specified node or undefined if + * node v is not in the graph. + * Complexity: O(|V|). + */Graph.prototype.neighbors=function(v){var preds=this.predecessors(v);if(preds){const union=new Set(preds);for(var succ of this.successors(v)){union.add(succ)}return Array.from(union.values())}};Graph.prototype.isLeaf=function(v){var neighbors;if(this.isDirected()){neighbors=this.successors(v)}else{neighbors=this.neighbors(v)}return neighbors.length===0}; +/** + * Creates new graph with nodes filtered via filter. Edges incident to rejected node + * are also removed. In case of compound graph, if parent is rejected by filter, + * than all its children are rejected too. + * Average-case complexity: O(|E|+|V|). + */Graph.prototype.filterNodes=function(filter){var copy=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});copy.setGraph(this.graph());var self=this;Object.entries(this._nodes).forEach(function([v,value]){if(filter(v)){copy.setNode(v,value)}});Object.values(this._edgeObjs).forEach(function(e){if(copy.hasNode(e.v)&©.hasNode(e.w)){copy.setEdge(e,self.edge(e))}});var parents={};function findParent(v){var parent=self.parent(v);if(parent===undefined||copy.hasNode(parent)){parents[v]=parent;return parent}else if(parent in parents){return parents[parent]}else{return findParent(parent)}}if(this._isCompound){copy.nodes().forEach(v=>copy.setParent(v,findParent(v)))}return copy}; /* === Edge functions ========== */ /** - * Sets the default edge label or factory function. This label will be - * assigned as default label in case if no label was specified while setting - * an edge or this function will be invoked each time when setting an edge - * with no label specified and returned value * will be used as a label for edge. - * Complexity: O(1). - */setDefaultEdgeLabel(newDefault){this.#defaultEdgeLabelFn=newDefault;if(typeof newDefault!=="function"){this.#defaultEdgeLabelFn=()=>newDefault}return this} -/** - * Gets the number of edges in the graph. - * Complexity: O(1). - */edgeCount(){return this.#edgeCount} -/** - * Gets edges of the graph. In case of compound graph subgraphs are not considered. - * Complexity: O(|E|). - */edges(){return Object.values(this.#edgeObjs)} -/** - * Establish an edges path over the nodes in nodes list. If some edge is already - * exists, it will update its label, otherwise it will create an edge between pair - * of nodes with label provided or default label if no label provided. - * Complexity: O(|nodes|). - */setPath(vs,value){var self=this;var args=arguments;vs.reduce(function(v,w){if(args.length>1){self.setEdge(v,w,value)}else{self.setEdge(v,w)}return w});return this} -/** - * Creates or updates the label for the edge (v, w) with the optionally supplied - * name. If label is supplied it is set as the value for the edge. If label is not - * supplied and the edge was created by this call then the default edge label will - * be assigned. The name parameter is only useful with multigraphs. - */setEdge(){var v,w,name,value;var valueSpecified=false;var arg0=arguments[0];if(typeof arg0==="object"&&arg0!==null&&"v"in arg0){v=arg0.v;w=arg0.w;name=arg0.name;if(arguments.length===2){value=arguments[1];valueSpecified=true}}else{v=arg0;w=arguments[1];name=arguments[3];if(arguments.length>2){value=arguments[2];valueSpecified=true}}v=""+v;w=""+w;if(name!==undefined){name=""+name}var e=edgeArgsToId(this.#isDirected,v,w,name);if(this.#edgeLabels.hasOwnProperty(e)){if(valueSpecified){this.#edgeLabels[e]=value}return this}if(name!==undefined&&!this.#isMultigraph){throw new Error("Cannot set a named edge when isMultigraph = false")} + * Sets the default edge label or factory function. This label will be + * assigned as default label in case if no label was specified while setting + * an edge or this function will be invoked each time when setting an edge + * with no label specified and returned value * will be used as a label for edge. + * Complexity: O(1). + */Graph.prototype.setDefaultEdgeLabel=function(newDefault){this._defaultEdgeLabelFn=newDefault;if(typeof newDefault!=="function"){this._defaultEdgeLabelFn=()=>newDefault}return this}; +/** + * Gets the number of edges in the graph. + * Complexity: O(1). + */Graph.prototype.edgeCount=function(){return this._edgeCount}; +/** + * Gets edges of the graph. In case of compound graph subgraphs are not considered. + * Complexity: O(|E|). + */Graph.prototype.edges=function(){return Object.values(this._edgeObjs)}; +/** + * Establish an edges path over the nodes in nodes list. If some edge is already + * exists, it will update its label, otherwise it will create an edge between pair + * of nodes with label provided or default label if no label provided. + * Complexity: O(|nodes|). + */Graph.prototype.setPath=function(vs,value){var self=this;var args=arguments;vs.reduce(function(v,w){if(args.length>1){self.setEdge(v,w,value)}else{self.setEdge(v,w)}return w});return this}; +/** + * Creates or updates the label for the edge (v, w) with the optionally supplied + * name. If label is supplied it is set as the value for the edge. If label is not + * supplied and the edge was created by this call then the default edge label will + * be assigned. The name parameter is only useful with multigraphs. + */Graph.prototype.setEdge=function(){var v,w,name,value;var valueSpecified=false;var arg0=arguments[0];if(typeof arg0==="object"&&arg0!==null&&"v"in arg0){v=arg0.v;w=arg0.w;name=arg0.name;if(arguments.length===2){value=arguments[1];valueSpecified=true}}else{v=arg0;w=arguments[1];name=arguments[3];if(arguments.length>2){value=arguments[2];valueSpecified=true}}v=""+v;w=""+w;if(name!==undefined){name=""+name}var e=edgeArgsToId(this._isDirected,v,w,name);if(this._edgeLabels.hasOwnProperty(e)){if(valueSpecified){this._edgeLabels[e]=value}return this}if(name!==undefined&&!this._isMultigraph){throw new Error("Cannot set a named edge when isMultigraph = false")} // It didn't exist, so we need to create it. // First ensure the nodes exist. -this.setNode(v);this.setNode(w);this.#edgeLabels[e]=valueSpecified?value:this.#defaultEdgeLabelFn(v,w,name);var edgeObj=edgeArgsToObj(this.#isDirected,v,w,name); +this.setNode(v);this.setNode(w);this._edgeLabels[e]=valueSpecified?value:this._defaultEdgeLabelFn(v,w,name);var edgeObj=edgeArgsToObj(this._isDirected,v,w,name); // Ensure we add undirected edges in a consistent way. -v=edgeObj.v;w=edgeObj.w;Object.freeze(edgeObj);this.#edgeObjs[e]=edgeObj;incrementOrInitEntry(this.#preds[w],v);incrementOrInitEntry(this.#sucs[v],w);this.#in[w][e]=edgeObj;this.#out[v][e]=edgeObj;this.#edgeCount++;return this} -/** - * Gets the label for the specified edge. - * Complexity: O(1). - */edge(v,w,name){var e=arguments.length===1?edgeObjToId(this.#isDirected,arguments[0]):edgeArgsToId(this.#isDirected,v,w,name);return this.#edgeLabels[e]} -/** - * Gets the label for the specified edge and converts it to an object. - * Complexity: O(1) - */edgeAsObj(){const edge=this.edge(...arguments);if(typeof edge!=="object"){return{label:edge}}return edge} -/** - * Detects whether the graph contains specified edge or not. No subgraphs are considered. - * Complexity: O(1). - */hasEdge(v,w,name){var e=arguments.length===1?edgeObjToId(this.#isDirected,arguments[0]):edgeArgsToId(this.#isDirected,v,w,name);return this.#edgeLabels.hasOwnProperty(e)} -/** - * Removes the specified edge from the graph. No subgraphs are considered. - * Complexity: O(1). - */removeEdge(v,w,name){var e=arguments.length===1?edgeObjToId(this.#isDirected,arguments[0]):edgeArgsToId(this.#isDirected,v,w,name);var edge=this.#edgeObjs[e];if(edge){v=edge.v;w=edge.w;delete this.#edgeLabels[e];delete this.#edgeObjs[e];decrementOrRemoveEntry(this.#preds[w],v);decrementOrRemoveEntry(this.#sucs[v],w);delete this.#in[w][e];delete this.#out[v][e];this.#edgeCount--}return this} -/** - * Return all edges that point to the node v. Optionally filters those edges down to just those - * coming from node u. Behavior is undefined for undirected graphs - use nodeEdges instead. - * Complexity: O(|E|). - */inEdges(v,u){var inV=this.#in[v];if(inV){var edges=Object.values(inV);if(!u){return edges}return edges.filter(edge=>edge.v===u)}} -/** - * Return all edges that are pointed at by node v. Optionally filters those edges down to just - * those point to w. Behavior is undefined for undirected graphs - use nodeEdges instead. - * Complexity: O(|E|). - */outEdges(v,w){var outV=this.#out[v];if(outV){var edges=Object.values(outV);if(!w){return edges}return edges.filter(edge=>edge.w===w)}} -/** - * Returns all edges to or from node v regardless of direction. Optionally filters those edges - * down to just those between nodes v and w regardless of direction. - * Complexity: O(|E|). - */nodeEdges(v,w){var inEdges=this.inEdges(v,w);if(inEdges){return inEdges.concat(this.outEdges(v,w))}}}function incrementOrInitEntry(map,k){if(map[k]){map[k]++}else{map[k]=1}}function decrementOrRemoveEntry(map,k){if(!--map[k]){delete map[k]}}function edgeArgsToId(isDirected,v_,w_,name){var v=""+v_;var w=""+w_;if(!isDirected&&v>w){var tmp=v;v=w;w=tmp}return v+EDGE_KEY_DELIM+w+EDGE_KEY_DELIM+(name===undefined?DEFAULT_EDGE_NAME:name)}function edgeArgsToObj(isDirected,v_,w_,name){var v=""+v_;var w=""+w_;if(!isDirected&&v>w){var tmp=v;v=w;w=tmp}var edgeObj={v:v,w:w};if(name){edgeObj.name=name}return edgeObj}function edgeObjToId(isDirected,edgeObj){return edgeArgsToId(isDirected,edgeObj.v,edgeObj.w,edgeObj.name)}module.exports=Graph},{}],45:[function(require,module,exports){ +v=edgeObj.v;w=edgeObj.w;Object.freeze(edgeObj);this._edgeObjs[e]=edgeObj;incrementOrInitEntry(this._preds[w],v);incrementOrInitEntry(this._sucs[v],w);this._in[w][e]=edgeObj;this._out[v][e]=edgeObj;this._edgeCount++;return this}; +/** + * Gets the label for the specified edge. + * Complexity: O(1). + */Graph.prototype.edge=function(v,w,name){var e=arguments.length===1?edgeObjToId(this._isDirected,arguments[0]):edgeArgsToId(this._isDirected,v,w,name);return this._edgeLabels[e]}; +/** + * Detects whether the graph contains specified edge or not. No subgraphs are considered. + * Complexity: O(1). + */Graph.prototype.hasEdge=function(v,w,name){var e=arguments.length===1?edgeObjToId(this._isDirected,arguments[0]):edgeArgsToId(this._isDirected,v,w,name);return this._edgeLabels.hasOwnProperty(e)}; +/** + * Removes the specified edge from the graph. No subgraphs are considered. + * Complexity: O(1). + */Graph.prototype.removeEdge=function(v,w,name){var e=arguments.length===1?edgeObjToId(this._isDirected,arguments[0]):edgeArgsToId(this._isDirected,v,w,name);var edge=this._edgeObjs[e];if(edge){v=edge.v;w=edge.w;delete this._edgeLabels[e];delete this._edgeObjs[e];decrementOrRemoveEntry(this._preds[w],v);decrementOrRemoveEntry(this._sucs[v],w);delete this._in[w][e];delete this._out[v][e];this._edgeCount--}return this}; +/** + * Return all edges that point to the node v. Optionally filters those edges down to just those + * coming from node u. Behavior is undefined for undirected graphs - use nodeEdges instead. + * Complexity: O(|E|). + */Graph.prototype.inEdges=function(v,u){var inV=this._in[v];if(inV){var edges=Object.values(inV);if(!u){return edges}return edges.filter(edge=>edge.v===u)}}; +/** + * Return all edges that are pointed at by node v. Optionally filters those edges down to just + * those point to w. Behavior is undefined for undirected graphs - use nodeEdges instead. + * Complexity: O(|E|). + */Graph.prototype.outEdges=function(v,w){var outV=this._out[v];if(outV){var edges=Object.values(outV);if(!w){return edges}return edges.filter(edge=>edge.w===w)}}; +/** + * Returns all edges to or from node v regardless of direction. Optionally filters those edges + * down to just those between nodes v and w regardless of direction. + * Complexity: O(|E|). + */Graph.prototype.nodeEdges=function(v,w){var inEdges=this.inEdges(v,w);if(inEdges){return inEdges.concat(this.outEdges(v,w))}};function incrementOrInitEntry(map,k){if(map[k]){map[k]++}else{map[k]=1}}function decrementOrRemoveEntry(map,k){if(!--map[k]){delete map[k]}}function edgeArgsToId(isDirected,v_,w_,name){var v=""+v_;var w=""+w_;if(!isDirected&&v>w){var tmp=v;v=w;w=tmp}return v+EDGE_KEY_DELIM+w+EDGE_KEY_DELIM+(name===undefined?DEFAULT_EDGE_NAME:name)}function edgeArgsToObj(isDirected,v_,w_,name){var v=""+v_;var w=""+w_;if(!isDirected&&v>w){var tmp=v;v=w;w=tmp}var edgeObj={v:v,w:w};if(name){edgeObj.name=name}return edgeObj}function edgeObjToId(isDirected,edgeObj){return edgeArgsToId(isDirected,edgeObj.v,edgeObj.w,edgeObj.name)}},{}],45:[function(require,module,exports){ // Includes only the "core" of graphlib module.exports={Graph:require("./graph"),version:require("./version")}},{"./graph":44,"./version":47}],46:[function(require,module,exports){var Graph=require("./graph");module.exports={write:write,read:read}; /** @@ -805,4 +801,4 @@ module.exports={Graph:require("./graph"),version:require("./version")}},{"./grap * // ['a', 'b'] * g2.edges() * // [ { v: 'a', w: 'b' } ] - */function read(json){var g=new Graph(json.options).setGraph(json.value);json.nodes.forEach(function(entry){g.setNode(entry.v,entry.value);if(entry.parent){g.setParent(entry.v,entry.parent)}});json.edges.forEach(function(entry){g.setEdge({v:entry.v,w:entry.w,name:entry.name},entry.value)});return g}},{"./graph":44}],47:[function(require,module,exports){module.exports="2.1.13"},{}]},{},[1])(1)}); + */function read(json){var g=new Graph(json.options).setGraph(json.value);json.nodes.forEach(function(entry){g.setNode(entry.v,entry.value);if(entry.parent){g.setParent(entry.v,entry.parent)}});json.edges.forEach(function(entry){g.setEdge({v:entry.v,w:entry.w,name:entry.name},entry.value)});return g}},{"./graph":44}],47:[function(require,module,exports){module.exports="2.1.9"},{}]},{},[1])(1)}); diff --git a/lib/version.js b/lib/version.js index 8b89e07a..b7835bf2 100644 --- a/lib/version.js +++ b/lib/version.js @@ -1 +1 @@ -module.exports = "1.0.6"; +module.exports = "1.0.5-whim"; diff --git a/package-lock.json b/package-lock.json index a4b93ca5..25517c0c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@whimsicalcode/dagre", - "version": "1.0.6", + "version": "1.0.5-whim", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@whimsicalcode/dagre", - "version": "1.0.6", + "version": "1.0.5-whim", "license": "MIT", "dependencies": { - "@dagrejs/graphlib": "2.1.13" + "@dagrejs/graphlib": "2.1.10" }, "devDependencies": { "benchmark": "2.1.4", @@ -455,9 +455,9 @@ } }, "node_modules/@dagrejs/graphlib": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/@dagrejs/graphlib/-/graphlib-2.1.13.tgz", - "integrity": "sha512-calbMa7Gcyo+/t23XBaqQqon8LlgE9regey4UVoikoenKBXvUnCUL3s9RP6USCxttfr0XWVICtYUuKMdehKqMw==", + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@dagrejs/graphlib/-/graphlib-2.1.10.tgz", + "integrity": "sha512-AxQeK6ort0BW9H3I4ppTew8orHX+odsGmaIjp6hcmt9jIUj4GH1ZyA2orkXDrJQxlCyHAMAznR5okVrM1DN3Tw==", "engines": { "node": ">17.0.0" } @@ -7023,9 +7023,9 @@ "dev": true }, "@dagrejs/graphlib": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/@dagrejs/graphlib/-/graphlib-2.1.13.tgz", - "integrity": "sha512-calbMa7Gcyo+/t23XBaqQqon8LlgE9regey4UVoikoenKBXvUnCUL3s9RP6USCxttfr0XWVICtYUuKMdehKqMw==" + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@dagrejs/graphlib/-/graphlib-2.1.10.tgz", + "integrity": "sha512-AxQeK6ort0BW9H3I4ppTew8orHX+odsGmaIjp6hcmt9jIUj4GH1ZyA2orkXDrJQxlCyHAMAznR5okVrM1DN3Tw==" }, "@eslint/eslintrc": { "version": "2.0.2", diff --git a/package.json b/package.json index 469d0621..34de101f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@whimsicalcode/dagre", - "version": "1.0.6", + "version": "1.0.5-whim", "description": "Graph layout for JavaScript", "author": "Chris Pettitt ", "contributors": [ @@ -27,7 +27,7 @@ "layout" ], "dependencies": { - "@dagrejs/graphlib": "2.1.13" + "@dagrejs/graphlib": "2.1.10" }, "devDependencies": { "benchmark": "2.1.4",