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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a94c3e3b4ecd74032308bd83bd3b018f23469b90cee573456638888c88649c72
4
- data.tar.gz: bd9c811610325eba50c2ba7659fa514ad6c84c3dd6b1ee7559999a08d6928812
3
+ metadata.gz: c9e81da580fe5dd2be2958e34bee75fe5c82bb29240edf43bb7d01c89522f863
4
+ data.tar.gz: 43648573d898ae4fdbce70ce84b6f6dbcfd5109ea95eb743e9fb51fc2101251b
5
5
  SHA512:
6
- metadata.gz: 759379528285a342e0228fa6199a1f4babf217e173b8f836b701e3faa5203af8783bf4f97e6d873a1af38d7d915f98e94c1021618d39503f505b341bb46f87b0
7
- data.tar.gz: 6f2f010305f6b217da688f7ab0b4ed7328b06e97fbc8ccd792ec9f0360448883584652474cb55d59f63ce36d6e4668a39359c58c33dcba194589d09509888352
6
+ metadata.gz: 2de393870f138bfeba855c7d1c95d8263e85a30e0e9fb4a3a65ae6614784531865b32cafc0761ab856331dc66b9f19df4a00c8bfff3ff69eb07a9b850902c718
7
+ data.tar.gz: a71eead28cac1eb28e4b3154fabd846d11468ae803f5e7cbe5e4cb04faed18d1a468793131e465b282504b71bde2ae03db114fa245f08a8b9d0be99b3f3cbfcf
@@ -1,24 +1,21 @@
1
- name: Ruby
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.4.x', '2.5.x', '2.6.x', '2.7.x']
13
-
10
+ ruby: [ '2.6', '2.7', '3.0' ]
14
11
  steps:
15
- - uses: actions/checkout@v2
16
- - name: Set up Ruby
17
- uses: actions/setup-ruby@v1
18
- with:
19
- ruby-version: ${{ matrix.ruby }}
20
- - name: Build and test with Rake
21
- run: |
22
- gem install bundler
23
- bundle install --jobs 4 --retry 3
24
- bundle exec rake
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
@@ -2,6 +2,9 @@ require:
2
2
  - rubocop-performance
3
3
  - rubocop-rspec
4
4
 
5
+ AllCops:
6
+ NewCops: enable
7
+
5
8
  Layout/LineLength:
6
9
  Max: 145
7
10
  IgnoredPatterns: ['(\A|\s)#']
data/CHANGELOG.md CHANGED
@@ -1,2 +1,7 @@
1
+ # 0.2.0
2
+ - Add type declaration files.
3
+ - Refactor some codes with type check.
4
+ - Fix some configuration files.
5
+
1
6
  # 0.1.0
2
7
  - First release.
data/Gemfile CHANGED
@@ -5,3 +5,5 @@ gemspec
5
5
 
6
6
  gem "rake", "~> 12.0"
7
7
  gem "rspec", "~> 3.0"
8
+ gem "rbs", "~> 1.2"
9
+ gem "steep", "~> 0.44"
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2020 Atsushi Tatsuma
1
+ Copyright (c) 2020-2021 Atsushi Tatsuma
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![Ruby](https://github.com/yoshoku/mopti/workflows/Ruby/badge.svg)
4
4
  [![Gem Version](https://badge.fury.io/rb/mopti.svg)](https://badge.fury.io/rb/mopti)
5
- [![BSD 3-Clause License](https://img.shields.io/badge/License-BSD%203--Clause-orange.svg)](https://github.com/yoshoku/mopti/blob/master/LICENSE.txt)
5
+ [![BSD 3-Clause License](https://img.shields.io/badge/License-BSD%203--Clause-orange.svg)](https://github.com/yoshoku/mopti/blob/main/LICENSE.txt)
6
6
  [![Documentation](http://img.shields.io/badge/api-reference-blue.svg)](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/master/CODE_OF_CONDUCT.md).
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/master/CODE_OF_CONDUCT.md).
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
@@ -25,7 +25,7 @@ module Mopti
25
25
  # # :fnc=>5.694864987422661e-13}
26
26
  #
27
27
  # *Reference*
28
- # 1. F. Gao and L. Han, "Implementing the Nelder-Mead simplex algorithm with adaptive parameters," Computational Optimization and Applications, vol. 51 (1), pp. 259--277, 2012.
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, x_init:, max_iter: nil, xtol: 1e-6, ftol: 1e-6)
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] != 0 ? (1 + NON_ZERO_TAU) * y[k] : ZERO_TAU
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).times do |j|
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 @args.is_a?(Hash)
161
- @fnc.call(x, **@args)
162
- elsif @args.is_a?(Array)
163
- @fnc.call(x, *@args)
164
- elsif @args.nil?
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, @args)
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. Moller, "A Scaled Conjugate Gradient Algorithm for Fast Supervised Learning," Neural Networks, Vol. 6, pp. 525--533, 1993.
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, x_init:, max_iter: 200, xtol: 1e-6, ftol: 1e-8, jtol: 1e-7)
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
- beta -= theta / kappa
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 = [beta * 4, BETA_MAX].min if delta < 0.25
157
- beta = [beta / 4, BETA_MIN].max if delta > 0.75
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 @args.is_a?(Hash)
180
- @fnc.call(x, **@args)
181
- elsif @args.is_a?(Array)
182
- @fnc.call(x, *@args)
183
- elsif @args.nil?
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, @args)
189
+ @fnc.call(x, args)
187
190
  end
188
191
  end
189
192
 
190
- def jacb(x)
191
- if @args.is_a?(Hash)
192
- @jcb.call(x, **@args)
193
- elsif @args.is_a?(Array)
194
- @jcb.call(x, *@args)
195
- elsif @args.nil?
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, @args)
201
+ @jcb.call(x, args)
199
202
  end
200
203
  end
201
204
  end
data/lib/mopti/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Mopti
4
4
  # The version of Mopti you are using.
5
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0'
6
6
  end
data/sig/mopti.rbs ADDED
@@ -0,0 +1,5 @@
1
+ module Mopti
2
+ VERSION: String
3
+
4
+ def self?.minimize: (algorithm: String algorithm, **untyped args) -> Hash[Symbol, untyped]?
5
+ end
@@ -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.1.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: 2020-02-19 00:00:00.000000000 Z
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.2
79
+ rubygems_version: 3.1.6
75
80
  signing_key:
76
81
  specification_version: 4
77
82
  summary: Multivariate Optimization Library in Ruby.