pest 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,8 +3,6 @@ require 'narray'
3
3
 
4
4
  describe Pest::DataSet::NArray do
5
5
  before(:each) do
6
- @v1 = Pest::Variable.new(:name => :foo)
7
- @v2 = Pest::Variable.new(:name => :bar)
8
6
  @class = Pest::DataSet::NArray
9
7
  end
10
8
 
@@ -23,47 +21,30 @@ describe Pest::DataSet::NArray do
23
21
  end
24
22
 
25
23
  describe "::from_file" do
26
- before(:each) do
27
- @matrix = @class.from_hash @v1 => [1,2,3], @v2 => [4,5,6]
28
- @file = Tempfile.new('test')
29
- @matrix.save(@file.path)
30
- end
31
-
32
- it "loads from NArray IO" do
33
- @class.from_file(@file).should == @matrix
34
- end
35
-
36
- it "looks for NArray from string" do
37
- @class.from_file(@file.path).should == @matrix
38
- end
39
-
40
- it "sets variables" do
41
- @class.from_file(@file).variables.values.should == [@v1, @v2]
24
+ it "delegates to from_csv" do
25
+ @class.should_receive(:from_csv)
26
+ @class.from_file('foo')
42
27
  end
43
28
  end
44
29
 
45
30
  describe "::from_hash" do
46
31
  before(:each) do
47
- @matrix = NArray.to_na [[4,5,6],[1,2,3]]
32
+ @matrix = NArray.to_na [[1,2,3],[4,5,6]]
48
33
  end
49
34
 
50
35
  it "creates a NArray" do
51
- @class.from_hash({@v1 => [1,2,3], @v2 => [4,5,6]}).should == @matrix
36
+ @class.from_hash({:foo => [1,2,3], :bar => [4,5,6]}).data.should == @matrix
52
37
  end
53
38
 
54
39
  it "sets variables" do
55
- @class.from_hash({@v1 => [1,2,3], @v2 => [4,5,6]}).variables.values.should == [@v1, @v2]
56
- end
57
-
58
- it "generates Pest::Variables if not passed" do
59
- @class.from_hash({:foo => [1,2,3]}).variables[:foo].should be_a(Pest::Variable)
40
+ @class.from_hash({:foo => [1,2,3], :bar => [4,5,6]}).variables.should == [:foo, :bar].to_set
60
41
  end
61
42
  end
62
43
 
63
44
  describe "::from_csv" do
64
45
  before(:each) do
65
46
  @file = Tempfile.new('test_csv')
66
- CSV.open(@file.path, 'w') do |csv|
47
+ CSV.open(@file.path, 'w', :col_sep => "\t") do |csv|
67
48
  csv << ["foo", "bar"]
68
49
  csv << [1,1]
69
50
  csv << [1,2]
@@ -73,22 +54,22 @@ describe Pest::DataSet::NArray do
73
54
 
74
55
  it "creates variables from first line" do
75
56
  @instance = @class.from_csv @file.path
76
- @instance.variable_array.map(&:name).should == ["bar", "foo"]
57
+ @instance.variables.should == ["foo", "bar"].to_set
77
58
  end
78
59
 
79
60
  it "creates data from the rest" do
80
61
  @instance = @class.from_csv @file.path
81
- @instance.to_hash.should == {@instance.variables["foo"] => [1,1,1], @instance.variables["bar"] => [1,2,3]}
62
+ @instance.to_hash.should == {"foo" => [1,1,1], "bar" => [1,2,3]}
82
63
  end
83
64
 
84
65
  it "accepts a filename" do
85
66
  @instance = @class.from_csv @file.path
86
- @instance.to_hash.should == {@instance.variables["foo"] => [1,1,1], @instance.variables["bar"] => [1,2,3]}
67
+ @instance.to_hash.should == {"foo" => [1,1,1], "bar" => [1,2,3]}
87
68
  end
88
69
 
89
70
  it "accepts an IO" do
90
71
  @instance = @class.from_csv @file
91
- @instance.to_hash.should == {@instance.variables["foo"] => [1,1,1], @instance.variables["bar"] => [1,2,3]}
72
+ @instance.to_hash.should == {"foo" => [1,1,1], "bar" => [1,2,3]}
92
73
  end
93
74
  end
94
75
 
@@ -98,44 +79,123 @@ describe Pest::DataSet::NArray do
98
79
  end
99
80
 
100
81
  it "sets keys" do
101
- @instance.to_hash.keys.should == @instance.variables.values
82
+ @instance.to_hash.keys.to_set.should == @instance.variables
102
83
  end
103
84
 
104
85
  it "sets values" do
105
- @instance.to_hash.values.should == [[4,5,6],[1,2,3]]
86
+ @instance.to_hash.values.should == [[1,2,3],[4,5,6]]
106
87
  end
107
88
  end
108
89
 
109
- describe "#data_vectors" do
90
+ describe "#pick" do
110
91
  before(:each) do
111
92
  @instance = @class.from_hash :foo => [1,2,3], :bar => [4,5,6]
112
93
  end
113
94
 
114
- it "returns an enumerable" do
115
- @instance.data_vectors.should be_a(Enumerable)
95
+ it "accepts a single symbol string" do
96
+ @instance.pick(:foo).data.to_a.first.should == [1,2,3]
97
+ end
98
+
99
+ it "accepts a single variable" do
100
+ @instance.pick(:foo).data.to_a.first.should == [1,2,3]
101
+ end
102
+
103
+ it "accepts multiple variables" do
104
+ @instance.pick(:bar, :foo).data.to_a.should == [[4,5,6],[1,2,3]]
105
+ end
106
+ end
107
+
108
+ describe "#[]" do
109
+ before(:each) do
110
+ @all = @class.from_hash :foo => [1,2,3,4], :bar => [5,6,7,8]
111
+ @range_subset = @class.from_hash :foo => [1,2], :bar => [5,6]
112
+ @index_subset = @class.from_hash :foo => [4], :bar => [8]
113
+ @union_subset = @class.from_hash :foo => [4,1,2], :bar => [8,5,6]
114
+ end
115
+
116
+ context "with integer argument" do
117
+ it "returns a copy with the vector at the passed index" do
118
+ @all[3].should == @index_subset
119
+ end
120
+ end
121
+
122
+ context "with a range argument" do
123
+ it "returns a copy with the vectors specified by the range" do
124
+ @all[0..1].should == @range_subset
125
+ end
126
+ end
127
+
128
+ context "with multiple arguments" do
129
+ it "returns a copy with the union of the passed arguments" do
130
+ @all[3,0..1].should == @union_subset
131
+ end
132
+ end
133
+ end
134
+
135
+ describe "#+" do
136
+ before(:each) do
137
+ @all = @class.from_hash :foo => [1,2,4], :bar => [5,6,8]
138
+ @set_1 = @class.from_hash :foo => [1,2], :bar => [5,6]
139
+ @set_2 = @class.from_hash :foo => [4], :bar => [8]
116
140
  end
117
141
 
118
- it "slices" do
119
- # NOTE: This is returning an array - probably could be more efficient
120
- @instance.data_vectors.first.should == [4,1]
142
+ it "returns the union of self and other" do
143
+ (@set_1 + @set_2).should == @all
121
144
  end
122
145
  end
123
146
 
124
- describe "#save" do
147
+ describe "#each" do
125
148
  before(:each) do
126
- @file = Tempfile.new('test')
127
149
  @instance = @class.from_hash :foo => [1,2,3], :bar => [4,5,6]
128
150
  end
129
151
 
130
- it "marshals to file" do
131
- @instance.save(@file)
132
- @class.from_file(@file.path).should == @instance
152
+ it "yields vectors" do
153
+ block = double("block")
154
+ block.should_receive(:yielding).with([1,4])
155
+ block.should_receive(:yielding).with([2,5])
156
+ block.should_receive(:yielding).with([3,6])
157
+ @instance.each {|i| block.yielding(i)}
158
+ end
159
+ end
160
+
161
+ describe "#map" do
162
+ before(:each) do
163
+ @instance = @class.from_hash :foo => [1,2,3], :bar => [4,5,6]
164
+ end
165
+
166
+ it "works" do
167
+ @instance.map {|i| i}.should == [[1,4],[2,5],[3,6]]
168
+ end
169
+ end
170
+
171
+ describe "#merge" do
172
+ before(:each) do
173
+ @other = @class.from_hash :foo => [10,11,12,13], :baz => [1,2,3,4]
174
+ @instance = @class.from_hash :foo => [1,2,3,4], :bar => [5,6,7,8]
175
+ end
176
+
177
+ it "accepts a dataset and returns dataset" do
178
+ @instance.merge(@other).should be_a(@class)
179
+ end
180
+
181
+ it "accepts a hash and returns dataset" do
182
+ @instance.merge(:foo => [10,11,12,13], :baz => [1,2,3,4]).should be_a(@class)
183
+ end
184
+
185
+ it "requires the dataset to have the same length" do
186
+ expect { @instance.merge(:foo => [1,2,3,4,5]) }.to raise_error(ArgumentError)
187
+ end
188
+
189
+ it "adds the passed variable to self" do
190
+ @instance.merge(@other).variables.should include(:baz)
191
+ end
192
+
193
+ it "adds the passed data to self" do
194
+ @instance.merge(@other).pick(:baz).to_a.should == [1,2,3,4]
133
195
  end
134
196
 
135
- it "saves to tmp dir if no filename specified" do
136
- Tempfile.should_receive(:new).and_return(@file)
137
- @instance.save
138
- @class.from_file(@file.path).should == @instance
197
+ it "over-writes variables in self with variables in other" do
198
+ @instance.merge(@other).pick(:foo).to_a.should == [10,11,12,13]
139
199
  end
140
200
  end
141
201
  end
@@ -91,5 +91,40 @@ describe Pest::DataSet do
91
91
  end
92
92
  end
93
93
 
94
- # Enumerable interface?
94
+ describe "#[]" do
95
+ context "with a single argument" do
96
+ it "returns NotImplementedError" do
97
+ expect { @instance[1] }.to raise_error(NotImplementedError)
98
+ end
99
+ end
100
+
101
+ context "with multiple arguments" do
102
+ it "returns NotImplementedError" do
103
+ expect { @instance[1,5] }.to raise_error(NotImplementedError)
104
+ end
105
+ end
106
+ end
107
+
108
+ describe "#+" do
109
+ it "returns NotImplementedError" do
110
+ expect { @instance + @instance }.to raise_error(NotImplementedError)
111
+ end
112
+ end
113
+
114
+ it "inherits from Enumerable" do
115
+ @instance = TestClass.new
116
+ @instance.should be_a(Enumerable)
117
+ end
118
+
119
+ describe "#each" do
120
+ it "yields vectors" do
121
+ expect { @instance.each {} }.to raise_error(NotImplementedError)
122
+ end
123
+ end
124
+
125
+ describe "#merge" do
126
+ it "returns NotImplementedError" do
127
+ expect { @instance.merge(@instance) }.to raise_error(NotImplementedError)
128
+ end
129
+ end
95
130
  end
@@ -3,10 +3,8 @@ require 'spec_helper'
3
3
  describe Pest::Estimator::Frequency do
4
4
  before(:each) do
5
5
  @class = Pest::Estimator::Frequency
6
- @v1 = Pest::Variable.new(:name => :foo)
7
- @v2 = Pest::Variable.new(:name => :bar)
8
- @data = Pest::DataSet::NArray.from_hash @v1 => [1,1,2,3], @v2 => [1,1,1,1]
9
- @test = Pest::DataSet::NArray.from_hash @v1 => [1,2,4], @v2 => [1,1,1]
6
+ @data = Pest::DataSet::NArray.from_hash :foo => [1,1,2,3], :bar => [1,1,1,1]
7
+ @test = Pest::DataSet::NArray.from_hash :foo => [1,2,4], :bar => [1,1,1]
10
8
  @instance = @class.new(@data)
11
9
  end
12
10
 
@@ -15,56 +13,57 @@ describe Pest::Estimator::Frequency do
15
13
  end
16
14
 
17
15
  it "generates marginal probabilities" do
18
- @instance.p(@v2).in(@test).should === NArray[[1.0, 1.0, 1.0]]
16
+ @instance.p(:bar => 1).should == 1.0
19
17
  end
20
18
 
21
19
  it "generates joint probability" do
22
- @instance.p(@v1, @v2).in(@test).should == NArray[[0.5, 0.25, 0]]
20
+ @instance.p(:foo => 2, :bar => 1).should == 0.25
23
21
  end
24
22
 
25
23
  it "generates conditional probability" do
26
- @instance.p(@v1).given(@v2).in(@test).should == NArray[[0.5, 0.25, 0]]
24
+ @instance.p(:foo => 2).given(:bar => 1).should == 0.25
25
+ end
26
+
27
+ it "generates marginal batch_probabilities" do
28
+ @instance.batch_p(:bar).in(@test).should == [1.0, 1.0, 1.0]
29
+ end
30
+
31
+ it "generates joint batch_probability" do
32
+ @instance.batch_p(:foo, :bar).in(@test).should == [0.5, 0.25, 0]
33
+ end
34
+
35
+ it "generates conditional batch_probability" do
36
+ @instance.batch_p(:foo).given(:bar).in(@test).should == [0.5, 0.25, 0]
27
37
  end
28
38
 
29
39
  describe Pest::Estimator::Frequency::Distribution do
30
40
  before(:each) do
31
- @dist = @instance.distributions[@data.variables.values.to_set]
41
+ @dist = @instance.distributions[*@data.variables]
32
42
  end
33
43
 
34
44
  describe "#cache_model" do
35
- context "with unrecognized checksum" do
36
- it "determines vector frequency" do
37
- @dist.cache_model
38
- @dist.frequencies[[1,1]].should == 2
39
- end
40
-
41
- it "defaults to 0" do
42
- @dist.cache_model
43
- @dist.frequencies[[4,1]].should == 0
44
- end
45
- end
46
-
47
- context "with recognized checksum but no file" do
48
- it "determines vector frequency" do
49
- @data.should_receive(:data_vectors).and_return @data
50
- @dist.cache_model
51
- end
45
+ it "determines vector frequency" do
46
+ @dist.cache_model
47
+ @dist.frequencies[[1,1]].should == 2
52
48
  end
53
49
 
54
- context "with recognized checksum and cache file" do
55
- before(:each) do
56
- @file = @dist.cache_model
57
- end
50
+ it "defaults to 0" do
51
+ @dist.cache_model
52
+ @dist.frequencies[[4,1]].should == 0
58
53
  end
59
54
  end
60
55
 
61
56
  describe "#probability" do
62
- it "returns an NArray" do
57
+ before(:each) do
58
+ @test = Pest::DataSet::Hash.from_hash(:foo => [1], :bar => [1])
59
+ end
60
+
61
+ it "returns an float" do
63
62
  @dist.probability(@test).should be_a(NArray)
64
63
  end
65
64
 
66
- it "calculates vector frequency / dataset length" do
67
- @dist.probability(@test).should == NArray[[0.5,0.25,0]]
65
+ it "calculates frequency / dataset length" do
66
+ @dist.probability(@test).to_a.should == [0.5]
68
67
  end
69
68
  end
70
69
 
@@ -28,32 +28,28 @@ describe Pest::Estimator do
28
28
 
29
29
  describe "#estimates" do
30
30
  before(:each) do
31
- @v1 = Pest::Variable.new(:name => :foo)
32
- @v2 = Pest::Variable.new(:name => :bar)
33
- @v3 = Pest::Variable.new(:name => :baz)
34
-
35
31
  @instance = TestClass.new
36
- @instance.stub(:variables).and_return({:foo => @v1, :bar => @v2})
32
+ @instance.stub(:variables).and_return([:foo, :bar].to_set)
37
33
  end
38
34
 
39
35
  it "accepts a set of variables" do
40
- @instance.distributions[@v1, @v2].should be_a(Pest::Estimator::Distribution)
36
+ @instance.distributions[:foo, :bar].should be_a(Pest::Estimator::Distribution)
41
37
  end
42
38
 
43
39
  it "returns an estimator for the passed variables" do
44
- @instance.distributions[@v1, @v2].variables.should == [@v1, @v2].to_set
40
+ @instance.distributions[:foo, :bar].variables.should == [:foo, :bar].to_set
45
41
  end
46
42
 
47
43
  it "returns an estimator for the passed strings" do
48
- @instance.distributions[:foo, :bar].variables.should == [@v1, @v2].to_set
44
+ @instance.distributions[:foo, :bar].variables.should == [:foo, :bar].to_set
49
45
  end
50
46
 
51
47
  it "is variable order agnostic" do
52
- @instance.distributions[@v1, @v2].should == @instance.distributions[@v2, @v1]
48
+ @instance.distributions[:foo, :bar].should == @instance.distributions[:bar, :foo]
53
49
  end
54
50
 
55
51
  it "fails if a set variable isn't defined" do
56
- lambda { @instance.distributions[@v1, @v3] }.should raise_error(ArgumentError)
52
+ lambda { @instance.distributions[:foo, :baz] }.should raise_error(ArgumentError)
57
53
  end
58
54
  end
59
55
 
@@ -61,10 +57,16 @@ describe Pest::Estimator do
61
57
  before(:each) do
62
58
  @class = TestClass::Distribution
63
59
  @estimator = TestClass.new
64
- @estimator.stub(:variables).and_return({:foo => @v1, :bar => @v2})
60
+ @estimator.stub(:variables).and_return({:foo => :foo, :bar => :bar})
65
61
  @instance = @class.new(@estimator, @estimator.variables)
66
62
  end
67
63
 
64
+ describe "#batch_probability" do
65
+ it "raises no implemented" do
66
+ expect { @instance.batch_probability }.to raise_error(NotImplementedError)
67
+ end
68
+ end
69
+
68
70
  describe "#probability" do
69
71
  it "raises no implemented" do
70
72
  expect { @instance.probability }.to raise_error(NotImplementedError)
@@ -7,11 +7,8 @@ end
7
7
 
8
8
  describe Pest::Function::Entropy do
9
9
  before(:each) do
10
- @v1 = Pest::Variable.new(:name => :foo)
11
- @v2 = Pest::Variable.new(:name => :bar)
12
- @v3 = Pest::Variable.new(:name => :baz)
13
10
  @instance = EntropyTestClass.new
14
- @instance.stub(:variables).and_return({:foo => @v1, :bar => @v2})
11
+ @instance.stub(:variables).and_return([:foo, :bar].to_set)
15
12
  end
16
13
 
17
14
  describe "#entropy" do
@@ -26,18 +23,18 @@ describe Pest::Function::Entropy do
26
23
 
27
24
  describe Pest::Function::Entropy::Builder do
28
25
  describe "::new" do
29
- before(:each) { @builder = EntropyTestClass::Builder.new(@instance, [@v1, :bar]) }
26
+ before(:each) { @builder = EntropyTestClass::Builder.new(@instance, [:foo, :bar]) }
30
27
 
31
28
  it "sets estimator" do
32
29
  @builder.estimator.should == @instance
33
30
  end
34
31
 
35
32
  it "sets event" do
36
- @builder.event.should == [@v1, @v2].to_set
33
+ @builder.event.should == [:foo, :bar].to_set
37
34
  end
38
35
 
39
36
  it "fails if variable undefined for estimator" do
40
- lambda { EntropyTestClass::Builder.new(@instance, [@v1, @v3]) }.should raise_error(ArgumentError)
37
+ lambda { EntropyTestClass::Builder.new(@instance, [:foo, :baz]) }.should raise_error(ArgumentError)
41
38
  end
42
39
 
43
40
  it "constructs dataset if passed hash"
@@ -48,7 +45,7 @@ describe Pest::Function::Entropy do
48
45
 
49
46
  it "sets givens" do
50
47
  @builder.given(:bar)
51
- @builder.givens.should include(@v2)
48
+ @builder.givens.should include(:bar)
52
49
  end
53
50
 
54
51
  it "returns self" do
@@ -69,7 +66,7 @@ describe Pest::Function::Entropy do
69
66
 
70
67
  it "gets entropy of event" do
71
68
  event = double('EntropyEventDist')
72
- @instance.distributions.stub(:[]).with([@v1].to_set).and_return(event)
69
+ @instance.distributions.stub(:[]).with([:foo].to_set).and_return(event)
73
70
  event.should_receive(:entropy).and_return 0.5
74
71
 
75
72
  EntropyTestClass::Builder.new(@instance,[:foo]).evaluate
@@ -78,8 +75,8 @@ describe Pest::Function::Entropy do
78
75
  it "gets entropy of givens" do
79
76
  event = double("EntropyEventDist", :entropy => 0.5)
80
77
  given = double("EntropyGivenDist", :entropy => 0.25)
81
- @instance.distributions.stub(:[]).with([@v1].to_set).and_return(event)
82
- @instance.distributions.stub(:[]).with([@v2].to_set).and_return(given)
78
+ @instance.distributions.stub(:[]).with([:foo].to_set).and_return(event)
79
+ @instance.distributions.stub(:[]).with([:bar].to_set).and_return(given)
83
80
  given.should_receive(:entropy).and_return 0.25
84
81
 
85
82
  EntropyTestClass::Builder.new(@instance,[:foo]).given(:bar).evaluate
@@ -88,15 +85,15 @@ describe Pest::Function::Entropy do
88
85
  it "returns H event - givens (if givens)" do
89
86
  event = double("EntropyEventDist", :entropy => 0.5)
90
87
  given = double("EntropyGivenDist", :entropy => 0.1)
91
- @instance.distributions.stub(:[]).with([@v1].to_set).and_return(event)
92
- @instance.distributions.stub(:[]).with([@v2].to_set).and_return(given)
88
+ @instance.distributions.stub(:[]).with([:foo].to_set).and_return(event)
89
+ @instance.distributions.stub(:[]).with([:bar].to_set).and_return(given)
93
90
 
94
91
  EntropyTestClass::Builder.new(@instance,[:foo]).given(:bar).evaluate.should == 0.4
95
92
  end
96
93
 
97
94
  it "returns H event (if no givens)" do
98
95
  event = double("EntropyEventDist", :entropy => 0.5)
99
- @instance.distributions.stub(:[]).with([@v1].to_set).and_return(event)
96
+ @instance.distributions.stub(:[]).with([:foo].to_set).and_return(event)
100
97
 
101
98
  EntropyTestClass::Builder.new(@instance,[:foo]).evaluate.should == 0.5
102
99
  end