yargi 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +54 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +23 -0
- data/LICENCE.md +22 -0
- data/Manifest.txt +15 -0
- data/README.md +128 -0
- data/Rakefile +23 -0
- data/examples/fs2dot.rb +1 -1
- data/examples/random.rb +20 -0
- data/lib/yargi.rb +8 -10
- data/lib/yargi/decorate.rb +55 -0
- data/lib/yargi/digraph.rb +71 -46
- data/lib/yargi/digraph_edge.rb +23 -23
- data/lib/yargi/digraph_vertex.rb +27 -27
- data/lib/yargi/edge_set.rb +12 -12
- data/lib/yargi/element_set.rb +54 -54
- data/lib/yargi/loader.rb +1 -0
- data/lib/yargi/markable.rb +12 -12
- data/lib/yargi/predicate.rb +62 -43
- data/lib/yargi/random.rb +98 -0
- data/lib/yargi/version.rb +14 -0
- data/lib/yargi/vertex_set.rb +12 -12
- data/spec/spec_helper.rb +2 -0
- data/spec/test_decorate.rb +28 -0
- data/spec/test_digraph.rb +42 -0
- data/spec/test_random.rb +45 -0
- data/spec/test_yargi.rb +8 -0
- data/tasks/debug_mail.rake +75 -0
- data/tasks/debug_mail.txt +13 -0
- data/tasks/gem.rake +68 -0
- data/tasks/spec_test.rake +71 -0
- data/tasks/unit_test.rake +76 -0
- data/tasks/yard.rake +51 -0
- data/test/test_all.rb +1 -1
- data/test/yargi/README-example.gif +0 -0
- data/test/yargi/digraph_set_features_test.rb +14 -16
- data/test/yargi/digraph_test.rb +33 -33
- data/test/yargi/digraph_vertex_test.rb +9 -9
- data/test/yargi/documentation_test.rb +7 -7
- data/test/yargi/edge_set_test.rb +3 -3
- data/test/yargi/element_set_test.rb +2 -2
- data/test/yargi/hypotheses_test.rb +4 -4
- data/test/yargi/markable_test.rb +11 -11
- data/test/yargi/predicate_test.rb +14 -14
- data/test/yargi/source-sink.gif +0 -0
- data/test/yargi/vertex_set_test.rb +7 -7
- data/yargi.gemspec +187 -0
- data/yargi.noespec +23 -0
- metadata +110 -38
- data/CONTRIBUTE +0 -11
- data/LICENCE +0 -25
- data/README +0 -79
- data/examples/fs2dot.dot +0 -78
- data/examples/fs2dot.gif +0 -0
data/lib/yargi/digraph_edge.rb
CHANGED
@@ -1,81 +1,81 @@
|
|
1
1
|
module Yargi
|
2
2
|
class Digraph
|
3
|
-
|
3
|
+
|
4
4
|
#
|
5
5
|
# Edge inside a digraph
|
6
6
|
#
|
7
|
-
# Methods reconnect, index= are provided for Digraph itself and are not
|
8
|
-
# intended to be used directly. Probably unexpectedly, source and target
|
7
|
+
# Methods reconnect, index= are provided for Digraph itself and are not
|
8
|
+
# intended to be used directly. Probably unexpectedly, source and target
|
9
9
|
# writers are provided as reconnection shortcuts and can be used by users.
|
10
10
|
#
|
11
11
|
class Edge
|
12
12
|
include Yargi::Markable
|
13
|
-
|
13
|
+
|
14
14
|
# Owning graph
|
15
15
|
attr_reader :graph
|
16
16
|
alias :digraph :graph
|
17
|
-
|
17
|
+
|
18
18
|
# Index in the vertices list of the owner
|
19
19
|
attr_accessor :index
|
20
|
-
|
20
|
+
|
21
21
|
# Source vertex
|
22
22
|
attr_reader :source
|
23
|
-
|
23
|
+
|
24
24
|
# Target vertex
|
25
25
|
attr_reader :target
|
26
|
-
|
26
|
+
|
27
27
|
# Creates an edge instance
|
28
28
|
def initialize(graph, index, source, target)
|
29
29
|
@graph, @index = graph, index
|
30
30
|
@source, @target = source, target
|
31
31
|
end
|
32
32
|
|
33
|
-
|
33
|
+
|
34
34
|
### Pseudo-protected section ##########################################
|
35
|
-
|
35
|
+
|
36
36
|
# Reconnects source and target
|
37
37
|
def reconnect(source, target)
|
38
38
|
@source = source if source
|
39
39
|
@target = target if target
|
40
40
|
end
|
41
41
|
|
42
|
-
|
42
|
+
|
43
43
|
### Query section #######################################################
|
44
|
-
|
44
|
+
|
45
45
|
# Returns edge extremities
|
46
46
|
def extremities
|
47
47
|
VertexSet[source, target]
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
# Shortcut for digraph.reconnect(edge, source, nil)
|
51
51
|
def source=(source)
|
52
52
|
@graph.reconnect(self, source, nil)
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
# Shortcut for digraph.reconnect(edge, nil, target)
|
56
56
|
def target=(target)
|
57
57
|
@graph.reconnect(self, nil, target)
|
58
58
|
end
|
59
|
-
|
60
|
-
|
59
|
+
|
60
|
+
|
61
61
|
### Sort, Hash, etc. section ############################################
|
62
|
-
|
62
|
+
|
63
63
|
# Compares indexes
|
64
64
|
def <=>(other)
|
65
65
|
return nil unless Edge===other and self.graph==other.graph
|
66
66
|
self.index <=> other.index
|
67
67
|
end
|
68
|
-
|
69
|
-
|
68
|
+
|
69
|
+
|
70
70
|
### Export section ######################################################
|
71
|
-
|
71
|
+
|
72
72
|
# Returns a string representation
|
73
73
|
def to_s; "e#{index}:#{source.to_s}->#{target.to_s}" end
|
74
|
-
|
74
|
+
|
75
75
|
# Inspects the vertex
|
76
76
|
def inspect; "e#{index}:#{source.inspect}->#{target.inspect}" end
|
77
|
-
|
77
|
+
|
78
78
|
end # class Edge
|
79
|
-
|
79
|
+
|
80
80
|
end
|
81
81
|
end
|
data/lib/yargi/digraph_vertex.rb
CHANGED
@@ -1,98 +1,98 @@
|
|
1
1
|
module Yargi
|
2
2
|
class Digraph
|
3
|
-
|
3
|
+
|
4
4
|
#
|
5
5
|
# Vertex inside a digraph.
|
6
6
|
#
|
7
|
-
# Methods add_in_edge, remove_in_edge, add_out_edge, remove_out_edge and index=
|
7
|
+
# Methods add_in_edge, remove_in_edge, add_out_edge, remove_out_edge and index=
|
8
8
|
# are provided for Digraph itself and are not intended to be used directly.
|
9
9
|
#
|
10
10
|
class Vertex
|
11
11
|
include Yargi::Markable
|
12
|
-
|
12
|
+
|
13
13
|
# Owning graph
|
14
14
|
attr_reader :graph
|
15
15
|
alias :digraph :graph
|
16
|
-
|
16
|
+
|
17
17
|
# Index in the vertices list of the owner
|
18
18
|
attr_accessor :index
|
19
|
-
|
19
|
+
|
20
20
|
# Creates a vertex instance
|
21
21
|
def initialize(graph, index)
|
22
22
|
@graph, @index = graph, index
|
23
23
|
@in_edges, @out_edges = EdgeSet[], EdgeSet[]
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
|
27
27
|
### Query section #######################################################
|
28
|
-
|
28
|
+
|
29
29
|
# Returns a copy of the incoming edges list.
|
30
30
|
def in_edges(filter=nil, &block)
|
31
31
|
@in_edges.filter(filter, &block)
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
# Returns a copy of the outgoing edges list.
|
35
35
|
def out_edges(filter=nil, &block)
|
36
36
|
@out_edges.filter(filter, &block)
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# Returns all adjacent vertices
|
40
40
|
def adjacent(filter=nil, &block)
|
41
41
|
(in_adjacent(filter, &block) + out_adjacent(filter, &block)).uniq
|
42
42
|
end
|
43
|
-
|
44
|
-
# Returns back-adjacent vertices
|
43
|
+
|
44
|
+
# Returns back-adjacent vertices
|
45
45
|
def in_adjacent(filter=nil, &block)
|
46
46
|
@in_edges.source.filter(filter, &block)
|
47
47
|
end
|
48
|
-
|
49
|
-
# Returns forward-adjacent vertices
|
48
|
+
|
49
|
+
# Returns forward-adjacent vertices
|
50
50
|
def out_adjacent(filter=nil, &block)
|
51
51
|
@out_edges.target.filter(filter, &block)
|
52
52
|
end
|
53
53
|
|
54
|
-
|
54
|
+
|
55
55
|
### Pseudo-protected section ##########################################
|
56
|
-
|
56
|
+
|
57
57
|
# Adds an incoming edge
|
58
58
|
def add_in_edge(edge)
|
59
59
|
@in_edges << edge
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
# Removes an incoming edge
|
63
63
|
def remove_in_edge(edge)
|
64
64
|
@in_edges.delete(edge)
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
# Adds an outgoing edge
|
68
68
|
def add_out_edge(edge)
|
69
69
|
@out_edges << edge
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
# Removes an outgoing edge
|
73
73
|
def remove_out_edge(edge)
|
74
74
|
@out_edges.delete(edge)
|
75
75
|
end
|
76
|
-
|
77
|
-
|
76
|
+
|
77
|
+
|
78
78
|
### Sort, Hash, etc. section ############################################
|
79
|
-
|
79
|
+
|
80
80
|
# Compares indexes
|
81
81
|
def <=>(other)
|
82
82
|
return nil unless Vertex===other and self.graph==other.graph
|
83
83
|
self.index <=> other.index
|
84
84
|
end
|
85
|
-
|
86
|
-
|
85
|
+
|
86
|
+
|
87
87
|
### Export section ######################################################
|
88
|
-
|
88
|
+
|
89
89
|
# Returns a string representation
|
90
90
|
def to_s; "V#{index}" end
|
91
|
-
|
91
|
+
|
92
92
|
# Inspects the vertex
|
93
93
|
def inspect; "V#{index}" end
|
94
|
-
|
94
|
+
|
95
95
|
end # class Vertex
|
96
|
-
|
96
|
+
|
97
97
|
end
|
98
98
|
end
|
data/lib/yargi/edge_set.rb
CHANGED
@@ -1,45 +1,45 @@
|
|
1
1
|
module Yargi
|
2
|
-
|
2
|
+
|
3
3
|
# A set of edges
|
4
4
|
class EdgeSet < ElementSet
|
5
|
-
|
5
|
+
|
6
6
|
### Factory section #######################################################
|
7
|
-
|
7
|
+
|
8
8
|
# Creates a VertexSet instance using _elements_ varargs.
|
9
9
|
def self.[](*elements)
|
10
10
|
EdgeSet.new(elements)
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
### Walking section #######################################################
|
14
|
-
|
14
|
+
|
15
15
|
# Returns a VertexSet with reachable vertices using the edges of this set.
|
16
16
|
def target
|
17
17
|
VertexSet.new(self.collect {|e| e.target}).uniq
|
18
18
|
end
|
19
19
|
alias :targets :target
|
20
|
-
|
21
|
-
# Returns a VertexSet with back-reachable vertices using the edges of this
|
20
|
+
|
21
|
+
# Returns a VertexSet with back-reachable vertices using the edges of this
|
22
22
|
# set.
|
23
23
|
def source
|
24
24
|
VertexSet.new(self.collect {|e| e.source}).uniq
|
25
25
|
end
|
26
26
|
alias :sources :source
|
27
|
-
|
27
|
+
|
28
28
|
### Writing section #######################################################
|
29
|
-
|
29
|
+
|
30
30
|
# Fired to each edge in the set
|
31
31
|
def source=(source)
|
32
32
|
self.each{|e| e.source=source}
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
# Fired to each edge in the set
|
36
36
|
def target=(target)
|
37
37
|
self.each{|e| e.target=target}
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
### Protected section #####################################################
|
41
41
|
protected
|
42
|
-
|
42
|
+
|
43
43
|
# Extends with EdgeSet instead of ElementSet
|
44
44
|
def extend_result(result)
|
45
45
|
EdgeSet.new(result)
|
data/lib/yargi/element_set.rb
CHANGED
@@ -1,139 +1,139 @@
|
|
1
1
|
require 'delegate'
|
2
2
|
|
3
3
|
module Yargi
|
4
|
-
|
4
|
+
|
5
5
|
# Main module of VertexSet and EdgeSet
|
6
6
|
class ElementSet < Array
|
7
|
-
|
7
|
+
|
8
8
|
### Factory section #######################################################
|
9
|
-
|
9
|
+
|
10
10
|
# Creates a ElementSet instance using _elements_ varargs.
|
11
11
|
def self.[](*elements)
|
12
12
|
ElementSet.new(elements)
|
13
13
|
end
|
14
|
-
|
15
|
-
|
14
|
+
|
15
|
+
|
16
16
|
### Array handling ########################################################
|
17
17
|
|
18
18
|
# Same as Array.dup
|
19
19
|
def dup() # :nodoc: #
|
20
|
-
extend_result(super)
|
20
|
+
extend_result(super)
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
# See Array.compact
|
24
24
|
def compact() # :nodoc: #
|
25
|
-
extend_result(super)
|
25
|
+
extend_result(super)
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
# See Array.flatten
|
29
29
|
def flatten() # :nodoc: #
|
30
|
-
extend_result(super)
|
30
|
+
extend_result(super)
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
# See Array.reverse
|
34
34
|
def reverse() # :nodoc: #
|
35
|
-
extend_result(super)
|
35
|
+
extend_result(super)
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
# See Array.uniq
|
39
39
|
def uniq() # :nodoc: #
|
40
|
-
extend_result(super)
|
40
|
+
extend_result(super)
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
# See Array.sort
|
44
44
|
def sort(&block) # :nodoc: #
|
45
|
-
extend_result(super(&block))
|
45
|
+
extend_result(super(&block))
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
# See Array.concat
|
49
49
|
def concat(other) # :nodoc: #
|
50
50
|
extend_result(super(other))
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
# See Array.[]
|
54
54
|
def [](*args) # :nodoc: #
|
55
55
|
result = super(*args)
|
56
|
-
Array===result ? extend_result(result) : result
|
56
|
+
Array===result ? extend_result(result) : result
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
# See Array.+
|
60
60
|
def +(right) # :nodoc: #
|
61
|
-
extend_result(super(right))
|
61
|
+
extend_result(super(right))
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
# See Array.-
|
65
65
|
def -(right) # :nodoc: #
|
66
|
-
extend_result(super(right))
|
66
|
+
extend_result(super(right))
|
67
67
|
end
|
68
|
-
|
69
|
-
|
68
|
+
|
69
|
+
|
70
70
|
### Enumerable handling ###################################################
|
71
|
-
|
71
|
+
|
72
72
|
# See Enumerable.each_cons
|
73
73
|
def each_cons(n) # :nodoc: #
|
74
|
-
super(n) {|c| yield extend_result(c)}
|
74
|
+
super(n) {|c| yield extend_result(c)}
|
75
75
|
end
|
76
|
-
|
76
|
+
|
77
77
|
# See Enumerable.each_slice
|
78
78
|
def each_slice(n) # :nodoc: #
|
79
|
-
super(n) {|c| yield extend_result(c)}
|
79
|
+
super(n) {|c| yield extend_result(c)}
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
# See Enumerable.select
|
83
83
|
def select(&block) # :nodoc: #
|
84
|
-
extend_result(super(&block))
|
84
|
+
extend_result(super(&block))
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
# See Enumerable.find_all
|
88
88
|
def find_all(&block) # :nodoc: #
|
89
|
-
extend_result(super(&block))
|
89
|
+
extend_result(super(&block))
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
# See Enumerable.grep
|
93
93
|
def grep(pattern, &block) # :nodoc: #
|
94
94
|
greped = super(pattern, &block)
|
95
95
|
block_given? ? greped : extend_result(greped)
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
# See Enumerable.reject
|
99
99
|
def partition(&block) # :nodoc: #
|
100
100
|
p = super(&block)
|
101
101
|
[extend_result(p[0]), extend_result(p[1])]
|
102
102
|
end
|
103
|
-
|
103
|
+
|
104
104
|
# See Enumerable.reject
|
105
105
|
def reject(&block) # :nodoc: #
|
106
|
-
extend_result(super(&block))
|
106
|
+
extend_result(super(&block))
|
107
107
|
end
|
108
|
-
|
109
|
-
|
108
|
+
|
109
|
+
|
110
110
|
### Markable handling #####################################################
|
111
|
-
|
112
|
-
# Fired to each element of the group.
|
111
|
+
|
112
|
+
# Fired to each element of the group.
|
113
113
|
def tag(*modules)
|
114
114
|
self.each {|elm| elm.tag(*modules)}
|
115
115
|
end
|
116
|
-
|
117
|
-
# Collects result of get_mark invocation on each element of the
|
116
|
+
|
117
|
+
# Collects result of get_mark invocation on each element of the
|
118
118
|
# group and returns it as an array.
|
119
119
|
def get_mark(key)
|
120
120
|
self.collect {|elm| elm.get_mark(key)}
|
121
121
|
end
|
122
122
|
|
123
|
-
# Fired to each element of the group. Values are duplicated by default.
|
123
|
+
# Fired to each element of the group. Values are duplicated by default.
|
124
124
|
# Put dup to false to avoid this behavior.
|
125
125
|
def set_mark(key, value, dup=true)
|
126
126
|
self.each {|elm| elm.set_mark(key, (dup and not(Symbol===value)) ? value.dup : value)}
|
127
127
|
end
|
128
|
-
|
128
|
+
|
129
129
|
# When _marks_ is provided, the invocation is fired to all group
|
130
130
|
# elements. When a block is given, it is called on each element,
|
131
131
|
# passing it as argument. If the block returns a hash, that hash
|
132
|
-
# is installed as marks on the iterated element.
|
132
|
+
# is installed as marks on the iterated element.
|
133
133
|
# The two usages (_marks_ and block) can be used conjointly.
|
134
134
|
def add_marks(marks=nil)
|
135
135
|
self.each {|elm| elm.add_marks(marks)} if marks
|
136
|
-
if block_given?
|
136
|
+
if block_given?
|
137
137
|
self.each do |elm|
|
138
138
|
hash = yield elm
|
139
139
|
elm.add_marks(hash) if Hash===hash
|
@@ -141,20 +141,20 @@ module Yargi
|
|
141
141
|
end
|
142
142
|
end
|
143
143
|
alias :merge_marks :add_marks
|
144
|
-
|
145
|
-
|
144
|
+
|
145
|
+
|
146
146
|
### Query handling ########################################################
|
147
|
-
|
148
|
-
# Filters this set with a 'predicate and block' predicate
|
147
|
+
|
148
|
+
# Filters this set with a 'predicate and block' predicate
|
149
149
|
# (see Yargi::Predicate)
|
150
150
|
def filter(predicate=nil, &block)
|
151
151
|
pred = Yargi::Predicate.to_predicate(predicate, &block)
|
152
152
|
extend_result(self.select{|e| pred===e})
|
153
153
|
end
|
154
|
-
|
154
|
+
|
155
155
|
### Protected section #####################################################
|
156
156
|
protected
|
157
|
-
|
157
|
+
|
158
158
|
# Extends a resulting array with the module. This method is intended
|
159
159
|
# to be overrided by specialization of this module.
|
160
160
|
def extend_result(result)
|
@@ -162,5 +162,5 @@ module Yargi
|
|
162
162
|
end
|
163
163
|
|
164
164
|
end # class ElementSet
|
165
|
-
|
165
|
+
|
166
166
|
end
|