BOAST 1.0.9 → 1.1.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/BOAST.gemspec +1 -1
- data/lib/BOAST.rb +5 -1
- data/lib/BOAST/Language/Algorithm.rb +104 -22
- data/lib/BOAST/Language/Annotation.rb +55 -0
- data/lib/BOAST/Language/Arithmetic.rb +44 -10
- data/lib/BOAST/Language/Case.rb +89 -52
- data/lib/BOAST/Language/CodeBlock.rb +17 -0
- data/lib/BOAST/Language/Comment.rb +38 -0
- data/lib/BOAST/Language/ControlStructure.rb +7 -0
- data/lib/BOAST/Language/Error.rb +7 -0
- data/lib/BOAST/Language/Expression.rb +4 -5
- data/lib/BOAST/Language/For.rb +59 -27
- data/lib/BOAST/Language/If.rb +12 -17
- data/lib/BOAST/Language/Index.rb +5 -5
- data/lib/BOAST/Language/Intrinsics.rb +38 -32
- data/lib/BOAST/Language/OpenMP.rb +1 -1
- data/lib/BOAST/Language/Operators.rb +208 -53
- data/lib/BOAST/Language/Pragma.rb +3 -3
- data/lib/BOAST/Language/Print.rb +3 -3
- data/lib/BOAST/Language/Procedure.rb +15 -8
- data/lib/BOAST/Language/Variable.rb +45 -87
- data/lib/BOAST/Language/While.rb +3 -0
- data/lib/BOAST/Optimization/Optimization.rb +241 -0
- metadata +7 -4
- data/lib/BOAST/Language/Optimization.rb +0 -74
- data/lib/BOAST/Language/Vector.rb +0 -6
@@ -4,6 +4,8 @@ module BOAST
|
|
4
4
|
include PrivateStateAccessor
|
5
5
|
include Inspectable
|
6
6
|
extend Functor
|
7
|
+
include Annotation
|
8
|
+
ANNOTATIONS = [ :name, :parameters, :constants ]
|
7
9
|
|
8
10
|
attr_reader :name
|
9
11
|
attr_reader :parameters
|
@@ -214,21 +216,22 @@ module BOAST
|
|
214
216
|
s += ")"
|
215
217
|
end
|
216
218
|
|
217
|
-
def pr_align
|
218
|
-
end
|
219
|
-
|
220
219
|
def open_c
|
221
220
|
s = indent + decl_c_s + "{"
|
222
221
|
output.puts s
|
223
222
|
increment_indent_level
|
224
223
|
constants.each { |c|
|
225
|
-
c
|
224
|
+
BOAST::decl c
|
226
225
|
}
|
227
226
|
if lang == C then
|
228
227
|
parameters.each { |p|
|
229
|
-
p.
|
228
|
+
align = p.align
|
229
|
+
BOAST::pr align if align
|
230
230
|
}
|
231
231
|
end
|
232
|
+
if @properties[:return] then
|
233
|
+
BOAST::decl @properties[:return]
|
234
|
+
end
|
232
235
|
return self
|
233
236
|
end
|
234
237
|
|
@@ -239,12 +242,16 @@ module BOAST
|
|
239
242
|
s += indent + "integer, parameter :: wp=kind(1.0d0)"
|
240
243
|
output.puts s
|
241
244
|
constants.each { |c|
|
242
|
-
c
|
245
|
+
BOAST::decl c
|
243
246
|
}
|
244
247
|
parameters.each { |p|
|
245
|
-
p
|
246
|
-
p.
|
248
|
+
BOAST::decl p
|
249
|
+
align = p.align
|
250
|
+
BOAST::pr align if align
|
247
251
|
}
|
252
|
+
if @properties[:return] then
|
253
|
+
BOAST::decl @properties[:return]
|
254
|
+
end
|
248
255
|
return self
|
249
256
|
end
|
250
257
|
|
@@ -13,7 +13,11 @@ module BOAST
|
|
13
13
|
if v1 then
|
14
14
|
if v2 then
|
15
15
|
#@size = Expression::new(Substraction, v2, v1) + 1
|
16
|
-
|
16
|
+
begin
|
17
|
+
@size = v2-v1+1
|
18
|
+
rescue
|
19
|
+
@size = Expression::new(Substraction, v2, v1) + 1
|
20
|
+
end
|
17
21
|
else
|
18
22
|
@size = v1
|
19
23
|
end
|
@@ -29,8 +33,10 @@ module BOAST
|
|
29
33
|
return "#{@val1}:#{@val2}"
|
30
34
|
elsif lang == FORTRAN and get_array_start != 1 then
|
31
35
|
return "#{get_array_start}:#{@size-(1+get_array_start)}"
|
36
|
+
elsif lang == FORTRAN and size.nil?
|
37
|
+
return "*"
|
32
38
|
else
|
33
|
-
return @size
|
39
|
+
return @size.to_s
|
34
40
|
end
|
35
41
|
end
|
36
42
|
|
@@ -47,13 +53,17 @@ module BOAST
|
|
47
53
|
return @val2
|
48
54
|
elsif @size
|
49
55
|
if 0.equal?(get_array_start) then
|
56
|
+
return @size - 1
|
57
|
+
else
|
50
58
|
if 1.equal?(get_array_start) then
|
51
|
-
return Expression::new(Addition, @size, get_array_start) - 1
|
52
|
-
else
|
53
59
|
return @size
|
60
|
+
else
|
61
|
+
begin
|
62
|
+
return @size + get_array_start - 1
|
63
|
+
rescue
|
64
|
+
return Expression::new(Addition, @size, get_array_start) - 1
|
65
|
+
end
|
54
66
|
end
|
55
|
-
else
|
56
|
-
return Expression::new(Substraction, @size, 1)
|
57
67
|
end
|
58
68
|
else
|
59
69
|
return nil
|
@@ -115,6 +125,8 @@ module BOAST
|
|
115
125
|
include Arithmetic
|
116
126
|
include Inspectable
|
117
127
|
extend Functor
|
128
|
+
include Annotation
|
129
|
+
ANNOTATIONS = [ :name, :type, :dimension ]
|
118
130
|
|
119
131
|
alias_method :orig_method_missing, :method_missing
|
120
132
|
|
@@ -146,7 +158,7 @@ module BOAST
|
|
146
158
|
attr_reader :restrict
|
147
159
|
attr_reader :deferred_shape
|
148
160
|
attr_reader :optional
|
149
|
-
attr_accessor :
|
161
|
+
attr_accessor :alignment
|
150
162
|
attr_accessor :replace_constant
|
151
163
|
attr_accessor :force_replace_constant
|
152
164
|
|
@@ -191,7 +203,7 @@ module BOAST
|
|
191
203
|
end
|
192
204
|
|
193
205
|
def align?
|
194
|
-
!!@
|
206
|
+
!!@alignment
|
195
207
|
end
|
196
208
|
|
197
209
|
def deferred_shape?
|
@@ -207,7 +219,7 @@ module BOAST
|
|
207
219
|
@texture = hash[:texture]
|
208
220
|
@allocate = hash[:allocate]
|
209
221
|
@restrict = hash[:restrict]
|
210
|
-
@
|
222
|
+
@alignment = hash[:align]
|
211
223
|
@deferred_shape = hash[:deferred_shape]
|
212
224
|
@optional = hash[:optional]
|
213
225
|
@force_replace_constant = false
|
@@ -271,8 +283,7 @@ module BOAST
|
|
271
283
|
|
272
284
|
def dereference
|
273
285
|
return copy("*(#{name})", :dimension => nil, :dim => nil, :direction => nil, :dir => nil) if [C, CL, CUDA].include?( lang )
|
274
|
-
return self if lang == FORTRAN
|
275
|
-
#return Expression::new("*",nil,self)
|
286
|
+
return Index::new(self, *(@dimension.collect { |d| d.start } ) ) if lang == FORTRAN
|
276
287
|
end
|
277
288
|
|
278
289
|
def struct_reference(x)
|
@@ -285,7 +296,7 @@ module BOAST
|
|
285
296
|
end
|
286
297
|
|
287
298
|
def [](*args)
|
288
|
-
return Index::new(self
|
299
|
+
return Index::new(self,*args)
|
289
300
|
end
|
290
301
|
|
291
302
|
def finalize
|
@@ -310,12 +321,7 @@ module BOAST
|
|
310
321
|
if dimension? and use_vla? and lang != FORTRAN then
|
311
322
|
s += "["
|
312
323
|
s += @dimension.reverse.collect { |d|
|
313
|
-
|
314
|
-
if dim then
|
315
|
-
dim.to_s
|
316
|
-
else
|
317
|
-
""
|
318
|
-
end
|
324
|
+
d.to_s
|
319
325
|
}.join("][")
|
320
326
|
s += "]"
|
321
327
|
end
|
@@ -386,12 +392,7 @@ module BOAST
|
|
386
392
|
s += " #{@name}["
|
387
393
|
s += "__restrict__ " if __restrict?
|
388
394
|
s += @dimension.reverse.collect { |d|
|
389
|
-
|
390
|
-
if dim then
|
391
|
-
dim.to_s
|
392
|
-
else
|
393
|
-
""
|
394
|
-
end
|
395
|
+
d.to_s
|
395
396
|
}.join("][")
|
396
397
|
s += "]"
|
397
398
|
else
|
@@ -413,8 +414,8 @@ module BOAST
|
|
413
414
|
s +=")]"
|
414
415
|
end
|
415
416
|
end
|
416
|
-
if __align? then
|
417
|
-
a = ( align? ?
|
417
|
+
if __align? and lang != CUDA then
|
418
|
+
a = ( align? ? alignment : 1 )
|
418
419
|
a = ( a >= default_align ? a : default_align )
|
419
420
|
s+= " __attribute((aligned(#{a})))"
|
420
421
|
end
|
@@ -423,7 +424,7 @@ module BOAST
|
|
423
424
|
end
|
424
425
|
|
425
426
|
def decl_texture_s
|
426
|
-
raise "Unsupported language #{lang} for texture!" if not [CL, CUDA].include?( lang )
|
427
|
+
raise LanguageError, "Unsupported language #{lang} for texture!" if not [CL, CUDA].include?( lang )
|
427
428
|
raise "Write is unsupported for textures!" if not (constant? or @direction == :in)
|
428
429
|
dim_number = 1
|
429
430
|
if dimension? then
|
@@ -454,69 +455,39 @@ module BOAST
|
|
454
455
|
return self
|
455
456
|
end
|
456
457
|
|
457
|
-
def
|
458
|
-
return "__assume_aligned
|
459
|
-
end
|
460
|
-
|
461
|
-
def pr_align_c(a)
|
462
|
-
s = ""
|
463
|
-
s += indent
|
464
|
-
s += pr_align_c_s(a)
|
465
|
-
s += finalize
|
466
|
-
output.print s
|
467
|
-
return self
|
458
|
+
def align_c(a)
|
459
|
+
return FuncCall::new("__assume_aligned", @name, a)
|
468
460
|
end
|
469
461
|
|
470
|
-
def
|
471
|
-
return "
|
462
|
+
def align_fortran(a)
|
463
|
+
return Pragma::new("DIR", "ASSUME_ALIGNED", "#{@name}: #{a}")
|
472
464
|
end
|
473
465
|
|
474
|
-
def
|
475
|
-
s = ""
|
476
|
-
s += indent
|
477
|
-
s += pr_align_fortran_s(a)
|
478
|
-
s += finalize
|
479
|
-
output.print s
|
480
|
-
return self
|
481
|
-
end
|
482
|
-
|
483
|
-
def pr_align
|
466
|
+
def align
|
484
467
|
if dimension? then
|
485
468
|
if align? or default_align > 1 then
|
486
|
-
a = ( align? ?
|
469
|
+
a = ( align? ? alignment : 1 )
|
487
470
|
a = ( a >= default_align ? a : default_align )
|
488
|
-
return
|
489
|
-
return
|
471
|
+
return align_c(a) if lang == C
|
472
|
+
return align_fortran(a) if lang == FORTRAN
|
490
473
|
end
|
491
474
|
end
|
475
|
+
return nil
|
492
476
|
end
|
493
477
|
|
494
478
|
def alloc_fortran( dims = nil )
|
495
|
-
|
496
|
-
s += indent
|
497
|
-
s += "allocate( #{name}("
|
498
|
-
s += dims.collect { |d| d.to_s }.join(", ")
|
499
|
-
s += ") )"
|
500
|
-
s += finalize
|
501
|
-
output.print s
|
502
|
-
return self
|
479
|
+
return FuncCall::new(:allocate, FuncCall(name, * dims ) )
|
503
480
|
end
|
504
481
|
|
505
482
|
def alloc_c( dims = nil, align = get_address_size)
|
506
|
-
|
507
|
-
s += indent
|
483
|
+
d = dims.collect { |d| d.to_s }.reverse.join(")*(")
|
508
484
|
if align > (OS.bits/8) then
|
509
485
|
# check alignment is a power of 2
|
510
486
|
raise "Invalid alignment #{align}!" if align & (align - 1) != 0
|
511
|
-
|
487
|
+
return FuncCall::new(:posix_memalign, self.address, align, FuncCall::new(:sizeof, @type.decl) * d)
|
512
488
|
else
|
513
|
-
|
489
|
+
return self === FuncCall::new(:malloc, FuncCall::new(:sizeof, @type.decl) * d).cast(self)
|
514
490
|
end
|
515
|
-
s += dims.collect { |d| d.to_s }.reverse.join(")*(")
|
516
|
-
s += ") )"
|
517
|
-
s += finalize
|
518
|
-
output.print s
|
519
|
-
return self
|
520
491
|
end
|
521
492
|
|
522
493
|
def alloc( dims = nil, align = get_address_size )
|
@@ -528,21 +499,11 @@ module BOAST
|
|
528
499
|
end
|
529
500
|
|
530
501
|
def dealloc_fortran
|
531
|
-
|
532
|
-
s += indent
|
533
|
-
s += "deallocate( #{name} )"
|
534
|
-
s += finalize
|
535
|
-
output.print s
|
536
|
-
return self
|
502
|
+
return FuncCall::new(:deallocate, self)
|
537
503
|
end
|
538
504
|
|
539
505
|
def dealloc_c
|
540
|
-
|
541
|
-
s += indent
|
542
|
-
s += "free( #{name} )"
|
543
|
-
s += finalize
|
544
|
-
output.print s
|
545
|
-
return self
|
506
|
+
return FuncCall::new(:free, self)
|
546
507
|
end
|
547
508
|
|
548
509
|
def dealloc
|
@@ -561,13 +522,10 @@ module BOAST
|
|
561
522
|
if dimension? then
|
562
523
|
s += ", dimension("
|
563
524
|
s += @dimension.collect { |d|
|
564
|
-
dim = d.to_s
|
565
525
|
if deferred_shape? or ( allocate? and @allocate == :heap )
|
566
526
|
":"
|
567
|
-
elsif dim then
|
568
|
-
dim.to_s
|
569
527
|
else
|
570
|
-
|
528
|
+
d.to_s
|
571
529
|
end
|
572
530
|
}.join(", ")
|
573
531
|
s += ")"
|
@@ -581,7 +539,7 @@ module BOAST
|
|
581
539
|
s += finalize
|
582
540
|
output.print s
|
583
541
|
if dimension? and (align? or default_align > 1) and (constant? or ( allocate? and @allocate != :heap ) ) then
|
584
|
-
a = ( align? ?
|
542
|
+
a = ( align? ? alignment : 1 )
|
585
543
|
a = ( a >= default_align ? a : default_align )
|
586
544
|
s = ""
|
587
545
|
s += indent
|
data/lib/BOAST/Language/While.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
module BOAST
|
2
2
|
|
3
3
|
class While < ControlStructure
|
4
|
+
include Annotation
|
5
|
+
ANNOTATIONS = [ :condition ]
|
4
6
|
|
5
7
|
attr_reader :condition
|
6
8
|
|
@@ -39,6 +41,7 @@ module BOAST
|
|
39
41
|
end
|
40
42
|
|
41
43
|
def pr(*args)
|
44
|
+
args = @args if args.length == 0 and @args
|
42
45
|
open
|
43
46
|
if @block then
|
44
47
|
@block.call(*args)
|
@@ -0,0 +1,241 @@
|
|
1
|
+
module BOAST
|
2
|
+
|
3
|
+
class OptimizationParameter
|
4
|
+
attr_reader :name
|
5
|
+
attr_reader :values
|
6
|
+
def initialize( name, values )
|
7
|
+
@name = name
|
8
|
+
@values = values
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class BooleanParameter < OptimizationParameter
|
13
|
+
def initialize( name )
|
14
|
+
super( name, [false, true] )
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
OP = OptimizationParameter
|
19
|
+
BP = BooleanParameter
|
20
|
+
|
21
|
+
class OptimizationSpace
|
22
|
+
attr_reader :parameters
|
23
|
+
|
24
|
+
def initialize( *parameters )
|
25
|
+
if parameters.length == 1 and parameters[0].is_a?(Hash) then
|
26
|
+
@parameters = []
|
27
|
+
parameters[0].each { |key, value|
|
28
|
+
@parameters.push( OptimizationParameter::new(key, value) )
|
29
|
+
}
|
30
|
+
else
|
31
|
+
@parameters = parameters
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_h
|
36
|
+
h = {}
|
37
|
+
@parameters.each { |p|
|
38
|
+
h[p.name] = p.values
|
39
|
+
}
|
40
|
+
return h
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
class Optimizer
|
46
|
+
include PrivateStateAccessor
|
47
|
+
attr_reader :experiments
|
48
|
+
attr_reader :search_space
|
49
|
+
attr_reader :log
|
50
|
+
|
51
|
+
def initialize(search_space, options = {} )
|
52
|
+
@search_space = search_space
|
53
|
+
@experiments = 0
|
54
|
+
@log = {}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class GeneticOptimizer < Optimizer
|
59
|
+
|
60
|
+
def initialize(search_space, options = {} )
|
61
|
+
super
|
62
|
+
require 'darwinning'
|
63
|
+
s = <<EOF
|
64
|
+
@organism = Class::new(Darwinning::Organism) do
|
65
|
+
@@block = nil
|
66
|
+
def self.block
|
67
|
+
return @@block
|
68
|
+
end
|
69
|
+
def self.block=(block)
|
70
|
+
@@block = block
|
71
|
+
end
|
72
|
+
@@experiments = 0
|
73
|
+
def self.experiments
|
74
|
+
return @@experiments
|
75
|
+
end
|
76
|
+
def self.experiments=(experiments)
|
77
|
+
@@experiments = experiments
|
78
|
+
end
|
79
|
+
EOF
|
80
|
+
@search_space.parameters.each { |param|
|
81
|
+
s += <<EOF
|
82
|
+
@genes.push( Darwinning::Gene.new(name: #{param.name.inspect}, value_range: #{param.values.inspect}) )
|
83
|
+
EOF
|
84
|
+
}
|
85
|
+
s += <<EOF
|
86
|
+
def initialize(*args)
|
87
|
+
super
|
88
|
+
end
|
89
|
+
|
90
|
+
def fitness
|
91
|
+
return @fitness if @fitness
|
92
|
+
opts = {}
|
93
|
+
genes.each { |gene|
|
94
|
+
opts[gene.name] = genotypes[gene]
|
95
|
+
}
|
96
|
+
@fitness = @@block.call(opts)
|
97
|
+
@@experiments = @@experiments + 1
|
98
|
+
return fitness
|
99
|
+
end
|
100
|
+
|
101
|
+
def to_a
|
102
|
+
opts = {}
|
103
|
+
genes.each { |gene|
|
104
|
+
opts[gene.name] = genotypes[gene]
|
105
|
+
}
|
106
|
+
return [opts, fitness]
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_s
|
110
|
+
return [opts, fitness].to_s
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
EOF
|
115
|
+
eval s
|
116
|
+
end
|
117
|
+
|
118
|
+
def optimize(options={}, &block)
|
119
|
+
opts = { :population_size => 20,
|
120
|
+
:fitness_goal => 0,
|
121
|
+
:generations_limit => 100 }
|
122
|
+
opts.update(options)
|
123
|
+
opts[:organism] = @organism
|
124
|
+
@organism.block = block
|
125
|
+
@organism.experiments = 0
|
126
|
+
population = Darwinning::Population.new(opts)
|
127
|
+
population.evolve!
|
128
|
+
@experiments = @organism.experiments
|
129
|
+
return population.best_member.to_a
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
class BruteForceOptimizer < Optimizer
|
135
|
+
|
136
|
+
def initialize(search_space, options = {} )
|
137
|
+
super
|
138
|
+
@randomize = options[:randomize]
|
139
|
+
end
|
140
|
+
|
141
|
+
def points
|
142
|
+
params2 = @search_space.parameters.dup
|
143
|
+
param = params2.shift
|
144
|
+
pts = param.values.collect { |val| {param.name => val} }
|
145
|
+
if params2.size == 0 then
|
146
|
+
return pts
|
147
|
+
else
|
148
|
+
optim2 = BruteForceOptimizer::new(OptimizationSpace::new(*params2))
|
149
|
+
pts3=[]
|
150
|
+
pts.each{ |p1|
|
151
|
+
optim2.each { |p2|
|
152
|
+
pts3.push(p1.dup.update(p2))
|
153
|
+
}
|
154
|
+
}
|
155
|
+
return pts3
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def each(&block)
|
160
|
+
return self.points.each(&block)
|
161
|
+
end
|
162
|
+
|
163
|
+
def each_random(&block)
|
164
|
+
return self.points.shuffle.each(&block)
|
165
|
+
end
|
166
|
+
|
167
|
+
def optimize(&block)
|
168
|
+
@experiments = 0
|
169
|
+
@log = {}
|
170
|
+
best = [nil, Float::INFINITY]
|
171
|
+
pts = points
|
172
|
+
pts.shuffle! if @randomize
|
173
|
+
pts.each { |config|
|
174
|
+
@experiments += 1
|
175
|
+
metric = block.call(config)
|
176
|
+
@log[config] = metric if optimizer_log
|
177
|
+
best = [config, metric] if metric < best[1]
|
178
|
+
}
|
179
|
+
if optimizer_log_file then
|
180
|
+
File::open(File::basename(optimizer_log_file,".yaml")+".yaml", "w") { |f|
|
181
|
+
f.print YAML::dump(@log)
|
182
|
+
}
|
183
|
+
File::open(File::basename(optimizer_log_file,".yaml")+"_parameters.yaml", "w") { |f|
|
184
|
+
f.print YAML::dump(@search_space.to_h)
|
185
|
+
}
|
186
|
+
end
|
187
|
+
return best
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
class GenericOptimization
|
193
|
+
|
194
|
+
attr_accessor :repeat
|
195
|
+
attr_reader :parameters
|
196
|
+
|
197
|
+
def size
|
198
|
+
return @parameters.size
|
199
|
+
end
|
200
|
+
|
201
|
+
def points
|
202
|
+
params2 = @parameters.dup
|
203
|
+
param = params2.shift
|
204
|
+
pts = param.values.collect { |val| {param.name => val} }
|
205
|
+
if params2.size == 0 then
|
206
|
+
return pts
|
207
|
+
else
|
208
|
+
optim2 = GenericOptimization::new(*params2)
|
209
|
+
pts3=[]
|
210
|
+
pts.each{ |p1|
|
211
|
+
optim2.each { |p2|
|
212
|
+
pts3.push(p1.dup.update(p2))
|
213
|
+
}
|
214
|
+
}
|
215
|
+
return pts3
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def each(&block)
|
220
|
+
return self.points.each(&block)
|
221
|
+
end
|
222
|
+
|
223
|
+
def each_random(&block)
|
224
|
+
return self.points.shuffle.each(&block)
|
225
|
+
end
|
226
|
+
|
227
|
+
def initialize( *parameters )
|
228
|
+
if parameters.length == 1 and parameters[0].is_a?(Hash) then
|
229
|
+
@parameters = []
|
230
|
+
parameters[0].each { |key, value|
|
231
|
+
@parameters.push( OptimizationParameter::new(key, value) )
|
232
|
+
}
|
233
|
+
else
|
234
|
+
@parameters = parameters
|
235
|
+
end
|
236
|
+
@repeat = 3
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|