mopti 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +13 -16
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +1 -1
- data/README.md +3 -3
- data/Steepfile +20 -0
- data/lib/mopti/nelder_mead.rb +17 -17
- data/lib/mopti/scaled_conjugate_gradient.rb +27 -24
- data/lib/mopti/version.rb +1 -1
- data/sig/mopti.rbs +5 -0
- data/sig/mopti/nelder_mead.rbs +21 -0
- data/sig/mopti/scaled_conjugate_gradient.rbs +24 -0
- data/sig/patch.rbs +20 -0
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9e81da580fe5dd2be2958e34bee75fe5c82bb29240edf43bb7d01c89522f863
|
4
|
+
data.tar.gz: 43648573d898ae4fdbce70ce84b6f6dbcfd5109ea95eb743e9fb51fc2101251b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2de393870f138bfeba855c7d1c95d8263e85a30e0e9fb4a3a65ae6614784531865b32cafc0761ab856331dc66b9f19df4a00c8bfff3ff69eb07a9b850902c718
|
7
|
+
data.tar.gz: a71eead28cac1eb28e4b3154fabd846d11468ae803f5e7cbe5e4cb04faed18d1a468793131e465b282504b71bde2ae03db114fa245f08a8b9d0be99b3f3cbfcf
|
data/.github/workflows/build.yml
CHANGED
@@ -1,24 +1,21 @@
|
|
1
|
-
name:
|
1
|
+
name: build
|
2
2
|
|
3
|
-
on: [push]
|
3
|
+
on: [push, pull_request]
|
4
4
|
|
5
5
|
jobs:
|
6
6
|
build:
|
7
|
-
|
8
7
|
runs-on: ubuntu-latest
|
9
|
-
|
10
8
|
strategy:
|
11
9
|
matrix:
|
12
|
-
ruby: ['2.
|
13
|
-
|
10
|
+
ruby: [ '2.6', '2.7', '3.0' ]
|
14
11
|
steps:
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
12
|
+
- uses: actions/checkout@v2
|
13
|
+
- name: Set up Ruby
|
14
|
+
uses: actions/setup-ruby@v1
|
15
|
+
with:
|
16
|
+
ruby-version: ${{ matrix.ruby }}
|
17
|
+
- name: Build and test with Rake
|
18
|
+
run: |
|
19
|
+
gem install bundler
|
20
|
+
bundle install --jobs 4 --retry 3
|
21
|
+
bundle exec rake
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|

|
4
4
|
[](https://badge.fury.io/rb/mopti)
|
5
|
-
[](https://github.com/yoshoku/mopti/blob/
|
5
|
+
[](https://github.com/yoshoku/mopti/blob/main/LICENSE.txt)
|
6
6
|
[](https://yoshoku.github.io/mopti/doc/)
|
7
7
|
|
8
8
|
Mopti is a multivariate optimization library in Ruby.
|
@@ -89,9 +89,9 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
89
89
|
|
90
90
|
## Contributing
|
91
91
|
|
92
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/yoshoku/mopti. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/yoshoku/mopti/blob/
|
92
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/yoshoku/mopti. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/yoshoku/mopti/blob/main/CODE_OF_CONDUCT.md).
|
93
93
|
|
94
94
|
|
95
95
|
## Code of Conduct
|
96
96
|
|
97
|
-
Everyone interacting in the Mopti project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/yoshoku/mopti/blob/
|
97
|
+
Everyone interacting in the Mopti project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/yoshoku/mopti/blob/main/CODE_OF_CONDUCT.md).
|
data/Steepfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
target :lib do
|
2
|
+
signature "sig"
|
3
|
+
|
4
|
+
check "lib" # Directory name
|
5
|
+
# check "Gemfile" # File name
|
6
|
+
# check "app/models/**/*.rb" # Glob
|
7
|
+
# # ignore "lib/templates/*.rb"
|
8
|
+
#
|
9
|
+
# # library "pathname", "set" # Standard libraries
|
10
|
+
# library "numo-narray" # Gems
|
11
|
+
end
|
12
|
+
|
13
|
+
# target :spec do
|
14
|
+
# signature "sig", "sig-private"
|
15
|
+
#
|
16
|
+
# check "spec"
|
17
|
+
#
|
18
|
+
# # library "pathname", "set" # Standard libraries
|
19
|
+
# # library "rspec"
|
20
|
+
# end
|
data/lib/mopti/nelder_mead.rb
CHANGED
@@ -25,7 +25,7 @@ module Mopti
|
|
25
25
|
# # :fnc=>5.694864987422661e-13}
|
26
26
|
#
|
27
27
|
# *Reference*
|
28
|
-
# 1. F.
|
28
|
+
# 1. Gao, F. and Han, L., "Implementing the Nelder-Mead simplex algorithm with adaptive parameters," Computational Optimization and Applications, vol. 51 (1), pp. 259--277, 2012.
|
29
29
|
class NelderMead
|
30
30
|
include Enumerable
|
31
31
|
|
@@ -38,7 +38,7 @@ module Mopti
|
|
38
38
|
# If nil is given, max_iter sets to 200 * number of dimensions.
|
39
39
|
# @param xtol [Float] Tolerance for termination for the optimal vector norm.
|
40
40
|
# @param ftol [Float] Tolerance for termination for the objective function value.
|
41
|
-
def initialize(fnc:, args: nil,
|
41
|
+
def initialize(fnc:, x_init:, args: nil, max_iter: nil, xtol: 1e-6, ftol: 1e-6)
|
42
42
|
@fnc = fnc
|
43
43
|
@args = args
|
44
44
|
@x_init = x_init
|
@@ -72,13 +72,13 @@ module Mopti
|
|
72
72
|
sim[0, true] = x
|
73
73
|
n.times do |k|
|
74
74
|
y = x.dup
|
75
|
-
y[k] = y[k]
|
75
|
+
y[k] = (y[k]).zero? ? ZERO_TAU : (1 + NON_ZERO_TAU) * y[k]
|
76
76
|
sim[k + 1, true] = y
|
77
77
|
end
|
78
78
|
|
79
79
|
fsim = Numo::DFloat.zeros(n + 1)
|
80
80
|
|
81
|
-
(n + 1).times { |k| fsim[k] = func(sim[k, true]) }
|
81
|
+
(n + 1).times { |k| fsim[k] = func(sim[k, true], @args) }
|
82
82
|
n_fev = n + 1
|
83
83
|
|
84
84
|
ind = fsim.sort_index
|
@@ -91,13 +91,13 @@ module Mopti
|
|
91
91
|
|
92
92
|
xbar = sim[0...-1, true].sum(0) / n
|
93
93
|
xr = xbar + alpha * (xbar - sim[-1, true])
|
94
|
-
fr = func(xr)
|
94
|
+
fr = func(xr, @args)
|
95
95
|
n_fev += 1
|
96
96
|
|
97
97
|
shrink = true
|
98
98
|
if fr < fsim[0]
|
99
99
|
xe = xbar + beta * (xr - xbar)
|
100
|
-
fe = func(xe)
|
100
|
+
fe = func(xe, @args)
|
101
101
|
n_fev += 1
|
102
102
|
shrink = false
|
103
103
|
if fe < fr
|
@@ -113,7 +113,7 @@ module Mopti
|
|
113
113
|
fsim[-1] = fr
|
114
114
|
elsif fr < fsim[-1]
|
115
115
|
xoc = xbar + gamma * (xr - xbar)
|
116
|
-
foc = func(xoc)
|
116
|
+
foc = func(xoc, @args)
|
117
117
|
n_fev += 1
|
118
118
|
if foc <= fr
|
119
119
|
shrink = false
|
@@ -122,7 +122,7 @@ module Mopti
|
|
122
122
|
end
|
123
123
|
else
|
124
124
|
xic = xbar - gamma * (xr - xbar)
|
125
|
-
fic = func(xic)
|
125
|
+
fic = func(xic, @args)
|
126
126
|
n_fev += 1
|
127
127
|
if fic < fsim[-1]
|
128
128
|
shrink = false
|
@@ -132,9 +132,9 @@ module Mopti
|
|
132
132
|
end
|
133
133
|
|
134
134
|
if shrink
|
135
|
-
(1..n).
|
135
|
+
(1..n).to_a.each do |j|
|
136
136
|
sim[j, true] = sim[0, true] + delta * (sim[j, true] - sim[0, true])
|
137
|
-
fsim[j] = func(sim[j, true])
|
137
|
+
fsim[j] = func(sim[j, true], @args)
|
138
138
|
n_fev += 1
|
139
139
|
end
|
140
140
|
end
|
@@ -156,15 +156,15 @@ module Mopti
|
|
156
156
|
|
157
157
|
private
|
158
158
|
|
159
|
-
def func(x)
|
160
|
-
if
|
161
|
-
@fnc.call(x,
|
162
|
-
elsif
|
163
|
-
@fnc.call(x,
|
164
|
-
elsif
|
159
|
+
def func(x, args)
|
160
|
+
if args.is_a?(Hash)
|
161
|
+
@fnc.call(x, **args)
|
162
|
+
elsif args.is_a?(Array)
|
163
|
+
@fnc.call(x, *args)
|
164
|
+
elsif args.nil?
|
165
165
|
@fnc.call(x)
|
166
166
|
else
|
167
|
-
@fnc.call(x,
|
167
|
+
@fnc.call(x, args)
|
168
168
|
end
|
169
169
|
end
|
170
170
|
end
|
@@ -42,7 +42,7 @@ module Mopti
|
|
42
42
|
# # :jcb=>1.8698188678645777e-07}
|
43
43
|
#
|
44
44
|
# *Reference*
|
45
|
-
# 1. M F
|
45
|
+
# 1. Moller, M F., "A Scaled Conjugate Gradient Algorithm for Fast Supervised Learning," Neural Networks, Vol. 6, pp. 525--533, 1993.
|
46
46
|
class ScaledConjugateGradient
|
47
47
|
include Enumerable
|
48
48
|
|
@@ -56,7 +56,7 @@ module Mopti
|
|
56
56
|
# @param xtol [Float] Tolerance for termination for the optimal vector norm.
|
57
57
|
# @param ftol [Float] Tolerance for termination for the objective function value.
|
58
58
|
# @param jtol [Float] Tolerance for termination for the gradient norm.
|
59
|
-
def initialize(fnc:, jcb:, args: nil,
|
59
|
+
def initialize(fnc:, jcb:, x_init:, args: nil, max_iter: 200, xtol: 1e-6, ftol: 1e-8, jtol: 1e-7)
|
60
60
|
@fnc = fnc
|
61
61
|
@jcb = jcb
|
62
62
|
@x_init = x_init
|
@@ -82,10 +82,10 @@ module Mopti
|
|
82
82
|
return to_enum(__method__) unless block_given?
|
83
83
|
|
84
84
|
x = @x_init
|
85
|
-
f_prev = func(x)
|
85
|
+
f_prev = func(x, @args)
|
86
86
|
n_fev = 1
|
87
87
|
f_curr = f_prev
|
88
|
-
j_next = jacb(x)
|
88
|
+
j_next = jacb(x, @args)
|
89
89
|
n_jev = 1
|
90
90
|
|
91
91
|
j_curr = j_next.dot(j_next)
|
@@ -109,7 +109,7 @@ module Mopti
|
|
109
109
|
|
110
110
|
sigma = SIGMA_INIT / Math.sqrt(kappa)
|
111
111
|
x_plus = x + sigma * d
|
112
|
-
j_plus = jacb(x_plus)
|
112
|
+
j_plus = jacb(x_plus, @args)
|
113
113
|
n_jev += 1
|
114
114
|
theta = d.dot(j_plus - j_next) / sigma
|
115
115
|
end
|
@@ -117,12 +117,15 @@ module Mopti
|
|
117
117
|
delta = theta + beta * kappa
|
118
118
|
if delta <= 0
|
119
119
|
delta = beta * kappa
|
120
|
-
|
120
|
+
# TODO: Investigate the cause of the type error.
|
121
|
+
# Cannot assign a value of type `::Complex` to a variable of type `::Float`
|
122
|
+
# beta -= theta / kappa
|
123
|
+
beta = (beta - (theta / kappa)).to_f
|
121
124
|
end
|
122
125
|
alpha = -mu / delta
|
123
126
|
|
124
127
|
x_next = x + alpha * d
|
125
|
-
f_next = func(x_next)
|
128
|
+
f_next = func(x_next, @args)
|
126
129
|
n_fev += 1
|
127
130
|
|
128
131
|
delta = 2 * (f_next - f_prev) / (alpha * mu)
|
@@ -146,15 +149,15 @@ module Mopti
|
|
146
149
|
f_prev = f_next
|
147
150
|
|
148
151
|
j_prev = j_next
|
149
|
-
j_next = jacb(x)
|
152
|
+
j_next = jacb(x, @args)
|
150
153
|
n_jev += 1
|
151
154
|
|
152
155
|
j_curr = j_next.dot(j_next)
|
153
156
|
break if j_curr <= @jtol
|
154
157
|
end
|
155
158
|
|
156
|
-
beta =
|
157
|
-
beta =
|
159
|
+
beta = beta * 4 < BETA_MAX ? beta * 4 : BETA_MAX if delta < 0.25
|
160
|
+
beta = beta / 4 > BETA_MIN ? beta / 4 : BETA_MIN if delta > 0.75
|
158
161
|
|
159
162
|
if n_successes == x.size
|
160
163
|
d = -j_next
|
@@ -175,27 +178,27 @@ module Mopti
|
|
175
178
|
|
176
179
|
private
|
177
180
|
|
178
|
-
def func(x)
|
179
|
-
if
|
180
|
-
@fnc.call(x,
|
181
|
-
elsif
|
182
|
-
@fnc.call(x,
|
183
|
-
elsif
|
181
|
+
def func(x, args)
|
182
|
+
if args.is_a?(Hash)
|
183
|
+
@fnc.call(x, **args)
|
184
|
+
elsif args.is_a?(Array)
|
185
|
+
@fnc.call(x, *args)
|
186
|
+
elsif args.nil?
|
184
187
|
@fnc.call(x)
|
185
188
|
else
|
186
|
-
@fnc.call(x,
|
189
|
+
@fnc.call(x, args)
|
187
190
|
end
|
188
191
|
end
|
189
192
|
|
190
|
-
def jacb(x)
|
191
|
-
if
|
192
|
-
@jcb.call(x,
|
193
|
-
elsif
|
194
|
-
@jcb.call(x,
|
195
|
-
elsif
|
193
|
+
def jacb(x, args)
|
194
|
+
if args.is_a?(Hash)
|
195
|
+
@jcb.call(x, **args)
|
196
|
+
elsif args.is_a?(Array)
|
197
|
+
@jcb.call(x, *args)
|
198
|
+
elsif args.nil?
|
196
199
|
@jcb.call(x)
|
197
200
|
else
|
198
|
-
@jcb.call(x,
|
201
|
+
@jcb.call(x, args)
|
199
202
|
end
|
200
203
|
end
|
201
204
|
end
|
data/lib/mopti/version.rb
CHANGED
data/sig/mopti.rbs
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Mopti
|
2
|
+
class NelderMead
|
3
|
+
include Enumerable[untyped]
|
4
|
+
|
5
|
+
@fnc: Method | Proc
|
6
|
+
|
7
|
+
def initialize: (fnc: Method | Proc fnc,
|
8
|
+
x_init: Numo::DFloat x_init, ?args: untyped? args, ?max_iter: Integer? max_iter,
|
9
|
+
?xtol: Float xtol, ?ftol: Float ftol) -> void
|
10
|
+
|
11
|
+
# def each: () { (x: Numo::DFloat, n_fev: Integer, n_iter: Integer, fnc: Float) -> untyped } -> untyped
|
12
|
+
def each: () { (untyped) -> untyped } -> untyped
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
NON_ZERO_TAU: Float
|
17
|
+
ZERO_TAU: Float
|
18
|
+
|
19
|
+
def func: (Numo::DFloat x, untyped args) -> Float
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Mopti
|
2
|
+
class ScaledConjugateGradient
|
3
|
+
include Enumerable[untyped]
|
4
|
+
|
5
|
+
@fnc: Method | Proc
|
6
|
+
@jcb: Method | Proc
|
7
|
+
|
8
|
+
def initialize: (fnc: Method | Proc fnc, jcb: Method | Proc jcb,
|
9
|
+
x_init: Numo::DFloat x_init, ?args: untyped? args, ?max_iter: Integer max_iter,
|
10
|
+
?xtol: Float xtol, ?ftol: Float ftol, ?jtol: Float jtol) -> void
|
11
|
+
|
12
|
+
# def each: () { (x: Numo::DFloat, n_fev: Integer, n_jev: Integer, n_iter: Integer, fnc: Float, jcb: Numo::DFloat) -> untyped } -> untyped
|
13
|
+
def each: () { (untyped) -> untyped } -> untyped
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
SIGMA_INIT: Float
|
18
|
+
BETA_MIN: Float
|
19
|
+
BETA_MAX: Float
|
20
|
+
|
21
|
+
def func: (Numo::DFloat x, untyped args) -> Float
|
22
|
+
def jacb: (Numo::DFloat x, untyped args) -> Numo::DFloat
|
23
|
+
end
|
24
|
+
end
|
data/sig/patch.rbs
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Numo
|
2
|
+
class NArray
|
3
|
+
def self.zeros: (*untyped) -> untyped
|
4
|
+
def dot: (untyped b) -> untyped
|
5
|
+
def empty?: () -> bool
|
6
|
+
def ndim: () -> Integer
|
7
|
+
def shape: () -> Array[Integer]
|
8
|
+
def swapaxes: (Integer, Integer) -> untyped
|
9
|
+
end
|
10
|
+
|
11
|
+
class DFloat < NArray
|
12
|
+
def -@: () -> untyped
|
13
|
+
def +: (untyped) -> untyped
|
14
|
+
def -: (untyped) -> untyped
|
15
|
+
def *: (untyped) -> untyped
|
16
|
+
def /: (untyped) -> untyped
|
17
|
+
def []: (*untyped) -> untyped
|
18
|
+
def []=: (*untyped) -> untyped
|
19
|
+
end
|
20
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mopti
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yoshoku
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: numo-narray
|
@@ -43,11 +43,16 @@ files:
|
|
43
43
|
- LICENSE.txt
|
44
44
|
- README.md
|
45
45
|
- Rakefile
|
46
|
+
- Steepfile
|
46
47
|
- lib/mopti.rb
|
47
48
|
- lib/mopti/nelder_mead.rb
|
48
49
|
- lib/mopti/scaled_conjugate_gradient.rb
|
49
50
|
- lib/mopti/version.rb
|
50
51
|
- mopti.gemspec
|
52
|
+
- sig/mopti.rbs
|
53
|
+
- sig/mopti/nelder_mead.rbs
|
54
|
+
- sig/mopti/scaled_conjugate_gradient.rbs
|
55
|
+
- sig/patch.rbs
|
51
56
|
homepage: https://github.com/yoshoku/mopti
|
52
57
|
licenses:
|
53
58
|
- BSD-3-Clause
|
@@ -71,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
76
|
- !ruby/object:Gem::Version
|
72
77
|
version: '0'
|
73
78
|
requirements: []
|
74
|
-
rubygems_version: 3.1.
|
79
|
+
rubygems_version: 3.1.6
|
75
80
|
signing_key:
|
76
81
|
specification_version: 4
|
77
82
|
summary: Multivariate Optimization Library in Ruby.
|