mirror of
https://github.com/anvaka/ngraph.path.git
synced 2026-01-18 15:13:12 +00:00
1 line
45 KiB
Plaintext
1 line
45 KiB
Plaintext
{"version":3,"file":"ngraph.path.cjs","sources":["../a-star/NodeHeap.js","../a-star/makeSearchStatePool.js","../a-star/heuristics.js","../a-star/defaultSettings.js","../a-star/a-star.js","../a-star/a-greedy-star.js","../a-star/nba/makeNBASearchStatePool.js","../a-star/nba/index.js","../index.js"],"sourcesContent":["/**\n * Based on https://github.com/mourner/tinyqueue\n * Copyright (c) 2017, Vladimir Agafonkin https://github.com/mourner/tinyqueue/blob/master/LICENSE\n * \n * Adapted for PathFinding needs by @anvaka\n * Copyright (c) 2017, Andrei Kashcha\n */\nexport default function NodeHeap(data, options) {\n if (!new.target) return new NodeHeap(data, options);\n\n if (!Array.isArray(data)) {\n // assume first argument is our config object;\n options = data;\n data = [];\n }\n\n options = options || {};\n\n this.data = data || [];\n this.length = this.data.length;\n this.compare = options.compare || defaultCompare;\n this.setNodeId = options.setNodeId || noop;\n\n if (this.length > 0) {\n for (var i = (this.length >> 1); i >= 0; i--) this._down(i);\n }\n\n if (options.setNodeId) {\n for (var i = 0; i < this.length; ++i) {\n this.setNodeId(this.data[i], i);\n }\n }\n}\n\nfunction noop() {}\n\nfunction defaultCompare(a, b) {\n return a - b;\n}\n\nNodeHeap.prototype = {\n\n push: function (item) {\n this.data.push(item);\n this.setNodeId(item, this.length);\n this.length++;\n this._up(this.length - 1);\n },\n\n pop: function () {\n if (this.length === 0) return undefined;\n\n var top = this.data[0];\n this.length--;\n\n if (this.length > 0) {\n this.data[0] = this.data[this.length];\n this.setNodeId(this.data[0], 0);\n this._down(0);\n }\n this.data.pop();\n\n return top;\n },\n\n peek: function () {\n return this.data[0];\n },\n\n updateItem: function (pos) {\n this._down(pos);\n this._up(pos);\n },\n\n _up: function (pos) {\n var data = this.data;\n var compare = this.compare;\n var setNodeId = this.setNodeId;\n var item = data[pos];\n\n while (pos > 0) {\n var parent = (pos - 1) >> 1;\n var current = data[parent];\n if (compare(item, current) >= 0) break;\n data[pos] = current;\n\n setNodeId(current, pos);\n pos = parent;\n }\n\n data[pos] = item;\n setNodeId(item, pos);\n },\n\n _down: function (pos) {\n var data = this.data;\n var compare = this.compare;\n var halfLength = this.length >> 1;\n var item = data[pos];\n var setNodeId = this.setNodeId;\n\n while (pos < halfLength) {\n var left = (pos << 1) + 1;\n var right = left + 1;\n var best = data[left];\n\n if (right < this.length && compare(data[right], best) < 0) {\n left = right;\n best = data[right];\n }\n if (compare(best, item) >= 0) break;\n\n data[pos] = best;\n setNodeId(best, pos);\n pos = left;\n }\n\n data[pos] = item;\n setNodeId(item, pos);\n }\n};","/**\n * This class represents a single search node in the exploration tree for\n * A* algorithm.\n * \n * @param {Object} node original node in the graph\n */\nfunction NodeSearchState(node) {\n this.node = node;\n\n // How we came to this node?\n this.parent = null;\n\n this.closed = false;\n this.open = 0;\n\n this.distanceToSource = Number.POSITIVE_INFINITY;\n // the f(n) = g(n) + h(n) value\n this.fScore = Number.POSITIVE_INFINITY;\n\n // used to reconstruct heap when fScore is updated.\n this.heapIndex = -1;\n};\n\nexport default function makeSearchStatePool() {\n var currentInCache = 0;\n var nodeCache = [];\n\n return {\n createNewState: createNewState,\n reset: reset\n };\n\n function reset() {\n currentInCache = 0;\n }\n\n function createNewState(node) {\n var cached = nodeCache[currentInCache];\n if (cached) {\n // TODO: This almost duplicates constructor code. Not sure if\n // it would impact performance if I move this code into a function\n cached.node = node;\n // How we came to this node?\n cached.parent = null;\n\n cached.closed = false;\n cached.open = 0;\n\n cached.distanceToSource = Number.POSITIVE_INFINITY;\n // the f(n) = g(n) + h(n) value\n cached.fScore = Number.POSITIVE_INFINITY;\n\n // used to reconstruct heap when fScore is updated.\n cached.heapIndex = -1;\n\n } else {\n cached = new NodeSearchState(node);\n nodeCache[currentInCache] = cached;\n }\n currentInCache++;\n return cached;\n }\n}","export { l2, l1 };\n\n/**\n * Euclid distance (l2 norm);\n * \n * @param {*} a \n * @param {*} b \n */\nfunction l2(a, b) {\n var dx = a.x - b.x;\n var dy = a.y - b.y;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n/**\n * Manhattan distance (l1 norm);\n * @param {*} a \n * @param {*} b \n */\nfunction l1(a, b) {\n var dx = a.x - b.x;\n var dy = a.y - b.y;\n return Math.abs(dx) + Math.abs(dy);\n}\n","// We reuse instance of array, but we trie to freeze it as well,\n// so that consumers don't modify it. Maybe it's a bad idea.\nconst NO_PATH = [];\nif (typeof Object.freeze === 'function') Object.freeze(NO_PATH);\n\nconst defaultSettings = {\n // Path search settings\n heuristic: blindHeuristic,\n distance: constantDistance,\n blocked: neverBlocked,\n compareFScore: compareFScore,\n NO_PATH: NO_PATH,\n\n // heap settings\n setHeapIndex: setHeapIndex,\n\n // nba:\n setH1: setH1,\n setH2: setH2,\n compareF1Score: compareF1Score,\n compareF2Score: compareF2Score,\n};\n\nexport default defaultSettings;\n\nfunction blindHeuristic(/* a, b */) {\n // blind heuristic makes this search equal to plain Dijkstra path search.\n return 0;\n}\n\nfunction constantDistance(/* a, b */) {\n return 1;\n}\n\nfunction neverBlocked(/* a, b, c */) {\n return false;\n}\n\nfunction compareFScore(a, b) {\n var result = a.fScore - b.fScore;\n // TODO: Can I improve speed with smarter ties-breaking?\n // I tried distanceToSource, but it didn't seem to have much effect\n return result;\n}\n\nfunction setHeapIndex(nodeSearchState, heapIndex) {\n nodeSearchState.heapIndex = heapIndex;\n}\n\nfunction compareF1Score(a, b) {\n return a.f1 - b.f1;\n}\n\nfunction compareF2Score(a, b) {\n return a.f2 - b.f2;\n}\n\nfunction setH1(node, heapIndex) {\n node.h1 = heapIndex;\n}\n\nfunction setH2(node, heapIndex) {\n node.h2 = heapIndex;\n}","/**\n * Performs a uni-directional A Star search on graph.\n * \n * We will try to minimize f(n) = g(n) + h(n), where\n * g(n) is actual distance from source node to `n`, and\n * h(n) is heuristic distance from `n` to target node.\n */\nimport NodeHeap from './NodeHeap.js';\nimport makeSearchStatePool from './makeSearchStatePool.js';\nimport * as heuristics from './heuristics.js';\nimport defaultSettings from './defaultSettings.js';\n\nvar NO_PATH = defaultSettings.NO_PATH;\n\n/**\n * Creates a new instance of pathfinder. A pathfinder has just one method:\n * `find(fromId, toId)`, it may be extended in future.\n * \n * @param {ngraph.graph} graph instance. See https://github.com/anvaka/ngraph.graph\n * @param {Object} options that configures search\n * @param {Function(a, b, link)} options.blocked - a function that returns `true` if the link between \n * nodes `a` and `b` are blocked paths. This function is useful for temporarily blocking routes \n * while allowing the graph to be reused without rebuilding.\n * @param {Function(a, b)} options.heuristic - a function that returns estimated distance between\n * nodes `a` and `b`. This function should never overestimate actual distance between two\n * nodes (otherwise the found path will not be the shortest). Defaults function returns 0,\n * which makes this search equivalent to Dijkstra search.\n * @param {Function(a, b)} options.distance - a function that returns actual distance between two\n * nodes `a` and `b`. By default this is set to return graph-theoretical distance (always 1);\n * @param {Boolean} options.oriented - whether graph should be considered oriented or not.\n * \n * @returns {Object} A pathfinder with single method `find()`.\n */\nfunction aStarPathSearch(graph, options) {\n options = options || {};\n // whether traversal should be considered over oriented graph.\n var oriented = options.oriented;\n\n var blocked = options.blocked;\n if (!blocked) blocked = defaultSettings.blocked;\n\n var heuristic = options.heuristic;\n if (!heuristic) heuristic = defaultSettings.heuristic;\n\n var distance = options.distance;\n if (!distance) distance = defaultSettings.distance;\n var pool = makeSearchStatePool();\n\n return {\n /**\n * Finds a path between node `fromId` and `toId`.\n * @returns {Array} of nodes between `toId` and `fromId`. Empty array is returned\n * if no path is found.\n */\n find: find\n };\n\n function find(fromId, toId) {\n var from = graph.getNode(fromId);\n if (!from) throw new Error('fromId is not defined in this graph: ' + fromId);\n var to = graph.getNode(toId);\n if (!to) throw new Error('toId is not defined in this graph: ' + toId);\n pool.reset();\n\n // Maps nodeId to NodeSearchState.\n var nodeState = new Map();\n\n // the nodes that we still need to evaluate\n var openSet = new NodeHeap({\n compare: defaultSettings.compareFScore,\n setNodeId: defaultSettings.setHeapIndex\n });\n\n var startNode = pool.createNewState(from);\n nodeState.set(fromId, startNode);\n\n // For the first node, fScore is completely heuristic.\n startNode.fScore = heuristic(from, to);\n\n // The cost of going from start to start is zero.\n startNode.distanceToSource = 0;\n openSet.push(startNode);\n startNode.open = 1;\n\n var cameFrom;\n\n while (openSet.length > 0) {\n cameFrom = openSet.pop();\n if (goalReached(cameFrom, to)) return reconstructPath(cameFrom);\n\n // no need to visit this node anymore\n cameFrom.closed = true;\n graph.forEachLinkedNode(cameFrom.node.id, visitNeighbour, oriented);\n }\n\n // If we got here, then there is no path.\n return NO_PATH;\n\n function visitNeighbour(otherNode, link) {\n var otherSearchState = nodeState.get(otherNode.id);\n if (!otherSearchState) {\n otherSearchState = pool.createNewState(otherNode);\n nodeState.set(otherNode.id, otherSearchState);\n }\n\n if (otherSearchState.closed) {\n // Already processed this node.\n return;\n }\n if (otherSearchState.open === 0) {\n // Remember this node.\n openSet.push(otherSearchState);\n otherSearchState.open = 1;\n }\n\n if (blocked(otherNode, cameFrom.node, link)) {\n // Path is blocked. Ignore this route\n return;\n }\n\n var tentativeDistance = cameFrom.distanceToSource + distance(otherNode, cameFrom.node, link);\n if (tentativeDistance >= otherSearchState.distanceToSource) {\n // This would only make our path longer. Ignore this route.\n return;\n }\n\n // bingo! we found shorter path:\n otherSearchState.parent = cameFrom;\n otherSearchState.distanceToSource = tentativeDistance;\n otherSearchState.fScore = tentativeDistance + heuristic(otherSearchState.node, to);\n\n openSet.updateItem(otherSearchState.heapIndex);\n }\n }\n}\n\naStarPathSearch.l2 = heuristics.l2;\naStarPathSearch.l1 = heuristics.l1;\n\nexport default aStarPathSearch;\n\nfunction goalReached(searchState, targetNode) {\n return searchState.node === targetNode;\n}\n\nfunction reconstructPath(searchState) {\n var path = [searchState.node];\n var parent = searchState.parent;\n\n while (parent) {\n path.push(parent.node);\n parent = parent.parent;\n }\n\n return path;\n}\n","/**\n * Performs suboptimal, greed A Star path finding.\n * This finder does not necessary finds the shortest path. The path\n * that it finds is very close to the shortest one. It is very fast though.\n */\nimport NodeHeap from './NodeHeap.js';\nimport makeSearchStatePool from './makeSearchStatePool.js';\nimport * as heuristics from './heuristics.js';\nimport defaultSettings from './defaultSettings.js';\n\nvar BY_FROM = 1;\nvar BY_TO = 2;\nvar NO_PATH = defaultSettings.NO_PATH;\n\n/**\n * Creates a new instance of pathfinder. A pathfinder has just one method:\n * `find(fromId, toId)`, it may be extended in future.\n * \n * NOTE: Algorithm implemented in this code DOES NOT find optimal path.\n * Yet the path that it finds is always near optimal, and it finds it very fast.\n * \n * @param {ngraph.graph} graph instance. See https://github.com/anvaka/ngraph.graph\n * \n * @param {Object} options that configures search\n * @param {Function(a, b, link)} options.blocked - a function that returns `true` if the link between \n * nodes `a` and `b` are blocked paths. This function is useful for temporarily blocking routes \n * while allowing the graph to be reused without rebuilding.\n * @param {Function(a, b)} options.heuristic - a function that returns estimated distance between\n * nodes `a` and `b`. Defaults function returns 0, which makes this search equivalent to Dijkstra search.\n * @param {Function(a, b)} options.distance - a function that returns actual distance between two\n * nodes `a` and `b`. By default this is set to return graph-theoretical distance (always 1);\n * @param {Boolean} options.oriented - whether graph should be considered oriented or not.\n * \n * @returns {Object} A pathfinder with single method `find()`.\n */\nfunction aStarBi(graph, options) {\n options = options || {};\n // whether traversal should be considered over oriented graph.\n var oriented = options.oriented;\n\n var blocked = options.blocked;\n if (!blocked) blocked = defaultSettings.blocked;\n\n var heuristic = options.heuristic;\n if (!heuristic) heuristic = defaultSettings.heuristic;\n\n var distance = options.distance;\n if (!distance) distance = defaultSettings.distance;\n var pool = makeSearchStatePool();\n\n return {\n find: find\n };\n\n function find(fromId, toId) {\n // Not sure if we should return NO_PATH or throw. Throw seem to be more\n // helpful to debug errors. So, throwing.\n var from = graph.getNode(fromId);\n if (!from) throw new Error('fromId is not defined in this graph: ' + fromId);\n var to = graph.getNode(toId);\n if (!to) throw new Error('toId is not defined in this graph: ' + toId);\n\n if (from === to) return [from]; // trivial case.\n\n pool.reset();\n\n var callVisitor = oriented ? orientedVisitor : nonOrientedVisitor;\n\n // Maps nodeId to NodeSearchState.\n var nodeState = new Map();\n\n var openSetFrom = new NodeHeap({\n compare: defaultSettings.compareFScore,\n setNodeId: defaultSettings.setHeapIndex\n });\n\n var openSetTo = new NodeHeap({\n compare: defaultSettings.compareFScore,\n setNodeId: defaultSettings.setHeapIndex\n });\n\n\n var startNode = pool.createNewState(from);\n nodeState.set(fromId, startNode);\n\n // For the first node, fScore is completely heuristic.\n startNode.fScore = heuristic(from, to);\n // The cost of going from start to start is zero.\n startNode.distanceToSource = 0;\n openSetFrom.push(startNode);\n startNode.open = BY_FROM;\n\n var endNode = pool.createNewState(to);\n endNode.fScore = heuristic(to, from);\n endNode.distanceToSource = 0;\n openSetTo.push(endNode);\n endNode.open = BY_TO;\n\n // Cost of the best solution found so far. Used for accurate termination\n var lMin = Number.POSITIVE_INFINITY;\n var minFrom;\n var minTo;\n\n var currentSet = openSetFrom;\n var currentOpener = BY_FROM;\n\n while (openSetFrom.length > 0 && openSetTo.length > 0) {\n if (openSetFrom.length < openSetTo.length) {\n // we pick a set with less elements\n currentOpener = BY_FROM;\n currentSet = openSetFrom;\n } else {\n currentOpener = BY_TO;\n currentSet = openSetTo;\n }\n\n var current = currentSet.pop();\n\n // no need to visit this node anymore\n current.closed = true;\n\n if (current.distanceToSource > lMin) continue;\n\n graph.forEachLinkedNode(current.node.id, callVisitor);\n\n if (minFrom && minTo) {\n // This is not necessary the best path, but we are so greedy that we\n // can't resist:\n return reconstructBiDirectionalPath(minFrom, minTo);\n }\n }\n\n return NO_PATH; // No path.\n\n function nonOrientedVisitor(otherNode, link) {\n return visitNode(otherNode, link, current);\n }\n\n function orientedVisitor(otherNode, link) {\n // For oritned graphs we need to reverse graph, when traveling\n // backwards. So, we use non-oriented ngraph's traversal, and \n // filter link orientation here.\n if (currentOpener === BY_FROM) {\n if (link.fromId === current.node.id) return visitNode(otherNode, link, current)\n } else if (currentOpener === BY_TO) {\n if (link.toId === current.node.id) return visitNode(otherNode, link, current);\n }\n }\n\n function canExit(currentNode) {\n var opener = currentNode.open\n if (opener && opener !== currentOpener) {\n return true;\n }\n\n return false;\n }\n\n function reconstructBiDirectionalPath(a, b) {\n var pathOfNodes = [];\n var aParent = a;\n while(aParent) {\n pathOfNodes.push(aParent.node);\n aParent = aParent.parent;\n }\n var bParent = b;\n while (bParent) {\n pathOfNodes.unshift(bParent.node);\n bParent = bParent.parent\n }\n return pathOfNodes;\n }\n\n function visitNode(otherNode, link, cameFrom) {\n var otherSearchState = nodeState.get(otherNode.id);\n if (!otherSearchState) {\n otherSearchState = pool.createNewState(otherNode);\n nodeState.set(otherNode.id, otherSearchState);\n }\n\n if (otherSearchState.closed) {\n // Already processed this node.\n return;\n }\n\n if (blocked(otherSearchState.node, cameFrom.node, link)) {\n // Path is blocked. Ignore this route\n return;\n }\n\n if (canExit(otherSearchState, cameFrom)) {\n // this node was opened by alternative opener. The sets intersect now,\n // we found an optimal path, that goes through *this* node. However, there\n // is no guarantee that this is the global optimal solution path.\n\n var potentialLMin = otherSearchState.distanceToSource + cameFrom.distanceToSource;\n if (potentialLMin < lMin) {\n minFrom = otherSearchState;\n minTo = cameFrom\n lMin = potentialLMin;\n }\n // we are done with this node.\n return;\n }\n\n var tentativeDistance = cameFrom.distanceToSource + distance(otherSearchState.node, cameFrom.node, link);\n\n if (tentativeDistance >= otherSearchState.distanceToSource) {\n // This would only make our path longer. Ignore this route.\n return;\n }\n\n // Choose target based on current working set:\n var target = (currentOpener === BY_FROM) ? to : from;\n var newFScore = tentativeDistance + heuristic(otherSearchState.node, target);\n if (newFScore >= lMin) {\n // this can't be optimal path, as we have already found a shorter path.\n return;\n }\n otherSearchState.fScore = newFScore;\n\n if (otherSearchState.open === 0) {\n // Remember this node in the current set\n currentSet.push(otherSearchState);\n currentSet.updateItem(otherSearchState.heapIndex);\n\n otherSearchState.open = currentOpener;\n }\n\n // bingo! we found shorter path:\n otherSearchState.parent = cameFrom;\n otherSearchState.distanceToSource = tentativeDistance;\n }\n }\n}\n\naStarBi.l2 = heuristics.l2;\naStarBi.l1 = heuristics.l1;\n\nexport default aStarBi;\n","/**\n * Creates new instance of NBASearchState. The instance stores information\n * about search state, and is used by NBA* algorithm.\n *\n * @param {Object} node - original graph node\n */\nfunction NBASearchState(node) {\n /**\n * Original graph node.\n */\n this.node = node;\n\n /**\n * Parent of this node in forward search\n */\n this.p1 = null;\n\n /**\n * Parent of this node in reverse search\n */\n this.p2 = null;\n\n /**\n * If this is set to true, then the node was already processed\n * and we should not touch it anymore.\n */\n this.closed = false;\n\n /**\n * Actual distance from this node to its parent in forward search\n */\n this.g1 = Number.POSITIVE_INFINITY;\n\n /**\n * Actual distance from this node to its parent in reverse search\n */\n this.g2 = Number.POSITIVE_INFINITY;\n\n\n /**\n * Underestimated distance from this node to the path-finding source.\n */\n this.f1 = Number.POSITIVE_INFINITY;\n\n /**\n * Underestimated distance from this node to the path-finding target.\n */\n this.f2 = Number.POSITIVE_INFINITY;\n\n // used to reconstruct heap when fScore is updated. TODO: do I need them both?\n\n /**\n * Index of this node in the forward heap.\n */\n this.h1 = -1;\n\n /**\n * Index of this node in the reverse heap.\n */\n this.h2 = -1;\n}\n\n/**\n * As path-finding is memory-intensive process, we want to reduce pressure on\n * garbage collector. This class helps us to recycle path-finding nodes and significantly\n * reduces the search time (~20% faster than without it).\n */\nexport default function makeNBASearchStatePool() {\n var currentInCache = 0;\n var nodeCache = [];\n\n return {\n /**\n * Creates a new NBASearchState instance\n */\n createNewState: createNewState,\n\n /**\n * Marks all created instances available for recycling.\n */\n reset: reset\n };\n\n function reset() {\n currentInCache = 0;\n }\n\n function createNewState(node) {\n var cached = nodeCache[currentInCache];\n if (cached) {\n // TODO: This almost duplicates constructor code. Not sure if\n // it would impact performance if I move this code into a function\n cached.node = node;\n\n // How we came to this node?\n cached.p1 = null;\n cached.p2 = null;\n\n cached.closed = false;\n\n cached.g1 = Number.POSITIVE_INFINITY;\n cached.g2 = Number.POSITIVE_INFINITY;\n cached.f1 = Number.POSITIVE_INFINITY;\n cached.f2 = Number.POSITIVE_INFINITY;\n\n // used to reconstruct heap when fScore is updated.\n cached.h1 = -1;\n cached.h2 = -1;\n } else {\n cached = new NBASearchState(node);\n nodeCache[currentInCache] = cached;\n }\n currentInCache++;\n return cached;\n }\n}\n","import NodeHeap from '../NodeHeap.js';\nimport * as heuristics from '../heuristics.js';\nimport defaultSettings from '../defaultSettings.js';\nimport makeNBASearchStatePool from './makeNBASearchStatePool.js';\n\nvar NO_PATH = defaultSettings.NO_PATH;\n\n/**\n * Creates a new instance of pathfinder. A pathfinder has just one method:\n * `find(fromId, toId)`.\n * \n * This is implementation of the NBA* algorithm described in \n * \n * \"Yet another bidirectional algorithm for shortest paths\" paper by Wim Pijls and Henk Post\n * \n * The paper is available here: https://repub.eur.nl/pub/16100/ei2009-10.pdf\n * \n * @param {ngraph.graph} graph instance. See https://github.com/anvaka/ngraph.graph\n * @param {Object} options that configures search\n * @param {Function(a, b, link)} options.blocked - a function that returns `true` if the link between \n * nodes `a` and `b` are blocked paths. This function is useful for temporarily blocking routes \n * while allowing the graph to be reused without rebuilding.\n * @param {Function(a, b)} options.heuristic - a function that returns estimated distance between\n * nodes `a` and `b`. This function should never overestimate actual distance between two\n * nodes (otherwise the found path will not be the shortest). Defaults function returns 0,\n * which makes this search equivalent to Dijkstra search.\n * @param {Function(a, b)} options.distance - a function that returns actual distance between two\n * nodes `a` and `b`. By default this is set to return graph-theoretical distance (always 1);\n * \n * @returns {Object} A pathfinder with single method `find()`.\n */\nfunction nba(graph, options) {\n options = options || {};\n // whether traversal should be considered over oriented graph.\n var oriented = options.oriented;\n var quitFast = options.quitFast;\n\n var blocked = options.blocked;\n if (!blocked) blocked = defaultSettings.blocked;\n\n var heuristic = options.heuristic;\n if (!heuristic) heuristic = defaultSettings.heuristic;\n\n var distance = options.distance;\n if (!distance) distance = defaultSettings.distance;\n\n // During stress tests I noticed that garbage collection was one of the heaviest\n // contributors to the algorithm's speed. So I'm using an object pool to recycle nodes.\n var pool = makeNBASearchStatePool();\n\n return {\n /**\n * Finds a path between node `fromId` and `toId`.\n * @returns {Array} of nodes between `toId` and `fromId`. Empty array is returned\n * if no path is found.\n */\n find: find\n };\n\n function find(fromId, toId) {\n // I must apologize for the code duplication. This was the easiest way for me to\n // implement the algorithm fast.\n var from = graph.getNode(fromId);\n if (!from) throw new Error('fromId is not defined in this graph: ' + fromId);\n var to = graph.getNode(toId);\n if (!to) throw new Error('toId is not defined in this graph: ' + toId);\n\n pool.reset();\n\n // I must also apologize for somewhat cryptic names. The NBA* is bi-directional\n // search algorithm, which means it runs two searches in parallel. One is called\n // forward search and it runs from source node to target, while the other one\n // (backward search) runs from target to source.\n\n // Everywhere where you see `1` it means it's for the forward search. `2` is for \n // backward search.\n\n // For oriented graph path finding, we need to reverse the graph, so that\n // backward search visits correct link. Obviously we don't want to duplicate\n // the graph, instead we always traverse the graph as non-oriented, and filter\n // edges in `visitN1Oriented/visitN2Oritented`\n var forwardVisitor = oriented ? visitN1Oriented : visitN1;\n var reverseVisitor = oriented ? visitN2Oriented : visitN2;\n\n // Maps nodeId to NBASearchState.\n var nodeState = new Map();\n\n // These two heaps store nodes by their underestimated values.\n var open1Set = new NodeHeap({\n compare: defaultSettings.compareF1Score,\n setNodeId: defaultSettings.setH1\n });\n var open2Set = new NodeHeap({\n compare: defaultSettings.compareF2Score,\n setNodeId: defaultSettings.setH2\n });\n\n // This is where both searches will meet.\n var minNode;\n\n // The smallest path length seen so far is stored here:\n var lMin = Number.POSITIVE_INFINITY;\n\n // We start by putting start/end nodes to the corresponding heaps\n // If variable names like `f1`, `g1` are too confusing, please refer\n // to makeNBASearchStatePool.js file, which has detailed description.\n var startNode = pool.createNewState(from);\n nodeState.set(fromId, startNode); \n startNode.g1 = 0;\n var f1 = heuristic(from, to);\n startNode.f1 = f1;\n open1Set.push(startNode);\n\n var endNode = pool.createNewState(to);\n nodeState.set(toId, endNode);\n endNode.g2 = 0;\n var f2 = f1; // they should agree originally\n endNode.f2 = f2;\n open2Set.push(endNode)\n\n // the `cameFrom` variable is accessed by both searches, so that we can store parents.\n var cameFrom;\n\n // this is the main algorithm loop:\n while (open2Set.length && open1Set.length) {\n if (open1Set.length < open2Set.length) {\n forwardSearch();\n } else {\n reverseSearch();\n }\n\n if (quitFast && minNode) break;\n }\n\n var path = reconstructPath(minNode);\n return path; // the public API is over\n\n function forwardSearch() {\n cameFrom = open1Set.pop();\n if (cameFrom.closed) {\n return;\n }\n\n cameFrom.closed = true;\n\n if (cameFrom.f1 < lMin && (cameFrom.g1 + f2 - heuristic(from, cameFrom.node)) < lMin) {\n graph.forEachLinkedNode(cameFrom.node.id, forwardVisitor);\n }\n\n if (open1Set.length > 0) {\n // this will be used in reverse search\n f1 = open1Set.peek().f1;\n } \n }\n\n function reverseSearch() {\n cameFrom = open2Set.pop();\n if (cameFrom.closed) {\n return;\n }\n cameFrom.closed = true;\n\n if (cameFrom.f2 < lMin && (cameFrom.g2 + f1 - heuristic(cameFrom.node, to)) < lMin) {\n graph.forEachLinkedNode(cameFrom.node.id, reverseVisitor);\n }\n\n if (open2Set.length > 0) {\n // this will be used in forward search\n f2 = open2Set.peek().f2;\n }\n }\n\n function visitN1(otherNode, link) {\n var otherSearchState = nodeState.get(otherNode.id);\n if (!otherSearchState) {\n otherSearchState = pool.createNewState(otherNode);\n nodeState.set(otherNode.id, otherSearchState);\n }\n\n if (otherSearchState.closed) return;\n\n if (blocked(cameFrom.node, otherNode, link)) return;\n\n var tentativeDistance = cameFrom.g1 + distance(cameFrom.node, otherNode, link);\n\n if (tentativeDistance < otherSearchState.g1) {\n otherSearchState.g1 = tentativeDistance;\n otherSearchState.f1 = tentativeDistance + heuristic(otherSearchState.node, to);\n otherSearchState.p1 = cameFrom;\n if (otherSearchState.h1 < 0) {\n open1Set.push(otherSearchState);\n } else {\n open1Set.updateItem(otherSearchState.h1);\n }\n }\n var potentialMin = otherSearchState.g1 + otherSearchState.g2;\n if (potentialMin < lMin) { \n lMin = potentialMin;\n minNode = otherSearchState;\n }\n }\n\n function visitN2(otherNode, link) {\n var otherSearchState = nodeState.get(otherNode.id);\n if (!otherSearchState) {\n otherSearchState = pool.createNewState(otherNode);\n nodeState.set(otherNode.id, otherSearchState);\n }\n\n if (otherSearchState.closed) return;\n\n if (blocked(cameFrom.node, otherNode, link)) return;\n\n var tentativeDistance = cameFrom.g2 + distance(cameFrom.node, otherNode, link);\n\n if (tentativeDistance < otherSearchState.g2) {\n otherSearchState.g2 = tentativeDistance;\n otherSearchState.f2 = tentativeDistance + heuristic(from, otherSearchState.node);\n otherSearchState.p2 = cameFrom;\n if (otherSearchState.h2 < 0) {\n open2Set.push(otherSearchState);\n } else {\n open2Set.updateItem(otherSearchState.h2);\n }\n }\n var potentialMin = otherSearchState.g1 + otherSearchState.g2;\n if (potentialMin < lMin) {\n lMin = potentialMin;\n minNode = otherSearchState;\n }\n }\n\n function visitN2Oriented(otherNode, link) {\n // we are going backwards, graph needs to be reversed. \n if (link.toId === cameFrom.node.id) return visitN2(otherNode, link);\n }\n function visitN1Oriented(otherNode, link) {\n // this is forward direction, so we should be coming FROM:\n if (link.fromId === cameFrom.node.id) return visitN1(otherNode, link);\n }\n }\n}\n\nnba.l2 = heuristics.l2;\nnba.l1 = heuristics.l1;\n\nexport default nba;\n\nfunction reconstructPath(searchState) {\n if (!searchState) return NO_PATH;\n\n var path = [searchState.node];\n var parent = searchState.p1;\n\n while (parent) {\n path.push(parent.node);\n parent = parent.p1;\n }\n\n var child = searchState.p2;\n\n while (child) {\n path.unshift(child.node);\n child = child.p2;\n }\n return path;\n}\n","import aStar from './a-star/a-star.js';\nimport aGreedy from './a-star/a-greedy-star.js';\nimport nba from './a-star/nba/index.js';\n\nconst pathFinders = {\n aStar,\n aGreedy,\n nba,\n};\n\nexport { aStar, aGreedy, nba };\nexport default pathFinders;\n"],"names":["NodeHeap","data","options","defaultCompare","noop","i","a","b","item","top","pos","compare","setNodeId","parent","current","halfLength","left","right","best","NodeSearchState","node","makeSearchStatePool","currentInCache","nodeCache","createNewState","reset","cached","l2","dx","dy","l1","NO_PATH","defaultSettings","blindHeuristic","constantDistance","neverBlocked","compareFScore","setHeapIndex","setH1","setH2","compareF1Score","compareF2Score","result","nodeSearchState","heapIndex","aStarPathSearch","graph","oriented","blocked","heuristic","distance","pool","find","fromId","toId","from","to","nodeState","openSet","startNode","cameFrom","goalReached","reconstructPath","visitNeighbour","otherNode","link","otherSearchState","tentativeDistance","heuristics.l2","heuristics.l1","searchState","targetNode","path","BY_FROM","BY_TO","aStarBi","callVisitor","orientedVisitor","nonOrientedVisitor","openSetFrom","openSetTo","endNode","lMin","minFrom","minTo","currentSet","currentOpener","reconstructBiDirectionalPath","visitNode","canExit","currentNode","opener","pathOfNodes","aParent","bParent","potentialLMin","target","newFScore","NBASearchState","makeNBASearchStatePool","nba","quitFast","forwardVisitor","visitN1Oriented","visitN1","reverseVisitor","visitN2Oriented","visitN2","open1Set","open2Set","minNode","f1","f2","forwardSearch","reverseSearch","potentialMin","child","pathFinders","aStar","aGreedy"],"mappings":"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"} |