borel 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pkg
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/MIT-LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2012 Amadeus Folego
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,6 @@
1
+ Borel
2
+ =====
3
+
4
+ Borelian sets are sets formed by the enumerable union and intersection, or the complement, of intervals in the Real line.
5
+
6
+ **Borel** aims to make it really easy to make union and intersection operations of interval in any ordered set.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ task_file_pattern = File.expand_path("../tasks/**/*.rb", __FILE__)
2
+ Dir[task_file_pattern].each do |task_file|
3
+ require File.expand_path(task_file)
4
+ end
5
+
6
+ task :default => [ :rspec ]
data/borel.gemspec ADDED
@@ -0,0 +1,17 @@
1
+ require 'borel/version.rb'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "borel"
5
+ s.version = Borel.version
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["Amadeus Folego"]
8
+ s.email = ["amadeusfolego@gmail.com"]
9
+ s.homepage = "http://github.com/amadeusfolego/borel"
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."
12
+ s.rubyforge_project = s.name
13
+ s.required_ruby_version = ">= 1.9.3"
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+ s.files = `git ls-files`.split("\n")
16
+ s.require_path = 'lib'
17
+ end
data/lib/borel.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'borel/interval'
2
+ require 'borel/range'
3
+ require 'borel/numeric'
@@ -0,0 +1,226 @@
1
+ Infinity = 1/0.0
2
+
3
+ class Interval
4
+ include Enumerable
5
+
6
+ def Interval.[](*array)
7
+ union(*
8
+ if array.empty?
9
+ []
10
+ elsif array.first.kind_of?(Array)
11
+ array.select{|x| !x.empty?}.map{|x| Simple.new(*x)}
12
+ else
13
+ [Simple.new(*array)]
14
+ end
15
+ )
16
+ rescue
17
+ unless
18
+ array.size <= 2 || array.all?{|x| Array === x && x.size <= 2}
19
+ raise Exception::Construction, array
20
+ end
21
+ raise
22
+ end
23
+
24
+ def Interval.union(*array)
25
+ l = []
26
+ array.map(&:components).flatten.sort_by(&:inf).each{|x|
27
+ if x.sup < x.inf
28
+ # skip it
29
+ elsif l.empty? || x.inf > l.last.sup
30
+ l <<= x
31
+ elsif x.sup > l.last.sup
32
+ l[-1] = Simple.new(l.last.inf, x.sup)
33
+ end
34
+ }
35
+ if l.size == 1
36
+ l.first
37
+ else
38
+ Multiple.new(l)
39
+ end
40
+ end
41
+
42
+ def construction
43
+ map{|x| x.extrema.uniq}
44
+ end
45
+
46
+ def simple?
47
+ false
48
+ end
49
+
50
+ def inspect
51
+ "Interval" + construction.inspect
52
+ end
53
+
54
+ def to_s
55
+ inspect
56
+ end
57
+
58
+ def ==(other)
59
+ self.components == other.components
60
+ end
61
+
62
+ def include?(x)
63
+ any?{|i| i.include? x}
64
+ end
65
+
66
+ def to_interval
67
+ self
68
+ end
69
+
70
+ def coerce(other)
71
+ [other.to_interval, self]
72
+ end
73
+
74
+ def +(other)
75
+ self | other
76
+ end
77
+
78
+ def ^(other)
79
+ self & other
80
+ end
81
+
82
+ def |(other)
83
+ Interval.union(other.to_interval, self)
84
+ end
85
+
86
+ def empty?
87
+ components.empty?
88
+ end
89
+
90
+ def degenerate?
91
+ all? {|x| x.degenerate?}
92
+ end
93
+
94
+ def hull
95
+ if empty?
96
+ Interval[]
97
+ else
98
+ Interval[components.first.inf, components.last.sup]
99
+ end
100
+ end
101
+
102
+ [[:&, :intersect]].each do |op, meth|
103
+ define_method(op) {|other|
104
+ (other.to_interval.map{|y| map{|x| x.send(meth,y)}}.flatten).reduce(:|)
105
+ }
106
+ end
107
+
108
+ [[:~, :complement]].each do |op, meth|
109
+ define_method(op) {
110
+ map{|x| x.to_interval.map(&meth).reduce(:&)}.flatten.reduce(:|)
111
+ }
112
+ end
113
+
114
+ [[:-, :minus]].each do |op, meth|
115
+ define_method(op) {|other|
116
+ map{|x| other.to_interval.map{|y| x.send(meth,y)}.reduce(:&)}.flatten.reduce(:|)
117
+ }
118
+ end
119
+ end
120
+
121
+ class Interval::Simple < Interval
122
+ include Enumerable
123
+
124
+ attr :inf
125
+ attr :sup
126
+
127
+ def each
128
+ yield(self)
129
+ self
130
+ end
131
+
132
+ def components
133
+ [self]
134
+ end
135
+
136
+ def initialize (a, b = a)
137
+ if (a.respond_to?(:nan?) && a.nan? ) || (b.respond_to?(:nan?) && b.nan?)
138
+ @inf, @sup = -Infinity, Infinity
139
+ else
140
+ @inf, @sup = a, b
141
+ end
142
+ freeze
143
+ end
144
+
145
+ def ==(other)
146
+ [inf, sup] == [other.inf, other.sup]
147
+ end
148
+
149
+ def intersect(other)
150
+ Interval[[inf, other.inf].max, [sup, other.sup].min]
151
+ end
152
+
153
+ def complement
154
+ Interval[-Infinity,inf] | Interval[sup,Infinity]
155
+ end
156
+
157
+ def minus (other)
158
+ self & ~other
159
+ end
160
+
161
+ def construction
162
+ extrema.uniq
163
+ end
164
+
165
+ def simple?
166
+ true
167
+ end
168
+
169
+ def include?(x)
170
+ inf <= x && x <= sup
171
+ end
172
+
173
+ def extrema
174
+ [inf, sup]
175
+ end
176
+
177
+ def degenerate?
178
+ inf == sup
179
+ end
180
+ end
181
+
182
+ class Interval::Multiple < Interval
183
+
184
+ attr :components
185
+
186
+ def initialize(array)
187
+ @components = array
188
+ freeze
189
+ end
190
+
191
+ def each
192
+ components.each{|o| yield(o)}
193
+ self
194
+ end
195
+ end
196
+
197
+ module Borel
198
+ class Construction < ArgumentError
199
+ def initialize(array)
200
+ super(
201
+ "An interval can only be constructed either from at most two " \
202
+ "numbers or from a sequence of arrays of at most two numbers: " +
203
+ array.inspect)
204
+ end
205
+ end
206
+
207
+ class NonDegenerate < ArgumentError
208
+ def initialize(i)
209
+ super("#{i.inspect} is not degenerate.")
210
+ end
211
+ end
212
+
213
+ class NonSimple < ArgumentError
214
+ def initialize(i)
215
+ super("#{i.inspect} is not simple.")
216
+ end
217
+ end
218
+
219
+ class OpenRight < ArgumentError
220
+ def initialize(range)
221
+ super(
222
+ "Cannot construct an interval from a three-dot range " \
223
+ "with end-value #{range.last.inspect}.")
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,5 @@
1
+ class Numeric
2
+ def to_interval
3
+ Interval[self]
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ class Range
2
+ def to_interval
3
+ Interval[first,
4
+ if exclude_end?
5
+ (last - 1).succ - 1
6
+ else
7
+ last
8
+ end]
9
+ rescue NoMethodError
10
+ raise Borel::OpenRight, self if exclude_end? && !last.respond_to?(:succ)
11
+ raise
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Borel
2
+ MAJOR = 0
3
+ MINOR = 0
4
+ TINY = 1
5
+
6
+ VERSION = [MAJOR, MINOR, TINY].join('.')
7
+
8
+ def self.version
9
+ VERSION
10
+ end
11
+ end
@@ -0,0 +1,116 @@
1
+ require 'borel/interval'
2
+
3
+ describe Interval do
4
+ context '#intersection' do
5
+
6
+ it "[]^[0,3] = []" do
7
+ pending
8
+ (Interval[] ^ Interval[0,3]).should eq Interval[]
9
+ end
10
+
11
+ it "[0,3]^[] = []" do
12
+ pending
13
+ (Interval[0,3] ^ Interval[]).should eq Interval[]
14
+ end
15
+
16
+ it "[0,2]^[1] = [1]" do
17
+ (Interval[0,2] ^ Interval[1]).should eq Interval[1]
18
+ end
19
+
20
+ it "[-infty, infty]^[0,1] = [0,1]" do
21
+ (Interval[-Infinity, Infinity] ^ Interval[0,1]).should eq Interval[0,1]
22
+ end
23
+
24
+ it "[0,3]^[1,2] = [1,2]" do
25
+ (Interval[0,3] ^ Interval[1,2]).should eq Interval[1,2]
26
+ end
27
+
28
+ it "[[-2,-1],[1,2]]^[[0,3],[4,5]] = [1,2]" do
29
+ (Interval[[-2,-1],[1,2]] ^ Interval[[0,3],[4,5]]).should eq Interval[1,2]
30
+ end
31
+ end
32
+
33
+ context '#union' do
34
+ it "[0,3]U[1,2] = [0,3]" do
35
+ (Interval[0,3] | Interval[1,2]).should eq Interval[0,3]
36
+ end
37
+
38
+ it "[1,2]U[0,3] = [0,3]" do
39
+ (Interval[1,2] | Interval[0,3]).should eq Interval[0,3]
40
+ end
41
+
42
+ it "[1,2]U[1,2] = [1,2]" do
43
+ (Interval[1,2] | Interval[1,2]).should eq Interval[1,2]
44
+ end
45
+
46
+ it "[1,2]U[2,3] = [1,3]" do
47
+ (Interval[1,2] | Interval[2,3]).should eq Interval[1,3]
48
+ end
49
+
50
+ it "[1,2]U[3,4] = [[1,2],[3,4]]" do
51
+ (Interval[1,2] | Interval[3,4]).should eq Interval[[1,2],[3,4]]
52
+ end
53
+ end
54
+
55
+ context '#minus' do
56
+ it "[2,3]-(0,1) = [2,3]" do
57
+ (Interval[2,3] - Interval[0,1]).should eq Interval[2,3]
58
+ end
59
+
60
+ it '[0,1]-(2,3) = [0,1]' do
61
+ (Interval[0,1] - Interval[2,3]).should eq Interval[0,1]
62
+ end
63
+
64
+ it '[1,2]-(0,3) = []' do
65
+ (Interval[1,2] - Interval[0,3]).should be_empty
66
+ end
67
+
68
+ it '[0,3]-(1,2) = [0,1]U[2,3]' do
69
+ (Interval[0,3] - Interval[1,2]).should eq Interval[[0,1],[2,3]]
70
+ end
71
+
72
+ it '[0,1]-(0,1) = [0]U[1]' do
73
+ (Interval[0,1] - Interval[0,1]).should eq Interval[0] | Interval[1]
74
+ end
75
+
76
+ it '[1,2]-(2,3) = [1,2]' do
77
+ (Interval[1,2] - Interval[2,3]).should eq Interval[1,2]
78
+ end
79
+
80
+ it '[2,3]-(1,2) = [2,3]' do
81
+ (Interval[2,3] - Interval[1,2]).should eq Interval[2,3]
82
+ end
83
+
84
+ it '[1,4]-(0,3) = [3,4]' do
85
+ (Interval[1,4] - Interval[0,3]).should eq Interval[3,4]
86
+ end
87
+
88
+ it '[1,3]-(2,4) = [1,2]' do
89
+ (Interval[1,3] - Interval[2,4]).should eq Interval[1,2]
90
+ end
91
+
92
+ it '[1,4]-(1,3) = [1]U[3,4]' do
93
+ (Interval[1,4] - Interval[1,3]).should eq Interval[3,4] | Interval[1]
94
+ end
95
+
96
+ it '[1,4]-(1,5) = [1]' do
97
+ (Interval[1,4] - Interval[1,5]).should eq Interval[1]
98
+ end
99
+
100
+ it '[1,3]-(2,3) = [1,2]U[3]' do
101
+ (Interval[1,3] - Interval[2,3]).should eq Interval[1,2] | Interval[3]
102
+ end
103
+
104
+ it '[1,3]-(0,3) = [3]' do
105
+ (Interval[1,3] - Interval[0,3]).should eq Interval[3]
106
+ end
107
+
108
+ it '[-infty,infty]-[0,1] = [-infty,0]U[1,infty]' do
109
+ (Interval[-Infinity,Infinity] - Interval[0,1]).should eq Interval[-Infinity,0]|Interval[1,Infinity]
110
+ end
111
+
112
+ it '[0,1]-[-infty,infty] = []' do
113
+ (Interval[0,1] - Interval[-Infinity,Infinity]).should eq Interval[]
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,30 @@
1
+ require 'borel/interval'
2
+ require 'borel/range'
3
+
4
+ describe Range do
5
+ context '#to_interval' do
6
+ it '(1..3) should be [1,3]' do
7
+ (1..3).to_interval.should eq Interval[1,3]
8
+ end
9
+
10
+ it '(1...3) should be [1,2]' do
11
+ (1...3).to_interval.should eq Interval[1,2]
12
+ end
13
+
14
+ it '(1..Infinity) should be [1,infty]' do
15
+ (1..Infinity).to_interval.should eq Interval[1,Infinity]
16
+ end
17
+
18
+ it '(1...Infinity) should raise OpenRight' do
19
+ expect{(1...Infinity).to_interval}.to raise_error Borel::OpenRight
20
+ end
21
+
22
+ it '(-Infinity..1) should be [-infty,1]' do
23
+ (-Infinity..1).to_interval.should eq Interval[-Infinity,1]
24
+ end
25
+
26
+ it '(-Infinity..Infinity) should be [-infty,infty]' do
27
+ (-Infinity..Infinity).to_interval.should eq Interval[-Infinity,Infinity]
28
+ end
29
+ end
30
+ end
data/tasks/gem.rb ADDED
@@ -0,0 +1,28 @@
1
+ gemspec = eval(File.read("borel.gemspec"))
2
+
3
+ desc "Validate the gemspec"
4
+ task :gemspec do
5
+ gemspec.validate
6
+ end
7
+
8
+ desc "Build gem locally"
9
+ task :build => :gemspec do
10
+ system "gem build #{gemspec.name}.gemspec"
11
+ FileUtils.mkdir_p "pkg"
12
+ FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", "pkg"
13
+ end
14
+
15
+ desc "Install gem locally"
16
+ task :install => :build do
17
+ system "gem install pkg/#{gemspec.name}-#{gemspec.version}"
18
+ end
19
+
20
+ desc "Launches interactive console with borel"
21
+ task :console => :install do
22
+ system "irb -r #{gemspec.name}"
23
+ end
24
+
25
+ desc "Clean automatically generated files"
26
+ task :clean do
27
+ FileUtils.rm_rf "pkg"
28
+ end
data/tasks/rspec.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ desc "Run specifications"
4
+ RSpec::Core::RakeTask.new(:rspec)
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: borel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Amadeus Folego
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-12 00:00:00.000000000 Z
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.
16
+ email:
17
+ - amadeusfolego@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - .rspec
24
+ - MIT-LICENSE
25
+ - README.md
26
+ - Rakefile
27
+ - borel.gemspec
28
+ - lib/borel.rb
29
+ - lib/borel/interval.rb
30
+ - lib/borel/numeric.rb
31
+ - lib/borel/range.rb
32
+ - lib/borel/version.rb
33
+ - spec/interval_spec.rb
34
+ - spec/range_spec.rb
35
+ - tasks/gem.rb
36
+ - tasks/rspec.rb
37
+ homepage: http://github.com/amadeusfolego/borel
38
+ licenses: []
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: 1.9.3
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.3.6
55
+ requirements: []
56
+ rubyforge_project: borel
57
+ rubygems_version: 1.8.11
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: Generic ordered set's operations
61
+ test_files: []