UNPKG

jsnetworkx

Version:

A graph processing and visualization library for JavaScript (port of NetworkX for Python).

289 lines (255 loc) 8.63 kB
'use strict'; var _slicedToArray = require('babel-runtime/helpers/sliced-to-array')['default']; var _Array$from = require('babel-runtime/core-js/array/from')['default']; var _getIterator = require('babel-runtime/core-js/get-iterator')['default']; var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; Object.defineProperty(exports, '__esModule', { value: true }); exports.toMapOfLists = toMapOfLists; exports.fromMapOfLists = fromMapOfLists; exports.toMapOfMaps = toMapOfMaps; exports.fromMapOfMaps = fromMapOfMaps; var _prepCreateUsing = require('./prepCreateUsing'); var _prepCreateUsing2 = _interopRequireDefault(_prepCreateUsing); var _internals = require('../_internals'); /** * This module provides functions to convert JSNetworkX graphs to and from * non-NetworkX formats. */ /** * Return adjacency representation of graph as a map of lists. * * Completely ignores edge data for `MultiGraph` and `MultiDiGraph`. * * @param {Graph} G A graph * @param {Iterable=} optNodelist Use only nods specified in this list. * * @return {!Map} */ function toMapOfLists(G, optNodelist) { var map = new _internals.Map(); if (optNodelist != null) { _Array$from(optNodelist).forEach(function (n) { return map.set(n, G.neighbors(n).filter(function (v) { return optNodelist.indexOf(v) > -1; })); }); } else { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = _getIterator(G), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var n = _step.value; map.set(n, G.neighbors(n)); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator['return']) { _iterator['return'](); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } return map; } /** * Return a graph from a map of lists. * * * @param {!Map} map A map of lists adjacency representation. * @param {Graph=} optCreateUsing Use specified graph for result. * Otherwise a new graph is created. * * @return {!Graph} */ function fromMapOfLists(map, optCreateUsing) { var G = (0, _prepCreateUsing2['default'])(optCreateUsing); G.addNodesFrom(map.keys()); if (G.isMultigraph() && !G.isDirected()) { // a map_of_lists can't show multiedges. BUT for undirected graphs, // each edge shows up twice in the map_of_lists. // So we need to treat this case separately. var seen = new _internals.Set(); map.forEach(function (nbrlist, node) { nbrlist.forEach(function (nbr) { if (!seen.has(nbr)) { G.addEdge(node, nbr); } }); seen.add(node); // don't allow reverse edge to show up }); } else { map.forEach(function (nbrlist, node) { nbrlist.forEach(function (nbr) { return G.addEdge(node, nbr); }); }); } return G; } /** * Return adjacency representation of graph as a map of maps. * * @param {Graph} G A jsnx Graph * @param {Iterable=} optNodelist Use only nodes specified in nodelist * @param {Object=} optEdgeData If provided, the value of the map will be * set to edgeData for all edges. This is useful to make * an adjacency matrix type representation with 1 as the edge data. * If optEdgeData is null or undefined, the edge data in G is used to * fill the values. * If G is a multigraph, the edge data is a dict for each pair (u,v). * * @return {!Map} */ function toMapOfMaps(G, optNodelist, optEdgeData) { var mapOfMaps = new _internals.Map(); if (optNodelist != null) { optNodelist = _Array$from(optNodelist); optNodelist.forEach(function (u) { var mapOfU = mapOfMaps.set(u, new _internals.Map()); G.get(u).forEach(function (v, data) { if (optNodelist.indexOf(v) > -1) { mapOfU.set(v, optEdgeData == null ? data : optEdgeData); } }); }); } else { // nodelist is undefined var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { var _loop = function () { var _step2$value = _slicedToArray(_step2.value, 2); var nbrmap = _step2$value[0]; var u = _step2$value[1]; /*eslint no-loop-func:0*/ var mapOfU = mapOfMaps.set(u, new _internals.Map()); nbrmap.forEach(function (data, v) { mapOfU.set(v, optEdgeData == null ? data : optEdgeData); }); }; for (var _iterator2 = _getIterator(G.adjacencyIter()), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { _loop(); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2['return']) { _iterator2['return'](); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } return mapOfMaps; } /** * Return a graph from a map of maps. * * @param {!Map} map A map of maps adjacency representation. * @param {Graph=} optCreateUsing Use specified graph for result. * Otherwise a new graph is created. * @param {boolean=} optMultigraphInput (default=False) * When True, the values of the inner dict are assumed * to be containers of edge data for multiple edges. * Otherwise this routine assumes the edge data are singletons. * * @return {Graph} */ function fromMapOfMaps(map, optCreateUsing, optMultigraphInput) { var G = (0, _prepCreateUsing2['default'])(optCreateUsing); var seen = new _internals.Set(); // don't add both directions of undirected graph G.addNodesFrom(map.keys()); // is map a MultiGraph or MultiDiGraph? if (optMultigraphInput) { // make a copy of the list of edge data (but not the edge data) if (G.isDirected()) { map.forEach(function (nbrs, u) { if ((0, _internals.isArrayLike)(nbrs)) { // throw expection of not map (object) throw new TypeError('Value is not a map.'); } nbrs.forEach(function (datadict, v) { for (var key in datadict) { var data = datadict[key]; if (G.isMultigraph()) { G.addEdge(u, v, key, data); } else { G.addEdge(u, v, data); } } }); }); } else { // undirected var isMultigraph = G.isMultigraph(); map.forEach(function (nbrs, u) { if ((0, _internals.isArrayLike)(nbrs)) { // throw exception of not map throw new TypeError('Not a map'); } nbrs.forEach(function (datadict, v) { // this works because sets convert the value to their string // representation if (!seen.has((0, _internals.tuple2)(u, v))) { for (var key in datadict) { var data = datadict[key]; if (isMultigraph) { G.addEdge(u, v, key, data); } else { G.addEdge(u, v, data); } } seen.add((0, _internals.tuple2)(v, u)); } }); }); } } else { // not a multigraph to multigraph transfer if (G.isMultigraph() && !G.isDirected()) { // map can have both representations u-v, v-u in dict. Only add one. // We don't need this check for digraphs since we add both directions, // or for Graph() since it is done implicitly (parallel edges not allowed) map.forEach(function (nbrs, u) { if ((0, _internals.isArrayLike)(nbrs)) { // throw exception of not dict (object) throw new TypeError('Value is not a map'); } nbrs.forEach(function (data, v) { if (!seen.has((0, _internals.tuple2)(u, v))) { G.addEdge(u, v, data); seen.add((0, _internals.tuple2)(v, u)); } }); }); } else { map.forEach(function (nbrs, u) { if ((0, _internals.isArrayLike)(nbrs)) { // throw exception of not dict (object) throw new TypeError('Value is not a map'); } nbrs.forEach(function (data, v) { G.addEdge(u, v, data); }); }); } } return G; } /*jshint ignore:start*/ /*jshint ignore:end*/