Skip to content

Commit 8cdd475

Browse files
authored
Merge pull request #74 from PraneethJain/bidirectional
Added bi-directional Best First and Dijkstra
2 parents 4904e24 + c5b2318 commit 8cdd475

File tree

4 files changed

+93
-4
lines changed

4 files changed

+93
-4
lines changed

pathfinding/finder/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
__all__ = ['a_star', 'best_first', 'bi_a_star', 'bi_breadth_first',
2-
'breadth_first', 'dijkstra', 'finder', 'ida_star']
2+
'bi_best_first', 'bi_dijkstra', 'breadth_first', 'dijkstra',
3+
'finder', 'ida_star']
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from .bi_a_star import BiAStarFinder
2+
from ..core.diagonal_movement import DiagonalMovement
3+
from .finder import TIME_LIMIT, MAX_RUNS
4+
5+
6+
class BiBestFirstFinder(BiAStarFinder):
7+
"""
8+
Bi-directional Best-First-Search algorithm.
9+
It is essentially the same as bi-directional A* but with a high weight
10+
on the heuristic, making it a greedy search.
11+
"""
12+
13+
def __init__(
14+
self,
15+
heuristic=None,
16+
weight=1,
17+
diagonal_movement=DiagonalMovement.never,
18+
time_limit=TIME_LIMIT,
19+
max_runs=MAX_RUNS,
20+
):
21+
"""
22+
:param heuristic: heuristic used to calculate distance of 2 points
23+
(defaults to manhattan)
24+
:param weight: weight for the edges
25+
:param diagonal_movement: if diagonal movement is allowed
26+
(see enum in diagonal_movement)
27+
:param time_limit: max. runtime in seconds
28+
:param max_runs: max. amount of tries until we abort the search
29+
"""
30+
super(BiBestFirstFinder, self).__init__(
31+
heuristic=heuristic,
32+
weight=weight,
33+
diagonal_movement=diagonal_movement,
34+
time_limit=time_limit,
35+
max_runs=max_runs,
36+
)
37+
38+
self.weighted = False
39+
40+
def apply_heuristic(self, node_a, node_b, heuristic=None, graph=None):
41+
return (
42+
super(BiBestFirstFinder, self).apply_heuristic(
43+
node_a, node_b, heuristic, graph=graph
44+
)
45+
* 1000000
46+
)

pathfinding/finder/bi_dijkstra.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from .bi_a_star import BiAStarFinder
2+
from ..core.diagonal_movement import DiagonalMovement
3+
from .finder import TIME_LIMIT, MAX_RUNS
4+
from ..core.heuristic import null
5+
6+
7+
class BiDijkstraFinder(BiAStarFinder):
8+
"""
9+
Bi-directional Dijkstra's algorithm.
10+
11+
It is similar to bi-directional A* but with a heuristic of zero.
12+
This means the search expands purely based on the lowest cost from the
13+
start and end points.
14+
"""
15+
16+
def __init__(
17+
self,
18+
weight=1,
19+
diagonal_movement=DiagonalMovement.never,
20+
time_limit=TIME_LIMIT,
21+
max_runs=MAX_RUNS,
22+
):
23+
"""
24+
:param weight: weight for the edges
25+
:param diagonal_movement: if diagonal movement is allowed
26+
(see enum in diagonal_movement)
27+
:param time_limit: max. runtime in seconds
28+
:param max_runs: max. amount of tries until we abort the search
29+
"""
30+
super(BiDijkstraFinder, self).__init__(
31+
heuristic=null,
32+
weight=weight,
33+
diagonal_movement=diagonal_movement,
34+
time_limit=time_limit,
35+
max_runs=max_runs,
36+
)
37+
38+
def apply_heuristic(self, node_a, node_b, heuristic=None, graph=None):
39+
return 0

test/test_path.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
from pathfinding.finder.a_star import AStarFinder
77
from pathfinding.finder.best_first import BestFirst
88
from pathfinding.finder.bi_a_star import BiAStarFinder
9+
from pathfinding.finder.bi_breadth_first import BiBreadthFirstFinder
10+
from pathfinding.finder.bi_best_first import BiBestFirstFinder
11+
from pathfinding.finder.bi_dijkstra import BiDijkstraFinder
912
from pathfinding.finder.breadth_first import BreadthFirstFinder
1013
from pathfinding.finder.dijkstra import DijkstraFinder
1114
from pathfinding.finder.finder import ExecutionRunsException
1215
from pathfinding.finder.finder import ExecutionTimeException
1316
from pathfinding.finder.ida_star import IDAStarFinder
1417
from pathfinding.finder.msp import MinimumSpanningTree
15-
from pathfinding.finder.bi_breadth_first import BiBreadthFirstFinder
1618

1719
import pytest
1820

@@ -22,8 +24,9 @@
2224
# test scenarios from Pathfinding.JS
2325
scenarios = os.path.join(BASE_PATH, 'path_test_scenarios.json')
2426
data = json.load(open(scenarios, 'r', encoding='utf-8'))
25-
finders = [AStarFinder, BestFirst, BiAStarFinder, BiBreadthFirstFinder,
26-
DijkstraFinder, IDAStarFinder, BreadthFirstFinder, MinimumSpanningTree]
27+
finders = [AStarFinder, BestFirst, BiAStarFinder, BiBreadthFirstFinder,
28+
BiBestFirstFinder, BiDijkstraFinder, DijkstraFinder, IDAStarFinder,
29+
BreadthFirstFinder, MinimumSpanningTree]
2730
TIME_LIMIT = 10 # give it a 10 second limit.
2831

2932

0 commit comments

Comments
 (0)