graphs 0.1.2-x86-linux → 0.1.3-x86-linux
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/graph.rb +86 -0
- data/tests/tests_graph.rb +113 -0
- metadata +1 -1
data/lib/graph.rb
CHANGED
@@ -5,6 +5,80 @@ require 'yaml'
|
|
5
5
|
# A graph with nodes and edges
|
6
6
|
class Graph
|
7
7
|
|
8
|
+
# Return a new Graph which is the intersection of every given graphs.
|
9
|
+
# Each node of the intersection is in every given graph (idem for edges).
|
10
|
+
# The last argument may be a hash of options.
|
11
|
+
# @option options [Boolean] :same_fields use only fields which are in every
|
12
|
+
# graph to perform the intersection
|
13
|
+
# @see Graph#&
|
14
|
+
def Graph::intersection(*graphs)
|
15
|
+
return nil if graphs.length == 0
|
16
|
+
|
17
|
+
opts = {}
|
18
|
+
|
19
|
+
if graphs[-1].is_a?(Hash)
|
20
|
+
return nil if graphs.length == 1
|
21
|
+
opts.update(graphs.pop)
|
22
|
+
end
|
23
|
+
|
24
|
+
graphs.each {|g|
|
25
|
+
if (!g.is_a?(Graph))
|
26
|
+
return nil
|
27
|
+
end
|
28
|
+
}
|
29
|
+
|
30
|
+
if opts[:same_fields]
|
31
|
+
graphs.map! {|g| g.clone}
|
32
|
+
|
33
|
+
# every first node of every graphs
|
34
|
+
nodes_ref = graphs.map {|g| g.nodes[0] || {}}
|
35
|
+
# every first edge of every graphs
|
36
|
+
edges_ref = graphs.map {|g| g.edges[0] || {}}
|
37
|
+
|
38
|
+
nodes_keys_ref = nodes_ref.map {|n| n.keys}
|
39
|
+
edges_keys_ref = edges_ref.map {|e| e.keys}
|
40
|
+
|
41
|
+
# keep only same keys
|
42
|
+
nodes_keys_uniq = nodes_keys_ref.inject {|i,e| i &= e}
|
43
|
+
edges_keys_uniq = edges_keys_ref.inject {|i,e| i &= e}
|
44
|
+
|
45
|
+
graphs.map! {|g|
|
46
|
+
g.nodes.map! { |n|
|
47
|
+
|
48
|
+
newnode = {}
|
49
|
+
|
50
|
+
n.each_key { |k|
|
51
|
+
newnode[k] = n[k] if nodes_keys_uniq.include?(k)
|
52
|
+
}
|
53
|
+
|
54
|
+
newnode
|
55
|
+
}
|
56
|
+
g.edges.map! { |n|
|
57
|
+
|
58
|
+
newedge = {}
|
59
|
+
|
60
|
+
n.each_key { |k|
|
61
|
+
newedge[k] = n[k] if edges_keys_uniq.include?(k)
|
62
|
+
}
|
63
|
+
|
64
|
+
newedge
|
65
|
+
}
|
66
|
+
g
|
67
|
+
}
|
68
|
+
|
69
|
+
elsif graphs.length == 2
|
70
|
+
return graphs[0] & graphs[1]
|
71
|
+
end
|
72
|
+
|
73
|
+
graph = graphs.shift.clone
|
74
|
+
|
75
|
+
graphs.each { |g|
|
76
|
+
graph &= g
|
77
|
+
}
|
78
|
+
|
79
|
+
return graph
|
80
|
+
end
|
81
|
+
|
8
82
|
# An array of nodes, each node is an hash of label/value paires
|
9
83
|
class NodeArray < Array
|
10
84
|
|
@@ -70,6 +144,18 @@ class Graph
|
|
70
144
|
Graph.new(nodes, edges)
|
71
145
|
end
|
72
146
|
|
147
|
+
# Clone the current graph. All nodes and edges are also cloned.
|
148
|
+
def clone()
|
149
|
+
g = Graph.new
|
150
|
+
g.nodes = self.nodes.clone
|
151
|
+
g.edges = self.edges.clone
|
152
|
+
|
153
|
+
g.nodes.map! {|h| h.clone}
|
154
|
+
g.edges.map! {|h| h.clone}
|
155
|
+
|
156
|
+
g
|
157
|
+
end
|
158
|
+
|
73
159
|
# Write the current Graph into a file.
|
74
160
|
# @param filename [String] A valid filename
|
75
161
|
# @param opts [Hash] A customizable set of options
|
data/tests/tests_graph.rb
CHANGED
@@ -34,6 +34,105 @@ class Graph_test < Test::Unit::TestCase
|
|
34
34
|
]
|
35
35
|
)
|
36
36
|
|
37
|
+
# == Graph::intersection == #
|
38
|
+
|
39
|
+
def test_intersection_no_graphs
|
40
|
+
assert_equal(nil, Graph::intersection)
|
41
|
+
assert_equal(nil, Graph::intersection({:same_fields => true}))
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_intersection_2_empty_graphs
|
45
|
+
g = Graph.new
|
46
|
+
h = g.clone
|
47
|
+
|
48
|
+
assert_equal(h, Graph::intersection(g, g))
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_intersection_4_empty_graphs_intersection
|
52
|
+
g = Graph.new
|
53
|
+
h = g.clone
|
54
|
+
|
55
|
+
assert_equal(h, Graph::intersection(g, g, g, g))
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_intersection_one_node_graph_and_empty_graph
|
59
|
+
g = Graph.new([{'label'=>'foo'}])
|
60
|
+
empty = Graph.new
|
61
|
+
empty2 = empty.clone
|
62
|
+
|
63
|
+
assert_equal(empty2, Graph::intersection(g, empty))
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_intersection_sample_graph_and_itself_5_times
|
67
|
+
g = @@sample_graph
|
68
|
+
h = g.clone
|
69
|
+
|
70
|
+
assert_equal(h, Graph::intersection(g, g, g, g, g))
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_intersection_sample_graph_and_itself_5_times_and_empty_graph
|
74
|
+
g = @@sample_graph
|
75
|
+
empty = Graph.new
|
76
|
+
empty2 = empty.clone
|
77
|
+
|
78
|
+
assert_equal(empty2, Graph::intersection(g, g, empty, g, g, g))
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_intersection_one_node_graph_and_one_other_node_graph
|
82
|
+
g = Graph.new([{'label'=>'foo'}])
|
83
|
+
h = Graph.new([{'label'=>'bar'}])
|
84
|
+
empty = Graph.new
|
85
|
+
|
86
|
+
assert_equal(empty, Graph::intersection(g, h))
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_intersection_sample_graph_and_no_graph
|
90
|
+
g = @@sample_graph
|
91
|
+
|
92
|
+
assert_equal(nil, Graph::intersection(g, 2))
|
93
|
+
assert_equal(nil, Graph::intersection(g, true))
|
94
|
+
assert_equal(nil, Graph::intersection(g, false))
|
95
|
+
assert_equal(nil, Graph::intersection(g, ['foo', 'bar']))
|
96
|
+
assert_equal(nil, Graph::intersection(g, 'foo'))
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_intersection_2_graphs_same_nodes_different_fields
|
100
|
+
g1 = @@sample_graph.clone
|
101
|
+
g2 = @@sample_graph_1.clone
|
102
|
+
empty = Graph.new
|
103
|
+
|
104
|
+
assert_equal(empty, Graph::intersection(g1, g2))
|
105
|
+
# test for side effects
|
106
|
+
assert_equal(@@sample_graph, g1)
|
107
|
+
assert_equal(@@sample_graph_1, g2)
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_intersection_2_graphs_same_nodes_different_fields_same_fields_option
|
111
|
+
g1 = @@sample_graph.clone
|
112
|
+
g2 = @@sample_graph_1.clone
|
113
|
+
|
114
|
+
intersec = Graph.new(
|
115
|
+
[
|
116
|
+
{'label'=>'foo'},
|
117
|
+
{'label'=>'bar'},
|
118
|
+
{'label'=>'chuck'}
|
119
|
+
],
|
120
|
+
[
|
121
|
+
{'node1'=>'foo', 'node2'=>'bar'},
|
122
|
+
{'node1'=>'bar', 'node2'=>'foo'},
|
123
|
+
{'node1'=>'foo', 'node2'=>'chuck'}
|
124
|
+
]
|
125
|
+
)
|
126
|
+
|
127
|
+
assert_equal(intersec, Graph::intersection(g1, g2, :same_fields => true))
|
128
|
+
# test for side effects
|
129
|
+
assert_equal(@@sample_graph, g1)
|
130
|
+
assert_equal(@@sample_graph_1, g2)
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
# == Graph#new == #
|
135
|
+
|
37
136
|
def test_new_empty_graph
|
38
137
|
g = Graph.new
|
39
138
|
|
@@ -41,6 +140,20 @@ class Graph_test < Test::Unit::TestCase
|
|
41
140
|
assert_equal([], g.edges)
|
42
141
|
end
|
43
142
|
|
143
|
+
# == Graph#clone == #
|
144
|
+
|
145
|
+
def test_empty_graph_clone
|
146
|
+
g = Graph.new
|
147
|
+
h = g.clone
|
148
|
+
|
149
|
+
assert_equal(g, h)
|
150
|
+
|
151
|
+
h.nodes.push({})
|
152
|
+
|
153
|
+
assert_equal(0, g.nodes.length)
|
154
|
+
assert_not_equal(g, h)
|
155
|
+
end
|
156
|
+
|
44
157
|
# == Graph#== == #
|
45
158
|
|
46
159
|
def test_equal_graphs
|