nlopt 0.1.0 → 0.1.2

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: c779a5c494c4f27159c477063ddf7574c40b9813936d25ca24a0e9b72a6c897c
4
+ data.tar.gz: dc7dd6083dfc4696ad9795fcb3565d7a67ecd150ca14b56bc99afdc171908335
5
5
  SHA512:
6
- metadata.gz: 73da0c81d6aafc93c9e21c0ae9474f112bdb9923a9dd08d176ac24a3b191047ca902f011cc37015395d7b2159237c9895d6cea9a869bd00c092263e9259d3204
7
- data.tar.gz: 57c37e5d06d5e5ebe37c70e70e8744225ecb2c5b7732c77a8c9b19c76d2f0d064f7bc4bd5146c4f1c46017f2f597583e1854a2695152cd9cc8bb1fdf630e7c44
6
+ metadata.gz: f9dde169b1604d8a2c4a726aff6faecfde7d63180a936ec4f0d640d02bb6f36cee1833718f3486c926da8332b34e0a6cdcf34518b853c1cbcf7a386873ccb378
7
+ data.tar.gz: 37b4f469c22ff6e21d4e1012ad1fcd7f6c09cc478cc215917d01a73c9aef04003dbce4c95f44f836dbf6b71c82e604acf43dddc8f9b8bb6ff510a871e6d3bd69
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.1.2 (2024-12-16)
2
+
3
+ - Added `add_inequality_constraint` and `add_equality_constraint` methods
4
+ - Added `initial_step` method
5
+
6
+ ## 0.1.1 (2024-12-15)
7
+
8
+ - Added more methods
9
+
1
10
  ## 0.1.0 (2024-12-14)
2
11
 
3
12
  - 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
@@ -6,12 +6,12 @@ module NLopt
6
6
  end
7
7
 
8
8
  def [](index)
9
- check_index(index)
9
+ index = check_index(index)
10
10
  @ptr[index * Fiddle::SIZEOF_DOUBLE, Fiddle::SIZEOF_DOUBLE].unpack1("d")
11
11
  end
12
12
 
13
13
  def []=(index, value)
14
- check_index(index)
14
+ index = check_index(index)
15
15
  @ptr[index * Fiddle::SIZEOF_DOUBLE, Fiddle::SIZEOF_DOUBLE] = [value].pack("d")
16
16
  end
17
17
 
@@ -26,10 +26,13 @@ module NLopt
26
26
 
27
27
  private
28
28
 
29
- def check_index(index)
30
- if index >= @n
31
- raise IndexError, "index #{index} outside of array bounds"
29
+ def check_index(original_index)
30
+ index = original_index
31
+ index += @n if index < 0
32
+ if index < 0 || index >= @n
33
+ raise IndexError, "index #{original_index} outside of array bounds"
32
34
  end
35
+ index
33
36
  end
34
37
  end
35
38
  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
@@ -12,23 +14,34 @@ module NLopt
12
14
 
13
15
  @opt = FFI.nlopt_create(algorithm, n)
14
16
  @opt.free = FFI["nlopt_destroy"]
17
+
18
+ @inequality_constraints = []
19
+ @equality_constraints = []
20
+ end
21
+
22
+ def dimension
23
+ FFI.nlopt_get_dimension(@opt)
24
+ end
25
+
26
+ def algorithm_name
27
+ FFI.nlopt_algorithm_name(FFI.nlopt_get_algorithm(@opt)).to_s
15
28
  end
16
29
 
17
30
  def set_min_objective(f)
18
- # keep reference
19
- @f = objective_callback(f)
20
- check_res FFI.nlopt_set_min_objective(@opt, @f, nil)
31
+ cb = objective_callback(f)
32
+ check_res FFI.nlopt_set_min_objective(@opt, cb, nil)
33
+ @cb = cb # keep reference
21
34
  end
22
35
 
23
36
  def set_max_objective(f)
24
- # keep reference
25
- @f = objective_callback(f)
26
- check_res FFI.nlopt_set_max_objective(@opt, @f, nil)
37
+ cb = objective_callback(f)
38
+ check_res FFI.nlopt_set_max_objective(@opt, cb, nil)
39
+ @cb = cb # keep reference
27
40
  end
28
41
 
29
42
  def set_lower_bounds(lb)
30
43
  if lb.is_a?(Array)
31
- check_res FFI.nlopt_set_lower_bounds(@opt, Fiddle::Pointer[lb.pack("d*")])
44
+ check_res FFI.nlopt_set_lower_bounds(@opt, alloc_dptr(lb))
32
45
  elsif lb.is_a?(Numeric)
33
46
  check_res FFI.nlopt_set_lower_bounds1(@opt, lb)
34
47
  else
@@ -38,7 +51,7 @@ module NLopt
38
51
 
39
52
  def set_upper_bounds(ub)
40
53
  if ub.is_a?(Array)
41
- check_res FFI.nlopt_set_upper_bounds(@opt, Fiddle::Pointer[ub.pack("d*")])
54
+ check_res FFI.nlopt_set_upper_bounds(@opt, alloc_dptr(ub))
42
55
  elsif ub.is_a?(Numeric)
43
56
  check_res FFI.nlopt_set_upper_bounds1(@opt, ub)
44
57
  else
@@ -46,16 +59,139 @@ module NLopt
46
59
  end
47
60
  end
48
61
 
62
+ def lower_bounds
63
+ out_dptr { |ptr| FFI.nlopt_get_lower_bounds(@opt, ptr) }
64
+ end
65
+
66
+ def upper_bounds
67
+ out_dptr { |ptr| FFI.nlopt_get_upper_bounds(@opt, ptr) }
68
+ end
69
+
70
+ def add_inequality_constraint(fc, tol: 0)
71
+ cb = objective_callback(fc)
72
+ check_res FFI.nlopt_add_inequality_constraint(@opt, cb, nil, tol)
73
+ @inequality_constraints << cb # keep reference
74
+ end
75
+
76
+ def add_equality_constraint(h, tol: 0)
77
+ cb = objective_callback(h)
78
+ check_res FFI.nlopt_add_equality_constraint(@opt, cb, nil, tol)
79
+ @equality_constraints << cb # keep reference
80
+ end
81
+
82
+ def remove_inequality_constraints
83
+ check_res FFI.nlopt_remove_inequality_constraints(@opt)
84
+ @inequality_constraints.clear
85
+ end
86
+
87
+ def remove_equality_constraints
88
+ check_res FFI.nlopt_remove_equality_constraints(@opt)
89
+ @equality_constraints.clear
90
+ end
91
+
92
+ def set_stopval(stopval)
93
+ check_res FFI.nlopt_set_stopval(@opt, stopval)
94
+ end
95
+
96
+ def stopval
97
+ FFI.nlopt_get_stopval(@opt)
98
+ end
99
+
100
+ def set_ftol_rel(tol)
101
+ check_res FFI.nlopt_set_ftol_rel(@opt, tol)
102
+ end
103
+
104
+ def ftol_rel
105
+ FFI.nlopt_get_ftol_rel(@opt)
106
+ end
107
+
108
+ def set_ftol_abs(tol)
109
+ check_res FFI.nlopt_set_ftol_abs(@opt, tol)
110
+ end
111
+
112
+ def ftol_abs
113
+ FFI.nlopt_get_ftol_abs(@opt)
114
+ end
115
+
116
+ def set_xtol_rel(tol)
117
+ check_res FFI.nlopt_set_xtol_rel(@opt, tol)
118
+ end
119
+
120
+ def xtol_rel
121
+ FFI.nlopt_get_xtol_rel(@opt)
122
+ end
123
+
124
+ def set_xtol_abs(tol)
125
+ if tol.is_a?(Array)
126
+ check_res FFI.nlopt_set_xtol_abs(@opt, alloc_dptr(tol))
127
+ elsif tol.is_a?(Numeric)
128
+ check_res FFI.nlopt_set_xtol_abs1(@opt, tol)
129
+ else
130
+ raise TypeError, "expected array or numeric"
131
+ end
132
+ end
133
+
134
+ def xtol_abs
135
+ out_dptr { |ptr| FFI.nlopt_get_xtol_abs(@opt, ptr) }
136
+ end
137
+
138
+ def set_x_weights(w)
139
+ if w.is_a?(Array)
140
+ check_res FFI.nlopt_set_x_weights(@opt, alloc_dptr(w))
141
+ elsif w.is_a?(Numeric)
142
+ check_res FFI.nlopt_set_x_weights1(@opt, w)
143
+ else
144
+ raise TypeError, "expected array or numeric"
145
+ end
146
+ end
147
+
148
+ def x_weights
149
+ out_dptr { |ptr| FFI.nlopt_get_x_weights(@opt, ptr) }
150
+ end
151
+
49
152
  def set_maxeval(maxeval)
50
153
  check_res FFI.nlopt_set_maxeval(@opt, maxeval)
51
154
  end
52
155
 
53
- def optimize(init)
54
- if init.size != dimension
55
- raise ArgumentError, "size does not match dimension"
56
- end
156
+ def maxeval
157
+ FFI.nlopt_get_maxeval(@opt)
158
+ end
159
+
160
+ def set_maxtime(maxtime)
161
+ check_res FFI.nlopt_set_maxtime(@opt, maxtime)
162
+ end
163
+
164
+ def maxtime
165
+ FFI.nlopt_get_maxtime(@opt)
166
+ end
167
+
168
+ def numevals
169
+ FFI.nlopt_get_numevals(@opt)
170
+ end
171
+
172
+ def set_param(name, val)
173
+ check_res FFI.nlopt_set_param(@opt, name, val)
174
+ end
57
175
 
58
- x = Fiddle::Pointer[init.pack("d*")]
176
+ def param(name, defaultval)
177
+ FFI.nlopt_get_param(@opt, name, defaultval)
178
+ end
179
+
180
+ def has_param?(name)
181
+ FFI.nlopt_has_param(@opt, name) == 1
182
+ end
183
+
184
+ def num_params
185
+ FFI.nlopt_num_params(@opt)
186
+ end
187
+
188
+ def nth_param(n)
189
+ ptr = FFI.nlopt_nth_param(@opt, n)
190
+ !ptr.null? ? ptr.to_s : nil
191
+ end
192
+
193
+ def optimize(init)
194
+ x = alloc_dptr(init)
59
195
  opt_f = Fiddle::Pointer.malloc(Fiddle::SIZEOF_DOUBLE)
60
196
  res = FFI.nlopt_optimize(@opt, x, opt_f)
61
197
 
@@ -65,19 +201,51 @@ module NLopt
65
201
  raise Error, msg
66
202
  end
67
203
 
68
- x.to_s(x.size).unpack("d*")
204
+ @last_optimum_value = read_dptr(opt_f)[0]
205
+
206
+ read_dptr(x)
69
207
  end
70
208
 
71
- def algorithm_name
72
- FFI.nlopt_algorithm_name(FFI.nlopt_get_algorithm(@opt)).to_s
209
+ def force_stop
210
+ check_res FFI.nlopt_force_stop(@opt)
73
211
  end
74
212
 
75
- def dimension
76
- FFI.nlopt_get_dimension(@opt)
213
+ def set_local_optimizer(local_opt)
214
+ check_res FFI.nlopt_set_local_optimizer(@opt, local_opt)
77
215
  end
78
216
 
79
- def numevals
80
- FFI.nlopt_get_numevals(@opt)
217
+ def set_initial_step(dx)
218
+ if dx.is_a?(Array)
219
+ check_res FFI.nlopt_set_initial_step(@opt, alloc_dptr(dx))
220
+ elsif dx.is_a?(Numeric)
221
+ check_res FFI.nlopt_set_initial_step1(@opt, dx)
222
+ else
223
+ raise TypeError, "expected array or numeric"
224
+ end
225
+ end
226
+
227
+ def initial_step(x)
228
+ out_dptr { |ptr| FFI.nlopt_get_initial_step(@opt, alloc_dptr(x), ptr) }
229
+ end
230
+
231
+ def set_population(pop)
232
+ check_res FFI.nlopt_set_population(@opt, pop)
233
+ end
234
+
235
+ def population
236
+ FFI.nlopt_get_population(@opt)
237
+ end
238
+
239
+ def set_vector_storage(dim)
240
+ check_res FFI.nlopt_set_vector_storage(@opt, dim)
241
+ end
242
+
243
+ def vector_storage
244
+ FFI.nlopt_get_vector_storage(@opt)
245
+ end
246
+
247
+ def to_ptr
248
+ @opt
81
249
  end
82
250
 
83
251
  private
@@ -88,9 +256,29 @@ module NLopt
88
256
  end
89
257
  end
90
258
 
259
+ def alloc_dptr(arr)
260
+ n = dimension
261
+ if arr.size != n
262
+ raise ArgumentError, "size does not match dimension"
263
+ end
264
+ Fiddle::Pointer[arr.pack("d#{n}")]
265
+ end
266
+
267
+ def read_dptr(ptr, size = nil)
268
+ size ||= ptr.size
269
+ ptr.to_s(size).unpack("d*")
270
+ end
271
+
272
+ def out_dptr
273
+ ptr = Fiddle::Pointer.malloc(dimension * Fiddle::SIZEOF_DOUBLE)
274
+ res = yield ptr
275
+ check_res res
276
+ read_dptr(ptr)
277
+ end
278
+
91
279
  def objective_callback(f)
92
280
  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*")
281
+ x = read_dptr(x, n * Fiddle::SIZEOF_DOUBLE)
94
282
  grad = !gradient.null? ? Gradient.new(gradient, n) : nil
95
283
  f.call(x, grad)
96
284
  end
data/lib/nlopt/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module NLopt
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.2"
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.2
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-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fiddle