rgl 0.5.1 → 0.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -77,7 +77,7 @@ def bfs_example(g = cycle(5), start = g.detect { |x| true })
77
77
  end
78
78
 
79
79
  # Would like to have GraphXML here
80
- def graph_from_dotfile (file)
80
+ def graph_from_dotfile(file)
81
81
  g = RGL::AdjacencyGraph.new
82
82
  pattern = /\s*([^\"]+)[\"\s]*--[\"\s]*([^\"\[\;]+)/ # ugly but works
83
83
  IO.foreach(file) { |line|
@@ -94,21 +94,23 @@ def graph_from_dotfile (file)
94
94
  g
95
95
  end
96
96
 
97
- # ruby -Ilib -r examples/examples.rb -rrgl/dot -e'bfs_example(module_graph,RGL::AdjacencyGraph).dotty'
98
-
97
+ # ruby -Ilib examples/examples.rb
99
98
  if $0 == __FILE__
100
99
  require 'rgl/dot'
101
100
 
102
101
  dg = RGL::DirectedAdjacencyGraph[1,2, 2,3, 2,4, 4,5, 6,4, 1,6]
103
- dg.dotty
104
102
  dg.write_to_graphic_file
105
- bfs_example(dg, 1).dotty
106
- bfs_example(graph_from_dotfile('dot/unix.dot'), 'Interdata').dotty({ 'label' => 'Interdata Nachfolger', 'fontsize' => 12 })
107
103
 
104
+ # BFS tree from 1 of dg:
105
+ bfs_example(dg, 1).write_to_graphic_file('png', 'bfs_example')
106
+
107
+ # Unix history as a graph:
108
+ g = bfs_example(graph_from_dotfile('examples/unix.dot'), 'Interdata')
109
+ g.write_to_graphic_file('png', 'unix', { 'label' => 'Interdata Nachfolger', 'fontsize' => 12 })
110
+
111
+ # Modules included by AdjacencyGraph:
108
112
  g = module_graph
109
113
  tree = bfs_example(module_graph, RGL::AdjacencyGraph)
110
114
  g = g.vertices_filtered_by { |v| tree.has_vertex? v }
111
- g.write_to_graphic_file
112
- g.dotty
115
+ g.write_to_graphic_file('png', 'module_graph')
113
116
  end
114
-
@@ -0,0 +1,53 @@
1
+ /* courtesy Ian Darwin and Geoff Collyer, Softquad Inc. */
2
+ digraph unix {
3
+ size="6,6";
4
+ "5th Edition" -> "6th Edition";
5
+ "5th Edition" -> "PWB 1.0";
6
+ "6th Edition" -> "LSX";
7
+ "6th Edition" -> "1 BSD";
8
+ "6th Edition" -> "Mini Unix";
9
+ "6th Edition" -> "Wollongong";
10
+ "6th Edition" -> "Interdata";
11
+ "Interdata" -> "Unix/TS 3.0";
12
+ "Interdata" -> "PWB 2.0";
13
+ "Interdata" -> "7th Edition";
14
+ "7th Edition" -> "8th Edition";
15
+ "7th Edition" -> "32V";
16
+ "7th Edition" -> "V7M";
17
+ "7th Edition" -> "Ultrix-11";
18
+ "7th Edition" -> "Xenix";
19
+ "7th Edition" -> "UniPlus+";
20
+ "V7M" -> "Ultrix-11";
21
+ "8th Edition" -> "9th Edition";
22
+ "1 BSD" -> "2 BSD";
23
+ "2 BSD" -> "2.8 BSD";
24
+ "2.8 BSD" -> "Ultrix-11";
25
+ "2.8 BSD" -> "2.9 BSD";
26
+ "32V" -> "3 BSD";
27
+ "3 BSD" -> "4 BSD";
28
+ "4 BSD" -> "4.1 BSD";
29
+ "4.1 BSD" -> "4.2 BSD";
30
+ "4.1 BSD" -> "2.8 BSD";
31
+ "4.1 BSD" -> "8th Edition";
32
+ "4.2 BSD" -> "4.3 BSD";
33
+ "4.2 BSD" -> "Ultrix-32";
34
+ "PWB 1.0" -> "PWB 1.2";
35
+ "PWB 1.0" -> "USG 1.0";
36
+ "PWB 1.2" -> "PWB 2.0";
37
+ "USG 1.0" -> "CB Unix 1";
38
+ "USG 1.0" -> "USG 2.0";
39
+ "CB Unix 1" -> "CB Unix 2";
40
+ "CB Unix 2" -> "CB Unix 3";
41
+ "CB Unix 3" -> "Unix/TS++";
42
+ "CB Unix 3" -> "PDP-11 Sys V";
43
+ "USG 2.0" -> "USG 3.0";
44
+ "USG 3.0" -> "Unix/TS 3.0";
45
+ "PWB 2.0" -> "Unix/TS 3.0";
46
+ "Unix/TS 1.0" -> "Unix/TS 3.0";
47
+ "Unix/TS 3.0" -> "TS 4.0";
48
+ "Unix/TS++" -> "TS 4.0";
49
+ "CB Unix 3" -> "TS 4.0";
50
+ "TS 4.0" -> "System V.0";
51
+ "System V.0" -> "System V.2";
52
+ "System V.2" -> "System V.3";
53
+ }
@@ -77,7 +77,7 @@ module RGL
77
77
  # Complexity is O(1), because the vertices are kept in a Hash containing
78
78
  # as values the lists of adjacent vertices of _v_.
79
79
  #
80
- def has_vertex? (v)
80
+ def has_vertex?(v)
81
81
  @vertices_dict.has_key?(v)
82
82
  end
83
83
 
@@ -87,7 +87,7 @@ module RGL
87
87
  # ---
88
88
  # MutableGraph interface.
89
89
  #
90
- def has_edge? (u, v)
90
+ def has_edge?(u, v)
91
91
  has_vertex?(u) && @vertices_dict[u].include?(v)
92
92
  end
93
93
 
@@ -4,9 +4,7 @@
4
4
  # library. The main module is RGL::Graph which defines the abstract behavior of
5
5
  # all graphs in the library.
6
6
 
7
- require 'rgl/enumerable_ext'
8
-
9
- RGL_VERSION = "0.5.1"
7
+ RGL_VERSION = "0.5.7"
10
8
 
11
9
  module RGL
12
10
  class NotDirectedError < RuntimeError; end
@@ -77,6 +75,9 @@ module RGL
77
75
  "(#{source}-#{target})"
78
76
  end
79
77
 
78
+ # Since Ruby 2.0 #inspect no longer calls #to_s. So we alias it to to_s (fixes #22)
79
+ alias inspect to_s
80
+
80
81
  # Returns the array [source,target].
81
82
  #
82
83
  def to_a
@@ -2,8 +2,7 @@ require 'rgl/dijkstra_visitor'
2
2
  require 'rgl/edge_properties_map'
3
3
  require 'rgl/path_builder'
4
4
 
5
- require 'delegate'
6
- require 'algorithms'
5
+ require 'lazy_priority_queue'
7
6
 
8
7
  module RGL
9
8
 
@@ -22,7 +22,7 @@ module RGL
22
22
  next if bfs.finished_vertex?(u)
23
23
 
24
24
  bfs.reset_start(u)
25
- bfs.move_forward_until { @found_odd_cycle }
25
+ bfs.move_forward_until { bfs.found_odd_cycle }
26
26
 
27
27
  return if bfs.found_odd_cycle
28
28
  end
@@ -84,4 +84,4 @@ module RGL
84
84
 
85
85
  end # class BipartiteBFSIterator
86
86
 
87
- end # module RGL
87
+ end # module RGL
@@ -2,8 +2,7 @@ require 'rgl/dijkstra_visitor'
2
2
  require 'rgl/edge_properties_map'
3
3
  require 'rgl/path_builder'
4
4
 
5
- require 'delegate'
6
- require 'algorithms'
5
+ require 'lazy_priority_queue'
7
6
 
8
7
  module RGL
9
8
 
@@ -55,7 +54,7 @@ module RGL
55
54
  def init(source)
56
55
  @visitor.set_source(source)
57
56
 
58
- @queue = Queue.new
57
+ @queue = MinPriorityQueue.new
59
58
  @queue.push(source, 0)
60
59
  end
61
60
 
@@ -82,8 +81,6 @@ module RGL
82
81
  new_v_distance = @distance_combinator.call(@visitor.distance_map[u], @edge_weights_map.edge_property(u, v))
83
82
 
84
83
  if new_v_distance < @visitor.distance_map[v]
85
- old_v_distance = @visitor.distance_map[v]
86
-
87
84
  @visitor.distance_map[v] = new_v_distance
88
85
  @visitor.parents_map[v] = u
89
86
 
@@ -91,7 +88,7 @@ module RGL
91
88
  @visitor.color_map[v] = :GRAY
92
89
  @queue.push(v, new_v_distance)
93
90
  elsif @visitor.color_map[v] == :GRAY
94
- @queue.decrease_key(v, old_v_distance, new_v_distance)
91
+ @queue.decrease_key(v, new_v_distance)
95
92
  end
96
93
 
97
94
  @visitor.handle_edge_relaxed(u, v)
@@ -104,29 +101,6 @@ module RGL
104
101
  edge_weights_map.is_a?(EdgePropertiesMap) ? edge_weights_map : NonNegativeEdgePropertiesMap.new(edge_weights_map, @graph.directed?)
105
102
  end
106
103
 
107
- class Queue < SimpleDelegator # :nodoc:
108
-
109
- def initialize
110
- @heap = Containers::Heap.new { |a, b| a.distance < b.distance }
111
- super(@heap)
112
- end
113
-
114
- def push(vertex, distance)
115
- @heap.push(vertex_key(vertex, distance), vertex)
116
- end
117
-
118
- def decrease_key(vertex, old_distance, new_distance)
119
- @heap.change_key(vertex_key(vertex, old_distance), vertex_key(vertex, new_distance))
120
- end
121
-
122
- def vertex_key(vertex, distance)
123
- VertexKey.new(vertex, distance)
124
- end
125
-
126
- VertexKey = Struct.new(:vertex, :distance)
127
-
128
- end
129
-
130
104
  end # class DijkstraAlgorithm
131
105
 
132
106
  module Graph
@@ -5,6 +5,9 @@
5
5
  # Minimal Dot support, based on Dave Thomas's dot module (included in rdoc).
6
6
  # rdot.rb is a modified version which also contains support for undirected
7
7
  # graphs.
8
+ #
9
+ # You need to have [GraphViz](http://www.graphviz.org) installed, because the
10
+ # functions in this modul execute the GraphViz executables _dot_ or _dotty_.
8
11
 
9
12
  require 'rgl/rdot'
10
13
 
@@ -17,6 +20,10 @@ module RGL
17
20
  v.to_s
18
21
  end
19
22
 
23
+ def vertex_id(v)
24
+ v
25
+ end
26
+
20
27
  # Return a RGL::DOT::Digraph for directed graphs or a DOT::Graph for an
21
28
  # undirected Graph. _params_ can contain any graph property specified in
22
29
  # rdot.rb.
@@ -26,21 +33,29 @@ module RGL
26
33
  fontsize = params['fontsize'] ? params['fontsize'] : '8'
27
34
  graph = (directed? ? DOT::Digraph : DOT::Graph).new(params)
28
35
  edge_class = directed? ? DOT::DirectedEdge : DOT::Edge
36
+ vertex_options = params['vertex'] || {}
37
+ edge_options = params['edge'] || {}
29
38
 
30
39
  each_vertex do |v|
31
- graph << DOT::Node.new(
32
- 'name' => v.object_id,
33
- 'fontsize' => fontsize,
34
- 'label' => vertex_label(v)
35
- )
40
+ default_vertex_options = {
41
+ 'name' => vertex_id(v),
42
+ 'fontsize' => fontsize,
43
+ 'label' => vertex_label(v)
44
+ }
45
+ each_vertex_options = default_vertex_options.merge(vertex_options)
46
+ vertex_options.each{|option, val| each_vertex_options[option] = val.call(v) if val.is_a?(Proc)}
47
+ graph << DOT::Node.new(each_vertex_options)
36
48
  end
37
49
 
38
50
  each_edge do |u, v|
39
- graph << edge_class.new(
40
- 'from' => u.object_id,
41
- 'to' => v.object_id,
42
- 'fontsize' => fontsize
43
- )
51
+ default_edge_options = {
52
+ 'from' => vertex_id(u),
53
+ 'to' => vertex_id(v),
54
+ 'fontsize' => fontsize
55
+ }
56
+ each_edge_options = default_edge_options.merge(edge_options)
57
+ edge_options.each{|option, val| each_edge_options[option] = val.call(u, v) if val.is_a?(Proc)}
58
+ graph << edge_class.new(each_edge_options)
44
59
  end
45
60
 
46
61
  graph
@@ -60,21 +75,25 @@ module RGL
60
75
  File.open(dotfile, "w") do |f|
61
76
  print_dotted_on(params, f)
62
77
  end
63
- system("dotty", dotfile)
78
+ unless system("dotty", dotfile)
79
+ raise "Error executing dotty. Did you install GraphViz?"
80
+ end
64
81
  end
65
82
 
66
83
  # Use dot[http://www.graphviz.org] to create a graphical representation of
67
84
  # the graph. Returns the filename of the graphics file.
68
85
  #
69
- def write_to_graphic_file(fmt='png', dotfile="graph")
86
+ def write_to_graphic_file(fmt='png', dotfile="graph", options={})
70
87
  src = dotfile + ".dot"
71
88
  dot = dotfile + "." + fmt
72
89
 
73
90
  File.open(src, 'w') do |f|
74
- f << self.to_dot_graph.to_s << "\n"
91
+ f << self.to_dot_graph(options).to_s << "\n"
75
92
  end
76
93
 
77
- system("dot -T#{fmt} #{src} -o #{dot}")
94
+ unless system("dot -T#{fmt} #{src} -o #{dot}")
95
+ raise "Error executing dot. Did you install GraphViz?"
96
+ end
78
97
  dot
79
98
  end
80
99
 
@@ -46,9 +46,9 @@ module RGL
46
46
  min_residual_capacity = [min_residual_capacity, @residual_capacity_map[u, v]].min
47
47
  end
48
48
 
49
- augmenting_path.each_cons(2) do |(u, v)|
50
- @flow_map[[u, v]] += min_residual_capacity
51
- @flow_map[[v, u]] -= min_residual_capacity
49
+ augmenting_path.each_cons(2) do |(uu, vv)|
50
+ @flow_map[[uu, vv]] += min_residual_capacity
51
+ @flow_map[[vv, uu]] -= min_residual_capacity
52
52
  end
53
53
  end
54
54
  end
@@ -133,4 +133,4 @@ module RGL
133
133
 
134
134
  end # module Graph
135
135
 
136
- end
136
+ end
@@ -10,6 +10,10 @@ module RGL
10
10
  module GraphIterator
11
11
  include Stream
12
12
  include GraphWrapper
13
+
14
+ def length
15
+ inject(0) { |sum| sum + 1 }
16
+ end
13
17
  end
14
18
 
15
19
  end # RGL
@@ -1,7 +1,7 @@
1
1
  # graphxml.rb
2
2
  #
3
3
  # This file contains minimal support for creating RGL graphs from the GraphML
4
- # format (see http://www.graphdrawing.org/graphml). The main purpose is to
4
+ # format (see http://graphml.graphdrawing.org/). The main purpose is to
5
5
  # have a rich set of example graphs to have some more tests.
6
6
  #
7
7
  # See the examples directory, which contains a subdirectory _north_ with the
@@ -48,7 +48,7 @@ module RGL
48
48
  end # class MutableGraphParser
49
49
 
50
50
  # Initializes an RGL graph from a subset of the GraphML format given in
51
- # +source+ (see http://www.graphdrawing.org/graphml).
51
+ # +source+ (see http://graphml.graphdrawing.org/).
52
52
  #
53
53
  def from_graphxml(source)
54
54
  listener = MutableGraphParser.new(self)
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rgl/traversal'
4
+
5
+ module RGL
6
+ module Graph
7
+ # Checks whether a path exists between _source_ and _target_ vertices
8
+ # in the graph.
9
+ #
10
+ def path?(source, target)
11
+ return false unless has_vertex?(source)
12
+
13
+ bfs_iterator = bfs_iterator(source)
14
+ bfs_iterator.include?(target)
15
+ end
16
+ end
17
+ end
@@ -328,7 +328,7 @@ module RGL
328
328
  # :call-seq:
329
329
  # graph << element -> graph
330
330
  #
331
- def << (element)
331
+ def <<(element)
332
332
  @elements << element
333
333
  self
334
334
  end
@@ -58,9 +58,12 @@ module RGL
58
58
  # Reset the iterator to the initial state (i.e. at_beginning? == true).
59
59
  #
60
60
  def set_to_begin
61
+ # Reset color_map
62
+ @color_map = Hash.new(:WHITE)
61
63
  color_map[@start_vertex] = :GRAY
62
- @waiting = [@start_vertex] # a queue
64
+ @waiting = [@start_vertex] # a queue
63
65
  handle_tree_edge(nil, @start_vertex) # discovers start vertex
66
+ self
64
67
  end
65
68
 
66
69
  def basic_forward # :nodoc:
@@ -169,6 +172,10 @@ module RGL
169
172
  # it is called on each _finish_vertex_ event. See
170
173
  # strongly_connected_components for an example usage.
171
174
  #
175
+ # Note that this traversal does not garantee, that roots are at the top of
176
+ # each spanning subtree induced by the DFS search on a directed graph (see
177
+ # also the discussion in issue #20[https://github.com/monora/rgl/issues/20]).
178
+ #
172
179
  def depth_first_search(vis = DFSVisitor.new(self), &b)
173
180
  each_vertex do |u|
174
181
  unless vis.finished_vertex?(u)
@@ -61,7 +61,7 @@ i -> h j e c
61
61
 
62
62
  assert_equal(4, vis.num_comp)
63
63
 
64
- res = vis.comp_map.to_a.sort.reduce({}) { |res, a|
64
+ result = vis.comp_map.to_a.sort.reduce({}) { |res, a|
65
65
  if res.key?(a[1])
66
66
  res[a[1]] << a[0]
67
67
  else
@@ -70,7 +70,7 @@ i -> h j e c
70
70
  res
71
71
  }
72
72
 
73
- std_res = res.to_a.map {
73
+ std_res = result.to_a.map {
74
74
  |a|
75
75
  [a[1][0], a[1]]
76
76
  }.sort
@@ -0,0 +1,23 @@
1
+ require 'test_helper'
2
+
3
+ require 'rgl/dijkstra'
4
+ require 'rgl/adjacency'
5
+
6
+ include RGL
7
+
8
+ class TestDijkstraIssue24 < Test::Unit::TestCase
9
+
10
+ def setup
11
+ @graph = RGL::AdjacencyGraph[2,53, 2,3, 3,8, 3,28, 3,39, 29,58, 8,35, 12,39, 10,29, 62,15, 15,32, 32,58, 58,44, 44,53]
12
+
13
+ end
14
+
15
+ def test_shortest_path_search
16
+ assert_equal([53, 44, 58, 32, 15, 62], shortest_path(53, 62))
17
+ end
18
+
19
+ def shortest_path(v,w)
20
+ @graph.dijkstra_shortest_path(Hash.new(1), v, w)
21
+ end
22
+
23
+ end