rsl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,6 @@
1
+ CHANGELOG
2
+
3
+ == 0.0.1
4
+
5
+ * Initial release.
6
+ * Simple least squares fit
data/README ADDED
@@ -0,0 +1,11 @@
1
+ == Ruby Scientific Library
2
+
3
+ Native Ruby scientific/numeric programs, available for use in any application.
4
+
5
+ For more information see http://www.sbrew.com/rsl
6
+
7
+ RSL is distributed under the Ruby License.
8
+
9
+ == WARNING
10
+
11
+ This is alpha-quality software. It is still very young.
data/Rakefile ADDED
@@ -0,0 +1,198 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/contrib/rubyforgepublisher'
8
+
9
+ $:.unshift(File.dirname(__FILE__) + "/lib")
10
+ require 'rsl'
11
+
12
+ PKG_NAME = 'rsl'
13
+ PKG_VERSION = Rsl::VERSION
14
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
15
+
16
+ RELEASE_NAME = "REL #{PKG_VERSION}"
17
+
18
+ RUBY_FORGE_PROJECT = "rsl"
19
+ RUBY_FORGE_USER = "timbreitkreutz"
20
+
21
+ desc "Default Task"
22
+ task :default => [ :clean, :test ]
23
+
24
+ desc "Clean images generated by tests"
25
+ task :clean do
26
+ rm FileList['test/output/*.png']
27
+ rm_rf 'pkg'
28
+ rm_rf 'doc'
29
+ end
30
+
31
+ # Run the unit tests
32
+ Rake::TestTask.new { |t|
33
+ t.libs << "test"
34
+ t.pattern = 'test/*_test.rb'
35
+ t.verbose = true
36
+ }
37
+
38
+
39
+ # Genereate the RDoc documentation
40
+ Rake::RDocTask.new { |rdoc|
41
+ rdoc.rdoc_dir = 'doc'
42
+ rdoc.title = "RSL -- Ruby Scientific Library"
43
+ # rdoc.options << '--line-numbers --inline-source --main README --accessor adv_attr_accessor=M'
44
+ rdoc.template = "#{ENV['template']}.rb" if ENV['template']
45
+ rdoc.rdoc_files.include('README', 'CHANGELOG')
46
+ rdoc.rdoc_files.include('lib/rsl.rb')
47
+ rdoc.rdoc_files.include('lib/rsl/*.rb')
48
+ }
49
+
50
+
51
+ # Create compressed packages
52
+ spec = Gem::Specification.new do |s|
53
+ s.platform = Gem::Platform::RUBY
54
+ s.name = PKG_NAME
55
+ s.summary = "A native Ruby Scientific/Numerical library."
56
+ s.description = %q{Find and contribute numeric/scientific programs in native Ruby.}
57
+ s.version = PKG_VERSION
58
+
59
+ s.author = "Tim Breitkreutz"
60
+ s.email = "tim@sbrew.com"
61
+ s.rubyforge_project = RUBY_FORGE_PROJECT
62
+ s.homepage = "http://www.sbrew.com/rsl"
63
+
64
+ s.has_rdoc = true
65
+ s.requirements << 'none'
66
+ s.require_path = 'lib'
67
+ s.autorequire = 'rsl'
68
+
69
+ s.files = [ "Rakefile", "README", "CHANGELOG" ]
70
+ s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
71
+ s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
72
+ end
73
+
74
+ Rake::GemPackageTask.new(spec) do |p|
75
+ p.gem_spec = spec
76
+ p.need_tar = true
77
+ p.need_zip = true
78
+ end
79
+
80
+ desc "Publish the API documentation"
81
+ task :pgem => [:package] do
82
+ Rake::SshFilePublisher.new("tim@sbrew.com", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
83
+ end
84
+
85
+ desc "Publish the release files to RubyForge."
86
+ task :release => [:package] do
87
+ files = ["gem", "tgz", "zip"].map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
88
+
89
+ if RUBY_FORGE_PROJECT then
90
+ require 'net/http'
91
+ require 'open-uri'
92
+
93
+ project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
94
+ project_data = open(project_uri) { |data| data.read }
95
+ group_id = project_data[/[?&]group_id=(\d+)/, 1]
96
+ raise "Couldn't get group id" unless group_id
97
+
98
+ # This echos password to shell which is a bit sucky
99
+ if ENV["RUBY_FORGE_PASSWORD"]
100
+ password = ENV["RUBY_FORGE_PASSWORD"]
101
+ else
102
+ print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
103
+ password = STDIN.gets.chomp
104
+ end
105
+
106
+ login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
107
+ data = [
108
+ "login=1",
109
+ "form_loginname=#{RUBY_FORGE_USER}",
110
+ "form_pw=#{password}"
111
+ ].join("&")
112
+ http.post("/account/login.php", data)
113
+ end
114
+
115
+ cookie = login_response["set-cookie"]
116
+ raise "Login failed" unless cookie
117
+ headers = { "Cookie" => cookie }
118
+
119
+ release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
120
+ release_data = open(release_uri, headers) { |data| data.read }
121
+ package_id = release_data[/[?&]package_id=(\d+)/, 1]
122
+ raise "Couldn't get package id" unless package_id
123
+
124
+ first_file = true
125
+ release_id = ""
126
+
127
+ files.each do |filename|
128
+ basename = File.basename(filename)
129
+ file_ext = File.extname(filename)
130
+ file_data = File.open(filename, "rb") { |file| file.read }
131
+
132
+ puts "Releasing #{basename}..."
133
+
134
+ release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
135
+ release_date = Time.now.strftime("%Y-%m-%d %H:%M")
136
+ type_map = {
137
+ ".zip" => "3000",
138
+ ".tgz" => "3110",
139
+ ".gz" => "3110",
140
+ ".gem" => "1400"
141
+ }; type_map.default = "9999"
142
+ type = type_map[file_ext]
143
+ boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
144
+
145
+ query_hash = if first_file then
146
+ {
147
+ "group_id" => group_id,
148
+ "package_id" => package_id,
149
+ "release_name" => RELEASE_NAME,
150
+ "release_date" => release_date,
151
+ "type_id" => type,
152
+ "processor_id" => "8000", # Any
153
+ "release_notes" => "",
154
+ "release_changes" => "",
155
+ "preformatted" => "1",
156
+ "submit" => "1"
157
+ }
158
+ else
159
+ {
160
+ "group_id" => group_id,
161
+ "release_id" => release_id,
162
+ "package_id" => package_id,
163
+ "step2" => "1",
164
+ "type_id" => type,
165
+ "processor_id" => "8000", # Any
166
+ "submit" => "Add This File"
167
+ }
168
+ end
169
+
170
+ query = "?" + query_hash.map do |(name, value)|
171
+ [name, URI.encode(value)].join("=")
172
+ end.join("&")
173
+
174
+ data = [
175
+ "--" + boundary,
176
+ "Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
177
+ "Content-Type: application/octet-stream",
178
+ "Content-Transfer-Encoding: binary",
179
+ "", file_data, ""
180
+ ].join("\x0D\x0A")
181
+
182
+ release_headers = headers.merge(
183
+ "Content-Type" => "multipart/form-data; boundary=#{boundary}"
184
+ )
185
+
186
+ target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
187
+ http.post(target + query, data, release_headers)
188
+ end
189
+
190
+ if first_file then
191
+ release_id = release_response.body[/release_id=(\d+)/, 1]
192
+ raise("Couldn't get release id") unless release_id
193
+ end
194
+
195
+ first_file = false
196
+ end
197
+ end
198
+ end
data/lib/rsl/base.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Rsl
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,43 @@
1
+
2
+
3
+ module Rsl
4
+ # Linear fit--least squares regression
5
+ # Fits the data in xes and ys to Y = b + a X
6
+ # returns (a, b)
7
+ def Rsl.least_squares_fit( xes, ys )
8
+ raise "input vectors must not be nil" if xes == nil || ys == nil
9
+ raise "input vectors must be larger" if xes.size < 3 || ys.size < 3
10
+ raise "input vectors must be of equal size" if xes.size != ys.size
11
+
12
+ run_x = 0.0
13
+ run_y = 0.0
14
+
15
+ count = 1.0
16
+
17
+ xes.to_a.each { |x|
18
+ raise "X vector contains a nil" if x == nil
19
+ run_x += ( x - run_x ) / count
20
+ count += 1.0
21
+ }
22
+ count = 1.0
23
+ ys.to_a.each { |y|
24
+ raise "Y vector contains a nil" if y == nil
25
+ run_y += ( ( y ) - run_y ) / count
26
+ count += 1.0
27
+ }
28
+
29
+ dx2, dxdy = 0.0, 0.0
30
+
31
+ (1..xes.size).each do |count|
32
+ dx = xes[count-1] - run_x
33
+ dy = ( ys[count-1] ) - run_y
34
+ dx2 += ( dx * dx - dx2 ) / count.to_f
35
+ dxdy += ( dx * dy - dxdy ) / count.to_f
36
+ end
37
+
38
+ b = dxdy / dx2 if dx2 != 0.0
39
+ a = run_y - run_x * b
40
+
41
+ return a, b
42
+ end
43
+ end
data/lib/rsl.rb ADDED
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + '/rsl/base'
2
+ require File.dirname(__FILE__) + '/rsl/least_squares_fit'
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'rsl'
5
+ require 'matrix'
6
+ require 'mathn'
7
+
8
+ class LinearFitTest < Test::Unit::TestCase
9
+
10
+ def test_fit
11
+ a, b = Rsl.least_squares_fit([1, 2, 3], [10, 11, 12 ])
12
+ assert_equal(sprintf("%.2f", a), "9.00")
13
+ assert_equal(sprintf("%.2f", b), "1.00")
14
+
15
+ a, b = Rsl.least_squares_fit([1, 2, 3], [10, 10.5, 12 ])
16
+ assert_equal(sprintf("%.2f", a), "8.83")
17
+ assert_equal(sprintf("%.2f", b), "1.00")
18
+
19
+ a, b = Rsl.least_squares_fit([1, 2, 3, 8, 11, 22], [10, 10.5, 12, 12.55, 13.55, 15.01 ])
20
+ assert_equal(sprintf("%.2f", a), "10.53")
21
+ assert_equal(sprintf("%.2f", b), "0.22")
22
+
23
+ # Some simple boundaries, zeros and negative inputs
24
+
25
+ a, b = Rsl.least_squares_fit([1, 0, 3, 8, 11, 22], [10, 10.5, 12, 12.55, 13.55, 15.01 ])
26
+ assert_equal(sprintf("%.2f", a), "10.65")
27
+ assert_equal(sprintf("%.2f", b), "0.22")
28
+
29
+ a, b = Rsl.least_squares_fit([1, 8, 3, 8, 11, 22], [10, 0, 12, 12.55, 13.55, 15.01 ])
30
+ assert_equal(sprintf("%.2f", a), "8.33")
31
+ assert_equal(sprintf("%.2f", b), "0.25")
32
+
33
+ a, b = Rsl.least_squares_fit([-100, 8, 3, 8, 11, 22], [10, 0, -12, 12.55, 13.55, 15.01 ])
34
+ assert_equal(sprintf("%.2f", a), "6.41")
35
+ assert_equal(sprintf("%.2f", b), "-0.01")
36
+ end
37
+
38
+ def test_nil_vector
39
+ assert_raise(RuntimeError) { a, b = Rsl.least_squares_fit(nil, nil) }
40
+ end
41
+
42
+ def test_nil_member
43
+ assert_raise(RuntimeError) { a, b = Rsl.least_squares_fit([nil, 1, 2, 3], [2, 3, 4, 5]) }
44
+ end
45
+
46
+ def test_wrong_length
47
+ assert_raise(RuntimeError) { a, b = Rsl.least_squares_fit([9, 1, 2, 3], [2, 3, 4, 5, 5]) }
48
+ end
49
+
50
+ def test_too_short
51
+ assert_raise(RuntimeError) { a, b = Rsl.least_squares_fit([9], [2]) }
52
+ assert_raise(RuntimeError) { a, b = Rsl.least_squares_fit([nil], [nil]) }
53
+ assert_raise(RuntimeError) { a, b = Rsl.least_squares_fit([2,2], [3,3]) }
54
+ end
55
+
56
+ def test_vectors
57
+ x = Vector[1, 2, 3]
58
+ y = Vector[10, 11, 12]
59
+ a, b = Rsl.least_squares_fit(x, y)
60
+ assert_equal(sprintf("%.2f", a), "9.00")
61
+ assert_equal(sprintf("%.2f", b), "1.00")
62
+ end
63
+ end
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: rsl
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2006-03-30 00:00:00 -07:00
8
+ summary: A native Ruby Scientific/Numerical library.
9
+ require_paths:
10
+ - lib
11
+ email: tim@sbrew.com
12
+ homepage: http://www.sbrew.com/rsl
13
+ rubyforge_project: rsl
14
+ description: Find and contribute numeric/scientific programs in native Ruby.
15
+ autorequire: rsl
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ authors:
29
+ - Tim Breitkreutz
30
+ files:
31
+ - Rakefile
32
+ - README
33
+ - CHANGELOG
34
+ - lib/rsl
35
+ - lib/rsl.rb
36
+ - lib/rsl/base.rb
37
+ - lib/rsl/least_squares_fit.rb
38
+ - test/least_squares_test.rb
39
+ test_files: []
40
+
41
+ rdoc_options: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ executables: []
46
+
47
+ extensions: []
48
+
49
+ requirements:
50
+ - none
51
+ dependencies: []
52
+