random_graph 0.1.1 → 0.1.2
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/.DS_Store +0 -0
- data/examples/sample01.png +0 -0
- data/examples/sample01.rb +6 -10
- data/examples/sample02.png +0 -0
- data/examples/sample02.rb +11 -15
- data/examples/sample03.rb +18 -23
- data/examples/sample04.rb +18 -23
- data/examples/sample05.png +0 -0
- data/examples/sample05.rb +38 -0
- data/examples/sample06.png +0 -0
- data/examples/sample06.rb +36 -0
- data/lib/.DS_Store +0 -0
- data/lib/random_graph/graph.rb +5 -6
- data/lib/random_graph/graph_algorithms.rb +14 -17
- data/lib/random_graph/random_generators.rb +24 -24
- data/lib/random_graph/version.rb +1 -1
- metadata +7 -3
- data/ .png +0 -0
- data/ .png +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dbd2560a240a7b9578cfd98169134fc9bd55c8d2
|
4
|
+
data.tar.gz: e8d5ce5ea32ffdcdbd333f4ededb4d9220397a6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20e734e0fbb5c61a1c94ee1c4cceac1919dd1e4c481709058c9c4d5dfeb8ae9c6feea97c605109df56e43961f55e873929fe496f212b1ba4bae486db2089984e
|
7
|
+
data.tar.gz: eb9b767894501dd04627310d26a1a5b006d3bae38d85ed33e8ed60a981442f99a0a7b452957446e6e17313de1e617e7b04a560f9149ad985ccb72fac3a64e9b8
|
data/.DS_Store
CHANGED
Binary file
|
Binary file
|
data/examples/sample01.rb
CHANGED
@@ -8,8 +8,8 @@ include RandomGraph
|
|
8
8
|
probability = []
|
9
9
|
data = []
|
10
10
|
|
11
|
-
size =
|
12
|
-
trials =
|
11
|
+
size = 20
|
12
|
+
trials = 10
|
13
13
|
(0..100).step(1) do |int|
|
14
14
|
puts "progress! #{int}" if int % 5 == 0
|
15
15
|
# puts int
|
@@ -28,12 +28,8 @@ g = Gruff::Bar.new
|
|
28
28
|
g.sort = false
|
29
29
|
g.title = 'probability vs. Number of connected components '
|
30
30
|
g.data('number of componetns', data)
|
31
|
-
g.y_axis_increment = 1
|
32
|
-
g.x_axis_label =
|
33
|
-
g.y_axis_label =
|
34
|
-
g.y_axis_increment = 10
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
g.write('sample02.png')
|
31
|
+
g.y_axis_increment = 1 # Points shown on the Y axis
|
32
|
+
g.x_axis_label = 'p value'
|
33
|
+
g.y_axis_label = 'number of connected components '
|
39
34
|
|
35
|
+
g.write('sample01.png')
|
Binary file
|
data/examples/sample02.rb
CHANGED
@@ -5,37 +5,33 @@ require 'gruff'
|
|
5
5
|
|
6
6
|
include RandomGraph
|
7
7
|
|
8
|
-
|
9
|
-
size = 900
|
8
|
+
size = 1000
|
10
9
|
p = 0.1
|
11
10
|
g = Graph.erdos_renyi_gnp(size, p)
|
12
11
|
frequency = Array.new(size)
|
13
12
|
frequency.fill(0)
|
14
13
|
(0...size).each do |i|
|
15
14
|
deg = g.degree(i)
|
16
|
-
frequency[deg] += 1
|
17
|
-
end
|
15
|
+
frequency[deg] += 1
|
16
|
+
end
|
18
17
|
|
19
18
|
max = 0
|
20
19
|
(0...size).each do |i|
|
21
|
-
max = i if frequency[i] > 0
|
22
|
-
end
|
20
|
+
max = i if frequency[i] > 0
|
21
|
+
end
|
23
22
|
|
24
|
-
new_freq = Array.new(max+1)
|
25
|
-
(0...max+1).each do |i|
|
23
|
+
new_freq = Array.new(max + 1)
|
24
|
+
(0...max + 1).each do |i|
|
26
25
|
new_freq[i] = frequency[i]
|
27
26
|
end
|
28
27
|
|
29
28
|
g = Gruff::Bar.new
|
30
29
|
g.sort = false
|
31
|
-
g.title = 'Degree distribution'
|
30
|
+
g.title = 'Degree distribution erdos_renyi_gnp'
|
32
31
|
g.data('Frequency', new_freq)
|
33
|
-
g.y_axis_increment = 1
|
34
|
-
g.x_axis_label =
|
35
|
-
g.y_axis_label =
|
32
|
+
g.y_axis_increment = 1 # Points shown on the Y axis
|
33
|
+
g.x_axis_label = 'Node Degree'
|
34
|
+
g.y_axis_label = 'Frequency'
|
36
35
|
g.y_axis_increment = 5
|
37
36
|
|
38
|
-
|
39
|
-
|
40
37
|
g.write('sample02.png')
|
41
|
-
|
data/examples/sample03.rb
CHANGED
@@ -5,39 +5,34 @@ require 'gruff'
|
|
5
5
|
|
6
6
|
include RandomGraph
|
7
7
|
|
8
|
-
the_hash = {}
|
9
|
-
|
10
|
-
(0...300000).each do |i|
|
8
|
+
the_hash = {}
|
11
9
|
|
10
|
+
(0...300_000).each do |_i|
|
12
11
|
g = Graph.erdos_renyi_gnm(4, 3)
|
13
12
|
x = 0b000000
|
14
|
-
x ^= 0b100000 if g.edge?(0,1)
|
15
|
-
x ^= 0b010000 if g.edge?(0,2)
|
16
|
-
x ^= 0b001000 if g.edge?(0,3)
|
17
|
-
x ^= 0b000100 if g.edge?(1,2)
|
18
|
-
x ^= 0b000010 if g.edge?(1,3)
|
19
|
-
x ^= 0b000001 if g.edge?(2,3)
|
20
|
-
|
21
|
-
if the_hash.
|
13
|
+
x ^= 0b100000 if g.edge?(0, 1)
|
14
|
+
x ^= 0b010000 if g.edge?(0, 2)
|
15
|
+
x ^= 0b001000 if g.edge?(0, 3)
|
16
|
+
x ^= 0b000100 if g.edge?(1, 2)
|
17
|
+
x ^= 0b000010 if g.edge?(1, 3)
|
18
|
+
x ^= 0b000001 if g.edge?(2, 3)
|
19
|
+
|
20
|
+
if the_hash.key?(x)
|
22
21
|
the_hash[x] = 1 + the_hash[x]
|
23
|
-
else
|
24
|
-
the_hash[x] = 1
|
25
|
-
end
|
26
|
-
end
|
22
|
+
else
|
23
|
+
the_hash[x] = 1
|
24
|
+
end
|
25
|
+
end
|
27
26
|
|
28
27
|
data = []
|
29
|
-
the_hash.each_value {|v| data << v }
|
30
|
-
|
28
|
+
the_hash.each_value { |v| data << v }
|
31
29
|
|
32
30
|
g = Gruff::Bar.new
|
33
31
|
g.sort = false
|
34
32
|
g.title = '4 node, 3 edge distribution'
|
35
33
|
g.data('Frequency', data)
|
36
|
-
g.y_axis_increment =
|
37
|
-
g.x_axis_label =
|
38
|
-
g.y_axis_label =
|
39
|
-
|
40
|
-
|
34
|
+
g.y_axis_increment = 10_000 # Points shown on the Y axis
|
35
|
+
g.x_axis_label = 'graph layout'
|
36
|
+
g.y_axis_label = 'Frequency'
|
41
37
|
|
42
38
|
g.write('sample03.png')
|
43
|
-
|
data/examples/sample04.rb
CHANGED
@@ -5,39 +5,34 @@ require 'gruff'
|
|
5
5
|
|
6
6
|
include RandomGraph
|
7
7
|
|
8
|
-
the_hash = {}
|
9
|
-
|
10
|
-
(0...30000).each do |i|
|
8
|
+
the_hash = {}
|
11
9
|
|
10
|
+
(0...30_000).each do |_i|
|
12
11
|
g = Graph.erdos_renyi_gnm(4, 5)
|
13
12
|
x = 0b000000
|
14
|
-
x ^= 0b100000 if g.edge?(0,1)
|
15
|
-
x ^= 0b010000 if g.edge?(0,2)
|
16
|
-
x ^= 0b001000 if g.edge?(0,3)
|
17
|
-
x ^= 0b000100 if g.edge?(1,2)
|
18
|
-
x ^= 0b000010 if g.edge?(1,3)
|
19
|
-
x ^= 0b000001 if g.edge?(2,3)
|
20
|
-
|
21
|
-
if the_hash.
|
13
|
+
x ^= 0b100000 if g.edge?(0, 1)
|
14
|
+
x ^= 0b010000 if g.edge?(0, 2)
|
15
|
+
x ^= 0b001000 if g.edge?(0, 3)
|
16
|
+
x ^= 0b000100 if g.edge?(1, 2)
|
17
|
+
x ^= 0b000010 if g.edge?(1, 3)
|
18
|
+
x ^= 0b000001 if g.edge?(2, 3)
|
19
|
+
|
20
|
+
if the_hash.key?(x)
|
22
21
|
the_hash[x] = 1 + the_hash[x]
|
23
|
-
else
|
24
|
-
the_hash[x] = 1
|
25
|
-
end
|
26
|
-
end
|
22
|
+
else
|
23
|
+
the_hash[x] = 1
|
24
|
+
end
|
25
|
+
end
|
27
26
|
|
28
27
|
data = []
|
29
|
-
the_hash.each_value {|v| data << v }
|
30
|
-
|
28
|
+
the_hash.each_value { |v| data << v }
|
31
29
|
|
32
30
|
g = Gruff::Bar.new
|
33
31
|
g.sort = false
|
34
32
|
g.title = '4 node, 5 edge distribution'
|
35
33
|
g.data('Frequency', data)
|
36
|
-
g.y_axis_increment =
|
37
|
-
g.x_axis_label =
|
38
|
-
g.y_axis_label =
|
39
|
-
|
40
|
-
|
34
|
+
g.y_axis_increment = 10_000 # Points shown on the Y axis
|
35
|
+
g.x_axis_label = 'graph layout'
|
36
|
+
g.y_axis_label = 'Frequency'
|
41
37
|
|
42
38
|
g.write('sample04.png')
|
43
|
-
|
Binary file
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'random_graph'
|
4
|
+
require 'gruff'
|
5
|
+
|
6
|
+
include RandomGraph
|
7
|
+
|
8
|
+
the_hash = {}
|
9
|
+
|
10
|
+
(0...300_000).each do |_i|
|
11
|
+
g = Graph.erdos_renyi_gnp(4, 0.5)
|
12
|
+
x = 0b000000
|
13
|
+
x ^= 0b100000 if g.edge?(0, 1)
|
14
|
+
x ^= 0b010000 if g.edge?(0, 2)
|
15
|
+
x ^= 0b001000 if g.edge?(0, 3)
|
16
|
+
x ^= 0b000100 if g.edge?(1, 2)
|
17
|
+
x ^= 0b000010 if g.edge?(1, 3)
|
18
|
+
x ^= 0b000001 if g.edge?(2, 3)
|
19
|
+
|
20
|
+
if the_hash.key?(x)
|
21
|
+
the_hash[x] = 1 + the_hash[x]
|
22
|
+
else
|
23
|
+
the_hash[x] = 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
data = []
|
28
|
+
the_hash.each_value { |v| data << v }
|
29
|
+
|
30
|
+
g = Gruff::Bar.new
|
31
|
+
g.sort = false
|
32
|
+
g.title = '4 node, 0.5 probability GNP'
|
33
|
+
g.data('Frequency', data)
|
34
|
+
g.y_axis_increment = 10_000 # Points shown on the Y axis
|
35
|
+
g.x_axis_label = 'graph layout'
|
36
|
+
g.y_axis_label = 'Frequency'
|
37
|
+
|
38
|
+
g.write('sample05.png')
|
Binary file
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'random_graph'
|
4
|
+
require 'gruff'
|
5
|
+
|
6
|
+
include RandomGraph
|
7
|
+
|
8
|
+
size = 1000
|
9
|
+
g = Graph.preferential_attachment(size)
|
10
|
+
frequency = Array.new(size)
|
11
|
+
frequency.fill(0)
|
12
|
+
(0...size).each do |i|
|
13
|
+
deg = g.degree(i)
|
14
|
+
frequency[deg] += 1
|
15
|
+
end
|
16
|
+
|
17
|
+
max = 0
|
18
|
+
(0...size).each do |i|
|
19
|
+
max = i if frequency[i] > 0
|
20
|
+
end
|
21
|
+
|
22
|
+
new_freq = Array.new(max + 1)
|
23
|
+
(0...max + 1).each do |i|
|
24
|
+
new_freq[i] = frequency[i]
|
25
|
+
end
|
26
|
+
|
27
|
+
g = Gruff::Bar.new
|
28
|
+
g.sort = false
|
29
|
+
g.title = 'Degree distribution preferential_attachment'
|
30
|
+
g.data('Frequency', new_freq)
|
31
|
+
g.y_axis_increment = 1 # Points shown on the Y axis
|
32
|
+
g.x_axis_label = 'Node Degree'
|
33
|
+
g.y_axis_label = 'Frequency'
|
34
|
+
g.y_axis_increment = 80
|
35
|
+
|
36
|
+
g.write('sample06.png')
|
data/lib/.DS_Store
CHANGED
Binary file
|
data/lib/random_graph/graph.rb
CHANGED
@@ -46,12 +46,11 @@ module RandomGraph
|
|
46
46
|
|
47
47
|
# add edge between two nodes
|
48
48
|
def add_edge(from, to)
|
49
|
-
fail ArgumentError
|
50
|
-
fail ArgumentError
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
49
|
+
fail ArgumentError, 'invalid node' if from >= @size || from < 0
|
50
|
+
fail ArgumentError, 'invalid node' if to >= @size || to < 0
|
51
|
+
return if to == from
|
52
|
+
@nodes[from] << to unless @nodes[from].include?(to)
|
53
|
+
@nodes[to] << from unless @nodes[to].include?(from)
|
55
54
|
end
|
56
55
|
|
57
56
|
def remove_edge(from, to)
|
@@ -1,14 +1,11 @@
|
|
1
|
-
#
|
1
|
+
# reopen module
|
2
2
|
module RandomGraph
|
3
|
+
# module implements graph algorithms
|
3
4
|
module GraphAlgorithms
|
4
|
-
def
|
5
|
-
distance = Array.new(@size)
|
6
|
-
|
7
|
-
|
8
|
-
queue = []
|
9
|
-
|
5
|
+
def bfs_distance(root)
|
6
|
+
distance = Array.new(@size).fill(Float::INFINITY)
|
7
|
+
queue = [root]
|
10
8
|
distance[root] = 0
|
11
|
-
queue.unshift(root)
|
12
9
|
|
13
10
|
until queue.empty?
|
14
11
|
|
@@ -18,14 +15,14 @@ module RandomGraph
|
|
18
15
|
if distance[a] == Float::INFINITY
|
19
16
|
distance[a] = distance[current] + 1
|
20
17
|
queue.unshift(a)
|
21
|
-
|
18
|
+
end
|
22
19
|
end
|
23
|
-
|
20
|
+
end
|
24
21
|
distance
|
25
|
-
|
22
|
+
end
|
26
23
|
|
27
24
|
def connected_component(root)
|
28
|
-
distances =
|
25
|
+
distances = bfs_distance(root)
|
29
26
|
adjacent = []
|
30
27
|
(0...distances.size).each do |i|
|
31
28
|
adjacent << i unless distances[i] == Float::INFINITY
|
@@ -53,25 +50,25 @@ module RandomGraph
|
|
53
50
|
worst = 0
|
54
51
|
if real_bad == 0
|
55
52
|
(0...size).each do |i|
|
56
|
-
distances =
|
53
|
+
distances = bfs_distance(i)
|
57
54
|
worst = [distances.max, worst].max
|
58
55
|
end
|
59
|
-
|
56
|
+
end
|
60
57
|
[worst, real_bad].max
|
61
|
-
|
58
|
+
end
|
62
59
|
|
63
60
|
def average_case_diameter
|
64
61
|
real_bad = number_of_components > 1 ? Float::INFINITY : 0
|
65
62
|
total = 0
|
66
63
|
if real_bad == 0
|
67
64
|
(0...size).each do |i|
|
68
|
-
distances =
|
65
|
+
distances = bfs_distance(i)
|
69
66
|
average = distances.inject(:+).to_f / (size - 1)
|
70
67
|
total += average
|
71
68
|
end
|
72
69
|
end
|
73
70
|
total / size
|
74
|
-
|
71
|
+
end
|
75
72
|
|
76
73
|
def clustering_coefficient
|
77
74
|
total_cluster = 0
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module RandomGraph
|
2
|
+
# implements random graph generators
|
2
3
|
module RandomGenerators
|
3
4
|
# Select a graph randomly, where all graphs with n nodes and m edges
|
4
5
|
# are equally likely to be selected.
|
@@ -8,39 +9,35 @@ module RandomGraph
|
|
8
9
|
# express as a summation, which is upper bounded by O(n^2)
|
9
10
|
|
10
11
|
def erdos_renyi_gnm(n, m)
|
11
|
-
fail ArgumentError
|
12
|
-
fail ArgumentError
|
12
|
+
fail ArgumentError, 'must have positive number of nodes' if n < 0
|
13
|
+
fail ArgumentError, 'must have positive number of edges' if m < 0
|
13
14
|
|
14
15
|
possible_edges = n * (n - 1) / 2
|
15
16
|
|
16
|
-
fail ArgumentError
|
17
|
+
fail ArgumentError, 'too many edges' if m > possible_edges
|
17
18
|
|
18
19
|
# create empty graph
|
19
20
|
g = Graph.new(n)
|
20
|
-
added_edges = {}
|
21
21
|
|
22
22
|
# for every edge
|
23
|
-
(0...m).each do |
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
to = rand(0...n)
|
31
|
-
valid_edge = !g.edge?(from, to) && (from != to)
|
32
|
-
end until valid_edge == true
|
23
|
+
(0...m).each do |_i|
|
24
|
+
loop do
|
25
|
+
# select a random number, representing on of the possible edges
|
26
|
+
from = rand(0...n)
|
27
|
+
to = rand(0...n)
|
28
|
+
break if !g.edge?(from, to) && (from != to)
|
29
|
+
end
|
33
30
|
g.add_edge(from, to)
|
34
31
|
end
|
35
32
|
g
|
36
|
-
|
33
|
+
end
|
37
34
|
|
38
35
|
# Create a graph with n nodes, where all edges have a probability p
|
39
36
|
# of existing
|
40
37
|
def erdos_renyi_gnp(n, p)
|
41
|
-
fail ArgumentError
|
42
|
-
fail ArgumentError
|
43
|
-
fail ArgumentError
|
38
|
+
fail ArgumentError, 'must have positive number of nodes' if n < 0
|
39
|
+
fail ArgumentError, 'need positive probability' if p < 0
|
40
|
+
fail ArgumentError, 'probability cannot be greater than 1!' if p > 1
|
44
41
|
|
45
42
|
# create empty graph
|
46
43
|
g = Graph.new(n)
|
@@ -52,12 +49,12 @@ module RandomGraph
|
|
52
49
|
g
|
53
50
|
end
|
54
51
|
|
55
|
-
# creates a
|
52
|
+
# creates a watts-strogatz random graph. n represents the number of nodes,
|
56
53
|
# k is the mean degree, and b is the beta parameter
|
57
54
|
def watts_strogatz(n, k, b)
|
58
|
-
fail ArgumentError
|
59
|
-
fail ArgumentError
|
60
|
-
fail ArgumentError
|
55
|
+
fail ArgumentError, 'must have positive number of nodes' if n < 0
|
56
|
+
fail ArgumentError, 'invalid beta parameter' if b < 0 || b > 1
|
57
|
+
fail ArgumentError, 'invalid mean degree if' if k > n || k < Math.log10(n)
|
61
58
|
|
62
59
|
# construction of regular ring lattice
|
63
60
|
g = Graph.new(n)
|
@@ -91,8 +88,9 @@ module RandomGraph
|
|
91
88
|
g
|
92
89
|
end
|
93
90
|
|
91
|
+
# preferential attachement model enforces power law degree distribution
|
94
92
|
def preferential_attachment(size)
|
95
|
-
fail ArgumentError
|
93
|
+
fail ArgumentError, 'invalid number of nodes' if size < 2
|
96
94
|
g = Graph.new(2)
|
97
95
|
g.add_edge(0, 1)
|
98
96
|
total_degree = 2
|
@@ -113,8 +111,10 @@ module RandomGraph
|
|
113
111
|
g
|
114
112
|
end
|
115
113
|
|
114
|
+
# n x n grid, with vertices isolated with probability p
|
115
|
+
|
116
116
|
def random_grid(n, p)
|
117
|
-
fail ArgumentError
|
117
|
+
fail ArgumentError, 'invalid probability' if p > 1 || p < 0
|
118
118
|
g = Graph.new(n**2)
|
119
119
|
(0...n**2).each do |i|
|
120
120
|
bottom = (i + n) % n**2
|
data/lib/random_graph/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: random_graph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- fselame
|
@@ -105,8 +105,6 @@ executables: []
|
|
105
105
|
extensions: []
|
106
106
|
extra_rdoc_files: []
|
107
107
|
files:
|
108
|
-
- " .png"
|
109
|
-
- " .png"
|
110
108
|
- ".DS_Store"
|
111
109
|
- ".gitignore"
|
112
110
|
- ".rspec"
|
@@ -119,12 +117,18 @@ files:
|
|
119
117
|
- bin/console
|
120
118
|
- bin/setup
|
121
119
|
- examples/.DS_Store
|
120
|
+
- examples/sample01.png
|
122
121
|
- examples/sample01.rb
|
122
|
+
- examples/sample02.png
|
123
123
|
- examples/sample02.rb
|
124
124
|
- examples/sample03.png
|
125
125
|
- examples/sample03.rb
|
126
126
|
- examples/sample04.png
|
127
127
|
- examples/sample04.rb
|
128
|
+
- examples/sample05.png
|
129
|
+
- examples/sample05.rb
|
130
|
+
- examples/sample06.png
|
131
|
+
- examples/sample06.rb
|
128
132
|
- lib/.DS_Store
|
129
133
|
- lib/random_graph.rb
|
130
134
|
- lib/random_graph/.DS_Store
|
data/ .png
DELETED
Binary file
|
data/ .png
DELETED
Binary file
|