drp 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|