/**
|
|
* @class FloydWarshall
|
|
*/
|
|
class FloydWarshall {
|
|
/**
|
|
* @constructor FloydWarshall
|
|
*/
|
|
constructor() {
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {Object} body
|
|
* @param {Array<Node>} nodesArray
|
|
* @param {Array<Edge>} edgesArray
|
|
* @returns {{}}
|
|
* @static
|
|
*/
|
|
getDistances(body, nodesArray, edgesArray) {
|
|
let D_matrix = {};
|
|
let edges = body.edges;
|
|
|
|
// prepare matrix with large numbers
|
|
for (let i = 0; i < nodesArray.length; i++) {
|
|
let node = nodesArray[i];
|
|
let cell = {};
|
|
D_matrix[node] = cell;
|
|
for (let j = 0; j < nodesArray.length; j++) {
|
|
cell[nodesArray[j]] = (i == j ? 0 : 1e9);
|
|
}
|
|
}
|
|
|
|
// put the weights for the edges in. This assumes unidirectionality.
|
|
for (let i = 0; i < edgesArray.length; i++) {
|
|
let edge = edges[edgesArray[i]];
|
|
// edge has to be connected if it counts to the distances. If it is connected to inner clusters it will crash so we also check if it is in the D_matrix
|
|
if (edge.connected === true && D_matrix[edge.fromId] !== undefined && D_matrix[edge.toId] !== undefined) {
|
|
D_matrix[edge.fromId][edge.toId] = 1;
|
|
D_matrix[edge.toId][edge.fromId] = 1;
|
|
}
|
|
}
|
|
|
|
let nodeCount = nodesArray.length;
|
|
|
|
// Adapted FloydWarshall based on unidirectionality to greatly reduce complexity.
|
|
for (let k = 0; k < nodeCount; k++) {
|
|
let knode = nodesArray[k];
|
|
let kcolm = D_matrix[knode];
|
|
for (let i = 0; i < nodeCount - 1; i++) {
|
|
let inode = nodesArray[i];
|
|
let icolm = D_matrix[inode];
|
|
for (let j = i + 1; j < nodeCount; j++) {
|
|
let jnode = nodesArray[j];
|
|
let jcolm = D_matrix[jnode];
|
|
|
|
let val = Math.min(icolm[jnode], icolm[knode] + kcolm[jnode]);
|
|
icolm[jnode] = val;
|
|
jcolm[inode] = val;
|
|
}
|
|
}
|
|
}
|
|
|
|
return D_matrix;
|
|
}
|
|
}
|
|
|
|
export default FloydWarshall;
|