rgl 0.3.1 → 0.4.0

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.
data/ChangeLog CHANGED
@@ -1,6 +1,80 @@
1
+ 2008-08-28 01:36 javanthropus
2
+
3
+ * ChangeLog (tags: REL_0_4_0): pre-tag commit
4
+
5
+ 2008-08-28 01:36 javanthropus
6
+
7
+ * Rakefile (tags: REL_0_4_0): Update rdoc2rf task to use rsync and
8
+ more generic remote path specification
9
+
10
+ 2008-08-27 23:30 javanthropus
11
+
12
+ * lib/rgl/base.rb (tags: REL_0_4_0): Preparing for 0.4.0 release
13
+
14
+ 2008-08-26 20:07 javanthropus
15
+
16
+ * lib/rgl/dot.rb, lib/rgl/rdot.rb, tests/TestRdot.rb: Move the DOT
17
+ module into the RGL module
18
+
19
+ * This eliminates a class conflict with the DOT module from rdoc
20
+ when building RGL's documentation * Also remove the superfluous
21
+ DOT prefixes from class names in the DOT module
22
+
23
+ 2008-08-24 06:16 javanthropus
24
+
25
+ * Rakefile: Remove some comments I accidentally left in while
26
+ testing rdoc functionality
27
+
28
+ 2008-08-24 06:03 javanthropus
29
+
30
+ * Rakefile, lib/rgl/transitiv_closure.rb, lib/rgl/transitivity.rb,
31
+ tests/TestTransitiveClosure.rb, tests/TestTransitivity.rb:
32
+ Feature 21641: Added transitive reduction functionality
33
+
34
+ * Updated the gem description to announce this functionality *
35
+ Moved the transitive closure functionality into the
36
+ transitivity.rb file along with the transitive reduction
37
+ funtionality * Modifed the transitiv_closure.rb file to simply
38
+ load the transitivity.rb file for backward compatibility * Moved
39
+ all transitivity tests into TestTransitivity.rb
40
+
41
+ 2008-08-23 15:45 javanthropus
42
+
43
+ * lib/rgl/condensation.rb, lib/rgl/transitiv_closure.rb,
44
+ tests/TestTransitiveClosure.rb: Defect 21630: Fixed transitive
45
+ closure
46
+
47
+ * The fix is based on the algorithm described in the
48
+ documentation for the implementation of transitive closure in
49
+ Boost * Along with the fix, performance is improved to O(|V||E|)
50
+ * This implementation needs graph condensation, so that function
51
+ was added as well * More tests were added to cover more corner
52
+ cases
53
+
54
+ 2008-08-23 05:40 javanthropus
55
+
56
+ * tests/TestGraph.rb: Update basic graph tests to account for
57
+ graphs with edgeless vertices Also clean up some minor formatting
58
+ and assertion issues
59
+
60
+ 2008-08-23 05:37 javanthropus
61
+
62
+ * lib/rgl/adjacency.rb: Defect 21609: Fix the to_adjacency method
63
+ to preserve edgeless vertices
64
+
65
+ 2008-03-18 15:03 javanthropus
66
+
67
+ * lib/rgl/rdot.rb, tests/TestRdot.rb: More reliably detect and
68
+ handle newlines embedded within IDs and labels
69
+
70
+ 2008-03-08 10:48 monora
71
+
72
+ * ChangeLog, lib/rgl/base.rb (utags: REL_0_3_1): Prepare 0.3.1
73
+ release
74
+
1
75
  2008-03-04 20:18 monora
2
76
 
3
- * Rakefile (tags: REL_0_3_0): pre-tag commit
77
+ * Rakefile (tags: REL_0_3_1, REL_0_3_0): pre-tag commit
4
78
 
5
79
  2008-03-02 18:16 javanthropus
6
80
 
data/Rakefile CHANGED
@@ -23,6 +23,17 @@ SOURCES = FileList['lib/**/*.rb']
23
23
  CLOBBER.include('TAGS', 'coverage')
24
24
  RDOC_DIR = './rgl'
25
25
 
26
+ # The location for published documents to be copied.
27
+ remote_user = ENV['REMOTE_USER'] || ''
28
+ remote_host = ENV['REMOTE_HOST'] || 'rubyforge.org'
29
+ remote_path = ENV['REMOTE_PATH'] || '/var/www/gforge-projects/rgl'
30
+ remote_path += '/' unless remote_path[-1, 1] == '/'
31
+ REMOTE_RDOC_DIR = remote_path
32
+ REMOTE_RDOC_DIR.insert(
33
+ 0,
34
+ remote_user + (remote_user.empty? ? '' : '@') + remote_host + ':'
35
+ ) unless remote_host.empty?
36
+
26
37
  # The default task is run if rake is given no explicit arguments.
27
38
 
28
39
  desc "Default Task"
@@ -124,6 +135,8 @@ else
124
135
  * Connected Components
125
136
  * Strongly Connected Components
126
137
  * Transitive Closure
138
+ * Transitive Reduction
139
+ * Graph Condensation
127
140
  * Search cycles (contributed by Shawn Garbett)
128
141
  EOF
129
142
 
@@ -211,7 +224,9 @@ end
211
224
 
212
225
  desc "Copy rdoc html to rubyforge"
213
226
  task :rdoc2rf => [:rdoc, :rcov, :changelog] do
214
- mv 'coverage', RDOC_DIR
215
- sh "scp -r #{RDOC_DIR} monora@rubyforge.org:/var/www/gforge-projects/rgl"
216
- sh "scp examples/*.jpg monora@rubyforge.org:/var/www/gforge-projects/rgl/examples"
227
+ cp_r 'coverage', RDOC_DIR
228
+ examples = File.join(RDOC_DIR, 'examples')
229
+ mkdir_p examples
230
+ cp Dir.glob('examples/*.jpg'), examples
231
+ sh "rsync -r --delete \"#{RDOC_DIR}\" \"#{REMOTE_RDOC_DIR}\""
217
232
  end
data/install.rb CHANGED
File without changes
@@ -1,6 +1,6 @@
1
1
  # adjacency.rb
2
2
  #
3
- # $Id: adjacency.rb,v 1.11 2008/03/02 13:45:43 monora Exp $
3
+ # $Id: adjacency.rb,v 1.12 2008/08/23 05:37:05 javanthropus Exp $
4
4
  #
5
5
  # The DirectedAdjacencyGraph class implements a generalized adjacency list
6
6
  # graph structure. An AdjacencyGraph is basically a two-dimensional structure
@@ -173,6 +173,7 @@ module RGL
173
173
 
174
174
  def to_adjacency
175
175
  result = (directed? ? DirectedAdjacencyGraph : AdjacencyGraph).new
176
+ each_vertex { |v| result.add_vertex(v) }
176
177
  each_edge { |u,v| result.add_edge(u, v) }
177
178
  result
178
179
  end
@@ -5,7 +5,7 @@
5
5
  # all graphs in the library.
6
6
  require 'rgl/enumerable_ext'
7
7
 
8
- RGL_VERSION = "0.3.1"
8
+ RGL_VERSION = "0.4.0"
9
9
 
10
10
  module RGL
11
11
  class NotDirectedError < RuntimeError; end
@@ -0,0 +1,47 @@
1
+ require 'rgl/base'
2
+ require 'rgl/implicit'
3
+
4
+ module RGL
5
+ module Graph
6
+ # Returns an RGL::ImplicitGraph where the strongly connected components of
7
+ # this graph are condensed into single nodes represented by Set instances
8
+ # containing the members of each strongly connected component. Edges
9
+ # between the different strongly connected components are preserved while
10
+ # edges within strongly connected components are omitted.
11
+ #
12
+ # Raises RGL::NotDirectedError if run on an undirected graph.
13
+ def condensation_graph
14
+ raise NotDirectedError,
15
+ "condensation_graph only supported for directed graphs" unless directed?
16
+
17
+ # Get the component map for the strongly connected components.
18
+ comp_map = strongly_connected_components.comp_map
19
+ # Invert the map such that for any number, n, in the component map a Set
20
+ # instance is created containing all of the nodes which map to n. The Set
21
+ # instances will be used to map to the number, n, with which the elements
22
+ # of the set are associated.
23
+ inv_comp_map = {}
24
+ comp_map.each { |v, n| (inv_comp_map[n] ||= Set.new) << v }
25
+
26
+ # Create an ImplicitGraph where the nodes are the strongly connected
27
+ # components of this graph and the edges are the edges of this graph which
28
+ # cross between the strongly connected components.
29
+ ImplicitGraph.new do |g|
30
+ g.vertex_iterator do |b|
31
+ inv_comp_map.each_value(&b)
32
+ end
33
+ g.adjacent_iterator do |scc, b|
34
+ scc.each do |v|
35
+ each_adjacent(v) do |w|
36
+ # Do not make the cluster reference itself in the graph.
37
+ if comp_map[v] != comp_map[w] then
38
+ b.call(inv_comp_map[comp_map[w]])
39
+ end
40
+ end
41
+ end
42
+ end
43
+ g.directed = true
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,7 +1,7 @@
1
1
  # dot.rb
2
- #
3
- # $Id: dot.rb,v 1.7 2008/02/26 06:01:22 javanthropus Exp $
4
- #
2
+ #
3
+ # $Id: dot.rb,v 1.8 2008/08/26 20:07:09 javanthropus Exp $
4
+ #
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.
@@ -12,20 +12,20 @@ module RGL
12
12
 
13
13
  module Graph
14
14
 
15
- # Return a DOT::DOTDigraph for directed graphs or a DOT::DOTSubgraph for an
15
+ # Return a RGL::DOT::Digraph for directed graphs or a DOT::Subgraph for an
16
16
  # undirected Graph. _params_ can contain any graph property specified in
17
17
  # rdot.rb.
18
18
 
19
19
  def to_dot_graph (params = {})
20
20
  params['name'] ||= self.class.name.gsub(/:/,'_')
21
21
  fontsize = params['fontsize'] ? params['fontsize'] : '8'
22
- graph = (directed? ? DOT::DOTDigraph : DOT::DOTSubgraph).new(params)
23
- edge_class = directed? ? DOT::DOTDirectedEdge : DOT::DOTEdge
22
+ graph = (directed? ? DOT::Digraph : DOT::Subgraph).new(params)
23
+ edge_class = directed? ? DOT::DirectedEdge : DOT::Edge
24
24
  each_vertex do |v|
25
25
  name = v.to_s
26
- graph << DOT::DOTNode.new('name' => name,
27
- 'fontsize' => fontsize,
28
- 'label' => name)
26
+ graph << DOT::Node.new('name' => name,
27
+ 'fontsize' => fontsize,
28
+ 'label' => name)
29
29
  end
30
30
  each_edge do |u,v|
31
31
  graph << edge_class.new('from' => u.to_s,
@@ -41,8 +41,8 @@ module RGL
41
41
  s << to_dot_graph(params).to_s << "\n"
42
42
  end
43
43
 
44
- # Call dotty[http://www.graphviz.org] for the graph which is written to the file 'graph.dot'
45
- # in the # current directory.
44
+ # Call dotty[http://www.graphviz.org] for the graph which is written to the
45
+ # file 'graph.dot' in the # current directory.
46
46
 
47
47
  def dotty (params = {})
48
48
  dotfile = "graph.dot"
@@ -58,11 +58,11 @@ module RGL
58
58
  def write_to_graphic_file (fmt='png', dotfile="graph")
59
59
  src = dotfile + ".dot"
60
60
  dot = dotfile + "." + fmt
61
-
61
+
62
62
  File.open(src, 'w') do |f|
63
63
  f << self.to_dot_graph.to_s << "\n"
64
64
  end
65
-
65
+
66
66
  system( "dot -T#{fmt} #{src} -o #{dot}" )
67
67
  dot
68
68
  end
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # It also supports undirected edges.
5
5
 
6
- module DOT
6
+ module RGL; module DOT
7
7
 
8
8
  # options for node declaration
9
9
 
@@ -131,8 +131,8 @@ module DOT
131
131
  'layerseq'
132
132
  ]
133
133
 
134
- # Ancestor of DOTEdge, DOTNode, and DOTGraph.
135
- class DOTElement
134
+ # Ancestor of Edge, Node, and Graph.
135
+ class Element
136
136
  attr_accessor :name, :options
137
137
 
138
138
  def initialize (params = {}, option_list = []) # :nodoc:
@@ -151,7 +151,7 @@ module DOT
151
151
  id = id.to_s
152
152
 
153
153
  # Return the ID verbatim if it looks like a name, a number, or HTML.
154
- return id if id =~ /^([[:alpha:]_][[:alnum:]_]*|-?(\.[[:digit:]]+|[[:digit:]]+(\.[[:digit:]]*)?)|<.*>)$/
154
+ return id if id =~ /\A([[:alpha:]_][[:alnum:]_]*|-?(\.[[:digit:]]+|[[:digit:]]+(\.[[:digit:]]*)?)|<.*>)\Z/m and id[-1] != ?\n
155
155
 
156
156
  # Return a quoted version of the ID otherwise.
157
157
  '"' + id.gsub('\\', '\\\\\\\\').gsub('"', '\\\\"') + '"'
@@ -166,7 +166,7 @@ module DOT
166
166
  label = label.to_s
167
167
 
168
168
  # Return the label verbatim if it looks like a name, a number, or HTML.
169
- return label if label =~ /^([[:alpha:]_][[:alnum:]_]*|-?(\.[[:digit:]]+|[[:digit:]]+(\.[[:digit:]]*)?)|<.*>)$/
169
+ return label if label =~ /\A([[:alpha:]_][[:alnum:]_]*|-?(\.[[:digit:]]+|[[:digit:]]+(\.[[:digit:]]*)?)|<.*>)\Z/m and label[-1] != ?\n
170
170
 
171
171
  # Return a quoted version of the label otherwise.
172
172
  '"' + label.split(/(\\n|\\r|\\l)/).collect do |part|
@@ -181,9 +181,9 @@ module DOT
181
181
  end
182
182
 
183
183
 
184
- # Ports are used when a DOTNode instance has its `shape' option set to
184
+ # Ports are used when a Node instance has its `shape' option set to
185
185
  # _record_ or _Mrecord_. Ports can be nested.
186
- class DOTPort
186
+ class Port
187
187
  attr_accessor :name, :label, :ports
188
188
 
189
189
  # Create a new port with either an optional name and label or a set of
@@ -222,10 +222,10 @@ module DOT
222
222
 
223
223
  # A node representation. Edges are drawn between nodes. The rendering of a
224
224
  # node depends upon the options set for it.
225
- class DOTNode < DOTElement
225
+ class Node < Element
226
226
  attr_accessor :ports
227
227
 
228
- # Creates a new DOTNode with the _params_ Hash providing settings for all
228
+ # Creates a new Node with the _params_ Hash providing settings for all
229
229
  # node options. The _option_list_ parameter restricts those options to the
230
230
  # list of valid names it contains. The exception to this is the _ports_
231
231
  # option which, if specified, must be an Enumerable containing a list of
@@ -275,14 +275,14 @@ module DOT
275
275
  end
276
276
  end
277
277
 
278
- end # class DOTNode
278
+ end # class Node
279
279
 
280
280
  # A graph representation. Whether or not it is rendered as directed or
281
281
  # undirected depends on which of the programs *dot* or *neato* is used to
282
282
  # process and render the graph.
283
- class DOTGraph < DOTElement
283
+ class Graph < Element
284
284
 
285
- # Creates a new DOTGraph with the _params_ Hash providing settings for all
285
+ # Creates a new Graph with the _params_ Hash providing settings for all
286
286
  # graph options. The _option_list_ parameter restricts those options to the
287
287
  # list of valid names it contains. The exception to this is the _elements_
288
288
  # option which, if specified, must be an Enumerable containing a list of
@@ -349,14 +349,14 @@ module DOT
349
349
  (elements.empty? ? '' : elements + "\n") + leader + "}"
350
350
  end
351
351
 
352
- end # class DOTGraph
352
+ end # class Graph
353
353
 
354
- # A digraph is a directed graph representation which is the same as a DOTGraph
354
+ # A digraph is a directed graph representation which is the same as a Graph
355
355
  # except that its header in dot notation has an identifier of _digraph_
356
356
  # instead of _graph_.
357
- class DOTDigraph < DOTGraph
357
+ class Digraph < Graph
358
358
 
359
- # Creates a new DOTDigraph with the _params_ Hash providing settings for all
359
+ # Creates a new Digraph with the _params_ Hash providing settings for all
360
360
  # graph options. The _option_list_ parameter restricts those options to the
361
361
  # list of valid names it contains. The exception to this is the _elements_
362
362
  # option which, if specified, must be an Enumerable containing a list of
@@ -366,14 +366,14 @@ module DOT
366
366
  @dot_string = 'digraph'
367
367
  end
368
368
 
369
- end # class DOTDigraph
369
+ end # class Digraph
370
370
 
371
- # A subgraph is a nested graph element and is the same as a DOTGraph except
371
+ # A subgraph is a nested graph element and is the same as a Graph except
372
372
  # that its header in dot notation has an identifier of _subgraph_ instead of
373
373
  # _graph_.
374
- class DOTSubgraph < DOTGraph
374
+ class Subgraph < Graph
375
375
 
376
- # Creates a new DOTSubgraph with the _params_ Hash providing settings for
376
+ # Creates a new Subgraph with the _params_ Hash providing settings for
377
377
  # all graph options. The _option_list_ parameter restricts those options to
378
378
  # list of valid names it contains. The exception to this is the _elements_
379
379
  # option which, if specified, must be an Enumerable containing a list of
@@ -383,10 +383,10 @@ module DOT
383
383
  @dot_string = 'subgraph'
384
384
  end
385
385
 
386
- end # class DOTSubgraph
386
+ end # class Subgraph
387
387
 
388
388
  # This is an undirected edge representation.
389
- class DOTEdge < DOTElement
389
+ class Edge < Element
390
390
 
391
391
  # A node or subgraph reference or instance to be used as the starting point
392
392
  # for an edge.
@@ -395,7 +395,7 @@ module DOT
395
395
  # for an edge.
396
396
  attr_accessor :to
397
397
 
398
- # Creates a new DOTEdge with the _params_ Hash providing settings for all
398
+ # Creates a new Edge with the _params_ Hash providing settings for all
399
399
  # edge options. The _option_list_ parameter restricts those options to the
400
400
  # list of valid names it contains.
401
401
  def initialize (params = {}, option_list = EDGE_OPTS)
@@ -431,15 +431,15 @@ module DOT
431
431
  '--'
432
432
  end
433
433
 
434
- end # class DOTEdge
434
+ end # class Edge
435
435
 
436
- # A directed edge representation otherwise identical to DOTEdge.
437
- class DOTDirectedEdge < DOTEdge
436
+ # A directed edge representation otherwise identical to Edge.
437
+ class DirectedEdge < Edge
438
438
 
439
439
  private
440
440
  def edge_link
441
441
  '->'
442
442
  end
443
443
 
444
- end # class DOTDirectedEdge
445
- end # module DOT
444
+ end # class DirectedEdge
445
+ end; end # module RGL; module DOT
@@ -1,46 +1,2 @@
1
- # transitiv_closure.rb
2
- #
3
- # == transitive_closure
4
- #
5
- # The transitive closure of a graph G = (V,E) is a graph G* = (V,E*),
6
- # such that E* contains an edge (u,v) if and only if G contains a path
7
- # (of at least one edge) from u to v. The transitive_closure() function
8
- # transforms the input graph g into the transitive closure graph tc.
9
-
10
- require 'rgl/adjacency'
11
-
12
- module RGL
13
-
14
- module Graph
15
-
16
- # Floyd-Warshal algorithm which should be O(n^3), where n is the number of
17
- # nodes. We can probably work a bit on the constant factors!
18
- #
19
- # In BGL, there is an algorithm with time complexity (worst-case) O(|V||E|)
20
- # (see BOOST_DOC/transitive_closure.html), based on the detection of strong
21
- # components.
22
-
23
- def transitive_closure_floyd_warshal
24
- raise NotDirectedError,
25
- "transitive_closure makes sense only for directed graphs." unless directed?
26
- tc = to_adjacency # direct links
27
-
28
- # indirect links
29
-
30
- each_vertex do |vi|
31
- each_vertex do |vj|
32
- each_vertex do |vk|
33
- unless tc.has_edge?(vi, vj)
34
- tc.add_edge(vi, vj) if has_edge?(vi, vk) and
35
- has_edge?(vk, vj)
36
- end
37
- end
38
- end
39
- end
40
- tc
41
- end
42
-
43
- alias_method :transitive_closure, :transitive_closure_floyd_warshal
44
-
45
- end # module Graph
46
- end # module RGL
1
+ # This file is deprecated and only provided for backward compatibility.
2
+ require 'rgl/transitivity'