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/README
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
= DRP, Directed Ruby Programming
|
2
|
+
|
3
|
+
Grammatical Evolution + Genetic Programming = Directed Programming
|
4
|
+
|
5
|
+
DRP is a generative programming system which lets you do GP, GE, hybrid GP and GE, and which like GE separates the search algorithm from the program representation.
|
6
|
+
|
7
|
+
The Web site of DRP is http://drp.rubyforge.org.
|
8
|
+
Documentation can be found at http://drp.rubyforge.org/rdoc.
|
9
|
+
For a much more in depth explanation see the INTRO file in the rdoc.
|
10
|
+
The RubyForge project page is http://rubyforge.org/projects/drp, where the latest
|
11
|
+
version of DRP may be downloaded.
|
12
|
+
DRP is also available as a RubyGem, see installation instructions below.
|
13
|
+
|
14
|
+
== Dependencies
|
15
|
+
|
16
|
+
DRP does not require any other packages. The test suite in the tests
|
17
|
+
directory requires the testing framework TestUnit, which comes with Ruby 1.8
|
18
|
+
and later and can also be found in the Ruby Application Archive
|
19
|
+
(http://raa.ruby-lang.org).
|
20
|
+
|
21
|
+
Deployment is handled by RubyGems and Rake.
|
22
|
+
|
23
|
+
== Installation
|
24
|
+
|
25
|
+
=== RubyGems Installation
|
26
|
+
|
27
|
+
To install drp as a gem, type:
|
28
|
+
|
29
|
+
$ gem install drp
|
30
|
+
|
31
|
+
To update it if previously installed as a gem:
|
32
|
+
|
33
|
+
$ gem update drp
|
34
|
+
|
35
|
+
To remove drp (although I'm sure you want want to do that):
|
36
|
+
|
37
|
+
$ gem uninstall drp
|
38
|
+
|
39
|
+
You may need root privileges to install, update, or remove the gem.
|
40
|
+
You can also download the compressed archive, but installing
|
41
|
+
as a gem is much more highly recomended.
|
42
|
+
|
43
|
+
== Testing
|
44
|
+
|
45
|
+
To run the test suite if you have the gem installed:
|
46
|
+
|
47
|
+
$ gem check -t drp
|
48
|
+
|
49
|
+
Note, it disconcertingly prints nothing on success.
|
50
|
+
|
51
|
+
If you are manually installing the archive:
|
52
|
+
|
53
|
+
$ rake test
|
54
|
+
|
55
|
+
runs all of the tests in the test directory.
|
56
|
+
|
57
|
+
= Support
|
58
|
+
|
59
|
+
* Visit the forums, bug list, and mailing list pages at
|
60
|
+
http://rubyforge.org/projects/drp
|
61
|
+
|
62
|
+
* Send email to Christophe McKeon at mailto:polypus@yahoo.com
|
63
|
+
|
64
|
+
* Ask on the ruby-talk mailing list or ruby forum
|
65
|
+
|
66
|
+
= Administrivia
|
67
|
+
|
68
|
+
:include:AUTHORS
|
69
|
+
Copyright (c) 2006, Christophe McKeon
|
70
|
+
Software License:: Distributed under the GNU GPL, see LICENSE
|
71
|
+
Documentation and Website:: Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License
|
72
|
+
|
73
|
+
== Warranty
|
74
|
+
|
75
|
+
This software is provided "as is" and without any express or implied
|
76
|
+
warranties, including, without limitation, the implied warranties of
|
77
|
+
merchantability and fitness for a particular purpose.
|
data/Rakefile
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
Gem::manage_gems
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require 'rake/testtask'
|
7
|
+
require 'rake/contrib/sshpublisher'
|
8
|
+
|
9
|
+
PROJECT_NAME = 'drp'
|
10
|
+
RUBYFORGE_USER = 'polypus'
|
11
|
+
RDOC_OPTIONS = ['--main','README','--include','examples/intro']
|
12
|
+
|
13
|
+
PKG_FILES = FileList[
|
14
|
+
'CHANGES', 'AUTHORS', 'README', 'TODO', 'LICENSE',
|
15
|
+
'Rakefile',
|
16
|
+
'examples/intro/*',
|
17
|
+
'examples/*.rb',
|
18
|
+
'lib/**/*.rb',
|
19
|
+
'test/**/*.rb'
|
20
|
+
].to_a
|
21
|
+
|
22
|
+
RDOC_FILES = FileList[
|
23
|
+
'README',
|
24
|
+
'INTRO'
|
25
|
+
].to_a
|
26
|
+
|
27
|
+
TEST_SUITE_FILE_NAME = 'test/ts_drp.rb'
|
28
|
+
|
29
|
+
DRP_DESCRIPTION = %{
|
30
|
+
Directed Programming is a new generative programming technique developed by Christophe McKeon which is a generalisation of Grammatical Evolution (http://www.grammatical-evolution.org) allowing one not only to do GE, but also to do Genetic Programming (http://www.genetic-programming.org) in pure Ruby without explicitly generating a program string as output. DP even allows you to set up hybrids of GP and GE where part of a GE subtree is calculated using normal Ruby functions/operators/etc. via. GP. DRP is the first ever implementation of DP and is written in pure Ruby.
|
31
|
+
}
|
32
|
+
|
33
|
+
spec = Gem::Specification.new do |s|
|
34
|
+
|
35
|
+
s.name = PROJECT_NAME
|
36
|
+
s.version = `ruby -Ilib -e 'require "info"; puts DRP::Version'`.strip
|
37
|
+
s.summary = 'genetic programming * grammatical evolution = directed (ruby) programming'
|
38
|
+
s.platform = Gem::Platform::RUBY
|
39
|
+
|
40
|
+
s.require_path = 'lib'
|
41
|
+
# s.autorequire = PROJECT_NAME
|
42
|
+
s.files = PKG_FILES
|
43
|
+
|
44
|
+
s.has_rdoc = true
|
45
|
+
s.rdoc_options = s.rdoc_options + RDOC_OPTIONS
|
46
|
+
s.extra_rdoc_files = RDOC_FILES
|
47
|
+
|
48
|
+
s.author = 'Christophe McKeon'
|
49
|
+
s.email = 'polypus@yahoo.com'
|
50
|
+
s.homepage = 'http://drp.rubyforge.org'
|
51
|
+
s.rubyforge_project = PROJECT_NAME
|
52
|
+
|
53
|
+
s.description = DRP_DESCRIPTION
|
54
|
+
|
55
|
+
s.test_file = TEST_SUITE_FILE_NAME
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
task :default => [:package]
|
60
|
+
|
61
|
+
# creates :package and :gem tasks
|
62
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
63
|
+
pkg.need_zip = true
|
64
|
+
pkg.need_tar = true
|
65
|
+
end
|
66
|
+
|
67
|
+
# creates an :rdoc task
|
68
|
+
Rake::RDocTask.new do |rd|
|
69
|
+
# rd.main = 'README' # this is set in options
|
70
|
+
rd.title = PROJECT_NAME
|
71
|
+
rd.rdoc_files = RDOC_FILES + FileList['lib/**/*.rb'].to_a
|
72
|
+
rd.rdoc_dir = 'rdoc'
|
73
|
+
rd.options += RDOC_OPTIONS
|
74
|
+
end
|
75
|
+
|
76
|
+
# creates an :rdoc task for :rubyforge_publish task
|
77
|
+
Rake::RDocTask.new(:rdoc_publish) do |rd|
|
78
|
+
rd.title = PROJECT_NAME
|
79
|
+
rd.rdoc_files = RDOC_FILES + FileList['lib/**/*.rb'].to_a
|
80
|
+
rd.rdoc_dir = 'rubyforge_website/rdoc'
|
81
|
+
rd.options += RDOC_OPTIONS
|
82
|
+
end
|
83
|
+
|
84
|
+
# creates a :test task
|
85
|
+
Rake::TestTask.new do |tt|
|
86
|
+
tt.pattern = TEST_SUITE_FILE_NAME
|
87
|
+
tt.verbose = true
|
88
|
+
# tt.warning = true
|
89
|
+
end
|
90
|
+
|
91
|
+
task :rubyforge_publish => [:rdoc_publish] do
|
92
|
+
# copies the contents of website, into the top level dir at rubyforge
|
93
|
+
host = RUBYFORGE_USER + "@rubyforge.org"
|
94
|
+
remote_dir = "/var/www/gforge-projects/#{PROJECT_NAME}"
|
95
|
+
local_dir = "rubyforge_website"
|
96
|
+
Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
|
97
|
+
# this did not allow control over name of local dir
|
98
|
+
# Rake::RubyForgePublisher.new(PROJECT_NAME, RUBYFORGE_USER).upload
|
99
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
more work on exceptions and error handling, and also testing of
|
3
|
+
exceptions
|
4
|
+
|
5
|
+
clean up weight and max_depth argument parsing, it's a bit all over
|
6
|
+
the place
|
7
|
+
|
8
|
+
feature idea: make a weight_fcd_of (perhaps named differently) which allows
|
9
|
+
you to determine the weight for a given rule depending on the depth
|
10
|
+
of another rule. this is handy if you have some higher rule method
|
11
|
+
which calls another rule method which has several choices, and you
|
12
|
+
want the choice to be contingent on the higher method's depth.
|
13
|
+
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'drp'
|
3
|
+
|
4
|
+
NUM_CANVASES = 8
|
5
|
+
CANVAS_SIZE = 200
|
6
|
+
|
7
|
+
class CanvasExample
|
8
|
+
|
9
|
+
extend DRP::RuleEngine
|
10
|
+
|
11
|
+
def initialize num_codons = 100
|
12
|
+
@codons = Array.new(num_codons) { rand }
|
13
|
+
@num_codons = num_codons
|
14
|
+
@index = 0
|
15
|
+
end
|
16
|
+
|
17
|
+
def next_codon
|
18
|
+
@index += 1
|
19
|
+
@index = 0 if @index >= @num_codons
|
20
|
+
@codons[@index]
|
21
|
+
end
|
22
|
+
|
23
|
+
begin_rules
|
24
|
+
|
25
|
+
max_depth 4..24
|
26
|
+
weight 1
|
27
|
+
|
28
|
+
def start_rule
|
29
|
+
start_rule + ctx_mv_list_prep
|
30
|
+
end
|
31
|
+
|
32
|
+
def ctx_mv_list_prep
|
33
|
+
ctx_begin + ctx_fill_style + ctx_stroke_style + ctx_mv_list + ctx_end
|
34
|
+
end
|
35
|
+
def ctx_mv_list
|
36
|
+
ctx_mv_list + ctx_mv
|
37
|
+
end
|
38
|
+
|
39
|
+
def ctx_mv
|
40
|
+
"ctx.#{mv_type}"
|
41
|
+
end
|
42
|
+
|
43
|
+
# this weight will apply to all following rule methods
|
44
|
+
weight_fcd 0..1
|
45
|
+
|
46
|
+
def mv_type
|
47
|
+
"lineTo(#{loc},#{loc});"
|
48
|
+
end
|
49
|
+
def mv_type
|
50
|
+
"moveTo(#{loc},#{loc});"
|
51
|
+
end
|
52
|
+
def mv_type
|
53
|
+
"bezierCurveTo(#{loc},#{loc},#{loc},#{loc},#{loc},#{loc});"
|
54
|
+
end
|
55
|
+
|
56
|
+
def ctx_end
|
57
|
+
"ctx.fill();"
|
58
|
+
end
|
59
|
+
def ctx_end
|
60
|
+
"ctx.stroke();"
|
61
|
+
end
|
62
|
+
|
63
|
+
end_rules
|
64
|
+
|
65
|
+
def loc
|
66
|
+
map(0..CANVAS_SIZE).to_i
|
67
|
+
end
|
68
|
+
|
69
|
+
def ctx_fill_style
|
70
|
+
"ctx.fillStyle=#{rgba}"
|
71
|
+
end
|
72
|
+
def ctx_stroke_style
|
73
|
+
"ctx.strokeStyle=#{rgba}"
|
74
|
+
end
|
75
|
+
def ctx_begin
|
76
|
+
"ctx.beginPath();"
|
77
|
+
end
|
78
|
+
def rgba
|
79
|
+
"'rgba(#{rgb_val},#{rgb_val},#{rgb_val},#{next_codon})';"
|
80
|
+
end
|
81
|
+
def rgb_val
|
82
|
+
map(0..256).to_i
|
83
|
+
end
|
84
|
+
|
85
|
+
def default_rule_method
|
86
|
+
''
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
def html script, body
|
92
|
+
%{<html><head>
|
93
|
+
<style>
|
94
|
+
canvas {margin: 10px; border: solid black 1px}
|
95
|
+
#drp {margin: 10px}
|
96
|
+
</style>
|
97
|
+
<script>#{script}</script></head>
|
98
|
+
<body>#{body}</body></html>
|
99
|
+
}
|
100
|
+
end
|
101
|
+
def js_draw_func
|
102
|
+
"function(ctx){#{CanvasExample.new.start_rule}},\n"
|
103
|
+
end
|
104
|
+
|
105
|
+
script = %{
|
106
|
+
window.onload = function() {
|
107
|
+
for( var i = 0; i < #{NUM_CANVASES}; i++ ) {
|
108
|
+
var ctx = document.getElementById('cvs_' + i).getContext('2d');
|
109
|
+
draw_funcs[i](ctx);
|
110
|
+
}
|
111
|
+
}
|
112
|
+
var draw_funcs = [
|
113
|
+
}
|
114
|
+
NUM_CANVASES.times do |i|
|
115
|
+
script += js_draw_func
|
116
|
+
end
|
117
|
+
script += "];"
|
118
|
+
|
119
|
+
body = ""
|
120
|
+
NUM_CANVASES.times do |i|
|
121
|
+
body += %{<canvas id='cvs_#{i}' width="#{CANVAS_SIZE}" height="#{CANVAS_SIZE}"></canvas>}
|
122
|
+
end
|
123
|
+
puts html(script, body)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'drp'
|
3
|
+
|
4
|
+
class MaxDepthsExample
|
5
|
+
|
6
|
+
extend DRP::RuleEngine
|
7
|
+
|
8
|
+
begin_rules
|
9
|
+
|
10
|
+
max_depth 2
|
11
|
+
|
12
|
+
def foo
|
13
|
+
"foo1 #{foo}"
|
14
|
+
end
|
15
|
+
|
16
|
+
max_depth 3
|
17
|
+
|
18
|
+
def foo
|
19
|
+
"foo2 #{foo}"
|
20
|
+
end
|
21
|
+
|
22
|
+
end_rules
|
23
|
+
|
24
|
+
def default_rule_method
|
25
|
+
"bar!"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
mde = MaxDepthsExample.new
|
31
|
+
3.times do
|
32
|
+
puts mde.foo
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'drp'
|
3
|
+
|
4
|
+
class MaxDepthsExample2
|
5
|
+
|
6
|
+
extend DRP::RuleEngine
|
7
|
+
|
8
|
+
begin_rules
|
9
|
+
|
10
|
+
max_depth 0..3
|
11
|
+
|
12
|
+
def foo
|
13
|
+
"foo1 #{foo}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def foo
|
17
|
+
"foo2 #{foo}"
|
18
|
+
end
|
19
|
+
|
20
|
+
end_rules
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
3.times do
|
25
|
+
mde2 = MaxDepthsExample2.new
|
26
|
+
3.times do
|
27
|
+
puts mde2.foo
|
28
|
+
end
|
29
|
+
puts
|
30
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'drp'
|
4
|
+
|
5
|
+
class OddsAndEnds
|
6
|
+
|
7
|
+
extend DRP::RuleEngine
|
8
|
+
|
9
|
+
def initialize num_codons
|
10
|
+
@array_of_goodies = %w{ lollypop hotpants sunset whalesong }
|
11
|
+
@num_codons = num_codons
|
12
|
+
@codons = Array.new(num_codons) { rand }
|
13
|
+
@c_index = 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def next_codon
|
17
|
+
@c_index = 0 if @c_index == @num_codons
|
18
|
+
cod = @codons[@c_index]
|
19
|
+
@c_index += 1
|
20
|
+
cod
|
21
|
+
end
|
22
|
+
|
23
|
+
begin_rules
|
24
|
+
|
25
|
+
max_depth 2..4
|
26
|
+
|
27
|
+
def max_depth_string
|
28
|
+
"max_depth = #{max_depth}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def depth_example
|
32
|
+
"#{depth} #{depth_example}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def depth_indirect_a
|
36
|
+
"#{depth} #{depth_indirect_b}"
|
37
|
+
end
|
38
|
+
def depth_indirect_b
|
39
|
+
"#{depth} #{depth_indirect_a}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def map_range
|
43
|
+
val = map 0..10
|
44
|
+
"#{val} #{map_range}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def map_range_i
|
48
|
+
index = map 0..3, :i_lin
|
49
|
+
@array_of_goodies[index] + ' ' + map_range_i
|
50
|
+
end
|
51
|
+
|
52
|
+
def map_block
|
53
|
+
val = map { |x,y| x * y * 10 }
|
54
|
+
"#{val} #{map_block}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def next_codons
|
58
|
+
"you can even get the next_codon: #{next_codon},\nand next_meta_codon: #{next_meta_codon}"
|
59
|
+
end
|
60
|
+
|
61
|
+
end_rules
|
62
|
+
|
63
|
+
def default_rule_method
|
64
|
+
"!"
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
oae = OddsAndEnds.new(40)
|
70
|
+
|
71
|
+
puts "querying for the max_depth:"
|
72
|
+
puts oae.max_depth_string
|
73
|
+
puts
|
74
|
+
|
75
|
+
puts "simple depth example:"
|
76
|
+
puts oae.depth_example
|
77
|
+
puts
|
78
|
+
|
79
|
+
puts "indirect depth example:"
|
80
|
+
puts oae.depth_indirect_a
|
81
|
+
puts
|
82
|
+
|
83
|
+
puts "map a range:"
|
84
|
+
puts oae.map_range
|
85
|
+
puts
|
86
|
+
|
87
|
+
puts "map an integer range:"
|
88
|
+
puts oae.map_range_i
|
89
|
+
puts
|
90
|
+
|
91
|
+
puts "map a block:"
|
92
|
+
puts oae.map_block
|
93
|
+
puts
|
94
|
+
|
95
|
+
puts oae.next_codons
|
96
|
+
puts
|