-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdijkstra.rb
executable file
·69 lines (57 loc) · 1.46 KB
/
dijkstra.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
require_relative "priority_queue"
class Dijkstra
def initialize(graph, source_node)
@graph = graph
@source_node = source_node
@path_to = {}
@distance_to = {}
@pq = PriorityQueue.new
if $verbose
puts ""
if $jruby
@progress = ProgressBar.create(:title => "Solving the Maze", :total => @graph.edges.count)
else
@progress = ProgressBar.create(:title => "Solving the Maze", :total => @graph.edges.count, format: 'Progress %c %C |%b>%i| %a %e')
end
end
compute_shortest_path
end
def shortest_path_to(node)
path = []
while node != @source_node
path.unshift(node)
node = @path_to[node]
end
path.unshift(@source_node)
end
private
def compute_shortest_path
update_distance_of_all_edges_to(Float::INFINITY)
@distance_to[@source_node] = 0
@pq.insert(@source_node, 0)
while @pq.any?
if $verbose
if @progress.finished?
@progress.stop
else
@progress.increment
end
end
node = @pq.remove_min
node.adjacent_edges.each do |adj_edge|
relax(adj_edge)
end
end
end
def update_distance_of_all_edges_to(distance)
@graph.nodes.each do |node|
@distance_to[node] = distance
end
end
def relax(edge)
return if @distance_to[edge.to] <= @distance_to[edge.from] + edge.weight
@distance_to[edge.to] = @distance_to[edge.from] + edge.weight
@path_to[edge.to] = edge.from
@pq.insert(edge.to, @distance_to[edge.to])
end
end