nlopt 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4700baee481eb9311b975cfd317df2f242f8e38f126b36fd44f14a34e9bee18b
4
- data.tar.gz: 8b11358fa772f186d6b562e85b23e8c8c7879d3d208b0cd7f4b2cf007481f867
3
+ metadata.gz: dc7b9fe5b30fd9f60c726dccd8edb8859e65eca488cd30e3e252c5ac83eacc4d
4
+ data.tar.gz: 260121b1a693646f681419086ababd4a569903289b2e2031610af9dd2a1357c7
5
5
  SHA512:
6
- metadata.gz: 73da0c81d6aafc93c9e21c0ae9474f112bdb9923a9dd08d176ac24a3b191047ca902f011cc37015395d7b2159237c9895d6cea9a869bd00c092263e9259d3204
7
- data.tar.gz: 57c37e5d06d5e5ebe37c70e70e8744225ecb2c5b7732c77a8c9b19c76d2f0d064f7bc4bd5146c4f1c46017f2f597583e1854a2695152cd9cc8bb1fdf630e7c44
6
+ metadata.gz: af0d54c03bfa3f38c080d65ef8f4ba5b3550085cb1acc8ad5990cb3a052e21e35bd7fa2ac75cfa417f21e4ef0e2dd2a0fb662aee7fe1cb40890463da3b6c1e6f
7
+ data.tar.gz: b9273f26c650eee060ce9b8228bcc2223ed7a28df4582d903cfff8ba598cd77215529a24078cd668197e23a0bb314e399d01410cd819f7eb892691a21e8c6c93
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.1.1 (2024-12-15)
2
+
3
+ - Added more methods
4
+
1
5
  ## 0.1.0 (2024-12-14)
2
6
 
3
7
  - First release
data/README.md CHANGED
@@ -12,7 +12,7 @@ First, install NLopt. For Homebrew, use:
12
12
  brew install nlopt
13
13
  ```
14
14
 
15
- And for Ubuntu, use:
15
+ And for Ubuntu 22.04+, use:
16
16
 
17
17
  ```sh
18
18
  sudo apt-get install libnlopt0
@@ -54,6 +54,10 @@ Perform the optimization
54
54
  xopt = opt.optimize([2, 3])
55
55
  ```
56
56
 
57
+ ## API
58
+
59
+ This library follows the [NLopt Python API](https://nlopt.readthedocs.io/en/latest/NLopt_Python_Reference/). You can follow Python tutorials and convert the code to Ruby in many cases. Feel free to open an issue if you run into problems.
60
+
57
61
  ## History
58
62
 
59
63
  View the [changelog](https://github.com/ankane/nlopt-ruby/blob/master/CHANGELOG.md)
data/lib/nlopt/ffi.rb CHANGED
@@ -14,18 +14,31 @@ module NLopt
14
14
 
15
15
  typealias "nlopt_algorithm", "int"
16
16
  typealias "nlopt_func", "void *"
17
+ typealias "nlopt_mfunc", "void *"
17
18
  typealias "nlopt_opt", "void *"
19
+ typealias "nlopt_precond", "void *"
18
20
  typealias "nlopt_result", "int"
19
21
  typealias "unsigned", "unsigned int"
20
22
 
21
23
  extern "const char * nlopt_algorithm_name(nlopt_algorithm a)"
24
+
25
+ # nlopt_algorithm enum <-> string conversion
26
+
22
27
  extern "const char * nlopt_algorithm_to_string(nlopt_algorithm algorithm)"
23
28
  extern "nlopt_algorithm nlopt_algorithm_from_string(const char *name)"
24
29
 
30
+ # nlopt_result enum <-> string conversion
31
+
25
32
  extern "const char * nlopt_result_to_string(nlopt_result algorithm)"
33
+ extern "nlopt_result nlopt_result_from_string(const char *name)"
34
+
35
+ extern "void nlopt_srand(unsigned long seed)"
36
+ extern "void nlopt_srand_time(void)"
26
37
 
27
38
  extern "void nlopt_version(int *major, int *minor, int *bugfix)"
28
39
 
40
+ # object-oriented api
41
+
29
42
  extern "nlopt_opt nlopt_create(nlopt_algorithm algorithm, unsigned n)"
30
43
  extern "void nlopt_destroy(nlopt_opt opt)"
31
44
  extern "nlopt_opt nlopt_copy(const nlopt_opt opt)"
@@ -35,10 +48,24 @@ module NLopt
35
48
  extern "nlopt_result nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void *f_data)"
36
49
  extern "nlopt_result nlopt_set_max_objective(nlopt_opt opt, nlopt_func f, void *f_data)"
37
50
 
51
+ extern "nlopt_result nlopt_set_precond_min_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data)"
52
+ extern "nlopt_result nlopt_set_precond_max_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data)"
53
+
38
54
  extern "nlopt_algorithm nlopt_get_algorithm(const nlopt_opt opt)"
39
55
  extern "unsigned nlopt_get_dimension(const nlopt_opt opt)"
56
+
40
57
  extern "const char * nlopt_get_errmsg(nlopt_opt opt)"
41
58
 
59
+ # generic algorithm parameters
60
+
61
+ extern "nlopt_result nlopt_set_param(nlopt_opt opt, const char *name, double val)"
62
+ extern "double nlopt_get_param(const nlopt_opt opt, const char *name, double defaultval)"
63
+ extern "int nlopt_has_param(const nlopt_opt opt, const char *name)"
64
+ extern "unsigned nlopt_num_params(const nlopt_opt opt)"
65
+ extern "const char * nlopt_nth_param(const nlopt_opt opt, unsigned n)"
66
+
67
+ # constraints
68
+
42
69
  extern "nlopt_result nlopt_set_lower_bounds(nlopt_opt opt, const double *lb)"
43
70
  extern "nlopt_result nlopt_set_lower_bounds1(nlopt_opt opt, double lb)"
44
71
  extern "nlopt_result nlopt_set_lower_bound(nlopt_opt opt, int i, double lb)"
@@ -48,9 +75,60 @@ module NLopt
48
75
  extern "nlopt_result nlopt_set_upper_bound(nlopt_opt opt, int i, double ub)"
49
76
  extern "nlopt_result nlopt_get_upper_bounds(const nlopt_opt opt, double *ub)"
50
77
 
78
+ extern "nlopt_result nlopt_remove_inequality_constraints(nlopt_opt opt)"
79
+ extern "nlopt_result nlopt_add_inequality_constraint(nlopt_opt opt, nlopt_func fc, void *fc_data, double tol)"
80
+ extern "nlopt_result nlopt_add_precond_inequality_constraint(nlopt_opt opt, nlopt_func fc, nlopt_precond pre, void *fc_data, double tol)"
81
+ extern "nlopt_result nlopt_add_inequality_mconstraint(nlopt_opt opt, unsigned m, nlopt_mfunc fc, void *fc_data, const double *tol)"
82
+
83
+ extern "nlopt_result nlopt_remove_equality_constraints(nlopt_opt opt)"
84
+ extern "nlopt_result nlopt_add_equality_constraint(nlopt_opt opt, nlopt_func h, void *h_data, double tol)"
85
+ extern "nlopt_result nlopt_add_precond_equality_constraint(nlopt_opt opt, nlopt_func h, nlopt_precond pre, void *h_data, double tol)"
86
+ extern "nlopt_result nlopt_add_equality_mconstraint(nlopt_opt opt, unsigned m, nlopt_mfunc h, void *h_data, const double *tol)"
87
+
88
+ # stopping criteria
89
+
90
+ extern "nlopt_result nlopt_set_stopval(nlopt_opt opt, double stopval)"
91
+ extern "double nlopt_get_stopval(const nlopt_opt opt)"
92
+
93
+ extern "nlopt_result nlopt_set_ftol_rel(nlopt_opt opt, double tol)"
94
+ extern "double nlopt_get_ftol_rel(const nlopt_opt opt)"
95
+ extern "nlopt_result nlopt_set_ftol_abs(nlopt_opt opt, double tol)"
96
+ extern "double nlopt_get_ftol_abs(const nlopt_opt opt)"
97
+
98
+ extern "nlopt_result nlopt_set_xtol_rel(nlopt_opt opt, double tol)"
99
+ extern "double nlopt_get_xtol_rel(const nlopt_opt opt)"
100
+ extern "nlopt_result nlopt_set_xtol_abs1(nlopt_opt opt, double tol)"
101
+ extern "nlopt_result nlopt_set_xtol_abs(nlopt_opt opt, const double *tol)"
102
+ extern "nlopt_result nlopt_get_xtol_abs(const nlopt_opt opt, double *tol)"
103
+ extern "nlopt_result nlopt_set_x_weights1(nlopt_opt opt, double w)"
104
+ extern "nlopt_result nlopt_set_x_weights(nlopt_opt opt, const double *w)"
105
+ extern "nlopt_result nlopt_get_x_weights(const nlopt_opt opt, double *w)"
106
+
51
107
  extern "nlopt_result nlopt_set_maxeval(nlopt_opt opt, int maxeval)"
52
108
  extern "int nlopt_get_maxeval(const nlopt_opt opt)"
53
109
 
54
110
  extern "int nlopt_get_numevals(const nlopt_opt opt)"
111
+
112
+ extern "nlopt_result nlopt_set_maxtime(nlopt_opt opt, double maxtime)"
113
+ extern "double nlopt_get_maxtime(const nlopt_opt opt)"
114
+
115
+ extern "nlopt_result nlopt_force_stop(nlopt_opt opt)"
116
+ extern "nlopt_result nlopt_set_force_stop(nlopt_opt opt, int val)"
117
+ extern "int nlopt_get_force_stop(const nlopt_opt opt)"
118
+
119
+ # more algorithm-specific parameters
120
+
121
+ extern "nlopt_result nlopt_set_local_optimizer(nlopt_opt opt, const nlopt_opt local_opt)"
122
+
123
+ extern "nlopt_result nlopt_set_population(nlopt_opt opt, unsigned pop)"
124
+ extern "unsigned nlopt_get_population(const nlopt_opt opt)"
125
+
126
+ extern "nlopt_result nlopt_set_vector_storage(nlopt_opt opt, unsigned dim)"
127
+ extern "unsigned nlopt_get_vector_storage(const nlopt_opt opt)"
128
+
129
+ extern "nlopt_result nlopt_set_default_initial_step(nlopt_opt opt, const double *x)"
130
+ extern "nlopt_result nlopt_set_initial_step(nlopt_opt opt, const double *dx)"
131
+ extern "nlopt_result nlopt_set_initial_step1(nlopt_opt opt, double dx)"
132
+ extern "nlopt_result nlopt_get_initial_step(const nlopt_opt opt, const double *x, double *dx)"
55
133
  end
56
134
  end
data/lib/nlopt/opt.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  module NLopt
2
2
  class Opt
3
+ attr_reader :last_optimum_value
4
+
3
5
  def initialize(algorithm, n)
4
6
  algorithm = FFI.nlopt_algorithm_from_string(algorithm)
5
7
  if algorithm < 0
@@ -14,21 +16,29 @@ module NLopt
14
16
  @opt.free = FFI["nlopt_destroy"]
15
17
  end
16
18
 
19
+ def dimension
20
+ FFI.nlopt_get_dimension(@opt)
21
+ end
22
+
23
+ def algorithm_name
24
+ FFI.nlopt_algorithm_name(FFI.nlopt_get_algorithm(@opt)).to_s
25
+ end
26
+
17
27
  def set_min_objective(f)
18
- # keep reference
19
- @f = objective_callback(f)
20
- check_res FFI.nlopt_set_min_objective(@opt, @f, nil)
28
+ cb = objective_callback(f)
29
+ check_res FFI.nlopt_set_min_objective(@opt, cb, nil)
30
+ @cb = cb # keep reference
21
31
  end
22
32
 
23
33
  def set_max_objective(f)
24
- # keep reference
25
- @f = objective_callback(f)
26
- check_res FFI.nlopt_set_max_objective(@opt, @f, nil)
34
+ cb = objective_callback(f)
35
+ check_res FFI.nlopt_set_max_objective(@opt, cb, nil)
36
+ @cb = cb # keep reference
27
37
  end
28
38
 
29
39
  def set_lower_bounds(lb)
30
40
  if lb.is_a?(Array)
31
- check_res FFI.nlopt_set_lower_bounds(@opt, Fiddle::Pointer[lb.pack("d*")])
41
+ check_res FFI.nlopt_set_lower_bounds(@opt, alloc_dptr(lb))
32
42
  elsif lb.is_a?(Numeric)
33
43
  check_res FFI.nlopt_set_lower_bounds1(@opt, lb)
34
44
  else
@@ -38,7 +48,7 @@ module NLopt
38
48
 
39
49
  def set_upper_bounds(ub)
40
50
  if ub.is_a?(Array)
41
- check_res FFI.nlopt_set_upper_bounds(@opt, Fiddle::Pointer[ub.pack("d*")])
51
+ check_res FFI.nlopt_set_upper_bounds(@opt, alloc_dptr(ub))
42
52
  elsif ub.is_a?(Numeric)
43
53
  check_res FFI.nlopt_set_upper_bounds1(@opt, ub)
44
54
  else
@@ -46,16 +56,125 @@ module NLopt
46
56
  end
47
57
  end
48
58
 
59
+ def lower_bounds
60
+ out_dptr { |ptr| FFI.nlopt_get_lower_bounds(@opt, ptr) }
61
+ end
62
+
63
+ def upper_bounds
64
+ out_dptr { |ptr| FFI.nlopt_get_upper_bounds(@opt, ptr) }
65
+ end
66
+
67
+ def remove_inequality_constraints
68
+ check_res FFI.nlopt_remove_inequality_constraints(@opt)
69
+ end
70
+
71
+ def remove_equality_constraints
72
+ check_res FFI.nlopt_remove_equality_constraints(@opt)
73
+ end
74
+
75
+ def set_stopval(stopval)
76
+ check_res FFI.nlopt_set_stopval(@opt, stopval)
77
+ end
78
+
79
+ def stopval
80
+ FFI.nlopt_get_stopval(@opt)
81
+ end
82
+
83
+ def set_ftol_rel(tol)
84
+ check_res FFI.nlopt_set_ftol_rel(@opt, tol)
85
+ end
86
+
87
+ def ftol_rel
88
+ FFI.nlopt_get_ftol_rel(@opt)
89
+ end
90
+
91
+ def set_ftol_abs(tol)
92
+ check_res FFI.nlopt_set_ftol_abs(@opt, tol)
93
+ end
94
+
95
+ def ftol_abs
96
+ FFI.nlopt_get_ftol_abs(@opt)
97
+ end
98
+
99
+ def set_xtol_rel(tol)
100
+ check_res FFI.nlopt_set_xtol_rel(@opt, tol)
101
+ end
102
+
103
+ def xtol_rel
104
+ FFI.nlopt_get_xtol_rel(@opt)
105
+ end
106
+
107
+ def set_xtol_abs(tol)
108
+ if tol.is_a?(Array)
109
+ check_res FFI.nlopt_set_xtol_abs(@opt, alloc_dptr(tol))
110
+ elsif tol.is_a?(Numeric)
111
+ check_res FFI.nlopt_set_xtol_abs1(@opt, tol)
112
+ else
113
+ raise TypeError, "expected array or numeric"
114
+ end
115
+ end
116
+
117
+ def xtol_abs
118
+ out_dptr { |ptr| FFI.nlopt_get_xtol_abs(@opt, ptr) }
119
+ end
120
+
121
+ def set_x_weights(w)
122
+ if w.is_a?(Array)
123
+ check_res FFI.nlopt_set_x_weights(@opt, alloc_dptr(w))
124
+ elsif w.is_a?(Numeric)
125
+ check_res FFI.nlopt_set_x_weights1(@opt, w)
126
+ else
127
+ raise TypeError, "expected array or numeric"
128
+ end
129
+ end
130
+
131
+ def x_weights
132
+ out_dptr { |ptr| FFI.nlopt_get_x_weights(@opt, ptr) }
133
+ end
134
+
49
135
  def set_maxeval(maxeval)
50
136
  check_res FFI.nlopt_set_maxeval(@opt, maxeval)
51
137
  end
52
138
 
53
- def optimize(init)
54
- if init.size != dimension
55
- raise ArgumentError, "size does not match dimension"
56
- end
139
+ def maxeval
140
+ FFI.nlopt_get_maxeval(@opt)
141
+ end
142
+
143
+ def set_maxtime(maxtime)
144
+ check_res FFI.nlopt_set_maxtime(@opt, maxtime)
145
+ end
146
+
147
+ def maxtime
148
+ FFI.nlopt_get_maxtime(@opt)
149
+ end
150
+
151
+ def numevals
152
+ FFI.nlopt_get_numevals(@opt)
153
+ end
154
+
155
+ def set_param(name, val)
156
+ check_res FFI.nlopt_set_param(@opt, name, val)
157
+ end
158
+
159
+ def param(name, defaultval)
160
+ FFI.nlopt_get_param(@opt, name, defaultval)
161
+ end
162
+
163
+ def has_param?(name)
164
+ FFI.nlopt_has_param(@opt, name) == 1
165
+ end
166
+
167
+ def num_params
168
+ FFI.nlopt_num_params(@opt)
169
+ end
170
+
171
+ def nth_param(n)
172
+ ptr = FFI.nlopt_nth_param(@opt, n)
173
+ !ptr.null? ? ptr.to_s : nil
174
+ end
57
175
 
58
- x = Fiddle::Pointer[init.pack("d*")]
176
+ def optimize(init)
177
+ x = alloc_dptr(init)
59
178
  opt_f = Fiddle::Pointer.malloc(Fiddle::SIZEOF_DOUBLE)
60
179
  res = FFI.nlopt_optimize(@opt, x, opt_f)
61
180
 
@@ -65,19 +184,43 @@ module NLopt
65
184
  raise Error, msg
66
185
  end
67
186
 
68
- x.to_s(x.size).unpack("d*")
187
+ @last_optimum_value = read_dptr(opt_f)[0]
188
+
189
+ read_dptr(x)
69
190
  end
70
191
 
71
- def algorithm_name
72
- FFI.nlopt_algorithm_name(FFI.nlopt_get_algorithm(@opt)).to_s
192
+ def force_stop
193
+ check_res FFI.nlopt_force_stop(@opt)
73
194
  end
74
195
 
75
- def dimension
76
- FFI.nlopt_get_dimension(@opt)
196
+ def set_local_optimizer(local_opt)
197
+ check_res FFI.nlopt_set_local_optimizer(@opt, local_opt)
77
198
  end
78
199
 
79
- def numevals
80
- FFI.nlopt_get_numevals(@opt)
200
+ def set_initial_step(dx)
201
+ if dx.is_a?(Array)
202
+ check_res FFI.nlopt_set_initial_step(@opt, alloc_dptr(dx))
203
+ elsif dx.is_a?(Numeric)
204
+ check_res FFI.nlopt_set_initial_step1(@opt, dx)
205
+ else
206
+ raise TypeError, "expected array or numeric"
207
+ end
208
+ end
209
+
210
+ def set_population(pop)
211
+ check_res FFI.nlopt_set_population(@opt, pop)
212
+ end
213
+
214
+ def population
215
+ FFI.nlopt_get_population(@opt)
216
+ end
217
+
218
+ def set_vector_storage(dim)
219
+ check_res FFI.nlopt_set_vector_storage(@opt, dim)
220
+ end
221
+
222
+ def vector_storage
223
+ FFI.nlopt_get_vector_storage(@opt)
81
224
  end
82
225
 
83
226
  private
@@ -88,9 +231,29 @@ module NLopt
88
231
  end
89
232
  end
90
233
 
234
+ def alloc_dptr(arr)
235
+ n = dimension
236
+ if arr.size != n
237
+ raise ArgumentError, "size does not match dimension"
238
+ end
239
+ Fiddle::Pointer[arr.pack("d#{n}")]
240
+ end
241
+
242
+ def read_dptr(ptr, size = nil)
243
+ size ||= ptr.size
244
+ ptr.to_s(size).unpack("d*")
245
+ end
246
+
247
+ def out_dptr
248
+ ptr = Fiddle::Pointer.malloc(dimension * Fiddle::SIZEOF_DOUBLE)
249
+ res = yield ptr
250
+ check_res res
251
+ read_dptr(ptr)
252
+ end
253
+
91
254
  def objective_callback(f)
92
255
  Fiddle::Closure::BlockCaller.new(Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_UINT, Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP]) do |n, x, gradient, func_data|
93
- x = x.to_s(n * Fiddle::SIZEOF_DOUBLE).unpack("d*")
256
+ x = read_dptr(x, n * Fiddle::SIZEOF_DOUBLE)
94
257
  grad = !gradient.null? ? Gradient.new(gradient, n) : nil
95
258
  f.call(x, grad)
96
259
  end
data/lib/nlopt/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module NLopt
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
data/lib/nlopt.rb CHANGED
@@ -37,4 +37,24 @@ module NLopt
37
37
  FFI.nlopt_version(major, minor, bugfix)
38
38
  [major, minor, bugfix].map { |v| v.to_s(v.size).unpack1("i") }.join(".")
39
39
  end
40
+
41
+ def self.srand(seed)
42
+ FFI.nlopt_srand(seed)
43
+ end
44
+
45
+ def self.srand_time
46
+ FFI.nlopt_srand_time
47
+ end
48
+
49
+ def self.version_major
50
+ lib_version.split(".")[0].to_i
51
+ end
52
+
53
+ def self.version_minor
54
+ lib_version.split(".")[1].to_i
55
+ end
56
+
57
+ def self.version_bugfix
58
+ lib_version.split(".")[2].to_i
59
+ end
40
60
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nlopt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-12-14 00:00:00.000000000 Z
11
+ date: 2024-12-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fiddle