rgl 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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'