dijkstra_graph 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 40d8dfafa22964edb55043f62194663df6ffe708
4
- data.tar.gz: 7c76517bd99090caca0eb6bafb488c147851391f
3
+ metadata.gz: d771e3085a0ffda14a30fc7fa92cf8e69208e984
4
+ data.tar.gz: 315da882ae3971d9c9a92e92755812074b5d4f3c
5
5
  SHA512:
6
- metadata.gz: 06cd0b89391979779f79bca07e34d8ea6e4917249d9d7d3a748f9c7843859e7b83acf6d6d248cc405e6a9683f3d3fbd5cbafb9283c4d5b8b626c483adf99cecf
7
- data.tar.gz: 610fce885958f2aa28ae069448368fb080df6a24f74ab265d955b2d4739e4c281ea83bb5e13df4ca877c673979b7ed1bccba276c0fb08ce4517c9ac4092a2bbd
6
+ metadata.gz: 5b0ceec8d23b964237a72e57ddcf3697300dbf755910a5ba3a459e36a0860e7cdd5818a2f8eeb8cef34bd3185b45cd9ca0aad47c145d29c1bd761cbf01b096c9
7
+ data.tar.gz: 5917752b4b7fefdf63a149b6d70c2d4e7134b21de7621d0bfc49e8992e017eb23a1423f75ae47d6c3ee27021b487a3e76b79bfda3d866dc5fac4d92b7f9df0bc
@@ -1,4 +1,4 @@
1
- Style/BlockLength:
1
+ Metrics/BlockLength:
2
2
  Exclude:
3
3
  - 'dijkstra_graph.gemspec'
4
4
  - 'Rakefile'
data/README.md CHANGED
@@ -32,25 +32,71 @@ get_edge_weight(source, destination)
32
32
  get_adjacent_vertices(source)
33
33
 
34
34
  # Use Dijkstra's algorithm to find the shortest distances
35
- # from the start vertex to each of the other vertices
35
+ # from the source vertex to each of the other vertices
36
36
  #
37
- # Returns a hash of form { 'start' => 0, 'a' => 3, 'b' => 4 },
38
- # where result[v] indicates the shortest distance from start to v
39
- shortest_distances(start)
37
+ # Returns a hash of form { 'source' => 0, 'a' => 3, 'b' => 4 },
38
+ # where result[v] indicates the shortest distance from source to v
39
+ shortest_distances(source)
40
40
 
41
41
  # Use Dijkstra's algorithm to find the shortest paths
42
- # from the start vertex to each of the other vertices
42
+ # from the source vertex to each of the other vertices
43
43
  #
44
44
  # Returns a hash of form { 'c' => ['a', 'b', 'c'] }, where
45
- # result[v] indicates the shortest path from start to v
46
- shortest_paths(start)
45
+ # result[v] indicates the shortest path from source to v
46
+ shortest_paths(source)
47
+
48
+ # Use Dijkstra's algorithm to find the shortest paths
49
+ # from the source vertex to vertices within a given radius
50
+ #
51
+ # Returns a hash of form { 'c' => ['a', 'b', 'c'] }, where
52
+ # result[v] indicates the shortest path from source to v
53
+ shortest_paths_in_radius(source, radius)
47
54
 
48
55
  # Use Dijkstra's algorithm to find the shortest path
49
- # from the start vertex to the destination vertex
56
+ # from the source vertex to the destination vertex
50
57
  #
51
58
  # Returns an array of vertices along the shortest path
52
59
  # of form ['a', 'b', 'c'], or [] if no such path exists
53
- shortest_path(start, destination)
60
+ shortest_path(source, destination)
61
+ ```
62
+
63
+ ## Installation
64
+
65
+ Add this line to your application's Gemfile:
66
+
67
+ ```ruby
68
+ gem 'dijkstra_graph'
69
+ ```
70
+
71
+ Then you can require the gem in Ruby programs:
72
+
73
+ ```ruby
74
+ require 'dijkstra_graph'
75
+
76
+ graph = DijkstraGraph::Graph.new
77
+ graph.add_undirected_edge('Burnaby', 'Vancouver', 10)
78
+ graph.add_edge('Burnaby', 'Port Coquitlam', 23)
79
+ graph.add_edge('Vancouver', 'Langley', 37)
80
+ graph.add_undirected_edge('Langley', 'Port Coquitlam', 35)
81
+ shortest_paths_from_vancouver = graph.shortest_paths('Vancouver')
82
+
83
+ # => { 'Burnaby' => ['Vancouver', 'Burnaby'],
84
+ # 'Langley' => ['Vancouver', 'Langley'],
85
+ # 'Port Coquitlam' => ['Vancouver', 'Burnaby', 'Port Coquitlam'] }
86
+
87
+ van_paths_within_35k = graph.shortest_paths_in_radius('Vancouver', 35)
88
+
89
+ # => { 'Burnaby' => ['Vancouver', 'Burnaby'],
90
+ # 'Port Coquitlam' => ['Vancouver', 'Burnaby', 'Port Coquitlam'] }
91
+
92
+ van_to_portco_path = graph.shortest_path('Vancouver', 'Port Coquitlam')
93
+
94
+ # => ['Vancouver', 'Burnaby', 'Port Coquitlam']
95
+
96
+ distances_from_vancouver = graph.shortest_distances('Vancouver')
97
+
98
+ # => { 'Vancouver' => 0, 'Burnaby' => 10,
99
+ # 'Langley' => 37, 'Port Coquitlam' => 33 }
54
100
  ```
55
101
 
56
102
  ## Development
@@ -63,4 +109,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/msayso
63
109
 
64
110
  ## License
65
111
 
66
- The weighted_graph library is open source and available under the terms of the [MIT License](http://opensource.org/licenses/MIT).
112
+ The dijkstra_graph library is open source and available under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -13,7 +13,7 @@ module DijkstraGraph
13
13
  # Vertices 'to-visit' are stored in a priority queue that
14
14
  # uses a Fibonacci heap to give O(1) insert, amortized O(1)
15
15
  # decrease_priority, and amortized O(log n) delete_min.
16
- # Priority represents path distance from the start vertex.
16
+ # Priority represents path distance from the source vertex.
17
17
  #
18
18
  # The shortest distances found so far to each vertex are
19
19
  # stored in a simple hash which gives O(1) read/write.
@@ -24,13 +24,13 @@ module DijkstraGraph
24
24
  end
25
25
 
26
26
  # Use Dijkstra's algorithm to find the shortest distances
27
- # from the start vertex to each of the other vertices
27
+ # from the source vertex to each of the other vertices
28
28
  #
29
- # Returns a hash of form { 'start' => 0, 'a' => 3, 'b' => 4 },
30
- # where result[v] indicates the shortest distance from start to v
31
- def shortest_distances(start)
29
+ # Returns a hash of form { 'source' => 0, 'a' => 3, 'b' => 4 },
30
+ # where result[v] indicates the shortest distance from source to v
31
+ def shortest_distances(source)
32
32
  distances = Hash.new { Float::INFINITY } # Initial distances = Inf
33
- queue = initialize_queue(start) # Begin at start node
33
+ queue = initialize_queue(source) # Begin at source node
34
34
  until queue.empty?
35
35
  v, distances[v] = queue.delete_min # Visit next closest vertex
36
36
  update_distances_to_neighbours(v, distances, queue) # Update neighbours
@@ -39,69 +39,108 @@ module DijkstraGraph
39
39
  end
40
40
 
41
41
  # Use Dijkstra's algorithm to find the shortest paths
42
- # from the start vertex to each of the other vertices
42
+ # from the source vertex to each of the other vertices
43
43
  #
44
44
  # Returns a hash of form { 'c' => ['a', 'b', 'c'] }, where
45
- # result[v] indicates the shortest path from start to v
46
- def shortest_paths(start)
45
+ # result[v] indicates the shortest path from source to v
46
+ def shortest_paths(source)
47
47
  predecessors = {} # Initialize vertex predecessors
48
48
  distances = Hash.new { Float::INFINITY } # Initialize distances to Inf
49
- queue = initialize_queue(start) # Initialize queue with start
49
+ queue = initialize_queue(source) # Initialize queue with source
50
50
  until queue.empty?
51
51
  # Visit next closest vertex and update neighbours
52
52
  v, distances[v] = queue.delete_min
53
- update_paths_to_neighbours(v, predecessors, distances, queue)
53
+ update_paths_to_neighbours(v, distances, queue, predecessors)
54
54
  end
55
- PathUtil.path_arrays(predecessors, start)
55
+ PathUtil.path_arrays(predecessors, source)
56
+ end
57
+
58
+ # Use Dijkstra's algorithm to find the shortest paths
59
+ # from the source vertex to vertices within a given radius
60
+ #
61
+ # Returns a hash of form { 'c' => ['a', 'b', 'c'] }, where
62
+ # result[v] indicates the shortest path from source to v
63
+ def shortest_paths_in_radius(source, radius)
64
+ predecessors = {} # Initialize vertex predecessors
65
+ distances = Hash.new { Float::INFINITY } # Initialize distances to Inf
66
+ queue = initialize_queue(source) # Initialize queue with source
67
+ until queue.empty?
68
+ # Visit next closest vertex and update neighbours
69
+ v, distance = queue.delete_min
70
+ return PathUtil.path_arrays(predecessors, source) if distance > radius
71
+ distances[v] = distance
72
+ update_neighbours_in_radius(v, distances, queue, predecessors, radius)
73
+ end
74
+ PathUtil.path_arrays(predecessors, source)
56
75
  end
57
76
 
58
77
  # Use Dijkstra's algorithm to find the shortest path
59
- # from the start vertex to the destination vertex
78
+ # from the source vertex to the destination vertex
60
79
  #
61
80
  # Returns an array of vertices along the shortest path
62
81
  # of form ['a', 'b', 'c'], or [] if no such path exists
63
- def shortest_path(start, dest)
82
+ def shortest_path(source, dest)
64
83
  predecessors = {} # Initialize vertex predecessors
65
84
  distances = Hash.new { Float::INFINITY } # Initialize distances to Inf
66
- queue = initialize_queue(start) # Initialize queue with start
85
+ queue = initialize_queue(source) # Initialize queue with source
67
86
  until queue.empty?
68
87
  v, distances[v] = queue.delete_min # Visit next closest node
69
- return PathUtil.path_array(predecessors, start, dest) if v == dest
70
- update_paths_to_neighbours(v, predecessors, distances, queue)
88
+ return PathUtil.path_array(predecessors, source, dest) if v == dest
89
+ update_paths_to_neighbours(v, distances, queue, predecessors)
71
90
  end
72
- [] # No path found from start to dest
91
+ [] # No path found from source to dest
73
92
  end
74
93
 
75
94
  private
76
95
 
77
- # Initialize priority queue with start vertex at distance = 0
78
- def initialize_queue(start_vertex)
96
+ # Initialize priority queue with source vertex at distance = 0
97
+ def initialize_queue(source_vertex)
79
98
  queue = PriorityQueue.new
80
- queue[start_vertex] = 0
99
+ queue[source_vertex] = 0
81
100
  queue
82
101
  end
83
102
 
84
103
  # Update distances to neighbours of v and queue changed neighbours
85
104
  def update_distances_to_neighbours(v, distances, queue)
86
- distance_v = distances[v]
87
- get_adjacent_vertices(v).each do |w|
88
- distance_through_v = distance_v + get_edge_weight(v, w)
89
- if distance_through_v < distances[w]
90
- queue[w] = distances[w] = distance_through_v
91
- end
92
- end
105
+ update_neighbours(v, distances, method(:update_distance),
106
+ distances: distances, queue: queue)
93
107
  end
94
108
 
95
109
  # Update paths to neighbours of v and queue changed neighbours
96
- def update_paths_to_neighbours(v, predecessors, distances, queue)
110
+ def update_paths_to_neighbours(v, distances, queue, predecessors)
111
+ update_neighbours(v, distances, method(:update_path),
112
+ distances: distances, queue: queue,
113
+ predecessors: predecessors, predecessor: v)
114
+ end
115
+
116
+ # Update paths to neighbours of v in radius and queue changed neighbours
117
+ def update_neighbours_in_radius(v, distances, queue, predecessors, radius)
118
+ update_neighbours(v, distances, method(:update_path),
119
+ distances: distances, queue: queue, radius: radius,
120
+ predecessors: predecessors, predecessor: v)
121
+ end
122
+
123
+ # Apply given method to each neighbour we find a shorter path to
124
+ def update_neighbours(v, distances, update_method, update_params)
97
125
  distance_v = distances[v]
98
126
  get_adjacent_vertices(v).each do |w|
99
127
  distance_through_v = distance_v + get_edge_weight(v, w)
100
128
  if distance_through_v < distances[w]
101
- queue[w] = distances[w] = distance_through_v
102
- predecessors[w] = v
129
+ update_method.call(w, distance_through_v, update_params)
103
130
  end
104
131
  end
105
132
  end
133
+
134
+ # Update shortest distance to vertex
135
+ def update_distance(vertex, distance, params)
136
+ params[:queue][vertex] = params[:distances][vertex] = distance
137
+ end
138
+
139
+ # Update shortest path to vertex
140
+ def update_path(vertex, distance, params)
141
+ return if params[:radius] && distance > params[:radius]
142
+ update_distance(vertex, distance, params)
143
+ params[:predecessors][vertex] = params[:predecessor]
144
+ end
106
145
  end
107
146
  end
@@ -1,3 +1,3 @@
1
1
  module DijkstraGraph
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.1.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dijkstra_graph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Sayson