Passed
Push — master ( 38602d...192324 )
by Xianshun
01:33
created

DijkstraShortestPath.__init__()   B

Complexity

Conditions 6

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
c 1
b 0
f 0
dl 0
loc 24
rs 7.6129
1
from abc import ABCMeta, abstractmethod
2
3
from pyalgs.algorithms.commons import util
4
from pyalgs.data_structures.commons.priority_queue import IndexMinPQ
5
from pyalgs.data_structures.commons.stack import Stack
6
from pyalgs.data_structures.graphs.graph import Digraph, Graph, EdgeWeightedGraph
7
8
9
class ShortestPath(object):
10
    __metaclass__ = ABCMeta
11
12
    @abstractmethod
13
    def shortestPathTo(self, v):
14
        pass
15
16
    @abstractmethod
17
    def hasPathTo(self, v):
18
        pass
19
20
21
class DijkstraShortestPath(ShortestPath):
22
23
    edgeTo = None
24
    s = 0
25
    pq = None
26
    cost = None
27
28
    def __init__(self, G, s):
29
        if isinstance(G, Graph):
30
            raise ValueError('Graph must be edge weighted')
31
        if isinstance(G, Digraph):
32
            raise ValueError('Graph must be edge weighted')
33
        if isinstance(G, EdgeWeightedGraph):
34
            G = G.to_edge_weighted_digraph()
35
36
        vertex_count = G.vertex_count()
37
        self.pq = IndexMinPQ(vertex_count)
38
        self.s = s
39
40
        self.marked = [False] * vertex_count
41
        self.edgeTo = [None] * vertex_count
42
        self.cost = [float("inf")] * vertex_count
43
44
        self.cost[s] = 0
45
        self.pq.insert(s, 0.0)
46
47
        while not self.pq.is_empty():
48
            v = self.pq.del_min()
49
            self.marked[v] = True
50
            for e in G.adj(v):
51
                self.relax(e)
52
53
    def relax(self, e):
54
        v = e.start()
55
        w = e.end()
56
        if self.cost[w] > self.cost[v] + e.weight:
57
            self.cost[w] = self.cost[v] + e.weight
58
            self.edgeTo[w] = e
59
            if self.pq.contains_index(w):
60
                self.pq.decrease_key(w, self.cost[w])
61
            else:
62
                self.pq.insert(w, self.cost[w])
63
64
    def hasPathTo(self, v):
65
        return self.marked[v]
66
67
    def shortestPathTo(self, v):
68
        path = Stack.create()
69
        x = v
70
        while x != self.s:
71
            path.push(self.edgeTo[x])
72
            x = self.edgeTo[x].start()
73
74
        return path.iterate()
75
76
    def path_length_to(self, v):
77
        return self.cost[v]
78