flow like the river

This commit is contained in:
root 2025-11-07 00:06:12 +01:00
commit 013fe673f3
42435 changed files with 5764238 additions and 0 deletions

2
VISUALIZACION/node_modules/ngraph.graph/.eslintignore generated vendored Executable file
View file

@ -0,0 +1,2 @@
dist
demo/dist

18
VISUALIZACION/node_modules/ngraph.graph/.eslintrc.json generated vendored Executable file
View file

@ -0,0 +1,18 @@
{
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"env": {
"browser": true,
"node": true,
"es6": true
},
"rules": {
"semi": "error",
"no-undef": "error",
"no-unused-vars": "error",
"no-shadow": "error"
}
}

View file

@ -0,0 +1,26 @@
name: Node.js CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x, 14.x, 15.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run build --if-present
- run: npm test

39
VISUALIZACION/node_modules/ngraph.graph/CHANGELOG.md generated vendored Executable file
View file

@ -0,0 +1,39 @@
# v20.0.0
The changelog is introduced. Justification for it is that there is a breaking change
in the library, and I wanted to call it out here.
### getLink(fromId, toId) / getLinks(nodeId)
`graph.getLinks(nodeId)` now returns a `Set` object. Previous version of the method
returned an `Array`.
Pre `v20.0.0` library versions, `getLink(fromId, toId)` operation had `O(deg(fromId))` time performance.
In `v20.0.0` the links are manged via sets, driving the `getLink()` performance down to `O(1)`.
#### How to update?
If your library used `graph.getLinks(fromId).length` constructs, you'll need to change that to
`graph.getLinks(fromId).size`
### addLink(fromId, toId, data)
For non-multigraphs, this method will now act similar to `addNode(nodeId, data)`. If link is
already present in the graph it will replace old `link.data` with new `data`. Otherwise a new link will be created.
Prior versions of the library always create a new link and clients were required to check link
presence to avoid duplicates.
```
// this code is no longer necessary:
if (graph.hasLink(fromId, toId) || graph.hasLink(toId, fromId)) {
graph.addLink(fromId, toId, 42);
}
// In version v20.0.0 it is equivalent to:
graph.addLink(fromId, toId, 42);
```
For multigraphs this method will act the same way as before - a new link will always be created.

27
VISUALIZACION/node_modules/ngraph.graph/LICENSE generated vendored Executable file
View file

@ -0,0 +1,27 @@
Copyright (c) 2013 - 2022, Andrei Kashcha
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of the Andrei Kashcha nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

198
VISUALIZACION/node_modules/ngraph.graph/README.md generated vendored Executable file
View file

@ -0,0 +1,198 @@
ngraph.graph
============
[Graph](http://en.wikipedia.org/wiki/Graph_\(mathematics\)) data structure for
javascript. This library belongs to a family of javascript graph packages called [ngraph](https://github.com/anvaka/ngraph).
[![build status](https://github.com/anvaka/ngraph.graph/actions/workflows/tests.yaml/badge.svg)](https://github.com/anvaka/ngraph.graph/actions/workflows/tests.yaml)
Install
=======
With [npm](http://npmjs.org) do:
```
npm install ngraph.graph
```
Or download from CDN:
``` html
<script src='https://unpkg.com/ngraph.graph@20.0.1/dist/ngraph.graph.min.js'></script>
```
If you download from CDN the library will be available under `createGraph` global name.
## Creating a graph
Create a graph with no edges and no nodes:
``` js
var createGraph = require('ngraph.graph');
var g = createGraph();
```
## Growing a graph
The graph `g` can be grown in two ways. You can add one node at a time:
``` js
g.addNode('hello');
g.addNode('world');
```
Now graph `g` contains two nodes: `hello` and `world`. You can also use `addLink()`
method to grow a graph. Calling this method with nodes which are not present in
the graph creates them:
``` js
g.addLink('space', 'bar'); // now graph 'g' has two new nodes: 'space' and 'bar'
```
If nodes already present in the graph 'addLink()' makes them connected:
``` js
// Only a link between 'hello' and 'world' is created. No new nodes.
g.addLink('hello', 'world');
```
### What to use as nodes and edges?
The most common and convenient choices are numbers and strings. You can
associate arbitrary data with node via optional second argument of `addNode()`
method:
``` js
// Node 'world' is associated with a string object 'custom data'
g.addNode('world', 'custom data');
// You can associate arbitrary objects with node:
g.addNode('server', {
status: 'on',
ip: '127.0.0.1'
});
// to get data back use `data` property of node:
var server = g.getNode('server');
console.log(server.data); // prints associated object
```
You can also associate arbitrary object with a link using third optional
argument of `addLink()` method:
``` js
// A link between nodes '1' and '2' is now associated with object 'x'
g.addLink(1, 2, x);
```
### Enumerating nodes and links
After you created a graph one of the most common things to do is to enumerate
its nodes/links to perform an operation.
``` js
g.forEachNode(function(node){
console.log(node.id, node.data);
});
```
The function takes callback which accepts current node. Node object may contain
internal information. `node.id` and `node.data` represent parameters passed to
the `g.addNode(id, data)` method and they are guaranteed to be present in future
versions of the library.
To enumerate all links in the graph use `forEachLink()` method:
``` js
g.forEachLink(function(link) {
console.dir(link);
});
```
To enumerate all links for a specific node use `forEachLinkedNode()` method:
``` js
g.forEachLinkedNode('hello', function(linkedNode, link){
console.log("Connected node: ", linkedNode.id, linkedNode.data);
console.dir(link); // link object itself
});
```
This method always enumerates both inbound and outbound links. If you want to
get only outbound links, pass third optional argument:
``` js
g.forEachLinkedNode('hello',
function(linkedNode, link) { /* ... */ },
true // enumerate only outbound links
);
```
To get a particular node object use `getNode()` method. E.g.:
``` js
var world = g.getNode('world'); // returns 'world' node
console.log(world.id, world.data);
```
To get a particular link object use `getLink()` method:
``` js
var helloWorldLink = g.getLink('hello', 'world'); // returns a link from 'hello' to 'world'
console.log(helloWorldLink);
```
To remove a node or a link from a graph use `removeNode()` or `removeLink()`
correspondingly:
``` js
g.removeNode('space');
// Removing link is a bit harder, since method requires actual link object:
g.forEachLinkedNode('hello', function(linkedNode, link){
g.removeLink(link);
});
```
You can also remove all nodes and links by calling
``` js
g.clear();
```
## Listening to Events
Whenever someone changes your graph you can listen to notifications:
``` js
g.on('changed', function(changes) {
console.dir(changes); // prints array of change records
});
g.add(42); // this will trigger 'changed event'
```
Each change record holds information:
```
ChangeRecord = {
changeType: add|remove|update - describes type of this change
node: - only present when this record reflects a node change, represents actual node
link: - only present when this record reflects a link change, represents actual link
}
```
Sometimes it is desirable to react only on bulk changes. ngraph.graph supports
this via `beginUpdate()`/`endUpdate()` methods:
``` js
g.beginUpdate();
for(var i = 0; i < 100; ++i) {
g.addLink(i, i + 1); // no events are triggered here
}
g.endUpdate(); // this triggers all listeners of 'changed' event
```
If you want to stop listen to events use `off()` method:
``` js
g.off('changed', yourHandler); // no longer interested in changes from graph
```
For more information about events, please follow to [ngraph.events](https://github.com/anvaka/ngraph.events)
License
=======
BSD 3-clause

674
VISUALIZACION/node_modules/ngraph.graph/dist/ngraph.graph.js generated vendored Executable file
View file

@ -0,0 +1,674 @@
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.createGraph = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
/**
* @fileOverview Contains definition of the core graph object.
*/
// TODO: need to change storage layer:
// 1. Be able to get all nodes O(1)
// 2. Be able to get number of links O(1)
/**
* @example
* var graph = require('ngraph.graph')();
* graph.addNode(1); // graph has one node.
* graph.addLink(2, 3); // now graph contains three nodes and one link.
*
*/
module.exports = createGraph;
var eventify = require('ngraph.events');
/**
* Creates a new graph
*/
function createGraph(options) {
// Graph structure is maintained as dictionary of nodes
// and array of links. Each node has 'links' property which
// hold all links related to that node. And general links
// array is used to speed up all links enumeration. This is inefficient
// in terms of memory, but simplifies coding.
options = options || {};
if ('uniqueLinkId' in options) {
console.warn(
'ngraph.graph: Starting from version 0.14 `uniqueLinkId` is deprecated.\n' +
'Use `multigraph` option instead\n',
'\n',
'Note: there is also change in default behavior: From now on each graph\n'+
'is considered to be not a multigraph by default (each edge is unique).'
);
options.multigraph = options.uniqueLinkId;
}
// Dear reader, the non-multigraphs do not guarantee that there is only
// one link for a given pair of node. When this option is set to false
// we can save some memory and CPU (18% faster for non-multigraph);
if (options.multigraph === undefined) options.multigraph = false;
if (typeof Map !== 'function') {
// TODO: Should we polyfill it ourselves? We don't use much operations there..
throw new Error('ngraph.graph requires `Map` to be defined. Please polyfill it before using ngraph');
}
var nodes = new Map(); // nodeId => Node
var links = new Map(); // linkId => Link
// Hash of multi-edges. Used to track ids of edges between same nodes
var multiEdges = {};
var suspendEvents = 0;
var createLink = options.multigraph ? createUniqueLink : createSingleLink,
// Our graph API provides means to listen to graph changes. Users can subscribe
// to be notified about changes in the graph by using `on` method. However
// in some cases they don't use it. To avoid unnecessary memory consumption
// we will not record graph changes until we have at least one subscriber.
// Code below supports this optimization.
//
// Accumulates all changes made during graph updates.
// Each change element contains:
// changeType - one of the strings: 'add', 'remove' or 'update';
// node - if change is related to node this property is set to changed graph's node;
// link - if change is related to link this property is set to changed graph's link;
changes = [],
recordLinkChange = noop,
recordNodeChange = noop,
enterModification = noop,
exitModification = noop;
// this is our public API:
var graphPart = {
/**
* Sometimes duck typing could be slow. Giving clients a hint about data structure
* via explicit version number here:
*/
version: 20.0,
/**
* Adds node to the graph. If node with given id already exists in the graph
* its data is extended with whatever comes in 'data' argument.
*
* @param nodeId the node's identifier. A string or number is preferred.
* @param [data] additional data for the node being added. If node already
* exists its data object is augmented with the new one.
*
* @return {node} The newly added node or node with given id if it already exists.
*/
addNode: addNode,
/**
* Adds a link to the graph. The function always create a new
* link between two nodes. If one of the nodes does not exists
* a new node is created.
*
* @param fromId link start node id;
* @param toId link end node id;
* @param [data] additional data to be set on the new link;
*
* @return {link} The newly created link
*/
addLink: addLink,
/**
* Removes link from the graph. If link does not exist does nothing.
*
* @param link - object returned by addLink() or getLinks() methods.
*
* @returns true if link was removed; false otherwise.
*/
removeLink: removeLink,
/**
* Removes node with given id from the graph. If node does not exist in the graph
* does nothing.
*
* @param nodeId node's identifier passed to addNode() function.
*
* @returns true if node was removed; false otherwise.
*/
removeNode: removeNode,
/**
* Gets node with given identifier. If node does not exist undefined value is returned.
*
* @param nodeId requested node identifier;
*
* @return {node} in with requested identifier or undefined if no such node exists.
*/
getNode: getNode,
/**
* Gets number of nodes in this graph.
*
* @return number of nodes in the graph.
*/
getNodeCount: getNodeCount,
/**
* Gets total number of links in the graph.
*/
getLinkCount: getLinkCount,
/**
* Gets total number of links in the graph.
*/
getEdgeCount: getLinkCount,
/**
* Synonym for `getLinkCount()`
*/
getLinksCount: getLinkCount,
/**
* Synonym for `getNodeCount()`
*/
getNodesCount: getNodeCount,
/**
* Gets all links (inbound and outbound) from the node with given id.
* If node with given id is not found null is returned.
*
* @param nodeId requested node identifier.
*
* @return Set of links from and to requested node if such node exists;
* otherwise null is returned.
*/
getLinks: getLinks,
/**
* Invokes callback on each node of the graph.
*
* @param {Function(node)} callback Function to be invoked. The function
* is passed one argument: visited node.
*/
forEachNode: forEachNode,
/**
* Invokes callback on every linked (adjacent) node to the given one.
*
* @param nodeId Identifier of the requested node.
* @param {Function(node, link)} callback Function to be called on all linked nodes.
* The function is passed two parameters: adjacent node and link object itself.
* @param oriented if true graph treated as oriented.
*/
forEachLinkedNode: forEachLinkedNode,
/**
* Enumerates all links in the graph
*
* @param {Function(link)} callback Function to be called on all links in the graph.
* The function is passed one parameter: graph's link object.
*
* Link object contains at least the following fields:
* fromId - node id where link starts;
* toId - node id where link ends,
* data - additional data passed to graph.addLink() method.
*/
forEachLink: forEachLink,
/**
* Suspend all notifications about graph changes until
* endUpdate is called.
*/
beginUpdate: enterModification,
/**
* Resumes all notifications about graph changes and fires
* graph 'changed' event in case there are any pending changes.
*/
endUpdate: exitModification,
/**
* Removes all nodes and links from the graph.
*/
clear: clear,
/**
* Detects whether there is a link between two nodes.
* Operation complexity is O(n) where n - number of links of a node.
* NOTE: this function is synonym for getLink()
*
* @returns link if there is one. null otherwise.
*/
hasLink: getLink,
/**
* Detects whether there is a node with given id
*
* Operation complexity is O(1)
* NOTE: this function is synonym for getNode()
*
* @returns node if there is one; Falsy value otherwise.
*/
hasNode: getNode,
/**
* Gets an edge between two nodes.
* Operation complexity is O(n) where n - number of links of a node.
*
* @param {string} fromId link start identifier
* @param {string} toId link end identifier
*
* @returns link if there is one; undefined otherwise.
*/
getLink: getLink
};
// this will add `on()` and `fire()` methods.
eventify(graphPart);
monitorSubscribers();
return graphPart;
function monitorSubscribers() {
var realOn = graphPart.on;
// replace real `on` with our temporary on, which will trigger change
// modification monitoring:
graphPart.on = on;
function on() {
// now it's time to start tracking stuff:
graphPart.beginUpdate = enterModification = enterModificationReal;
graphPart.endUpdate = exitModification = exitModificationReal;
recordLinkChange = recordLinkChangeReal;
recordNodeChange = recordNodeChangeReal;
// this will replace current `on` method with real pub/sub from `eventify`.
graphPart.on = realOn;
// delegate to real `on` handler:
return realOn.apply(graphPart, arguments);
}
}
function recordLinkChangeReal(link, changeType) {
changes.push({
link: link,
changeType: changeType
});
}
function recordNodeChangeReal(node, changeType) {
changes.push({
node: node,
changeType: changeType
});
}
function addNode(nodeId, data) {
if (nodeId === undefined) {
throw new Error('Invalid node identifier');
}
enterModification();
var node = getNode(nodeId);
if (!node) {
node = new Node(nodeId, data);
recordNodeChange(node, 'add');
} else {
node.data = data;
recordNodeChange(node, 'update');
}
nodes.set(nodeId, node);
exitModification();
return node;
}
function getNode(nodeId) {
return nodes.get(nodeId);
}
function removeNode(nodeId) {
var node = getNode(nodeId);
if (!node) {
return false;
}
enterModification();
var prevLinks = node.links;
if (prevLinks) {
prevLinks.forEach(removeLinkInstance);
node.links = null;
}
nodes.delete(nodeId);
recordNodeChange(node, 'remove');
exitModification();
return true;
}
function addLink(fromId, toId, data) {
enterModification();
var fromNode = getNode(fromId) || addNode(fromId);
var toNode = getNode(toId) || addNode(toId);
var link = createLink(fromId, toId, data);
var isUpdate = links.has(link.id);
links.set(link.id, link);
// TODO: this is not cool. On large graphs potentially would consume more memory.
addLinkToNode(fromNode, link);
if (fromId !== toId) {
// make sure we are not duplicating links for self-loops
addLinkToNode(toNode, link);
}
recordLinkChange(link, isUpdate ? 'update' : 'add');
exitModification();
return link;
}
function createSingleLink(fromId, toId, data) {
var linkId = makeLinkId(fromId, toId);
var prevLink = links.get(linkId);
if (prevLink) {
prevLink.data = data;
return prevLink;
}
return new Link(fromId, toId, data, linkId);
}
function createUniqueLink(fromId, toId, data) {
// TODO: Find a better/faster way to store multigraphs
var linkId = makeLinkId(fromId, toId);
var isMultiEdge = multiEdges.hasOwnProperty(linkId);
if (isMultiEdge || getLink(fromId, toId)) {
if (!isMultiEdge) {
multiEdges[linkId] = 0;
}
var suffix = '@' + (++multiEdges[linkId]);
linkId = makeLinkId(fromId + suffix, toId + suffix);
}
return new Link(fromId, toId, data, linkId);
}
function getNodeCount() {
return nodes.size;
}
function getLinkCount() {
return links.size;
}
function getLinks(nodeId) {
var node = getNode(nodeId);
return node ? node.links : null;
}
function removeLink(link, otherId) {
if (otherId !== undefined) {
link = getLink(link, otherId);
}
return removeLinkInstance(link);
}
function removeLinkInstance(link) {
if (!link) {
return false;
}
if (!links.get(link.id)) return false;
enterModification();
links.delete(link.id);
var fromNode = getNode(link.fromId);
var toNode = getNode(link.toId);
if (fromNode) {
fromNode.links.delete(link);
}
if (toNode) {
toNode.links.delete(link);
}
recordLinkChange(link, 'remove');
exitModification();
return true;
}
function getLink(fromNodeId, toNodeId) {
if (fromNodeId === undefined || toNodeId === undefined) return undefined;
return links.get(makeLinkId(fromNodeId, toNodeId));
}
function clear() {
enterModification();
forEachNode(function(node) {
removeNode(node.id);
});
exitModification();
}
function forEachLink(callback) {
if (typeof callback === 'function') {
var valuesIterator = links.values();
var nextValue = valuesIterator.next();
while (!nextValue.done) {
if (callback(nextValue.value)) {
return true; // client doesn't want to proceed. Return.
}
nextValue = valuesIterator.next();
}
}
}
function forEachLinkedNode(nodeId, callback, oriented) {
var node = getNode(nodeId);
if (node && node.links && typeof callback === 'function') {
if (oriented) {
return forEachOrientedLink(node.links, nodeId, callback);
} else {
return forEachNonOrientedLink(node.links, nodeId, callback);
}
}
}
// eslint-disable-next-line no-shadow
function forEachNonOrientedLink(links, nodeId, callback) {
var quitFast;
var valuesIterator = links.values();
var nextValue = valuesIterator.next();
while (!nextValue.done) {
var link = nextValue.value;
var linkedNodeId = link.fromId === nodeId ? link.toId : link.fromId;
quitFast = callback(nodes.get(linkedNodeId), link);
if (quitFast) {
return true; // Client does not need more iterations. Break now.
}
nextValue = valuesIterator.next();
}
}
// eslint-disable-next-line no-shadow
function forEachOrientedLink(links, nodeId, callback) {
var quitFast;
var valuesIterator = links.values();
var nextValue = valuesIterator.next();
while (!nextValue.done) {
var link = nextValue.value;
if (link.fromId === nodeId) {
quitFast = callback(nodes.get(link.toId), link);
if (quitFast) {
return true; // Client does not need more iterations. Break now.
}
}
nextValue = valuesIterator.next();
}
}
// we will not fire anything until users of this library explicitly call `on()`
// method.
function noop() {}
// Enter, Exit modification allows bulk graph updates without firing events.
function enterModificationReal() {
suspendEvents += 1;
}
function exitModificationReal() {
suspendEvents -= 1;
if (suspendEvents === 0 && changes.length > 0) {
graphPart.fire('changed', changes);
changes.length = 0;
}
}
function forEachNode(callback) {
if (typeof callback !== 'function') {
throw new Error('Function is expected to iterate over graph nodes. You passed ' + callback);
}
var valuesIterator = nodes.values();
var nextValue = valuesIterator.next();
while (!nextValue.done) {
if (callback(nextValue.value)) {
return true; // client doesn't want to proceed. Return.
}
nextValue = valuesIterator.next();
}
}
}
/**
* Internal structure to represent node;
*/
function Node(id, data) {
this.id = id;
this.links = null;
this.data = data;
}
function addLinkToNode(node, link) {
if (node.links) {
node.links.add(link);
} else {
node.links = new Set([link]);
}
}
/**
* Internal structure to represent links;
*/
function Link(fromId, toId, data, id) {
this.fromId = fromId;
this.toId = toId;
this.data = data;
this.id = id;
}
function makeLinkId(fromId, toId) {
return fromId.toString() + '👉 ' + toId.toString();
}
},{"ngraph.events":2}],2:[function(require,module,exports){
module.exports = function eventify(subject) {
validateSubject(subject);
var eventsStorage = createEventsStorage(subject);
subject.on = eventsStorage.on;
subject.off = eventsStorage.off;
subject.fire = eventsStorage.fire;
return subject;
};
function createEventsStorage(subject) {
// Store all event listeners to this hash. Key is event name, value is array
// of callback records.
//
// A callback record consists of callback function and its optional context:
// { 'eventName' => [{callback: function, ctx: object}] }
var registeredEvents = Object.create(null);
return {
on: function (eventName, callback, ctx) {
if (typeof callback !== 'function') {
throw new Error('callback is expected to be a function');
}
var handlers = registeredEvents[eventName];
if (!handlers) {
handlers = registeredEvents[eventName] = [];
}
handlers.push({callback: callback, ctx: ctx});
return subject;
},
off: function (eventName, callback) {
var wantToRemoveAll = (typeof eventName === 'undefined');
if (wantToRemoveAll) {
// Killing old events storage should be enough in this case:
registeredEvents = Object.create(null);
return subject;
}
if (registeredEvents[eventName]) {
var deleteAllCallbacksForEvent = (typeof callback !== 'function');
if (deleteAllCallbacksForEvent) {
delete registeredEvents[eventName];
} else {
var callbacks = registeredEvents[eventName];
for (var i = 0; i < callbacks.length; ++i) {
if (callbacks[i].callback === callback) {
callbacks.splice(i, 1);
}
}
}
}
return subject;
},
fire: function (eventName) {
var callbacks = registeredEvents[eventName];
if (!callbacks) {
return subject;
}
var fireArguments;
if (arguments.length > 1) {
fireArguments = Array.prototype.splice.call(arguments, 1);
}
for(var i = 0; i < callbacks.length; ++i) {
var callbackInfo = callbacks[i];
callbackInfo.callback.apply(callbackInfo.ctx, fireArguments);
}
return subject;
}
};
}
function validateSubject(subject) {
if (!subject) {
throw new Error('Eventify cannot use falsy object as events subject');
}
var reservedWords = ['on', 'fire', 'off'];
for (var i = 0; i < reservedWords.length; ++i) {
if (subject.hasOwnProperty(reservedWords[i])) {
throw new Error("Subject cannot be eventified, since it already has property '" + reservedWords[i] + "'");
}
}
}
},{}]},{},[1])(1)
});

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,49 @@
/**
* This examples shows how to find all connected components of a graph.
*
* Created in response to https://github.com/anvaka/ngraph.graph/issues/18
*/
module.exports = function findConnectedComponents(graph) {
var nodeIdToComponentId = new Map();
var connectedComponents = [];
var lastComponentId = 0;
graph.forEachNode(function(node) {
if (nodeIdToComponentId.has(node.id)) {
// we already seen this cluster. Ignore it.
return;
}
// We found a new connected component:
nodeIdToComponentId.set(node.id, lastComponentId);
var currentComponent = [node.id];
connectedComponents.push(currentComponent);
// Let's find what other nodes belong to this component
dfs(graph, node.id, otherNode => {
let componentId = nodeIdToComponentId.get(otherNode.id);
if (componentId !== undefined && componentId === lastComponentId) {
// this is possible when we have a loop. Just ignore the node.
return false;
} else if (componentId !== undefined) {
throw new Error('Reached a component from another component. DFS is broken?');
}
currentComponent.push(otherNode.id);
nodeIdToComponentId.set(otherNode.id, lastComponentId);
return true; // let's visit neighbors
});
lastComponentId += 1;
});
return connectedComponents;
};
function dfs(graph, startFromNodeId, visitor) {
graph.forEachLinkedNode(startFromNodeId, function(otherNode) {
if (visitor(otherNode)) dfs(graph, otherNode.id, visitor);
});
}

182
VISUALIZACION/node_modules/ngraph.graph/index.d.ts generated vendored Executable file
View file

@ -0,0 +1,182 @@
// Type definitions for ngraph.graph v20.0.0
// Project: https://github.com/anvaka/ngraph.graph
// Definitions by: Nathan Westlake <https://github.com/CorayThan> and Anvaka <https://github.com/anvaka>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/**
* A graph data structure for javascript.
*/
declare module "ngraph.graph" {
import { EventedType } from 'ngraph.events'
export type NodeId = string | number
export type LinkId = string
/**
* A single link (edge) of the graph
*/
export interface Link<Data = any> {
/**
* Unique identifier of this link
*/
id: LinkId,
/**
* Node identifier where this links starts
*/
fromId: NodeId,
/**
* Node identifier where this link points to
*/
toId: NodeId,
/**
* Arbitrary data associated with this link
*/
data: Data
}
/**
* A single node of a graph.
*/
export interface Node<Data = any> {
/**
* Unique identifier of this node
*/
id: NodeId,
/**
* Set of incoming/outgoing links (edges) to/from this node.
*
* For the sake of memory consumption preservation, this property
* is null when this node has no links.
*
* Link instance is referentially equal throughout the API.
*/
links: Set<Link<any>> | null,
/**
* Associated data connected to this node.
*/
data: Data
}
/**
* A graph data structure
*/
export interface Graph<NodeData = any, LinkData = any> {
/**
* Adds a new node to the graph. If node with such id already exists
* its data is overwritten with the new data
*/
addNode: (node: NodeId, data?: NodeData) => Node<NodeData>
/**
* Adds a new link to the graph. If link already exists and the graph
* is not a multigraph, then link's data is overwritten with a new data.
*
* When graph is a multigraph, then a new link is always added between the
* nodes.
*/
addLink: (from: NodeId, to: NodeId, data?: LinkData) => Link<LinkData>
/**
* Removes a link from the graph. You'll need to pass an actual link instance
* to remove it. If you pass two arguments, the function assumes they represent
* from/to node ids, and removes the corresponding link.
*
* Returns true if link is found and removed. False otherwise.
*/
removeLink: (link: Link<LinkData>) => boolean
/**
* Removes node by node id. Returns true if node was removed,
* false otherwise (e.g. no such node exists in the graph)
*/
removeNode: (nodeId: NodeId) => boolean
/**
* Returns a node by its identifier. Undefined value is returned if node
* with such identifer does not exist.
*/
getNode: (nodeId: NodeId) => Node<NodeData> | undefined
/**
* Checks whether given node exists in the graph. Return the node
* or undefined if no such node exist.
*/
hasNode: (nodeId: NodeId) => Node<NodeData> | undefined
/**
* Returns a link between two nodes
*/
getLink: (fromNodeId: NodeId, toNodeId: NodeId) => Link<LinkData> | undefined
/**
* Checks if link is present in the graph
*/
hasLink: (fromNodeId: NodeId, toNodeId: NodeId) => Link<LinkData> | undefined
/**
* Returns number of nodes in the graph
*/
getNodesCount: () => number
/**
* Returns number of nodes in the graph
*/
getNodeCount: () => number
/**
* Returns number of links (edges) in the graph
*/
getLinksCount: () => number
/**
* Returns number of links (edges) in the graph
*/
getLinkCount: () => number
/**
* Returns all links associated with this node
*/
getLinks: (nodeId: NodeId) => Set<Link<LinkData>> | null
/**
* Iterates over every single node in the graph, passing the node to a callback.
*
* If callback function returns "true"-like value, enumeration stops.
**/
forEachNode: (callbackPerNode: (node: Node<NodeData>) => void | undefined | null | boolean) => void
/**
* Iterates over every single link in the graph, passing the link to a callback.
* If callback function returns "true"-like value, enumeration stops.
*/
forEachLink: (callbackPerLink: (link: Link<LinkData>) => void | undefined | boolean) => void
forEachLinkedNode: (nodeId: NodeId, callbackPerNode: (node: Node<NodeData>, link: Link<LinkData>) => void, oriented: boolean) => void
/**
* Suspend all notifications about graph changes until
* endUpdate is called.
*/
beginUpdate: () => void
/**
* Resumes all notifications about graph changes and fires
* graph 'changed' event in case there are any pending changes.
*/
endUpdate: () => void
/**
* Removes all nodes and links from the graph.
*/
clear: () => void
}
/**
* Creates a new instance of a graph.
*/
export default function createGraph<NodeData = any, LinkData = any>(options?: { multigraph: boolean }): Graph<NodeData, LinkData> & EventedType
}

580
VISUALIZACION/node_modules/ngraph.graph/index.js generated vendored Executable file
View file

@ -0,0 +1,580 @@
/**
* @fileOverview Contains definition of the core graph object.
*/
// TODO: need to change storage layer:
// 1. Be able to get all nodes O(1)
// 2. Be able to get number of links O(1)
/**
* @example
* var graph = require('ngraph.graph')();
* graph.addNode(1); // graph has one node.
* graph.addLink(2, 3); // now graph contains three nodes and one link.
*
*/
module.exports = createGraph;
var eventify = require('ngraph.events');
/**
* Creates a new graph
*/
function createGraph(options) {
// Graph structure is maintained as dictionary of nodes
// and array of links. Each node has 'links' property which
// hold all links related to that node. And general links
// array is used to speed up all links enumeration. This is inefficient
// in terms of memory, but simplifies coding.
options = options || {};
if ('uniqueLinkId' in options) {
console.warn(
'ngraph.graph: Starting from version 0.14 `uniqueLinkId` is deprecated.\n' +
'Use `multigraph` option instead\n',
'\n',
'Note: there is also change in default behavior: From now on each graph\n'+
'is considered to be not a multigraph by default (each edge is unique).'
);
options.multigraph = options.uniqueLinkId;
}
// Dear reader, the non-multigraphs do not guarantee that there is only
// one link for a given pair of node. When this option is set to false
// we can save some memory and CPU (18% faster for non-multigraph);
if (options.multigraph === undefined) options.multigraph = false;
if (typeof Map !== 'function') {
// TODO: Should we polyfill it ourselves? We don't use much operations there..
throw new Error('ngraph.graph requires `Map` to be defined. Please polyfill it before using ngraph');
}
var nodes = new Map(); // nodeId => Node
var links = new Map(); // linkId => Link
// Hash of multi-edges. Used to track ids of edges between same nodes
var multiEdges = {};
var suspendEvents = 0;
var createLink = options.multigraph ? createUniqueLink : createSingleLink,
// Our graph API provides means to listen to graph changes. Users can subscribe
// to be notified about changes in the graph by using `on` method. However
// in some cases they don't use it. To avoid unnecessary memory consumption
// we will not record graph changes until we have at least one subscriber.
// Code below supports this optimization.
//
// Accumulates all changes made during graph updates.
// Each change element contains:
// changeType - one of the strings: 'add', 'remove' or 'update';
// node - if change is related to node this property is set to changed graph's node;
// link - if change is related to link this property is set to changed graph's link;
changes = [],
recordLinkChange = noop,
recordNodeChange = noop,
enterModification = noop,
exitModification = noop;
// this is our public API:
var graphPart = {
/**
* Sometimes duck typing could be slow. Giving clients a hint about data structure
* via explicit version number here:
*/
version: 20.0,
/**
* Adds node to the graph. If node with given id already exists in the graph
* its data is extended with whatever comes in 'data' argument.
*
* @param nodeId the node's identifier. A string or number is preferred.
* @param [data] additional data for the node being added. If node already
* exists its data object is augmented with the new one.
*
* @return {node} The newly added node or node with given id if it already exists.
*/
addNode: addNode,
/**
* Adds a link to the graph. The function always create a new
* link between two nodes. If one of the nodes does not exists
* a new node is created.
*
* @param fromId link start node id;
* @param toId link end node id;
* @param [data] additional data to be set on the new link;
*
* @return {link} The newly created link
*/
addLink: addLink,
/**
* Removes link from the graph. If link does not exist does nothing.
*
* @param link - object returned by addLink() or getLinks() methods.
*
* @returns true if link was removed; false otherwise.
*/
removeLink: removeLink,
/**
* Removes node with given id from the graph. If node does not exist in the graph
* does nothing.
*
* @param nodeId node's identifier passed to addNode() function.
*
* @returns true if node was removed; false otherwise.
*/
removeNode: removeNode,
/**
* Gets node with given identifier. If node does not exist undefined value is returned.
*
* @param nodeId requested node identifier;
*
* @return {node} in with requested identifier or undefined if no such node exists.
*/
getNode: getNode,
/**
* Gets number of nodes in this graph.
*
* @return number of nodes in the graph.
*/
getNodeCount: getNodeCount,
/**
* Gets total number of links in the graph.
*/
getLinkCount: getLinkCount,
/**
* Gets total number of links in the graph.
*/
getEdgeCount: getLinkCount,
/**
* Synonym for `getLinkCount()`
*/
getLinksCount: getLinkCount,
/**
* Synonym for `getNodeCount()`
*/
getNodesCount: getNodeCount,
/**
* Gets all links (inbound and outbound) from the node with given id.
* If node with given id is not found null is returned.
*
* @param nodeId requested node identifier.
*
* @return Set of links from and to requested node if such node exists;
* otherwise null is returned.
*/
getLinks: getLinks,
/**
* Invokes callback on each node of the graph.
*
* @param {Function(node)} callback Function to be invoked. The function
* is passed one argument: visited node.
*/
forEachNode: forEachNode,
/**
* Invokes callback on every linked (adjacent) node to the given one.
*
* @param nodeId Identifier of the requested node.
* @param {Function(node, link)} callback Function to be called on all linked nodes.
* The function is passed two parameters: adjacent node and link object itself.
* @param oriented if true graph treated as oriented.
*/
forEachLinkedNode: forEachLinkedNode,
/**
* Enumerates all links in the graph
*
* @param {Function(link)} callback Function to be called on all links in the graph.
* The function is passed one parameter: graph's link object.
*
* Link object contains at least the following fields:
* fromId - node id where link starts;
* toId - node id where link ends,
* data - additional data passed to graph.addLink() method.
*/
forEachLink: forEachLink,
/**
* Suspend all notifications about graph changes until
* endUpdate is called.
*/
beginUpdate: enterModification,
/**
* Resumes all notifications about graph changes and fires
* graph 'changed' event in case there are any pending changes.
*/
endUpdate: exitModification,
/**
* Removes all nodes and links from the graph.
*/
clear: clear,
/**
* Detects whether there is a link between two nodes.
* Operation complexity is O(n) where n - number of links of a node.
* NOTE: this function is synonym for getLink()
*
* @returns link if there is one. null otherwise.
*/
hasLink: getLink,
/**
* Detects whether there is a node with given id
*
* Operation complexity is O(1)
* NOTE: this function is synonym for getNode()
*
* @returns node if there is one; Falsy value otherwise.
*/
hasNode: getNode,
/**
* Gets an edge between two nodes.
* Operation complexity is O(n) where n - number of links of a node.
*
* @param {string} fromId link start identifier
* @param {string} toId link end identifier
*
* @returns link if there is one; undefined otherwise.
*/
getLink: getLink
};
// this will add `on()` and `fire()` methods.
eventify(graphPart);
monitorSubscribers();
return graphPart;
function monitorSubscribers() {
var realOn = graphPart.on;
// replace real `on` with our temporary on, which will trigger change
// modification monitoring:
graphPart.on = on;
function on() {
// now it's time to start tracking stuff:
graphPart.beginUpdate = enterModification = enterModificationReal;
graphPart.endUpdate = exitModification = exitModificationReal;
recordLinkChange = recordLinkChangeReal;
recordNodeChange = recordNodeChangeReal;
// this will replace current `on` method with real pub/sub from `eventify`.
graphPart.on = realOn;
// delegate to real `on` handler:
return realOn.apply(graphPart, arguments);
}
}
function recordLinkChangeReal(link, changeType) {
changes.push({
link: link,
changeType: changeType
});
}
function recordNodeChangeReal(node, changeType) {
changes.push({
node: node,
changeType: changeType
});
}
function addNode(nodeId, data) {
if (nodeId === undefined) {
throw new Error('Invalid node identifier');
}
enterModification();
var node = getNode(nodeId);
if (!node) {
node = new Node(nodeId, data);
recordNodeChange(node, 'add');
} else {
node.data = data;
recordNodeChange(node, 'update');
}
nodes.set(nodeId, node);
exitModification();
return node;
}
function getNode(nodeId) {
return nodes.get(nodeId);
}
function removeNode(nodeId) {
var node = getNode(nodeId);
if (!node) {
return false;
}
enterModification();
var prevLinks = node.links;
if (prevLinks) {
prevLinks.forEach(removeLinkInstance);
node.links = null;
}
nodes.delete(nodeId);
recordNodeChange(node, 'remove');
exitModification();
return true;
}
function addLink(fromId, toId, data) {
enterModification();
var fromNode = getNode(fromId) || addNode(fromId);
var toNode = getNode(toId) || addNode(toId);
var link = createLink(fromId, toId, data);
var isUpdate = links.has(link.id);
links.set(link.id, link);
// TODO: this is not cool. On large graphs potentially would consume more memory.
addLinkToNode(fromNode, link);
if (fromId !== toId) {
// make sure we are not duplicating links for self-loops
addLinkToNode(toNode, link);
}
recordLinkChange(link, isUpdate ? 'update' : 'add');
exitModification();
return link;
}
function createSingleLink(fromId, toId, data) {
var linkId = makeLinkId(fromId, toId);
var prevLink = links.get(linkId);
if (prevLink) {
prevLink.data = data;
return prevLink;
}
return new Link(fromId, toId, data, linkId);
}
function createUniqueLink(fromId, toId, data) {
// TODO: Find a better/faster way to store multigraphs
var linkId = makeLinkId(fromId, toId);
var isMultiEdge = multiEdges.hasOwnProperty(linkId);
if (isMultiEdge || getLink(fromId, toId)) {
if (!isMultiEdge) {
multiEdges[linkId] = 0;
}
var suffix = '@' + (++multiEdges[linkId]);
linkId = makeLinkId(fromId + suffix, toId + suffix);
}
return new Link(fromId, toId, data, linkId);
}
function getNodeCount() {
return nodes.size;
}
function getLinkCount() {
return links.size;
}
function getLinks(nodeId) {
var node = getNode(nodeId);
return node ? node.links : null;
}
function removeLink(link, otherId) {
if (otherId !== undefined) {
link = getLink(link, otherId);
}
return removeLinkInstance(link);
}
function removeLinkInstance(link) {
if (!link) {
return false;
}
if (!links.get(link.id)) return false;
enterModification();
links.delete(link.id);
var fromNode = getNode(link.fromId);
var toNode = getNode(link.toId);
if (fromNode) {
fromNode.links.delete(link);
}
if (toNode) {
toNode.links.delete(link);
}
recordLinkChange(link, 'remove');
exitModification();
return true;
}
function getLink(fromNodeId, toNodeId) {
if (fromNodeId === undefined || toNodeId === undefined) return undefined;
return links.get(makeLinkId(fromNodeId, toNodeId));
}
function clear() {
enterModification();
forEachNode(function(node) {
removeNode(node.id);
});
exitModification();
}
function forEachLink(callback) {
if (typeof callback === 'function') {
var valuesIterator = links.values();
var nextValue = valuesIterator.next();
while (!nextValue.done) {
if (callback(nextValue.value)) {
return true; // client doesn't want to proceed. Return.
}
nextValue = valuesIterator.next();
}
}
}
function forEachLinkedNode(nodeId, callback, oriented) {
var node = getNode(nodeId);
if (node && node.links && typeof callback === 'function') {
if (oriented) {
return forEachOrientedLink(node.links, nodeId, callback);
} else {
return forEachNonOrientedLink(node.links, nodeId, callback);
}
}
}
// eslint-disable-next-line no-shadow
function forEachNonOrientedLink(links, nodeId, callback) {
var quitFast;
var valuesIterator = links.values();
var nextValue = valuesIterator.next();
while (!nextValue.done) {
var link = nextValue.value;
var linkedNodeId = link.fromId === nodeId ? link.toId : link.fromId;
quitFast = callback(nodes.get(linkedNodeId), link);
if (quitFast) {
return true; // Client does not need more iterations. Break now.
}
nextValue = valuesIterator.next();
}
}
// eslint-disable-next-line no-shadow
function forEachOrientedLink(links, nodeId, callback) {
var quitFast;
var valuesIterator = links.values();
var nextValue = valuesIterator.next();
while (!nextValue.done) {
var link = nextValue.value;
if (link.fromId === nodeId) {
quitFast = callback(nodes.get(link.toId), link);
if (quitFast) {
return true; // Client does not need more iterations. Break now.
}
}
nextValue = valuesIterator.next();
}
}
// we will not fire anything until users of this library explicitly call `on()`
// method.
function noop() {}
// Enter, Exit modification allows bulk graph updates without firing events.
function enterModificationReal() {
suspendEvents += 1;
}
function exitModificationReal() {
suspendEvents -= 1;
if (suspendEvents === 0 && changes.length > 0) {
graphPart.fire('changed', changes);
changes.length = 0;
}
}
function forEachNode(callback) {
if (typeof callback !== 'function') {
throw new Error('Function is expected to iterate over graph nodes. You passed ' + callback);
}
var valuesIterator = nodes.values();
var nextValue = valuesIterator.next();
while (!nextValue.done) {
if (callback(nextValue.value)) {
return true; // client doesn't want to proceed. Return.
}
nextValue = valuesIterator.next();
}
}
}
/**
* Internal structure to represent node;
*/
function Node(id, data) {
this.id = id;
this.links = null;
this.data = data;
}
function addLinkToNode(node, link) {
if (node.links) {
node.links.add(link);
} else {
node.links = new Set([link]);
}
}
/**
* Internal structure to represent links;
*/
function Link(fromId, toId, data, id) {
this.fromId = fromId;
this.toId = toId;
this.data = data;
this.id = id;
}
function makeLinkId(fromId, toId) {
return fromId.toString() + '👉 ' + toId.toString();
}

45
VISUALIZACION/node_modules/ngraph.graph/package.json generated vendored Executable file
View file

@ -0,0 +1,45 @@
{
"name": "ngraph.graph",
"version": "20.0.1",
"description": "graph data structure",
"main": "index.js",
"jsdelivr": "dist/ngraph.graph.min.js",
"unpkg": "dist/ngraph.graph.min.js",
"scripts": {
"build": "browserify index.js -s createGraph -o dist/ngraph.graph.js && uglifyjs dist/ngraph.graph.js -o dist/ngraph.graph.min.js",
"test": "tap --branches=90 --lines=90 --statements=90 --functions=90 test/*.js",
"cover": "tap --branches=80 --lines=80 --statements=80 --functions=80 --coverage-report=html --no-browser test/*.js"
},
"repository": {
"type": "git",
"url": "https://github.com/anvaka/ngraph.graph.git"
},
"keywords": [
"graph",
"graph theory",
"edge",
"vertex",
"node",
"network",
"connection",
"ngraph",
"vivagraph",
"ngraphjs"
],
"author": "Andrei Kashcha",
"license": "BSD-3-Clause",
"bugs": {
"url": "https://github.com/anvaka/ngraph.graph/issues"
},
"devDependencies": {
"benchmark": "^2.1.4",
"browserify": "^17.0.0",
"eslint": "^7.25.0",
"ngraph.random": "^1.1.0",
"tap": "^16.0.1",
"uglify-js": "^3.13.5"
},
"dependencies": {
"ngraph.events": "^1.2.1"
}
}

View file

@ -0,0 +1,53 @@
var createGraph = require('../');
var randomAPI = require('ngraph.random').random;
var Benchmark = require('benchmark');
var suite = new Benchmark.Suite;
var edgeIterationSumWeight = 0;
var edgeIterationMultigraph = 0;
suite.add('Edge iteration', function() {
var graph = createGraph();
var random = randomAPI(42);
var maxEdgeId = 10000000;
for(var i = 1; i < 1000; ++i) {
var fromId = random.next(maxEdgeId);
var toId = random.next(maxEdgeId);
graph.addLink(fromId, toId, i);
}
edgeIterationSumWeight = 0;
for (var i = 0; i < 100; ++i) {
graph.forEachLink(addUpWeight);
}
function addUpWeight(link) {
edgeIterationSumWeight += link.data;
}
});
suite.add('Edge iteration for multigraph', function() {
var graph = createGraph({multigraph: true});
var random = randomAPI(42);
var maxEdgeId = 10000000;
for(var i = 1; i < 1000; ++i) {
var fromId = random.next(maxEdgeId);
var toId = random.next(maxEdgeId);
graph.addLink(fromId, toId, i);
}
edgeIterationMultigraph = 0;
for (var i = 0; i < 100; ++i) {
graph.forEachLink(addUpWeight);
}
function addUpWeight(link) {
edgeIterationMultigraph += link.data;
}
});
suite.on('cycle', function(event) {
console.log(String(event.target));
console.log('edge iteration sum weight', edgeIterationSumWeight);
console.log('edge iteration multigraph weight', edgeIterationMultigraph);
})
// run async
.run({ 'async': true });

View file

@ -0,0 +1,120 @@
var createGraph = require('../');
var randomAPI = require('ngraph.random').random;
var Benchmark = require('benchmark');
var suite = new Benchmark.Suite;
suite.add('Adding 5,000 edges', function() {
var graph = createGraph();
for(var i = 1; i < 5000; ++i) {
graph.addLink(i, i - 1, i);
}
});
suite.add('Adding 5,000 multigraph edges', function() {
var graph = createGraph({multigraph: true});
for(var i = 1; i < 5000; ++i) {
graph.addLink(i, i - 1, i);
}
});
suite.add('Adding 5,000 random edges', function() {
var graph = createGraph();
var random = randomAPI(42);
var maxEdgeId = 10000000;
for(var i = 1; i < 5000; ++i) {
var fromId = random.next(maxEdgeId);
var toId = random.next(maxEdgeId);
graph.addLink(fromId, toId, i);
}
});
suite.add('Adding 5,000 random edges to multigraph', function() {
var graph = createGraph({multigraph: true});
var random = randomAPI(42);
var maxEdgeId = 10000000;
for(var i = 1; i < 5000; ++i) {
var fromId = random.next(maxEdgeId);
var toId = random.next(maxEdgeId);
graph.addLink(fromId, toId, i);
}
});
suite.add('Adding 5,000 random edges and randomly removing them', function() {
var graph = createGraph();
var random = randomAPI(42);
var maxEdgeId = 10000000;
for(var i = 1; i < 5000; ++i) {
var fromId = random.next(maxEdgeId);
var toId = random.next(maxEdgeId);
graph.addLink(fromId, toId, i);
}
for(var i = 1; i < 15000; ++i) {
var fromId = random.next(maxEdgeId);
var toId = random.next(maxEdgeId);
graph.removeLink(fromId, toId);
}
});
suite.add('Adding 5,000 random edges to multigraph and randomly removing them', function() {
var graph = createGraph({multigraph: true});
var random = randomAPI(42);
var maxEdgeId = 10000000;
for(var i = 1; i < 15000; ++i) {
var fromId = random.next(maxEdgeId);
var toId = random.next(maxEdgeId);
graph.addLink(fromId, toId, i);
}
for(var i = 1; i < 5000; ++i) {
var fromId = random.next(maxEdgeId);
var toId = random.next(maxEdgeId);
graph.removeLink(fromId, toId);
}
});
suite.add('Removing all edges one by one from 5k graph', function() {
var graph = createGraph();
var random = randomAPI(42);
var maxEdgeId = 10000000;
for(var i = 1; i < 5000; ++i) {
var fromId = random.next(maxEdgeId);
var toId = random.next(maxEdgeId);
graph.addLink(fromId, toId, i);
}
var links = [];
graph.forEachLink(function (link) {
links.push(link);
});
for (var i = 0; i < links.length; ++i) {
graph.removeLink(links[i]);
}
});
suite.add('Removing all edges one by one from 5k multigraph graph', function() {
var graph = createGraph({multigraph: true});
var random = randomAPI(42);
var maxEdgeId = 10000000;
for(var i = 1; i < 5000; ++i) {
var fromId = random.next(maxEdgeId);
var toId = random.next(maxEdgeId);
graph.addLink(fromId, toId, i);
}
var links = [];
graph.forEachLink(function (link) {
links.push(link);
});
for (var i = 0; i < links.length; ++i) {
graph.removeLink(links[i]);
}
});
suite.on('cycle', function(event) {
console.log(String(event.target));
})
// run async
.run({ 'async': true });

View file

@ -0,0 +1,31 @@
var Benchmark = require('benchmark');
var createGraph = require('../'),
numberOfNodes = 10000;
var suite = new Benchmark.Suite();
var graph = createGraph();
for (var i = 0; i < numberOfNodes; ++i) {
graph.addNode('hello' + i, i);
}
var sum = 0;
// add tests
suite.add('forEachNode', function() {
var localSum = 0;
graph.forEachNode(function (node) {
localSum += node.data;
});
sum = localSum;
})
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
console.log(sum);
console.log('Fastest is ' + this.filter('fastest').map("name"));
})
// run async
.run({ 'async': true });

20
VISUALIZACION/node_modules/ngraph.graph/perf/snapshot.txt generated vendored Executable file
View file

@ -0,0 +1,20 @@
Node v12.4.0
> node perf/edge-iteration.js
Edge iteration x 626 ops/sec ±1.36% (86 runs sampled)
Edge iteration for multigraph x 568 ops/sec ±0.97% (87 runs sampled)
» node perf/graph-construction.js
Adding 5,000 edges x 580 ops/sec ±1.40% (86 runs sampled)
Adding 5,000 multigraph edges x 432 ops/sec ±1.08% (82 runs sampled)
Adding 5,000 random edges x 219 ops/sec ±0.92% (81 runs sampled)
Adding 5,000 random edges to multigraph x 179 ops/sec ±0.93% (78 runs sampled)
Adding 5,000 random edges and randomly removing them x 7.83 ops/sec ±4.33% (24 runs sampled)
Adding 5,000 random edges to multigraph and randomly removing them x 5.97 ops/sec ±4.07% (20 runs sampled)
Removing all edges one by one from 5k graph x 126 ops/sec ±1.20% (76 runs sampled)
Removing all edges one by one from 5k multigraph graph x 97.78 ops/sec ±4.15% (69 runs sampled)
» node perf/node-iteration.js
graphWithOutMap x 572 ops/sec ±3.64% (71 runs sampled)
graphWithMap x 5,744 ops/sec ±6.48% (69 runs sampled)
Fastest is graphWithMap

385
VISUALIZACION/node_modules/ngraph.graph/test/construction.js generated vendored Executable file
View file

@ -0,0 +1,385 @@
var test = require('tap').test,
createGraph = require('..');
test('add node adds node', function(t) {
var graph = createGraph();
var customData = '31337';
var node = graph.addNode(1, customData);
t.equal(graph.getNodesCount(), 1, 'exactly one node');
t.equal(graph.getLinksCount(), 0, 'no links');
t.equal(graph.getNode(1), node, 'invalid node returned by addNode (or getNode)');
t.equal(node.data, customData, 'data was not set properly');
t.equal(node.id, 1, 'node id was not set properly');
t.end();
});
test('hasNode checks node', function(t) {
var graph = createGraph();
graph.addNode(1);
t.ok(graph.hasNode(1), 'node is there');
t.notOk(graph.hasNode(2), 'should not be here');
t.end();
});
test('hasLink checks links', function (t) {
var graph = createGraph();
graph.addLink(1, 2);
var link12 = graph.hasLink(1, 2);
t.ok(link12.fromId === 1 && link12.toId === 2, 'link is found');
// this is somewhat doubtful... has link will return null, but forEachLinkedNode
// will actually iterate over this link. Not sure how to have consistency here
// for now documenting behavior in the test:
var noLink = graph.hasLink(2, 1);
t.notOk(noLink, 'hasLink is always directional');
var obviousNo = graph.hasLink();
t.notOk(obviousNo, 'No links there');
t.end();
});
test('hasLink is the same as getLink', function (t) {
var graph = createGraph();
t.equal(graph.getLink, graph.hasLink, 'hasLink is synonym for getLink');
t.end();
});
test('it considers uniqueLinkId as multigraph', function (t) {
var options = {uniqueLinkId: true};
createGraph(options);
t.equal(options.multigraph, true, 'multigraph is set');
t.end();
});
test('it throw if no node id is passed', function(t) {
var graph = createGraph();
t.throws(function() {
graph.addNode(); // no id, should throw
}, 'It throws on undefined node');
t.end();
});
test('it fires update event when node is updated', function(t) {
t.plan(3);
var graph = createGraph();
graph.addNode(1, 'hello');
graph.on('changed', checkChangedEvent);
graph.addNode(1, 'world');
t.end();
function checkChangedEvent(changes) {
var change = changes[0];
t.equal(change.node.id, 1);
t.equal(change.node.data, 'world');
t.equal(change.changeType, 'update');
}
});
test('it can add node with id similar to reserved prototype property', function(t) {
var graph = createGraph();
graph.addNode('constructor');
graph.addLink('watch', 'constructor');
var iterated = 0;
graph.forEachNode(function() {
iterated += 1;
});
t.ok(graph.hasLink('watch', 'constructor'));
t.equal(graph.getLinksCount(), 1, 'one link');
t.equal(iterated, 2, 'has two nodes');
t.end();
});
test('add link adds link', function(t) {
var graph = createGraph();
var link = graph.addLink(1, 2),
firstNodeLinks = graph.getLinks(1),
secondNodeLinks = graph.getLinks(2);
t.equal(graph.getNodesCount(), 2, 'Two nodes');
t.equal(graph.getLinksCount(), 1, 'One link');
t.equal(firstNodeLinks.size, 1, 'number of links of the first node is wrong');
t.equal(secondNodeLinks.size, 1, 'number of links of the second node is wrong');
t.equal(link, Array.from(firstNodeLinks)[0], 'invalid link in the first node');
t.equal(link, Array.from(secondNodeLinks)[0], 'invalid link in the second node');
t.end();
});
test('it can add multi-edges', function (t) {
t.plan(5);
var graph = createGraph({multigraph: true});
graph.addLink(1, 2, 'first');
graph.addLink(1, 2, 'second');
graph.addLink(1, 2, 'third');
t.equal(graph.getLinksCount(), 3, 'three links!');
t.equal(graph.getNodesCount(), 2, 'Two nodes');
graph.forEachLinkedNode(1, function (otherNode, link) {
t.ok(link.data === 'first' || link.data === 'second' || link.data === 'third', 'Link is here');
});
t.end();
});
test('it can produce unique link ids', function (t) {
// eslint-disable-next-line no-shadow
t.test('by default links are de-duped', function (t) {
var seen = {};
var graph = createGraph();
graph.addLink(1, 2, 'first');
graph.addLink(1, 2, 'second');
graph.addLink(1, 2, 'third');
graph.forEachLink(verifyLinksAreNotUnique);
var link = graph.getLink(1, 2);
t.equal(seen[link.id], 1, 'Link 1->2 seen 1 time');
t.equal(link.data, 'third', 'Last link wins');
// eslint-disable-next-line no-shadow
function verifyLinksAreNotUnique(link) {
seen[link.id] = (seen[link.id] || 0) + 1;
}
t.end();
});
// eslint-disable-next-line no-shadow
t.test('You can create multigraph', function (t) {
var graph = createGraph({
multigraph: true
});
var seen = {};
graph.addLink(1, 2, 'first');
graph.addLink(1, 2, 'second');
graph.addLink(1, 2, 'third');
graph.forEachLink(verifyLinkIsUnique);
t.equal(graph.getLinksCount(), 3, 'All three links are here');
t.end();
function verifyLinkIsUnique(link) {
t.notOk(seen[link.id], link.id + ' is unique');
seen[link.id] = true;
}
});
t.end();
});
test('add one node fires changed event', function(t) {
t.plan(3);
var graph = createGraph();
var testNodeId = 'hello world';
graph.on('changed', function(changes) {
t.ok(changes && changes.length === 1, "Only one change should be recorded");
t.equal(changes[0].node.id, testNodeId, "Wrong node change notification");
t.equal(changes[0].changeType, 'add', "Add change type expected.");
});
graph.addNode(testNodeId);
t.end();
});
test('add link fires changed event', function(t) {
t.plan(4);
var graph = createGraph();
var fromId = 1,
toId = 2;
graph.on('changed', function(changes) {
t.ok(changes && changes.length === 3, "Three change should be recorded: node, node and link");
t.equal(changes[2].link.fromId, fromId, "Wrong link from Id");
t.equal(changes[2].link.toId, toId, "Wrong link toId");
t.equal(changes[2].changeType, 'add', "Add change type expected.");
});
graph.addLink(fromId, toId);
t.end();
});
test('remove isolated node remove it', function(t) {
var graph = createGraph();
graph.addNode(1);
graph.removeNode(1);
t.equal(graph.getNodesCount(), 0, 'Remove operation failed');
t.end();
});
test('supports plural methods', function(t) {
var graph = createGraph();
graph.addLink(1, 2);
t.equal(graph.getNodeCount(), 2, 'two nodes are there');
t.equal(graph.getLinkCount(), 1, 'two nodes are there');
t.equal(graph.getNodesCount(), 2, 'two nodes are there');
t.equal(graph.getLinksCount(), 1, 'two nodes are there');
t.end();
});
test('remove link removes it', function(t) {
t.plan(5);
var graph = createGraph();
var link = graph.addLink(1, 2);
var linkIsRemoved = graph.removeLink(link);
t.equal(graph.getNodesCount(), 2, 'remove link should not remove nodes');
t.equal(graph.getLinksCount(), 0, 'No Links');
t.equal(graph.getLinks(1).size, 0, 'link should be removed from the first node');
t.equal(graph.getLinks(2).size, 0, 'link should be removed from the second node');
t.ok(linkIsRemoved, 'Link removal is successful');
graph.forEachLink(function() {
test.ok(false, 'No links should be in graph');
});
t.end();
});
test('it can remove link by from/to ids', function(t) {
var graph = createGraph();
graph.addLink(1, 2);
var linkIsRemoved = graph.removeLink(1, 2);
t.equal(graph.getNodesCount(), 2, 'remove link should not remove nodes');
t.equal(graph.getLinksCount(), 0, 'No Links');
t.equal(graph.getLinks(1).size, 0, 'link should be removed from the first node');
t.equal(graph.getLinks(2).size, 0, 'link should be removed from the second node');
t.ok(linkIsRemoved, 'Link removal is successful');
graph.forEachLink(function() {
test.ok(false, 'No links should be in graph');
});
t.end();
});
test('remove link returns false if no link removed', function (t) {
var graph = createGraph();
graph.addLink(1, 2);
var result = graph.removeLink('blah');
t.notOk(result, 'Link is not removed');
var alsoNo = graph.removeLink();
t.notOk(alsoNo, 'No link - no removal');
t.end();
});
test('remove isolated node fires changed event', function(t) {
t.plan(4);
var graph = createGraph();
graph.addNode(1);
graph.on('changed', function(changes) {
t.ok(changes && changes.length === 1, "One change should be recorded: node removed");
t.equal(changes[0].node.id, 1, "Wrong node Id");
t.equal(changes[0].changeType, 'remove', "'remove' change type expected.");
});
var result = graph.removeNode(1);
t.ok(result, 'node is removed');
t.end();
});
test('remove link fires changed event', function(t) {
t.plan(3);
var graph = createGraph();
var link = graph.addLink(1, 2);
graph.on('changed', function(changes) {
t.ok(changes && changes.length === 1, "One change should be recorded: link removed");
t.equal(changes[0].link, link, "Wrong link removed");
t.equal(changes[0].changeType, 'remove', "'remove' change type expected.");
});
graph.removeLink(link);
t.end();
});
test('remove linked node fires changed event', function(t) {
t.plan(5);
var graph = createGraph(),
link = graph.addLink(1, 2),
nodeIdToRemove = 1;
graph.on('changed', function(changes) {
t.ok(changes && changes.length === 2, "Two changes should be recorded: link and node removed");
t.equal(changes[0].link, link, "Wrong link removed");
t.equal(changes[0].changeType, 'remove', "'remove' change type expected.");
t.equal(changes[1].node.id, nodeIdToRemove, "Wrong node removed");
t.equal(changes[1].changeType, 'remove', "'remove' change type expected.");
});
graph.removeNode(nodeIdToRemove);
t.end();
});
test('remove node with many links removes them all', function(t) {
var graph = createGraph();
graph.addLink(1, 2);
graph.addLink(1, 3);
graph.removeNode(1);
t.equal(graph.getNodesCount(), 2, 'remove link should remove one node only');
t.equal(graph.getLinks(1), null, 'link should be removed from the first node');
t.equal(graph.getLinks(2).size, 0, 'link should be removed from the second node');
t.equal(graph.getLinks(3).size, 0, 'link should be removed from the third node');
graph.forEachLink(function() {
test.ok(false, 'No links should be in graph');
});
t.end();
});
test('remove node returns false when no node removed', function (t) {
var graph = createGraph();
graph.addNode('hello');
var result = graph.removeNode('blah');
t.notOk(result, 'No "blah" node');
t.end();
});
test('clearGraph clears graph', function (t) {
var graph = createGraph();
graph.addNode('hello');
graph.addLink(1, 2);
graph.clear();
t.equal(graph.getNodesCount(), 0, 'No nodes');
t.equal(graph.getLinksCount(), 0, 'No links');
t.end();
});
test('beginUpdate holds events', function(t) {
var graph = createGraph();
var changedCount = 0;
graph.on('changed', function () {
changedCount += 1;
});
graph.beginUpdate();
graph.addNode(1);
t.equal(changedCount, 0, 'Begin update freezes updates until `endUpdate()`');
graph.endUpdate();
t.equal(changedCount, 1, 'event is fired only after endUpdate()');
t.end();
});

View file

@ -0,0 +1,25 @@
var test = require('tap').test;
var findConnectedComponents = require('../examples/findConnectedComponents');
var createGraph = require('..');
test('can find connected components', function(t) {
// our graph has three components
var graph = createGraph();
graph.addLink(1, 2);
graph.addLink(2, 3);
graph.addLink(5, 6);
graph.addNode(8);
// let's add loop:
graph.addLink(9, 9);
// lets verify it:
var components = findConnectedComponents(graph);
t.equal(components.length, 4, 'all components found');
t.same(components[0], [1, 2, 3], 'first component found');
t.same(components[1], [5, 6], 'second component found');
t.same(components[2], [8], 'third component found');
t.same(components[3], [9], 'fourth component found');
t.end();
});

158
VISUALIZACION/node_modules/ngraph.graph/test/iteration.js generated vendored Executable file
View file

@ -0,0 +1,158 @@
var test = require('tap').test,
createGraph = require('..');
test('forEachLinkedNode respects orientation', function(t) {
t.plan(3);
var graph = createGraph();
graph.addLink(1, 2);
graph.addLink(2, 3);
var oriented = true;
graph.forEachLinkedNode(2, function(node, link) {
t.ok(link.toId === 3, 'Only 3 is connected to node 2, when traversal is oriented');
}, oriented);
graph.forEachLinkedNode(2, function(node, link) {
t.ok(link.toId === 3 || link.toId === 2, 'both incoming and outgoing links are visited');
}, !oriented);
t.end();
});
test('forEachLinkedNode handles self-loops', function(t) {
t.plan(1);
var graph = createGraph();
graph.addLink(1, 1);
// we should visit exactly one time
graph.forEachLinkedNode(1, function(node, link) {
t.ok(link.fromId === 1 && link.toId === 1, 'Link 1 is visited once');
});
t.end();
});
test('forEachLinkedNode will not crash on invalid node id', function(t) {
t.plan(0);
var graph = createGraph();
graph.addLink(1, 2);
graph.forEachLinkedNode(3, function() {
t.notOk(true, 'This code will never be executed');
});
});
test('forEachLinkedNode can quit fast for oriented graphs', function(t) {
var graph = createGraph();
var oriented = true;
graph.addLink(1, 2);
graph.addLink(1, 3);
var visited = 0;
graph.forEachLinkedNode(1, function() {
t.ok(true, 'Visited first link');
visited += 1;
return true; // We want to stop right now!
}, oriented);
t.equal(visited, 1, 'One link is visited');
t.end();
});
test('forEachLinkedNode can quit fast for non-oriented graphs', function(t) {
var graph = createGraph();
var oriented = false;
graph.addLink(1, 2);
graph.addLink(1, 3);
var visited = 0;
graph.forEachLinkedNode(1, function() {
t.ok(true, 'Visited first link');
visited += 1;
return true; // We want to stop right now!
}, oriented);
t.equal(visited, 1, 'One link is visited');
t.end();
});
test('forEachLinkedNode returns quitFast flag', function(t) {
var graph = createGraph();
graph.addLink(1, 2);
graph.addLink(1, 3);
var fastQuit = graph.forEachLinkedNode(1, function() {
return true; // Stop right now.
});
t.ok(fastQuit, 'Fast quit triggered when callback opted out');
var notSoFast = graph.forEachLinkedNode(1, function() { });
t.notOk(notSoFast, 'Fast quit is not triggered when all elements visited');
t.end();
});
test('forEachLink visits each link', function(t) {
t.plan(1);
var graph = createGraph();
graph.addLink(1, 2);
graph.forEachLink(function(link) {
t.ok(link.fromId === 1 && link.toId === 2, 'Link is here');
});
t.end();
});
test('forEachLink will not crash on empty callback', function(t) {
var graph = createGraph();
graph.addLink(1, 2);
graph.forEachLink(); // didn't pass callback, no worries.
t.end();
});
test('forEachNode will stop when requested', function(t) {
t.plan(1);
var graph = createGraph();
graph.addLink(1, 2);
graph.forEachNode(function(node) {
t.equal(node.id, 1, 'We visit only one node');
return true; // we want to stop now!
});
t.end();
});
test('forEachNode returns fastQuit', function(t) {
var graph = createGraph();
graph.addLink(1, 2);
var fastQuit = graph.forEachNode(function(node) {
t.equal(node.id, 1, 'We visit only one node');
return true; // we want to stop now!
}); // no callback? No worries
t.ok(fastQuit, 'fastQuit is set when callback opted out');
var notSoFast = graph.forEachNode(function() { });
t.notOk(notSoFast, 'fastQuit is not set when all nodes visited');
t.end();
});
test('forEachNode throws when callback is not a function', function(t) {
var graph = createGraph();
graph.addLink(1, 2);
t.throws(function() {
graph.forEachNode('not a function');
});
t.end();
});
test('forEachLink stops when requested', function(t) {
var graph = createGraph();
graph.addLink(1, 2);
graph.addLink(2, 3);
var visitCount = 0;
graph.forEachLink(function() {
visitCount += 1;
return true;
});
t.equal(visitCount, 1, 'only one link visited');
t.end();
});