borel 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1 +1,2 @@
1
1
  pkg
2
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "http://www.rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rspec', '~> 2.8.0'
7
+ gem 'guard', '~> 1.0.0'
8
+ end
@@ -0,0 +1,6 @@
1
+ guard 'rspec', :version => 2 do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/borel/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
6
+
@@ -1,3 +1,5 @@
1
+ (The MIT License)
2
+
1
3
  Copyright (c) 2012 Amadeus Folego
2
4
 
3
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
data/README.md CHANGED
@@ -12,8 +12,8 @@ Borelian sets are formed by enumerable union, intersection or
12
12
 
13
13
  [1]: http://intervals.rubyforge.org
14
14
 
15
- Installation
16
- ------------
15
+ Install
16
+ -------
17
17
 
18
18
  You may install it traditionally, for interactive sessions:
19
19
 
@@ -111,7 +111,46 @@ Interval['a','c'] ^ Interval['b','d'] # -> Interval['b','c']
111
111
  Interval['a','c'] | Interval['b','d'] # -> Interval['a','d']
112
112
  ```
113
113
 
114
- ### Remarks
114
+ Math Extensions
115
+ ---------------
115
116
 
116
- * There is no distinction between **open** and **closed** intervals
117
- * Complement and Minus operations are not supported on any class
117
+ By requiring `borel/math_extensions` you are provided with some natural
118
+ math-related interval methods:
119
+
120
+ ```ruby
121
+ Interval[1,5].rand # -> Random.new.rand 1..5
122
+ Interval[1,5].width # -> 5-1 or 4
123
+ ```
124
+
125
+ It's supported only for Numeric Comparable and arithmetic supported classes
126
+
127
+ Remarks
128
+ -------
129
+
130
+ * There is no distinction between **open** and **closed**intervals
131
+ * Complement and Minus operations have limited support for
132
+ non numeric-comparable classes
133
+
134
+ License
135
+ -------
136
+
137
+ (The MIT License)
138
+
139
+ Copyright (c) 2012 Amadeus Folego
140
+
141
+ Permission is hereby granted, free of charge, to any person obtaining a copy
142
+ of this software and associated documentation files (the "Software"), to
143
+ deal in the Software without restriction, including without limitation the
144
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
145
+ sell copies of the Software, and to permit persons to whom the Software is
146
+ furnished to do so, subject to the following conditions:
147
+
148
+ The above copyright notice and this permission notice shall be included in
149
+ all copies or substantial portions of the Software.
150
+
151
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
152
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
153
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
154
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
155
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
156
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -8,7 +8,9 @@ Gem::Specification.new do |s|
8
8
  s.email = ["amadeusfolego@gmail.com"]
9
9
  s.homepage = "http://github.com/amadeusfolego/borel"
10
10
  s.summary = "Generic ordered set's operations"
11
- s.description = "Borel sets are made of enumerable union and intersection of intervals. Borel performs regular set operations on any interval of a Comparable class."
11
+ s.description = "Borel sets are made of enumerable union and intersection of
12
+ intervals. Borel performs regular operations on any interval of any
13
+ Comparable class."
12
14
  s.rubyforge_project = s.name
13
15
  s.required_ruby_version = ">= 1.9.3"
14
16
  s.required_rubygems_version = ">= 1.3.6"
@@ -0,0 +1,36 @@
1
+ module Borel
2
+ class Construction < ArgumentError
3
+ def initialize(array)
4
+ super(
5
+ "An interval can only be constructed either from at most two " \
6
+ "numbers or from a sequence of arrays of at most two numbers: " +
7
+ array.inspect)
8
+ end
9
+ end
10
+
11
+ class NonDegenerate < ArgumentError
12
+ def initialize(i)
13
+ super("#{i.inspect} is not degenerate.")
14
+ end
15
+ end
16
+
17
+ class NonSimple < ArgumentError
18
+ def initialize(i)
19
+ super("#{i.inspect} is not simple.")
20
+ end
21
+ end
22
+
23
+ class EmptyInterval < ArgumentError
24
+ def initialize
25
+ super("The interval is empty.")
26
+ end
27
+ end
28
+
29
+ class OpenRight < ArgumentError
30
+ def initialize(range)
31
+ super(
32
+ "Cannot construct an interval from a three-dot range " \
33
+ "with end-value #{range.last.inspect}.")
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,5 @@
1
+ require 'borel/errors'
2
+
1
3
  Infinity = 1/0.0
2
4
 
3
5
  class Interval
@@ -200,34 +202,3 @@ class Interval::Multiple < Interval
200
202
  self
201
203
  end
202
204
  end
203
-
204
- module Borel
205
- class Construction < ArgumentError
206
- def initialize(array)
207
- super(
208
- "An interval can only be constructed either from at most two " \
209
- "numbers or from a sequence of arrays of at most two numbers: " +
210
- array.inspect)
211
- end
212
- end
213
-
214
- class NonDegenerate < ArgumentError
215
- def initialize(i)
216
- super("#{i.inspect} is not degenerate.")
217
- end
218
- end
219
-
220
- class NonSimple < ArgumentError
221
- def initialize(i)
222
- super("#{i.inspect} is not simple.")
223
- end
224
- end
225
-
226
- class OpenRight < ArgumentError
227
- def initialize(range)
228
- super(
229
- "Cannot construct an interval from a three-dot range " \
230
- "with end-value #{range.last.inspect}.")
231
- end
232
- end
233
- end
@@ -0,0 +1,2 @@
1
+ require 'borel/math_extensions/randomizable'
2
+ require 'borel/math_extensions/interval_arithmetic'
@@ -0,0 +1,13 @@
1
+ require 'borel'
2
+
3
+ module Borel
4
+ module IntervalArithmetic
5
+ def width
6
+ raise NonSimple, self unless self.respond_to?(:simple?) and self.simple?
7
+ self.extrema.last - self.extrema.first
8
+ end
9
+
10
+ Interval.send(:include, self)
11
+ end
12
+ end
13
+
@@ -0,0 +1,20 @@
1
+ require 'borel/math_extensions/interval_arithmetic'
2
+
3
+ module Borel
4
+ module Randomizable
5
+ def rand
6
+ raise EmptyInterval if self.respond_to?(:empty?) and self.empty?
7
+
8
+ if self.simple?
9
+ Random.new.rand Range.new *self.extrema
10
+ else
11
+ total_weight = self.map(&:width).reduce(:+)
12
+ selected_weight = Random.new.rand 0..total_weight
13
+ rand_interval = self.find{|c| (selected_weight -= c.width) <= 0}
14
+ Random.new.rand Range.new *rand_interval.extrema
15
+ end
16
+ end
17
+
18
+ Interval.send(:include, self)
19
+ end
20
+ end
@@ -1,7 +1,7 @@
1
1
  module Borel
2
2
  MAJOR = 0
3
- MINOR = 1
4
- TINY = 1
3
+ MINOR = 2
4
+ TINY = 0
5
5
 
6
6
  VERSION = [MAJOR, MINOR, TINY].join('.')
7
7
 
@@ -0,0 +1,33 @@
1
+ require 'borel/math_extensions/interval_arithmetic'
2
+
3
+ describe Borel::IntervalArithmetic do
4
+ it "should include #width" do
5
+ class Foo
6
+ include Borel::IntervalArithmetic
7
+ end
8
+
9
+ Foo.instance_methods.should include :width
10
+ end
11
+
12
+ context "#width" do
13
+ specify "Interval[1,2] -> 1" do
14
+ Interval[1,2].width.should be 1
15
+ end
16
+
17
+ specify "Interval[-1,2] -> 3" do
18
+ Interval[-1,2].width.should be 3
19
+ end
20
+
21
+ specify "Interval[1] -> 0" do
22
+ Interval[1].width.should be 0
23
+ end
24
+
25
+ it "should raise error if not simple" do
26
+ expect{Interval[].width}.
27
+ to raise_error Borel::NonSimple
28
+
29
+ expect{Interval[[1,2],[3,4]].width}.
30
+ to raise_error Borel::NonSimple
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,54 @@
1
+ require 'borel/math_extensions/randomizable'
2
+
3
+ describe Borel::Randomizable do
4
+ it 'should include #rand' do
5
+ class Foo
6
+ include Borel::Randomizable
7
+ end
8
+
9
+ Foo.instance_methods.should include :rand
10
+ end
11
+
12
+ context '#random' do
13
+ let(:interval){ Interval[1,10] }
14
+ let(:rand_mock) { mock }
15
+
16
+ it 'should be a point inside the interval' do
17
+ interval.should include interval.rand
18
+ end
19
+
20
+ it 'should be itself if degenerate' do
21
+ Interval[5].rand.should be 5
22
+ end
23
+
24
+ it 'should be a random number on simple intervals' do
25
+ random_number = 3
26
+ Random.should_receive(:new).and_return(rand_mock)
27
+ rand_mock.should_receive(:rand).with(1..10).and_return(random_number)
28
+
29
+ interval.rand.should be random_number
30
+ end
31
+
32
+ it 'should run on multiple intervals by weight' do
33
+ interval = Interval[[1,5],[6,8]]
34
+
35
+ Random.should_receive(:new).exactly(2).times.and_return(rand_mock)
36
+ rand_mock.should_receive(:rand).with(0..6).and_return(4)
37
+ rand_mock.should_receive(:rand).with(1..5).and_return(3)
38
+
39
+ interval.rand.should be 3
40
+
41
+ Random.should_receive(:new).exactly(2).times.and_return(rand_mock)
42
+ rand_mock.should_receive(:rand).with(0..6).and_return(6)
43
+ rand_mock.should_receive(:rand).with(6..8).and_return(7)
44
+
45
+ interval.rand.should be 7
46
+ end
47
+
48
+ it 'should raise error if empty' do
49
+ expect{Interval[].rand}.
50
+ to raise_error Borel::EmptyInterval
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,11 @@
1
+ require 'borel/math_extensions'
2
+
3
+ describe "Intervals Math Extensions" do
4
+ specify do
5
+ Interval.should include Borel::Randomizable
6
+ end
7
+
8
+ specify do
9
+ Interval.should include Borel::IntervalArithmetic
10
+ end
11
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: borel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,10 +9,13 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-18 00:00:00.000000000 Z
12
+ date: 2012-02-24 00:00:00.000000000 Z
13
13
  dependencies: []
14
- description: Borel sets are made of enumerable union and intersection of intervals.
15
- Borel performs regular set operations on any interval of a Comparable class.
14
+ description: ! 'Borel sets are made of enumerable union and intersection of
15
+
16
+ intervals. Borel performs regular operations on any interval of any
17
+
18
+ Comparable class.'
16
19
  email:
17
20
  - amadeusfolego@gmail.com
18
21
  executables: []
@@ -21,17 +24,26 @@ extra_rdoc_files: []
21
24
  files:
22
25
  - .gitignore
23
26
  - .rspec
24
- - MIT-LICENSE
27
+ - Gemfile
28
+ - Guardfile
29
+ - LICENSE
25
30
  - README.md
26
31
  - Rakefile
27
32
  - borel.gemspec
28
33
  - lib/borel.rb
34
+ - lib/borel/errors.rb
29
35
  - lib/borel/interval.rb
36
+ - lib/borel/math_extensions.rb
37
+ - lib/borel/math_extensions/interval_arithmetic.rb
38
+ - lib/borel/math_extensions/randomizable.rb
30
39
  - lib/borel/nil_class.rb
31
40
  - lib/borel/numeric.rb
32
41
  - lib/borel/range.rb
33
42
  - lib/borel/version.rb
34
43
  - spec/interval_spec.rb
44
+ - spec/math_extensions/interval_arithmetic_spec.rb
45
+ - spec/math_extensions/randomizable_spec.rb
46
+ - spec/math_extensions_spec.rb
35
47
  - spec/nil_class_spec.rb
36
48
  - spec/numeric_spec.rb
37
49
  - spec/range_spec.rb
@@ -57,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
69
  version: 1.3.6
58
70
  requirements: []
59
71
  rubyforge_project: borel
60
- rubygems_version: 1.8.11
72
+ rubygems_version: 1.8.10
61
73
  signing_key:
62
74
  specification_version: 3
63
75
  summary: Generic ordered set's operations