Skip to content

Commit e2a2d71

Browse files
djikstra tests added
1 parent eebd306 commit e2a2d71

File tree

8 files changed

+166
-37
lines changed

8 files changed

+166
-37
lines changed

.travis.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ script:
2222
# Graph Theory Tests
2323
- python Algorithm_tests/graphtheory_tests/bellman_ford_test.py
2424
- python Algorithm_tests/graphtheory_tests/kahn_topological_ordering_test.py
25+
- python Algorithm_tests/graphtheory_tests/Djikstra/djikstra_heap_test.py
26+
- python Algorithm_tests/graphtheory_tests/Djikstra/djikstra_naive_test.py
2527

2628
# Math tests
2729
- python Algorithm_tests/other_tests/test_binarysearch.py
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Import folder where sorting algorithms
2+
import sys
3+
import unittest
4+
5+
# For importing from different folders
6+
# OBS: This is supposed to be done with automated testing, hence relative to folder we want to import from
7+
sys.path.append('Algorithms/graphtheory/dijkstra/')
8+
9+
# If run from local:
10+
#sys.path.append('../../../Algorithms/graphtheory/dijkstra/')
11+
12+
from heapdijkstra import dijkstra
13+
14+
class test_Dijkstra(unittest.TestCase):
15+
def setUp(self):
16+
self.G1 = {}
17+
self.correct_path1 = []
18+
self.correct_dist1 = float("inf")
19+
20+
self.G2 = {1:{2:1, 4:10}, 2:{3:15}, 3:{6:5}, 4:{5:1}, 5:{6:1}, 6: {}}
21+
self.correct_path2 = [1,4,5,6]
22+
self.correct_dist2 = 12
23+
24+
self.G3 = {1: {2: 1, 4: 10}, 2: {3: 15}, 3: {}, 4: {5:1}, 5: {}, 6: {}}
25+
self.correct_path3 = []
26+
self.correct_dist3 = float("inf")
27+
28+
self.G4 = {1: {2: 1, 4: 10}, 2: {3: 15}, 3: {6: 5}, 4: {5: 1}, 5: {6: 1}, 6: {}}
29+
self.correct_path4 = [1, 4, 5]
30+
self.correct_dist4 = 11
31+
32+
def test_emptygraph(self):
33+
path_to_take, distances = dijkstra(self.G1, 0, 1)
34+
self.assertEqual(distances[1], self.correct_dist1)
35+
self.assertEqual(path_to_take, self.correct_path1)
36+
37+
def test_simplegraph(self):
38+
path_to_take, distances = dijkstra(self.G2, 1, 6)
39+
self.assertEqual(distances[6], self.correct_dist2)
40+
self.assertEqual(path_to_take, self.correct_path2)
41+
42+
def test_no_path_exists(self):
43+
path_to_take, distances = dijkstra(self.G3, 1, 6)
44+
self.assertEqual(distances[6], self.correct_dist3)
45+
self.assertEqual(path_to_take, self.correct_path3)
46+
47+
def test_not_endpoint(self):
48+
path_to_take, distances = dijkstra(self.G4, 1, 5)
49+
self.assertEqual(distances[5], self.correct_dist4)
50+
self.assertEqual(path_to_take, self.correct_path4)
51+
52+
if __name__ == '__main__':
53+
print("Running Djikstra tests:")
54+
unittest.main()
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Import folder where sorting algorithms
2+
import sys
3+
import unittest
4+
5+
# For importing from different folders
6+
# OBS: This is supposed to be done with automated testing, hence relative to folder we want to import from
7+
sys.path.append('Algorithms/graphtheory/dijkstra/')
8+
9+
# If run from local:
10+
#sys.path.append('../../../Algorithms/graphtheory/dijkstra/')
11+
12+
from dijkstra import dijkstra
13+
14+
class test_Dijkstra(unittest.TestCase):
15+
def setUp(self):
16+
self.G1 = {}
17+
self.correct_path1 = []
18+
self.correct_dist1 = float("inf")
19+
20+
self.G2 = {1:{2:1, 4:10}, 2:{3:15}, 3:{6:5}, 4:{5:1}, 5:{6:1}, 6: {}}
21+
self.correct_path2 = [1,4,5,6]
22+
self.correct_dist2 = 12
23+
24+
self.G3 = {1: {2: 1, 4: 10}, 2: {3: 15}, 3: {}, 4: {5:1}, 5: {}, 6: {}}
25+
self.correct_path3 = []
26+
self.correct_dist3 = float("inf")
27+
28+
self.G4 = {1: {2: 1, 4: 10}, 2: {3: 15}, 3: {6: 5}, 4: {5: 1}, 5: {6: 1}, 6: {}}
29+
self.correct_path4 = [1, 4, 5]
30+
self.correct_dist4 = 11
31+
32+
def test_emptygraph(self):
33+
path_to_take, distance = dijkstra(self.G1, 0, 1)
34+
self.assertEqual(distance, self.correct_dist1)
35+
self.assertEqual(path_to_take, self.correct_path1)
36+
37+
def test_simplegraph(self):
38+
path_to_take, distance = dijkstra(self.G2, 1, 6)
39+
self.assertEqual(distance, self.correct_dist2)
40+
self.assertEqual(path_to_take, self.correct_path2)
41+
42+
def test_no_path_exists(self):
43+
path_to_take, distance = dijkstra(self.G3, 1, 6)
44+
self.assertEqual(distance, self.correct_dist3)
45+
self.assertEqual(path_to_take, self.correct_path3)
46+
47+
def test_not_endpoint(self):
48+
path_to_take, distance = dijkstra(self.G4, 1, 5)
49+
self.assertEqual(distance, self.correct_dist4)
50+
self.assertEqual(path_to_take, self.correct_path4)
51+
52+
53+
if __name__ == '__main__':
54+
print("Running Djikstra tests:")
55+
unittest.main()
Binary file not shown.
Binary file not shown.
Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
# Dijkstra's algorithm for finding the shortest path in a graph
2-
# Programmed 2019-01-28 <aladdin.persson at hotmail dot com>
1+
'''
2+
Dijkstra's algorithm for finding the shortest path in a graph
3+
4+
Programmed by Aladdin Persson <aladdin.persson at hotmail dot com>
5+
2019-01-28 Initial programming
6+
2020-03-28 Cleaned up code
7+
'''
38

49
def make_graph(file):
510
try:
@@ -9,16 +14,16 @@ def make_graph(file):
914

1015
line_list = f.readlines()
1116

12-
# Found on mukeshmithrakumar github, thought this was clean..
13-
# populate the graph using data from the text file via dictionary comprehensions
1417
G = {int(line.split()[0]): {(int(tup.split(',')[0])): int(tup.split(',')[1])
1518
for tup in line.split()[1:] if tup} for line in line_list if line}
1619

1720
f.close()
1821
return G
1922

20-
2123
def dijkstra(G, start, end):
24+
if start not in G or end not in G:
25+
return [], float('inf')
26+
2227
shortest_distance = {}
2328
predecessor = {}
2429
unseenNodes = G
@@ -34,7 +39,6 @@ def dijkstra(G, start, end):
3439
while unseenNodes:
3540
minNode = None
3641

37-
# priority-queue? -> Hittar bästa noden hittils
3842
for node in unseenNodes:
3943
if minNode is None:
4044
minNode = node
@@ -49,32 +53,32 @@ def dijkstra(G, start, end):
4953

5054
unseenNodes.pop(minNode)
5155

52-
print("pred")
53-
print(predecessor)
56+
# Find path from start node s to end node t
5457
currentNode = end
5558

5659
while currentNode != start:
5760
try:
5861
path.insert(0, currentNode)
5962
currentNode = predecessor[currentNode]
6063
except KeyError:
61-
print('Path not reachable')
62-
break
64+
return [], float('inf')
65+
6366
path.insert(0,start)
6467

65-
return path, shortest_distance[end]
6668

69+
return path, shortest_distance[end]
6770

6871

72+
if __name__ == '__main__':
73+
#G = make_graph('dijkstraData.txt')
6974

70-
#G = make_graph('dijkstraData.txt')
75+
G = {1:{2:10, 3:20},
76+
2:{4:40},
77+
3:{4:5},
78+
4:{}}
7179

72-
G = {1:{2:10, 3:20},
73-
2:{4:40},
74-
3:{4:5},
75-
4:{}}
76-
print(f'Current graph is: {G}')
77-
path, shortest = dijkstra(G, 1, 4)
80+
print(f'Current graph is: {G}')
81+
path, shortest = dijkstra(G, 1, 4)
7882

79-
print(path)
80-
print(shortest)
83+
print(path)
84+
print(shortest)

Algorithms/graphtheory/dijkstra/heapdijkstra.py

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
# Dijkstra's algorithm for finding the shortest path.
2-
# Improved version with the usage of heaps.
1+
'''
2+
Dijkstra's algorithm for finding the shortest path.
3+
Improved version with the usage of heaps.
34
4-
# Programmed by Aladdin Persson <aladdin.persson at hotmail dot com>
5-
# 2019-02-15 Initial coding
5+
Programmed by Aladdin Persson <aladdin.persson at hotmail dot com>
6+
2019-02-15 Initial coding
7+
2020-03-28 Small code changes, fixed for edge cases not covered
8+
9+
'''
610

711
import heapq
812

@@ -14,14 +18,16 @@ def make_graph(file):
1418

1519
line_list = f.readlines()
1620

17-
# Kinda messy.
18-
# populate the graph using data from the text file via dictionary comprehensions
21+
# Kinda messy graph loading
1922
G = {int(line.split()[0]): {(int(tup.split(',')[0])): int(tup.split(',')[1])
2023
for tup in line.split()[1:] if tup} for line in line_list if line}
2124
f.close()
2225
return G
2326

2427
def dijkstra(G, start, end=None):
28+
if start not in G or (end != None and end not in G):
29+
return [], {end:float('inf')}
30+
2531
distance, visited, history, heap, path = {}, {}, {}, [], []
2632

2733
for node in G.keys():
@@ -48,19 +54,27 @@ def dijkstra(G, start, end=None):
4854
try:
4955
path.insert(0, current_node)
5056
current_node = history[current_node]
57+
5158
except KeyError:
52-
print('Path not reachable')
53-
break
59+
return [], distance
5460

5561
path.insert(0, start)
5662

57-
return distance, path
63+
return path, distance
5864

5965

6066
if __name__ == '__main__':
61-
start, end = 1, 160
62-
print(f'Goal is to find the path from node {start} to node {end}')
63-
G = make_graph('dijkstraData.txt')
64-
65-
dist, path = dijkstra(G, start, end)
66-
print(f'Path found: {path}')
67+
# start, end = 1, 160
68+
# print(f'Goal is to find the path from node {start} to node {end}')
69+
# G = make_graph('dijkstraData.txt')
70+
71+
G = {1: {2: 10, 3: 20},
72+
2: {4: 40},
73+
3: {4: 5},
74+
4: {}}
75+
start=1
76+
end=2
77+
78+
path, dist = dijkstra(G, start, end)
79+
print(f'Path found: {path}')
80+
print(dist)

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ Whenever I face an interesting problem I document the algorithm that I learned t
1515
* :white_check_mark: [Kahns Topological Sort](https://github.com/AladdinPerzon/Algorithms-Collection-Python/blob/master/Algorithms/graphtheory/kahns-toposort/kahns.py) **- O(n + m)**
1616
* :white_check_mark: [Bellman-Ford Shortest Path](https://github.com/AladdinPerzon/Algorithms-Collection-Python/blob/master/Algorithms/graphtheory/bellman-ford/bellman_ford.py) **-O(mn)**
1717
* :small_red_triangle: [Floyd-Warshall Shortest Path](https://github.com/AladdinPerzon/Algorithms-Collection-Python/blob/master/Algorithms/graphtheory/floyd-warshall/floyd-warshall.py) **- O(n<sup>3</sup>)**
18-
* :small_red_triangle: [Dijkstra Shortest Path](https://github.com/AladdinPerzon/Algorithms-Collection-Python/blob/master/Algorithms/graphtheory/dijkstra/djikstra.py) **- Naive implementation**
19-
* :small_red_triangle: [Dijkstra Shortest Path](https://github.com/AladdinPerzon/Algorithms-Collection-Python/blob/master/Algorithms/graphtheory/dijkstra/heapdijkstra.py) **O(mlog(n)) - Heap implementation**
18+
* :white_check_mark: [Dijkstra Shortest Path](https://github.com/AladdinPerzon/Algorithms-Collection-Python/blob/master/Algorithms/graphtheory/dijkstra/djikstra.py) **- Naive implementation**
19+
* :white_check_mark: [Dijkstra Shortest Path](https://github.com/AladdinPerzon/Algorithms-Collection-Python/blob/master/Algorithms/graphtheory/dijkstra/heapdijkstra.py) **O(mlog(n)) - Heap implementation**
2020
* :small_red_triangle: [Karger's Minimum cut](https://github.com/AladdinPerzon/Algorithms-Collection-Python/blob/master/Algorithms/graphtheory/kargers/kargermincut.py)
2121
* :small_red_triangle: [Prim's Algorithm](https://github.com/AladdinPerzon/Algorithms-Collection-Python/blob/master/Algorithms/graphtheory/prims/prims_algorithm.py) **- Naive implementation**
2222
* :small_red_triangle: [Prim's Algorithm](https://github.com/AladdinPerzon/Algorithms-Collection-Python/blob/master/Algorithms/graphtheory/prims/primheap.py) **- mlog(n)**

0 commit comments

Comments
 (0)