rsl 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/CHANGELOG +6 -0
- data/README +11 -0
- data/Rakefile +198 -0
- data/lib/rsl/base.rb +3 -0
- data/lib/rsl/least_squares_fit.rb +43 -0
- data/lib/rsl.rb +2 -0
- data/test/least_squares_test.rb +63 -0
- metadata +52 -0
data/CHANGELOG
ADDED
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,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,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
|
+
|