jsnetworkx
Version:
A graph processing and visualization library for JavaScript (port of NetworkX for Python).
1,544 lines (1,326 loc) • 47.1 kB
JavaScript
var _get = require('babel-runtime/helpers/get')['default'];
var _inherits = require('babel-runtime/helpers/inherits')['default'];
var _createClass = require('babel-runtime/helpers/create-class')['default'];
var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default'];
var _defineProperty = require('babel-runtime/helpers/define-property')['default'];
var _slicedToArray = require('babel-runtime/helpers/sliced-to-array')['default'];
var _regeneratorRuntime = require('babel-runtime/regenerator')['default'];
var _Object$keys = require('babel-runtime/core-js/object/keys')['default'];
var _Object$assign = require('babel-runtime/core-js/object/assign')['default'];
var _Array$from = require('babel-runtime/core-js/array/from')['default'];
var _getIterator = require('babel-runtime/core-js/get-iterator')['default'];
var _Object$getOwnPropertyNames = require('babel-runtime/core-js/object/get-own-property-names')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
Object.defineProperty(exports, '__esModule', {
value: true
});
var marked0$0 = [yieldEdges, yieldDegree].map(_regeneratorRuntime.mark);
var _DiGraph2 = require('./DiGraph');
var _DiGraph3 = _interopRequireDefault(_DiGraph2);
var _MultiGraph = require('./MultiGraph');
var _MultiGraph2 = _interopRequireDefault(_MultiGraph);
var _exceptionsJSNetworkXError = require('../exceptions/JSNetworkXError');
var _exceptionsJSNetworkXError2 = _interopRequireDefault(_exceptionsJSNetworkXError);
var _internals = require('../_internals');
/**
* A directed graph class that can store multiedges.
*
* Multiedges are multiple edges between two nodes. Each edge can hold optional
* data or attributes.
*
* A MultiDiGraph holds directed edges. Self loops are allowed. Edges are
* respresented as links between nodes with optional key/value attributes.
*
* ### Example
*
* Create an empty graph structure (a "null graph") with no nodes and no edges:
*
* ```
* var G = new jsnx.MultiDiGraph();
* ```
*
* G can be grown in several ways.
*
* #### Nodes
*
* Add one node at a time:
*
* ```
* G.addNode(1);
* ```
*
* Add the nodes from any iterable:
*
* ```
* G.addNodesFrom([2,3]);
* var H = new jsnx.Graph();
* H.addPath([0,1,2,3,4,5]);
* G.addNodesFrom(H);
* ```
*
* In addition to strings and integers, any object that implements a custom
* `toString` method can represent a node.
*
* #### Edges
*
* `G` can also be grown by adding edges. Add one edge,
*
* ```
* G.addEdge(1, 2);
* ```
*
* a list of edges,
*
* ```
* G.addEdgesFrom([[1,2], [1,3]]);
* ```
*
* or a collection of edges
*
* ```
* G.addEdgesFrom(H.edges());
* ```
*
* If some edges connect nodes not yet in the graph, the nodes are added
* automatically. If an edge already exists, an additional edge is created and
* stored using a key to identify the edge. By default the key is the lowest
* unused integer.
*
* ```
* G.addEdgesFrom([[4,5,{route:282}], [4,5,{route:37}]]);
* G.get(4);
* // Map {5: {0: {}, 1: {route: 282}, 2: {route: 37}}}
*
* #### Attributes
*
* Each graph, node and edge can hold key/value attribute pairs in an associated
* attribute object. By default these are empty, but can be added or changed
* using `addEdge` or `addNode`.
*
* ```
* G.addNode(1, {time: '5pm'});
* G.addNodesFrom([3], {time: '2pm'});
* G.nodes(true);
* // [[1, {time: '5pm'}], [3, {time: '2pm'}]]
* ```
*
* Add edge attributes using `addEdge` and `addEdgesFrom`:
*
* ```
* G.addEdge(1, 2, {weight: 4.7});
* G.addEdgesFrom([[3,4], [4,5]], {color: 'red'});
* G.addEdgesFrom([[1,2,{color: 'blue'}], [2,3,{weight: 8}]]);
* ```
*/
var MultiDiGraph = (function (_DiGraph) {
_inherits(MultiDiGraph, _DiGraph);
/**
* @param {(Object|Array|Graph)} optData Data to initialize graph.
* If no data is passed, an empty graph is created. The data can be an edge
* list, or any JSNetworkX graph object.
* @param {Object=} opt_attr (default= no attributes)
* Attributes to add to graph as key=value pairs.
*/
function MultiDiGraph(optData, optAttr) {
_classCallCheck(this, MultiDiGraph);
_get(Object.getPrototypeOf(MultiDiGraph.prototype), 'constructor', this).call(this, optData, optAttr);
}
_createClass(MultiDiGraph, [{
key: 'addEdge',
/**
* Add an edge between u and v.
*
* The nodes u and v will be automatically added if they are not already in
* the graph.
*
* Edge attributes can be specified by providing an object with key/value
* pairs.
*
* ### Note
*
* To replace/update edge data, use the optional key argument to identify a
* unique edge. Otherwise a new edge will be created.
*
* ### Example
*
* The following add the edge e=(1,2) to graph G:
*
* ```
* var G = new jsnx.MultiDiGraph();
* G.addEdge(1, 2);
* G.addEdgesFrom([[1,2]]);
* ```
*
* Associate data to edges using keywords:
*
* ```
* G.addEdge(1, 2, {weight: 3});
* G.addEdge(1, 2, 0, {weight: 4}); // update data for key=0
* G.addEdge(1, 3, {weight: 7, capacity: 15, length: 342.7});
* ```
* @param {Node} u
* @param {Node} v
* @param {(string|number)} optKey (default=lowest unused integer) Used to
* distinguish multiedges between a pair of nodes.
* @param {Object} opAttrDict Object of edge attributes. Key/value pairs will
* update existing data associated with the edge.
*/
value: function addEdge(u, v, optKey, optAttrDict) {
if (optKey && typeof optKey === 'object') {
optAttrDict = optKey;
optKey = null;
}
if (optAttrDict && !(0, _internals.isPlainObject)(optAttrDict)) {
throw new _exceptionsJSNetworkXError2['default']('The optAttrDict argument must be a plain object.');
}
// add nodes
var keydict;
if (!this.succ.has(u)) {
this.succ.set(u, new _internals.Map());
this.pred.set(u, new _internals.Map());
this.node.set(u, {});
}
if (!this.succ.has(v)) {
this.succ.set(v, new _internals.Map());
this.pred.set(v, new _internals.Map());
this.node.set(v, {});
}
if (this.succ.get(u).has(v)) {
keydict = this.get(u).get(v);
if (optKey == null) {
// find unique integer key
optKey = _Object$keys(keydict).length;
while (keydict[optKey]) {
optKey += 1;
}
}
keydict[optKey] = _Object$assign((0, _internals.getDefault)(keydict[optKey], {}), optAttrDict);
} else {
// selfloops work this way without special treatment
if (optKey == null) {
optKey = 0;
}
keydict = _defineProperty({}, optKey, _Object$assign({}, optAttrDict));
this.succ.get(u).set(v, keydict);
this.pred.get(v).set(u, keydict);
}
}
}, {
key: 'removeEdge',
/**
* Remove an edge between u and v.
*
* ### Example
*
* ```
* var G = new jsnx.MultiDiGraph();
* G.addPath([0,1,2,3]);
* G.removeEdge(0, 1);
* ```
*
* For multiple edges:
*
* ```
* var G = new jsnx.MultiDiGraph();
* G.addEdgesFrom([[1,2], [1,2], [1,2]]);
* G.removeEdge(1, 2); // remove a single (arbitrary) edge
* ```
*
* For edges with keys:
*
* ```
* var G = new jsnx.MultiDiGraph();
* G.addEdge(1, 2, 'first');
* G.addEdge(1, 2, 'second');
* G.removeEdge(1, 2, 'second');
* ```
* @param {Node} u
* @param {Node} v
* @param {(string|number)} optKey Used to distinguish multiple edges between
* a pair of nodes. If undefined, remove a single (arbitrary) edge between
* u and v.
*/
value: function removeEdge(u, v, optKey) {
var keydict;
var neightborsOfU = this.adj.get(u);
if (neightborsOfU) {
keydict = neightborsOfU.get(v);
}
if (keydict == null) {
throw new _exceptionsJSNetworkXError2['default']((0, _internals.sprintf)('The edge %j-%j is not in the graph', u, v));
}
// remove the edge with specified data
if (optKey == null) {
for (var key in keydict) {
delete keydict[key];
break;
}
} else {
if (!keydict[optKey]) {
throw new _exceptionsJSNetworkXError2['default']((0, _internals.sprintf)('The edge %j-%j with key %j is not in the graph', u, v, optKey));
}
delete keydict[optKey];
}
if (_Object$keys(keydict).length === 0) {
// remove the key entries if last edge
this.succ.get(u)['delete'](v);
this.pred.get(v)['delete'](u);
}
}
}, {
key: 'edgesIter',
/**
* Return an iterator over the edges.
*
* Edges are returned as tuples with optional data and keys in the order
* `(node, neighbor, key, data)`.
*
* ### Note
*
* Nodes in `optNbunch` that are not in the graph will be (quietly) ignored.
* For directed graphs this returns the out-edges.
*
* ### Example
*
* ```
* var G = new jsnx.MultiDiGraph();
* G.addPath([0,1,2,3]);
* Array.from(G.edgesIter());
* // [[0,1], [1,2], [2,3]]
* Array.from(G.edgesIter(true));
* // [[0,1,{}], [1,2,{}], [2,3,{}]]
* Array.from(G.edgesIter([0,2]));
* // [[0,1], [2,3]]
* ```
*
* @alias outEdgesIter
*
* @param {Iterable} optNbunch (default=all nodes) A container of nodes.
* The container will be iterated over only once.
* @param {boolean} optData (default=false) If true, return edge attribute
* dictionaries with each edge.
* @param {boolean} optKeys (default=flase) If true, return edge keys with
* each edge.
* @return {Iterator} An iterator of `(u,v)`, `(u,v,d)` or `(u,v,key,d)` edges
*/
value: _regeneratorRuntime.mark(function edgesIter(optNbunch) {
var optData = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];
var optKeys = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
var nodesNbrs;
return _regeneratorRuntime.wrap(function edgesIter$(context$2$0) {
// istanbul ignore next
var _this = this;
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
if (typeof optNbunch === 'boolean') {
optKeys = optData;
optData = optNbunch;
optNbunch = null;
}
nodesNbrs = optNbunch == null ? this.adj : (0, _internals.mapIterator)(this.nbunchIter(optNbunch), function (n) {
return (0, _internals.tuple2)(n, _this.adj.get(n));
});
return context$2$0.delegateYield(yieldEdges(nodesNbrs, optData, optKeys, 'out'), 't0', 3);
case 3:
case 'end':
return context$2$0.stop();
}
}, edgesIter, this);
})
}, {
key: 'outEdgesIter',
/**
* @alias edgesIter
*/
value: function outEdgesIter(optNbunch, optData, optKeys) {
return this.edgesIter(optNbunch, optData, optKeys);
}
}, {
key: 'outEdges',
/**
* Return a list of the outgoing edges.
*
* Edges are returned as tuples with optional data and keys in the order
* `(node, neighbor, key, data)`.
*
* ### Note
*
* Nodes in `optNbunch` that are not in the graph will be (quietly) ignored.
* For directed graphs `edges()` is the same as `outEdges()`.
*
* @see inEdges
*
* @param {Iterable} optNbunch (default=all nodes) A container of nodes.
* The container will be iterated over only once.
* @param {boolean} optData (default=false) If true, return edge attribute
* dictionaries with each edge.
* @param {boolean} optKeys (default=flase) If true, return edge keys with
* each edge.
* @return {Array} A list of `(u,v)`, `(u,v,d)` or `(u,v,key,d)` tuples of
* edges
*/
value: function outEdges(optNbunch, optData, optKeys) {
return _Array$from(this.outEdgesIter(optNbunch, optData, optKeys));
}
}, {
key: 'inEdgesIter',
/**
* Return an iterator over the incoming edges.
*
* Edges are returned as tuples with optional data and keys in the order
* `(node, neighbor, key, data)`.
*
* @see edgesIter
*
* @param {Iterable=} optNbunch (default=all nodes) A container of nodes.
* The container will be iterated over only once.
* @param {boolean=} optData (default=false) If true, return edge attribute
* dictionaries with each edge.
* @param {boolean=} optKeys (default=flase) If true, return edge keys with
* each edge.
* @return {Iterator} An iterator of `(u,v)`, `(u,v,d)` or `(u,v,key,d)` edges
*/
value: _regeneratorRuntime.mark(function inEdgesIter(optNbunch) {
var optData = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];
var optKeys = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
var nodesNbrs;
return _regeneratorRuntime.wrap(function inEdgesIter$(context$2$0) {
// istanbul ignore next
var _this2 = this;
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
if (typeof optNbunch === 'boolean') {
optKeys = optData;
optData = optNbunch;
optNbunch = null;
}
nodesNbrs = optNbunch == null ? this.pred : (0, _internals.mapIterator)(this.nbunchIter(optNbunch), function (n) {
return (0, _internals.tuple2)(n, _this2.pred.get(n));
});
return context$2$0.delegateYield(yieldEdges(nodesNbrs, optData, optKeys, 'in'), 't0', 3);
case 3:
case 'end':
return context$2$0.stop();
}
}, inEdgesIter, this);
})
}, {
key: 'inEdges',
/**
* Return a list of the incoming edges.
*
* @see outEdges
*
* @param {Iterable=} optNbunch (default=all nodes) A container of nodes.
* The container will be iterated over only once.
* @param {boolean=} optData (default=false) If true, return edge attribute
* dictionaries with each edge.
* @param {boolean=} optKeys (default=flase) If true, return edge keys with
* each edge.
* @return {Array} A list of `(u,v)`, `(u,v,d)` or `(u,v,key,d)` tuples of
* edges
*/
value: function inEdges(optNbunch, optData, optKeys) {
return _Array$from(this.inEdgesIter(optNbunch, optData, optKeys));
}
}, {
key: 'degreeIter',
/**
* Return an iterator for `(node, degree)`.
*
* The node degree is the number of edges adjacent to the node.
*
* ### Example
*
* ```
* var G = new jsnx.MultiDiGraph();
* G.addPath([0,1,2,3]);
* Array.from(G.degreeIter([0,1]));
* // [[0,1], [1,2]]
* ```
*
* @param {Iterable=} optNbunch (default=all nodes) A container of nodes.
* The container will be iterated through once.
* @param {string=} optString (default=null)
* The edge attribute that holds the numerical value used as a weight. If
* None, then each edge has weight 1.
* The degree is the sum of the edge weights.
* @return {Iterator} The iterator returns two-tuples of `(node, degree)`.
*/
value: _regeneratorRuntime.mark(function degreeIter(optNbunch, optWeight) {
var tuple2Succ, tuple2Pred, nodesNbrs, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step$value, _step$value$0, n, succ, _step$value$1, _, pred, keydict, inDegree, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, outDegree, _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, _iteratorNormalCompletion4, _didIteratorError4, _iteratorError4, _iterator4, _step4, _step4$value, _step4$value$0, _step4$value$1;
return _regeneratorRuntime.wrap(function degreeIter$(context$2$0) {
// istanbul ignore next
var _this3 = this;
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
tuple2Succ = (0, _internals.createTupleFactory)(2);
tuple2Pred = (0, _internals.createTupleFactory)(2);
nodesNbrs = optNbunch == null ? (0, _internals.zipIterator)(this.succ.entries(), this.pred.entries()) : (0, _internals.zipIterator)((0, _internals.mapIterator)(this.nbunchIter(optNbunch), function (n) {
return tuple2Succ(n, _this3.succ.get(n));
}), (0, _internals.mapIterator)(this.nbunchIter(optNbunch), function (n) {
return tuple2Pred(n, _this3.pred.get(n));
}));
if (!(optWeight == null)) {
context$2$0.next = 78;
break;
}
_iteratorNormalCompletion = true;
_didIteratorError = false;
_iteratorError = undefined;
context$2$0.prev = 7;
_iterator = _getIterator(nodesNbrs);
case 9:
if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
context$2$0.next = 62;
break;
}
_step$value = _slicedToArray(_step.value, 2);
_step$value$0 = _slicedToArray(_step$value[0], 2);
n = _step$value$0[0];
succ = _step$value$0[1];
_step$value$1 = _slicedToArray(_step$value[1], 2);
_ = _step$value$1[0];
pred = _step$value$1[1];
inDegree = 0;
_iteratorNormalCompletion2 = true;
_didIteratorError2 = false;
_iteratorError2 = undefined;
context$2$0.prev = 21;
for (_iterator2 = _getIterator(pred.values()); !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
keydict = _step2.value;
inDegree += _Object$keys(keydict).length;
}
context$2$0.next = 29;
break;
case 25:
context$2$0.prev = 25;
context$2$0.t0 = context$2$0['catch'](21);
_didIteratorError2 = true;
_iteratorError2 = context$2$0.t0;
case 29:
context$2$0.prev = 29;
context$2$0.prev = 30;
if (!_iteratorNormalCompletion2 && _iterator2['return']) {
_iterator2['return']();
}
case 32:
context$2$0.prev = 32;
if (!_didIteratorError2) {
context$2$0.next = 35;
break;
}
throw _iteratorError2;
case 35:
return context$2$0.finish(32);
case 36:
return context$2$0.finish(29);
case 37:
outDegree = 0;
_iteratorNormalCompletion3 = true;
_didIteratorError3 = false;
_iteratorError3 = undefined;
context$2$0.prev = 41;
for (_iterator3 = _getIterator(succ.values()); !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
keydict = _step3.value;
inDegree += _Object$keys(keydict).length;
}
context$2$0.next = 49;
break;
case 45:
context$2$0.prev = 45;
context$2$0.t1 = context$2$0['catch'](41);
_didIteratorError3 = true;
_iteratorError3 = context$2$0.t1;
case 49:
context$2$0.prev = 49;
context$2$0.prev = 50;
if (!_iteratorNormalCompletion3 && _iterator3['return']) {
_iterator3['return']();
}
case 52:
context$2$0.prev = 52;
if (!_didIteratorError3) {
context$2$0.next = 55;
break;
}
throw _iteratorError3;
case 55:
return context$2$0.finish(52);
case 56:
return context$2$0.finish(49);
case 57:
context$2$0.next = 59;
return [n, inDegree + outDegree];
case 59:
_iteratorNormalCompletion = true;
context$2$0.next = 9;
break;
case 62:
context$2$0.next = 68;
break;
case 64:
context$2$0.prev = 64;
context$2$0.t2 = context$2$0['catch'](7);
_didIteratorError = true;
_iteratorError = context$2$0.t2;
case 68:
context$2$0.prev = 68;
context$2$0.prev = 69;
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
case 71:
context$2$0.prev = 71;
if (!_didIteratorError) {
context$2$0.next = 74;
break;
}
throw _iteratorError;
case 74:
return context$2$0.finish(71);
case 75:
return context$2$0.finish(68);
case 76:
context$2$0.next = 110;
break;
case 78:
_iteratorNormalCompletion4 = true;
_didIteratorError4 = false;
_iteratorError4 = undefined;
context$2$0.prev = 81;
_iterator4 = _getIterator(nodesNbrs);
case 83:
if (_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done) {
context$2$0.next = 96;
break;
}
_step4$value = _slicedToArray(_step4.value, 2);
_step4$value$0 = _slicedToArray(_step4$value[0], 2);
n = _step4$value$0[0];
succ = _step4$value$0[1];
_step4$value$1 = _slicedToArray(_step4$value[1], 2);
_ = _step4$value$1[0];
pred = _step4$value$1[1];
context$2$0.next = 93;
return [n, sumEdgeAttribute(pred, optWeight, 1) + sumEdgeAttribute(succ, optWeight, 1)];
case 93:
_iteratorNormalCompletion4 = true;
context$2$0.next = 83;
break;
case 96:
context$2$0.next = 102;
break;
case 98:
context$2$0.prev = 98;
context$2$0.t3 = context$2$0['catch'](81);
_didIteratorError4 = true;
_iteratorError4 = context$2$0.t3;
case 102:
context$2$0.prev = 102;
context$2$0.prev = 103;
if (!_iteratorNormalCompletion4 && _iterator4['return']) {
_iterator4['return']();
}
case 105:
context$2$0.prev = 105;
if (!_didIteratorError4) {
context$2$0.next = 108;
break;
}
throw _iteratorError4;
case 108:
return context$2$0.finish(105);
case 109:
return context$2$0.finish(102);
case 110:
case 'end':
return context$2$0.stop();
}
}, degreeIter, this, [[7, 64, 68, 76], [21, 25, 29, 37], [30,, 32, 36], [41, 45, 49, 57], [50,, 52, 56], [69,, 71, 75], [81, 98, 102, 110], [103,, 105, 109]]);
})
}, {
key: 'inDegreeIter',
/**
* Return an iterator for `(node, in-degree)`.
*
* The node in-degree is the number of edges pointing to the node.
*
* ### Example
*
* ```
* var G = new jsnx.MultiDiGraph();
* G.addPath([0,1,2,3]);
* Array.from(G.degreeIter([0,1]));
* // [[0,0], [1,1]]
* ```
*
* @param {Iterable=} optNbunch (default=all nodes) A container of nodes.
* The container will be iterated through once.
* @param {string=} optString (default=null)
* The edge attribute that holds the numerical value used as a weight. If
* None, then each edge has weight 1.
* The degree is the sum of the edge weights.
* @return {Iterator} The iterator returns two-tuples of `(node, degree)`.
*/
value: _regeneratorRuntime.mark(function inDegreeIter(optNbunch, optWeight) {
return _regeneratorRuntime.wrap(function inDegreeIter$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
return context$2$0.delegateYield(yieldDegree(this, this.pred, optNbunch, optWeight), 't0', 1);
case 1:
case 'end':
return context$2$0.stop();
}
}, inDegreeIter, this);
})
}, {
key: 'outDegreeIter',
/**
* Return an iterator for `(node, out-degree)`.
*
* The node out-degree is the number of edges pointing out of the node.
*
* ### Example
*
* ```
* var G = new jsnx.MultiDiGraph();
* G.addPath([0,1,2,3]);
* Array.from(G.degreeIter([0,1]));
* // [[0,1], [1,1]]
* ```
*
* @param {Iterable=} optNbunch (default=all nodes) A container of nodes.
* The container will be iterated through once.
* @param {string=} optString (default=null)
* The edge attribute that holds the numerical value used as a weight. If
* None, then each edge has weight 1.
* The degree is the sum of the edge weights.
* @return {Iterator} The iterator returns two-tuples of `(node, degree)`.
*/
value: _regeneratorRuntime.mark(function outDegreeIter(optNbunch, optWeight) {
return _regeneratorRuntime.wrap(function outDegreeIter$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
return context$2$0.delegateYield(yieldDegree(this, this.succ, optNbunch, optWeight), 't0', 1);
case 1:
case 'end':
return context$2$0.stop();
}
}, outDegreeIter, this);
})
}, {
key: 'isMultigraph',
/**
* Return True if graph is a multigraph, False otherwise.
*
* @return {boolean} True if graph is a multigraph, False otherwise.
*/
value: function isMultigraph() {
return true;
}
}, {
key: 'isDirected',
/**
* Return True if graph is directed, False otherwise.
*
* @return {boolean} True if graph is directed, False otherwise.
*/
value: function isDirected() {
return true;
}
}, {
key: 'toDirected',
/**
* Return a directed copy of the graph.
*
* ### Notes
*
* This returns a deep copy of the edge, node, and
* graph attributes which attempts to completely copy
* all of the data and references.
*
* This is in contrast to the similar `var G = new MultiDiGraph(D);`, which
* returns a shallow copy of the data.
*
* @return {MultiDiGraph} A deep copy of the graph.
*/
value: function toDirected() {
return (0, _internals.deepcopy)(this);
}
}, {
key: 'toUndirected',
/**
* Return an undirected representation of the digraph.
*
* ### Notes
*
* The result is an undirected graph with the same name, nodes and
* with edge `(u,v,data)` if either `(u,v,data)` or `(v,u,data)`
* is in the digraph. If both edges exist in digraph and
* their edge data is different, only one edge is created
* with an arbitrary choice of which edge data to use.
* You must check and correct for this manually if desired.
*
* This returns a deep copy of the edge, node, and
* graph attributes which attempts to completely copy
* all of the data and references.
*
* This is in contrast to the similar `var G = new MultiGraph(D);`, which
* returns a shallow copy of the data.
*
* @param {boolean=} optReciprocal If true, only keep edges that appear in
* both directions in the original digraph.
* @return {MultiGraph}
*/
value: function toUndirected(optReciprocal) {
var H = new _MultiGraph2['default']();
H.name = this.name;
H.addNodesFrom(this);
var _iteratorNormalCompletion5 = true;
var _didIteratorError5 = false;
var _iteratorError5 = undefined;
try {
for (var _iterator5 = _getIterator(this.adjacencyIter()), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
var _step5$value = _slicedToArray(_step5.value, 2);
var u = _step5$value[0];
var nbrs = _step5$value[1];
var _iteratorNormalCompletion6 = true;
var _didIteratorError6 = false;
var _iteratorError6 = undefined;
try {
for (var _iterator6 = _getIterator(nbrs), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
var _step6$value = _slicedToArray(_step6.value, 2);
var v = _step6$value[0];
var keydict = _step6$value[1];
for (var key in keydict) {
if (!optReciprocal || this.hasEdge(v, u, key)) {
H.addEdge(u, v, key, (0, _internals.deepcopy)(keydict[key]));
}
}
}
} catch (err) {
_didIteratorError6 = true;
_iteratorError6 = err;
} finally {
try {
if (!_iteratorNormalCompletion6 && _iterator6['return']) {
_iterator6['return']();
}
} finally {
if (_didIteratorError6) {
throw _iteratorError6;
}
}
}
}
} catch (err) {
_didIteratorError5 = true;
_iteratorError5 = err;
} finally {
try {
if (!_iteratorNormalCompletion5 && _iterator5['return']) {
_iterator5['return']();
}
} finally {
if (_didIteratorError5) {
throw _iteratorError5;
}
}
}
H.graph = (0, _internals.deepcopy)(this.graph);
H.node = (0, _internals.deepcopy)(this.node);
return H;
}
}, {
key: 'subgraph',
/**
* Return the subgraph induced on nodes in `nbunch`.
*
* The induced subgraph of the graph contains the nodes in `optNbunch` and the
* edges between those nodes.
*
* ### Notes
*
* The graph, edge or node attributes just point to the original graph.
* So changes to the node or edge structure will not be reflected in
* the original graph while changes to the attributes will.
*
* To create a subgraph with its own copy of the edge/node attributes use:
* `jsnx.MultiDiGraph(G.subgraph(nbunch))`.
*
* ### Example
*
* ```
* var G = new jsnx.MultiDiGraph();
* G.addPath([0,1,2,3]);
* var H = G.subgraph([0,1,2]);
* H.edges();
* // [[0,1], [1,2]]
* ```
*
* @param {Iterable} nBunch A container of nodes which will be iterated
* through once.
* @return {MultiDiGraph}
*/
value: function subgraph(nBunch) {
var bunch = this.nbunchIter(nBunch);
// create new graph and copy subgraph into it
var H = new this.constructor();
// copy node and attribute dictionaries
var _iteratorNormalCompletion7 = true;
var _didIteratorError7 = false;
var _iteratorError7 = undefined;
try {
for (var _iterator7 = _getIterator(bunch), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
var n = _step7.value;
H.node.set(n, this.node.get(n));
}
} catch (err) {
_didIteratorError7 = true;
_iteratorError7 = err;
} finally {
try {
if (!_iteratorNormalCompletion7 && _iterator7['return']) {
_iterator7['return']();
}
} finally {
if (_didIteratorError7) {
throw _iteratorError7;
}
}
}
var HSucc = H.succ;
var HPred = H.pred;
var thisSucc = this.succ;
// add nodes
var _iteratorNormalCompletion8 = true;
var _didIteratorError8 = false;
var _iteratorError8 = undefined;
try {
for (var _iterator8 = _getIterator(H), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
var n = _step8.value;
HSucc.set(n, new _internals.Map());
HPred.set(n, new _internals.Map());
}
} catch (err) {
_didIteratorError8 = true;
_iteratorError8 = err;
} finally {
try {
if (!_iteratorNormalCompletion8 && _iterator8['return']) {
_iterator8['return']();
}
} finally {
if (_didIteratorError8) {
throw _iteratorError8;
}
}
}
// add edges
var _iteratorNormalCompletion9 = true;
var _didIteratorError9 = false;
var _iteratorError9 = undefined;
try {
for (var _iterator9 = _getIterator(HSucc), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {
var _step9$value = _slicedToArray(_step9.value, 2);
var u = _step9$value[0];
var HNbrs = _step9$value[1];
var _iteratorNormalCompletion10 = true;
var _didIteratorError10 = false;
var _iteratorError10 = undefined;
try {
for (var _iterator10 = _getIterator(thisSucc.get(u)), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
var _step10$value = _slicedToArray(_step10.value, 2);
var v = _step10$value[0];
var keydict = _step10$value[1];
if (HSucc.has(v)) {
// add both representations of edge: u-v and v-u
// they share the same keydict
var keydictCopy = (0, _internals.clone)(keydict);
HNbrs.set(v, keydictCopy);
HPred.get(v).set(u, keydictCopy);
}
}
} catch (err) {
_didIteratorError10 = true;
_iteratorError10 = err;
} finally {
try {
if (!_iteratorNormalCompletion10 && _iterator10['return']) {
_iterator10['return']();
}
} finally {
if (_didIteratorError10) {
throw _iteratorError10;
}
}
}
}
} catch (err) {
_didIteratorError9 = true;
_iteratorError9 = err;
} finally {
try {
if (!_iteratorNormalCompletion9 && _iterator9['return']) {
_iterator9['return']();
}
} finally {
if (_didIteratorError9) {
throw _iteratorError9;
}
}
}
H.graph = this.graph;
return H;
}
}, {
key: 'reverse',
/**
* Return the reverse of the graph.
*
* The reverse is a graph with the same nodes and edges but with the
* directions of the edges reversed.
*
* @param {boolean=} optCopy If true, return a new MultiDiGraph holding the
* reversed edges. If false, the reverse graph is created using the original
* graph (this changes the original graph).
* @return {?MultiDiGraph}
*/
value: function reverse() {
var optCopy = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0];
var H;
if (optCopy) {
H = new this.constructor(null, { name: (0, _internals.sprintf)('Reverse of (%s)', this.name) });
H.addNodesFrom(this);
H.addEdgesFrom((0, _internals.mapIterator)(this.edges(true, true), function (_ref) {
var _ref2 = _slicedToArray(_ref, 4);
var u = _ref2[0];
var v = _ref2[1];
var key = _ref2[2];
var data = _ref2[3];
return (0, _internals.tuple4)(v, u, key, (0, _internals.deepcopy)(data));
}));
H.graph = (0, _internals.deepcopy)(this.graph);
H.node = (0, _internals.deepcopy)(this.node);
} else {
var _ref3 = [this.succ, this.pred];
this.pred = _ref3[0];
this.succ = _ref3[1];
this.adj = this.succ;
H = this;
}
return H;
}
}], [{
key: '__name__',
/**
* Holds the graph type (class) name for information.
*
* @type {string}
*/
get: function get() {
return 'MultiDiGraph';
}
}]);
return MultiDiGraph;
})(_DiGraph3['default']);
exports['default'] = MultiDiGraph;
// Simulate multiple inheritance by merging prototypes
_Object$getOwnPropertyNames(_MultiGraph2['default'].prototype).forEach(function (prop) {
if (!MultiDiGraph.prototype.hasOwnProperty(prop)) {
MultiDiGraph.prototype[prop] = _MultiGraph2['default'].prototype[prop];
}
});
function yieldEdges(nodesNbrs, data, keys, type) {
var _iteratorNormalCompletion11, _didIteratorError11, _iteratorError11, _iterator11, _step11, _step11$value, n, nbrs, _iteratorNormalCompletion12, _didIteratorError12, _iteratorError12, _iterator12, _step12, _step12$value, nbr, keydict, key, result;
return _regeneratorRuntime.wrap(function yieldEdges$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
_iteratorNormalCompletion11 = true;
_didIteratorError11 = false;
_iteratorError11 = undefined;
context$1$0.prev = 3;
_iterator11 = _getIterator(nodesNbrs);
case 5:
if (_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done) {
context$1$0.next = 48;
break;
}
_step11$value = _slicedToArray(_step11.value, 2);
n = _step11$value[0];
nbrs = _step11$value[1];
_iteratorNormalCompletion12 = true;
_didIteratorError12 = false;
_iteratorError12 = undefined;
context$1$0.prev = 12;
_iterator12 = _getIterator(nbrs);
case 14:
if (_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done) {
context$1$0.next = 31;
break;
}
_step12$value = _slicedToArray(_step12.value, 2);
nbr = _step12$value[0];
keydict = _step12$value[1];
context$1$0.t0 = _regeneratorRuntime.keys(keydict);
case 19:
if ((context$1$0.t1 = context$1$0.t0()).done) {
context$1$0.next = 28;
break;
}
key = context$1$0.t1.value;
result = type === 'out' ? [n, nbr] : [nbr, n];
if (keys) {
result[2] = isNaN(key) ? key : +key;
}
if (data) {
result.push(keydict[key]);
}
context$1$0.next = 26;
return result;
case 26:
context$1$0.next = 19;
break;
case 28:
_iteratorNormalCompletion12 = true;
context$1$0.next = 14;
break;
case 31:
context$1$0.next = 37;
break;
case 33:
context$1$0.prev = 33;
context$1$0.t2 = context$1$0['catch'](12);
_didIteratorError12 = true;
_iteratorError12 = context$1$0.t2;
case 37:
context$1$0.prev = 37;
context$1$0.prev = 38;
if (!_iteratorNormalCompletion12 && _iterator12['return']) {
_iterator12['return']();
}
case 40:
context$1$0.prev = 40;
if (!_didIteratorError12) {
context$1$0.next = 43;
break;
}
throw _iteratorError12;
case 43:
return context$1$0.finish(40);
case 44:
return context$1$0.finish(37);
case 45:
_iteratorNormalCompletion11 = true;
context$1$0.next = 5;
break;
case 48:
context$1$0.next = 54;
break;
case 50:
context$1$0.prev = 50;
context$1$0.t3 = context$1$0['catch'](3);
_didIteratorError11 = true;
_iteratorError11 = context$1$0.t3;
case 54:
context$1$0.prev = 54;
context$1$0.prev = 55;
if (!_iteratorNormalCompletion11 && _iterator11['return']) {
_iterator11['return']();
}
case 57:
context$1$0.prev = 57;
if (!_didIteratorError11) {
context$1$0.next = 60;
break;
}
throw _iteratorError11;
case 60:
return context$1$0.finish(57);
case 61:
return context$1$0.finish(54);
case 62:
case 'end':
return context$1$0.stop();
}
}, marked0$0[0], this, [[3, 50, 54, 62], [12, 33, 37, 45], [38,, 40, 44], [55,, 57, 61]]);
}
function sumEdgeAttribute(nbrs, attribute, def) {
var sum = 0;
var _iteratorNormalCompletion13 = true;
var _didIteratorError13 = false;
var _iteratorError13 = undefined;
try {
for (var _iterator13 = _getIterator(nbrs.values()), _step13; !(_iteratorNormalCompletion13 = (_step13 = _iterator13.next()).done); _iteratorNormalCompletion13 = true) {
var keydict = _step13.value;
for (var key in keydict) {
sum += (0, _internals.getDefault)(keydict[key][attribute], def);
}
}
} catch (err) {
_didIteratorError13 = true;
_iteratorError13 = err;
} finally {
try {
if (!_iteratorNormalCompletion13 && _iterator13['return']) {
_iterator13['return']();
}
} finally {
if (_didIteratorError13) {
throw _iteratorError13;
}
}
}
return sum;
}
function yieldDegree(graph, edges, nBunch, weight) {
var nodesNbrs, _iteratorNormalCompletion14, _didIteratorError14, _iteratorError14, _iterator14, _step14, _step14$value, n, nbrs, sum, _iteratorNormalCompletion15, _didIteratorError15, _iteratorError15, _iterator15, _step15, keydict, _iteratorNormalCompletion16, _didIteratorError16, _iteratorError16, _iterator16, _step16, _step16$value;
return _regeneratorRuntime.wrap(function yieldDegree$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
nodesNbrs = nBunch == null ? edges : (0, _internals.mapIterator)(graph.nbunchIter(nBunch), function (n) {
return (0, _internals.tuple2)(n, edges.get(n));
});
if (!(weight == null)) {
context$1$0.next = 52;
break;
}
_iteratorNormalCompletion14 = true;
_didIteratorError14 = false;
_iteratorError14 = undefined;
context$1$0.prev = 5;
_iterator14 = _getIterator(nodesNbrs);
case 7:
if (_iteratorNormalCompletion14 = (_step14 = _iterator14.next()).done) {
context$1$0.next = 36;
break;
}
_step14$value = _slicedToArray(_step14.value, 2);
n = _step14$value[0];
nbrs = _step14$value[1];
sum = 0;
_iteratorNormalCompletion15 = true;
_didIteratorError15 = false;
_iteratorError15 = undefined;
context$1$0.prev = 15;
for (_iterator15 = _getIterator(nbrs.values()); !(_iteratorNormalCompletion15 = (_step15 = _iterator15.next()).done); _iteratorNormalCompletion15 = true) {
keydict = _step15.value;
sum += _Object$keys(keydict).length;
}
context$1$0.next = 23;
break;
case 19:
context$1$0.prev = 19;
context$1$0.t0 = context$1$0['catch'](15);
_didIteratorError15 = true;
_iteratorError15 = context$1$0.t0;
case 23:
context$1$0.prev = 23;
context$1$0.prev = 24;
if (!_iteratorNormalCompletion15 && _iterator15['return']) {
_iterator15['return']();
}
case 26:
context$1$0.prev = 26;
if (!_didIteratorError15) {
context$1$0.next = 29;
break;
}
throw _iteratorError15;
case 29:
return context$1$0.finish(26);
case 30:
return context$1$0.finish(23);
case 31:
context$1$0.next = 33;
return [n, sum];
case 33:
_iteratorNormalCompletion14 = true;
context$1$0.next = 7;
break;
case 36:
context$1$0.next = 42;
break;
case 38:
context$1$0.prev = 38;
context$1$0.t1 = context$1$0['catch'](5);
_didIteratorError14 = true;
_iteratorError14 = context$1$0.t1;
case 42:
context$1$0.prev = 42;
context$1$0.prev = 43;
if (!_iteratorNormalCompletion14 && _iterator14['return']) {
_iterator14['return']();
}
case 45:
context$1$0.prev = 45;
if (!_didIteratorError14) {
context$1$0.next = 48;
break;
}
throw _iteratorError14;
case 48:
return context$1$0.finish(45);
case 49:
return context$1$0.finish(42);
case 50:
context$1$0.next = 80;
break;
case 52:
_iteratorNormalCompletion16 = true;
_didIteratorError16 = false;
_iteratorError16 = undefined;
context$1$0.prev = 55;
_iterator16 = _getIterator(nodesNbrs);
case 57:
if (_iteratorNormalCompletion16 = (_step16 = _iterator16.next()).done) {
context$1$0.next = 66;
break;
}
_step16$value = _slicedToArray(_step16.value, 2);
n = _step16$value[0];
nbrs = _step16$value[1];
context$1$0.next = 63;
return [n, sumEdgeAttribute(nbrs, weight, 1)];
case 63:
_iteratorNormalCompletion16 = true;
context$1$0.next = 57;
break;
case 66:
context$1$0.next = 72;
break;
case 68:
context$1$0.prev = 68;
context$1$0.t2 = context$1$0['catch'](55);
_didIteratorError16 = true;
_iteratorError16 = context$1$0.t2;
case 72:
context$1$0.prev = 72;
context$1$0.prev = 73;
if (!_iteratorNormalCompletion16 && _iterator16['return']) {
_iterator16['return']();
}
case 75:
context$1$0.prev = 75;
if (!_didIteratorError16) {
context$1$0.next = 78;
break;
}
throw _iteratorError16;
case 78:
return context$1$0.finish(75);
case 79:
return context$1$0.finish(72);
case 80:
case 'end':
return context$1$0.stop();
}
}, marked0$0[1], this, [[5, 38, 42, 50], [15, 19, 23, 31], [24,, 26, 30], [43,, 45, 49], [55, 68, 72, 80], [73,, 75, 79]]);
}
module.exports = exports['default'];
/* eslint-disable no-unused-vars */
/* eslint-enable no-unused-vars */
/* eslint-disable no-unused-vars */
/* eslint-enable no-unused-vars */
;