graphology-metrics
Advanced tools
Comparing version 1.18.2 to 2.0.0
@@ -1,20 +0,30 @@ | ||
import Graph from 'graphology-types'; | ||
import Graph, {Attributes} from 'graphology-types'; | ||
import {MinimalEdgeMapper} from 'graphology-utils/getters'; | ||
type BetweennessCentralityMapping = {[key: string]: number}; | ||
type BetweennessCentralityMapping = {[node: string]: number}; | ||
type BetweennessCentralityOptions = { | ||
attributes?: { | ||
centrality?: string; | ||
weight?: string; | ||
}; | ||
type BetweennessCentralityOptions<EdgeAttributes extends Attributes> = { | ||
nodeCentralityAttribute?: string; | ||
getEdgeWeight?: | ||
| keyof EdgeAttributes | ||
| MinimalEdgeMapper<number, EdgeAttributes> | ||
| null; | ||
normalized?: boolean; | ||
weighted?: boolean; | ||
}; | ||
interface IBetweennessCentrality { | ||
( | ||
graph: Graph, | ||
options?: BetweennessCentralityOptions | ||
< | ||
NodeAttributes extends Attributes = Attributes, | ||
EdgeAttributes extends Attributes = Attributes | ||
>( | ||
graph: Graph<NodeAttributes, EdgeAttributes>, | ||
options?: BetweennessCentralityOptions<EdgeAttributes> | ||
): BetweennessCentralityMapping; | ||
assign(graph: Graph, options?: BetweennessCentralityOptions): void; | ||
assign< | ||
NodeAttributes extends Attributes = Attributes, | ||
EdgeAttributes extends Attributes = Attributes | ||
>( | ||
graph: Graph<NodeAttributes, EdgeAttributes>, | ||
options?: BetweennessCentralityOptions<EdgeAttributes> | ||
): void; | ||
} | ||
@@ -21,0 +31,0 @@ |
@@ -18,8 +18,5 @@ /** | ||
var DEFAULTS = { | ||
attributes: { | ||
centrality: 'betweennessCentrality', | ||
weight: 'weight' | ||
}, | ||
normalized: true, | ||
weighted: false | ||
nodeCentralityAttribute: 'betweennessCentrality', | ||
getEdgeWeight: 'weight', | ||
normalized: true | ||
}; | ||
@@ -30,10 +27,8 @@ | ||
* | ||
* @param {boolean} assign - Assign the results to node attributes? | ||
* @param {Graph} graph - Target graph. | ||
* @param {object} [options] - Options: | ||
* @param {object} [attributes] - Attribute names: | ||
* @param {string} [weight] - Name of the weight attribute. | ||
* @param {string} [centrality] - Name of the attribute to assign. | ||
* @param {boolean} [normalized] - Should the centrality be normalized? | ||
* @param {boolean} [weighted] - Weighted graph? | ||
* @param {boolean} assign - Assign the results to node attributes? | ||
* @param {Graph} graph - Target graph. | ||
* @param {object} [options] - Options: | ||
* @param {object} [nodeCentralityAttribute] - Name of the attribute to assign. | ||
* @param {string} [getEdgeWeight] - Name of the weight attribute or getter function. | ||
* @param {boolean} [normalized] - Should the centrality be normalized? | ||
* @param {object} | ||
@@ -50,9 +45,7 @@ */ | ||
var weightAttribute = options.attributes.weight; | ||
var centralityAttribute = options.attributes.centrality; | ||
var outputName = options.nodeCentralityAttribute; | ||
var normalized = options.normalized; | ||
var weighted = options.weighted; | ||
var brandes = weighted | ||
? createDijkstraIndexedBrandes(graph, weightAttribute) | ||
var brandes = options.getEdgeWeight | ||
? createDijkstraIndexedBrandes(graph, options.getEdgeWeight) | ||
: createUnweightedIndexedBrandes(graph); | ||
@@ -103,3 +96,3 @@ | ||
if (assign) return brandes.index.assign(centralityAttribute, centralities); | ||
if (assign) return brandes.index.assign(outputName, centralities); | ||
@@ -106,0 +99,0 @@ return brandes.index.collect(centralities); |
import Graph from 'graphology-types'; | ||
type ClosenessCentralityOptions = { | ||
attributes?: { | ||
centrality?: string; | ||
}; | ||
nodeCentralityAttribute?: string; | ||
wassermanFaust?: boolean; | ||
@@ -8,0 +6,0 @@ }; |
@@ -29,2 +29,3 @@ /** | ||
// TODO: what about self loops? | ||
// TODO: refactor a BFSQueue working on integer ranges in graphology-indices? | ||
@@ -35,5 +36,3 @@ /** | ||
var DEFAULTS = { | ||
attributes: { | ||
centrality: 'closenessCentrality' | ||
}, | ||
nodeCentralityAttribute: 'closenessCentrality', | ||
wassermanFaust: false | ||
@@ -98,4 +97,3 @@ }; | ||
* @param {?object} option - Options: | ||
* @param {?object} attributes - Custom attribute names: | ||
* @param {?string} centrality - Name of the centrality attribute to assign. | ||
* @param {?string} nodeCentralityAttribute - Name of the centrality attribute to assign. | ||
* @param {?boolean} wassermanFaust - Whether to compute the Wasserman & Faust | ||
@@ -142,3 +140,3 @@ * variant of the metric. | ||
if (assign) { | ||
return bfs.index.assign(options.attributes.centrality, mapping); | ||
return bfs.index.assign(options.nodeCentralityAttribute, mapping); | ||
} | ||
@@ -145,0 +143,0 @@ |
import Graph from 'graphology-types'; | ||
type DegreeCentralityOptions = { | ||
attributes?: { | ||
centrality?: string; | ||
}; | ||
nodeCentralityAttribute?: string; | ||
}; | ||
type DegreeCentralityMapping = {[key: string]: number}; | ||
type DegreeCentralityMapping = {[node: string]: number}; | ||
@@ -16,10 +14,6 @@ interface IDegreeCentralityBase { | ||
interface IDegreeCentrality extends IDegreeCentralityBase { | ||
degreeCentrality: IDegreeCentralityBase; | ||
inDegreeCentrality: IDegreeCentralityBase; | ||
outDegreeCentrality: IDegreeCentralityBase; | ||
} | ||
declare const degreeCentrality: IDegreeCentralityBase; | ||
declare const inDegreeCentrality: IDegreeCentralityBase; | ||
declare const outDegreeCentrality: IDegreeCentralityBase; | ||
declare const degreeCentrality: IDegreeCentrality; | ||
export default degreeCentrality; | ||
export {degreeCentrality, inDegreeCentrality, outDegreeCentrality}; |
@@ -19,4 +19,3 @@ /** | ||
* @param {object} [options] - Options: | ||
* @param {object} [attributes] - Custom attribute names: | ||
* @param {string} [centrality] - Name of the attribute to assign. | ||
* @param {string} [nodeCentralityAttribute] - Name of the attribute to assign. | ||
* @return {object|void} | ||
@@ -46,28 +45,26 @@ */ | ||
var attributes = options.attributes || {}; | ||
var centralityAttribute = options.nodeCentralityAttribute || name; | ||
var centralityAttribute = attributes.centrality || name; | ||
var ratio = graph.order - 1; | ||
var getDegree = graph[method].bind(graph); | ||
// Variables | ||
var order = graph.order, | ||
nodes = graph.nodes(), | ||
getDegree = graph[method].bind(graph), | ||
centralities = {}; | ||
if (assign) { | ||
graph.updateEachNodeAttributes( | ||
function (node, attr) { | ||
attr[centralityAttribute] = getDegree(node) / ratio; | ||
return attr; | ||
}, | ||
{attributes: [centralityAttribute]} | ||
); | ||
if (order === 0) return assign ? undefined : centralities; | ||
return; | ||
} | ||
var s = 1 / (order - 1); | ||
var centralities = {}; | ||
// Iteration variables | ||
var node, centrality, i; | ||
graph.forEachNode(function (node) { | ||
centralities[node] = getDegree(node) / ratio; | ||
}); | ||
for (i = 0; i < order; i++) { | ||
node = nodes[i]; | ||
centrality = getDegree(node) * s; | ||
if (assign) graph.setNodeAttribute(node, centralityAttribute, centrality); | ||
else centralities[node] = centrality; | ||
} | ||
return assign ? undefined : centralities; | ||
return centralities; | ||
} | ||
@@ -78,5 +75,9 @@ | ||
*/ | ||
var degreeCentrality = abstractDegreeCentrality.bind(null, false, 'degree'), | ||
inDegreeCentrality = abstractDegreeCentrality.bind(null, false, 'inDegree'), | ||
outDegreeCentrality = abstractDegreeCentrality.bind(null, false, 'outDegree'); | ||
var degreeCentrality = abstractDegreeCentrality.bind(null, false, 'degree'); | ||
var inDegreeCentrality = abstractDegreeCentrality.bind(null, false, 'inDegree'); | ||
var outDegreeCentrality = abstractDegreeCentrality.bind( | ||
null, | ||
false, | ||
'outDegree' | ||
); | ||
@@ -98,5 +99,4 @@ degreeCentrality.assign = abstractDegreeCentrality.bind(null, true, 'degree'); | ||
*/ | ||
degreeCentrality.degreeCentrality = degreeCentrality; | ||
degreeCentrality.inDegreeCentrality = inDegreeCentrality; | ||
degreeCentrality.outDegreeCentrality = outDegreeCentrality; | ||
module.exports = degreeCentrality; | ||
exports.degreeCentrality = degreeCentrality; | ||
exports.inDegreeCentrality = inDegreeCentrality; | ||
exports.outDegreeCentrality = outDegreeCentrality; |
@@ -1,11 +0,14 @@ | ||
import Graph from 'graphology-types'; | ||
import Graph, {Attributes} from 'graphology-types'; | ||
import {MinimalEdgeMapper} from 'graphology-utils/getters'; | ||
type EigenvectorCentralityOptions = { | ||
attributes?: { | ||
centrality?: string; | ||
weight?: string; | ||
}; | ||
type EigenvectorCentralityOptions< | ||
EdgeAttributes extends Attributes = Attributes | ||
> = { | ||
nodeCentralityAttribute?: string; | ||
getEdgeWeight?: | ||
| keyof EdgeAttributes | ||
| MinimalEdgeMapper<number, EdgeAttributes> | ||
| null; | ||
maxIterations?: number; | ||
tolerance?: number; | ||
weighted?: boolean; | ||
}; | ||
@@ -16,7 +19,16 @@ | ||
interface EigenvectorCentrality { | ||
( | ||
graph: Graph, | ||
options?: EigenvectorCentralityOptions | ||
< | ||
NodeAttributes extends Attributes = Attributes, | ||
EdgeAttributes extends Attributes = Attributes | ||
>( | ||
graph: Graph<NodeAttributes, EdgeAttributes>, | ||
options?: EigenvectorCentralityOptions<EdgeAttributes> | ||
): EigenvectorCentralityMapping; | ||
assign(graph: Graph, options?: EigenvectorCentralityOptions): void; | ||
assign< | ||
NodeAttributes extends Attributes = Attributes, | ||
EdgeAttributes extends Attributes = Attributes | ||
>( | ||
graph: Graph<NodeAttributes, EdgeAttributes>, | ||
options?: EigenvectorCentralityOptions<EdgeAttributes> | ||
): void; | ||
} | ||
@@ -23,0 +35,0 @@ |
@@ -27,9 +27,6 @@ /** | ||
var DEFAULTS = { | ||
attributes: { | ||
centrality: 'eigenvectorCentrality', | ||
weight: 'weight' | ||
}, | ||
nodeCentralityAttribute: 'eigenvectorCentrality', | ||
getEdgeWeight: 'weight', | ||
maxIterations: 100, | ||
tolerance: 1e-6, | ||
weighted: false | ||
tolerance: 1e-6 | ||
}; | ||
@@ -64,8 +61,6 @@ | ||
* @param {?object} option - Options: | ||
* @param {?object} attributes - Custom attribute names: | ||
* @param {?string} centrality - Name of the centrality attribute to assign. | ||
* @param {?string} weight - Name of the weight algorithm. | ||
* @param {?number} maxIterations - Maximum number of iterations to perform. | ||
* @param {?number} tolerance - Error tolerance when checking for convergence. | ||
* @param {?boolean} weighted - Should we use the graph's weights. | ||
* @param {?string} nodeCentralityAttribute - Name of the centrality attribute to assign. | ||
* @param {?string} getEdgeWeight - Name of the weight algorithm or getter function. | ||
* @param {?number} maxIterations - Maximum number of iterations to perform. | ||
* @param {?number} tolerance - Error tolerance when checking for convergence. | ||
* @return {object|undefined} | ||
@@ -83,10 +78,6 @@ */ | ||
var tolerance = options.tolerance; | ||
var weighted = options.weighted; | ||
var centralityAttribute = options.attributes.centrality; | ||
var weightAttribute = weighted ? options.attributes.weight : null; | ||
var N = graph.order; | ||
var index = new WeightedNeighborhoodIndex(graph, weightAttribute); | ||
var index = new WeightedNeighborhoodIndex(graph, options.getEdgeWeight); | ||
@@ -149,3 +140,3 @@ var i, j, l, w; | ||
if (assign) { | ||
index.assign(centralityAttribute, x); | ||
index.assign(options.nodeCentralityAttribute, x); | ||
return; | ||
@@ -152,0 +143,0 @@ } |
@@ -1,9 +0,13 @@ | ||
import Graph from 'graphology-types'; | ||
import Graph, {Attributes, EdgeMapper} from 'graphology-types'; | ||
type HITSOptions = { | ||
attributes?: { | ||
authority?: string; | ||
hub?: string; | ||
weight?: string; | ||
}; | ||
type HITSOptions< | ||
NodeAttributes extends Attributes, | ||
EdgeAttributes extends Attributes | ||
> = { | ||
nodeAuthorityAttribute?: string; | ||
nodeHubAttribute?: string; | ||
getEdgeWeight?: | ||
| keyof EdgeAttributes | ||
| EdgeMapper<number, NodeAttributes, EdgeAttributes> | ||
| null; | ||
maxIterations?: number; | ||
@@ -15,3 +19,2 @@ normalize?: boolean; | ||
type HITSResult = { | ||
converged: boolean; | ||
authorities: {[node: string]: number}; | ||
@@ -22,4 +25,16 @@ hubs: {[node: string]: number}; | ||
interface HITS { | ||
(graph: Graph, options?: HITSOptions): HITSResult; | ||
assign(graph: Graph, options?: HITSOptions): void; | ||
< | ||
NodeAttributes extends Attributes = Attributes, | ||
EdgeAttributes extends Attributes = Attributes | ||
>( | ||
graph: Graph<NodeAttributes, EdgeAttributes>, | ||
options?: HITSOptions<NodeAttributes, EdgeAttributes> | ||
): HITSResult; | ||
assign< | ||
NodeAttributes extends Attributes = Attributes, | ||
EdgeAttributes extends Attributes = Attributes | ||
>( | ||
graph: Graph, | ||
options?: HITSOptions<NodeAttributes, EdgeAttributes> | ||
): void; | ||
} | ||
@@ -26,0 +41,0 @@ |
@@ -9,3 +9,7 @@ /** | ||
var isGraph = require('graphology-utils/is-graph'); | ||
var createEdgeWeightGetter = | ||
require('graphology-utils/getters').createEdgeWeightGetter; | ||
// TODO: optimize using NeighborhoodIndex | ||
/** | ||
@@ -15,7 +19,5 @@ * Defaults. | ||
var DEFAULTS = { | ||
attributes: { | ||
authority: 'authority', | ||
hub: 'hub', | ||
weight: 'weight' | ||
}, | ||
nodeAuthorityAttribute: 'authority', | ||
nodeHubAttribute: 'hub', | ||
getEdgeWeight: 'weight', | ||
maxIterations: 100, | ||
@@ -83,22 +85,21 @@ normalize: true, | ||
var getEdgeWeight = createEdgeWeightGetter(options.getEdgeWeight).fromEntry; | ||
// Variables | ||
var order = graph.order, | ||
size = graph.size, | ||
nodes = graph.nodes(), | ||
edges = graph.edges(), | ||
hubs = dict(nodes, 1 / order), | ||
weights = {}, | ||
converged = false, | ||
lastHubs, | ||
authorities; | ||
var order = graph.order; | ||
var nodes = graph.nodes(); | ||
var edges; | ||
var hubs = dict(nodes, 1 / order); | ||
var weights = {}; | ||
var converged = false; | ||
var lastHubs; | ||
var authorities; | ||
// Iteration variables | ||
var node, neighbor, edge, iteration, maxAuthority, maxHub, error, s, i, j, m; | ||
var node, neighbor, edge, iteration, maxAuthority, maxHub, error, S, i, j, m; | ||
// Indexing weights | ||
for (i = 0; i < size; i++) { | ||
edge = edges[i]; | ||
weights[edge] = | ||
graph.getEdgeAttribute(edge, options.attributes.weight) || 1; | ||
} | ||
graph.forEachEdge(function (e, a, s, t, sa, ta, u) { | ||
weights[e] = getEdgeWeight(e, a, s, t, sa, ta, u); | ||
}); | ||
@@ -116,3 +117,3 @@ // Performing iterations | ||
node = nodes[i]; | ||
edges = graph.outEdges(node).concat(graph.undirectedEdges(node)); | ||
edges = graph.outboundEdges(node); | ||
@@ -134,3 +135,3 @@ // Iterating over neighbors | ||
node = nodes[i]; | ||
edges = graph.outEdges(node).concat(graph.undirectedEdges(node)); | ||
edges = graph.outboundEdges(node); | ||
@@ -148,9 +149,9 @@ for (j = 0, m = edges.length; j < m; j++) { | ||
// Normalizing | ||
s = 1 / maxHub; | ||
S = 1 / maxHub; | ||
for (node in hubs) hubs[node] *= s; | ||
for (node in hubs) hubs[node] *= S; | ||
s = 1 / maxAuthority; | ||
S = 1 / maxAuthority; | ||
for (node in authorities) authorities[node] *= s; | ||
for (node in authorities) authorities[node] *= S; | ||
@@ -168,11 +169,14 @@ // Checking convergence | ||
if (!converged) | ||
throw Error('graphology-metrics/centrality/hits: failed to converge.'); | ||
// Should we normalize the result? | ||
if (options.normalize) { | ||
s = 1 / sum(authorities); | ||
S = 1 / sum(authorities); | ||
for (node in authorities) authorities[node] *= s; | ||
for (node in authorities) authorities[node] *= S; | ||
s = 1 / sum(hubs); | ||
S = 1 / sum(hubs); | ||
for (node in hubs) hubs[node] *= s; | ||
for (node in hubs) hubs[node] *= S; | ||
} | ||
@@ -182,14 +186,18 @@ | ||
if (assign) { | ||
for (i = 0; i < order; i++) { | ||
node = nodes[i]; | ||
graph.setNodeAttribute( | ||
node, | ||
options.attributes.authority, | ||
authorities[node] | ||
); | ||
graph.setNodeAttribute(node, options.attributes.hub, hubs[node]); | ||
} | ||
graph.updateEachNodeAttributes( | ||
function (n, attr) { | ||
attr[options.nodeAuthorityAttribute] = authorities[n]; | ||
attr[options.nodeHubAttribute] = hubs[n]; | ||
return attr; | ||
}, | ||
{ | ||
attributes: [options.nodeAuthorityAttribute, options.nodeHubAttribute] | ||
} | ||
); | ||
return; | ||
} | ||
return {converged: converged, hubs: hubs, authorities: authorities}; | ||
return {hubs: hubs, authorities: authorities}; | ||
} | ||
@@ -196,0 +204,0 @@ |
export {default as betweenness} from './betweenness'; | ||
export {default as closeness} from './closeness'; | ||
export {default as degree} from './degree'; | ||
export { | ||
degreeCentrality as degree, | ||
inDegreeCentrality as inDegree, | ||
outDegreeCentrality as outDegree | ||
} from './degree'; | ||
export {default as eigenvector} from './eigenvector'; | ||
export {default as hits} from './hits'; | ||
export {default as pagerank} from './pagerank'; |
@@ -7,7 +7,12 @@ /** | ||
*/ | ||
var degree = require('./degree.js'); | ||
exports.betweenness = require('./betweenness.js'); | ||
exports.closeness = require('./closeness.js'); | ||
exports.degree = require('./degree.js'); | ||
exports.eigenvector = require('./eigenvector.js'); | ||
exports.hits = require('./hits.js'); | ||
exports.pagerank = require('./pagerank.js'); | ||
exports.degree = degree.degreeCentrality; | ||
exports.inDegree = degree.inDegreeCentrality; | ||
exports.outDegree = degree.outDegreeCentrality; |
@@ -1,12 +0,13 @@ | ||
import Graph from 'graphology-types'; | ||
import Graph, {Attributes} from 'graphology-types'; | ||
import {MinimalEdgeMapper} from 'graphology-utils/getters'; | ||
type PagerankOptions = { | ||
attributes?: { | ||
pagerank?: string; | ||
weight?: string; | ||
}; | ||
type PagerankOptions<EdgeAttributes extends Attributes> = { | ||
nodePagerankAttribute?: string; | ||
getEdgeWeight: | ||
| keyof EdgeAttributes | ||
| MinimalEdgeMapper<number, EdgeAttributes> | ||
| null; | ||
alpha?: number; | ||
maxIterations?: number; | ||
tolerance?: number; | ||
weighted?: boolean; | ||
}; | ||
@@ -17,4 +18,16 @@ | ||
interface Pagerank { | ||
(graph: Graph, options?: PagerankOptions): PagerankMapping; | ||
assign(graph: Graph, options?: PagerankOptions): void; | ||
< | ||
NodeAttributes extends Attributes = Attributes, | ||
EdgeAttributes extends Attributes = Attributes | ||
>( | ||
graph: Graph<NodeAttributes, EdgeAttributes>, | ||
options?: PagerankOptions<EdgeAttributes> | ||
): PagerankMapping; | ||
assign< | ||
NodeAttributes extends Attributes = Attributes, | ||
EdgeAttributes extends Attributes = Attributes | ||
>( | ||
graph: Graph<NodeAttributes, EdgeAttributes>, | ||
options?: PagerankOptions<EdgeAttributes> | ||
): void; | ||
} | ||
@@ -21,0 +34,0 @@ |
@@ -20,10 +20,7 @@ /** | ||
var DEFAULTS = { | ||
attributes: { | ||
pagerank: 'pagerank', | ||
weight: 'weight' | ||
}, | ||
nodePagerankAttribute: 'pagerank', | ||
getEdgeWeight: 'weight', | ||
alpha: 0.85, | ||
maxIterations: 100, | ||
tolerance: 1e-6, | ||
weighted: false | ||
tolerance: 1e-6 | ||
}; | ||
@@ -57,6 +54,4 @@ | ||
var tolerance = options.tolerance; | ||
var weighted = options.weighted; | ||
var pagerankAttribute = options.attributes.pagerank; | ||
var weightAttribute = weighted ? options.attributes.weight : null; | ||
var pagerankAttribute = options.nodePagerankAttribute; | ||
@@ -66,3 +61,3 @@ var N = graph.order; | ||
var index = new WeightedNeighborhoodIndex(graph, weightAttribute); | ||
var index = new WeightedNeighborhoodIndex(graph, options.getEdgeWeight); | ||
@@ -69,0 +64,0 @@ var i, j, l, d; |
@@ -1,9 +0,5 @@ | ||
export {default as centrality} from './centrality'; | ||
export {default as density} from './density'; | ||
export {default as diameter} from './diameter'; | ||
export {default as eccentricity} from './eccentricity'; | ||
export {default as extent} from './extent'; | ||
export {default as layoutQuality} from './layout-quality'; | ||
export {default as modularity} from './modularity'; | ||
export {default as weightedDegree} from './weighted-degree'; | ||
export {default as weightedSize} from './weighted-size'; | ||
export * as centrality from './centrality'; | ||
export * as edge from './edge'; | ||
export * as graph from './graph'; | ||
export * as layoutQuality from './layout-quality'; | ||
export * as node from './node'; |
10
index.js
@@ -8,9 +8,5 @@ /** | ||
exports.centrality = require('./centrality'); | ||
exports.density = require('./density.js'); | ||
exports.diameter = require('./diameter.js'); | ||
exports.eccentricity = require('./eccentricity.js'); | ||
exports.extent = require('./extent.js'); | ||
exports.edge = require('./edge'); | ||
exports.graph = require('./graph'); | ||
exports.layoutQuality = require('./layout-quality'); | ||
exports.modularity = require('./modularity.js'); | ||
exports.weightedDegree = require('./weighted-degree.js'); | ||
exports.weightedSize = require('./weighted-size.js'); | ||
exports.node = require('./node'); |
{ | ||
"name": "graphology-metrics", | ||
"version": "1.18.2", | ||
"version": "2.0.0", | ||
"description": "Miscellaneous graph metrics for graphology.", | ||
"main": "index.js", | ||
"files": [ | ||
"*.js", | ||
"index.js", | ||
"*.d.ts", | ||
"centrality", | ||
"layout-quality" | ||
"edge", | ||
"graph", | ||
"layout-quality", | ||
"node" | ||
], | ||
@@ -55,6 +58,6 @@ "scripts": { | ||
"dependencies": { | ||
"graphology-shortest-path": "^1.5.2", | ||
"graphology-utils": "^2.3.0", | ||
"mnemonist": "^0.38.3" | ||
"graphology-shortest-path": "^2.0.0", | ||
"graphology-utils": "^2.4.4", | ||
"mnemonist": "^0.39.0" | ||
} | ||
} |
431
README.md
@@ -19,2 +19,3 @@ # Graphology metrics | ||
- [Modularity](#modularity) | ||
- [Simple size](#simple-size) | ||
- [Weighted size](#weighted-size) | ||
@@ -24,17 +25,18 @@ | ||
- [Centrality](#centrality) | ||
- [Betweenness centrality](#betweenness-centrality) | ||
- [Closeness centrality](#closeness-centrality) | ||
- [Degree centrality](#degree-centrality) | ||
- [Eigenvector centrality](#eigenvector-centrality) | ||
- [HITS](#hits) | ||
- [Pagerank](#pagerank) | ||
- [Degree](#degree) | ||
- [Eccentricity](#eccentricity) | ||
- [Weighted degree](#weighted-degree) | ||
_Attributes metrics_ | ||
_Edge metrics_ | ||
- [Modalities](#modalities) | ||
- [Simmelian strength](#simmelian-strength) | ||
_Centrality_ | ||
- [Betweenness centrality](#betweenness-centrality) | ||
- [Closeness centrality](#closeness-centrality) | ||
- [Degree centrality](#degree-centrality) | ||
- [Eigenvector centrality](#eigenvector-centrality) | ||
- [HITS](#hits) | ||
- [Pagerank](#pagerank) | ||
_Layout quality metrics_ | ||
@@ -46,9 +48,10 @@ | ||
## Graph metrics | ||
### Density | ||
Computes the density of the given graph. | ||
Computes the density of the given graph. Note that multi variants can exceed `0`, as it is also the case when considering self loops. | ||
```js | ||
import {density} from 'graphology-metrics'; | ||
import density from 'graphology-metrics/density'; | ||
import {density} from 'graphology-metrics/graph/density'; | ||
@@ -69,5 +72,10 @@ // Passing a graph instance | ||
multiUndirectedDensity | ||
} from 'graphology-metric/density'; | ||
} from 'graphology-metric/graph/density'; | ||
const d = undirectedDensity(mixedGraph); | ||
// If you need to chose the kind of density dynamically | ||
import {abstractDensity} from 'graphology-metric/graph/density'; | ||
abstractDensity('directed', true, 10, 24); | ||
``` | ||
@@ -86,2 +94,17 @@ | ||
_Abstract version arguments_ | ||
Either: | ||
- **type** _string_: type of density to compute (`directed`, `undirected` or `mixed`). | ||
- **multi** _boolean_: whether to compute density for the multi of simple case. | ||
- **graph** _Graph_: target graph. | ||
Or: | ||
- **type** _string_: type of density to compute (`directed`, `undirected` or `mixed`). | ||
- **multi** _boolean_: whether to compute density for the multi of simple case. | ||
- **order** _number_: number of nodes in the graph. | ||
- **size** _number_: number of edges in the graph. | ||
### Diameter | ||
@@ -92,5 +115,3 @@ | ||
```js | ||
import {diameter} from 'graphology-metrics'; | ||
// Alternatively, to load only the relevant code: | ||
import diameter from 'graphology-metrics/diameter'; | ||
import diameter from 'graphology-metrics/graph/diameter'; | ||
@@ -118,14 +139,16 @@ const graph = new Graph(); | ||
```js | ||
import extent from 'graphology-metrics/extent'; | ||
import {nodeExtent, edgeExtent} from 'graphology-metrics/graph'; | ||
// Alternatively, to load only the relevant code: | ||
import {nodeExtent, edgeExtent} from 'graphology-metrics/graph/extent'; | ||
// Retrieving a single node attribute's extent | ||
extent(graph, 'size'); | ||
nodeExtent(graph, 'size'); | ||
>>> [1, 34] | ||
// Retrieving multiple node attributes' extents | ||
extent(graph, ['x', 'y']); | ||
nodeExtent(graph, ['x', 'y']); | ||
>>> {x: [-4, 3], y: [-34, 56]} | ||
// For edges | ||
extent.edgeExtent(graph, 'weight'); | ||
// The same for edges | ||
edgeExtent(graph, 'weight'); | ||
>>> [0, 5.7] | ||
@@ -144,5 +167,3 @@ ``` | ||
```js | ||
import {modularity} from 'graphology-metrics'; | ||
// Alternatively, to load only the relevant code: | ||
import modularity from 'graphology-metrics/modularity'; | ||
import modularity from 'graphology-metrics/graph/modularity'; | ||
@@ -152,5 +173,7 @@ // Simplest way | ||
// If the partition is not given by node attributes | ||
// Custom node partition | ||
const Q = modularity(graph, { | ||
communities: {1: 0, 2: 0, 3: 1, 4: 1, 5: 1} | ||
getNodeCommunity(node, attr) { | ||
return attr.customPartition; | ||
} | ||
}); | ||
@@ -163,9 +186,25 @@ ``` | ||
- **options** _?object_: options: | ||
- **attributes** _?object_: attributes' names: | ||
- **community** _?string_ [`community`]: name of the nodes' community attribute in case we need to read them from the graph itself. | ||
- **weight** _?string_ [`weight`]: name of the edges' weight attribute. | ||
- **communities** _?object_: object mapping nodes to their respective communities. | ||
- **getNodeCommunity** _?string\|function_ [`community`]: name of the node community attribute or getter function. | ||
- **getEdgeWeight** _?string\|function_ [`weight`]: name of the edges' weight attribute or getter function. | ||
- **resolution** _?number_: resolution parameter (`γ`). | ||
- **weighted** _?boolean_ [`true`]: whether to compute weighted modularity or not. | ||
### Simple size | ||
Computes the simple size of a given graph, i.e. its number of edges if we consider the graph simple, even if it has multiple edges between pairs of nodes. | ||
```js | ||
import {simpleSize} from 'graphology-metrics'; | ||
// Alternatively, to load only the relevant code: | ||
import simpleSize from 'graphology-metrics/graph/simple-size'; | ||
const graph = new MultiGraph(); | ||
graph.mergeEdge(1, 2); | ||
graph.mergeEdge(1, 2); | ||
graph.mergeEdge(4, 3); | ||
graph.mergeUndirectedEdge(5, 6); | ||
simpleSize(graph); | ||
>>> 3 | ||
``` | ||
### Weighted size | ||
@@ -176,5 +215,3 @@ | ||
```js | ||
import {weightedSize} from 'graphology-metrics'; | ||
// Alternatively, to load only the relevant code: | ||
import weightedSize from 'graphology-metrics/weighted-size'; | ||
import weightedSize from 'graphology-metrics/graph/weighted-size'; | ||
@@ -192,2 +229,5 @@ const graph = new Graph(); | ||
>>> 4 | ||
// With custom getter | ||
weightedSize(graph, (_, attr) => attr.importance); | ||
``` | ||
@@ -198,8 +238,80 @@ | ||
- **graph** _Graph_: target graph. | ||
- **weightAttribute** _?string_ [`weight`]: name of the weight attribute. | ||
- **getEdgeWeight** _?string\|function_ [`weight`]: name of the weight attribute or getter function. | ||
### Centrality | ||
## Node metrics | ||
#### Betweenness centrality | ||
### Weighted degree | ||
Computes the weighted degree of nodes. The weighted degree of a node is the sum of its edges' weights. | ||
```js | ||
import { | ||
weightedDegree, | ||
weightedInDegree, | ||
weightedOutDegree, | ||
weightedInboundDegree, | ||
weightedOutboundDegree, | ||
weightedUndirectedDegree, | ||
weightedDirectedDegree | ||
} from 'graphology-metrics/node/weighted-degree'; | ||
// To compute weighted degree of a node | ||
weightedDegree(graph, 'A'); | ||
// To use a custom weight | ||
weightedDegree(graph, 'A', function (_, attr) { | ||
return attr.importance; | ||
}); | ||
``` | ||
_Arguments_ | ||
- **graph** _Graph_: target graph. | ||
- **node** _any_: desired node. | ||
- **getEdgeWeight** _?string\|function_: name of the edge weight attribute or getter function. | ||
### Eccentricity | ||
Computes the eccentricity which is the maximum of the shortest paths between the given node and any other node. | ||
```js | ||
import eccentricity from 'graphology-metrics/node/eccentricity'; | ||
graph.addNode('1'); | ||
graph.addNode('2'); | ||
graph.addNode('3'); | ||
graph.addNode('4'); | ||
graph.addUndirectedEdge(1, 2); | ||
graph.addUndirectedEdge(2, 3); | ||
graph.addUndirectedEdge(3, 1); | ||
graph.addUndirectedEdge(3, 4); | ||
eccentricity(graph, 3) >> 1; | ||
``` | ||
_Arguments_ | ||
- **graph** _Graph_: target graph. | ||
- **node** _any_: desired node. | ||
## Edge metrics | ||
### Simmelian strength | ||
Function returning the simmelian strength, i.e. the number of triangles an edge is part of, of all the edges in the given graph. | ||
```js | ||
import simmelianStrength from 'graphology-metrics/edge/simmelian-strength'; | ||
// To compute strength for every edge: | ||
const strengths = simmelianStrength(graph); | ||
// To directly map the result onto edge attributes (`simmelianStrength`): | ||
simmelianStrength.assign(graph); | ||
``` | ||
## Centrality | ||
### Betweenness centrality | ||
Computes the betweenness centrality for every node. | ||
@@ -211,7 +323,4 @@ | ||
// To compute centrality for every node: | ||
const centrality = betweennessCentrality(graph); | ||
const centralities = betweennessCentrality(graph); | ||
// To compute weighted betweenness centrality | ||
const centrality = betweennessCentrality(graph, {weighted: true}); | ||
// To directly map the result onto nodes' attributes (`betweennessCentrality`): | ||
@@ -221,3 +330,11 @@ betweennessCentrality.assign(graph); | ||
// To directly map the result onto a custom attribute: | ||
betweennessCentrality.assign(graph, {attributes: {centrality: 'myCentrality'}}); | ||
betweennessCentrality.assign(graph, {nodeCentralityAttribute: 'myCentrality'}); | ||
// To ignore weights | ||
const centralities = betweennessCentrality(graph, {getEdgeWeight: null}); | ||
// To use a getter function for weights | ||
const centralities = betweennessCentrality(graph, { | ||
getEdgeWeight: (_, attr) => attr.importance | ||
}); | ||
``` | ||
@@ -229,7 +346,5 @@ | ||
- **options** _?object_: options: | ||
- **attributes** _?object_: Custom attribute names: | ||
- **centrality** _?string_ [`betweennessCentrality`]: Name of the centrality attribute to assign. | ||
- **weight** _?string_: Name of the weight attribute. | ||
- **nodeCentralityAttribute** _?string_ [`betweennessCentrality`]: Name of the centrality attribute to assign. | ||
- **getEdgeWeight** _?string\|function_ [`weight`]: Name of the edge weight attribute or getter function. | ||
- **normalized** _?boolean_ [`true`]: should the result be normalized? | ||
- **weighted** _?boolean_ [`false`]: should we compute the weighted betweenness centrality? | ||
@@ -257,7 +372,6 @@ ### Closeness centrality | ||
- **options** _?object_: options: | ||
- **attributes** _?object_: attributes' names: | ||
- **centrality** _?string_ [`eigenvectorCentrality`]: name of the node attribute that will be assigned the eigenvector centrality. | ||
- **nodeCentralityAttribute** _?string_ [`closenessCentrality`]: name of the node attribute that will be assigned the closeness centrality. | ||
- **wassermanFaust** _?boolean_ [`false`]: whether to use Wasserman & Faust's normalization scheme. | ||
#### Degree centrality | ||
### Degree centrality | ||
@@ -267,4 +381,2 @@ Computes the degree centrality for every node. | ||
```js | ||
import degreeCentrality from 'graphology-metrics/centrality/degree'; | ||
// Or to load more specific functions: | ||
import { | ||
@@ -277,3 +389,3 @@ degreeCentrality, | ||
// To compute degree centrality for every node: | ||
const centrality = degreeCentrality(graph); | ||
const centralities = degreeCentrality(graph); | ||
@@ -284,3 +396,3 @@ // To directly map the result onto nodes' attributes (`degreeCentrality`): | ||
// To directly map the result onto a custom attribute: | ||
degreeCentrality.assign(graph, {attributes: {centrality: 'myCentrality'}}); | ||
degreeCentrality.assign(graph, {nodeCentralityAttribute: 'myCentrality'}); | ||
``` | ||
@@ -292,4 +404,3 @@ | ||
- **options** _?object_: options: | ||
- **attributes** _?object_: custom attribute names: | ||
- **centrality** _?string_ [`degreeCentrality`]: name of the centrality attribute to assign. | ||
- **nodeCentralityAttribute** _?string_ [`degreeCentrality`]: name of the centrality attribute to assign. | ||
@@ -310,3 +421,6 @@ ### Eigenvector centrality | ||
// Note that you can also pass options to customize the algorithm: | ||
const p = eigenvectorCentrality(graph, {tolerance: 1e-3, weighted: false}); | ||
const p = eigenvectorCentrality(graph, {tolerance: 1e-3}); | ||
// To ignore your graph's weights | ||
eigenvectorCentrality.assign(graph, {getEdgeWeight: null}); | ||
``` | ||
@@ -318,10 +432,7 @@ | ||
- **options** _?object_: options: | ||
- **attributes** _?object_: attributes' names: | ||
- **centrality** _?string_ [`eigenvectorCentrality`]: name of the node attribute that will be assigned the eigenvector centrality. | ||
- **weight** _?string_ [`weight`]: name of the edges' weight attribute. | ||
- **nodeCentralityAttribute** _?string_ [`eigenvectorCentrality`]: name of the node attribute that will be assigned the eigenvector centrality. | ||
- **getEdgeWeight** _?string\|function_ [`weight`]: name of the edges' weight attribute or getter function. | ||
- **maxIterations** _?number_ [`100`]: maximum number of iterations to perform. | ||
- **tolerance** _?number_ [`1.e-6`]: convergence error tolerance. | ||
- **weighted** _?boolean_ [`false`]: whether to use available weights or not. | ||
### HITS | ||
@@ -348,6 +459,5 @@ | ||
- **options** _?object_: options: | ||
- **attributes** _?object_: attributes' names: | ||
- **weight** _?string_ [`weight`]: name of the edges' weight attribute. | ||
- **hub** _?string_ [`hub`]: name of the node attribute holding hub information. | ||
- **authority** _?string_ [`authority`]: name of the node attribute holding authority information. | ||
- **getEdgeWeight** _?string\|function_ [`weight`]: name of the edges' weight attribute or getter function. | ||
- **nodeHubAttribute** _?string_ [`hub`]: name of the node attribute holding hub information. | ||
- **nodeAuthorityAttribute** _?string_ [`authority`]: name of the node attribute holding authority information. | ||
- **maxIterations** _?number_ [`100`]: maximum number of iterations to perform. | ||
@@ -371,3 +481,6 @@ - **normalize** _?boolean_ [`true`]: should the result be normalized by the sum of values. | ||
// Note that you can also pass options to customize the algorithm: | ||
const p = pagerank(graph, {alpha: 0.9, weighted: false}); | ||
const p = pagerank(graph, {alpha: 0.9}); | ||
// To ignore your graph's weights | ||
pagerank.assign(graph, {getEdgeWeight: null}); | ||
``` | ||
@@ -379,188 +492,10 @@ | ||
- **options** _?object_: options: | ||
- **attributes** _?object_: attributes' names: | ||
- **pagerank** _?string_ [`pagerank`]: name of the node attribute that will be assigned the pagerank score. | ||
- **weight** _?string_ [`weight`]: name of the edges' weight attribute. | ||
- **nodePagerankAttribute** _?string_ [`pagerank`]: name of the node attribute that will be assigned the pagerank score. | ||
- **getEdgeWeight** _?string\|function_ [`weight`]: name of the edges' weight attribute or getter function. | ||
- **alpha** _?number_ [`0.85`]: damping parameter of the algorithm. | ||
- **maxIterations** _?number_ [`100`]: maximum number of iterations to perform. | ||
- **tolerance** _?number_ [`1.e-6`]: convergence error tolerance. | ||
- **weighted** _?boolean_ [`false`]: whether to use available weights or not. | ||
### Weighted degree | ||
## Layout quality metrics | ||
Computes the weighted degree of nodes. The weighted degree of a node is the sum of its edges' weights. | ||
```js | ||
import weightedDegree from 'graphology-metrics/weighted-degree'; | ||
// Or to load more specific functions: | ||
import { | ||
weightedDegree, | ||
weightedInDegree, | ||
weightedOutDegree | ||
} from 'graphology-metrics/weighted-degree'; | ||
// To compute weighted degree of a single node | ||
weightedDegree(graph, 'A'); | ||
// To compute weighted degree of every node | ||
const weightedDegrees = weightedDegree(graph); | ||
// To compute normalized weighted degree, i.e. weighted degree will be | ||
// divided by the node's relevant degree | ||
weightedDegree(graph, 'A', {normalized: true}); | ||
// To directly map the result onto node attributes | ||
weightedDegree.assign(graph); | ||
``` | ||
_Arguments_ | ||
To compute the weighted degree of a single node: | ||
- **graph** _Graph_: target graph. | ||
- **node** _any_: desired node. | ||
- **options** _?object_: options. See below. | ||
To compute the weighted degree of every node: | ||
- **graph** _Graph_: target graph. | ||
- **options** _?object_: options. See below. | ||
_Options_ | ||
- **attributes** _?object_: custom attribute names: | ||
- **weight** _?string_ [`weight`]: name of the weight attribute. | ||
- **weightedDegree** _?string_ [`weightedDegree`]: name of the attribute to assign. | ||
### Degree | ||
Returns degree information for every node in the graph. Note that [`graphology`](https://graphology.github.io)'s API already gives you access to this information through `#.degree` etc. So only consider this function as a convenience to extract/assign all degrees at once. | ||
```js | ||
import degree from 'graphology-metrics/degree'; | ||
import degree, { | ||
inDegree, | ||
outDegree, | ||
undirectedDegree, | ||
directedDegree, | ||
allDegree | ||
} from 'graphology-metrics/degree'; | ||
// To extract degree information for every node | ||
const degrees = degree(graph); | ||
>>> {node1: 34, node2: 45, ...} | ||
// To extract only in degree information for every node | ||
const inDegrees = inDegree(graph); | ||
// To extract full degree breakdown for every node | ||
const degrees = allDegree(graph); | ||
>>> { // Assuming the graph is directed | ||
node1: { | ||
inDegree: 2, | ||
outDegree: 36 | ||
}, | ||
... | ||
} | ||
// To map degree information to node attributes | ||
degree.assign(graph); | ||
graph.getNodeAttribute(node, 'degree'); | ||
>>> 45 | ||
// To map only degree & in degree to node attributes | ||
allDegree.assign(graph, {types: ['degree', 'inDegree']}); | ||
// To map only degree & in degree with different names | ||
allDegree( | ||
graph, | ||
{ | ||
attributes: { | ||
inDegree: 'in', | ||
outDegree: 'out' | ||
}, | ||
types: ['inDegree', 'outDegree'] | ||
} | ||
) | ||
>>> { | ||
1: {in: 1, out: 1}, | ||
... | ||
} | ||
``` | ||
_Arguments_ | ||
- **graph** _Graph_: target graph. | ||
- **options** _?object_: options: | ||
- **attributes** _?object_: Custom attribute names: | ||
- **degree** _?string_: Name of the mixed degree attribute. | ||
- **inDegree** _?string_: Name of the mixed inDegree attribute. | ||
- **outDegree** _?string_: Name of the mixed outDegree attribute. | ||
- **undirectedDegree** _?string_: Name of the mixed undirectedDegree attribute. | ||
- **directedDegree** _?string_: Name of the mixed directedDegree attribute. | ||
- **types** _?array_: List of degree types to extract. | ||
### Eccentricity | ||
Computes the eccentricity which is the maximum of the shortest paths between the given node and any other node. | ||
```js | ||
import {eccentricity} from 'graphology-metrics'; | ||
// Alternatively, to load only the relevant code: | ||
import eccentricity from 'graphology-metrics/eccentricity'; | ||
graph.addNode('1'); | ||
graph.addNode('2'); | ||
graph.addNode('3'); | ||
graph.addNode('4'); | ||
graph.addUndirectedEdge(1, 2); | ||
graph.addUndirectedEdge(2, 3); | ||
graph.addUndirectedEdge(3, 1); | ||
graph.addUndirectedEdge(3, 4); | ||
eccentricity(graph, 3) >> 1; | ||
``` | ||
_Arguments_ | ||
- **graph** _Graph_: target graph. | ||
- **node** _any_: desired node. | ||
### Modalities | ||
Method returning a node categorical attribute's modalities and related statistics. | ||
```js | ||
import modalities from 'graphology-metrics/modalities'; | ||
// Retrieving the 'type' attribute's modalities | ||
const info = modalities(graph, 'type'); | ||
>>> { | ||
value1: { | ||
nodes: 34, | ||
internalEdges: 277, | ||
internalDensity: 0.03, | ||
externalEdges: 45, | ||
externalDensity: 0.05, | ||
inboundEdges: 67, | ||
inboundDensity: 0.07, | ||
outboundEdges: 124, | ||
outboundDensity: 0.003 | ||
}, | ||
... | ||
} | ||
// Retrieving modalities info for several attributes at once | ||
const info = modalities(graph, ['type', 'lang']); | ||
>>> { | ||
type: {...}, | ||
lang: {...} | ||
} | ||
``` | ||
_Arguments_ | ||
- **graph** _Graph_: target graph. | ||
- **attribute** _string|array_: target categorical attribute or array of categorical attributes. | ||
### Edge Uniformity | ||
@@ -567,0 +502,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
51
89897
2166
517
1
+ Addedgraphology-indices@0.17.0(transitive)
+ Addedgraphology-shortest-path@2.1.0(transitive)
+ Addedgraphology-types@0.24.8(transitive)
- Removedgraphology-indices@0.16.6(transitive)
- Removedgraphology-shortest-path@1.5.2(transitive)
- Removedgraphology-types@0.24.7(transitive)
- Removedmnemonist@0.38.5(transitive)
Updatedgraphology-utils@^2.4.4
Updatedmnemonist@^0.39.0