rbgraph 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +27 -0
- data/lib/rbgraph/edge.rb +13 -4
- data/lib/rbgraph/graph.rb +28 -0
- data/lib/rbgraph/node.rb +18 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48930f7885070f0f57459ad7b36759d8be7d7d48
|
4
|
+
data.tar.gz: a6eb4e8ae29f93011695334241bdd192f670a1b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68715928c6e71ae2606a85e8a8d56d0e232a54f1981bc9837866af3419a44f4174164fff77f77bf5dfe531c892fb0729af221bf81be62b27e35f8fb6cd275ace
|
7
|
+
data.tar.gz: 0c6107d685f112847d7a09ced014740fbf448d332b838670278ab8f9dab27a425a1355bb3a0ee3f596a0e60bc4b3f1397952de2ec09323e1356956b3ab218f6a
|
data/README.md
CHANGED
@@ -49,5 +49,32 @@ node.out_degree
|
|
49
49
|
```
|
50
50
|
depending on if you constructed a Directed or Undirected graph.
|
51
51
|
|
52
|
+
Version 0.0.8+
|
53
|
+
|
54
|
+
Support for weighted edges.
|
55
|
+
```ruby
|
56
|
+
graph = Rbgraph::UndirectedGraph.new()
|
57
|
+
graph.add_edge!({id: 1}, {id: 2})
|
58
|
+
graph.add_edge!({id: 2}, {id: 3})
|
59
|
+
graph.edges["1==2"].weight => 1
|
60
|
+
graph.add_edge!({id: 1}, {id: 2})
|
61
|
+
graph.edges["1==2"].weight => 2
|
62
|
+
graph.add_edge!({id: 1}, {id: 2}, {weight: 3})
|
63
|
+
graph.edges["1==2"].weight => 5
|
64
|
+
```
|
65
|
+
|
66
|
+
Support for node merging.
|
67
|
+
```ruby
|
68
|
+
graph = Rbgraph::UndirectedGraph.new()
|
69
|
+
graph.add_edge!({id: 1}, {id: 2})
|
70
|
+
graph.add_edge!({id: 2}, {id: 3})
|
71
|
+
graph.add_edge!({id: 3}, {id: 4})
|
72
|
+
|
73
|
+
# 1 -> 2 -> 3 -> 4
|
74
|
+
graph.merge_nodes!([2, 3])
|
75
|
+
# 1 -> 2 => 4
|
76
|
+
```
|
77
|
+
|
78
|
+
|
52
79
|
### Disclaimer
|
53
80
|
This project is written on a need to use basis for inclusion to other projects I'm working on for now, so completion is not an immediate goal.
|
data/lib/rbgraph/edge.rb
CHANGED
@@ -3,17 +3,21 @@ module Rbgraph
|
|
3
3
|
class Edge
|
4
4
|
|
5
5
|
attr_accessor :id
|
6
|
+
attr_accessor :graph
|
6
7
|
attr_accessor :node1
|
7
8
|
attr_accessor :node2
|
9
|
+
attr_accessor :weight
|
8
10
|
attr_accessor :directed
|
9
11
|
attr_accessor :attributes
|
10
12
|
|
11
13
|
def initialize(node1, node2, attributes = {})
|
12
14
|
self.node1 = node1
|
13
15
|
self.node2 = node2
|
16
|
+
self.directed = !!attributes.delete(:directed)
|
17
|
+
interpolated_node_ids = directed ? [node1.id, node2.id] : [node1.id, node2.id].sort
|
18
|
+
self.id = attributes.delete(:id) || ("%s=#{attributes[:kind]}=%s" % interpolated_node_ids)
|
19
|
+
self.weight = attributes.delete(:weight) || 1
|
14
20
|
self.attributes = attributes
|
15
|
-
self.id = attributes[:id] || "#{node1.id}=#{attributes[:kind]}=#{node2.id}"
|
16
|
-
self.directed = !!attributes[:directed]
|
17
21
|
end
|
18
22
|
|
19
23
|
def ==(node)
|
@@ -25,12 +29,17 @@ module Rbgraph
|
|
25
29
|
id
|
26
30
|
end
|
27
31
|
|
32
|
+
def has_node?(node)
|
33
|
+
node == node1 || node == node2
|
34
|
+
end
|
35
|
+
|
28
36
|
def other_node(node)
|
29
37
|
# ([node1, node2] - [node]).first ! Fails for edge connecting a node to itself
|
30
38
|
node == node1 ? node2 : node1
|
31
39
|
end
|
32
40
|
|
33
41
|
def merge(edge)
|
42
|
+
self.weight += edge.weight unless edge.weight.nil?
|
34
43
|
attributes.merge!(edge.attributes.reject { |k, v| k == :id })
|
35
44
|
self
|
36
45
|
end
|
@@ -39,7 +48,7 @@ module Rbgraph
|
|
39
48
|
if directed
|
40
49
|
node == node1
|
41
50
|
else
|
42
|
-
node
|
51
|
+
has_node?(node)
|
43
52
|
end
|
44
53
|
end
|
45
54
|
|
@@ -47,7 +56,7 @@ module Rbgraph
|
|
47
56
|
if directed
|
48
57
|
node == node2
|
49
58
|
else
|
50
|
-
node
|
59
|
+
has_node?(node)
|
51
60
|
end
|
52
61
|
end
|
53
62
|
|
data/lib/rbgraph/graph.rb
CHANGED
@@ -16,6 +16,7 @@ module Rbgraph
|
|
16
16
|
|
17
17
|
def add_node!(node)
|
18
18
|
node = node.is_a?(Node) ? node : Node.new(node)
|
19
|
+
node.graph = self
|
19
20
|
if nodes[node.id].nil?
|
20
21
|
nodes[node.id] = node
|
21
22
|
else
|
@@ -28,6 +29,7 @@ module Rbgraph
|
|
28
29
|
node1 = add_node!(node1)
|
29
30
|
node2 = add_node!(node2)
|
30
31
|
edge = Edge.new(node1, node2, edge_attributes)
|
32
|
+
edge.graph = self
|
31
33
|
edge = if edges[edge.id].nil?
|
32
34
|
edges[edge.id] = edge
|
33
35
|
else
|
@@ -37,6 +39,32 @@ module Rbgraph
|
|
37
39
|
edge
|
38
40
|
end
|
39
41
|
|
42
|
+
def remove_node!(node)
|
43
|
+
node = node.is_a?(Node) ? node : nodes[node]
|
44
|
+
if node
|
45
|
+
node.edges.values.each { |edge| remove_edge!(edge) }
|
46
|
+
nodes.delete(node.id)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def remove_edge!(edge)
|
51
|
+
edge = edge.is_a?(Edge) ? edge : edges[edge]
|
52
|
+
edge.node1.remove_neighbor(edge.node2)
|
53
|
+
edge.node2.remove_neighbor(edge.node1)
|
54
|
+
edges.delete(edge.id)
|
55
|
+
end
|
56
|
+
|
57
|
+
def merge_nodes!(node_ids, &block)
|
58
|
+
node_ids = node_ids || yield
|
59
|
+
first_node = nodes[node_ids.shift]
|
60
|
+
if !first_node.nil? && !node_ids.empty?
|
61
|
+
node_ids.each do |node_id|
|
62
|
+
node = nodes[node_id]
|
63
|
+
first_node.absorb!(node)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
40
68
|
def connect_nodes(node1, node2, edge)
|
41
69
|
raise NotImplementedError("Cannot connect nodes on a general graph! Use either Directed or Undirected subclasses")
|
42
70
|
end
|
data/lib/rbgraph/node.rb
CHANGED
@@ -3,6 +3,7 @@ module Rbgraph
|
|
3
3
|
class Node
|
4
4
|
|
5
5
|
attr_accessor :id
|
6
|
+
attr_accessor :graph
|
6
7
|
attr_accessor :attributes
|
7
8
|
attr_accessor :neighbors
|
8
9
|
attr_accessor :edges
|
@@ -10,7 +11,7 @@ module Rbgraph
|
|
10
11
|
def initialize(attributes = {})
|
11
12
|
self.attributes = attributes
|
12
13
|
raise "Node should have an id attribute!" if attributes[:id].nil?
|
13
|
-
self.id = attributes
|
14
|
+
self.id = attributes.delete(:id)
|
14
15
|
self.neighbors = {}
|
15
16
|
self.edges = {}
|
16
17
|
end
|
@@ -37,6 +38,22 @@ module Rbgraph
|
|
37
38
|
self
|
38
39
|
end
|
39
40
|
|
41
|
+
def remove_neighbor(node)
|
42
|
+
neighbors.delete(node.id)
|
43
|
+
end
|
44
|
+
|
45
|
+
def absorb!(node)
|
46
|
+
node.edges.each do |edge_id, edge|
|
47
|
+
other_node = edge.other_node(node)
|
48
|
+
if edge.out_for?(node)
|
49
|
+
graph.add_edge!(self, other_node, edge.attributes) unless other_node == self
|
50
|
+
elsif edge.in_for?(node)
|
51
|
+
graph.add_edge!(other_node, self, edge.attributes) unless other_node == self
|
52
|
+
end
|
53
|
+
end
|
54
|
+
graph.remove_node!(node)
|
55
|
+
end
|
56
|
+
|
40
57
|
def outgoing_edges
|
41
58
|
edges.select { |eid, edge| edge.out_for?(self) }
|
42
59
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbgraph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- George Lamprianidis
|
@@ -60,7 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
60
|
version: '0'
|
61
61
|
requirements: []
|
62
62
|
rubyforge_project:
|
63
|
-
rubygems_version: 2.4.
|
63
|
+
rubygems_version: 2.4.6
|
64
64
|
signing_key:
|
65
65
|
specification_version: 4
|
66
66
|
summary: Ruby graphs!
|