minimization 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -1,3 +1,6 @@
1
+ === 0.2.0 / 2010-04-15
2
+ * New Minimization::NewtonRahpson class, which implements a naive Newton-Rahpson minimization method
3
+ x=x_n-(f'(x)/f''(x))
1
4
  === 0.1.1 / 2010-03-19
2
5
 
3
6
  * New Minimization#minimize convenience method
@@ -4,4 +4,6 @@ Manifest.txt
4
4
  README.txt
5
5
  Rakefile
6
6
  lib/minimization.rb
7
- test/test_minimization.rb
7
+ spec/minimization_unidimensional_spec.rb
8
+ spec/spec.opts
9
+ spec/spec_helper.rb
data/README.txt CHANGED
@@ -9,6 +9,7 @@ Minimization algorithms on pure Ruby.
9
9
  == FEATURES/PROBLEMS:
10
10
 
11
11
  Unidimensional:
12
+ * Newton-Rahpson (requires first and second derivative)
12
13
  * Golden Section
13
14
  * Brent (Port of GSL code)
14
15
 
data/Rakefile CHANGED
@@ -3,12 +3,14 @@
3
3
  require 'rubygems'
4
4
  require 'hoe'
5
5
  require './lib/minimization'
6
+ Hoe.plugin :git
6
7
 
7
8
  Hoe.spec 'minimization' do
8
9
  self.version=Minimization::VERSION
9
10
  self.rubyforge_name = 'ruby-statsample' # if different than 'minimization'
10
11
  self.developer('Claudio Bustos', 'clbustos_AT_gmail.com')
11
12
  self.remote_rdoc_dir = 'minimization'
13
+ self.extra_deps << ['text-table', "~>1.2"]
12
14
  end
13
15
 
14
16
  # vim: syntax=ruby
@@ -1,4 +1,4 @@
1
- # = minimization.rb -
1
+ # = minimization.rb -
2
2
  # Minimization- Minimization algorithms on pure Ruby
3
3
  # Copyright (C) 2010 Claudio Bustos
4
4
  #
@@ -16,353 +16,428 @@
16
16
  # along with this program; if not, write to the Free Software
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
18
  #
19
-
19
+ require 'text-table'
20
+ # Algorithms for unidimensional minimization
20
21
  module Minimization
21
-
22
- VERSION="0.1.1"
23
- FailedIteration=Class.new(Exception)
22
+ VERSION="0.2.0"
23
+ FailedIteration=Class.new(Exception)
24
24
  # Base class for unidimensional minimizers
25
- class Unidimensional
26
- # Default value for error
27
- EPSILON=1e-6
28
- # Default number of maximum iterations
29
- MAX_ITERATIONS=100
30
- # Minimum value for x
31
- attr_reader :x_minimum
32
- # Minimum value for f(x)
33
- attr_reader :f_minimum
34
- # Log of iterations
35
- attr_reader :log
36
- # Absolute error on x
37
- attr_accessor :epsilon
38
- # Create a new minimizer
39
- def initialize(lower, upper, proc)
40
- raise "first argument should be lower than second" if lower>=upper
41
- @lower=lower
42
- @upper=upper
43
- @proc=proc
44
- golden = 0.3819660;
45
- @expected = @lower + golden * (@upper - @lower);
46
- @max_iteration=MAX_ITERATIONS
47
- @epsilon=EPSILON
48
- @iterations=0
49
- @log=""
25
+ class Unidimensional
26
+ # Default value for error on f(x)
27
+ EPSILON=1e-6
28
+ # Default number of maximum iterations
29
+ MAX_ITERATIONS=100
30
+ # Minimum value for x
31
+ attr_reader :x_minimum
32
+ # Minimum value for f(x)
33
+ attr_reader :f_minimum
34
+ # Log of iterations. Should be an array
35
+ attr_reader :log
36
+ # Name of fields of log
37
+ attr_reader :log_header
38
+ # Absolute error on x
39
+ attr_accessor :epsilon
40
+ # Expected value. Fast minimum finding if set
41
+ attr_reader :expected
42
+ # Create a new minimizer
43
+ def initialize(lower, upper, proc)
44
+ raise "first argument should be lower than second" if lower>=upper
45
+ @lower=lower
46
+ @upper=upper
47
+ @proc=proc
48
+ golden = 0.3819660;
49
+ @expected = @lower + golden * (@upper - @lower);
50
+ @max_iteration=MAX_ITERATIONS
51
+ @epsilon=EPSILON
52
+ @iterations=0
53
+ @log=[]
54
+ @log_header=%w{I xl xh f(xl) f(xh) dx df(x)}
55
+ end
56
+ # Set expected value
57
+ def expected=(v)
58
+ @expected=v
59
+ end
60
+ def log_summary
61
+ @log.join("\n")
50
62
  end
51
63
  # Convenience method to minimize
52
- # Usage:
64
+ # == Parameters:
65
+ # * <tt>lower</tt>: Lower possible value
66
+ # * <tt>upper</tt>: Higher possible value
67
+ # * <tt>expected</tt>: Optional expected value. Faster the search is near correct value.
68
+ # * <tt>&block</tt>: Block with function to minimize
69
+ # == Usage:
53
70
  # minimizer=Minimization::GoldenSection.minimize(-1000, 1000) {|x|
54
71
  # x**2 }
55
- #
72
+ #
56
73
  def self.minimize(lower,upper,expected=nil,&block)
57
74
  minimizer=new(lower,upper,block)
58
75
  minimizer.expected=expected unless expected.nil?
59
76
  raise FailedIteration unless minimizer.iterate
60
77
  minimizer
61
78
  end
62
- def f(x)
79
+ # Iterate to find the minimum
80
+ def iterate
81
+ raise "You should implement this"
82
+ end
83
+ def f(x)
63
84
  @proc.call(x)
64
85
  end
65
- end
66
- # = Golden Section Minimizer.
67
- # Basic minimization algorithm. Slow, but robust
68
- # Use:
69
- # require 'minimization'
70
- # min=Minimization::GoldenSection.new(-1000,20000 , proc {|x| (x+1)**2}
71
- # min.expected=1.5 # Expected value
72
- # min.iterate
73
- # min.x_minimum
74
- # min.f_minimum
75
- # min.log
86
+ end
87
+ # Classic Newton-Raphson minimization method.
88
+ # Requires first and second derivative
89
+ # == Usage
90
+ # f = lambda {|x| x**2}
91
+ # fd = lambda {|x| 2x}
92
+ # fdd = lambda {|x| 2}
93
+ # min = Minimization::NewtonRaphson.new(-1000,1000, f,fd,fdd)
94
+ # min.iterate
95
+ # min.x_minimum
96
+ # min.f_minimum
97
+ #
98
+ class NewtonRaphson < Unidimensional
99
+ # == Parameters:
100
+ # * <tt>lower</tt>: Lower possible value
101
+ # * <tt>upper</tt>: Higher possible value
102
+ # * <tt>proc</tt>: Original function
103
+ # * <tt>proc_1d</tt>: First derivative
104
+ # * <tt>proc_2d</tt>: Second derivative
105
+ #
106
+ def initialize(lower, upper, proc, proc_1d, proc_2d)
107
+ super(lower,upper,proc)
108
+ @proc_1d=proc_1d
109
+ @proc_2d=proc_2d
110
+ end
111
+ # Raises an error
112
+ def self.minimize(*args)
113
+ raise "You should use #new and #iterate"
114
+ end
115
+ def iterate
116
+ # First
117
+ x_prev=@lower
118
+ x=@expected
119
+ failed=true
120
+ k=0
121
+ while (x-x_prev).abs > @epsilon and k<@max_iteration
122
+ k+=1
123
+ x_prev=x
124
+ x=x-(@proc_1d.call(x).quo(@proc_2d.call(x)))
125
+ f_prev=f(x_prev)
126
+ f=f(x)
127
+ x_min,x_max=[x,x_prev].min, [x,x_prev].max
128
+ f_min,f_max=[f,f_prev].min, [f,f_prev].max
129
+ @log << [k, x_min, x_max, f_min, f_max, (x_prev-x).abs, (f-f_prev).abs]
130
+ end
131
+ raise FailedIteration, "Not converged" if k>=@max_iteration
132
+ @x_minimum = x;
133
+ @f_minimum = f(x);
134
+ end
135
+ end
136
+ # = Golden Section Minimizer.
137
+ # Basic minimization algorithm. Slow, but robust.
138
+ # See Unidimensional for methods.
139
+ # == Usage.
140
+ # require 'minimization'
141
+ # min=Minimization::GoldenSection.new(-1000,20000 , proc {|x| (x+1)**2}
142
+ # min.expected=1.5 # Expected value
143
+ # min.iterate
144
+ # min.x_minimum
145
+ # min.f_minimum
146
+ # min.log
76
147
  class GoldenSection < Unidimensional
77
- attr_accessor :expected
78
- def initialize(lower,upper, proc)
79
- super
80
- end
81
- # Start the iteration
82
- def iterate
83
- ax=@lower
84
- bx=@expected
85
- cx=@upper
86
- c = (3-Math::sqrt(5)).quo(2);
87
- r = 1-c;
88
-
89
- x0 = ax;
90
- x3 = cx;
91
- if ((cx-bx).abs > (bx-ax).abs)
92
- x1 = bx;
93
- x2 = bx + c*(cx-bx);
94
- else
95
- x2 = bx;
96
- x1 = bx - c*(bx-ax);
97
- end
98
- f1 = f(x1);
99
- f2 = f(x2);
100
-
101
- k = 1;
102
-
103
-
104
-
105
- while (x3-x0).abs > @epsilon and k<@max_iteration
106
- @log+=sprintf("k=%4d, |a-b|=%e\n", k, (x3-x0).abs)
107
- if f2 < f1
108
- x0 = x1;
109
- x1 = x2;
110
- x2 = r*x1 + c*x3; # x2 = x1+c*(x3-x1)
111
- f1 = f2;
112
- f2 = f(x2);
113
- else
114
- x3 = x2;
115
- x2 = x1;
116
- x1 = r*x2 + c*x0; # x1 = x2+c*(x0-x2)
117
- f2 = f1;
118
- f1 = f(x1);
119
- end
120
- k +=1;
121
- end
122
-
123
- if f1 < f2
124
- @x_minimum = x1;
125
- @f_minimum = f1;
148
+ # Start the iteration
149
+ def iterate
150
+ ax=@lower
151
+ bx=@expected
152
+ cx=@upper
153
+ c = (3-Math::sqrt(5)).quo(2);
154
+ r = 1-c;
155
+
156
+ x0 = ax;
157
+ x3 = cx;
158
+ if ((cx-bx).abs > (bx-ax).abs)
159
+ x1 = bx;
160
+ x2 = bx + c*(cx-bx);
161
+ else
162
+ x2 = bx;
163
+ x1 = bx - c*(bx-ax);
164
+ end
165
+ f1 = f(x1);
166
+ f2 = f(x2);
167
+
168
+ k = 1;
169
+
170
+
171
+
172
+ while (x3-x0).abs > @epsilon and k<@max_iteration
173
+ if f2 < f1
174
+ x0 = x1;
175
+ x1 = x2;
176
+ x2 = r*x1 + c*x3; # x2 = x1+c*(x3-x1)
177
+ f1 = f2;
178
+ f2 = f(x2);
126
179
  else
127
- @x_minimum = x2;
128
- @f_minimum = f2;
180
+ x3 = x2;
181
+ x2 = x1;
182
+ x1 = r*x2 + c*x0; # x1 = x2+c*(x0-x2)
183
+ f2 = f1;
184
+ f1 = f(x1);
129
185
  end
130
- true
186
+ @log << [k, x3,x0, f1,f2,(x3-x0).abs, (f1-f2).abs]
187
+
188
+ k +=1;
131
189
  end
132
190
 
191
+ if f1 < f2
192
+ @x_minimum = x1;
193
+ @f_minimum = f1;
194
+ else
195
+ @x_minimum = x2;
196
+ @f_minimum = f2;
197
+ end
198
+ true
199
+ end
200
+
201
+ end
202
+
203
+ # Direct port of Brent algorithm found on GSL.
204
+ # See Unidimensional for methods.
205
+ # == Usage
206
+ # min=Minimization::Brent.new(-1000,20000 , proc {|x| (x+1)**2}
207
+ # min.expected=1.5 # Expected value
208
+ # min.iterate
209
+ # min.x_minimum
210
+ # min.f_minimum
211
+ # min.log
212
+
213
+ class Brent < Unidimensional
214
+ GSL_SQRT_DBL_EPSILON=1.4901161193847656e-08
215
+ def initialize(lower,upper, proc)
216
+ super
217
+
218
+ @do_bracketing=true
219
+
220
+ # Init
221
+
222
+ golden = 0.3819660; #golden = (3 - sqrt(5))/2
223
+
224
+ v = @lower + golden * (@upper - @lower);
225
+ w = v;
226
+
227
+ @x_minimum = v ;
228
+ @f_minimum = f(v) ;
229
+ @x_lower=@lower
230
+ @x_upper=@upper
231
+ @f_lower = f(@lower) ;
232
+ @f_upper = f(@lower) ;
233
+
234
+ @v = v;
235
+ @w = w;
236
+
237
+ @d = 0;
238
+ @e = 0;
239
+ @f_v=f(v)
240
+ @f_w=@f_v
241
+ end
242
+
243
+ def expected=(v)
244
+ @x_minimum=v
245
+ @f_minimum=f(v)
246
+ @do_bracketing=false
133
247
  end
134
248
 
135
- # Direct port of Brent algorithm found on GSL
136
- # min=Minimization::Brent.new(-1000,20000 , proc {|x| (x+1)**2}
137
- # min.expected=1.5 # Expected value
138
- # min.iterate
139
- # min.x_minimum
140
- # min.f_minimum
141
- # min.log
142
-
143
- class Brent < Unidimensional
144
- GSL_SQRT_DBL_EPSILON=1.4901161193847656e-08
145
- def initialize(lower,upper, proc)
146
- super
147
-
148
- @do_bracketing=true
149
-
150
- # Init
151
-
152
- golden = 0.3819660; #golden = (3 - sqrt(5))/2
153
-
154
- v = @lower + golden * (@upper - @lower);
155
- w = v;
156
-
157
- @x_minimum = v ;
158
- @f_minimum = f(v) ;
159
- @x_lower=@lower
160
- @x_upper=@upper
161
- @f_lower = f(@lower) ;
162
- @f_upper = f(@lower) ;
163
-
164
- @v = v;
165
- @w = w;
166
-
167
- @d = 0;
168
- @e = 0;
169
- @f_v=f(v)
170
- @f_w=@f_v
171
- end
172
-
173
- def expected=(v)
174
- @x_minimum=v
175
- @f_minimum=f(v)
176
- @do_bracketing=false
249
+ def bracketing
250
+ eval_max=10
251
+ f_left = @f_lower;
252
+ f_right = @f_upper;
253
+ x_left = @x_lower;
254
+ x_right= @x_upper;
255
+ golden = 0.3819660; # golden = (3 - sqrt(5))/2 */
256
+ nb_eval=0
257
+
258
+ if (f_right >= f_left)
259
+ x_center = (x_right - x_left) * golden + x_left;
260
+ nb_eval+=1;
261
+ f_center=f(x_center)
262
+ else
263
+ x_center = x_right ;
264
+ f_center = f_right ;
265
+ x_right = (x_center - x_left).quo(golden) + x_left;
266
+ nb_eval+=1;
267
+ f_right=f(x_right);
177
268
  end
178
- def bracketing
179
- eval_max=10
180
- f_left = @f_lower;
181
- f_right = @f_upper;
182
- x_left = @x_lower;
183
- x_right= @x_upper;
184
- golden = 0.3819660; # golden = (3 - sqrt(5))/2 */
185
- nb_eval=0
186
-
187
- if (f_right >= f_left)
188
- x_center = (x_right - x_left) * golden + x_left;
189
- nb_eval+=1;
190
- f_center=f(x_center)
191
- else
192
- x_center = x_right ;
193
- f_center = f_right ;
194
- x_right = (x_center - x_left).quo(golden) + x_left;
195
- nb_eval+=1;
196
- f_right=f(x_right);
197
- end
198
-
199
-
200
- begin
201
- @log+=sprintf("B%d: [%0.5f - %0.5f] -> [%0.5f - %0.5f] E: %0.6f\n", nb_eval, x_left, x_right, f_left, f_right, (x_left-x_right).abs)
202
- if (f_center < f_left )
203
- if (f_center < f_right)
204
- @x_lower = x_left;
205
- @x_upper = x_right;
206
- @x_minimum = x_center;
207
- @f_lower = f_left;
208
- @f_upper = f_right;
209
- @f_minimum = f_center;
210
- return true;
211
- elsif (f_center > f_right)
212
- x_left = x_center;
213
- f_left = f_center;
214
- x_center = x_right;
215
- f_center = f_right;
216
- x_right = (x_center - x_left).quo(golden) + x_left;
217
- nb_eval+=1;
218
- f_right=f(x_right);
219
- else # f_center == f_right */
220
- x_right = x_center;
221
- f_right = f_center;
222
- x_center = (x_right - x_left).quo(golden) + x_left;
223
- nb_eval+=1;
224
- f_center=f(x_center);
225
- end
226
- else # f_center >= f_left */
269
+
270
+
271
+ begin
272
+ @log << ["B#{nb_eval}", x_left, x_right, f_left, f_right, (x_left-x_right).abs, (f_left-f_right).abs]
273
+ if (f_center < f_left )
274
+ if (f_center < f_right)
275
+ @x_lower = x_left;
276
+ @x_upper = x_right;
277
+ @x_minimum = x_center;
278
+ @f_lower = f_left;
279
+ @f_upper = f_right;
280
+ @f_minimum = f_center;
281
+ return true;
282
+ elsif (f_center > f_right)
283
+ x_left = x_center;
284
+ f_left = f_center;
285
+ x_center = x_right;
286
+ f_center = f_right;
287
+ x_right = (x_center - x_left).quo(golden) + x_left;
288
+ nb_eval+=1;
289
+ f_right=f(x_right);
290
+ else # f_center == f_right */
227
291
  x_right = x_center;
228
292
  f_right = f_center;
229
- x_center = (x_right - x_left) * golden + x_left;
293
+ x_center = (x_right - x_left).quo(golden) + x_left;
230
294
  nb_eval+=1;
231
295
  f_center=f(x_center);
232
296
  end
233
- end while ((nb_eval < eval_max) and
234
- ((x_right - x_left) > GSL_SQRT_DBL_EPSILON * ( (x_right + x_left) * 0.5 ) + GSL_SQRT_DBL_EPSILON))
235
- @x_lower = x_left;
236
- @x_upper = x_right;
237
- @x_minimum = x_center;
238
- @f_lower = f_left;
239
- @f_upper = f_right;
240
- @f_minimum = f_center;
241
- return false;
242
-
243
- end
244
- # Start the minimization process
245
- # If you want to control manually the process, use brent_iterate
246
- def iterate
247
- k=0
248
- bracketing if @do_bracketing
249
- while k<@max_iteration and (@x_lower-@x_upper).abs>@epsilon
250
- k+=1
251
- result=brent_iterate
252
- raise "Error on iteration" if !result
253
- @log+=sprintf("%d: [%0.5f - %0.5f] -> [%0.5f - %0.5f] E: %0.6f\n", k, @x_lower, @x_upper, @f_lower, @f_upper, (@x_lower-@x_upper).abs)
297
+ else # f_center >= f_left */
298
+ x_right = x_center;
299
+ f_right = f_center;
300
+ x_center = (x_right - x_left) * golden + x_left;
301
+ nb_eval+=1;
302
+ f_center=f(x_center);
254
303
  end
255
- @iterations=k
256
- return true
257
- end
258
- # Generate one iteration.
259
- def brent_iterate
260
- x_left = @x_lower;
261
- x_right = @x_upper;
262
-
263
- z = @x_minimum;
264
- d = @e;
265
- e = @d;
266
- v = @v;
267
- w = @w;
268
- f_v = @f_v;
269
- f_w = @f_w;
270
- f_z = @f_minimum;
271
-
272
- golden = 0.3819660; # golden = (3 - sqrt(5))/2 */
273
-
274
- w_lower = (z - x_left)
275
- w_upper = (x_right - z)
276
-
277
- tolerance = GSL_SQRT_DBL_EPSILON * z.abs
278
-
279
- midpoint = 0.5 * (x_left + x_right)
280
- _p,q,r=0,0,0
281
- if (e.abs > tolerance)
282
-
283
- # fit parabola */
284
-
285
- r = (z - w) * (f_z - f_v);
286
- q = (z - v) * (f_z - f_w);
287
- _p = (z - v) * q - (z - w) * r;
288
- q = 2 * (q - r);
289
-
290
- if (q > 0)
291
- _p = -_p
292
- else
293
- q = -q;
294
- end
295
- r = e;
296
- e = d;
304
+ end while ((nb_eval < eval_max) and
305
+ ((x_right - x_left) > GSL_SQRT_DBL_EPSILON * ( (x_right + x_left) * 0.5 ) + GSL_SQRT_DBL_EPSILON))
306
+ @x_lower = x_left;
307
+ @x_upper = x_right;
308
+ @x_minimum = x_center;
309
+ @f_lower = f_left;
310
+ @f_upper = f_right;
311
+ @f_minimum = f_center;
312
+ return false;
313
+
314
+ end
315
+ # Start the minimization process
316
+ # If you want to control manually the process, use brent_iterate
317
+ def iterate
318
+ k=0
319
+ bracketing if @do_bracketing
320
+ while k<@max_iteration and (@x_lower-@x_upper).abs>@epsilon
321
+ k+=1
322
+ result=brent_iterate
323
+ raise FailedIteration,"Error on iteration" if !result
324
+ begin
325
+ @log << [k, @x_lower, @x_upper, @f_lower, @f_upper, (@x_lower-@x_upper).abs, (@f_lower-@f_upper).abs]
326
+ rescue =>@e
327
+ @log << [k, @e.to_s,nil,nil,nil,nil,nil]
297
328
  end
298
-
299
- if (_p.abs < (0.5 * q * r).abs and _p < q * w_lower and _p < q * w_upper)
300
- t2 = 2 * tolerance ;
301
-
302
- d = _p.quo(q);
303
- u = z + d;
304
-
305
- if ((u - x_left) < t2 or (x_right - u) < t2)
306
- d = (z < midpoint) ? tolerance : -tolerance ;
307
- end
329
+ end
330
+ @iterations=k
331
+ return true
332
+ end
333
+ # Generate one iteration.
334
+ def brent_iterate
335
+ x_left = @x_lower;
336
+ x_right = @x_upper;
337
+
338
+ z = @x_minimum;
339
+ d = @e;
340
+ e = @d;
341
+ v = @v;
342
+ w = @w;
343
+ f_v = @f_v;
344
+ f_w = @f_w;
345
+ f_z = @f_minimum;
346
+
347
+ golden = 0.3819660; # golden = (3 - sqrt(5))/2 */
348
+
349
+ w_lower = (z - x_left)
350
+ w_upper = (x_right - z)
351
+
352
+ tolerance = GSL_SQRT_DBL_EPSILON * z.abs
353
+
354
+ midpoint = 0.5 * (x_left + x_right)
355
+ _p,q,r=0,0,0
356
+ if (e.abs > tolerance)
357
+
358
+ # fit parabola */
359
+
360
+ r = (z - w) * (f_z - f_v);
361
+ q = (z - v) * (f_z - f_w);
362
+ _p = (z - v) * q - (z - w) * r;
363
+ q = 2 * (q - r);
364
+
365
+ if (q > 0)
366
+ _p = -_p
308
367
  else
309
-
310
- e = (z < midpoint) ? x_right - z : -(z - x_left) ;
311
- d = golden * e;
368
+ q = -q;
312
369
  end
313
-
314
- if ( d.abs >= tolerance)
315
- u = z + d;
370
+ r = e;
371
+ e = d;
372
+ end
373
+
374
+ if (_p.abs < (0.5 * q * r).abs and _p < q * w_lower and _p < q * w_upper)
375
+ t2 = 2 * tolerance ;
376
+
377
+ d = _p.quo(q);
378
+ u = z + d;
379
+
380
+ if ((u - x_left) < t2 or (x_right - u) < t2)
381
+ d = (z < midpoint) ? tolerance : -tolerance ;
382
+ end
383
+ else
384
+
385
+ e = (z < midpoint) ? x_right - z : -(z - x_left) ;
386
+ d = golden * e;
387
+ end
388
+
389
+ if ( d.abs >= tolerance)
390
+ u = z + d;
391
+ else
392
+ u = z + ((d > 0) ? tolerance : -tolerance) ;
393
+ end
394
+
395
+ @e = e;
396
+ @d = d;
397
+
398
+ f_u=f(u)
399
+
400
+ if (f_u <= f_z)
401
+ if (u < z)
402
+ @x_upper = z;
403
+ @f_upper = f_z;
316
404
  else
317
- u = z + ((d > 0) ? tolerance : -tolerance) ;
405
+ @x_lower = z;
406
+ @f_lower = f_z;
318
407
  end
319
-
320
- @e = e;
321
- @d = d;
322
-
323
- f_u=f(u)
324
-
325
- if (f_u <= f_z)
326
- if (u < z)
327
- @x_upper = z;
328
- @f_upper = f_z;
329
- else
330
- @x_lower = z;
331
- @f_lower = f_z;
332
- end
408
+ @v = w;
409
+ @f_v = f_w;
410
+ @w = z;
411
+ @f_w = f_z;
412
+ @x_minimum = u;
413
+ @f_minimum = f_u;
414
+ return true;
415
+ else
416
+ if (u < z)
417
+ @x_lower = u;
418
+ @f_lower = f_u;
419
+ return true;
420
+ else
421
+ @x_upper = u;
422
+ @f_upper = f_u;
423
+ return true;
424
+ end
425
+
426
+ if (f_u <= f_w or w == z)
333
427
  @v = w;
334
428
  @f_v = f_w;
335
- @w = z;
336
- @f_w = f_z;
337
- @x_minimum = u;
338
- @f_minimum = f_u;
429
+ @w = u;
430
+ @f_w = f_u;
431
+ return true;
432
+ elsif f_u <= f_v or v == z or v == w
433
+ @v = u;
434
+ @f_v = f_u;
339
435
  return true;
340
- else
341
- if (u < z)
342
- @x_lower = u;
343
- @f_lower = f_u;
344
- return true;
345
- else
346
- @x_upper = u;
347
- @f_upper = f_u;
348
- return true;
349
- end
350
-
351
- if (f_u <= f_w or w == z)
352
- @v = w;
353
- @f_v = f_w;
354
- @w = u;
355
- @f_w = f_u;
356
- return true;
357
- elsif f_u <= f_v or v == z or v == w
358
- @v = u;
359
- @f_v = f_u;
360
- return true;
361
- end
362
-
363
436
  end
364
- return false
365
-
437
+
366
438
  end
439
+ return false
440
+
367
441
  end
368
442
  end
443
+ end
@@ -0,0 +1,62 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ describe Minimization::Unidimensional, "subclass" do
3
+ before(:all) do
4
+ @p1=rand(100)
5
+ @p2=rand(100)
6
+ @func=lambda {|x| (x-@p1)**2+@p2}
7
+ @funcd=lambda {|x| 2*(x-@p1)}
8
+ @funcdd=lambda {|x| 2}
9
+ end
10
+
11
+ describe Minimization::NewtonRaphson do
12
+ before do
13
+ @min = Minimization::NewtonRaphson.new(-1000,1000, @func,@funcd, @funcdd)
14
+ @min.iterate
15
+ end
16
+ it "#x_minimum be close to expected" do
17
+ @min.x_minimum.should be_close(@p1,@min.epsilon)
18
+ end
19
+ it "#f_minimum ( f(x)) be close to expected" do
20
+ @min.f_minimum.should be_close(@p2,@min.epsilon)
21
+ end
22
+ context "#log" do
23
+ subject {@min.log}
24
+ it {should be_instance_of Array}
25
+ it {should respond_to :to_table}
26
+ end
27
+ end
28
+
29
+
30
+ describe Minimization::GoldenSection do
31
+ before do
32
+ @min = Minimization::GoldenSection.minimize(-1000,1000, &@func)
33
+ end
34
+ it "#x_minimum be close to expected" do
35
+ @min.x_minimum.should be_close(@p1,@min.epsilon)
36
+ end
37
+ it "#f_minimum ( f(x)) be close to expected" do
38
+ @min.f_minimum.should be_close(@p2,@min.epsilon)
39
+ end
40
+ context "#log" do
41
+ subject {@min.log}
42
+ it {should be_instance_of Array}
43
+ it {should respond_to :to_table}
44
+ end
45
+ end
46
+ describe Minimization::Brent do
47
+ before do
48
+ @min = Minimization::Brent.minimize(-1000,1000, &@func)
49
+ end
50
+ it "should x be correct" do
51
+ @min.x_minimum.should be_close(@p1,@min.epsilon)
52
+ end
53
+ it "should f(x) be correct" do
54
+ @min.f_minimum.should be_close(@p2,@min.epsilon)
55
+ end
56
+ context "#log" do
57
+ subject {@min.log}
58
+ it {should be_instance_of Array}
59
+ it {should respond_to :to_table}
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,2 @@
1
+ --color
2
+ -f s
@@ -0,0 +1,15 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'minimization.rb'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
10
+
11
+ class String
12
+ def deindent
13
+ gsub /^[ \t]*/, ''
14
+ end
15
+ end
metadata CHANGED
@@ -1,17 +1,58 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minimization
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claudio Bustos
8
8
  autorequire:
9
9
  bindir: bin
10
- cert_chain: []
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDMjCCAhqgAwIBAgIBADANBgkqhkiG9w0BAQUFADA/MREwDwYDVQQDDAhjbGJ1
14
+ c3RvczEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
15
+ MB4XDTEwMDMyOTIxMzg1NVoXDTExMDMyOTIxMzg1NVowPzERMA8GA1UEAwwIY2xi
16
+ dXN0b3MxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
17
+ bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf8JVMGqE7m5kYb+PNN
18
+ neZv2pcXV5fQCi6xkyG8bi2/SIFy/LyxuvLzEeOxBeaz1Be93bayIUquOIqw3dyw
19
+ /KXWa31FxuNuvAm6CN8fyeRYX/ou4cw3OIUUnIvB7RMNIu4wbgeM6htV/QEsNLrv
20
+ at1/mh9JpqawPrcjIOVMj4BIp67vmzJCaUf+S/H2uYtSO09F+YQE3tv85TPeRmqU
21
+ yjyXyTc/oJiw1cXskUL8UtMWZmrwNLHXuZWWIMzkjiz3UNdhJr/t5ROk8S2WPznl
22
+ 0bMy/PMIlAbqWolRn1zl2VFJ3TaXScbqImY8Wf4g62b/1ZSUlGrtnLNsCYXrWiso
23
+ UPUCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFGu9
24
+ rrJ1H64qRmNNu3Jj/Qjvh0u5MA0GCSqGSIb3DQEBBQUAA4IBAQCV0Unka5isrhZk
25
+ GjqSDqY/6hF+G2pbFcbWUpjmC8NWtAxeC+7NGV3ljd0e1SLfoyBj4gnFtFmY8qX4
26
+ K02tgSZM0eDV8TpgFpWXzK6LzHvoanuahHLZEtk/+Z885lFene+nHadkem1n9iAB
27
+ cs96JO9/JfFyuXM27wFAwmfHCmJfPF09R4VvGHRAvb8MGzSVgk2i06OJTqkBTwvv
28
+ JHJdoyw3+8bw9RJ+jLaNoQ+xu+1pQdS2bb3m7xjZpufml/m8zFCtjYM/7qgkKR8z
29
+ /ZZt8lCiKfFArppRrZayE2FVsps4X6WwBdrKTMZ0CKSXTRctbEj1BAZ67eoTvBBt
30
+ rpP0jjs0
31
+ -----END CERTIFICATE-----
11
32
 
12
- date: 2010-03-19 00:00:00 -03:00
33
+ date: 2010-04-15 00:00:00 -04:00
13
34
  default_executable:
14
35
  dependencies:
36
+ - !ruby/object:Gem::Dependency
37
+ name: text-table
38
+ type: :runtime
39
+ version_requirement:
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: "1.2"
45
+ version:
46
+ - !ruby/object:Gem::Dependency
47
+ name: rubyforge
48
+ type: :development
49
+ version_requirement:
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 2.0.4
55
+ version:
15
56
  - !ruby/object:Gem::Dependency
16
57
  name: hoe
17
58
  type: :development
@@ -20,7 +61,7 @@ dependencies:
20
61
  requirements:
21
62
  - - ">="
22
63
  - !ruby/object:Gem::Version
23
- version: 2.4.0
64
+ version: 2.6.0
24
65
  version:
25
66
  description: Minimization algorithms on pure Ruby.
26
67
  email:
@@ -41,7 +82,9 @@ files:
41
82
  - README.txt
42
83
  - Rakefile
43
84
  - lib/minimization.rb
44
- - test/test_minimization.rb
85
+ - spec/minimization_unidimensional_spec.rb
86
+ - spec/spec.opts
87
+ - spec/spec_helper.rb
45
88
  has_rdoc: true
46
89
  homepage: http://ruby-statsample.rubyforge.org/
47
90
  licenses: []
@@ -71,5 +114,5 @@ rubygems_version: 1.3.5
71
114
  signing_key:
72
115
  specification_version: 3
73
116
  summary: Minimization algorithms on pure Ruby.
74
- test_files:
75
- - test/test_minimization.rb
117
+ test_files: []
118
+
@@ -0,0 +1,3 @@
1
+ b��G4B ���1њ�h��r5vt���Ԯ�ᗅ�~Nӫ�&
2
+ H ,����9! �\m�_�L��]6����i�*��3)�'���&�����~{`-z�,V ���"u"��C�|�PBpۢ�%5 �~Z��<\��f�dC�rj��v^�
3
+ �x�[D��Ù���Pځ�`��"CE�� ����E'4%�!?�O��_��p
@@ -1,28 +0,0 @@
1
- $:.unshift(File.dirname(__FILE__)+'/../lib/')
2
- require "test/unit"
3
- require "minimization"
4
-
5
- class TestMinimization < Test::Unit::TestCase
6
- def setup
7
- @p1=rand(100)
8
- @p2=rand(100)
9
- @func=lambda {|x| (x-@p1)**2+@p2}
10
- end
11
- def test_facade
12
- min=Minimization::GoldenSection.minimize(-1000,1000) {|x| (x-@p1)**2+@p2}
13
- assert_in_delta(@p1,min.x_minimum, min.epsilon)
14
- assert_in_delta(@p2,min.f_minimum, min.epsilon)
15
- end
16
- def test_golden
17
- min=Minimization::GoldenSection.new(-1000,1000, @func)
18
- min.iterate
19
- assert_in_delta(@p1, min.x_minimum, min.epsilon)
20
- assert_in_delta(@p2, min.f_minimum, min.epsilon)
21
- end
22
- def test_brent
23
- min=Minimization::Brent.new(-1000,1000, @func)
24
- min.iterate
25
- assert_in_delta(@p1, min.x_minimum, min.epsilon)
26
- assert_in_delta(@p2, min.f_minimum, min.epsilon)
27
- end
28
- end