UNPKG

react-sigma-conglei

Version:

Lightweight but powerful library for drawing network graphs built on top of dunnock/react-sigma

724 lines (672 loc) 22 kB
var Sigma = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // identity function for calling harmony imports with the correct context /******/ __webpack_require__.i = function(value) { return value; }; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 132); /******/ }) /************************************************************************/ /******/ ({ /***/ 132: /***/ (function(module, exports) { /*** IMPORTS FROM imports-loader ***/ (function() { ;(function(undefined) { 'use strict'; if (typeof sigma === 'undefined') throw new Error('sigma is not declared'); sigma.utils.pkg('sigma.plugins'); sigma.plugins.generators = {}; // collection of generators function isNumber(value) { // source: is.js // NaN is number :) return value === value && Object.prototype.toString.call(value) === '[object Number]'; }; function isObject(value) { // source: is.js return typeof value === 'object' && !!value; }; /** * Generates a random graph. * * @param {object} options * @param {number} options.nbNodes The number of nodes. * @param {number} options.nbEdges The number of edges. * @return {object} A graph object that can be read by sigma.classes.graph */ sigma.plugins.generators.random = function(options) { if (!options) throw new Error('Missing argument: options'); if (!isObject(options)) throw new TypeError('Invalid argument: options is not an object, was ' + options); if (!isNumber(options.nbNodes) || options.nbNodes < 1) throw new TypeError('Invalid argument: options.nbNodes is not a positive number, was ' + options.nbNodes); if (!isNumber(options.nbEdges) || options.nbEdges < 1) throw new TypeError('Invalid argument: options.nbEdges is not a number, was ' + options.nbEdges); var i, N = options.nbNodes, E = options.nbEdges, g = { nodes: [], edges: [] }; // Generate a random graph: for (i = 0; i < N; i++) g.nodes.push({ id: 'n' + i, label: 'Node ' + i, x: Math.random(), y: Math.random(), size: 1 }); for (i = 0; i < E; i++) g.edges.push({ id: 'e' + i, label: 'Edge ' + i, source: 'n' + (Math.random() * N | 0), target: 'n' + (Math.random() * N | 0) }); return g; }; /** * Generates a simple balanced tree. * Source: https://github.com/gka/randomgraph.js (license: public domain) * * @param {object} options * @param {number} options.nbChildren The number of children each node has. * @param {number} options.height The height of the tree. * @return {object} A graph object that can be read by sigma.classes.graph */ sigma.plugins.generators.balancedTree = function(options) { if (!options) throw new Error('Missing argument: options'); if (!isObject(options)) throw new TypeError('Invalid argument: options is not an object, was ' + options); if (!isNumber(options.nbChildren) || options.nbChildren < 1) throw new TypeError('Invalid argument: options.nbChildren is not a positive number, was ' + options.nbChildren); if (!isNumber(options.height) || options.height < 1) throw new TypeError('Invalid argument: options.height is not a positive number, was ' + options.height); var v = 0, m = 0, R = options.nbChildren, H = options.height, graph = { nodes: [{ id: 'n0', label: 'Node 0', x: Math.random(), y: Math.random(), size: 1, index: 0 }], edges: [] }, newLeaves = [], i, j, height, node, leaves; for (i = 0; i < R; i++) { node = { id: 'n' + (++v), label: 'Node '+ v, x: Math.random(), y: Math.random(), size: 1, index: (v - 1) }; graph.nodes.push(node); newLeaves.push(node); graph.edges.push({ id: 'e' + (m++), label: 'Edge ' + m, source: 'n0', target: 'n' + v }); } for (height = 1; height < H; height++) { leaves = newLeaves; newLeaves = []; for (j = 0; j < leaves.length; j++) { for (i = 0; i < R; i++) { node = { id: 'n' + (++v), label: 'Node '+ v, x: Math.random(), y: Math.random(), size: 1, index: (v - 1) }; newLeaves.push(node); graph.nodes.push(node); graph.edges.push({ id: 'e' + (m++), label: 'Edge ' + m, source: 'n' + leaves[j].index, target: 'n' + v }); } } } return graph; }; /** * Generates an Erdős–Rényi graph. Call it with options (n,p) or (n,m). * Source: https://github.com/gka/randomgraph.js (license: public domain) * * @param {object} options * @param {number} options.nbNodes The number of nodes. * @param {?number} options.p The probability [0..1] of a edge between any two nodes. * @param {?number} options.nbEdges The number of edges. * @return {object} A graph object that can be read by sigma.classes.graph */ sigma.plugins.generators.erdosRenyi = function(options) { if (!options) throw new Error('Missing argument: options'); if (!isObject(options)) throw new TypeError('Invalid argument: options is not an object, was ' + options); if (!isNumber(options.nbNodes) || options.nbNodes < 1) throw new TypeError('Invalid argument: options.nbNodes is not a positive number, was ' + options.nbNodes); if (options.nbNodes < 3) throw new TypeError('Invalid argument: options.nbNodes is smaller than 3, was ' + options.nbNodes); if ('nbEdges' in options && 'p' in options) throw new TypeError('Invalid argument: choose between options.nbEdges and options.p'); var graph = { nodes: [], edges: [] }, edge, i, j, k = 0, N = options.nbNodes, P = options.p; if (options.p >= 0) { if (!isNumber(options.p) || options.p < 0) throw new TypeError('Invalid argument: options.p is not a positive number, was ' + options.p); for (i = 0; i < N; i++) { graph.nodes.push({ id: 'n' + i, label: 'Node '+ i, x: Math.random(), y: Math.random(), size: 1 }); for (j = 0; j < i; j++) { if (Math.random() < P) { graph.edges.push({ id: 'e' + (k++), label: 'Edge ' + k, source: 'n' + i, target: 'n' + j }); } } } } else { if (!isNumber(options.nbEdges) || options.nbEdges < 1) throw new TypeError('Invalid argument: options.nbEdges is not a positive number, was ' + options.nbEdges); var tmpEdges = [], M = options.nbEdges, k; for (i = 0; i < N; i++) { graph.nodes.push({ id: 'n' + i, label: 'Node '+ i, x: Math.random(), y: Math.random(), size: 1 }); for (j = i + 1; j < N; j++) { tmpEdges.push({ source: 'n' + i, target: 'n' + j }); } } // pick m random edges from tmpEdges k = tmpEdges.length - 1; for (i = 0; i < M; i++) { edge = tmpEdges.splice(Math.floor(Math.random() * k), 1)[0]; edge.id = 'e' + i; edge.label = 'Edge ' + i; graph.edges.push(edge); k--; } } return graph; }; /** * Generates a Barabási–Albert graph. * Source: https://github.com/gka/randomgraph.js (license: public domain) * * @param {object} options * @param {number} options.nbNodes The total number of nodes N > 0 * @param {number} options.m0 m0 > 0 && m0 < N * @param {number} options.m M > 0 && M <= m0 * @return {object} A graph object that can be read by sigma.classes.graph */ sigma.plugins.generators.barabasiAlbert = function(options) { if (!options) throw new Error('Missing argument: options'); if (!isObject(options)) throw new TypeError('Invalid argument: options is not an object, was ' + options); if (!isNumber(options.nbNodes) || options.nbNodes < 1) throw new TypeError('Invalid argument: options.nbNodes is not a positive number, was ' + options.nbNodes); if (options.nbNodes < 3) throw new TypeError('Invalid argument: options.nbNodes is smaller than 3, was ' + options.nbNodes); if (!isNumber(options.m0) || options.m0 <= 0) throw new TypeError('Invalid argument: options.m0 is not a positive number, was ' + options.m0); if (!isNumber(options.m) || options.m <= 0) throw new TypeError('Invalid argument: options.m is not a positive number, was ' + options.m); if (options.m0 >= options.nbNode) throw new TypeError('Invalid argument: options.m0 is greater than options.nbNodes, was ' + options.m0); if (options.m > options.m0) throw new TypeError('Invalid argument: options.m is strictly greater than options.m0, was ' + options.m); var graph = { nodes: [], edges: [] }, edge_lut = {}, degrees = [], i, j, edge, sum, s, m, r, p, k = 0, N = options.nbNodes, m0 = options.m0, M = options.m; // creating m0 nodes for (i = 0; i < m0; i++) { graph.nodes.push({ id: 'n' + i, label: 'node '+ i, x: Math.random(), y: Math.random(), size: 1 }); degrees[i] = 0; } // Linking every node with each other (no self-loops) for (i = 0; i < m0; i++) { for (j = i + 1; j < m0; j++) { edge = { id: 'e' + (k++), label: 'Edge ' + k, source: 'n' + i, target: 'n' + j }; edge_lut[edge.source + '-' + edge.target] = edge; graph.edges.push(edge); degrees[i]++; degrees[j]++; } } // Adding N - m0 nodes, each with M edges for (i = m0; i < N; i++) { graph.nodes.push({ id: 'n' + i, label: 'node '+ i, x: Math.random(), y: Math.random(), size: 1 }); degrees[i] = 0; sum = 0; // sum of all nodes degrees for (j = 0; j < i; j++) sum += degrees[j]; s = 0; for (m = 0; m < M; m++) { r = Math.random(); p = 0; for (j = 0; j < i; j++) { if (edge_lut[i + '-' + j] || edge_lut[j + '-' + i]) continue; if (i == 1) p = 1; else { p += degrees[j] / sum + s / (i - m); } if (r <= p) { s += degrees[j] / sum; edge = { id: 'e' + (k++), label: 'Edge ' + k, source: 'n' + i, target: 'n' + j }; edge_lut[edge.source + '-' + edge.target] = edge; graph.edges.push(edge); degrees[i]++; degrees[j]++; break; } } } } return graph; }; /** * Generates a Watts-Strogatz Small World graph. * Call it with options alpha or beta to run the corresponding model. * Source: https://github.com/gka/randomgraph.js (license: public domain) * * @param {object} options * @param {number} options.nbNodes The number of nodes. * @param {number} options.k The mean degree of nodes (even integer). * @param {?number} options.alpha The rewiring probability [0..1]. * @param {?number} options.beta The rewiring probability [0..1]. * @return {object} A graph object that can be read by sigma.classes.graph */ sigma.plugins.generators.wattsStrogatz = function(options) { if (!options) throw new Error('Missing argument: options'); if (!isObject(options)) throw new TypeError('Invalid argument: options is not an object, was ' + options); if (!isNumber(options.nbNodes) || options.nbNodes < 1) throw new TypeError('Invalid argument: options.nbNodes is not a positive number, was ' + options.nbNodes); if (options.nbNodes < 3) throw new TypeError('Invalid argument: options.nbNodes is smaller than 3, was ' + options.nbNodes); if (!isNumber(options.k) || (options.k % 2) != 0) throw new TypeError('Invalid argument: options.k is not an even integer, was ' + options.k); var graph = { nodes: [], edges: [] }, i, j, k = 0, edge, edge_lut = {}, N = options.nbNodes, K = options.k; function calculateRij(i, j) { if (i == j || edge_lut[i + '-' + j]) return 0; var mij = calculatemij(i, j); if (mij >= K) return 1; if (mij === 0) return p; return Math.pow(mij / K, options.alpha) * (1 - p) + p; }; function calculatemij(i, j) { var mij = 0, l; for (l = 0; l < N; l++) { if (l != i && l != j && edge_lut[i + '-' + l] && edge_lut[j + '-' + l]) { mij++; } } return mij; }; if ('alpha' in options) { if (!isNumber(options.alpha) || options.alpha < 0 || options.alpha > 1) throw new TypeError('Invalid argument: options.alpha is not a number between [0,1], was ' + options.alpha); var p = Math.pow(10, -10), ec = 0, ids = [], nk_half = N * K / 2, Rij, sumRij, r, pij; for (i = 0; i < N; i++) { graph.nodes.push({ id: 'n' + i, label: 'Node '+ i, x: Math.random(), y: Math.random(), size: 1 }); // create a latice ring structure edge = { id: 'e' + (k++), label: 'Edge '+ k, source: 'n' + i, target: 'n' + ((i + 1) % N) }; edge_lut[edge.source + '-' + edge.target] = edge; graph.edges.push(edge); ec++; } // Creating N * K / 2 edges while (ec < nk_half) { for (i = 0; i < N; i++) { ids.push(i); } while (ec < nk_half && ids.length > 0) { i = ids.splice(Math.floor(Math.random() * ids.length), 1)[0]; Rij = []; sumRij = 0; for (j = 0; j < N; j++) { Rij[j] = calculateRij(i, j); sumRij += Rij[j]; } r = Math.random(); pij = 0; for (j = 0; j < N; j++) { if (i != j) { pij += Rij[j] / sumRij; if (r <= pij) { edge = { id: 'e' + (k++), label: 'Edge '+ k, source: 'n' + i, target: 'n' + j }; graph.edges.push(edge); ec++; edge_lut[edge.source + '-' + edge.target] = edge; } } } } } } else { // beta if (!isNumber(options.beta) || options.beta < 0 || options.beta > 1) throw new TypeError('Invalid argument: options.beta is not a number between [0,1], was ' + options.beta); var t; K = K>>1; // divide by two for (i = 0; i < N; i++) { graph.nodes.push({ id: 'n' + i, label: 'node '+ i, x: Math.random(), y: Math.random(), size: 1 }); // create a latice ring structure for (j = 1; j <= K; j++) { edge = { id: 'e' + (k++), label: 'Edge '+ k, source: 'n' + i, target: 'n' + ((i + j) % N) }; edge_lut[edge.source + '-' + edge.target] = edge; graph.edges.push(edge); } } // rewiring of edges for (i = 0; i < N; i++) { for (j = 1; j <= K; j++) { // for every pair of nodes if (Math.random() <= options.beta) { do { t = Math.floor(Math.random() * (N - 1)); } while (t == i || edge_lut['n'+ i + '-n' + t]); var j_ = (i + j) % N; edge_lut['n'+ i + '-n' + j_].target = 'n'+ t; // rewire edge_lut['n'+ i + '-n' + t] = edge_lut['n'+ i + '-n' + j_]; delete edge_lut['n'+ i + '-n' + j_]; } } } } return graph; }; /** * Generates a path. * Source: https://github.com/anvaka/ngraph.generators (license: MIT) * * @param {number} length The number of nodes. * @return {object} A graph object that can be read by sigma.classes.graph */ sigma.plugins.generators.path = function(length) { if (!length || length < 0) { throw new TypeError('Invalid argument: "length" is not a positive number, was ' + length); } var graph = { nodes: [{ id: 'n0', label: 'Node 0', x: Math.random(), y: Math.random(), size: 1 }], edges: [] }; for (var i = 1; i < length; ++i) { graph.nodes.push({ id: 'n' + i, label: 'Node ' + i, x: Math.random(), y: Math.random(), size: 1 }); graph.edges.push({ id: 'e' + i, label: 'Edge '+ i, source: 'n' + (i - 1), target: 'n' + i }); } return graph; }; /** * Generates a grid with n rows and m columns. * Source: https://github.com/anvaka/ngraph.generators (license: MIT) * * @param {Number} n The number of rows in the graph. * @param {Number} m The number of columns in the graph. * @return {object} A graph object that can be read by sigma.classes.graph */ sigma.plugins.generators.grid = function(n, m) { if (n < 1) throw new TypeError('Invalid argument: "n" is not a positive integer, was ' + n); if (m < 1) throw new TypeError('Invalid argument: "m" is not a positive integer, was ' + m); var graph = { nodes: [], edges: [] }, i, j, k = 0, nodeids = [], source, target; nodeids.length = n * m; if (n === 1 && m === 1) { graph.nodes.push({ id: 'n0', label: 'Node 0', x: Math.random(), y: Math.random(), size: 1 }); return graph; } for (i = 0; i < n; ++i) { for (j = 0; j < m; ++j) { source = i + j * n; if (!nodeids[source]) { graph.nodes.push({ id: 'n' + source, label: 'Node ' + source, x: Math.random(), y: Math.random(), size: 1 }); nodeids[source] = true; } if (i > 0) { target = i - 1 + j * n; if (!nodeids[target]) { graph.nodes.push({ id: 'n' + target, label: 'Node ' + target, x: Math.random(), y: Math.random(), size: 1 }); nodeids[target] = true; } graph.edges.push({ id: 'e' + (k++), label: 'Edge '+ k, source: 'n' + source, target: 'n' + target }); } if (j > 0) { target = i + (j - 1) * n; if (!nodeids[target]) { graph.nodes.push({ id: 'n' + target, label: 'Node ' + target, x: Math.random(), y: Math.random(), size: 1 }); nodeids[target] = true; } graph.edges.push({ id: 'e' + (k++), label: 'Edge '+ k, source: 'n' + source, target: 'n' + target }); } } } return graph; }; }).call(this); }.call(window)); /***/ }) /******/ });