elaine 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,23 @@
1
+
2
+ require 'elaine/distributed'
3
+ class DistributedPageRankVertex < Elaine::Distributed::Vertex
4
+ def compute
5
+ # puts "Working on supserstep: #{superstep}"
6
+ if superstep >= 1
7
+ # sum = messages.inject(0) {|total,msg| total += msg; total }
8
+ # sum = messages.reduce(0, :+)
9
+ sum = messages.reduce(0) do |total, msg|
10
+ raise "Got an out-of-step message! current superstep: #{superstep}, message from superstep: #{msg[:superstep]}" if msg[:superstep] != (superstep - 1)
11
+ total += msg[:value]
12
+
13
+ end
14
+ @value = (0.15 / 3) + 0.85 * sum
15
+ end
16
+
17
+ if superstep < 30
18
+ deliver_to_all_neighbors({value: @value / neighbors.size, superstep: superstep})
19
+ else
20
+ halt
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,41 @@
1
+
2
+ require 'elaine/distributed'
3
+ class DistributedTriadCensusVertex < Elaine::Distributed::Vertex
4
+ def compute
5
+ # puts "Working on supserstep: #{superstep}"
6
+ if superstep == 1
7
+ deliver_to_all_neighbors({source: id; neighborhood: @outedges})
8
+ elsif superstep == 2
9
+ # sum = messages.inject(0) {|total,msg| total += msg; total }
10
+ # sum = messages.reduce(0, :+)
11
+ @value = {type2: 0, type3: 0 }
12
+
13
+ u = id.to_s.plit("_")[1].to_i
14
+ messages.each(0) do |msg|
15
+ # raise "Got an out-of-step message! current superstep: #{superstep}, message from superstep: #{msg[:superstep]}" if msg[:superstep] != (superstep - 1)
16
+ v = msg[:source].to_s.split("_")[1].to_i
17
+ if u < v
18
+
19
+ msg[:neighborhood].each do |node_w|
20
+ w = node_w.to_s.split("_")[1].to_i
21
+ if v < w
22
+ num_edges = 2
23
+ if @outedges.include? node_w
24
+ num_edges += 1
25
+ end
26
+
27
+ @value[:type2] += 1 if num_edges == 2
28
+ @value[:type3] += 1 if num_edges == 3
29
+
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ else
36
+ vote_to_stop
37
+ end
38
+
39
+
40
+ end
41
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'elaine'
2
+
3
+ include Elaine
4
+
5
+ class AddVertex < Vertex
6
+ def compute
7
+ @value += 1
8
+ halt if @value >= 5
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ require 'elaine/distributed'
2
+ class DistributedAddVertex < Elaine::Distributed::Vertex
3
+ def compute
4
+ @value += 1
5
+ halt if @value >= 5
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ require 'elaine'
2
+ require 'elaine/distributed'
3
+ require 'dcell'
4
+ # require 'test_add_vertex'
5
+
6
+ load File.expand_path("../test_add_vertex.rb", __FILE__)
7
+ load File.expand_path("../distributed_page_rank_vertex.rb", __FILE__)
8
+
9
+ DCell.start id: "test.elaine.coordinator", addr: "tcp://127.0.0.1:8090"
10
+
11
+ Elaine::Distributed::Coordinator.supervise_as :coordinator
12
+ sleep
@@ -0,0 +1,12 @@
1
+ require 'elaine'
2
+ require 'elaine/distributed'
3
+ require 'dcell'
4
+
5
+ load File.expand_path("../test_add_vertex.rb", __FILE__)
6
+ load File.expand_path("../distributed_page_rank_vertex.rb", __FILE__)
7
+
8
+ DCell.start id: "test.elaine.worker1", addr: "tcp://127.0.0.1:8091"
9
+
10
+ Elaine::Distributed::Worker.supervise_as :worker, coordinator_node: "test.elaine.coordinator"
11
+ Elaine::Distributed::PostOffice.supervise_as :postoffice
12
+ sleep
@@ -0,0 +1,12 @@
1
+ require 'elaine'
2
+ require 'elaine/distributed'
3
+ require 'dcell'
4
+
5
+ load File.expand_path("../test_add_vertex.rb", __FILE__)
6
+ load File.expand_path("../distributed_page_rank_vertex.rb", __FILE__)
7
+
8
+ DCell.start id: "test.elaine.worker2", addr: "tcp://127.0.0.1:8092"
9
+
10
+ Elaine::Distributed::Worker.supervise_as :worker, coordinator_node: "test.elaine.coordinator"
11
+ Elaine::Distributed::PostOffice.supervise_as :postoffice
12
+ sleep
@@ -0,0 +1,56 @@
1
+ require 'helper'
2
+
3
+ describe Vertex do
4
+ it 'should create a vertex with id, value, and edges' do
5
+ lambda { Vertex.new(:a, 10, :b) }.should_not raise_error
6
+ lambda { Vertex.new(:a, 10, :b, :c) }.should_not raise_error
7
+ end
8
+
9
+ let(:v) { Vertex.new(:a, 10, :b, :c) }
10
+
11
+ it 'should report new vertex as active' do
12
+ v.active?.should be_true
13
+
14
+ v.halt
15
+ v.active?.should be_false
16
+ end
17
+
18
+ it 'should contain a modifiable value' do
19
+ v.value = 20
20
+ v.value.should == 20
21
+ end
22
+
23
+ it 'should keep track of the current superstep' do
24
+ v.superstep.should == 0
25
+ v.step
26
+ v.superstep.should == 1
27
+ end
28
+
29
+ it 'should allow iterating over out-edges' do
30
+ v.edges.size.should == 2
31
+ v.edges.each {|e| [:b, :c].should include e }
32
+ end
33
+
34
+ it 'should allow arbitrary type for edge' do
35
+ lambda do
36
+ Vertex.new(:a, 10, {id: 1, weight:10}, {id: 2, weight:20})
37
+ end.should_not raise_error
38
+ end
39
+
40
+ it 'should allow a user defined compute' do
41
+ class V < Vertex
42
+ def compute; @value = 20; end
43
+ end
44
+
45
+ v = V.new(:a, 10)
46
+ v.compute
47
+ v.value.should == 20
48
+ end
49
+
50
+ it 'should have an inbox for incoming messages' do
51
+ v.messages.size.should == 0
52
+ v.messages = [:a, :b]
53
+ v.messages.size.should == 2
54
+ end
55
+
56
+ end
@@ -0,0 +1,61 @@
1
+ require 'helper'
2
+
3
+ describe Worker do
4
+
5
+ let(:graph) do
6
+ [
7
+ AddVertex.new(:igvita, 1, :wikipedia),
8
+ AddVertex.new(:wikipedia, 2, :google),
9
+ AddVertex.new(:google, 1, :wikipedia)
10
+ ]
11
+ end
12
+
13
+ let(:worker) do
14
+ Worker.new(graph)
15
+ end
16
+
17
+ it 'should accept non-zero number of nodes' do
18
+ lambda { Worker.new([]) }.should raise_error
19
+ end
20
+
21
+ it 'should partition graphs with variable worker sizes' do
22
+ graph = [
23
+ Vertex.new(:igvita, 1, :wikipedia),
24
+ Vertex.new(:wikipedia, 2, :google),
25
+ Vertex.new(:google, 1, :wikipedia)
26
+ ]
27
+
28
+ c = Coordinator.new(graph)
29
+ c.workers.size.should == 1
30
+
31
+ c = Coordinator.new(graph, partitions: 2)
32
+ c.workers.size.should == 2
33
+ end
34
+
35
+ it 'should execute an async superstep' do
36
+ # TODO: simulate async message delivery to worker by returning
37
+ # a thread per message
38
+ worker.superstep.should be_an_instance_of Thread
39
+ end
40
+
41
+ it 'should perform single iteration on the graph' do
42
+ # TODO: reuse a threadpool within worker for each partition
43
+ worker.superstep.join
44
+ worker.vertices.first.value.should == 2
45
+ end
46
+
47
+ it 'should return the number of active vertices for next superstep' do
48
+ worker.superstep.join
49
+ worker.active.should > 0
50
+ end
51
+
52
+ it 'should deliver messages to vertices at beginning of each superstep' do
53
+ PostOffice.instance.deliver(:igvita, 'hello')
54
+ worker.superstep.join
55
+
56
+ ig = worker.vertices.find {|v| v.id == :igvita }
57
+ ig.messages.size.should == 1
58
+ ig.messages.first.should == 'hello'
59
+ end
60
+
61
+ end
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: elaine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Blackburn
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
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: celluloid-io
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
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: dcell
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: activesupport
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Distribtuted implementation of Google's Pregel framework for large-scale
98
+ graph processing. Forked from http://github.com/igrigorik/pregel
99
+ email:
100
+ - jeremy.blackburn@gmail.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - .gitignore
106
+ - .ruby-version
107
+ - Gemfile
108
+ - README.md
109
+ - Rakefile
110
+ - autotest/discover.rb
111
+ - elaine.gemspec
112
+ - examples/.gitignore
113
+ - examples/erdos-renyi-N_1000-E_0.2.egonets
114
+ - lib/elaine.rb
115
+ - lib/elaine/coordinator.rb
116
+ - lib/elaine/distributed.rb
117
+ - lib/elaine/distributed/coordinator.rb
118
+ - lib/elaine/distributed/post_office.rb
119
+ - lib/elaine/distributed/vertex.rb
120
+ - lib/elaine/distributed/worker.rb
121
+ - lib/elaine/version.rb
122
+ - lib/elaine/vertex.rb
123
+ - lib/elaine/worker.rb
124
+ - spec/coordinator_spec.rb
125
+ - spec/distributed_coordinator_spec.rb
126
+ - spec/distributed_helper.rb
127
+ - spec/distributed_page_rank_vertex.rb
128
+ - spec/distributed_triad_census_vertex.rb
129
+ - spec/helper.rb
130
+ - spec/test_add_vertex.rb
131
+ - spec/test_coordinator_node.rb
132
+ - spec/test_worker_node1.rb
133
+ - spec/test_worker_node2.rb
134
+ - spec/vertex_spec.rb
135
+ - spec/worker_spec.rb
136
+ homepage: http://bitbucket.org/worst/elaine
137
+ licenses: []
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - '>='
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubyforge_project: elaine
155
+ rubygems_version: 2.0.6
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: Distribtuted implementation of Google's Pregel framework for large-scale
159
+ graph processing. Forked from http://github.com/igrigorik/pregel
160
+ test_files:
161
+ - spec/coordinator_spec.rb
162
+ - spec/distributed_coordinator_spec.rb
163
+ - spec/distributed_helper.rb
164
+ - spec/distributed_page_rank_vertex.rb
165
+ - spec/distributed_triad_census_vertex.rb
166
+ - spec/helper.rb
167
+ - spec/test_add_vertex.rb
168
+ - spec/test_coordinator_node.rb
169
+ - spec/test_worker_node1.rb
170
+ - spec/test_worker_node2.rb
171
+ - spec/vertex_spec.rb
172
+ - spec/worker_spec.rb
173
+ has_rdoc: