sooth 1.0.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,176 +3,214 @@ require 'tempfile'
3
3
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
4
 
5
5
  describe Sooth::Predictor do
6
- let(:predictor) { Sooth::Predictor.new(42) }
6
+ let(:error_event) { 42 }
7
+ let(:predictor) { Sooth::Predictor.new(error_event) }
7
8
 
8
9
  describe "#observe" do
9
- it "increments observation counts" do
10
- expect(predictor.observe([1,2], 3)).to eq(1)
11
- expect(predictor.observe([1,2], 3)).to eq(2)
12
- expect(predictor.observe([1,2], 3)).to eq(3)
10
+ it "increments counts" do
11
+ expect(predictor.observe(1, 3)).to eq(1)
12
+ expect(predictor.observe(1, 3)).to eq(2)
13
+ expect(predictor.observe(1, 3)).to eq(3)
13
14
  end
14
15
 
15
- it "properly sorts and finds bigrams" do
16
- expect(predictor.observe([2,1], 3)).to eq(1)
17
- expect(predictor.observe([1,3], 2)).to eq(1)
18
- expect(predictor.observe([3,2], 1)).to eq(1)
19
- expect(predictor.observe([1,3], 2)).to eq(2)
20
- expect(predictor.observe([2,1], 3)).to eq(2)
21
- expect(predictor.observe([3,2], 1)).to eq(2)
16
+ it "sorts and finds contexts" do
17
+ expect(predictor.observe(2, 3)).to eq(1)
18
+ expect(predictor.observe(1, 2)).to eq(1)
19
+ expect(predictor.observe(3, 1)).to eq(1)
20
+ expect(predictor.observe(1, 2)).to eq(2)
21
+ expect(predictor.observe(2, 3)).to eq(2)
22
+ expect(predictor.observe(3, 1)).to eq(2)
22
23
  end
23
24
  end
24
25
 
25
26
  describe "#count" do
26
- it "returns a zero count for an unobserved bigram" do
27
- expect(predictor.count([1,2])).to eq(0)
27
+ it "returns zero for an unobserved context" do
28
+ expect(predictor.count(1)).to eq(0)
28
29
  end
29
30
 
30
- it "returns the total count for an observed bigram" do
31
- predictor.observe([1,2], 2)
32
- predictor.observe([1,2], 1)
33
- predictor.observe([1,2], 4)
34
- predictor.observe([1,2], 3)
35
- predictor.observe([1,2], 0)
36
- predictor.observe([1,2], 1)
37
- predictor.observe([1,2], 4)
38
- expect(predictor.count([1,2])).to eq(7)
31
+ it "returns the number of observations" do
32
+ predictor.observe(1, 2)
33
+ predictor.observe(1, 1)
34
+ predictor.observe(1, 4)
35
+ predictor.observe(1, 3)
36
+ predictor.observe(1, 0)
37
+ predictor.observe(1, 1)
38
+ predictor.observe(1, 4)
39
+ expect(predictor.count(1)).to eq(7)
39
40
  end
40
41
  end
41
42
 
43
+ describe "#size" do
44
+ it "returns zero for an unobserved context" do
45
+ expect(predictor.size(1)).to eq(0)
46
+ end
47
+
48
+ it "returns the number of distinct events" do
49
+ predictor.observe(1, 2)
50
+ predictor.observe(1, 1)
51
+ predictor.observe(1, 4)
52
+ predictor.observe(1, 3)
53
+ predictor.observe(1, 0)
54
+ predictor.observe(1, 1)
55
+ predictor.observe(1, 4)
56
+ expect(predictor.size(1)).to eq(5)
57
+ end
58
+
59
+ end
60
+
42
61
  describe "#select" do
43
- it "returns the error symbol for an unobserved bigram" do
44
- expect(predictor.select([1,2], 1)).to eq(42)
45
- end
46
-
47
- it "returns the correct symbol for an observed bigram" do
48
- predictor.observe([1,2], 4)
49
- predictor.observe([1,2], 3)
50
- predictor.observe([1,2], 4)
51
- predictor.observe([1,2], 5)
52
- expect(predictor.select([1,2], 1)).to eq(3)
53
- expect(predictor.select([1,2], 2)).to eq(4)
54
- expect(predictor.select([1,2], 3)).to eq(4)
55
- expect(predictor.select([1,2], 4)).to eq(5)
56
- end
57
-
58
- it "returns the error symbol for a limit that is out of range" do
59
- predictor.observe([1,2], 4)
60
- predictor.observe([1,2], 3)
61
- predictor.observe([1,2], 5)
62
- expect(predictor.select([1,2], 0)).to eq(42)
63
- expect(predictor.select([1,2], 4)).to eq(42)
64
- end
65
-
66
- it "selects the correct symbol with many contexts" do
67
- predictor.observe([2,1], 4)
68
- predictor.observe([1,3], 5)
69
- predictor.observe([3,2], 6)
70
- predictor.observe([1,3], 7)
71
- predictor.observe([2,1], 8)
72
- predictor.observe([3,2], 9)
73
- predictor.observe([1,3], 1)
74
- predictor.observe([2,1], 2)
75
- predictor.observe([3,2], 3)
76
- expect(predictor.select([2,1], 0)).to eq(42)
77
- expect(predictor.select([2,1], 1)).to eq(2)
78
- expect(predictor.select([2,1], 2)).to eq(4)
79
- expect(predictor.select([2,1], 3)).to eq(8)
80
- expect(predictor.select([2,1], 4)).to eq(42)
81
- expect(predictor.select([1,3], 0)).to eq(42)
82
- expect(predictor.select([1,3], 1)).to eq(1)
83
- expect(predictor.select([1,3], 2)).to eq(5)
84
- expect(predictor.select([1,3], 3)).to eq(7)
85
- expect(predictor.select([1,3], 4)).to eq(42)
86
- expect(predictor.select([3,2], 0)).to eq(42)
87
- expect(predictor.select([3,2], 1)).to eq(3)
88
- expect(predictor.select([3,2], 2)).to eq(6)
89
- expect(predictor.select([3,2], 3)).to eq(9)
90
- expect(predictor.select([3,2], 4)).to eq(42)
62
+ it "returns the error event for an unobserved context" do
63
+ expect(predictor.select(1, 1)).to eq(error_event)
64
+ end
65
+
66
+ it "returns the correct event for an observed context" do
67
+ predictor.observe(1, 4)
68
+ predictor.observe(1, 3)
69
+ predictor.observe(1, 4)
70
+ predictor.observe(1, 5)
71
+ expect(predictor.select(1, 1)).to eq(3)
72
+ expect(predictor.select(1, 2)).to eq(4)
73
+ expect(predictor.select(1, 3)).to eq(4)
74
+ expect(predictor.select(1, 4)).to eq(5)
75
+ end
76
+
77
+ it "returns the error event for a limit that is out of range" do
78
+ predictor.observe(1, 4)
79
+ predictor.observe(1, 3)
80
+ predictor.observe(1, 5)
81
+ expect(predictor.select(1, 0)).to eq(error_event)
82
+ expect(predictor.select(1, 4)).to eq(error_event)
83
+ end
84
+
85
+ it "selects the correct event with many contexts" do
86
+ predictor.observe(2, 4)
87
+ predictor.observe(1, 5)
88
+ predictor.observe(3, 6)
89
+ predictor.observe(1, 7)
90
+ predictor.observe(2, 8)
91
+ predictor.observe(3, 9)
92
+ predictor.observe(1, 1)
93
+ predictor.observe(2, 2)
94
+ predictor.observe(3, 3)
95
+ expect(predictor.select(2, 0)).to eq(error_event)
96
+ expect(predictor.select(2, 1)).to eq(2)
97
+ expect(predictor.select(2, 2)).to eq(4)
98
+ expect(predictor.select(2, 3)).to eq(8)
99
+ expect(predictor.select(2, 4)).to eq(error_event)
100
+ expect(predictor.select(1, 0)).to eq(error_event)
101
+ expect(predictor.select(1, 1)).to eq(1)
102
+ expect(predictor.select(1, 2)).to eq(5)
103
+ expect(predictor.select(1, 3)).to eq(7)
104
+ expect(predictor.select(1, 4)).to eq(error_event)
105
+ expect(predictor.select(3, 0)).to eq(error_event)
106
+ expect(predictor.select(3, 1)).to eq(3)
107
+ expect(predictor.select(3, 2)).to eq(6)
108
+ expect(predictor.select(3, 3)).to eq(9)
109
+ expect(predictor.select(3, 4)).to eq(error_event)
91
110
  end
92
111
  end
93
112
 
94
113
  describe "#clear" do
95
-
96
- it "clears to a blank slate" do
97
- expect(predictor.observe([1,2], 3)).to eq(1)
98
- expect(predictor.observe([1,2], 3)).to eq(2)
99
- expect(predictor.observe([1,2], 3)).to eq(3)
114
+ it "resets to a blank slate" do
115
+ expect(predictor.observe(1, 3)).to eq(1)
116
+ expect(predictor.observe(1, 3)).to eq(2)
117
+ expect(predictor.observe(1, 3)).to eq(3)
100
118
  predictor.clear
101
- expect(predictor.observe([1,2], 3)).to eq(1)
102
- expect(predictor.observe([1,2], 3)).to eq(2)
103
- expect(predictor.observe([1,2], 3)).to eq(3)
119
+ expect(predictor.observe(1, 3)).to eq(1)
120
+ expect(predictor.observe(1, 3)).to eq(2)
121
+ expect(predictor.observe(1, 3)).to eq(3)
104
122
  end
105
-
106
123
  end
107
124
 
108
125
  describe "#save" do
109
-
110
126
  it "can save a file and load it back again" do
111
127
  begin
112
128
  file = Tempfile.new('sooth_spec')
113
- expect(predictor.observe([1,2], 3)).to eq(1)
114
- expect(predictor.observe([2,1], 3)).to eq(1)
115
- expect(predictor.observe([1,2], 3)).to eq(2)
116
- expect(predictor.observe([1,2], 3)).to eq(3)
129
+ expect(predictor.observe(1, 3)).to eq(1)
130
+ expect(predictor.observe(2, 3)).to eq(1)
131
+ expect(predictor.observe(1, 3)).to eq(2)
132
+ expect(predictor.observe(1, 3)).to eq(3)
117
133
  expect { predictor.save(file.path) } .to_not raise_error
118
- expect(predictor.count([1,2])).to eq(3)
119
- expect(predictor.count([2,1])).to eq(1)
134
+ expect(predictor.count(1)).to eq(3)
135
+ expect(predictor.count(2)).to eq(1)
120
136
  predictor.clear
121
- expect(predictor.count([1,2])).to eq(0)
122
- expect(predictor.count([2,1])).to eq(0)
137
+ expect(predictor.count(1)).to eq(0)
138
+ expect(predictor.count(2)).to eq(0)
123
139
  expect { predictor.load(file.path) }.to_not raise_error
124
- expect(predictor.count([1,2])).to eq(3)
125
- expect(predictor.count([2,1])).to eq(1)
126
- expect(predictor.observe([1,2], 3)).to eq(4)
127
- expect(predictor.observe([1,2], 1)).to eq(1)
128
- expect(predictor.observe([2,1], 3)).to eq(2)
129
- expect(predictor.observe([2,1], 1)).to eq(1)
140
+ expect(predictor.count(1)).to eq(3)
141
+ expect(predictor.count(2)).to eq(1)
142
+ expect(predictor.observe(1, 3)).to eq(4)
143
+ expect(predictor.observe(1, 1)).to eq(1)
144
+ expect(predictor.observe(2, 3)).to eq(2)
145
+ expect(predictor.observe(2, 1)).to eq(1)
130
146
  ensure
131
147
  file.close
132
148
  file.unlink
133
149
  end
134
150
  end
151
+ end
135
152
 
153
+ describe "#distribution" do
154
+ it "can iterate over a distribution" do
155
+ end
136
156
  end
137
157
 
138
- describe "#uncertainty" do
158
+ describe "#distribution" do
159
+ it "has no distribution for a new context" do
160
+ expect(predictor.distribution(1)).to be_nil
161
+ expect(predictor.count(1)).to eq(0)
162
+ expect(predictor.uncertainty(1)).to be_nil
163
+ end
164
+
165
+ it "has a correct probability distribution" do
166
+ predictor.observe(1, 4)
167
+ predictor.observe(1, 2)
168
+ predictor.observe(1, 4)
169
+ predictor.observe(1, 3)
170
+ dist = Hash[predictor.distribution(1)]
171
+ expect(dist[1]).to be_nil
172
+ expect(dist[2]).to eq(0.25)
173
+ expect(dist[3]).to eq(0.25)
174
+ expect(dist[4]).to eq(0.5)
175
+ end
176
+ end
139
177
 
178
+ describe "#uncertainty" do
140
179
  it "has no uncertainty for a new context" do
141
- expect(predictor.uncertainty([1, 2])).to be_nil
142
- expect(predictor.count([1, 2])).to eq(0)
143
- expect(predictor.uncertainty([1, 2])).to be_nil
180
+ expect(predictor.uncertainty(1)).to be_nil
181
+ expect(predictor.count(1)).to eq(0)
182
+ expect(predictor.uncertainty(1)).to be_nil
144
183
  end
145
184
 
146
185
  it "has zero uncertainty for a lone context" do
147
- predictor.observe([1, 2], 3)
148
- expect(predictor.uncertainty([1, 2])).to eq(0)
186
+ predictor.observe(1, 3)
187
+ expect(predictor.uncertainty(1)).to eq(0)
149
188
  end
150
189
 
151
190
  it "has maximal uncertainty for a uniform distribution" do
152
- (1..256).each { |i| predictor.observe([1, 2], i) }
153
- expect(predictor.uncertainty([1, 2])).to eq(8)
191
+ (1..256).each { |i| predictor.observe(1, i) }
192
+ expect(predictor.uncertainty(1)).to eq(8)
154
193
  end
155
-
156
194
  end
157
195
 
158
196
  describe "#surprise" do
197
+ it "has no surprise for a new context" do
198
+ expect(predictor.surprise(1, 3)).to be_nil
199
+ end
159
200
 
160
- it "has no surprise for a new context or symbol" do
161
- expect(predictor.surprise([1, 2], 3)).to be_nil
162
- expect(predictor.count([1, 2])).to eq(0)
163
- expect(predictor.surprise([1, 2], 3)).to be_nil
201
+ it "has no surprise for a new event" do
202
+ predictor.observe(1, 3)
203
+ expect(predictor.surprise(1, 4)).to be_nil
164
204
  end
165
205
 
166
- it "has zero surprise for a lone context" do
167
- predictor.observe([1, 2], 3)
168
- expect(predictor.surprise([1, 2], 3)).to eq(0)
206
+ it "has zero surprise for a lone event" do
207
+ predictor.observe(1, 3)
208
+ expect(predictor.surprise(1, 3)).to eq(0)
169
209
  end
170
210
 
171
211
  it "has uniform surprise for a uniform distribution" do
172
- (1..256).each { |i| predictor.observe([1, 2], i) }
173
- expect(predictor.surprise([1, 2], 3)).to eq(8)
212
+ (1..256).each { |i| predictor.observe(1, i) }
213
+ expect(predictor.surprise(1, 3)).to eq(8)
174
214
  end
175
-
176
215
  end
177
-
178
216
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sooth
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Hutchens
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-03 00:00:00.000000000 Z
11
+ date: 2016-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '6.0'
103
+ version: '8.2'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '6.0'
110
+ version: '8.2'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rake-compiler
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -142,7 +142,6 @@ executables: []
142
142
  extensions:
143
143
  - ext/sooth_native/extconf.rb
144
144
  extra_rdoc_files:
145
- - CHANGELOG.md
146
145
  - README.md
147
146
  files:
148
147
  - CHANGELOG.md
@@ -183,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
183
182
  version: '0'
184
183
  requirements: []
185
184
  rubyforge_project:
186
- rubygems_version: 2.4.8
185
+ rubygems_version: 2.5.1
187
186
  signing_key:
188
187
  specification_version: 4
189
188
  summary: Sooth is a simple stochastic predictive model.