graphshaper 0.2.4 → 0.3.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.
- data/.travis.yml +5 -0
- data/README.md +3 -1
- data/bin/graphshaper +30 -19
- data/graphshaper.gemspec +7 -7
- data/lib/graphshaper.rb +2 -1
- data/lib/graphshaper/adapters/{avocadodb_adapter.rb → arangodb_adapter.rb} +16 -16
- data/lib/graphshaper/adapters/dot_adapter.rb +4 -4
- data/lib/graphshaper/adapters/json_adapter.rb +40 -0
- data/lib/graphshaper/adapters/logging_adapter.rb +4 -5
- data/lib/graphshaper/adapters/sql_adapter.rb +8 -8
- data/lib/graphshaper/undirected_graph.rb +28 -28
- data/lib/graphshaper/version.rb +1 -1
- data/spec/adapters/{avocadodb_adapter_spec.rb → arangodb_adapter_spec.rb} +20 -20
- data/spec/adapters/dot_adapter_spec.rb +6 -6
- data/spec/adapters/json_adapter_spec.rb +63 -0
- data/spec/adapters/logging_adapter_spec.rb +5 -5
- data/spec/adapters/sql_adapter_spec.rb +12 -12
- data/spec/undirected_graph_spec.rb +30 -30
- metadata +59 -24
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Graphshaper
|
2
2
|
|
3
3
|
[](http://travis-ci.org/moonglum/graphshaper)
|
4
|
+
[](https://gemnasium.com/moonglum/graphshaper)
|
5
|
+
[](https://codeclimate.com/github/moonglum/graphshaper)
|
4
6
|
|
5
7
|
Graphshaper can generate realistic, scale-free graphs of any size. It is tested with MRI Ruby (1.9.2. and 1.9.3) and the 1.9 versions of jRuby and Rubinius.
|
6
8
|
|
@@ -26,7 +28,7 @@ The commandline tool expects one argument: The number of vertices you want your
|
|
26
28
|
|
27
29
|
You can use the following options:
|
28
30
|
|
29
|
-
* `-a`, `--
|
31
|
+
* `-a`, `--arango`: Store the graph in a local ArangoDB instance
|
30
32
|
* `-l`, `--log`: Store the graph in two CSV files for nodes and edges
|
31
33
|
* `-d`, `--dot`: Store the graph in the dot format
|
32
34
|
* `-p`, `--png`: Export the graph as a PNG (you need to install graphviz for that – circo is used for the layout)
|
data/bin/graphshaper
CHANGED
@@ -9,37 +9,41 @@ options = {}
|
|
9
9
|
|
10
10
|
optparse = OptionParser.new do |opts|
|
11
11
|
opts.banner = "Usage: graphshaper [options] size"
|
12
|
-
|
13
|
-
opts.on("-a", "--
|
14
|
-
options[:
|
12
|
+
|
13
|
+
opts.on("-a", "--arango", "Store the graph in a local ArangoDB instance") do |arango|
|
14
|
+
options[:arango] = arango
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
opts.on("-l", "--log", "Store the graph in two CSV files for nodes and edges") do |log|
|
18
18
|
options[:log] = log
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
opts.on("-d", "--dot", "Store the graph in the dot format") do |dot|
|
22
22
|
options[:dot] = dot
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
opts.on("-s", "--sql", "Store the graph in sql format") do |sql|
|
26
26
|
options[:sql] = sql
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
opts.on("-p", "--png", "Export the graph as a PNG (graphviz must be installed)") do |png|
|
30
30
|
options[:dot] = png
|
31
31
|
options[:png] = png
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
opts.on("-t", "--testdata", "Generate Test Data (for shortestpath)") do |sp|
|
35
35
|
options[:t] = sp
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
|
+
opts.on("-j", "--json", "Generate JSON files") do |j|
|
39
|
+
options[:json] = j
|
40
|
+
end
|
41
|
+
|
38
42
|
opts.on_tail("--version", "Show version") do
|
39
43
|
puts Graphshaper::VERSION
|
40
44
|
exit
|
41
45
|
end
|
42
|
-
|
46
|
+
|
43
47
|
opts.parse!
|
44
48
|
end
|
45
49
|
|
@@ -54,26 +58,26 @@ if options[:png] and `which circo` == ""
|
|
54
58
|
exit
|
55
59
|
end
|
56
60
|
|
57
|
-
# check for running component:
|
58
|
-
if options[:
|
61
|
+
# check for running component: ArangoDB
|
62
|
+
if options[:arango]
|
59
63
|
begin
|
60
64
|
HTTParty.get 'http://localhost:8529'
|
61
65
|
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
|
62
|
-
puts "No
|
66
|
+
puts "No ArangoDB instance is running on port 8529. Please start ArangoDB or run without --arango option."
|
63
67
|
exit
|
64
68
|
end
|
65
69
|
end
|
66
70
|
|
67
71
|
adapters = []
|
68
|
-
|
72
|
+
|
69
73
|
if options[:log]
|
70
74
|
generated_vertices_csv_file = File.new("generated_vertices.csv", "w")
|
71
75
|
generated_edges_csv_file = File.new("generated_edges.csv", "w")
|
72
76
|
adapters << Graphshaper::LoggingAdapter.new(generated_vertices_csv_file, generated_edges_csv_file)
|
73
77
|
end
|
74
78
|
|
75
|
-
if options[:
|
76
|
-
adapters << Graphshaper::
|
79
|
+
if options[:arango]
|
80
|
+
adapters << Graphshaper::ArangoDbAdapter.new("vertices", "edges")
|
77
81
|
end
|
78
82
|
|
79
83
|
if options[:dot]
|
@@ -85,10 +89,16 @@ if options[:sql]
|
|
85
89
|
generated_graph_sql_file = File.new("generated_graph.sql", "w")
|
86
90
|
generated_vertices_sql_file = File.new("generated_vertices.sql", "w")
|
87
91
|
generated_edges_sql_file = File.new("generated_edges.sql", "w")
|
88
|
-
|
92
|
+
|
89
93
|
adapters << Graphshaper::SqlAdapter.new(generated_graph_sql_file, generated_vertices_sql_file, generated_edges_sql_file)
|
90
94
|
end
|
91
95
|
|
96
|
+
if options[:json]
|
97
|
+
`rm -r generated_edges`
|
98
|
+
Dir.mkdir("generated_edges")
|
99
|
+
adapters << Graphshaper::JsonAdapter.new("generated_edges")
|
100
|
+
end
|
101
|
+
|
92
102
|
number_of_vertices = ARGV.first.to_i
|
93
103
|
inner_vertices = 20
|
94
104
|
outer_vertices = number_of_vertices - inner_vertices
|
@@ -116,11 +126,12 @@ end
|
|
116
126
|
|
117
127
|
print "#{graph.order} vertices and #{graph.size} edges generated"
|
118
128
|
|
119
|
-
print " and saved into
|
129
|
+
print " and saved into ArangoDB" if options[:arango]
|
120
130
|
print " and logged" if options[:log]
|
121
131
|
print " and generated as a dot" if options[:dot]
|
122
132
|
print " and saved in sql format" if options[:sql]
|
123
133
|
print " and generated test cases" if options[:t]
|
134
|
+
print " and generated JSON files" if options[:json]
|
124
135
|
|
125
136
|
if options[:png]
|
126
137
|
system('circo -Tpng generated_graph.dot -o generated_graph.png')
|
@@ -134,4 +145,4 @@ elsif ellapsed_time < 60
|
|
134
145
|
puts " in about #{ellapsed_time.round} seconds"
|
135
146
|
else
|
136
147
|
puts " in about #{ellapsed_time.round / 60} minutes and #{ellapsed_time.round % 60} seconds"
|
137
|
-
end
|
148
|
+
end
|
data/graphshaper.gemspec
CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
|
|
5
5
|
gem.authors = ["Lucas Dohmen"]
|
6
6
|
gem.email = ["me@moonglum.net"]
|
7
7
|
gem.description = %q{Generate realistic graphs}
|
8
|
-
gem.summary = %q{Graphshaper can generate realistic, scale-free graphs of any size.}
|
8
|
+
gem.summary = %q{Graphshaper can generate realistic, scale-free graphs of any size for different databases.}
|
9
9
|
gem.homepage = "http://moonglum.github.com/graphshaper"
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
@@ -14,10 +14,10 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.name = "graphshaper"
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = Graphshaper::VERSION
|
17
|
-
|
18
|
-
gem.add_dependency
|
19
|
-
gem.add_development_dependency "rake",
|
20
|
-
gem.add_development_dependency "rspec",
|
21
|
-
gem.add_development_dependency "
|
22
|
-
gem.add_development_dependency "
|
17
|
+
|
18
|
+
gem.add_dependency "httparty", "~> 0.10.2"
|
19
|
+
gem.add_development_dependency "rake", "~> 10.0.3"
|
20
|
+
gem.add_development_dependency "rspec", "~> 2.13.0"
|
21
|
+
gem.add_development_dependency "webmock", "~> 1.11.0"
|
22
|
+
gem.add_development_dependency "yard", "~> 0.8.5.2"
|
23
23
|
end
|
data/lib/graphshaper.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require "graphshaper/version"
|
2
2
|
require "graphshaper/undirected_graph"
|
3
|
-
require "graphshaper/adapters/
|
3
|
+
require "graphshaper/adapters/arangodb_adapter"
|
4
4
|
require "graphshaper/adapters/logging_adapter"
|
5
5
|
require "graphshaper/adapters/dot_adapter"
|
6
6
|
require "graphshaper/adapters/sql_adapter"
|
7
|
+
require "graphshaper/adapters/json_adapter"
|
7
8
|
|
8
9
|
module Graphshaper
|
9
10
|
end
|
@@ -1,47 +1,47 @@
|
|
1
1
|
require "httparty"
|
2
2
|
|
3
3
|
module Graphshaper
|
4
|
-
class
|
4
|
+
class ArangoDbAdapter
|
5
5
|
include HTTParty
|
6
|
-
|
6
|
+
|
7
7
|
base_uri 'localhost:8529'
|
8
8
|
format :json
|
9
|
-
|
9
|
+
|
10
10
|
def initialize(vertex_collection_name, edge_collection_name)
|
11
11
|
@vertex_collection_name = vertex_collection_name
|
12
12
|
@edge_collection_name = edge_collection_name
|
13
13
|
@vertex_matching = []
|
14
14
|
@edge_matching = []
|
15
|
-
|
15
|
+
|
16
16
|
[@vertex_collection_name, @edge_collection_name].each { |collection| drop_and_create_collection collection}
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def add_vertex(id)
|
20
20
|
cmd = "/document?collection=#{@vertex_collection_name}"
|
21
|
-
|
22
|
-
|
21
|
+
body = "{ \"id\" : \"#{id}\" }"
|
22
|
+
response = self.class.post(cmd, :body => body)
|
23
23
|
@vertex_matching[id] = response.parsed_response["_id"]
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def add_edge(edge_id, from, to)
|
27
27
|
database_id_for_first_node = @vertex_matching[from]
|
28
28
|
database_id_for_second_node = @vertex_matching[to]
|
29
|
-
|
29
|
+
|
30
30
|
cmd = "/edge?collection=#{@edge_collection_name}&from=#{database_id_for_first_node}&to=#{database_id_for_second_node}"
|
31
|
-
|
32
|
-
|
31
|
+
body = "{ \"id\" : \"#{edge_id}\" }"
|
32
|
+
response = self.class.post(cmd, :body => body)
|
33
33
|
@edge_matching[edge_id] = response.parsed_response["_id"]
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
def close
|
37
|
-
|
37
|
+
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
private
|
41
|
-
|
41
|
+
|
42
42
|
def drop_and_create_collection(name)
|
43
43
|
self.class.delete "/_api/collection/#{name}"
|
44
44
|
self.class.post "/_api/collection", body: "{ \"name\" : \"#{name}\"}"
|
45
45
|
end
|
46
46
|
end
|
47
|
-
end
|
47
|
+
end
|
@@ -4,18 +4,18 @@ module Graphshaper
|
|
4
4
|
@output_file = output_file
|
5
5
|
@output_file << "digraph genereated_graph { \n rankdir=LR;\n node [shape = circle];\n edge [dir=none];\n"
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def add_edge(edge_id, in_id, out_id)
|
9
9
|
@output_file << " #{in_id} -> #{out_id} [ label = \"#{edge_id}\" ];\n"
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def add_vertex(vertex_id)
|
13
13
|
@output_file << " #{vertex_id};\n"
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def close
|
17
17
|
@output_file << "}"
|
18
18
|
@output_file.close
|
19
19
|
end
|
20
20
|
end
|
21
|
-
end
|
21
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Graphshaper
|
2
|
+
# An adapter to generate JSON files in the format specified by Michael Hackstein
|
3
|
+
class JsonAdapter
|
4
|
+
def initialize(base_path, file_class = File)
|
5
|
+
@base_path = base_path
|
6
|
+
@file_class = file_class
|
7
|
+
@vertex_file_names = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_edge(edge_id, from_id, to_id)
|
11
|
+
file_name = "#{@base_path}/#{from_id}.json"
|
12
|
+
file = @file_class.new(file_name, "a")
|
13
|
+
file.write(%Q<{"id":#{to_id}},>)
|
14
|
+
file.close
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_vertex(vertex_id)
|
18
|
+
file_name = "#{@base_path}/#{vertex_id}.json"
|
19
|
+
@vertex_file_names << file_name
|
20
|
+
file = @file_class.new(file_name, "w")
|
21
|
+
file.write(file_header(vertex_id))
|
22
|
+
file.close
|
23
|
+
end
|
24
|
+
|
25
|
+
def close
|
26
|
+
@vertex_file_names.each do |file_name|
|
27
|
+
content = @file_class.read(file_name).gsub(/,\z/, '')
|
28
|
+
file = @file_class.new(file_name, "w+")
|
29
|
+
file.write("#{content}]}")
|
30
|
+
file.close
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def file_header(id)
|
37
|
+
%Q<{"id":#{id},"children" : [>
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module Graphshaper
|
2
|
-
|
3
2
|
# A simple adapter for logging the created graph
|
4
3
|
class LoggingAdapter
|
5
4
|
def initialize(vertex_logger_file, edge_logger_file)
|
@@ -8,18 +7,18 @@ module Graphshaper
|
|
8
7
|
@vertex_logger_file << "vertex_id\n"
|
9
8
|
@edge_logger_file << "edge_id,from_id,to_id\n"
|
10
9
|
end
|
11
|
-
|
10
|
+
|
12
11
|
def add_edge(edge_id, from_id, to_id)
|
13
12
|
@edge_logger_file << "#{edge_id},#{from_id},#{to_id}\n"
|
14
13
|
end
|
15
|
-
|
14
|
+
|
16
15
|
def add_vertex(vertex_id)
|
17
16
|
@vertex_logger_file << "#{vertex_id}\n"
|
18
17
|
end
|
19
|
-
|
18
|
+
|
20
19
|
def close
|
21
20
|
@vertex_logger_file.close
|
22
21
|
@edge_logger_file.close
|
23
22
|
end
|
24
23
|
end
|
25
|
-
end
|
24
|
+
end
|
@@ -4,38 +4,38 @@ module Graphshaper
|
|
4
4
|
@schema_file = schema_file
|
5
5
|
@vertex_file = vertex_file
|
6
6
|
@edge_file = edge_file
|
7
|
-
|
7
|
+
|
8
8
|
File.readlines("templates/schema.sql").each do |schema_line|
|
9
9
|
@schema_file << schema_line
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
@vertex_file << "LOCK TABLES `vertices` WRITE;\n"
|
13
13
|
@vertex_file << "INSERT INTO `vertices` (`id`, `vertex_id`)\n"
|
14
14
|
@vertex_file << "VALUES\n\t"
|
15
|
-
|
15
|
+
|
16
16
|
@edge_file << "LOCK TABLES `edges` WRITE;\n"
|
17
17
|
@edge_file << "INSERT INTO `edges` (`id`, `edge_id`, `from_id`, `to_id`)\n"
|
18
18
|
@edge_file << "VALUES\n\t"
|
19
|
-
|
19
|
+
|
20
20
|
@first_vertex = true
|
21
21
|
@first_edge = true
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def add_vertex(vertex_id)
|
25
25
|
@vertex_file << ",\n\t" unless @first_vertex
|
26
26
|
@vertex_file << "(#{vertex_id + 1},#{vertex_id})"
|
27
27
|
@first_vertex = false
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def add_edge(edge_id, from_id, to_id)
|
31
31
|
@edge_file << ",\n\t" unless @first_edge
|
32
32
|
@edge_file << "(#{edge_id + 1},#{edge_id},#{from_id + 1},#{to_id + 1})"
|
33
33
|
@first_edge = false
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
def close
|
37
37
|
[@vertex_file, @edge_file].each { |file| file << ";\nUNLOCK TABLES;"}
|
38
38
|
[@schema_file, @vertex_file, @edge_file].each { |file| file.close }
|
39
39
|
end
|
40
40
|
end
|
41
|
-
end
|
41
|
+
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
require "set"
|
2
2
|
|
3
3
|
module Graphshaper
|
4
|
-
|
4
|
+
|
5
5
|
# A Graph is undirected when its edges do not have a direction.
|
6
6
|
class UndirectedGraph
|
7
|
-
|
7
|
+
|
8
8
|
# Create a graph with a given number of vertices and no edges.
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# @param [Integer] number_of_vertices The number of vertices that the generated graph should have
|
11
11
|
# @param [Hash] options_hash The options to create an undirected graph
|
12
12
|
# @option options_hash [Array<Object>] :adapters An array of adapters you want to use
|
@@ -15,66 +15,66 @@ module Graphshaper
|
|
15
15
|
|
16
16
|
@vertex_degrees = []
|
17
17
|
@unconnected_vertices = Set.new
|
18
|
-
|
18
|
+
|
19
19
|
number_of_vertices.times { add_vertex }
|
20
20
|
@edges = Set.new
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
# The number of vertices.
|
24
24
|
#
|
25
25
|
# @return [Integer] Number of vertices.
|
26
26
|
def order
|
27
27
|
@vertex_degrees.length
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
# The number of edges.
|
31
|
-
#
|
31
|
+
#
|
32
32
|
# @return [Integer] Number of edges.
|
33
33
|
def size
|
34
34
|
@edges.length
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
# Connect all orphans with existing nodes
|
38
38
|
def connect_all_vertices
|
39
39
|
while number_of_orphans > 0
|
40
40
|
vertex_orphan = orphans.shuffle.first
|
41
41
|
while vertex_orphan == (random_vertex = rand(order)); end
|
42
|
-
|
42
|
+
|
43
43
|
add_edge vertex_orphan, random_vertex
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
# Add a new vertex to the graph.
|
48
48
|
# If you call it with a block {|preferential_attachment| ... }, the block will be called for every existing vertex: An edge from the new vertex to this vertex will be created if and only if the block returns true.
|
49
49
|
# @yield [preferential_attachment] The block that tests if the edge should be added.
|
50
50
|
#
|
51
51
|
# @yieldparam [Float] preferential_attachment The preferential attachment of the existing vertex
|
52
52
|
# @yieldreturn [Boolean] Should the edge be added?
|
53
|
-
#
|
53
|
+
#
|
54
54
|
# @return [Integer] ID of the newly created vertex.
|
55
55
|
def add_vertex(&block)
|
56
56
|
new_vertex_id = @vertex_degrees.length
|
57
|
-
|
57
|
+
|
58
58
|
@vertex_degrees << 0
|
59
59
|
@unconnected_vertices << new_vertex_id
|
60
|
-
|
60
|
+
|
61
61
|
unless @adapters.nil?
|
62
62
|
@adapters.each do |adapter|
|
63
63
|
adapter.add_vertex new_vertex_id
|
64
64
|
end
|
65
65
|
end
|
66
|
-
|
67
|
-
if block_given?
|
66
|
+
|
67
|
+
if block_given?
|
68
68
|
each_vertex_with_preferential_attachment do |vertex_id, preferential_attachment|
|
69
69
|
add_edge new_vertex_id, vertex_id if block.call(preferential_attachment)
|
70
70
|
end
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
new_vertex_id
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
# Add a new edge to the graph between two existing vertices.
|
77
|
-
#
|
77
|
+
#
|
78
78
|
# @param [Integer] first_vertex_id
|
79
79
|
# @param [Integer] second_vertex_id
|
80
80
|
# @raise [RuntimeError] The method throws a RuntimeError if you try to add a self-referential edge or an edge with a non-existing vertex.
|
@@ -89,7 +89,7 @@ module Graphshaper
|
|
89
89
|
@unconnected_vertices.delete second_vertex_id
|
90
90
|
@vertex_degrees[second_vertex_id] += 1
|
91
91
|
@edges << [first_vertex_id, second_vertex_id].sort
|
92
|
-
|
92
|
+
|
93
93
|
unless @adapters.nil?
|
94
94
|
@adapters.each do |adapter|
|
95
95
|
adapter.add_edge @edges.length - 1, first_vertex_id, second_vertex_id
|
@@ -97,7 +97,7 @@ module Graphshaper
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
end
|
100
|
-
|
100
|
+
|
101
101
|
# Tests, if an edge between the two vertices exists.
|
102
102
|
#
|
103
103
|
# @param [Integer] first_vertex_id
|
@@ -106,21 +106,21 @@ module Graphshaper
|
|
106
106
|
def edge_between?(first_vertex_id, second_vertex_id)
|
107
107
|
@edges.include? [first_vertex_id, second_vertex_id]
|
108
108
|
end
|
109
|
-
|
109
|
+
|
110
110
|
# The number of vertices without edges.
|
111
111
|
#
|
112
112
|
# @return [Integer] Number of vertices without edges.
|
113
113
|
def number_of_orphans
|
114
114
|
@unconnected_vertices.to_a.length
|
115
115
|
end
|
116
|
-
|
116
|
+
|
117
117
|
# The vertices without edges as an array.
|
118
118
|
#
|
119
119
|
# @return [Array<Integer>] IDs of the Vertices without edges.
|
120
120
|
def orphans
|
121
121
|
@unconnected_vertices.to_a
|
122
122
|
end
|
123
|
-
|
123
|
+
|
124
124
|
# Return the vertex degree for the vertex with the given ID.
|
125
125
|
#
|
126
126
|
# @param [Integer] vertex_id
|
@@ -128,7 +128,7 @@ module Graphshaper
|
|
128
128
|
def vertex_degree_for(vertex_id)
|
129
129
|
@vertex_degrees[vertex_id]
|
130
130
|
end
|
131
|
-
|
131
|
+
|
132
132
|
# Calculates the distribution of degrees in the graph. The value at the n-th position of the returned array is the number of vertices with n edges.
|
133
133
|
#
|
134
134
|
# @return [Array<Integer>] The degree distribution as an array of Integers.
|
@@ -143,16 +143,16 @@ module Graphshaper
|
|
143
143
|
end
|
144
144
|
degree_distribution
|
145
145
|
end
|
146
|
-
|
146
|
+
|
147
147
|
# Return the sum of all degrees.
|
148
148
|
#
|
149
149
|
# @return [Integer] Sum of all degrees
|
150
150
|
def sum_of_all_degrees
|
151
151
|
@edges.length * 2
|
152
152
|
end
|
153
|
-
|
153
|
+
|
154
154
|
# Iterate over all vertices of the graph. Call it with a block {|vertex_id, preferential_attachment| ... }.
|
155
|
-
#
|
155
|
+
#
|
156
156
|
# @yield [vertex_id, preferential_attachment] The block that tests if the edge should be added.
|
157
157
|
# @yieldparam [Integer] vertex_id The preferential attachment of the existing vertex
|
158
158
|
# @yieldparam [Float] preferential_attachment The preferential attachment of the existing vertex
|
@@ -167,4 +167,4 @@ module Graphshaper
|
|
167
167
|
end
|
168
168
|
end
|
169
169
|
end
|
170
|
-
end
|
170
|
+
end
|
data/lib/graphshaper/version.rb
CHANGED
@@ -1,46 +1,46 @@
|
|
1
1
|
require "spec_helper"
|
2
|
-
require "graphshaper/adapters/
|
2
|
+
require "graphshaper/adapters/arangodb_adapter"
|
3
3
|
|
4
|
-
describe Graphshaper::
|
4
|
+
describe Graphshaper::ArangoDbAdapter do
|
5
5
|
before :each do
|
6
6
|
stub_request(:delete, "http://localhost:8529/_api/collection/vertices").to_return(:status => 200, :body => "", :headers => {})
|
7
7
|
stub_request(:post, "http://localhost:8529/_api/collection").with(:body => "{ \"name\" : \"vertices\"}")
|
8
8
|
stub_request(:delete, "http://localhost:8529/_api/collection/edges").to_return(:status => 200, :body => "", :headers => {})
|
9
9
|
stub_request(:post, "http://localhost:8529/_api/collection").with(:body => "{ \"name\" : \"edges\"}")
|
10
10
|
stub_request(:post, "http://localhost:8529/document?collection=vertices")
|
11
|
-
|
12
|
-
|
11
|
+
.with(:body => "{ \"id\" : \"1\" }")
|
12
|
+
.to_return(:body => "{ \"_rev\": 26445614, \"_id\": \"73482/26445614\", \"error\": false }", :status => 200 )
|
13
13
|
stub_request(:post, "http://localhost:8529/document?collection=vertices")
|
14
|
-
|
15
|
-
|
14
|
+
.with(:body => "{ \"id\" : \"2\" }")
|
15
|
+
.to_return(:body => "{ \"_rev\": 26445614, \"_id\": \"73482/26445615\", \"error\": false }", :status => 200 )
|
16
16
|
stub_request(:post, "http://localhost:8529/edge?collection=edges&from=73482/26445614&to=73482/26445615")
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@
|
17
|
+
.with(:body => "{ \"id\" : \"7\" }")
|
18
|
+
.to_return(:body => "{ \"_rev\": 9683012, \"_id\": \"7848004/9683012\", \"error\": false }", :status => 200)
|
19
|
+
|
20
|
+
@arango_adapter = Graphshaper::ArangoDbAdapter.new "vertices", "edges"
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
it "should drop the collections on startup" do
|
24
24
|
WebMock.should have_requested(:delete, "http://localhost:8529/_api/collection/vertices")
|
25
25
|
WebMock.should have_requested(:delete, "http://localhost:8529/_api/collection/edges")
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
it "should create the collections on startup" do
|
29
29
|
WebMock.should have_requested(:post, "http://localhost:8529/_api/collection").with(:body => "{ \"name\" : \"vertices\"}")
|
30
30
|
WebMock.should have_requested(:post, "http://localhost:8529/_api/collection").with(:body => "{ \"name\" : \"edges\"}")
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
it "should add a vertex" do
|
34
|
-
@
|
35
|
-
|
34
|
+
@arango_adapter.add_vertex 1
|
35
|
+
|
36
36
|
WebMock.should have_requested(:post, "http://localhost:8529/document?collection=vertices").with(:body => "{ \"id\" : \"1\" }")
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
it "should add an edge with the correct vertex ids" do
|
40
|
-
@
|
41
|
-
@
|
42
|
-
@
|
43
|
-
|
40
|
+
@arango_adapter.add_vertex 1
|
41
|
+
@arango_adapter.add_vertex 2
|
42
|
+
@arango_adapter.add_edge 7, 1, 2
|
43
|
+
|
44
44
|
WebMock.should have_requested(:post, "http://localhost:8529/edge?collection=edges&from=73482/26445614&to=73482/26445615").with(:body => "{ \"id\" : \"7\" }")
|
45
45
|
end
|
46
46
|
end
|
@@ -6,31 +6,31 @@ describe Graphshaper::DotAdapter do
|
|
6
6
|
@output_file = double()
|
7
7
|
@output_file.stub :<<
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
it "should write a header into the file" do
|
11
11
|
@output_file.should_receive(:<<).with("digraph genereated_graph { \n rankdir=LR;\n node [shape = circle];\n edge [dir=none];\n")
|
12
12
|
Graphshaper::DotAdapter.new @output_file
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
describe "initialized Dot Adapter" do
|
16
16
|
before :each do
|
17
17
|
@dot_adapter = Graphshaper::DotAdapter.new @output_file
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
it "should be closeable" do
|
21
21
|
@output_file.should_receive(:<<).with("}")
|
22
22
|
@output_file.should_receive(:close)
|
23
23
|
@dot_adapter.close
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
it "should write an edge in the correct format" do
|
27
27
|
@output_file.should_receive(:<<).with(" 1 -> 2 [ label = \"0\" ];\n")
|
28
28
|
@dot_adapter.add_edge(0,1,2)
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
it "should write a vertex in the correct format" do
|
32
32
|
@output_file.should_receive(:<<).with(" 15;\n")
|
33
33
|
@dot_adapter.add_vertex(15)
|
34
34
|
end
|
35
35
|
end
|
36
|
-
end
|
36
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "graphshaper/adapters/json_adapter"
|
3
|
+
|
4
|
+
describe Graphshaper::JsonAdapter do
|
5
|
+
describe "Initialized Adapter" do
|
6
|
+
let(:file_class) { double }
|
7
|
+
let(:vertex_id) { 1 }
|
8
|
+
let(:edge_id) { 2 }
|
9
|
+
let(:from_id) { 3 }
|
10
|
+
let(:to_id) { 4 }
|
11
|
+
subject { Graphshaper::JsonAdapter.new "test_dir", file_class }
|
12
|
+
|
13
|
+
it "should create a new edge file" do
|
14
|
+
file = double
|
15
|
+
file.should_receive(:write).with(%Q<{"id":#{vertex_id},"children" : [>)
|
16
|
+
file.should_receive(:close)
|
17
|
+
file_class.stub(:new).and_return { file }
|
18
|
+
file_class.should_receive(:new).with("test_dir/#{vertex_id}.json", "w")
|
19
|
+
|
20
|
+
subject.add_vertex(vertex_id)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should add edges to the vertices" do
|
24
|
+
file = double
|
25
|
+
file.should_receive(:write).with(%Q<{"id":#{to_id}},>)
|
26
|
+
file.should_receive(:close)
|
27
|
+
file_class.stub(:new).and_return { file }
|
28
|
+
file_class.should_receive(:new).with("test_dir/#{from_id}.json", "a")
|
29
|
+
|
30
|
+
subject.add_edge(edge_id, from_id, to_id)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should close all vertex files" do
|
34
|
+
file_1 = double
|
35
|
+
file_2 = double
|
36
|
+
close_file_1 = double
|
37
|
+
close_file_2 = double
|
38
|
+
|
39
|
+
[file_1, file_2, close_file_1, close_file_2].each do |f|
|
40
|
+
f.stub(:write)
|
41
|
+
f.stub(:close)
|
42
|
+
end
|
43
|
+
|
44
|
+
[close_file_1, close_file_2].each do |f|
|
45
|
+
f.should_receive(:write).with("a]}")
|
46
|
+
f.should_receive(:close)
|
47
|
+
end
|
48
|
+
|
49
|
+
file_class.stub(:read).with("test_dir/1.json").and_return { "a," }
|
50
|
+
file_class.stub(:read).with("test_dir/2.json").and_return { "a" }
|
51
|
+
|
52
|
+
file_class.stub(:new).with("test_dir/1.json", "w").and_return { file_1 }
|
53
|
+
file_class.stub(:new).with("test_dir/2.json", "w").and_return { file_2 }
|
54
|
+
|
55
|
+
file_class.stub(:new).with("test_dir/1.json", "w+").and_return { close_file_1 }
|
56
|
+
file_class.stub(:new).with("test_dir/2.json", "w+").and_return { close_file_2 }
|
57
|
+
|
58
|
+
subject.add_vertex(1)
|
59
|
+
subject.add_vertex(2)
|
60
|
+
subject.close
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -8,26 +8,26 @@ describe Graphshaper::LoggingAdapter do
|
|
8
8
|
@edge_logger = double()
|
9
9
|
@edge_logger.stub :<<
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
it "should write a header into the files" do
|
13
13
|
@vertex_logger.should_receive(:<<).with("vertex_id\n")
|
14
14
|
@edge_logger.should_receive(:<<).with("edge_id,from_id,to_id\n")
|
15
15
|
Graphshaper::LoggingAdapter.new @vertex_logger, @edge_logger
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
describe "Initialized Logger" do
|
19
19
|
before :each do
|
20
20
|
@adapter = Graphshaper::LoggingAdapter.new @vertex_logger, @edge_logger
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
it "should write edges to the logger at edge creation" do
|
24
24
|
@edge_logger.should_receive(:<<).with("0,1,3\n")
|
25
25
|
@adapter.add_edge 0,1,3
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
it "should write vertices to the logger at vertex creation" do
|
29
29
|
@vertex_logger.should_receive(:<<).with("5\n")
|
30
30
|
@adapter.add_vertex 5
|
31
31
|
end
|
32
32
|
end
|
33
|
-
end
|
33
|
+
end
|
@@ -8,49 +8,49 @@ describe Graphshaper::SqlAdapter do
|
|
8
8
|
@vertex_file = StringIO.new
|
9
9
|
@edge_file = StringIO.new
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
describe "generated files" do
|
13
13
|
before :each do
|
14
14
|
@sql_adapter = Graphshaper::SqlAdapter.new @schema_file, @vertex_file, @edge_file
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
it "should write the schema to the file" do
|
18
18
|
schema_string = @schema_file.string
|
19
|
-
|
19
|
+
|
20
20
|
File.readlines("templates/schema.sql").each do |schema_line|
|
21
21
|
schema_string.should include(schema_line)
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
it "should write the vertices to the file" do
|
26
26
|
@sql_adapter.add_vertex(0)
|
27
27
|
@sql_adapter.add_vertex(1)
|
28
28
|
@sql_adapter.close
|
29
|
-
|
29
|
+
|
30
30
|
vertex_string = @vertex_file.string
|
31
|
-
|
31
|
+
|
32
32
|
vertex_string.should include(" (1,0),\n")
|
33
33
|
vertex_string.should include(" (2,1);\n")
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
it "should write the vertices to the file" do
|
37
37
|
@sql_adapter.add_edge(0,5,6)
|
38
38
|
@sql_adapter.add_edge(1,7,8)
|
39
39
|
@sql_adapter.close
|
40
|
-
|
40
|
+
|
41
41
|
edge_string = @edge_file.string
|
42
|
-
|
42
|
+
|
43
43
|
edge_string.should include(" (1,0,6,7),\n")
|
44
44
|
edge_string.should include(" (2,1,8,9);\n")
|
45
45
|
end
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
it "should close the three files" do
|
49
49
|
@schema_file.should_receive(:close)
|
50
50
|
@edge_file.should_receive(:close)
|
51
51
|
@vertex_file.should_receive(:close)
|
52
|
-
|
52
|
+
|
53
53
|
sql_adapter = Graphshaper::SqlAdapter.new @schema_file, @vertex_file, @edge_file
|
54
54
|
sql_adapter.close
|
55
55
|
end
|
56
|
-
end
|
56
|
+
end
|
@@ -7,97 +7,97 @@ describe Graphshaper::UndirectedGraph do
|
|
7
7
|
graph.order.should ==(5)
|
8
8
|
graph.size.should ==(0)
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
describe "initialized graph" do
|
12
12
|
before :each do
|
13
13
|
@graph = Graphshaper::UndirectedGraph.new 5
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
it "should be able to add new vertices" do
|
17
17
|
expect { @graph.add_vertex }.to change{ @graph.order }.by(1)
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
it "should add a vertex with two existing ids" do
|
21
21
|
expect { @graph.add_edge 0, 1 }.to change{ @graph.size }.by(1)
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
it "shouldn't add a vertex if one of the ids doesn't exist" do
|
25
25
|
expect { @graph.add_edge 0, 5}.to raise_error(RuntimeError, "ID doesn't exist")
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
it "should answer the question if there is an edge between two vertices with false if they are not" do
|
29
29
|
@graph.edge_between?(0,1).should be_false
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
it "should answer the question if there is an edge between two vertices with true if they are" do
|
33
33
|
@graph.add_edge 0,1
|
34
34
|
@graph.edge_between?(0,1).should be_true
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
it "shouldn't add an edge that has already been added" do
|
38
38
|
@graph.add_edge 0,1
|
39
39
|
expect { @graph.add_edge 0, 1 }.to change{ @graph.size }.by(0)
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
it "shouldn't add an edge that has already been added - independent of direction" do
|
43
43
|
@graph.add_edge 0,1
|
44
44
|
expect { @graph.add_edge 1,0 }.to change{ @graph.size }.by(0)
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
it "should not add an edge where the first and second vertex are the same" do
|
48
48
|
expect { @graph.add_edge 0, 0}.to raise_error(RuntimeError, "No Self-Referential Edge")
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
it "should return the graph's order for the number of orphans for a graph without vertices" do
|
52
52
|
@graph.number_of_orphans.should ==(@graph.order)
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
it "should return 0 for the number of orphans for a graph connected in a circle" do
|
56
56
|
circle_array = (0...5).to_a
|
57
57
|
circle_array.zip(circle_array.rotate).each do |vertex_a, vertex_b|
|
58
58
|
@graph.add_edge vertex_a, vertex_b
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
it "should calculate the vertex degree" do
|
63
63
|
expect { @graph.add_edge 0,1 }.to change { @graph.vertex_degree_for 1}.by(1)
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
it "should calculate the degree distribution" do
|
67
67
|
@graph.degree_distribution.should ==[5]
|
68
68
|
@graph.add_edge 0,1
|
69
69
|
@graph.add_edge 1,2
|
70
70
|
@graph.degree_distribution.should ==[2,2,1]
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
it "should be able to connect all vertices" do
|
74
74
|
expect { @graph.connect_all_vertices }.to change{ @graph.number_of_orphans }.by(-5)
|
75
75
|
end
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
describe "calculating the vertex's degree and preferential attachment" do
|
79
79
|
before :each do
|
80
80
|
@graph = Graphshaper::UndirectedGraph.new 5
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
83
|
it "should calculate the degree of 0 for every vertex in a graph without edges" do
|
84
84
|
5.times do |vertex_id|
|
85
85
|
@graph.vertex_degree_for(vertex_id).should ==0
|
86
86
|
end
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
it "should calculate the degree for a vertex with two edges" do
|
90
90
|
@graph.add_edge 0,1
|
91
91
|
@graph.add_edge 1,2
|
92
92
|
@graph.vertex_degree_for(1).should ==2
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
it "should calculate the sum of all degrees" do
|
96
96
|
@graph.add_edge 0,1
|
97
97
|
@graph.add_edge 1,2
|
98
98
|
@graph.sum_of_all_degrees.should ==4
|
99
99
|
end
|
100
|
-
|
100
|
+
|
101
101
|
it "should provide an iterator for preferential attachments that sums up to 0 for a graph without edges" do
|
102
102
|
sum = 0
|
103
103
|
@graph.each_vertex_with_preferential_attachment do |vertex_id, preferential_attachment|
|
@@ -105,7 +105,7 @@ describe Graphshaper::UndirectedGraph do
|
|
105
105
|
end
|
106
106
|
sum.should ==0
|
107
107
|
end
|
108
|
-
|
108
|
+
|
109
109
|
it "should calculate the preferential attachments in a way that their sum is always 1 when there is at least one edge" do
|
110
110
|
sum = 0
|
111
111
|
@graph.add_edge 0,1
|
@@ -114,7 +114,7 @@ describe Graphshaper::UndirectedGraph do
|
|
114
114
|
end
|
115
115
|
sum.should ==1
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
it "should add up the preferential attachments to one even if edges are added in the block" do
|
119
119
|
sum = 0
|
120
120
|
@graph.add_edge 0,1
|
@@ -124,47 +124,47 @@ describe Graphshaper::UndirectedGraph do
|
|
124
124
|
end
|
125
125
|
sum.should ==1
|
126
126
|
end
|
127
|
-
|
127
|
+
|
128
128
|
it "should add a vertex to the graph with edges according to preferential attachment" do
|
129
129
|
@graph.add_edge 0,1
|
130
|
-
|
130
|
+
|
131
131
|
# Two vertices with preferential_attachment of 0.5, all others with 0
|
132
132
|
@graph.add_vertex do |preferential_attachment|
|
133
133
|
preferential_attachment > 0.4
|
134
134
|
end
|
135
|
-
|
135
|
+
|
136
136
|
# One more vertex
|
137
137
|
@graph.order.should ==(6)
|
138
|
-
|
138
|
+
|
139
139
|
# Two additional edges
|
140
140
|
@graph.size.should ==(3)
|
141
141
|
end
|
142
142
|
end
|
143
|
-
|
143
|
+
|
144
144
|
describe "Adapter Support" do
|
145
145
|
before :each do
|
146
146
|
@adapter = double()
|
147
147
|
@adapter.stub :add_vertex
|
148
148
|
@adapter.stub :add_edge
|
149
149
|
end
|
150
|
-
|
150
|
+
|
151
151
|
it "should tell the adapter about the inital vertices on creation" do
|
152
152
|
5.times do |vertex_id|
|
153
153
|
@adapter.should_receive(:add_vertex).with(vertex_id)
|
154
154
|
end
|
155
155
|
graph = Graphshaper::UndirectedGraph.new 5, adapters: [@adapter]
|
156
156
|
end
|
157
|
-
|
157
|
+
|
158
158
|
it "should tell the adapter about later added vertices" do
|
159
159
|
graph = Graphshaper::UndirectedGraph.new 5, adapters: [@adapter]
|
160
160
|
@adapter.should_receive(:add_vertex).with(5)
|
161
161
|
graph.add_vertex
|
162
162
|
end
|
163
|
-
|
163
|
+
|
164
164
|
it "should tell the adapter about later added edges" do
|
165
165
|
graph = Graphshaper::UndirectedGraph.new 5, adapters: [@adapter]
|
166
166
|
@adapter.should_receive(:add_edge).with(0, 1, 2)
|
167
167
|
graph.add_edge 1, 2
|
168
168
|
end
|
169
169
|
end
|
170
|
-
end
|
170
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphshaper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,63 +9,88 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-03-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: httparty
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.
|
21
|
+
version: 0.10.2
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.10.2
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: rake
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ~>
|
31
36
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.
|
37
|
+
version: 10.0.3
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 10.0.3
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: rspec
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ~>
|
42
52
|
- !ruby/object:Gem::Version
|
43
|
-
version: 2.
|
53
|
+
version: 2.13.0
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.13.0
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
49
|
-
requirement:
|
63
|
+
name: webmock
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ~>
|
53
68
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
69
|
+
version: 1.11.0
|
55
70
|
type: :development
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 1.11.0
|
58
78
|
- !ruby/object:Gem::Dependency
|
59
|
-
name:
|
60
|
-
requirement:
|
79
|
+
name: yard
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
61
81
|
none: false
|
62
82
|
requirements:
|
63
83
|
- - ~>
|
64
84
|
- !ruby/object:Gem::Version
|
65
|
-
version:
|
85
|
+
version: 0.8.5.2
|
66
86
|
type: :development
|
67
87
|
prerelease: false
|
68
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.8.5.2
|
69
94
|
description: Generate realistic graphs
|
70
95
|
email:
|
71
96
|
- me@moonglum.net
|
@@ -83,14 +108,16 @@ files:
|
|
83
108
|
- bin/graphshaper
|
84
109
|
- graphshaper.gemspec
|
85
110
|
- lib/graphshaper.rb
|
86
|
-
- lib/graphshaper/adapters/
|
111
|
+
- lib/graphshaper/adapters/arangodb_adapter.rb
|
87
112
|
- lib/graphshaper/adapters/dot_adapter.rb
|
113
|
+
- lib/graphshaper/adapters/json_adapter.rb
|
88
114
|
- lib/graphshaper/adapters/logging_adapter.rb
|
89
115
|
- lib/graphshaper/adapters/sql_adapter.rb
|
90
116
|
- lib/graphshaper/undirected_graph.rb
|
91
117
|
- lib/graphshaper/version.rb
|
92
|
-
- spec/adapters/
|
118
|
+
- spec/adapters/arangodb_adapter_spec.rb
|
93
119
|
- spec/adapters/dot_adapter_spec.rb
|
120
|
+
- spec/adapters/json_adapter_spec.rb
|
94
121
|
- spec/adapters/logging_adapter_spec.rb
|
95
122
|
- spec/adapters/sql_adapter_spec.rb
|
96
123
|
- spec/spec_helper.rb
|
@@ -108,21 +135,29 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
108
135
|
- - ! '>='
|
109
136
|
- !ruby/object:Gem::Version
|
110
137
|
version: '0'
|
138
|
+
segments:
|
139
|
+
- 0
|
140
|
+
hash: -4051901559196272302
|
111
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
142
|
none: false
|
113
143
|
requirements:
|
114
144
|
- - ! '>='
|
115
145
|
- !ruby/object:Gem::Version
|
116
146
|
version: '0'
|
147
|
+
segments:
|
148
|
+
- 0
|
149
|
+
hash: -4051901559196272302
|
117
150
|
requirements: []
|
118
151
|
rubyforge_project:
|
119
|
-
rubygems_version: 1.8.
|
152
|
+
rubygems_version: 1.8.25
|
120
153
|
signing_key:
|
121
154
|
specification_version: 3
|
122
|
-
summary: Graphshaper can generate realistic, scale-free graphs of any size
|
155
|
+
summary: Graphshaper can generate realistic, scale-free graphs of any size for different
|
156
|
+
databases.
|
123
157
|
test_files:
|
124
|
-
- spec/adapters/
|
158
|
+
- spec/adapters/arangodb_adapter_spec.rb
|
125
159
|
- spec/adapters/dot_adapter_spec.rb
|
160
|
+
- spec/adapters/json_adapter_spec.rb
|
126
161
|
- spec/adapters/logging_adapter_spec.rb
|
127
162
|
- spec/adapters/sql_adapter_spec.rb
|
128
163
|
- spec/spec_helper.rb
|