diff --git a/bower.json b/bower.json index 229def72..3533e8c8 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "graphlib", - "version": "2.2.1", + "version": "2.2.2", "main": [ "dist/graphlib.core.js" ], diff --git a/dist/graphlib.core.js b/dist/graphlib.core.js index 1ed4f81f..d9924a35 100644 --- a/dist/graphlib.core.js +++ b/dist/graphlib.core.js @@ -459,28 +459,28 @@ topsort.CycleException = CycleException; * have its priority decreased in O(log n) time. */ class PriorityQueue { - #arr = []; - #keyIndices = {}; + _arr = []; + _keyIndices = {}; /** * Returns the number of elements in the queue. Takes `O(1)` time. */ size() { - return this.#arr.length; + 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; }); + 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); + return this._keyIndices.hasOwnProperty(key); } /** @@ -490,9 +490,9 @@ class PriorityQueue { * @param {Object} key */ priority(key) { - var index = this.#keyIndices[key]; + var index = this._keyIndices[key]; if (index !== undefined) { - return this.#arr[index].priority; + return this._arr[index].priority; } } @@ -504,7 +504,7 @@ class PriorityQueue { if (this.size() === 0) { throw new Error("Queue underflow"); } - return this.#arr[0].key; + return this._arr[0].key; } /** @@ -516,14 +516,14 @@ class PriorityQueue { * @param {Number} priority the initial priority for the key */ add(key, priority) { - var keyIndices = this.#keyIndices; + var keyIndices = this._keyIndices; key = String(key); if (!keyIndices.hasOwnProperty(key)) { - var arr = this.#arr; + var arr = this._arr; var index = arr.length; keyIndices[key] = index; arr.push({key: key, priority: priority}); - this.#decrease(index); + this._decrease(index); return true; } return false; @@ -533,10 +533,10 @@ class PriorityQueue { * 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); + this._swap(0, this._arr.length - 1); + var min = this._arr.pop(); + delete this._keyIndices[min.key]; + this._heapify(0); return min.key; } @@ -548,17 +548,17 @@ class PriorityQueue { * @param {Number} priority the new priority for the key */ decrease(key, priority) { - var index = this.#keyIndices[key]; - if (priority > this.#arr[index].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); + "Key: " + key + " Old: " + this._arr[index].priority + " New: " + priority); } - this.#arr[index].priority = priority; - this.#decrease(index); + this._arr[index].priority = priority; + this._decrease(index); } - #heapify(i) { - var arr = this.#arr; + _heapify(i) { + var arr = this._arr; var l = 2 * i; var r = l + 1; var largest = i; @@ -568,14 +568,14 @@ class PriorityQueue { largest = arr[r].priority < arr[largest].priority ? r : largest; } if (largest !== i) { - this.#swap(i, largest); - this.#heapify(largest); + this._swap(i, largest); + this._heapify(largest); } } } - #decrease(index) { - var arr = this.#arr; + _decrease(index) { + var arr = this._arr; var priority = arr[index].priority; var parent; while (index !== 0) { @@ -583,14 +583,14 @@ class PriorityQueue { if (arr[parent].priority < priority) { break; } - this.#swap(index, parent); + this._swap(index, parent); index = parent; } } - #swap(i, j) { - var arr = this.#arr; - var keyIndices = this.#keyIndices; + _swap(i, j) { + var arr = this._arr; + var keyIndices = this._keyIndices; var origArrI = arr[i]; var origArrJ = arr[j]; arr[i] = origArrJ; @@ -620,64 +620,64 @@ var EDGE_KEY_DELIM = "\x01"; // we're going to get to a performant hashtable in JavaScript. class Graph { - #isDirected = true; - #isMultigraph = false; - #isCompound = false; + _isDirected = true; + _isMultigraph = false; + _isCompound = false; // Label for the graph itself - #label; + _label; // Defaults to be set when creating a new node - #defaultNodeLabelFn = () => undefined; + _defaultNodeLabelFn = () => undefined; // Defaults to be set when creating a new edge - #defaultEdgeLabelFn = () => undefined; + _defaultEdgeLabelFn = () => undefined; // v -> label - #nodes = {}; + _nodes = {}; // v -> edgeObj - #in = {}; + _in = {}; // u -> v -> Number - #preds = {}; + _preds = {}; // v -> edgeObj - #out = {}; + _out = {}; // v -> w -> Number - #sucs = {}; + _sucs = {}; // e -> edgeObj - #edgeObjs = {}; + _edgeObjs = {}; // e -> label - #edgeLabels = {}; + _edgeLabels = {}; /* Number of nodes in the graph. Should only be changed by the implementation. */ - #nodeCount = 0; + _nodeCount = 0; /* Number of edges in the graph. Should only be changed by the implementation. */ - #edgeCount = 0; + _edgeCount = 0; - #parent; + _parent; - #children; + _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; + 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) { + if (this._isCompound) { // v -> parent - this.#parent = {}; + this._parent = {}; // v -> children - this.#children = {}; - this.#children[GRAPH_NODE] = {}; + this._children = {}; + this._children[GRAPH_NODE] = {}; } } @@ -687,28 +687,28 @@ class Graph { * Whether graph was created with 'directed' flag set to true or not. */ isDirected() { - return this.#isDirected; + return this._isDirected; } /** * Whether graph was created with 'multigraph' flag set to true or not. */ isMultigraph() { - return this.#isMultigraph; + return this._isMultigraph; } /** * Whether graph was created with 'compound' flag set to true or not. */ isCompound() { - return this.#isCompound; + return this._isCompound; } /** * Sets the label of the graph. */ setGraph(label) { - this.#label = label; + this._label = label; return this; } @@ -716,7 +716,7 @@ class Graph { * Gets the graph label. */ graph() { - return this.#label; + return this._label; } @@ -730,9 +730,9 @@ class Graph { * Complexity: O(1). */ setDefaultNodeLabel(newDefault) { - this.#defaultNodeLabelFn = newDefault; + this._defaultNodeLabelFn = newDefault; if (typeof newDefault !== 'function') { - this.#defaultNodeLabelFn = () => newDefault; + this._defaultNodeLabelFn = () => newDefault; } return this; @@ -743,7 +743,7 @@ class Graph { * Complexity: O(1). */ nodeCount() { - return this.#nodeCount; + return this._nodeCount; } /** @@ -752,7 +752,7 @@ class Graph { * Complexity: O(1). */ nodes() { - return Object.keys(this.#nodes); + return Object.keys(this._nodes); } /** @@ -761,7 +761,7 @@ class Graph { */ sources() { var self = this; - return this.nodes().filter(v => Object.keys(self.#in[v]).length === 0); + return this.nodes().filter(v => Object.keys(self._in[v]).length === 0); } /** @@ -770,7 +770,7 @@ class Graph { */ sinks() { var self = this; - return this.nodes().filter(v => Object.keys(self.#out[v]).length === 0); + return this.nodes().filter(v => Object.keys(self._out[v]).length === 0); } /** @@ -797,24 +797,24 @@ class Graph { * Complexity: O(1). */ setNode(v, value) { - if (this.#nodes.hasOwnProperty(v)) { + if (this._nodes.hasOwnProperty(v)) { if (arguments.length > 1) { - this.#nodes[v] = value; + 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._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; + this._in[v] = {}; + this._preds[v] = {}; + this._out[v] = {}; + this._sucs[v] = {}; + ++this._nodeCount; return this; } @@ -823,14 +823,14 @@ class Graph { * Complexity: O(|V|). */ node(v) { - return this.#nodes[v]; + return this._nodes[v]; } /** * Detects whether graph has a node with specified name or not. */ hasNode(v) { - return this.#nodes.hasOwnProperty(v); + return this._nodes.hasOwnProperty(v); } /** @@ -841,24 +841,24 @@ class Graph { */ 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]; + 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]; + 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; + 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; } @@ -870,7 +870,7 @@ class Graph { * Average-case complexity: O(1). */ setParent(v, parent) { - if (!this.#isCompound) { + if (!this._isCompound) { throw new Error("Cannot set parent in a non-compound graph"); } @@ -890,14 +890,14 @@ class Graph { } this.setNode(v); - this.#removeFromParentsChildList(v); - this.#parent[v] = parent; - this.#children[parent][v] = true; + this._removeFromParentsChildList(v); + this._parent[v] = parent; + this._children[parent][v] = true; return this; } - #removeFromParentsChildList(v) { - delete this.#children[this.#parent[v]][v]; + _removeFromParentsChildList(v) { + delete this._children[this._parent[v]][v]; } /** @@ -905,8 +905,8 @@ class Graph { * Complexity: O(1). */ parent(v) { - if (this.#isCompound) { - var parent = this.#parent[v]; + if (this._isCompound) { + var parent = this._parent[v]; if (parent !== GRAPH_NODE) { return parent; } @@ -918,8 +918,8 @@ class Graph { * Complexity: O(1). */ children(v = GRAPH_NODE) { - if (this.#isCompound) { - var children = this.#children[v]; + if (this._isCompound) { + var children = this._children[v]; if (children) { return Object.keys(children); } @@ -936,7 +936,7 @@ class Graph { * Complexity: O(|V|). */ predecessors(v) { - var predsV = this.#preds[v]; + var predsV = this._preds[v]; if (predsV) { return Object.keys(predsV); } @@ -948,7 +948,7 @@ class Graph { * Complexity: O(|V|). */ successors(v) { - var sucsV = this.#sucs[v]; + var sucsV = this._sucs[v]; if (sucsV) { return Object.keys(sucsV); } @@ -989,21 +989,21 @@ class Graph { */ filterNodes(filter) { var copy = new this.constructor({ - directed: this.#isDirected, - multigraph: this.#isMultigraph, - compound: this.#isCompound + directed: this._isDirected, + multigraph: this._isMultigraph, + compound: this._isCompound }); copy.setGraph(this.graph()); var self = this; - Object.entries(this.#nodes).forEach(function([v, value]) { + Object.entries(this._nodes).forEach(function([v, value]) { if (filter(v)) { copy.setNode(v, value); } }); - Object.values(this.#edgeObjs).forEach(function(e) { + Object.values(this._edgeObjs).forEach(function(e) { if (copy.hasNode(e.v) && copy.hasNode(e.w)) { copy.setEdge(e, self.edge(e)); } @@ -1022,7 +1022,7 @@ class Graph { } } - if (this.#isCompound) { + if (this._isCompound) { copy.nodes().forEach(v => copy.setParent(v, findParent(v))); } @@ -1039,9 +1039,9 @@ class Graph { * Complexity: O(1). */ setDefaultEdgeLabel(newDefault) { - this.#defaultEdgeLabelFn = newDefault; + this._defaultEdgeLabelFn = newDefault; if (typeof newDefault !== 'function') { - this.#defaultEdgeLabelFn = () => newDefault; + this._defaultEdgeLabelFn = () => newDefault; } return this; @@ -1052,7 +1052,7 @@ class Graph { * Complexity: O(1). */ edgeCount() { - return this.#edgeCount; + return this._edgeCount; } /** @@ -1060,7 +1060,7 @@ class Graph { * Complexity: O(|E|). */ edges() { - return Object.values(this.#edgeObjs); + return Object.values(this._edgeObjs); } /** @@ -1118,15 +1118,15 @@ class Graph { name = "" + name; } - var e = edgeArgsToId(this.#isDirected, v, w, name); - if (this.#edgeLabels.hasOwnProperty(e)) { + var e = edgeArgsToId(this._isDirected, v, w, name); + if (this._edgeLabels.hasOwnProperty(e)) { if (valueSpecified) { - this.#edgeLabels[e] = value; + this._edgeLabels[e] = value; } return this; } - if (name !== undefined && !this.#isMultigraph) { + if (name !== undefined && !this._isMultigraph) { throw new Error("Cannot set a named edge when isMultigraph = false"); } @@ -1135,20 +1135,20 @@ class Graph { this.setNode(v); this.setNode(w); - this.#edgeLabels[e] = valueSpecified ? value : this.#defaultEdgeLabelFn(v, w, name); + this._edgeLabels[e] = valueSpecified ? value : this._defaultEdgeLabelFn(v, w, name); - var edgeObj = edgeArgsToObj(this.#isDirected, 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++; + 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; } @@ -1158,9 +1158,9 @@ class Graph { */ edge(v, w, name) { var e = (arguments.length === 1 - ? edgeObjToId(this.#isDirected, arguments[0]) - : edgeArgsToId(this.#isDirected, v, w, name)); - return this.#edgeLabels[e]; + ? edgeObjToId(this._isDirected, arguments[0]) + : edgeArgsToId(this._isDirected, v, w, name)); + return this._edgeLabels[e]; } /** @@ -1182,9 +1182,9 @@ class Graph { */ 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); + ? edgeObjToId(this._isDirected, arguments[0]) + : edgeArgsToId(this._isDirected, v, w, name)); + return this._edgeLabels.hasOwnProperty(e); } /** @@ -1193,19 +1193,19 @@ class Graph { */ 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]; + ? 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--; + 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; } @@ -1216,7 +1216,7 @@ class Graph { * Complexity: O(|E|). */ inEdges(v, u) { - var inV = this.#in[v]; + var inV = this._in[v]; if (inV) { var edges = Object.values(inV); if (!u) { @@ -1232,7 +1232,7 @@ class Graph { * Complexity: O(|E|). */ outEdges(v, w) { - var outV = this.#out[v]; + var outV = this._out[v]; if (outV) { var edges = Object.values(outV); if (!w) { @@ -1390,7 +1390,7 @@ function read(json) { } },{"./graph":16}],19:[function(require,module,exports){ -module.exports = '2.2.1'; +module.exports = '2.2.2'; },{}]},{},[1])(1) }); diff --git a/dist/graphlib.core.min.js b/dist/graphlib.core.min.js index d43b43f8..89756ba9 100644 --- a/dist/graphlib.core.min.js +++ b/dist/graphlib.core.min.js @@ -47,26 +47,26 @@ var results=[];function dfs(v){var entry=visited[v]={onStack:true,lowlink:index, * 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={}; +class PriorityQueue{_arr=[];_keyIndices={}; /** * Returns the number of elements in the queue. Takes `O(1)` time. - */size(){return this.#arr.length} + */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})} + */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)} + */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}} + */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} + */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`. @@ -74,17 +74,17 @@ class PriorityQueue{#arr=[];#keyIndices={}; * * @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} + */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} + */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)}_heapify(i){var arr=this._arr;var l=2*i;var r=l+1;var largest=i;if(l>1;if(arr[parent].priorityundefined; +_defaultNodeLabelFn=()=>undefined; // Defaults to be set when creating a new edge -#defaultEdgeLabelFn=()=>undefined; +_defaultEdgeLabelFn=()=>undefined; // v -> label -#nodes={}; +_nodes={}; // v -> edgeObj -#in={}; +_in={}; // u -> v -> Number -#preds={}; +_preds={}; // v -> edgeObj -#out={}; +_out={}; // v -> w -> Number -#sucs={}; +_sucs={}; // e -> edgeObj -#edgeObjs={}; +_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){ +_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={}; +this._parent={}; // v -> children -this.#children={};this.#children[GRAPH_NODE]={}}} +this._children={};this._children[GRAPH_NODE]={}}} /* === Graph functions ========= */ /** * Whether graph was created with 'directed' flag set to true or not. - */isDirected(){return this.#isDirected} + */isDirected(){return this._isDirected} /** * Whether graph was created with 'multigraph' flag set to true or not. - */isMultigraph(){return this.#isMultigraph} + */isMultigraph(){return this._isMultigraph} /** * Whether graph was created with 'compound' flag set to true or not. - */isCompound(){return this.#isCompound} + */isCompound(){return this._isCompound} /** * Sets the label of the graph. - */setGraph(label){this.#label=label;return this} + */setGraph(label){this._label=label;return this} /** * Gets the graph label. - */graph(){return this.#label} + */graph(){return this._label} /* === Node functions ========== */ /** * Sets the default node label. If newDefault is a function, it will be @@ -144,24 +144,24 @@ this.#children={};this.#children[GRAPH_NODE]={}}} * 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} + */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} + */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)} + */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)} + */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)} + */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|). @@ -171,46 +171,46 @@ this.#children={};this.#children[GRAPH_NODE]={}}} * 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} + */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]} + */node(v){return this._nodes[v]} /** * Detects whether graph has a node with specified name or not. - */hasNode(v){return this.#nodes.hasOwnProperty(v)} + */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} + */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{ + */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)}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]} +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}}} + */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[]}} + */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)}} + */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)}} + */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. @@ -221,7 +221,7 @@ parent+="";for(var ancestor=parent;ancestor!==undefined;ancestor=this.parent(anc * 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} + */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} /* === Edge functions ========== */ /** * Sets the default edge label or factory function. This label will be @@ -229,15 +229,15 @@ parent+="";for(var ancestor=parent;ancestor!==undefined;ancestor=this.parent(anc * 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} + */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} + */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)} + */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 @@ -249,16 +249,16 @@ parent+="";for(var ancestor=parent;ancestor!==undefined;ancestor=this.parent(anc * 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")} + */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")} // 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} +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]} + */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) @@ -266,21 +266,21 @@ v=edgeObj.v;w=edgeObj.w;Object.freeze(edgeObj);this.#edgeObjs[e]=edgeObj;increme /** * 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)} + */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} + */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)}} + */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)}} + */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. @@ -301,4 +301,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":16}],19:[function(require,module,exports){module.exports="2.2.1"},{}]},{},[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":16}],19:[function(require,module,exports){module.exports="2.2.2"},{}]},{},[1])(1)}); diff --git a/dist/graphlib.js b/dist/graphlib.js index 1ed4f81f..d9924a35 100644 --- a/dist/graphlib.js +++ b/dist/graphlib.js @@ -459,28 +459,28 @@ topsort.CycleException = CycleException; * have its priority decreased in O(log n) time. */ class PriorityQueue { - #arr = []; - #keyIndices = {}; + _arr = []; + _keyIndices = {}; /** * Returns the number of elements in the queue. Takes `O(1)` time. */ size() { - return this.#arr.length; + 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; }); + 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); + return this._keyIndices.hasOwnProperty(key); } /** @@ -490,9 +490,9 @@ class PriorityQueue { * @param {Object} key */ priority(key) { - var index = this.#keyIndices[key]; + var index = this._keyIndices[key]; if (index !== undefined) { - return this.#arr[index].priority; + return this._arr[index].priority; } } @@ -504,7 +504,7 @@ class PriorityQueue { if (this.size() === 0) { throw new Error("Queue underflow"); } - return this.#arr[0].key; + return this._arr[0].key; } /** @@ -516,14 +516,14 @@ class PriorityQueue { * @param {Number} priority the initial priority for the key */ add(key, priority) { - var keyIndices = this.#keyIndices; + var keyIndices = this._keyIndices; key = String(key); if (!keyIndices.hasOwnProperty(key)) { - var arr = this.#arr; + var arr = this._arr; var index = arr.length; keyIndices[key] = index; arr.push({key: key, priority: priority}); - this.#decrease(index); + this._decrease(index); return true; } return false; @@ -533,10 +533,10 @@ class PriorityQueue { * 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); + this._swap(0, this._arr.length - 1); + var min = this._arr.pop(); + delete this._keyIndices[min.key]; + this._heapify(0); return min.key; } @@ -548,17 +548,17 @@ class PriorityQueue { * @param {Number} priority the new priority for the key */ decrease(key, priority) { - var index = this.#keyIndices[key]; - if (priority > this.#arr[index].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); + "Key: " + key + " Old: " + this._arr[index].priority + " New: " + priority); } - this.#arr[index].priority = priority; - this.#decrease(index); + this._arr[index].priority = priority; + this._decrease(index); } - #heapify(i) { - var arr = this.#arr; + _heapify(i) { + var arr = this._arr; var l = 2 * i; var r = l + 1; var largest = i; @@ -568,14 +568,14 @@ class PriorityQueue { largest = arr[r].priority < arr[largest].priority ? r : largest; } if (largest !== i) { - this.#swap(i, largest); - this.#heapify(largest); + this._swap(i, largest); + this._heapify(largest); } } } - #decrease(index) { - var arr = this.#arr; + _decrease(index) { + var arr = this._arr; var priority = arr[index].priority; var parent; while (index !== 0) { @@ -583,14 +583,14 @@ class PriorityQueue { if (arr[parent].priority < priority) { break; } - this.#swap(index, parent); + this._swap(index, parent); index = parent; } } - #swap(i, j) { - var arr = this.#arr; - var keyIndices = this.#keyIndices; + _swap(i, j) { + var arr = this._arr; + var keyIndices = this._keyIndices; var origArrI = arr[i]; var origArrJ = arr[j]; arr[i] = origArrJ; @@ -620,64 +620,64 @@ var EDGE_KEY_DELIM = "\x01"; // we're going to get to a performant hashtable in JavaScript. class Graph { - #isDirected = true; - #isMultigraph = false; - #isCompound = false; + _isDirected = true; + _isMultigraph = false; + _isCompound = false; // Label for the graph itself - #label; + _label; // Defaults to be set when creating a new node - #defaultNodeLabelFn = () => undefined; + _defaultNodeLabelFn = () => undefined; // Defaults to be set when creating a new edge - #defaultEdgeLabelFn = () => undefined; + _defaultEdgeLabelFn = () => undefined; // v -> label - #nodes = {}; + _nodes = {}; // v -> edgeObj - #in = {}; + _in = {}; // u -> v -> Number - #preds = {}; + _preds = {}; // v -> edgeObj - #out = {}; + _out = {}; // v -> w -> Number - #sucs = {}; + _sucs = {}; // e -> edgeObj - #edgeObjs = {}; + _edgeObjs = {}; // e -> label - #edgeLabels = {}; + _edgeLabels = {}; /* Number of nodes in the graph. Should only be changed by the implementation. */ - #nodeCount = 0; + _nodeCount = 0; /* Number of edges in the graph. Should only be changed by the implementation. */ - #edgeCount = 0; + _edgeCount = 0; - #parent; + _parent; - #children; + _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; + 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) { + if (this._isCompound) { // v -> parent - this.#parent = {}; + this._parent = {}; // v -> children - this.#children = {}; - this.#children[GRAPH_NODE] = {}; + this._children = {}; + this._children[GRAPH_NODE] = {}; } } @@ -687,28 +687,28 @@ class Graph { * Whether graph was created with 'directed' flag set to true or not. */ isDirected() { - return this.#isDirected; + return this._isDirected; } /** * Whether graph was created with 'multigraph' flag set to true or not. */ isMultigraph() { - return this.#isMultigraph; + return this._isMultigraph; } /** * Whether graph was created with 'compound' flag set to true or not. */ isCompound() { - return this.#isCompound; + return this._isCompound; } /** * Sets the label of the graph. */ setGraph(label) { - this.#label = label; + this._label = label; return this; } @@ -716,7 +716,7 @@ class Graph { * Gets the graph label. */ graph() { - return this.#label; + return this._label; } @@ -730,9 +730,9 @@ class Graph { * Complexity: O(1). */ setDefaultNodeLabel(newDefault) { - this.#defaultNodeLabelFn = newDefault; + this._defaultNodeLabelFn = newDefault; if (typeof newDefault !== 'function') { - this.#defaultNodeLabelFn = () => newDefault; + this._defaultNodeLabelFn = () => newDefault; } return this; @@ -743,7 +743,7 @@ class Graph { * Complexity: O(1). */ nodeCount() { - return this.#nodeCount; + return this._nodeCount; } /** @@ -752,7 +752,7 @@ class Graph { * Complexity: O(1). */ nodes() { - return Object.keys(this.#nodes); + return Object.keys(this._nodes); } /** @@ -761,7 +761,7 @@ class Graph { */ sources() { var self = this; - return this.nodes().filter(v => Object.keys(self.#in[v]).length === 0); + return this.nodes().filter(v => Object.keys(self._in[v]).length === 0); } /** @@ -770,7 +770,7 @@ class Graph { */ sinks() { var self = this; - return this.nodes().filter(v => Object.keys(self.#out[v]).length === 0); + return this.nodes().filter(v => Object.keys(self._out[v]).length === 0); } /** @@ -797,24 +797,24 @@ class Graph { * Complexity: O(1). */ setNode(v, value) { - if (this.#nodes.hasOwnProperty(v)) { + if (this._nodes.hasOwnProperty(v)) { if (arguments.length > 1) { - this.#nodes[v] = value; + 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._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; + this._in[v] = {}; + this._preds[v] = {}; + this._out[v] = {}; + this._sucs[v] = {}; + ++this._nodeCount; return this; } @@ -823,14 +823,14 @@ class Graph { * Complexity: O(|V|). */ node(v) { - return this.#nodes[v]; + return this._nodes[v]; } /** * Detects whether graph has a node with specified name or not. */ hasNode(v) { - return this.#nodes.hasOwnProperty(v); + return this._nodes.hasOwnProperty(v); } /** @@ -841,24 +841,24 @@ class Graph { */ 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]; + 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]; + 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; + 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; } @@ -870,7 +870,7 @@ class Graph { * Average-case complexity: O(1). */ setParent(v, parent) { - if (!this.#isCompound) { + if (!this._isCompound) { throw new Error("Cannot set parent in a non-compound graph"); } @@ -890,14 +890,14 @@ class Graph { } this.setNode(v); - this.#removeFromParentsChildList(v); - this.#parent[v] = parent; - this.#children[parent][v] = true; + this._removeFromParentsChildList(v); + this._parent[v] = parent; + this._children[parent][v] = true; return this; } - #removeFromParentsChildList(v) { - delete this.#children[this.#parent[v]][v]; + _removeFromParentsChildList(v) { + delete this._children[this._parent[v]][v]; } /** @@ -905,8 +905,8 @@ class Graph { * Complexity: O(1). */ parent(v) { - if (this.#isCompound) { - var parent = this.#parent[v]; + if (this._isCompound) { + var parent = this._parent[v]; if (parent !== GRAPH_NODE) { return parent; } @@ -918,8 +918,8 @@ class Graph { * Complexity: O(1). */ children(v = GRAPH_NODE) { - if (this.#isCompound) { - var children = this.#children[v]; + if (this._isCompound) { + var children = this._children[v]; if (children) { return Object.keys(children); } @@ -936,7 +936,7 @@ class Graph { * Complexity: O(|V|). */ predecessors(v) { - var predsV = this.#preds[v]; + var predsV = this._preds[v]; if (predsV) { return Object.keys(predsV); } @@ -948,7 +948,7 @@ class Graph { * Complexity: O(|V|). */ successors(v) { - var sucsV = this.#sucs[v]; + var sucsV = this._sucs[v]; if (sucsV) { return Object.keys(sucsV); } @@ -989,21 +989,21 @@ class Graph { */ filterNodes(filter) { var copy = new this.constructor({ - directed: this.#isDirected, - multigraph: this.#isMultigraph, - compound: this.#isCompound + directed: this._isDirected, + multigraph: this._isMultigraph, + compound: this._isCompound }); copy.setGraph(this.graph()); var self = this; - Object.entries(this.#nodes).forEach(function([v, value]) { + Object.entries(this._nodes).forEach(function([v, value]) { if (filter(v)) { copy.setNode(v, value); } }); - Object.values(this.#edgeObjs).forEach(function(e) { + Object.values(this._edgeObjs).forEach(function(e) { if (copy.hasNode(e.v) && copy.hasNode(e.w)) { copy.setEdge(e, self.edge(e)); } @@ -1022,7 +1022,7 @@ class Graph { } } - if (this.#isCompound) { + if (this._isCompound) { copy.nodes().forEach(v => copy.setParent(v, findParent(v))); } @@ -1039,9 +1039,9 @@ class Graph { * Complexity: O(1). */ setDefaultEdgeLabel(newDefault) { - this.#defaultEdgeLabelFn = newDefault; + this._defaultEdgeLabelFn = newDefault; if (typeof newDefault !== 'function') { - this.#defaultEdgeLabelFn = () => newDefault; + this._defaultEdgeLabelFn = () => newDefault; } return this; @@ -1052,7 +1052,7 @@ class Graph { * Complexity: O(1). */ edgeCount() { - return this.#edgeCount; + return this._edgeCount; } /** @@ -1060,7 +1060,7 @@ class Graph { * Complexity: O(|E|). */ edges() { - return Object.values(this.#edgeObjs); + return Object.values(this._edgeObjs); } /** @@ -1118,15 +1118,15 @@ class Graph { name = "" + name; } - var e = edgeArgsToId(this.#isDirected, v, w, name); - if (this.#edgeLabels.hasOwnProperty(e)) { + var e = edgeArgsToId(this._isDirected, v, w, name); + if (this._edgeLabels.hasOwnProperty(e)) { if (valueSpecified) { - this.#edgeLabels[e] = value; + this._edgeLabels[e] = value; } return this; } - if (name !== undefined && !this.#isMultigraph) { + if (name !== undefined && !this._isMultigraph) { throw new Error("Cannot set a named edge when isMultigraph = false"); } @@ -1135,20 +1135,20 @@ class Graph { this.setNode(v); this.setNode(w); - this.#edgeLabels[e] = valueSpecified ? value : this.#defaultEdgeLabelFn(v, w, name); + this._edgeLabels[e] = valueSpecified ? value : this._defaultEdgeLabelFn(v, w, name); - var edgeObj = edgeArgsToObj(this.#isDirected, 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++; + 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; } @@ -1158,9 +1158,9 @@ class Graph { */ edge(v, w, name) { var e = (arguments.length === 1 - ? edgeObjToId(this.#isDirected, arguments[0]) - : edgeArgsToId(this.#isDirected, v, w, name)); - return this.#edgeLabels[e]; + ? edgeObjToId(this._isDirected, arguments[0]) + : edgeArgsToId(this._isDirected, v, w, name)); + return this._edgeLabels[e]; } /** @@ -1182,9 +1182,9 @@ class Graph { */ 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); + ? edgeObjToId(this._isDirected, arguments[0]) + : edgeArgsToId(this._isDirected, v, w, name)); + return this._edgeLabels.hasOwnProperty(e); } /** @@ -1193,19 +1193,19 @@ class Graph { */ 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]; + ? 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--; + 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; } @@ -1216,7 +1216,7 @@ class Graph { * Complexity: O(|E|). */ inEdges(v, u) { - var inV = this.#in[v]; + var inV = this._in[v]; if (inV) { var edges = Object.values(inV); if (!u) { @@ -1232,7 +1232,7 @@ class Graph { * Complexity: O(|E|). */ outEdges(v, w) { - var outV = this.#out[v]; + var outV = this._out[v]; if (outV) { var edges = Object.values(outV); if (!w) { @@ -1390,7 +1390,7 @@ function read(json) { } },{"./graph":16}],19:[function(require,module,exports){ -module.exports = '2.2.1'; +module.exports = '2.2.2'; },{}]},{},[1])(1) }); diff --git a/dist/graphlib.min.js b/dist/graphlib.min.js index d43b43f8..89756ba9 100644 --- a/dist/graphlib.min.js +++ b/dist/graphlib.min.js @@ -47,26 +47,26 @@ var results=[];function dfs(v){var entry=visited[v]={onStack:true,lowlink:index, * 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={}; +class PriorityQueue{_arr=[];_keyIndices={}; /** * Returns the number of elements in the queue. Takes `O(1)` time. - */size(){return this.#arr.length} + */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})} + */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)} + */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}} + */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} + */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`. @@ -74,17 +74,17 @@ class PriorityQueue{#arr=[];#keyIndices={}; * * @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} + */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} + */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)}_heapify(i){var arr=this._arr;var l=2*i;var r=l+1;var largest=i;if(l>1;if(arr[parent].priorityundefined; +_defaultNodeLabelFn=()=>undefined; // Defaults to be set when creating a new edge -#defaultEdgeLabelFn=()=>undefined; +_defaultEdgeLabelFn=()=>undefined; // v -> label -#nodes={}; +_nodes={}; // v -> edgeObj -#in={}; +_in={}; // u -> v -> Number -#preds={}; +_preds={}; // v -> edgeObj -#out={}; +_out={}; // v -> w -> Number -#sucs={}; +_sucs={}; // e -> edgeObj -#edgeObjs={}; +_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){ +_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={}; +this._parent={}; // v -> children -this.#children={};this.#children[GRAPH_NODE]={}}} +this._children={};this._children[GRAPH_NODE]={}}} /* === Graph functions ========= */ /** * Whether graph was created with 'directed' flag set to true or not. - */isDirected(){return this.#isDirected} + */isDirected(){return this._isDirected} /** * Whether graph was created with 'multigraph' flag set to true or not. - */isMultigraph(){return this.#isMultigraph} + */isMultigraph(){return this._isMultigraph} /** * Whether graph was created with 'compound' flag set to true or not. - */isCompound(){return this.#isCompound} + */isCompound(){return this._isCompound} /** * Sets the label of the graph. - */setGraph(label){this.#label=label;return this} + */setGraph(label){this._label=label;return this} /** * Gets the graph label. - */graph(){return this.#label} + */graph(){return this._label} /* === Node functions ========== */ /** * Sets the default node label. If newDefault is a function, it will be @@ -144,24 +144,24 @@ this.#children={};this.#children[GRAPH_NODE]={}}} * 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} + */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} + */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)} + */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)} + */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)} + */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|). @@ -171,46 +171,46 @@ this.#children={};this.#children[GRAPH_NODE]={}}} * 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} + */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]} + */node(v){return this._nodes[v]} /** * Detects whether graph has a node with specified name or not. - */hasNode(v){return this.#nodes.hasOwnProperty(v)} + */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} + */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{ + */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)}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]} +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}}} + */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[]}} + */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)}} + */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)}} + */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. @@ -221,7 +221,7 @@ parent+="";for(var ancestor=parent;ancestor!==undefined;ancestor=this.parent(anc * 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} + */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} /* === Edge functions ========== */ /** * Sets the default edge label or factory function. This label will be @@ -229,15 +229,15 @@ parent+="";for(var ancestor=parent;ancestor!==undefined;ancestor=this.parent(anc * 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} + */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} + */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)} + */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 @@ -249,16 +249,16 @@ parent+="";for(var ancestor=parent;ancestor!==undefined;ancestor=this.parent(anc * 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")} + */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")} // 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} +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]} + */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) @@ -266,21 +266,21 @@ v=edgeObj.v;w=edgeObj.w;Object.freeze(edgeObj);this.#edgeObjs[e]=edgeObj;increme /** * 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)} + */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} + */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)}} + */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)}} + */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. @@ -301,4 +301,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":16}],19:[function(require,module,exports){module.exports="2.2.1"},{}]},{},[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":16}],19:[function(require,module,exports){module.exports="2.2.2"},{}]},{},[1])(1)}); diff --git a/lib/version.js b/lib/version.js index e3d40348..a39338fe 100644 --- a/lib/version.js +++ b/lib/version.js @@ -1 +1 @@ -module.exports = '2.2.2-pre'; +module.exports = '2.2.2'; diff --git a/package-lock.json b/package-lock.json index c1f82066..29ecdfcf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@dagrejs/graphlib", - "version": "2.2.2-pre", + "version": "2.2.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@dagrejs/graphlib", - "version": "2.2.2-pre", + "version": "2.2.2", "license": "MIT", "devDependencies": { "benchmark": "2.1.4", diff --git a/package.json b/package.json index 391e63c7..994b16ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dagrejs/graphlib", - "version": "2.2.2-pre", + "version": "2.2.2", "description": "A directed and undirected multi-graph library", "author": "Chris Pettitt ", "license": "MIT", @@ -47,4 +47,4 @@ "type": "git", "url": "https://github.com/dagrejs/graphlib.git" } -} \ No newline at end of file +}