pretty_gsl 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/Gemfile +4 -0
- data/LICENCE +22 -0
- data/README.md +35 -0
- data/Rakefile +12 -0
- data/examples/ruby_gsl_example.rb +49 -0
- data/lib/pretty_gsl/minimizer.rb +78 -0
- data/lib/pretty_gsl/version.rb +3 -0
- data/lib/pretty_gsl.rb +4 -0
- data/pretty_gsl.gemspec +19 -0
- data/test/minimizer_test.rb +35 -0
- data/test/test_helper.rb +2 -0
- metadata +74 -0
data/Gemfile
ADDED
data/LICENCE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Ben Doyle
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# PrettyGLS
|
2
|
+
|
3
|
+
This gem provides a nice interface to the GNU scientific library through the Ruby/GSL wrapper. I've simply attempted to update the interface to use more idiomatic ruby.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'pretty_gsl'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install pretty_gsl
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
function = Proc.new{ |variables, constants| ...}
|
22
|
+
optional_gradient = Proc.new{ |variables, constants, gradient_components| ...}
|
23
|
+
constants = [1,2,3, ...]
|
24
|
+
guess = [1,2,3, ...]
|
25
|
+
m = Minimizer.new(function, constants, function_gradient: optional_gradient)
|
26
|
+
m.minimize(*guess)
|
27
|
+
=> {:success=>true, :minimum_x=>[1, 2], :iterations=>50, :minimum_f=>30.0, :simplex_size=>0.0008 ... }
|
28
|
+
|
29
|
+
## Contributing
|
30
|
+
|
31
|
+
1. Fork it
|
32
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
33
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
34
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
35
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# RUBY
|
2
|
+
# ruby 1.9.2p320 (2012-04-20 revision 35421) [x86_64-darwin11.3.0]
|
3
|
+
|
4
|
+
# GEM
|
5
|
+
# gsl (1.14.7)
|
6
|
+
|
7
|
+
# LIB
|
8
|
+
# gsl-1.15
|
9
|
+
|
10
|
+
|
11
|
+
require 'gsl'
|
12
|
+
include GSL
|
13
|
+
include GSL::MultiMin
|
14
|
+
|
15
|
+
my_f = Proc.new do |v, params|
|
16
|
+
x = v[0]
|
17
|
+
y = v[1]
|
18
|
+
p0 = params[0]
|
19
|
+
p1 = params[1]
|
20
|
+
10.0 * (x - p0) * (x - p0) + 20.0 * (y - p1) * (y - p1) + 30.0
|
21
|
+
end
|
22
|
+
|
23
|
+
my_df = Proc.new do |v, params, df|
|
24
|
+
x = v[0]
|
25
|
+
y = v[1]
|
26
|
+
p0 = params[0]
|
27
|
+
p1 = params[1]
|
28
|
+
df[0] = 20.0*(x-p0)
|
29
|
+
df[1] = 40.0*(y-p1)
|
30
|
+
end
|
31
|
+
|
32
|
+
my_func = Function_fdf.alloc(my_f, my_df, 2)
|
33
|
+
my_func.set_params([1.0, 2.0]) # parameters
|
34
|
+
|
35
|
+
x = Vector.alloc(5.0, 7.0) # starting point
|
36
|
+
|
37
|
+
minimizer = FdfMinimizer.alloc("conjugate_fr", 2)
|
38
|
+
minimizer.set(my_func, x, 0.01, 1e-4)
|
39
|
+
|
40
|
+
iter = 0
|
41
|
+
begin
|
42
|
+
iter += 1
|
43
|
+
status = minimizer.iterate()
|
44
|
+
status = minimizer.test_gradient(1e-3)
|
45
|
+
puts("Minimum found at") if status == GSL::SUCCESS
|
46
|
+
x = minimizer.x
|
47
|
+
f = minimizer.f
|
48
|
+
printf("%5d %.5f %.5f %10.5f\n", iter, x[0], x[1], f)
|
49
|
+
end while status == GSL::CONTINUE and iter < 100
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module PrettyGSL
|
2
|
+
class Minimizer
|
3
|
+
include GSL
|
4
|
+
include GSL::MultiMin
|
5
|
+
|
6
|
+
attr_reader :result
|
7
|
+
|
8
|
+
def initialize(function, constants, options = {})
|
9
|
+
@function = function
|
10
|
+
@constants = constants
|
11
|
+
@params = {
|
12
|
+
max_iterations: 100, # the maximum number of iterations to carry out the minimization
|
13
|
+
step_size: 0.01, # initial guess of the length scale of the minimiztion steps
|
14
|
+
direction_tolerance: 1e-4, # the tolerance for errors in the direction of line minimization
|
15
|
+
absolute_gradient_tolerance: 1e-3, # halt if the magnetude of the gradient falls below this value
|
16
|
+
}.merge(options)
|
17
|
+
@result = nil
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def minimize(*guess)
|
22
|
+
minimizer = get_gsl_minimizer(guess)
|
23
|
+
@params[:max_iterations].times do |iter|
|
24
|
+
status = minimizer.iterate
|
25
|
+
status = test_gsl_convergence(minimizer)
|
26
|
+
if status != CONTINUE
|
27
|
+
@result = {
|
28
|
+
success: status == SUCCESS,
|
29
|
+
minimum_x: minimizer.x.to_a,
|
30
|
+
iterations: iter
|
31
|
+
}.merge(get_gsl_result(minimizer))
|
32
|
+
break
|
33
|
+
end
|
34
|
+
end
|
35
|
+
@result
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
def test_gsl_convergence(minimizer)
|
40
|
+
if @params[:function_gradient]
|
41
|
+
minimizer.test_gradient @params[:absolute_gradient_tolerance]
|
42
|
+
else
|
43
|
+
minimizer.test_size @params[:absolute_gradient_tolerance]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_gsl_minimizer(guess)
|
48
|
+
minimizer = nil
|
49
|
+
if @params[:function_gradient]
|
50
|
+
function = Function_fdf.alloc(@function, @params[:function_gradient], guess.size)
|
51
|
+
function.set_params(@constants)
|
52
|
+
minimizer = FdfMinimizer.alloc("conjugate_fr", guess.size)
|
53
|
+
minimizer.set(function, Vector.alloc(*guess), @params[:step_size], @params[:direction_tolerance])
|
54
|
+
else
|
55
|
+
function = Function.alloc(@function, guess.size)
|
56
|
+
function.set_params(@constants)
|
57
|
+
minimizer = FMinimizer.alloc("nmsimplex", guess.size)
|
58
|
+
ss = Vector.alloc(guess.size)
|
59
|
+
ss.set_all(@params[:step_size])
|
60
|
+
minimizer.set(function, Vector.alloc(*guess), ss)
|
61
|
+
end
|
62
|
+
minimizer
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_gsl_result(minimizer)
|
66
|
+
if @params[:function_gradient]
|
67
|
+
{
|
68
|
+
minimum_f: minimizer.f,
|
69
|
+
}
|
70
|
+
else
|
71
|
+
{
|
72
|
+
minimum_f: minimizer.fval,
|
73
|
+
simplex_size: minimizer.size,
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/pretty_gsl.rb
ADDED
data/pretty_gsl.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/pretty_gsl/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Ben Doyle"]
|
6
|
+
gem.email = ["doyle.ben@gmail.com"]
|
7
|
+
gem.description = "prettify ruby/gsl with more idiomatic ruby"
|
8
|
+
gem.summary = "GSL wrapper wrapper"
|
9
|
+
gem.homepage = "https://github.com/BenDoyle/pretty_gsl"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "pretty_gsl"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = PrettyGSL::VERSION
|
17
|
+
|
18
|
+
gem.add_runtime_dependency "gsl"
|
19
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class MinimizerTest < Test::Unit::TestCase
|
4
|
+
include PrettyGSL
|
5
|
+
def setup
|
6
|
+
@function = Proc.new do |variables, constants|
|
7
|
+
x = variables[0]
|
8
|
+
y = variables[1]
|
9
|
+
p0 = constants[0]
|
10
|
+
p1 = constants[1]
|
11
|
+
10.0 * (x - p0) * (x - p0) + 20.0 * (y - p1) * (y - p1) + 30.0
|
12
|
+
end
|
13
|
+
|
14
|
+
@function_gradient = Proc.new do |variables, constants, gradient_components|
|
15
|
+
x = variables[0]
|
16
|
+
y = variables[1]
|
17
|
+
p0 = constants[0]
|
18
|
+
p1 = constants[1]
|
19
|
+
gradient_components[0] = 20.0*(x-p0)
|
20
|
+
gradient_components[1] = 40.0*(y-p1)
|
21
|
+
end
|
22
|
+
|
23
|
+
@constants = [1.0, 2.0]
|
24
|
+
@guess = [5.0, 7.0]
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_with_gradient
|
28
|
+
assert_not_nil Minimizer.new(@function, @constants, function_gradient: @function_gradient).minimize(*@guess)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_without_gradient
|
32
|
+
assert_not_nil Minimizer.new(@function, @constants).minimize(*@guess)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pretty_gsl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ben Doyle
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: gsl
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: prettify ruby/gsl with more idiomatic ruby
|
31
|
+
email:
|
32
|
+
- doyle.ben@gmail.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- Gemfile
|
38
|
+
- LICENCE
|
39
|
+
- README.md
|
40
|
+
- Rakefile
|
41
|
+
- examples/ruby_gsl_example.rb
|
42
|
+
- lib/pretty_gsl.rb
|
43
|
+
- lib/pretty_gsl/minimizer.rb
|
44
|
+
- lib/pretty_gsl/version.rb
|
45
|
+
- pretty_gsl.gemspec
|
46
|
+
- test/minimizer_test.rb
|
47
|
+
- test/test_helper.rb
|
48
|
+
homepage: https://github.com/BenDoyle/pretty_gsl
|
49
|
+
licenses: []
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
requirements: []
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.8.23
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: GSL wrapper wrapper
|
72
|
+
test_files:
|
73
|
+
- test/minimizer_test.rb
|
74
|
+
- test/test_helper.rb
|