abuelo 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +40 -0
- data/MIT-LICENSE +8 -0
- data/README.md +52 -0
- data/Rakefile +7 -0
- data/abuelo.gemspec +28 -0
- data/lib/abuelo/edge.rb +71 -0
- data/lib/abuelo/exceptions/exceptions.rb +11 -0
- data/lib/abuelo/graph.rb +127 -0
- data/lib/abuelo/node.rb +55 -0
- data/lib/abuelo/version.rb +3 -0
- data/lib/abuelo.rb +4 -0
- data/spec/edge_spec.rb +67 -0
- data/spec/graph_spec.rb +130 -0
- data/spec/node_spec.rb +55 -0
- data/spec/spec_helper.rb +9 -0
- metadata +120 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 56d6315d3eafd194ee45e20bfa60eff9b68548c6
|
4
|
+
data.tar.gz: a15a915a0c83f075c4a67495dce09628fab155f4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ce7fdf584034fbe02e378dadd644c6e16dc617e3d50c7130cd97011f44bb9c9170af759b11be232f8b53d24b958ad286dda5a5a0b057075dc93d42daa619b8b5
|
7
|
+
data.tar.gz: 463ff60c87536021e450664c9a9749818bf4381a1b9db69f004e8f651ca0f3fe73421eee25af210b66b843425a34a48bc1f96160f67912c880c7e1cc303add43
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
abuelo (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
coderay (1.1.0)
|
10
|
+
diff-lcs (1.2.5)
|
11
|
+
method_source (0.8.2)
|
12
|
+
pry (0.10.1)
|
13
|
+
coderay (~> 1.1.0)
|
14
|
+
method_source (~> 0.8.1)
|
15
|
+
slop (~> 3.4)
|
16
|
+
rake (10.4.2)
|
17
|
+
rspec (3.3.0)
|
18
|
+
rspec-core (~> 3.3.0)
|
19
|
+
rspec-expectations (~> 3.3.0)
|
20
|
+
rspec-mocks (~> 3.3.0)
|
21
|
+
rspec-core (3.3.2)
|
22
|
+
rspec-support (~> 3.3.0)
|
23
|
+
rspec-expectations (3.3.1)
|
24
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
25
|
+
rspec-support (~> 3.3.0)
|
26
|
+
rspec-mocks (3.3.2)
|
27
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
28
|
+
rspec-support (~> 3.3.0)
|
29
|
+
rspec-support (3.3.0)
|
30
|
+
slop (3.6.0)
|
31
|
+
|
32
|
+
PLATFORMS
|
33
|
+
ruby
|
34
|
+
|
35
|
+
DEPENDENCIES
|
36
|
+
abuelo!
|
37
|
+
bundler (~> 1.7)
|
38
|
+
pry
|
39
|
+
rake
|
40
|
+
rspec
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
Copyright (c) 2016 Dirk Holzapfel
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
5
|
+
|
6
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
7
|
+
|
8
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Abuelo
|
2
|
+
Abuelo is a graph theory library that allows you to build a representation of a directed graph with its nodes and edges.
|
3
|
+
|
4
|
+
## Examples
|
5
|
+
```ruby
|
6
|
+
graph = Abuelo::Graph.new
|
7
|
+
|
8
|
+
node_1 = Abuelo::Node.new('node 1')
|
9
|
+
node_2 = Abuelo::Node.new('node 2')
|
10
|
+
node_3 = Abuelo::Node.new('node 3')
|
11
|
+
edge_1 = Abuelo::Edge.new(node_1, node_2, 42)
|
12
|
+
edge_2 = Abuelo::Edge.new(node_2, node_3, 23)
|
13
|
+
|
14
|
+
graph.add_node(node_1)
|
15
|
+
.add_node(node_2)
|
16
|
+
.add_node(node_3)
|
17
|
+
.add_edge(edge_1)
|
18
|
+
.add_edge(edge_2)
|
19
|
+
|
20
|
+
graph.nodes # => [node_1, node_2, node_3]
|
21
|
+
graph.has_node?(node_1) # => true
|
22
|
+
graph.has_node_with_name?('foo') # => false
|
23
|
+
graph.edges # => [edge_1, edge_2]
|
24
|
+
graph.has_edge?(edge_1) # => true
|
25
|
+
graph.find_edge(node_1, node_2) # => edge_1
|
26
|
+
graph.edges_for_node(node_2) # => [edge_2]
|
27
|
+
```
|
28
|
+
|
29
|
+
## Future
|
30
|
+
* Implement graph algorithms
|
31
|
+
* [Kruskal's algorithm](https://en.wikipedia.org/wiki/Kruskal%27s_algorithm)
|
32
|
+
* [Prim's algorithm](https://en.wikipedia.org/wiki/Prim%27s_algorithm)
|
33
|
+
* [Dijkstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)
|
34
|
+
* Implement visualization of graph
|
35
|
+
|
36
|
+
## Installation
|
37
|
+
Abuelo is a gem which you can install with:
|
38
|
+
```
|
39
|
+
gem install abuelo
|
40
|
+
```
|
41
|
+
|
42
|
+
In Rails 3+, add the following to your ```Gemfile```:
|
43
|
+
```
|
44
|
+
gem 'abuelo'
|
45
|
+
```
|
46
|
+
|
47
|
+
## Credits
|
48
|
+
Dirk Holzapfel
|
49
|
+
|
50
|
+
[cachezero.net](http://cachezero.net)
|
51
|
+
|
52
|
+
[bitcrowd.net](http://bitcrowd.net)
|
data/Rakefile
ADDED
data/abuelo.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require 'abuelo/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = 'abuelo'
|
6
|
+
spec.version = Abuelo::VERSION
|
7
|
+
spec.date = '2016-01-10'
|
8
|
+
spec.summary = "Abuelo"
|
9
|
+
spec.description = "Abuelo is a graph theory library."
|
10
|
+
spec.authors = ["Dirk Holzapfel"]
|
11
|
+
spec.email = 'dirk@bitcrowd.net'
|
12
|
+
spec.homepage =
|
13
|
+
'http://github.com/dirkholzapfel/abuelo'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split("\n")
|
17
|
+
spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# Development
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
23
|
+
spec.add_development_dependency 'rake'
|
24
|
+
spec.add_development_dependency 'pry'
|
25
|
+
|
26
|
+
# Testing
|
27
|
+
spec.add_development_dependency 'rspec'
|
28
|
+
end
|
data/lib/abuelo/edge.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
module Abuelo
|
2
|
+
#
|
3
|
+
# Class Edge provides a representation of an edge.
|
4
|
+
# An edge connects two nodes(start-node and end-node) and has a weight.
|
5
|
+
#
|
6
|
+
# @author Dirk Holzapfel <dirk@bitcrowd.net>
|
7
|
+
#
|
8
|
+
class Edge
|
9
|
+
|
10
|
+
# @return [Abuelo::Node] start-node
|
11
|
+
attr_reader :node_1
|
12
|
+
|
13
|
+
# @return [Abuelo::Node] end-node
|
14
|
+
attr_reader :node_2
|
15
|
+
|
16
|
+
# @return [Numeric] weight
|
17
|
+
attr_reader :weight
|
18
|
+
|
19
|
+
#
|
20
|
+
# Initialiazises the edge with its two nodes and its weight.
|
21
|
+
#
|
22
|
+
# @param [Abuelo::Node] node_1 start-node
|
23
|
+
# @param [Abuelo::Node] node_2 end-node
|
24
|
+
# @param [Numeric] weight of the edge
|
25
|
+
#
|
26
|
+
def initialize(node_1, node_2, weight = 0)
|
27
|
+
@node_1 = node_1
|
28
|
+
@node_2 = node_2
|
29
|
+
@weight = weight
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# @return [Abuelo::Edge] a new edge with same weight but reversed start- and end-node.
|
34
|
+
#
|
35
|
+
def opposite
|
36
|
+
Abuelo::Edge.new(node_2, node_1, weight)
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Comparison based on weight.
|
41
|
+
#
|
42
|
+
# @param [Abuelo::Edge] other_edge
|
43
|
+
#
|
44
|
+
# @return [-1, 0, +1 or ni]
|
45
|
+
#
|
46
|
+
def <=>(other_edge)
|
47
|
+
self.weight <=> other_edge.weight
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Equality check.
|
52
|
+
#
|
53
|
+
# @param [Abuelo::Edge] other_edge
|
54
|
+
#
|
55
|
+
# @return [Boolean] true if start-, end-node and weight of both edges are equal
|
56
|
+
#
|
57
|
+
def ==(other_edge)
|
58
|
+
self.node_1 == other_edge.node_1 &&
|
59
|
+
self.node_2 == other_edge.node_2 &&
|
60
|
+
self.weight == other_edge.weight
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# @return [String] human readable representation of edge
|
65
|
+
#
|
66
|
+
def to_s
|
67
|
+
"#{node_1.to_s} -> #{node_2.to_s} with weight #{weight}"
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
data/lib/abuelo/graph.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
module Abuelo
|
2
|
+
#
|
3
|
+
# Class Graph provides a representation of a directed graph.
|
4
|
+
# A graph consists of nodes (= vertices, points) and edges (= lines, arcs).
|
5
|
+
#
|
6
|
+
# @author Dirk Holzapfel <dirk@bitcrowd.net>
|
7
|
+
#
|
8
|
+
class Graph
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@nodes = {} # @nodes = { node_name => node_object }
|
12
|
+
@edges = {} # @edges = { node_object => { node_object => edge }}
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
#
|
17
|
+
# @return [Array<Abuelo::Node>] list of nodes of the graph
|
18
|
+
#
|
19
|
+
def nodes
|
20
|
+
@nodes.values
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Adds a node to the graph.
|
25
|
+
#
|
26
|
+
# @param [Abuelo::Node] node to add
|
27
|
+
#
|
28
|
+
# @return [Abuelo::Graph] the graph
|
29
|
+
#
|
30
|
+
# @raise [Abuelo::Exceptions::NodeAlreadyExistsError] if the node is
|
31
|
+
# already contained in the graph
|
32
|
+
#
|
33
|
+
def add_node(node)
|
34
|
+
raise Abuelo::Exceptions::NodeAlreadyExistsError if has_node?(node)
|
35
|
+
|
36
|
+
@nodes[node.name] = node
|
37
|
+
node.graph = self
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Checks if the given node is contained in the graph.
|
43
|
+
#
|
44
|
+
# @param [Abuelo::Node] node
|
45
|
+
#
|
46
|
+
# @return [Boolean]
|
47
|
+
#
|
48
|
+
def has_node?(node)
|
49
|
+
has_node_with_name?(node.name)
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# Checks if a node with the given name is contained in the graph.
|
54
|
+
#
|
55
|
+
# @param [String] name of the node
|
56
|
+
#
|
57
|
+
# @return [Boolean]
|
58
|
+
#
|
59
|
+
def has_node_with_name?(name)
|
60
|
+
@nodes[name] ? true : false
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
#
|
65
|
+
# @return [Array<Abuelo::Edge>] list of edges of the graph
|
66
|
+
#
|
67
|
+
def edges
|
68
|
+
edges = @edges.keys.map { |key| @edges[key].values }
|
69
|
+
edges.flatten
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Adds an edge to the graph.
|
74
|
+
#
|
75
|
+
# @param [Abuelo::Edge] edge to add
|
76
|
+
#
|
77
|
+
# @return [Abuelo::Graph] the graph
|
78
|
+
#
|
79
|
+
# @raise [Abuelo::Exceptions::EdgeAlreadyExistsError] if the edge is
|
80
|
+
# already contained in the graph
|
81
|
+
#
|
82
|
+
def add_edge(edge)
|
83
|
+
raise Abuelo::Exceptions::EdgeAlreadyExistsError if has_edge?(edge)
|
84
|
+
|
85
|
+
@edges[edge.node_1] ||= {}
|
86
|
+
@edges[edge.node_1][edge.node_2] = edge
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Checks if the given edge is contained in the graph.
|
92
|
+
#
|
93
|
+
# @param [Abuelo::Edge] edge
|
94
|
+
#
|
95
|
+
# @return [Boolean]
|
96
|
+
#
|
97
|
+
def has_edge?(edge)
|
98
|
+
find_edge(edge.node_1, edge.node_2) ? true : false
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Checks if there is an edge between the two given nodes.
|
103
|
+
#
|
104
|
+
# @param [Abuelo::Node] node_1
|
105
|
+
# @param [Abuelo::Node] node_2
|
106
|
+
#
|
107
|
+
# @return [Abuelo::Edge, nil] the edge if found, otherwise nil
|
108
|
+
#
|
109
|
+
def find_edge(node_1, node_2)
|
110
|
+
@edges[node_1][node_2] if @edges[node_1]
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# Returns all edges that start from the given node.
|
115
|
+
#
|
116
|
+
# @param [Abuelo::Node] node <description>
|
117
|
+
#
|
118
|
+
# @return [Array<Abuelo::Edge>] list of edges that start from the given node
|
119
|
+
#
|
120
|
+
def edges_for_node(node)
|
121
|
+
edges = []
|
122
|
+
edges += @edges[node].values.to_a if @edges[node]
|
123
|
+
edges
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
data/lib/abuelo/node.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Abuelo
|
2
|
+
#
|
3
|
+
# Class Node provides a representation of a node.
|
4
|
+
# A node has a name. Any object may be attached on initialization.
|
5
|
+
#
|
6
|
+
# @author Dirk Holzapfel <dirk@bitcrowd.net>
|
7
|
+
#
|
8
|
+
class Node
|
9
|
+
# @return [String] name
|
10
|
+
attr_reader :name
|
11
|
+
|
12
|
+
# @return [Object] attached object
|
13
|
+
attr_reader :object
|
14
|
+
|
15
|
+
# @return [Abuelo::Graph] associated graph
|
16
|
+
attr_accessor :graph
|
17
|
+
|
18
|
+
#
|
19
|
+
# Initialiazises the node with its name.
|
20
|
+
#
|
21
|
+
# @param [String] name of the node
|
22
|
+
# @param [Object] object to attach to the node.
|
23
|
+
# This is useful on some algorithm implementations.
|
24
|
+
#
|
25
|
+
def initialize(name, object = nil)
|
26
|
+
@name = name
|
27
|
+
@object = object
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# @return [Array<Abuelo::Edge>] list of edges starting from the node
|
32
|
+
#
|
33
|
+
def edges
|
34
|
+
graph.edges_for_node(self) if graph
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# @return [String] human readable representation of node
|
39
|
+
#
|
40
|
+
def to_s
|
41
|
+
@name
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Equality check.
|
46
|
+
#
|
47
|
+
# @param [Abuelo::Node] other_node
|
48
|
+
#
|
49
|
+
# @return [Boolean] true if name is equal
|
50
|
+
#
|
51
|
+
def ==(other_node)
|
52
|
+
self.name == other_node.name
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/abuelo.rb
ADDED
data/spec/edge_spec.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Abuelo::Edge do
|
4
|
+
|
5
|
+
let(:node_1) { Abuelo::Node.new('node 1') }
|
6
|
+
let(:node_2) { Abuelo::Node.new('node 2') }
|
7
|
+
|
8
|
+
let(:edge) { described_class.new(node_1, node_2, 3) }
|
9
|
+
|
10
|
+
context 'initialization' do
|
11
|
+
it 'sets the weight to 0 if not given' do
|
12
|
+
expect(described_class.new(node_1, node_2).weight).to eq 0
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'accessors' do
|
17
|
+
it 'has following getters' do
|
18
|
+
expect(edge.respond_to?(:node_1)).to be true
|
19
|
+
expect(edge.respond_to?(:node_2)).to be true
|
20
|
+
expect(edge.respond_to?(:weight)).to be true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#opposite' do
|
25
|
+
it 'returns an edge object with the same weight, but reversed nodes' do
|
26
|
+
opposite = edge.opposite
|
27
|
+
expect(opposite.node_1).to eq edge.node_2
|
28
|
+
expect(opposite.node_2).to eq edge.node_1
|
29
|
+
expect(opposite.weight).to eq edge.weight
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#to_s' do
|
34
|
+
it 'is human readable' do
|
35
|
+
expect(edge.to_s).to eq 'node 1 -> node 2 with weight 3'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#==(other)' do
|
40
|
+
it 'is true when the nodes and weight match' do
|
41
|
+
other = Abuelo::Edge.new(node_1, node_2, 3)
|
42
|
+
expect(edge == other).to be true
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'is false when the nodes do not match' do
|
46
|
+
other = Abuelo::Edge.new(node_2, node_1, 3)
|
47
|
+
expect(edge == other).to be false
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'is false when the weight does not match' do
|
51
|
+
other = Abuelo::Edge.new(node_1, node_2, 1)
|
52
|
+
expect(edge == other).to be false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'order' do
|
57
|
+
it 'is sorted by its weight' do
|
58
|
+
edge_1 = described_class.new(node_1, node_2, 1)
|
59
|
+
edge_2 = described_class.new(node_1, node_2, 2)
|
60
|
+
edge_3 = described_class.new(node_1, node_2, 3)
|
61
|
+
|
62
|
+
edges = [edge_3, edge_1, edge_2]
|
63
|
+
|
64
|
+
expect(edges.sort).to eq [edge_1, edge_2, edge_3]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/spec/graph_spec.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Abuelo::Graph do
|
4
|
+
|
5
|
+
let(:node_1) { Abuelo::Node.new('node 1') }
|
6
|
+
let(:node_2) { Abuelo::Node.new('node 2') }
|
7
|
+
let(:edge) { Abuelo::Edge.new(node_1, node_2, 42) }
|
8
|
+
|
9
|
+
let(:graph) do
|
10
|
+
graph = described_class.new
|
11
|
+
graph.add_node(node_1)
|
12
|
+
graph.add_node(node_2)
|
13
|
+
graph.add_edge(edge)
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'nodes' do
|
17
|
+
describe '#nodes' do
|
18
|
+
it 'returns the nodes of the graph' do
|
19
|
+
expect(graph.nodes).to match_array [node_1, node_2]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#add_node(node)' do
|
24
|
+
it 'adds the node to the graph' do
|
25
|
+
new_node = Abuelo::Node.new('node 3')
|
26
|
+
|
27
|
+
expect{
|
28
|
+
graph.add_node(new_node)
|
29
|
+
}.to change{ graph.nodes.count }.by 1
|
30
|
+
|
31
|
+
expect(graph.has_node?(new_node)).to be true
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'raises an error if a node with the same name in the graph exists' do
|
35
|
+
new_node = Abuelo::Node.new('node 1')
|
36
|
+
|
37
|
+
expect{
|
38
|
+
graph.add_node(new_node)
|
39
|
+
}.to raise_error(Abuelo::Exceptions::NodeAlreadyExistsError)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'sets the graph of the node to itself' do
|
43
|
+
new_node = Abuelo::Node.new('node 3')
|
44
|
+
|
45
|
+
expect{
|
46
|
+
graph.add_node(new_node)
|
47
|
+
}.to change{ new_node.graph }.to(graph)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#has_node?(node)' do
|
52
|
+
it 'returns true if node is in the graph. checks object name' do
|
53
|
+
expect(graph.has_node?(node_1)).to be true
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'returns false if node is not in the graph. checks object name' do
|
57
|
+
new_node = Abuelo::Node.new('node 3')
|
58
|
+
expect(graph.has_node?(new_node)).to be false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#has_node_with_name?(name)' do
|
63
|
+
it 'returns true if a node with the given name is in the graph' do
|
64
|
+
expect(graph.has_node_with_name?('node 1')).to be true
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'returns fale if no node with the given name is in the graph' do
|
68
|
+
expect(graph.has_node_with_name?('foo')).to be false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
context 'edges' do
|
75
|
+
describe '#edges' do
|
76
|
+
it 'returns the edges of the graph' do
|
77
|
+
expect(graph.edges).to match_array [edge]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '#add_edge(edge)' do
|
82
|
+
it 'adds the edge to the graph' do
|
83
|
+
new_edge = Abuelo::Edge.new(node_2, node_1, 23)
|
84
|
+
|
85
|
+
expect{
|
86
|
+
graph.add_edge(new_edge)
|
87
|
+
}.to change{ graph.edges.count }.by 1
|
88
|
+
|
89
|
+
expect(graph.has_edge?(new_edge)).to be true
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'raises an error if an edge with the same name nodes in the graph exists' do
|
93
|
+
new_edge = Abuelo::Edge.new(node_1, node_2, 23)
|
94
|
+
|
95
|
+
expect{
|
96
|
+
graph.add_edge(new_edge)
|
97
|
+
}.to raise_error(Abuelo::Exceptions::EdgeAlreadyExistsError)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe '#edges_for_node(node)' do
|
102
|
+
it 'returns all edges that start from the given node' do
|
103
|
+
expect(graph.edges_for_node(node_1)).to eq [edge]
|
104
|
+
expect(graph.edges_for_node(node_2)).to eq []
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '#has_edge?(edge)' do
|
109
|
+
it 'returns true if there is an edge with similiar nodes in the graph' do
|
110
|
+
expect(graph.has_edge?(edge)).to be true
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'returns false if there is no edge with similiar nodes in the graph' do
|
114
|
+
other_edge = Abuelo::Edge.new(node_2, node_1, 23)
|
115
|
+
expect(graph.has_edge?(other_edge)).to be false
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '#find_edge(node_1, node_2)' do
|
120
|
+
it 'returns the edge if it can be found in the graph' do
|
121
|
+
expect(graph.find_edge(node_1, node_2)).to eq edge
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'returns nil if the edge cannot be found in the graph' do
|
125
|
+
expect(graph.find_edge(node_2, node_1)).to be nil
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
data/spec/node_spec.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Abuelo::Node do
|
4
|
+
|
5
|
+
let(:node) { described_class.new('node 1') }
|
6
|
+
|
7
|
+
context 'initialization' do
|
8
|
+
it 'sets object to nil if not given' do
|
9
|
+
expect(node.object).to be nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'accessors' do
|
14
|
+
it 'has following getters' do
|
15
|
+
expect(node.respond_to?(:name)).to be true
|
16
|
+
expect(node.respond_to?(:object)).to be true
|
17
|
+
expect(node.respond_to?(:graph)).to be true
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'has following setters' do
|
21
|
+
expect(node.respond_to?(:graph=)).to be true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#edges' do
|
26
|
+
it 'calls edges_for_node on its graph' do
|
27
|
+
graph = Abuelo::Graph.new
|
28
|
+
node.graph = graph
|
29
|
+
expect(graph).to receive(:edges_for_node).with(node)
|
30
|
+
node.edges
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'responds with nil if the node has no associated graph' do
|
34
|
+
expect(node.edges).to be nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#to_s' do
|
39
|
+
it 'responds with its name' do
|
40
|
+
expect(node.to_s).to eq 'node 1'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#==(other)' do
|
45
|
+
it 'is true when the names match' do
|
46
|
+
other = Abuelo::Node.new('node 1')
|
47
|
+
expect(node == other).to be true
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'is false when the names do not match' do
|
51
|
+
other = Abuelo::Node.new('node 2')
|
52
|
+
expect(node == other).to be false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: abuelo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dirk Holzapfel
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Abuelo is a graph theory library.
|
70
|
+
email: dirk@bitcrowd.net
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
files:
|
75
|
+
- ".gitignore"
|
76
|
+
- Gemfile
|
77
|
+
- Gemfile.lock
|
78
|
+
- MIT-LICENSE
|
79
|
+
- README.md
|
80
|
+
- Rakefile
|
81
|
+
- abuelo.gemspec
|
82
|
+
- lib/abuelo.rb
|
83
|
+
- lib/abuelo/edge.rb
|
84
|
+
- lib/abuelo/exceptions/exceptions.rb
|
85
|
+
- lib/abuelo/graph.rb
|
86
|
+
- lib/abuelo/node.rb
|
87
|
+
- lib/abuelo/version.rb
|
88
|
+
- spec/edge_spec.rb
|
89
|
+
- spec/graph_spec.rb
|
90
|
+
- spec/node_spec.rb
|
91
|
+
- spec/spec_helper.rb
|
92
|
+
homepage: http://github.com/dirkholzapfel/abuelo
|
93
|
+
licenses:
|
94
|
+
- MIT
|
95
|
+
metadata: {}
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options: []
|
98
|
+
require_paths:
|
99
|
+
- lib
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
requirements: []
|
111
|
+
rubyforge_project:
|
112
|
+
rubygems_version: 2.4.5
|
113
|
+
signing_key:
|
114
|
+
specification_version: 4
|
115
|
+
summary: Abuelo
|
116
|
+
test_files:
|
117
|
+
- spec/edge_spec.rb
|
118
|
+
- spec/graph_spec.rb
|
119
|
+
- spec/node_spec.rb
|
120
|
+
- spec/spec_helper.rb
|