Module: Silicium::Graphs
- Included in:
- GraphVisualizer, OrientedGraph
- Defined in:
- lib/graph.rb,
lib/graph/dfs.rb,
lib/graph/scc.rb,
lib/graph/kruskal.rb,
lib/topological_sort.rb
Defined Under Namespace
Classes: Graph, GraphError, Node, OrientedGraph, Pair, TopologicalSortClass, UnionFind, UnorientedGraph
Instance Method Summary collapse
- #add_edge!(mst, edge, label) ⇒ Object
-
#add_to_queue(graph, queue, node, visited) ⇒ Object
Adds to queue not visited vertices.
- #add_to_stack(graph, node, stack, visited) ⇒ Object
-
#breadth_first_search?(graph, start, goal) ⇒ Boolean
Implements breadth-first search (BFS).
-
#connected?(graph) ⇒ Boolean
Checks if graph is connected.
- #depth_first_search?(graph, start, goal) ⇒ Boolean
- #dfs_traverse(graph, start) ⇒ Object
- #dfs_traverse_recursive(graph, node, visited, traversed) ⇒ Object
-
#dfu(graph, vertice, visited) ⇒ Object
Passes graph’s vertices and marks them visited.
-
#dijkstra_algorithm(graph, starting_vertex) ⇒ Object
Implements algorithm of Dijkstra.
- #goal_node?(graph, node, goal) ⇒ Boolean
-
#graph_to_sets(graph) ⇒ Object
“Split” graph into elements like :[from, to] = label.
-
#kruskal_mst(graph) ⇒ Object
Implements algorithm of Kruskal.
-
#number_of_connected(graph) ⇒ Object
Returns number of connected vertices.
- #sum_labels(graph) ⇒ Object
Instance Method Details
#add_edge!(mst, edge, label) ⇒ Object
272 273 274 275 276 277 |
# File 'lib/graph.rb', line 272 def add_edge!(mst, edge, label) mst.add_vertex!(edge[0]) mst.add_vertex!(edge[1]) mst.add_edge!(edge[0], edge[1]) mst.label_edge!(edge[0], edge[1], label) end |
#add_to_queue(graph, queue, node, visited) ⇒ Object
Adds to queue not visited vertices
233 234 235 236 237 238 239 240 |
# File 'lib/graph.rb', line 233 def add_to_queue(graph, queue, node, visited) graph.vertices[node].each do |child| unless visited[child] queue.push(child) visited[child] = true end end end |
#add_to_stack(graph, node, stack, visited) ⇒ Object
21 22 23 24 25 26 |
# File 'lib/graph/dfs.rb', line 21 def add_to_stack(graph, node, stack, visited) return if visited[node] visited[node] = true graph.vertices[node].each { |child| stack.push(child) } end |
#breadth_first_search?(graph, start, goal) ⇒ Boolean
Implements breadth-first search (BFS)
219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/graph.rb', line 219 def breadth_first_search?(graph, start, goal) visited = Hash.new(false) queue = Queue.new queue.push(start) visited[start] = true until queue.empty? do node = queue.pop return true if node == goal add_to_queue(graph, queue, node, visited) end false end |
#connected?(graph) ⇒ Boolean
Checks if graph is connected
243 244 245 246 247 248 249 250 251 |
# File 'lib/graph.rb', line 243 def connected?(graph) start = graph.vertices.keys[0] goal = graph.vertices.keys[graph.vertex_number - 1] pred = breadth_first_search?(graph, start, goal) graph.reverse! pred = pred and breadth_first_search?(graph, goal, start) graph.reverse! pred end |
#depth_first_search?(graph, start, goal) ⇒ Boolean
4 5 6 7 8 9 10 11 12 13 |
# File 'lib/graph/dfs.rb', line 4 def depth_first_search?(graph, start, goal) visited = Hash.new(false) stack = [start] until stack.empty? node = stack.pop return true if goal_node?(graph, node, goal) add_to_stack(graph, node, stack, visited) end false end |
#dfs_traverse(graph, start) ⇒ Object
28 29 30 31 32 33 |
# File 'lib/graph/dfs.rb', line 28 def dfs_traverse(graph, start) visited = Hash.new(false) traversed = [] dfs_traverse_recursive(graph, start, visited, traversed) traversed end |
#dfs_traverse_recursive(graph, node, visited, traversed) ⇒ Object
35 36 37 38 39 |
# File 'lib/graph/dfs.rb', line 35 def dfs_traverse_recursive(graph, node, visited, traversed) visited[node] = true traversed.push(node) graph.vertices[node].each { |child| dfs_traverse_recursive(graph, child, visited, traversed) unless visited[child] } end |
#dfu(graph, vertice, visited) ⇒ Object
Passes graph’s vertices and marks them visited
267 268 269 270 |
# File 'lib/graph.rb', line 267 def dfu(graph, vertice, visited) visited[vertice] = true graph.vertices[vertice].each { |item| dfu(graph, item, visited) unless visited[item] } end |
#dijkstra_algorithm(graph, starting_vertex) ⇒ Object
Implements algorithm of Dijkstra
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
# File 'lib/graph.rb', line 303 def dijkstra_algorithm(graph, starting_vertex) if !graph.has_vertex?(starting_vertex) raise GraphError.new("Graph does not contains vertex #{starting_vertex}") end unvisited_vertices = graph.vertices.clone.to_a labels = {} paths = {} initialize_labels_and_paths(graph, labels,paths,starting_vertex) while unvisited_vertices.size > 0 unvisited_vertices.sort { |a, b| compare_labels(a, b, labels) } vertex = unvisited_vertices.first vertex[1].each do |adj| new_label = labels[vertex[0]] + graph.get_edge_label(vertex[0], adj) if change_label?(labels[adj], new_label) labels[adj] = new_label paths[adj] = paths[vertex[0]].clone paths[adj].push adj end end unvisited_vertices.delete_at(0) end {"labels" => labels, "paths" => paths} end |
#goal_node?(graph, node, goal) ⇒ Boolean
15 16 17 18 19 |
# File 'lib/graph/dfs.rb', line 15 def goal_node?(graph, node, goal) raise ArgumentError if graph.vertices[node].nil? node == goal end |
#graph_to_sets(graph) ⇒ Object
“Split” graph into elements like :[from, to] = label
283 284 285 286 287 288 289 |
# File 'lib/graph.rb', line 283 def graph_to_sets(graph) labels = {} graph.vertices.keys.each do |from| graph.adjacted_with(from).each { |to| labels[Pair.new(from, to)] = graph.get_edge_label(from, to) } end labels.to_set.sort_by { |elem| elem[1] }.to_h end |
#kruskal_mst(graph) ⇒ Object
Implements algorithm of Kruskal
23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/graph/kruskal.rb', line 23 def kruskal_mst(graph) mst = UnorientedGraph.new uf = UnionFind.new(graph) graph_to_sets(graph).each do |edge, label| unless uf.connected?(edge[0], edge[1]) add_edge!(mst, edge, label) uf.union(edge[0], edge[1]) end end mst end |
#number_of_connected(graph) ⇒ Object
Returns number of connected vertices
254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/graph.rb', line 254 def number_of_connected(graph) visited = Hash.new(false) res = 0 graph.vertices.keys.each do |v| unless visited[v] dfu(graph, v, visited) res += 1 end end res end |
#sum_labels(graph) ⇒ Object
291 292 293 294 295 296 297 |
# File 'lib/graph.rb', line 291 def sum_labels(graph) labels = 0 graph.vertices.keys.each do |from| graph.adjacted_with(from).each { |to| labels += graph.get_edge_label(from, to) } end labels / 2 end |