drp 0.0.6
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.
- data/AUTHORS +6 -0
- data/CHANGES +0 -0
- data/INTRO +309 -0
- data/LICENSE +281 -0
- data/README +77 -0
- data/Rakefile +99 -0
- data/TODO +13 -0
- data/examples/intro/README +2 -0
- data/examples/intro/canvas_example.rb +123 -0
- data/examples/intro/max_depths_example.rb +34 -0
- data/examples/intro/max_depths_example_2.rb +30 -0
- data/examples/intro/odds_and_ends.rb +96 -0
- data/examples/intro/parameterization_example.rb +32 -0
- data/examples/intro/toy_example.rb +22 -0
- data/examples/intro/weight_fcd_example.rb +44 -0
- data/examples/intro/weights_example.rb +33 -0
- data/examples/intro/weights_example_2.rb +30 -0
- data/examples/symbolic_regression.rb +127 -0
- data/lib/defaults.rb +30 -0
- data/lib/drp.rb +30 -0
- data/lib/error.rb +69 -0
- data/lib/info.rb +30 -0
- data/lib/instance_methods.rb +154 -0
- data/lib/pso.rb +178 -0
- data/lib/rule_engine.rb +324 -0
- data/lib/utils.rb +67 -0
- data/lib/weights_and_max_depths.rb +264 -0
- data/test/tc_instance_methods.rb +219 -0
- data/test/tc_max_depths.rb +98 -0
- data/test/tc_utils.rb +60 -0
- data/test/tc_weights.rb +372 -0
- data/test/ts_drp.rb +28 -0
- metadata +80 -0
data/lib/utils.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
|
2
|
+
=begin
|
3
|
+
|
4
|
+
DRP, Genetic Programming + Grammatical Evolution = Directed Ruby Programming
|
5
|
+
Copyright (C) 2006, Christophe McKeon
|
6
|
+
|
7
|
+
This program is free software; you can redistribute it and/or
|
8
|
+
modify it under the terms of the GNU General Public License
|
9
|
+
as published by the Free Software Foundation; either version 2
|
10
|
+
of the License, or (at your option) any later version.
|
11
|
+
|
12
|
+
This program is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU General Public License
|
18
|
+
along with this program; if not, write to the Free Softwar Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
19
|
+
|
20
|
+
=end
|
21
|
+
|
22
|
+
module DRP
|
23
|
+
|
24
|
+
module Utils
|
25
|
+
|
26
|
+
class << self
|
27
|
+
|
28
|
+
def map range, val, function = :linear
|
29
|
+
# this line is necessary in case nil is explicitly passed
|
30
|
+
function = function ? function.to_sym : :linear
|
31
|
+
case function.to_sym
|
32
|
+
|
33
|
+
when :linear, :lin
|
34
|
+
linear_map range, val
|
35
|
+
|
36
|
+
when :i_linear, :i_lin
|
37
|
+
i_linear_map range, val
|
38
|
+
|
39
|
+
else
|
40
|
+
raise ArgumentError, "bad function for range: #{function}", caller
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def linear_map range, val
|
47
|
+
first, last = range.first, range.last
|
48
|
+
diff = last - first
|
49
|
+
diff * val + first
|
50
|
+
end
|
51
|
+
|
52
|
+
def i_linear_map range, val
|
53
|
+
first, last = range.first, range.last
|
54
|
+
distance = (last - first).to_i.abs + 1
|
55
|
+
i = (distance * val).floor
|
56
|
+
if first < last
|
57
|
+
first + i
|
58
|
+
else
|
59
|
+
first - i
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end # class << self
|
64
|
+
|
65
|
+
end # module Utils
|
66
|
+
|
67
|
+
end # module DRP
|
@@ -0,0 +1,264 @@
|
|
1
|
+
|
2
|
+
=begin
|
3
|
+
|
4
|
+
DRP, Genetic Programming + Grammatical Evolution = Directed Ruby Programming
|
5
|
+
Copyright (C) 2006, Christophe McKeon
|
6
|
+
|
7
|
+
This program is free software; you can redistribute it and/or
|
8
|
+
modify it under the terms of the GNU General Public License
|
9
|
+
as published by the Free Software Foundation; either version 2
|
10
|
+
of the License, or (at your option) any later version.
|
11
|
+
|
12
|
+
This program is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU General Public License
|
18
|
+
along with this program; if not, write to the Free Softwar Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
19
|
+
|
20
|
+
=end
|
21
|
+
|
22
|
+
module DRP
|
23
|
+
|
24
|
+
module MaxDepths
|
25
|
+
|
26
|
+
# the max_depth classes are stored in class variables
|
27
|
+
# and are passed an instance of the extended user class
|
28
|
+
# so that they can ask for codons if they need them.
|
29
|
+
# they need not be copied like weights because they are
|
30
|
+
# only run once at instance initialization
|
31
|
+
|
32
|
+
class StaticMaxDepth
|
33
|
+
def initialize int
|
34
|
+
@value = int.to_i
|
35
|
+
end
|
36
|
+
def value drp_instance_unused
|
37
|
+
@value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class MappedMaxDepth
|
42
|
+
def initialize range, function = :i_linear
|
43
|
+
@range, @function = range, function
|
44
|
+
end
|
45
|
+
def value drp_instance
|
46
|
+
Utils::map(
|
47
|
+
@range,
|
48
|
+
drp_instance.next_meta_codon,
|
49
|
+
@function
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class ProcMaxDepth
|
55
|
+
def initialize proc
|
56
|
+
@proc, @arity = proc, proc.arity
|
57
|
+
end
|
58
|
+
def value drp_instance
|
59
|
+
if @arity <= 0
|
60
|
+
@proc.call.to_i
|
61
|
+
elsif @arity == 1
|
62
|
+
@proc.call(drp_instance.next_meta_codon).to_i
|
63
|
+
else
|
64
|
+
@proc.call(*Array.new(@arity) { drp_instance.next_meta_codon }).to_i
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end # module MaxDepths
|
70
|
+
|
71
|
+
module Weights
|
72
|
+
|
73
|
+
# user args can be array or proc
|
74
|
+
WeightArgs = Struct.new :user_args, :rule_method, :drp_instance
|
75
|
+
|
76
|
+
class AbstractWeight
|
77
|
+
def self.factory args_or_proc
|
78
|
+
proc do |rule_method, drp_instance|
|
79
|
+
self.new WeightArgs.new(args_or_proc, rule_method, drp_instance)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
=begin
|
85
|
+
weight 10.0 static weight
|
86
|
+
weight 0..1 static mapped
|
87
|
+
weight 0..1, :function static mapped w/ function
|
88
|
+
weight {} static proc gets codons
|
89
|
+
=end
|
90
|
+
|
91
|
+
class StaticWeight < AbstractWeight
|
92
|
+
attr_reader :value
|
93
|
+
def initialize args
|
94
|
+
user_args = args.user_args
|
95
|
+
sz = user_args.size
|
96
|
+
case sz
|
97
|
+
when 1
|
98
|
+
arg = user_args[0]
|
99
|
+
case arg
|
100
|
+
when Numeric
|
101
|
+
@value = arg.to_f
|
102
|
+
when Range
|
103
|
+
@value = Utils::map(
|
104
|
+
arg,
|
105
|
+
args.drp_instance.next_meta_codon
|
106
|
+
)
|
107
|
+
else
|
108
|
+
raise ArgumentError, 'when 1 arg given to weight, must be Numeric, or Range', caller
|
109
|
+
end
|
110
|
+
when 2
|
111
|
+
rng = args[0]
|
112
|
+
func = args[1].to_sym
|
113
|
+
if (rng.kind_of? Range) && (func.kind_of? Symbol)
|
114
|
+
@value = Utils::map(
|
115
|
+
rng,
|
116
|
+
args.drp_instance.next_meta_codon,
|
117
|
+
func
|
118
|
+
)
|
119
|
+
else
|
120
|
+
raise ArgumentError, 'weight args of wrong types'
|
121
|
+
end
|
122
|
+
else
|
123
|
+
raise ArgumentError, "weight takes 1 or 2 args, #{sz} given"
|
124
|
+
end # case user_args.size
|
125
|
+
end # def initialize
|
126
|
+
end
|
127
|
+
|
128
|
+
class ProcStaticWeight < StaticWeight
|
129
|
+
def initialize args
|
130
|
+
proc = args.user_args
|
131
|
+
ar = proc.arity
|
132
|
+
inst = args.drp_instance
|
133
|
+
if ar <= 0
|
134
|
+
@value = proc.call
|
135
|
+
elsif ar == 1
|
136
|
+
@value = proc.call inst.next_meta_codon
|
137
|
+
else
|
138
|
+
@value = proc.call *Array.new(ar) { inst.next_meta_codon }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
=begin
|
144
|
+
weight_dyn 0..1 codon maps to range for every rule method choice
|
145
|
+
weight_dyn 0..1, :function same but using function
|
146
|
+
weight_dyn 0..1, 0..1 initial min and max determined by metacodons
|
147
|
+
and further runtime mapping also
|
148
|
+
weight_dyn 0..1, 0..1, :function same but function used for runtime mapping
|
149
|
+
weight_dyn { |codon| } same but using use block, gets meta_codons
|
150
|
+
=end
|
151
|
+
|
152
|
+
=begin DYNAMIC WEIGHTS PROBABLY NOT THAT USEFUL
|
153
|
+
|
154
|
+
class DynamicWeight < AbstractWeight
|
155
|
+
def initialize args
|
156
|
+
@drp_instance = args.drp_instance
|
157
|
+
arg1, arg2, arg3 = args.user_args
|
158
|
+
if arg1.kind_of? Range
|
159
|
+
@range = arg1
|
160
|
+
if arg2.kind_of? Range
|
161
|
+
if (arg3.kind_of? Symbol) or (arg3.kind_of? String)
|
162
|
+
@function = arg3
|
163
|
+
end
|
164
|
+
min = Utils::map(@range, @drp_instance.next_meta_codon)
|
165
|
+
max = Utils::map(arg2, @drp_instance.next_meta_codon)
|
166
|
+
@range = min..max
|
167
|
+
elsif (arg2.kind_of? Symbol) or (arg2.kind_of? String)
|
168
|
+
@function = arg2
|
169
|
+
end
|
170
|
+
else
|
171
|
+
raise ArgumentError, 'weight_dyn args of wrong type'
|
172
|
+
end
|
173
|
+
end
|
174
|
+
def value
|
175
|
+
val = Utils::map(
|
176
|
+
@range,
|
177
|
+
@drp_instance.next_meta_codon,
|
178
|
+
@function
|
179
|
+
)
|
180
|
+
puts val
|
181
|
+
val
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
class ProcDynamicWeight < AbstractWeight
|
186
|
+
def initialize args
|
187
|
+
@proc = args.user_args
|
188
|
+
@arity = @proc.arity
|
189
|
+
@drp_instance = args.drp_instance
|
190
|
+
end
|
191
|
+
def value
|
192
|
+
case @arity
|
193
|
+
# these are here, and also ordered, for efficiencies sake
|
194
|
+
when 1
|
195
|
+
@proc.call @drp_instance.next_meta_codon
|
196
|
+
when 2
|
197
|
+
@proc.call @drp_instance.next_meta_codon, @drp_instance.next_meta_codon
|
198
|
+
when 0
|
199
|
+
raise ArgumentError, "block given to dynamic weight must have 1 or more arguments"
|
200
|
+
else
|
201
|
+
@proc.call *Array.new(@arity) { @drp_instance.next_meta_codon }
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
=end
|
207
|
+
|
208
|
+
=begin
|
209
|
+
weight_fcd 0..1 dynamic from current depth (uses max_depth)
|
210
|
+
weight_fcd 0..1, :function dynamic fcd w/ function
|
211
|
+
weight_fcd 0..1, 0..1 dynamic like previous but start
|
212
|
+
and end of range mapped from codons
|
213
|
+
weight_fcd 0..1, 0..1, :function like previous with function
|
214
|
+
the function applies to the dynamic mapping
|
215
|
+
of the current depth, and not the static
|
216
|
+
mapping via codons of start and end
|
217
|
+
which is always just linear
|
218
|
+
weight_fcd { |max_depth| dynamic, expects a block which takes the
|
219
|
+
... max_depth and returns a proc which
|
220
|
+
proc {|depth| ... } which takes the current depth
|
221
|
+
}
|
222
|
+
=end
|
223
|
+
|
224
|
+
class WeightFromCurrentDepth < AbstractWeight
|
225
|
+
def initialize args
|
226
|
+
@drp_instance = args.drp_instance
|
227
|
+
@rule_method = args.rule_method
|
228
|
+
@max_depth = @rule_method.max_depth - 1
|
229
|
+
arg1, arg2, arg3 = args.user_args
|
230
|
+
if arg1.kind_of? Range
|
231
|
+
@range = arg1
|
232
|
+
if arg2.kind_of? Range
|
233
|
+
if (arg3.kind_of? Symbol) or (arg3.kind_of? String)
|
234
|
+
@function = arg3
|
235
|
+
end
|
236
|
+
min = Utils::map(@range, @drp_instance.next_meta_codon)
|
237
|
+
max = Utils::map(arg2, @drp_instance.next_meta_codon)
|
238
|
+
@range = min..max
|
239
|
+
elsif (arg2.kind_of? Symbol) or (arg2.kind_of? String)
|
240
|
+
@function = arg2
|
241
|
+
end
|
242
|
+
else
|
243
|
+
raise ArgumentError, 'bad argument to weight_fcd'
|
244
|
+
end
|
245
|
+
end
|
246
|
+
def value
|
247
|
+
val = @rule_method.depth.to_f / @max_depth
|
248
|
+
Utils::map(@range, val, @function)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
class ProcWeightFromCurrentDepth < AbstractWeight
|
253
|
+
def initialize args
|
254
|
+
@rule_method = args.rule_method
|
255
|
+
@proc = args.user_args.call @rule_method.max_depth
|
256
|
+
end
|
257
|
+
def value
|
258
|
+
@proc.call @rule_method.depth
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
end # module Weights
|
263
|
+
|
264
|
+
end # module DRP
|
@@ -0,0 +1,219 @@
|
|
1
|
+
|
2
|
+
=begin
|
3
|
+
|
4
|
+
DRP, Genetic Programming + Grammatical Evolution = Directed Ruby Programming
|
5
|
+
Copyright (C) 2006, Christophe McKeon
|
6
|
+
|
7
|
+
This program is free software; you can redistribute it and/or
|
8
|
+
modify it under the terms of the GNU General Public License
|
9
|
+
as published by the Free Software Foundation; either version 2
|
10
|
+
of the License, or (at your option) any later version.
|
11
|
+
|
12
|
+
This program is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU General Public License
|
18
|
+
along with this program; if not, write to the Free Softwar Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
19
|
+
|
20
|
+
=end
|
21
|
+
|
22
|
+
class TestInstanceMethodsHelper
|
23
|
+
|
24
|
+
extend DRP::RuleEngine
|
25
|
+
|
26
|
+
MAX_DEPTH = 10
|
27
|
+
MAX_DEPTH_2 = 3
|
28
|
+
DEFAULT_NUM_CODONS = 40
|
29
|
+
|
30
|
+
attr_reader :minimum_depth, :maximum_depth, :depths
|
31
|
+
|
32
|
+
def initialize codons = nil
|
33
|
+
@minimum_depth = 2000000000
|
34
|
+
@maximum_depth = 0
|
35
|
+
@depths = []
|
36
|
+
self.codons= codons
|
37
|
+
# init_drp
|
38
|
+
end
|
39
|
+
|
40
|
+
def next_codon
|
41
|
+
@codon_index = 0 if @codon_index == @num_codons
|
42
|
+
res = @codons[@codon_index]
|
43
|
+
@codon_index += 1
|
44
|
+
res
|
45
|
+
end
|
46
|
+
|
47
|
+
def codons= codons
|
48
|
+
@codons = codons || Array.new(DEFAULT_NUM_CODONS) { rand }
|
49
|
+
@codon_index = 0
|
50
|
+
@num_codons = @codons.size
|
51
|
+
end
|
52
|
+
|
53
|
+
begin_rules
|
54
|
+
|
55
|
+
### depth tests ###
|
56
|
+
|
57
|
+
# because there is only ever one LHS
|
58
|
+
# in the follwing rules, each one is always
|
59
|
+
# picked and hence is deterministic and
|
60
|
+
# recursed to the maximum depth.
|
61
|
+
|
62
|
+
max_depth MAX_DEPTH
|
63
|
+
|
64
|
+
def test_depth_pre
|
65
|
+
register_depth
|
66
|
+
test_depth_pre
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_depth_post
|
70
|
+
test_depth_post
|
71
|
+
register_depth
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_depth_2_rules
|
75
|
+
@depths << depth
|
76
|
+
other_rule
|
77
|
+
test_depth_2_rules
|
78
|
+
end
|
79
|
+
|
80
|
+
max_depth MAX_DEPTH_2
|
81
|
+
|
82
|
+
def other_rule
|
83
|
+
@depths << depth
|
84
|
+
other_rule
|
85
|
+
end
|
86
|
+
|
87
|
+
end_rules
|
88
|
+
|
89
|
+
def register_depth
|
90
|
+
the_depth = depth
|
91
|
+
@depths << the_depth
|
92
|
+
# print @depths, "\n"
|
93
|
+
@minimum_depth = the_depth if the_depth < @minimum_depth
|
94
|
+
@maximum_depth = the_depth if the_depth > @maximum_depth
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
class TestInstanceMethods < Test::Unit::TestCase
|
100
|
+
|
101
|
+
MD = TestInstanceMethodsHelper::MAX_DEPTH
|
102
|
+
MD2 = TestInstanceMethodsHelper::MAX_DEPTH_2
|
103
|
+
|
104
|
+
def setup
|
105
|
+
@drp_obj = TestInstanceMethodsHelper.new
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_depth_pre
|
109
|
+
@drp_obj.test_depth_pre
|
110
|
+
assert_equal 1, @drp_obj.minimum_depth
|
111
|
+
assert_equal MD, @drp_obj.maximum_depth
|
112
|
+
assert_equal (1..MD).to_a, @drp_obj.depths
|
113
|
+
# assert false, "NOTE: just to have a false assertion for gemspec"
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_depth_post
|
117
|
+
@drp_obj.test_depth_post
|
118
|
+
assert_equal 1, @drp_obj.minimum_depth
|
119
|
+
assert_equal MD, @drp_obj.maximum_depth
|
120
|
+
assert_equal (1..MD).to_a.reverse, @drp_obj.depths
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_depth_2_rules
|
124
|
+
@drp_obj.test_depth_2_rules
|
125
|
+
depths_should_be = []
|
126
|
+
MD.times do |i|
|
127
|
+
depths_should_be << (i + 1)
|
128
|
+
MD2.times do |j|
|
129
|
+
depths_should_be << (j + 1)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
assert_equal depths_should_be, @drp_obj.depths
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_map_range
|
136
|
+
|
137
|
+
# NOTE the following effectively tests Utils::RangeFunctions as well
|
138
|
+
|
139
|
+
assert_kind_of Float, @drp_obj.map(0..1)
|
140
|
+
assert_kind_of Float, @drp_obj.map(0.0..1.0)
|
141
|
+
|
142
|
+
single_codon 0.0
|
143
|
+
|
144
|
+
# linear function tests
|
145
|
+
r = @drp_obj.map 0..1
|
146
|
+
assert_equal r, 0.0
|
147
|
+
|
148
|
+
r = @drp_obj.map 1..0
|
149
|
+
assert_equal r, 1.0
|
150
|
+
r = @drp_obj.map -12.3..12.3
|
151
|
+
assert_equal r, -12.3
|
152
|
+
r = @drp_obj.map 12.3..-12.3
|
153
|
+
assert_equal r, 12.3
|
154
|
+
|
155
|
+
single_codon 0.5
|
156
|
+
|
157
|
+
# linear function tests
|
158
|
+
r = @drp_obj.map 0..1
|
159
|
+
assert_equal r, 0.5
|
160
|
+
r = @drp_obj.map 1..0
|
161
|
+
assert_equal r, 0.5
|
162
|
+
r = @drp_obj.map -12.3..12.3
|
163
|
+
assert_equal r, 0
|
164
|
+
r = @drp_obj.map 12.3..-12.3
|
165
|
+
assert_equal r, 0
|
166
|
+
|
167
|
+
single_codon 1.0
|
168
|
+
|
169
|
+
# linear function tests
|
170
|
+
r = @drp_obj.map 0..1
|
171
|
+
assert_equal r, 1.0
|
172
|
+
r = @drp_obj.map 1..0
|
173
|
+
assert_equal r, 0.0
|
174
|
+
r = @drp_obj.map -12.3..12.3
|
175
|
+
assert_equal r, 12.3
|
176
|
+
r = @drp_obj.map 12.3..-12.3
|
177
|
+
assert_equal r, -12.3
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_map_block
|
182
|
+
|
183
|
+
num_codons = 10
|
184
|
+
codons = Array.new(num_codons) { rand }
|
185
|
+
set_codons codons
|
186
|
+
|
187
|
+
# assert_nil(codons.detect { |c| c >= 1.0 || c < 0.0 })
|
188
|
+
identity = proc { |x| x }
|
189
|
+
no_params = proc {}
|
190
|
+
local = codons.collect &identity
|
191
|
+
mapped = []
|
192
|
+
|
193
|
+
num_codons.times do
|
194
|
+
mapped << @drp_obj.map(&identity)
|
195
|
+
end
|
196
|
+
|
197
|
+
assert_equal local, mapped
|
198
|
+
|
199
|
+
# test multiple params
|
200
|
+
set_codons [1,2,3]
|
201
|
+
r = @drp_obj.map { |a,b,c,d| [a,b,c,d] }
|
202
|
+
assert_equal [1,2,3,1], r
|
203
|
+
|
204
|
+
assert_raise(ArgumentError) { @drp_obj.map &no_params }
|
205
|
+
|
206
|
+
# should not accept args and block
|
207
|
+
assert_raise(ArgumentError) { @drp_obj.map 0..1, &identity }
|
208
|
+
assert_raise(ArgumentError) { @drp_obj.map 0..1, :linear, &identity }
|
209
|
+
|
210
|
+
end
|
211
|
+
|
212
|
+
def single_codon codon
|
213
|
+
@drp_obj.codons = [codon]
|
214
|
+
end
|
215
|
+
def set_codons codons
|
216
|
+
@drp_obj.codons = codons
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|