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
@@ -0,0 +1,98 @@
|
|
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 TestMaxDepthsHelper
|
23
|
+
|
24
|
+
extend DRP::RuleEngine
|
25
|
+
|
26
|
+
attr_reader :test_simple_depth_attained
|
27
|
+
|
28
|
+
def initialize single_codon = nil
|
29
|
+
@test_simple_depth_attained = 0
|
30
|
+
@single_codon = single_codon
|
31
|
+
# init_drp
|
32
|
+
end
|
33
|
+
|
34
|
+
# note max_depths call next_meta_codon
|
35
|
+
# but their is a default next_meta_codon which
|
36
|
+
# just calls next_codon
|
37
|
+
def next_codon
|
38
|
+
@single_codon || rand
|
39
|
+
end
|
40
|
+
|
41
|
+
begin_rules
|
42
|
+
|
43
|
+
# note, some of these tests depend on the return
|
44
|
+
# value of default_rule_method below
|
45
|
+
|
46
|
+
max_depth 4
|
47
|
+
def test_simple
|
48
|
+
test_simple + 1
|
49
|
+
end
|
50
|
+
|
51
|
+
max_depth 3..9
|
52
|
+
def test_map_range
|
53
|
+
test_map_range + 1
|
54
|
+
end
|
55
|
+
|
56
|
+
max_depth { |x,y| x + y }
|
57
|
+
def test_proc
|
58
|
+
test_proc + 1
|
59
|
+
end
|
60
|
+
|
61
|
+
end_rules
|
62
|
+
|
63
|
+
def default_rule_method
|
64
|
+
0
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
class TestMaxDepths < Test::Unit::TestCase
|
70
|
+
|
71
|
+
def test_exceptions
|
72
|
+
# TODO
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_simple
|
76
|
+
@drp_obj = TestMaxDepthsHelper.new
|
77
|
+
assert_equal 4, @drp_obj.test_simple
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_map_range
|
81
|
+
7.times do |i|
|
82
|
+
codon = i/7.0
|
83
|
+
@drp_obj = TestMaxDepthsHelper.new codon
|
84
|
+
#puts "i: #{i}, cod: #{codon}, map: #{@drp_obj.test_map_range}"
|
85
|
+
assert_equal i + 3, @drp_obj.test_map_range
|
86
|
+
end
|
87
|
+
@drp_obj = TestMaxDepthsHelper.new 0.99999999999
|
88
|
+
assert_equal 9, @drp_obj.test_map_range
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_proc
|
92
|
+
@drp_obj = TestMaxDepthsHelper.new 3
|
93
|
+
assert_equal 6, @drp_obj.test_proc
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
|
data/test/tc_utils.rb
ADDED
@@ -0,0 +1,60 @@
|
|
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
|
+
# TODO test if the range is of the form n..n where n is the same number
|
23
|
+
|
24
|
+
class TestUtils < Test::Unit::TestCase
|
25
|
+
|
26
|
+
def test_i_linear_map
|
27
|
+
|
28
|
+
r = 0..4
|
29
|
+
|
30
|
+
assert_equal 0, DRP::Utils::map(r, 0, :i_linear)
|
31
|
+
assert_equal 0, DRP::Utils::map(r, 0.19999, :i_linear)
|
32
|
+
assert_equal 1, DRP::Utils::map(r, 0.2, :i_linear)
|
33
|
+
assert_equal 1, DRP::Utils::map(r, 0.39999, :i_linear)
|
34
|
+
assert_equal 2, DRP::Utils::map(r, 0.4, :i_linear)
|
35
|
+
assert_equal 2, DRP::Utils::map(r, 0.59999, :i_linear)
|
36
|
+
assert_equal 3, DRP::Utils::map(r, 0.6, :i_linear)
|
37
|
+
assert_equal 3, DRP::Utils::map(r, 0.79999, :i_linear)
|
38
|
+
assert_equal 4, DRP::Utils::map(r, 0.8, :i_linear)
|
39
|
+
assert_equal 4, DRP::Utils::map(r, 0.99999, :i_linear)
|
40
|
+
# this is 5 but codons need to be 0 <= c < 1 so it should never happen
|
41
|
+
# assert_equal 5, DRP::Utils::map(r, 1, :i_linear)
|
42
|
+
|
43
|
+
r = 4..0
|
44
|
+
|
45
|
+
assert_equal 4, DRP::Utils::map(r, 0, :i_linear)
|
46
|
+
assert_equal 4, DRP::Utils::map(r, 0.19999, :i_linear)
|
47
|
+
assert_equal 3, DRP::Utils::map(r, 0.2, :i_linear)
|
48
|
+
assert_equal 3, DRP::Utils::map(r, 0.39999, :i_linear)
|
49
|
+
assert_equal 2, DRP::Utils::map(r, 0.4, :i_linear)
|
50
|
+
assert_equal 2, DRP::Utils::map(r, 0.59999, :i_linear)
|
51
|
+
assert_equal 1, DRP::Utils::map(r, 0.6, :i_linear)
|
52
|
+
assert_equal 1, DRP::Utils::map(r, 0.79999, :i_linear)
|
53
|
+
assert_equal 0, DRP::Utils::map(r, 0.8, :i_linear)
|
54
|
+
assert_equal 0, DRP::Utils::map(r, 0.99999, :i_linear)
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
|
data/test/tc_weights.rb
ADDED
@@ -0,0 +1,372 @@
|
|
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
|
+
############### STATIC WEIGHTS ###############
|
23
|
+
|
24
|
+
=begin
|
25
|
+
weight 10.0 static weight
|
26
|
+
weight 0..1 static mapped
|
27
|
+
weight 0..1, :function static mapped w/ function
|
28
|
+
weight {} static proc gets codons
|
29
|
+
=end
|
30
|
+
|
31
|
+
class TestStaticWeightsHelper
|
32
|
+
|
33
|
+
extend DRP::RuleEngine
|
34
|
+
|
35
|
+
attr_writer :codon
|
36
|
+
attr_reader :_1, :_0, :_33, :_67, :_m1, :_m01_02, :_p30, :_p70
|
37
|
+
|
38
|
+
def initialize codon = nil
|
39
|
+
@codon = codon
|
40
|
+
@_1 = @_0 = @_33 = @_67 = @_m1 = @_m01_02 = @_p30 = @_p70 = 0
|
41
|
+
end
|
42
|
+
|
43
|
+
def next_codon
|
44
|
+
@codon || rand
|
45
|
+
end
|
46
|
+
|
47
|
+
begin_rules
|
48
|
+
|
49
|
+
# test constant
|
50
|
+
|
51
|
+
weight 1
|
52
|
+
def _1_0
|
53
|
+
@_1 += 1
|
54
|
+
end
|
55
|
+
|
56
|
+
weight 0
|
57
|
+
def _1_0
|
58
|
+
@_0 += 1
|
59
|
+
end
|
60
|
+
|
61
|
+
weight 33
|
62
|
+
def _33_67
|
63
|
+
@_33 += 1
|
64
|
+
end
|
65
|
+
|
66
|
+
weight 67
|
67
|
+
def _33_67
|
68
|
+
@_67 += 1
|
69
|
+
end
|
70
|
+
|
71
|
+
# test mapped
|
72
|
+
|
73
|
+
weight 0.1..0.2
|
74
|
+
def mapped
|
75
|
+
@_m01_02 += 1
|
76
|
+
end
|
77
|
+
|
78
|
+
weight 1
|
79
|
+
def mapped
|
80
|
+
@_m1 += 1
|
81
|
+
end
|
82
|
+
|
83
|
+
# test proc
|
84
|
+
|
85
|
+
weight { |x,y,z| ((x + y + z) * 100).to_i }
|
86
|
+
def proc
|
87
|
+
@_p30 += 1
|
88
|
+
end
|
89
|
+
|
90
|
+
weight 70
|
91
|
+
def proc
|
92
|
+
@_p70 += 1
|
93
|
+
end
|
94
|
+
|
95
|
+
end_rules
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
class TestStaticWeights < Test::Unit::TestCase
|
100
|
+
|
101
|
+
def test_constant
|
102
|
+
ts = TestStaticWeightsHelper.new
|
103
|
+
100.times do |i|
|
104
|
+
ts.codon = i.to_f/100
|
105
|
+
ts._1_0
|
106
|
+
ts._33_67
|
107
|
+
end
|
108
|
+
assert_equal 100, ts._1
|
109
|
+
assert_equal 0, ts._0
|
110
|
+
assert_equal 33, ts._33
|
111
|
+
assert_equal 67, ts._67
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_mapped
|
115
|
+
ts = TestStaticWeightsHelper.new
|
116
|
+
100.times do |i|
|
117
|
+
ts.codon = i.to_f/100
|
118
|
+
ts.mapped
|
119
|
+
end
|
120
|
+
m = ts._m01_02
|
121
|
+
m1 = ts._m1
|
122
|
+
# puts ">>>>>", m, m1, "<<<<<"
|
123
|
+
# these figures take normalization into account
|
124
|
+
assert m >= 9 && m <= 17
|
125
|
+
assert m1 >= 83
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_mapped_w_function
|
129
|
+
# TODO no functions yet
|
130
|
+
assert true
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_proc
|
134
|
+
ts = TestStaticWeightsHelper.new(0.1)
|
135
|
+
# since the codon is set here
|
136
|
+
# to 0.1 then (x + y + z) * 100 in proc equal 30
|
137
|
+
100.times do |i|
|
138
|
+
ts.codon = i.to_f/100
|
139
|
+
ts.proc
|
140
|
+
end
|
141
|
+
assert_equal 30, ts._p30
|
142
|
+
assert_equal 70, ts._p70
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
############### FROM CURRENT DEPTH WEIGHTS ##################
|
148
|
+
|
149
|
+
|
150
|
+
=begin
|
151
|
+
weight_fcd 0..1 dynamic from current depth (uses max_depth)
|
152
|
+
weight_fcd 0..1, :function dynamic fcd w/ function
|
153
|
+
weight_fcd 0..1, 0..1 dynamic like previous but start
|
154
|
+
and end of range mapped from codons
|
155
|
+
weight_fcd 0..1, 0..1, :function like previous with function
|
156
|
+
the function applies to the dynamic mapping
|
157
|
+
of the current depth, and not the static
|
158
|
+
mapping via codons of start and end
|
159
|
+
which is always just linear
|
160
|
+
weight_fcd { |max_depth| dynamic, expects a block which takes the
|
161
|
+
... max_depth and returns a proc which
|
162
|
+
proc {|depth| ... } which takes the current depth
|
163
|
+
}
|
164
|
+
=end
|
165
|
+
|
166
|
+
class TestFCDWeightsHelper
|
167
|
+
|
168
|
+
extend DRP::RuleEngine
|
169
|
+
|
170
|
+
attr_reader :str
|
171
|
+
|
172
|
+
def initialize
|
173
|
+
reset
|
174
|
+
end
|
175
|
+
def reset
|
176
|
+
@str = ''
|
177
|
+
end
|
178
|
+
|
179
|
+
begin_rules
|
180
|
+
|
181
|
+
max_depth 3
|
182
|
+
|
183
|
+
weight_fcd 1.0..0.0
|
184
|
+
def simple
|
185
|
+
@str << 'a'
|
186
|
+
# print @str, '>>', depth, "\n"
|
187
|
+
simple
|
188
|
+
end
|
189
|
+
|
190
|
+
weight_fcd 0.0..1.0
|
191
|
+
def simple
|
192
|
+
@str << 'b'
|
193
|
+
# print @str, '>>', depth, "\n"
|
194
|
+
simple
|
195
|
+
end
|
196
|
+
|
197
|
+
end_rules
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
class TestFCDWeights < Test::Unit::TestCase
|
202
|
+
|
203
|
+
def test_simple
|
204
|
+
td = TestFCDWeightsHelper.new
|
205
|
+
100.times do
|
206
|
+
td.simple
|
207
|
+
# on first pick 'a' must be chosen w/ 1.0 vs 0.0 weight
|
208
|
+
# on second pick 'a' must be chosen with 0.5 vs 0 weight
|
209
|
+
# on third pick 'a' and 'b' both have weight 0 so
|
210
|
+
# either can be chosen
|
211
|
+
# if 'a' was chosen on third then
|
212
|
+
# all the rest will be 'b' because 'a' has exceeded max depth 3
|
213
|
+
# else
|
214
|
+
# on fourth pick 'b' must be chosen because it now has weight
|
215
|
+
# 0.5 vs 'a' which still has weight 0.0
|
216
|
+
# on fifth pick 'b' must be chosen because it now has weight 1.0
|
217
|
+
# on sixth pick 'a' is the only active rule method because 'b' has
|
218
|
+
# gone past it's max_depth, so 'a' must be picked
|
219
|
+
assert ('aaabbb' == td.str) || ('aabbba' == td.str)
|
220
|
+
td.reset
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
end
|
225
|
+
|
226
|
+
##############################################################
|
227
|
+
|
228
|
+
|
229
|
+
|
230
|
+
|
231
|
+
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
############### DYNAMIC WEIGHTS ##############
|
236
|
+
|
237
|
+
=begin
|
238
|
+
weight_dyn 0..1 codon maps to range for every rule method choice
|
239
|
+
weight_dyn 0..1, :function same but using function
|
240
|
+
weight_dyn 0..1, 0..1 initial min and max determined by metacodons
|
241
|
+
and further runtime mapping also
|
242
|
+
weight_dyn 0..1, 0..1, :function same but function used for runtime mapping
|
243
|
+
weight_dyn { |codon| } same but using user block, gets meta_codons
|
244
|
+
=end
|
245
|
+
|
246
|
+
=begin NOT SURE HOW USEFUL 'DYNAMIC' WEIGHTS ARE
|
247
|
+
|
248
|
+
class TestDynamicWeightsHelper
|
249
|
+
|
250
|
+
extend DRP::RuleEngine
|
251
|
+
|
252
|
+
attr_reader :test_simple_count, :num_meta_codon_requests, :num_codon_requests
|
253
|
+
|
254
|
+
def initialize codon = nil
|
255
|
+
@codon = codon
|
256
|
+
reset
|
257
|
+
end
|
258
|
+
|
259
|
+
def next_codon
|
260
|
+
@num_codon_requests += 1
|
261
|
+
@codon || rand
|
262
|
+
end
|
263
|
+
|
264
|
+
def next_meta_codon
|
265
|
+
@num_meta_codon_requests += 1
|
266
|
+
rand
|
267
|
+
end
|
268
|
+
|
269
|
+
def reset
|
270
|
+
@num_codon_requests = 0
|
271
|
+
@num_meta_codon_requests = 0
|
272
|
+
end
|
273
|
+
|
274
|
+
begin_rules
|
275
|
+
|
276
|
+
weight_dyn 0..1
|
277
|
+
def test_simple
|
278
|
+
end
|
279
|
+
def test_simple
|
280
|
+
end
|
281
|
+
|
282
|
+
weight_dyn 0..1, 0..1
|
283
|
+
def test_init_range
|
284
|
+
end
|
285
|
+
def test_init_range
|
286
|
+
end
|
287
|
+
|
288
|
+
end_rules
|
289
|
+
|
290
|
+
end
|
291
|
+
|
292
|
+
class TestDynamicWeights < Test::Unit::TestCase
|
293
|
+
|
294
|
+
# this is a very indirect test
|
295
|
+
def test_simple
|
296
|
+
td = TestDynamicWeightsHelper.new
|
297
|
+
# 4 meta_codons are used to initialize test_init_range weights
|
298
|
+
# so need to reset
|
299
|
+
td.reset
|
300
|
+
n = 10
|
301
|
+
n.times do
|
302
|
+
td.test_simple
|
303
|
+
end
|
304
|
+
# both test_simple rule methods get weights
|
305
|
+
# allocated via meta_codons for each and every choice
|
306
|
+
assert_equal n * 2, td.num_meta_codon_requests
|
307
|
+
# once the weights are set a rule must be
|
308
|
+
# picked which uses a regular codon
|
309
|
+
assert_equal n, td.num_codon_requests
|
310
|
+
end
|
311
|
+
|
312
|
+
def test_init_range
|
313
|
+
td = TestDynamicWeightsHelper.new
|
314
|
+
# 4 meta_codons are used to initialize test_init_range weights
|
315
|
+
assert_equal 4, td.num_meta_codon_requests
|
316
|
+
n = 10
|
317
|
+
n.times do
|
318
|
+
td.test_init_range
|
319
|
+
end
|
320
|
+
# both test_init_range rule methods get
|
321
|
+
# their initial weight range set at initialization time
|
322
|
+
# which requires 2 metacodons each.
|
323
|
+
assert_equal (n * 2) + 4, td.num_meta_codon_requests
|
324
|
+
# once the weights are set a rule must be
|
325
|
+
# picked which uses a regular codon
|
326
|
+
assert_equal n, td.num_codon_requests
|
327
|
+
end
|
328
|
+
|
329
|
+
end
|
330
|
+
|
331
|
+
=end
|
332
|
+
|
333
|
+
|
334
|
+
=begin
|
335
|
+
|
336
|
+
ITER_TEST_DEFAULT_NUM_ITER = 1000
|
337
|
+
ITER_TEST_MAX_NUM_ITER = 100000
|
338
|
+
|
339
|
+
def iter_test(
|
340
|
+
test_helper, selector, expected = true,
|
341
|
+
num_iter = ITER_TEST_DEFAULT_NUM_ITER,
|
342
|
+
max_num_iter = ITER_TEST_MAX_NUM_ITER
|
343
|
+
)
|
344
|
+
|
345
|
+
if num_iter > max_num_iter
|
346
|
+
return false
|
347
|
+
end
|
348
|
+
|
349
|
+
test = true
|
350
|
+
num_iter.times do
|
351
|
+
test &&= test_helper.send(selector)
|
352
|
+
end
|
353
|
+
|
354
|
+
if test == expected
|
355
|
+
return true
|
356
|
+
else
|
357
|
+
return iter_test(test_helper, selector, expected, num_iter * 2, max_num_iter)
|
358
|
+
end
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
# non deterministic assert
|
363
|
+
def nd_assert test_helper, selector, expected = true
|
364
|
+
val = iter_test(test_helper, selector, expected)
|
365
|
+
msg = "nondeterministic test failure: '#{selector}', " +
|
366
|
+
# TODO these instructions should be in the docs
|
367
|
+
"run 'rake test' a few more times to double check"
|
368
|
+
assert val, msg
|
369
|
+
end
|
370
|
+
|
371
|
+
=end
|
372
|
+
|