pest 0.0.0 → 0.1.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,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