rbgraph 0.0.15 → 0.1.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.
- checksums.yaml +4 -4
- data/lib/rbgraph/edge.rb +28 -35
- data/lib/rbgraph/graph.rb +37 -31
- data/lib/rbgraph/graphs/directed.rb +2 -2
- data/lib/rbgraph/graphs/undirected.rb +2 -2
- data/lib/rbgraph/node.rb +35 -22
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6802faf7d27b90722ed3e60db98fb448c2bcaf4e
|
4
|
+
data.tar.gz: dbbc67f346e322fba63e9400d3f45fcab0b2e9c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5ad1891b6dd29d0dcbcac9c66769009a7fb0e55e4abbf469482efe6da486616b40613a779cd990c8ee07ea5d7d14786e390dc07a5e514fd338f0e5624861fdb
|
7
|
+
data.tar.gz: 233f7cf3a5e6bc70b738a91f3de6d7c0c06ce22c904fda430315bd26953d81c0ad57318162c2cb41771770b68ee4782f0c0bb34174e5a5677e6c9214628a4697
|
data/lib/rbgraph/edge.rb
CHANGED
@@ -7,17 +7,18 @@ module Rbgraph
|
|
7
7
|
attr_accessor :node1
|
8
8
|
attr_accessor :node2
|
9
9
|
attr_accessor :weight
|
10
|
-
attr_accessor :
|
11
|
-
attr_accessor :
|
12
|
-
|
13
|
-
def initialize(node1, node2,
|
14
|
-
self.
|
15
|
-
self.
|
16
|
-
self.
|
17
|
-
|
18
|
-
self.
|
19
|
-
|
20
|
-
self.
|
10
|
+
attr_accessor :kind
|
11
|
+
attr_accessor :data
|
12
|
+
|
13
|
+
def initialize(graph, node1, node2, weight, kind, data = {})
|
14
|
+
self.graph = graph
|
15
|
+
self.node1 = node1
|
16
|
+
self.node2 = node2
|
17
|
+
self.weight = weight.nil? ? 1 : weight.to_i
|
18
|
+
self.kind = kind
|
19
|
+
nodes_ids = graph.directed? ? [node1.id, node2.id] : [node1.id, node2.id].sort
|
20
|
+
self.id = "%s=#{kind}=%s" % nodes_ids
|
21
|
+
self.data = data
|
21
22
|
end
|
22
23
|
|
23
24
|
def ==(node)
|
@@ -26,7 +27,11 @@ module Rbgraph
|
|
26
27
|
alias_method :==, :eql?
|
27
28
|
|
28
29
|
def hash
|
29
|
-
id
|
30
|
+
id.hash
|
31
|
+
end
|
32
|
+
|
33
|
+
def attributes
|
34
|
+
{id: id, weight: weight, kind: kind, data: data}
|
30
35
|
end
|
31
36
|
|
32
37
|
def has_node?(node)
|
@@ -38,45 +43,33 @@ module Rbgraph
|
|
38
43
|
node == node1 ? node2 : node1
|
39
44
|
end
|
40
45
|
|
41
|
-
def merge(edge)
|
42
|
-
raise "Cannot merge directed and undirected edge!" if directed ^ edge.directed # XOR
|
46
|
+
def merge!(edge, &block)
|
43
47
|
self.weight += edge.weight unless edge.weight.nil?
|
44
|
-
|
48
|
+
raise "Cannot merging edges of different kind!" if kind != edge.kind
|
49
|
+
data.merge!(edge.data, &block)
|
50
|
+
graph.remove_edge!(edge)
|
45
51
|
self
|
46
52
|
end
|
47
53
|
|
48
54
|
def out_for?(node)
|
49
|
-
|
50
|
-
node == node1
|
51
|
-
else
|
52
|
-
has_node?(node)
|
53
|
-
end
|
55
|
+
graph.directed? ? node == node1 : has_node?(node)
|
54
56
|
end
|
55
57
|
|
56
58
|
def in_for?(node)
|
57
|
-
|
58
|
-
node == node2
|
59
|
-
else
|
60
|
-
has_node?(node)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def original_attributes
|
65
|
-
attributes.merge({directed: directed, weight: weight})
|
59
|
+
graph.directed? ? node == node2 : has_node?(node)
|
66
60
|
end
|
67
61
|
|
68
62
|
def to_s
|
69
|
-
|
70
|
-
|
71
|
-
"==(#{attributes[:kind]}(#{weight}))=="} #{node2.id}]"
|
63
|
+
descr = graph.directed? ? ["=", "=>>"] : ["==", "=="]
|
64
|
+
"[#{node1.id} %s(#{attributes[:kind]}(#{weight}))%s #{node2.id}]" % descr
|
72
65
|
end
|
73
66
|
|
74
67
|
def inspect
|
75
|
-
"<Rbgraph::Edge:##{id} #{
|
68
|
+
"<Rbgraph::Edge:##{id} #{attributes.inspect}>"
|
76
69
|
end
|
77
70
|
|
78
|
-
def to_json
|
79
|
-
{
|
71
|
+
def to_json(options = {})
|
72
|
+
attributes.reject { |k, v| v.nil? || (v.respond_to?(:empty?) && v.empty?) }.to_json(options)
|
80
73
|
end
|
81
74
|
|
82
75
|
end
|
data/lib/rbgraph/graph.rb
CHANGED
@@ -14,29 +14,34 @@ module Rbgraph
|
|
14
14
|
nodes.values.length
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
def directed?
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_node!(node_id, node_data, &block)
|
22
|
+
if nodes[node_id].nil?
|
23
|
+
nodes[node_id] = Node.new(self, node_id, node_data)
|
22
24
|
else
|
23
|
-
nodes[node.id]
|
25
|
+
nodes[node_id] = yield(self, nodes[node.id], node_data) if block_given?
|
24
26
|
end
|
25
|
-
nodes[
|
27
|
+
nodes[node_id]
|
26
28
|
end
|
27
29
|
|
28
|
-
def add_edge!(node1, node2,
|
29
|
-
node1 = add_node!(node1)
|
30
|
-
node2 = add_node!(node2)
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
edges[edge.id] = edge
|
30
|
+
def add_edge!(node1, node2, weight = 1, kind = nil, edge_data = {}, &block)
|
31
|
+
node1 = add_node!(node1[:id], node1[:data])
|
32
|
+
node2 = add_node!(node2[:id], node2[:data])
|
33
|
+
new_edge = Edge.new(self, node1, node2, weight, kind, edge_data)
|
34
|
+
if edges[new_edge.id].nil?
|
35
|
+
edges[new_edge.id] = new_edge
|
35
36
|
else
|
36
|
-
|
37
|
+
if block_given?
|
38
|
+
edges[new_edge.id] = yield(self, edges[edge.id], new_edge)
|
39
|
+
else
|
40
|
+
edges[new_edge.id].weight += weight
|
41
|
+
end
|
37
42
|
end
|
38
|
-
connect_nodes(node1, node2,
|
39
|
-
|
43
|
+
connect_nodes(node1, node2, edges[new_edge.id])
|
44
|
+
edges[new_edge.id]
|
40
45
|
end
|
41
46
|
|
42
47
|
def remove_node!(node)
|
@@ -56,25 +61,26 @@ module Rbgraph
|
|
56
61
|
edges.delete(edge.id)
|
57
62
|
end
|
58
63
|
|
59
|
-
def merge_nodes!(node_ids,
|
60
|
-
node_ids =
|
64
|
+
def merge_nodes!(node_ids, new_node_id = nil, new_node_data = {}, merge_options = {}, &block)
|
65
|
+
node_ids = nodes.values_at(*node_ids).compact.map(&:id)
|
61
66
|
return nil if node_ids.empty?
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
+
if new_node_id.nil?
|
68
|
+
# If new_node_id is nil then select the first from the list as the surviving node.
|
69
|
+
new_node = nodes[node_ids.shift]
|
70
|
+
else
|
71
|
+
# Otherwise either check if a node with the given id exists, or create a new one.
|
72
|
+
if nodes[new_node_id].nil?
|
73
|
+
new_node = add_node!(new_node_id, new_node_data)
|
67
74
|
else
|
68
|
-
new_node = nodes[
|
69
|
-
|
75
|
+
new_node = nodes[new_node_id]
|
76
|
+
random_not_existent_id = nodes.keys.sort_by { |k| -k.to_s.length } .first.to_s + "_"
|
77
|
+
new_node.merge!(Node.new(self, 0, new_node_data))
|
78
|
+
node_ids.delete(new_node_id)
|
70
79
|
end
|
71
|
-
new_node.merge(Node.new({id: 0}.merge(new_attrs)))
|
72
|
-
else
|
73
|
-
new_node = add_node!(new_attrs)
|
74
80
|
end
|
75
81
|
node_ids.each do |node_id|
|
76
82
|
node = nodes[node_id]
|
77
|
-
new_node.
|
83
|
+
new_node.merge!(node, merge_options, &block)
|
78
84
|
end
|
79
85
|
new_node
|
80
86
|
end
|
@@ -84,7 +90,7 @@ module Rbgraph
|
|
84
90
|
end
|
85
91
|
|
86
92
|
def inspect
|
87
|
-
edges.map(&:inspect)
|
93
|
+
edges.values.map(&:inspect)
|
88
94
|
end
|
89
95
|
|
90
96
|
end
|
data/lib/rbgraph/node.rb
CHANGED
@@ -4,16 +4,17 @@ module Rbgraph
|
|
4
4
|
|
5
5
|
attr_accessor :id
|
6
6
|
attr_accessor :graph
|
7
|
-
attr_accessor :attributes
|
8
7
|
attr_accessor :neighbors
|
9
8
|
attr_accessor :edges
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
raise "Node should have
|
14
|
-
self.
|
15
|
-
self.
|
16
|
-
self.
|
9
|
+
attr_accessor :data
|
10
|
+
|
11
|
+
def initialize(graph, id, data = {})
|
12
|
+
raise "Node should have a non-nil id!" if id.nil?
|
13
|
+
self.graph = graph
|
14
|
+
self.id = id
|
15
|
+
self.neighbors = {}
|
16
|
+
self.edges = {}
|
17
|
+
self.data = data || {}
|
17
18
|
end
|
18
19
|
|
19
20
|
def ==(node)
|
@@ -22,12 +23,15 @@ module Rbgraph
|
|
22
23
|
alias_method :==, :eql?
|
23
24
|
|
24
25
|
def hash
|
25
|
-
id
|
26
|
+
id.hash
|
26
27
|
end
|
27
28
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
29
|
+
def attributes
|
30
|
+
{id: id, data: data}
|
31
|
+
end
|
32
|
+
|
33
|
+
def [](key)
|
34
|
+
attributes.fetch(key.to_sym)
|
31
35
|
end
|
32
36
|
|
33
37
|
def connect_to(node, edge)
|
@@ -38,18 +42,27 @@ module Rbgraph
|
|
38
42
|
self
|
39
43
|
end
|
40
44
|
|
41
|
-
def
|
42
|
-
node.edges.values.each do |
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
def merge!(node, options = {}, &block)
|
46
|
+
node.edges.values.group_by(&:kind).each do |kind, edges|
|
47
|
+
edges.each do |edge|
|
48
|
+
other_node = edge.other_node(node)
|
49
|
+
edge_kind = edge.kind || options[:edge_kind]
|
50
|
+
unless other_node == self
|
51
|
+
if edge.out_for?(node)
|
52
|
+
graph.add_edge!(self, other_node, edge.weight, edge_kind, edge.data, &block)
|
53
|
+
elsif edge.in_for?(node)
|
54
|
+
graph.add_edge!(other_node, self, edge.weight, edge_kind, edge.data, &block)
|
55
|
+
end
|
56
|
+
end
|
48
57
|
end
|
49
58
|
end
|
50
59
|
graph.remove_node!(node)
|
51
60
|
end
|
52
61
|
|
62
|
+
def merge_data!(node)
|
63
|
+
data.merge!(node.data)
|
64
|
+
end
|
65
|
+
|
53
66
|
def outgoing_edges
|
54
67
|
edges.select { |eid, edge| edge.out_for?(self) }
|
55
68
|
end
|
@@ -67,11 +80,11 @@ module Rbgraph
|
|
67
80
|
end
|
68
81
|
|
69
82
|
def inspect
|
70
|
-
"<Rbgraph::Node:##{id} #{
|
83
|
+
"<Rbgraph::Node:##{id} #{data.inspect}>"
|
71
84
|
end
|
72
85
|
|
73
|
-
def to_json
|
74
|
-
|
86
|
+
def to_json(options = {})
|
87
|
+
attributes.to_json(options)
|
75
88
|
end
|
76
89
|
|
77
90
|
end
|