feat: Implemented O(n) => O(log2(n)) speedup.

This commit is contained in:
NunoSempere 2021-12-07 23:45:55 +01:00
parent 74d1f2be23
commit 54111831ca

View File

@ -7,23 +7,44 @@ let avg = arr => arr.reduce((a, b) => (a + b), 0) / arr.length
/* Main function */ /* Main function */
function findPathsInner({ sourceElementId, targetElementId, pathSoFar, links, nodes, maxLengthOfPath }) { function findPathsInner({
sourceElementId, sourceElementPosition,
targetElementId, targetElementPosition,
links, nodes,
maxLengthOfPath, pathSoFar
}) {
let paths = [] let paths = []
let minPos = Math.min(sourceElementPosition, targetElementPosition)
let maxPos = Math.max(sourceElementPosition, targetElementPosition)
let linksInner = links.filter(link =>
(minPos <= link.sourceElementPosition && link.sourceElementPosition <= maxPos) &&
(minPos <= link.targetElementPosition && link.targetElementPosition <= maxPos)
)
let linksNow = linksInner.filter(link => (link.source == sourceElementId || link.target == sourceElementId))
if (maxLengthOfPath > 0) { if (maxLengthOfPath > 0) {
for (let link of links) { for (let link of linksNow) {
if ( if (
((link.source == sourceElementId) && (link.target == targetElementId)) || ((link.source == sourceElementId) && (link.target == targetElementId)) ||
((link.source == targetElementId) && (link.target == sourceElementId)) ((link.source == targetElementId) && (link.target == sourceElementId))
) { ) {
paths.push(pathSoFar.concat(link).flat()) paths.push(pathSoFar.concat(link).flat())
} else if ((link.source == sourceElementId)) { } else if ((link.source == sourceElementId)) {
let newPaths = findPathsInner({ sourceElementId: link.target, targetElementId, pathSoFar: pathSoFar.concat(link).flat(), links, nodes, maxLengthOfPath: (maxLengthOfPath - 1) }) let newPaths = findPathsInner({
sourceElementId: link.target, sourceElementPosition: link.sourceElementPosition,
targetElementId, targetElementPosition,
pathSoFar: pathSoFar.concat(link).flat(),
links: linksInner, nodes, maxLengthOfPath: (maxLengthOfPath - 1)
})
if (newPaths.length != 0) { if (newPaths.length != 0) {
paths.push(...newPaths) paths.push(...newPaths)
} }
} else if ((link.target == sourceElementId)) { } else if ((link.target == sourceElementId)) {
let newPaths = findPathsInner({ sourceElementId: link.source, targetElementId, pathSoFar: pathSoFar.concat(link).flat(), links, nodes, maxLengthOfPath: (maxLengthOfPath - 1) }) let newPaths = findPathsInner({
sourceElementId: link.source, sourceElementPosition: link.sourceElementPosition,
targetElementId, targetElementPosition,
pathSoFar: pathSoFar.concat(link).flat(),
links: linksInner, nodes, maxLengthOfPath: (maxLengthOfPath - 1) })
if (newPaths.length != 0) { if (newPaths.length != 0) {
paths.push(...newPaths) paths.push(...newPaths)
} }
@ -33,17 +54,36 @@ function findPathsInner({ sourceElementId, targetElementId, pathSoFar, links, no
return paths return paths
} }
/*
function findPaths({ sourceElementId, targetElementId, links, nodes }) { function findPaths({
sourceElementId, sourceElementPosition,
targetElementId, targetElementPosition,
nodes, links, direction
}) {
let positionSourceElement = nodes.map((element, i) => (element.id)).indexOf(sourceElementId) let positionSourceElement = nodes.map((element, i) => (element.id)).indexOf(sourceElementId)
let positionTargetElement = nodes.map((element, i) => (element.id)).indexOf(targetElementId) let positionTargetElement = nodes.map((element, i) => (element.id)).indexOf(targetElementId)
let maxLengthOfPath = Math.abs(positionSourceElement - positionTargetElement) let maxLengthOfPath = Math.abs(positionSourceElement - positionTargetElement)
return findPathsInner({
return findPathsInner({ sourceElementId, targetElementId, pathSoFar: [], links, nodes, maxLengthOfPath }) sourceElementId, sourceElementPosition,
targetElementId, targetElementPosition,
links, nodes, direction,
maxLengthOfPath, pathSoFar: []
})
} }
*/
function findDistance({ sourceElementId, sourceElementPosition, targetElementId, targetElementPosition, nodes, links, direction }) { function findDistance({
let paths = findPaths({ sourceElementId, targetElementId, nodes, links }) sourceElementId, sourceElementPosition,
targetElementId, targetElementPosition,
nodes, links, direction
}) {
let maxLengthOfPath = Math.abs(sourceElementPosition - targetElementPosition)
let paths = findPathsInner({
sourceElementId, sourceElementPosition,
targetElementId, targetElementPosition,
links, nodes, direction,
maxLengthOfPath, pathSoFar: []
});
console.log(`findDistance from ${sourceElementPosition} to ${targetElementPosition}`) console.log(`findDistance from ${sourceElementPosition} to ${targetElementPosition}`)
console.log(targetElementId) console.log(targetElementId)
console.log(direction) console.log(direction)
@ -106,7 +146,6 @@ function findDistancesForAllElements({ nodes, links }) {
let midpoint = Math.round(nodes.length / 2) let midpoint = Math.round(nodes.length / 2)
let referenceElement = referenceElements.length > 0 ? referenceElements[0] : nodes[midpoint] let referenceElement = referenceElements.length > 0 ? referenceElements[0] : nodes[midpoint]
// console.log(nodes) // console.log(nodes)
let [upwardsLinks, downwardsLinks] = getDirectionalLinks({ nodes, links })
console.log(`referenceElement.position: ${referenceElement.position}`) console.log(`referenceElement.position: ${referenceElement.position}`)
let distances = nodes.map(node => { let distances = nodes.map(node => {
if (node.isReferenceValue || (node.id == referenceElement.id)) { if (node.isReferenceValue || (node.id == referenceElement.id)) {
@ -114,14 +153,14 @@ function findDistancesForAllElements({ nodes, links }) {
} else { } else {
console.log("node") console.log("node")
console.log(node) console.log(node)
let isUpwardsDirection = referenceElement.position < node.position; let isUpwardsDirection = referenceElement.position < node.position
let distance = findDistance({ let distance = findDistance({
sourceElementId: referenceElement.id, sourceElementId: referenceElement.id,
sourceElementPosition: referenceElement.position, sourceElementPosition: referenceElement.position,
targetElementId: node.id, targetElementId: node.id,
targetElementPosition: node.position, targetElementPosition: node.position,
nodes: nodes, nodes: nodes,
links: links, // isUpwardsDirection ? upwardsLinks : downwardsLinks, // links links: links,
direction: isUpwardsDirection ? "upwards" : "downwards" direction: isUpwardsDirection ? "upwards" : "downwards"
}) })
return distance return distance
@ -149,7 +188,19 @@ export function CreateTableWithDistances({ isListOrdered, orderedList, listOfEle
if (!isListOrdered || orderedList.length < listOfElements.length) { if (!isListOrdered || orderedList.length < listOfElements.length) {
return (<div>{""}</div>) return (<div>{""}</div>)
} else { } else {
let nodes = orderedList.map((id, pos) => ({ ...listOfElements[id], position: pos })) let nodes = []
let positionDictionary=({})
orderedList.forEach((id, pos) => {
nodes.push({ ...listOfElements[id], position: pos })
positionDictionary[id] = pos
})
// let nodes = orderedList.map((id, pos) => ({ ...listOfElements[id], position: pos }))
/* Pre-process links to talk in terms of distances */
links = links.map(link => ({...link,
sourceElementPosition: positionDictionary[link.source],
targetElementPosition: positionDictionary[link.target]
}))
/* Continue */
let distances = findDistancesForAllElements({ nodes, links }) let distances = findDistancesForAllElements({ nodes, links })
let rows = nodes.map((element, i) => ({ id: numToAlphabeticalString(element.position), position: element.position, name: element.name, distances: distances[i] })) let rows = nodes.map((element, i) => ({ id: numToAlphabeticalString(element.position), position: element.position, name: element.name, distances: distances[i] }))
console.log("rows@CreateTableWithDistances") console.log("rows@CreateTableWithDistances")