sooth 1.0.3 → 2.0.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.
@@ -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.