UNPKG

jsnetworkx

Version:

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

166 lines (141 loc) 5.18 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 _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; Object.defineProperty(exports, '__esModule', { value: true }); exports.havelHakimiGraph = havelHakimiGraph; exports.genHavelHakimiGraph = genHavelHakimiGraph; var _internalsDelegate = require('../_internals/delegate'); var _internalsDelegate2 = _interopRequireDefault(_internalsDelegate); var _exceptionsJSNetworkXError = require('../exceptions/JSNetworkXError'); var _exceptionsJSNetworkXError2 = _interopRequireDefault(_exceptionsJSNetworkXError); var _algorithmsGraphical = require('../algorithms/graphical'); var _classic = require('./classic'); var _internalsSprintf = require('../_internals/sprintf'); var _internalsSprintf2 = _interopRequireDefault(_internalsSprintf); 'use strict'; // TODO: configuration_model // TODO: directed_configuration_model // TODO: expected_degree_graph /** * Return a simple graph with given degree sequence constructed * using the Havel-Hakimi algorithm. * * ### Notes * * The Havel-Hakimi algorithm constructs a simple graph by * successively connecting the node of highest degree to other nodes * of highest degree, resorting remaining nodes by degree, and * repeating the process. The resulting graph has a high * degree-associativity. Nodes are labeled `1,.., degreeSequence.length`, * corresponding to their position in `degreeSequence`. * * The basic algorithm is from Hakimi (1) and was generalized by * Kleitman and Wang (2). * * ### References * * [1] Hakimi S., * On Realizability of a Set of Integers as Degrees of the * Vertices of a linear Graph. I, * Journal of SIAM, 10(3), pp. 496-506 (1962) * [2] Kleitman D.J. and Wang D.L. * Algorithms for Constructing Graphs and Digraphs with Given Valences and * Factors, * Discrete Mathematics, 6(1), pp. 79-88 (1973) * * @param {Iterable} degreeSequence list of integers * Each integer corresponds to the degree of a node (need not be sorted). * @param {Graph} optCreateUsing * Return graph of this type. The instance will be cleared. * Directed graphs are not allowed. * @return {Graph} */ function havelHakimiGraph(degreeSequence, optCreateUsing) { degreeSequence = _Array$from(degreeSequence); if (!(0, _algorithmsGraphical.isValidDegreeSequence)(degreeSequence)) { throw new _exceptionsJSNetworkXError2['default']('Invalid degree sequence'); } if (optCreateUsing != null) { if (optCreateUsing.isDirected()) { throw new _exceptionsJSNetworkXError2['default']('Directed Graph not supported'); } } var numberOfNodes = degreeSequence.length; var G = (0, _classic.emptyGraph)(numberOfNodes, optCreateUsing); var numDegrees = new Array(numberOfNodes); for (var i = 0; i < numberOfNodes; i++) { numDegrees[i] = []; } var maxDegree = 0; var degreeSum = 0; var n = 0; for (i = 0; i < numberOfNodes; i++) { var degree = degreeSequence[i]; // process only the non-zero integers if (degree > 0) { numDegrees[degree].push(n); maxDegree = Math.max(maxDegree, degree); degreeSum += degree; n += 1; } } // Return graph if no edges if (n === 0) { return G; } // form list of [stubs,name] for each node. var modstubs = new Array(maxDegree + 1); for (i = 0; i < maxDegree + 1; i++) { modstubs[i] = [0, 0]; } // Successively reduce degree sequence by removing the maximum degree while (n > 0) { // Retrieve the maximum degree in the sequence while (numDegrees[maxDegree].length === 0) { maxDegree -= 1; } // If there are not enough stubs to connect to, then the sequence is not // graphical if (maxDegree > n - 1) { throw new _exceptionsJSNetworkXError2['default']('Non-graphical integer sequence'); } // Remove largest stub in list var source = numDegrees[maxDegree].pop(); n -= 1; // Reduce the next maxDegree largest stubs var mslen = 0; var k = maxDegree; for (i = 0; i < maxDegree; i++) { while (numDegrees[k].length === 0) { k -= 1; } var target = numDegrees[k].pop(); G.addEdge(source, target); n -= 1; if (k > 1) { modstubs[mslen] = [k - 1, target]; mslen += 1; } } // Add back to the list any nonzero stubs that were removed for (i = 0; i < mslen; i++) { var _modstubs$i = _slicedToArray(modstubs[i], 2); var stubval = _modstubs$i[0]; var stubtarget = _modstubs$i[1]; numDegrees[stubval].push(stubtarget); n += 1; } } G.name = (0, _internalsSprintf2['default'])('havelHakimiGraph %s nodes %d edges', G.order(), G.size()); return G; } // TODO: directed_havel_hakimi_graph // TODO: degree_sequence_tree // TODO: random_degree_sequence_graph // TODO: DegreeSequenceRandomGraph function genHavelHakimiGraph(degreeSequence, optCreateUsing) { return (0, _internalsDelegate2['default'])('havelHakimiGraph', [degreeSequence, optCreateUsing]); }