nudge 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,6 @@
1
1
  .hg*
2
+ pkg/*
3
+ nudge.gemspec
2
4
  *.pdf
3
5
  *.aux
4
6
  *.dvi
data/Rakefile CHANGED
@@ -5,16 +5,18 @@ begin
5
5
  Jeweler::Tasks.new do |gemspec|
6
6
  gemspec.name = "nudge"
7
7
  gemspec.summary = "Genetic Programming in the Nudge language"
8
- gemspec.description = "It's way complicated"
8
+ gemspec.description = "DOES NOT WORK YET. The nudge gem will provide a simple framework for building, running and managing genetic programming experiments which automatically discover algorithms and equations to solve well-defined target problems. It depends on CouchDB and Ruby 1.9+"
9
9
  gemspec.email = "bill@vagueinnovation.com"
10
10
  gemspec.homepage = "http://github.com/Vaguery/PragGP"
11
11
  gemspec.authors = ["Bill Tozier", "Trek Glowacki"]
12
12
 
13
- gemspec.add_dependency('couchrest')
14
- gemspec.add_dependency('sinatra')
15
- gemspec.add_dependency('treetop')
16
- gemspec.add_dependency('polyglot')
17
- gemspec.add_dependency('active_support')
13
+ gemspec.required_ruby_version = '>= 1.9.1'
14
+
15
+ gemspec.add_dependency('couchrest', '>= 0.33')
16
+ gemspec.add_dependency('sinatra', '>= 0.9.4')
17
+ gemspec.add_dependency('treetop', '>= 1.4.3')
18
+ gemspec.add_dependency('polyglot', '>= 0.2.9')
19
+ gemspec.add_dependency('activesupport', '>= 2.3.5')
18
20
  end
19
21
 
20
22
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -0,0 +1,23 @@
1
+ NUDGECODE:
2
+
3
+ block {
4
+ literal «1»
5
+ literal «2»
6
+ block {
7
+ sample «3»
8
+ sample «4»
9
+ }
10
+ }
11
+
12
+ # local values:
13
+ «1» float: 9.128
14
+ «2» code: block {literal code «5» block {sample bool «6»}}
15
+ «3» image: file:///881727183.jpg
16
+ «4» int: 881
17
+ «5» code: block { do int_add do int_multiply }
18
+ «6» bool: false
19
+
20
+ # local values can include references to other local values, but can never backtrack
21
+ # syntax check: are all local values assigned?
22
+ # syntax check: are all local values strings?
23
+ # semantic check: are there no backward-references?
@@ -0,0 +1,5 @@
1
+ Description:
2
+
3
+
4
+ Usage:
5
+
@@ -0,0 +1,73 @@
1
+ class NudgeGenerator < RubiGen::Base
2
+
3
+ DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
4
+ Config::CONFIG['ruby_install_name'])
5
+
6
+ default_options :author => nil
7
+
8
+ attr_reader :name
9
+
10
+ def initialize(runtime_args, runtime_options = {})
11
+ super
12
+ usage if args.empty?
13
+ @destination_root = File.expand_path(args.shift)
14
+ @name = base_name
15
+ extract_options
16
+ end
17
+
18
+ def manifest
19
+ record do |m|
20
+ # Ensure appropriate folder(s) exists
21
+ m.directory ''
22
+ BASEDIRS.each { |path| m.directory path }
23
+
24
+ # Create stubs
25
+ # m.template "template.rb", "some_file_after_erb.rb"
26
+ # m.template_copy_each ["template.rb", "template2.rb"]
27
+ # m.file "file", "some_file_copied"
28
+
29
+ m.file "activate.rb", "activate.rb"
30
+
31
+ # m.file_copy_each ["path/to/file", "path/to/file2"]
32
+
33
+ m.dependency "install_rubigen_scripts", [destination_root, 'nudge'],
34
+ :shebang => options[:shebang], :collision => :force
35
+ end
36
+ end
37
+
38
+ protected
39
+ def banner
40
+ <<-EOS
41
+ Creates a ...
42
+
43
+ USAGE: #{spec.name} name
44
+ EOS
45
+ end
46
+
47
+ def add_options!(opts)
48
+ opts.separator ''
49
+ opts.separator 'Options:'
50
+ # For each option below, place the default
51
+ # at the top of the file next to "default_options"
52
+ # opts.on("-a", "--author=\"Your Name\"", String,
53
+ # "Some comment about this option",
54
+ # "Default: none") { |o| options[:author] = o }
55
+ opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
56
+ end
57
+
58
+ def extract_options
59
+ # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
60
+ # Templates can access these value via the attr_reader-generated methods, but not the
61
+ # raw instance variable value.
62
+ # @author = options[:author]
63
+ end
64
+
65
+ # Installation skeleton. Intermediate directories are automatically
66
+ # created so don't sweat their absence here.
67
+ BASEDIRS = %w(
68
+ config
69
+ experiment
70
+ spec
71
+ tmp
72
+ )
73
+ end
File without changes
data/bin/nudge ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'rubigen'
5
+
6
+ if %w(-v --version).include? ARGV.first
7
+ require 'nudge/version'
8
+ puts "#{File.basename($0)} #{Nudge::VERSION}"
9
+ exit(0)
10
+ end
11
+
12
+ require 'rubigen/scripts/generate'
13
+ source = RubiGen::PathSource.new(:application,
14
+ File.join(File.dirname(__FILE__), "../app_generators"))
15
+ RubiGen::Base.reset_sources
16
+ RubiGen::Base.append_sources source
17
+ RubiGen::Scripts::Generate.new.run(ARGV, :generator => 'nudge')
@@ -101,15 +101,18 @@ module Nudge
101
101
  def enable(item)
102
102
  if item.superclass == Instruction
103
103
  @instructions_library[item] = item.new(self)
104
- elsif item.superclass == NudgeType
104
+ elsif item.include? NudgeType
105
105
  @types |= [item]
106
106
  end
107
107
  end
108
108
 
109
109
  def active?(item)
110
+ puts "#{item.inspect} is the item"
110
111
  if item.superclass == Instruction
111
112
  @instructions_library.include?(item)
112
- elsif item.superclass == NudgeType
113
+ elsif item.include? NudgeType
114
+ puts "#{@types} is the type list"
115
+
113
116
  @types.include?(item)
114
117
  end
115
118
  end
@@ -160,7 +163,7 @@ module Nudge
160
163
  def disable(item)
161
164
  if item.superclass == Instruction
162
165
  @instructions_library.delete(item)
163
- elsif item.superclass == NudgeType
166
+ elsif item.include? NudgeType
164
167
  @types.delete(item)
165
168
  end
166
169
  end
@@ -82,7 +82,7 @@ module Nudge
82
82
  def randomize(context)
83
83
  raise(ArgumentError,"Random code cannot be created") if context.types == [CodeType]
84
84
  newType = context.types.sample
85
- @type = newType.to_s.slice(0..-5).downcase
85
+ @type = newType.to_nudgecode
86
86
  if newType != CodeType
87
87
  @value = newType.any_value
88
88
  else
@@ -123,7 +123,7 @@ module Nudge
123
123
 
124
124
  def randomize(context)
125
125
  newType = context.types.sample
126
- @type = newType.to_s.slice(0..-5).downcase
126
+ @type = newType.to_nudgecode
127
127
  if newType != CodeType
128
128
  @value = newType.any_value
129
129
  else
@@ -1,108 +1,111 @@
1
1
  # coding: utf-8
2
-
3
- class CodeType < NudgeType
4
- @@defaultPoints = 20
2
+ module NudgeType
5
3
 
6
- def self.random_skeleton(points=@@defaultPoints, blocks=points/10)
7
- blocks = [0,[points,blocks].min].max
4
+ class CodeType
5
+ include TypeBehaviors
6
+ @@defaultPoints = 20
7
+
8
+ def self.random_skeleton(points=@@defaultPoints, blocks=points/10)
9
+ blocks = [0,[points,blocks].min].max
8
10
 
9
- if points > 1
10
- skel = ["block {"]
11
- (points-2).times {skel << "*"}
12
- skel << "*}"
13
- front = 0
14
- (blocks-1).times do
15
- until skel[front].include?("*") do
16
- a,b = rand(points), rand(points)
17
- front,back = [a,b].min, [a,b].max
11
+ if points > 1
12
+ skel = ["block {"]
13
+ (points-2).times {skel << "*"}
14
+ skel << "*}"
15
+ front = 0
16
+ (blocks-1).times do
17
+ until skel[front].include?("*") do
18
+ a,b = rand(points), rand(points)
19
+ front,back = [a,b].min, [a,b].max
20
+ end
21
+ skel[front] = skel[front].sub(/\*/," block {")
22
+ skel[back] = skel[back] + "}"
18
23
  end
19
- skel[front] = skel[front].sub(/\*/," block {")
20
- skel[back] = skel[back] + "}"
21
- end
22
- skel = skel.join
23
- else
24
- if blocks>0
25
- skel = "block {}"
24
+ skel = skel.join
26
25
  else
27
- skel = "*"
26
+ if blocks>0
27
+ skel = "block {}"
28
+ else
29
+ skel = "*"
30
+ end
28
31
  end
32
+ return skel
29
33
  end
30
- return skel
31
- end
32
34
 
33
35
 
34
- def self.any_type(types)
35
- raise(ArgumentError,"no available NudgeTypes") if types.empty?
36
- return types.sample
37
- end
36
+ def self.any_type(types)
37
+ raise(ArgumentError,"no available NudgeTypes") if types.empty?
38
+ return types.sample
39
+ end
38
40
 
39
41
 
40
- def self.any_instruction(instructions)
41
- raise(ArgumentError,"no available Instructions") if instructions.empty?
42
- return instructions.sample
43
- end
42
+ def self.any_instruction(instructions)
43
+ raise(ArgumentError,"no available Instructions") if instructions.empty?
44
+ return instructions.sample
45
+ end
44
46
 
45
47
 
46
- def self.any_reference(references)
47
- raise(ArgumentError,"no available references") if references.empty?
48
- return references.sample
49
- end
48
+ def self.any_reference(references)
49
+ raise(ArgumentError,"no available references") if references.empty?
50
+ return references.sample
51
+ end
50
52
 
51
53
 
52
- def self.roulette_wheel(references, instructions, types)
53
- basis = Hash["reference", references.length,
54
- "instruction", instructions.length,
55
- "sample", types.length]
56
- sum = basis.values.inject(:+)
57
- spin = rand(sum)
58
- basis.each do |result,weight|
59
- return result if spin <= weight && weight > 0
60
- spin -= weight
54
+ def self.roulette_wheel(references, instructions, types)
55
+ basis = Hash["reference", references.length,
56
+ "instruction", instructions.length,
57
+ "sample", types.length]
58
+ sum = basis.values.inject(:+)
59
+ spin = rand(sum)
60
+ basis.each do |result,weight|
61
+ return result if spin <= weight && weight > 0
62
+ spin -= weight
63
+ end
64
+ raise "A problem occurred when executing CodeType#roulette_wheel"
61
65
  end
62
- raise "A problem occurred when executing CodeType#roulette_wheel"
63
- end
64
66
 
65
67
 
66
- def self.random_value(context, params = {})
67
- points = params[:points] || @@defaultPoints
68
- blocks = params[:blocks] || points/10
69
- skeleton = params[:skeleton] || self.random_skeleton(points, blocks)
70
- instructions = params[:instructions] || context.instructions
71
- references = params[:references] || context.references
72
- types = params[:types] || context.types
68
+ def self.random_value(context, params = {})
69
+ points = params[:points] || @@defaultPoints
70
+ blocks = params[:blocks] || points/10
71
+ skeleton = params[:skeleton] || self.random_skeleton(points, blocks)
72
+ instructions = params[:instructions] || context.instructions
73
+ references = params[:references] || context.references
74
+ types = params[:types] || context.types
73
75
 
74
- while skeleton.include?("*") do
75
- case self.roulette_wheel(references,instructions,types)
76
- when "instruction"
77
- newPoint = " do " + self.any_instruction(instructions).to_nudgecode
78
- when "reference"
79
- newPoint = " ref " + self.any_reference(references)
80
- when "sample"
81
- theType = any_type(types)
82
- if theType == CodeType
83
- if types != [CodeType]
84
- theType = self.any_type(types - [CodeType])
85
- else
86
- raise ArgumentError, "Random code cannot be created"
76
+ while skeleton.include?("*") do
77
+ case self.roulette_wheel(references,instructions,types)
78
+ when "instruction"
79
+ newPoint = " do " + self.any_instruction(instructions).to_nudgecode
80
+ when "reference"
81
+ newPoint = " ref " + self.any_reference(references)
82
+ when "sample"
83
+ theType = any_type(types)
84
+ if theType == CodeType
85
+ if types != [CodeType]
86
+ theType = self.any_type(types - [CodeType])
87
+ else
88
+ raise ArgumentError, "Random code cannot be created"
89
+ end
87
90
  end
91
+ newPoint = " sample " + theType.to_nudgecode + " (" + theType.any_value.to_s + ")"
92
+ else
93
+ raise ArgumentError, "Nothing to make random code from"
88
94
  end
89
- newPoint = " sample " + theType.to_nudgecode + " (" + theType.any_value.to_s + ")"
90
- else
91
- raise ArgumentError, "Nothing to make random code from"
95
+ skeleton = skeleton.sub(/\*/, newPoint)
96
+ skeleton = skeleton.sub(/\n/,'')
92
97
  end
93
- skeleton = skeleton.sub(/\*/, newPoint)
94
- skeleton = skeleton.sub(/\n/,'')
98
+ skeleton
95
99
  end
96
- skeleton
97
- end
98
100
 
99
101
 
100
102
 
101
- def self.from_s(string_value)
102
- return string_value.sub(/\(/,"«").sub(/\)/,"»")
103
- end
103
+ def self.from_s(string_value)
104
+ return string_value.sub(/\(/,"«").sub(/\)/,"»")
105
+ end
104
106
 
105
- def self.any_value(context)
106
- self.random_value(context)
107
+ def self.any_value(context)
108
+ self.random_value(context)
109
+ end
107
110
  end
108
111
  end
@@ -1,102 +1,115 @@
1
1
  # coding: utf-8
2
2
 
3
- class NudgeType
4
- require 'singleton'
5
- include Singleton
6
-
7
- @@all_types = []
8
-
9
- def self.inherited(subclass)
10
- @@all_types << subclass
11
- super
12
- end
3
+ module NudgeType
13
4
 
14
5
  def self.all_types
15
- @@all_types
6
+ @all_types ||= []
16
7
  end
17
8
 
18
9
  def self.push_types
19
10
  [IntType, BoolType, FloatType]
20
11
  end
21
12
 
22
- def self.to_nudgecode
23
- self.to_s.slice(0..-5).downcase
24
- end
25
-
26
- def self.from_s
27
- raise "Your subclass of NudgeType should provide a method for parsing string values in code"
28
- end
29
- end
30
-
13
+ module TypeBehaviors
14
+ def self.extended(subclass)
15
+ NudgeType.all_types << subclass
16
+ end
17
+
18
+ def to_nudgecode
19
+ self.to_s.demodulize.slice(0..-5).downcase.intern
20
+ end
31
21
 
22
+ def from_s(some_string)
23
+ raise "This class must implement #{self.inspect}.from_s"
24
+ end
32
25
 
26
+ def any_value
27
+ raise "This class must implement #{self.inspect}.any_value"
28
+ end
33
29
 
34
- class IntType < NudgeType
35
- @defaultLowest = -100
36
- @defaultHighest = 100
37
-
38
- def self.defaultLowest
39
- @defaultLowest
30
+ def random_value(params)
31
+ raise "This class must implement #{self.inspect}.random_value"
32
+ end
40
33
  end
41
34
 
42
- def self.defaultHighest
43
- @defaultHighest
35
+ class BasicType
36
+ def self.inherited(subclass)
37
+ subclass.extend TypeBehaviors
38
+ end
44
39
  end
45
40
 
46
- def self.random_value(params={})
47
- bottom = params[:randomIntegerLowerBound] || @defaultLowest
48
- top = params[:randomIntegerUpperBound] || @defaultHighest
49
- lowest, highest = [bottom,top].min, [bottom,top].max
50
- rand(highest-lowest).to_i + lowest
51
- end
52
-
53
- def self.from_s(string_value)
54
- return string_value.to_i
55
- end
56
-
57
- def self.any_value
58
- self.random_value
59
- end
60
- end
41
+ class IntType < Fixnum
42
+ extend TypeBehaviors
43
+ @defaultLowest = -100
44
+ @defaultHighest = 100
61
45
 
46
+ def self.defaultLowest
47
+ @defaultLowest
48
+ end
62
49
 
50
+ def self.defaultHighest
51
+ @defaultHighest
52
+ end
63
53
 
54
+ def self.random_value(params={})
55
+ bottom = params[:randomIntegerLowerBound] || @defaultLowest
56
+ top = params[:randomIntegerUpperBound] || @defaultHighest
57
+ lowest, highest = [bottom,top].min, [bottom,top].max
58
+ rand(highest-lowest).to_i + lowest
59
+ end
64
60
 
65
- class BoolType < NudgeType
66
- def self.random_value(params = {})
67
- p = params[:randomBooleanTruthProb] || 0.5
68
- rand() < p
69
- end
70
-
71
- def self.from_s(string_value)
72
- return string_value.downcase == "true"
73
- end
74
-
75
- def self.any_value
76
- self.random_value
61
+ def self.from_s(string_value)
62
+ return string_value.to_i
63
+ end
64
+
65
+ def self.any_value
66
+ self.random_value
67
+ end
77
68
  end
78
- end
79
69
 
80
70
 
81
71
 
82
72
 
83
- class FloatType < NudgeType
84
- @defaultLowest = -1000.0
85
- @defaultHighest = 1000.0
86
-
87
- def self.random_value(params = {})
88
- bottom = params[:randomFloatLowerBound] || @defaultLowest
89
- top = params[:randomFloatUpperBound] || @defaultHighest
90
- bottom, top = [bottom,top].min, [bottom,top].max
91
- range = top - bottom
92
- (rand*range) + bottom
93
- end
94
-
95
- def self.from_s(string_value)
96
- return string_value.to_f
73
+ class BoolType
74
+ extend TypeBehaviors
75
+
76
+ def self.random_value(params = {})
77
+ p = params[:randomBooleanTruthProb] || 0.5
78
+ rand() < p
79
+ end
80
+
81
+ def self.from_s(string_value)
82
+ string_value.downcase == "true" ? true : false
83
+ end
84
+
85
+ def self.any_value
86
+ self.random_value
87
+ end
97
88
  end
98
-
99
- def self.any_value
100
- self.random_value
89
+
90
+
91
+
92
+
93
+ class FloatType < Float
94
+ extend TypeBehaviors
95
+
96
+ @defaultLowest = -1000.0
97
+ @defaultHighest = 1000.0
98
+
99
+ def self.random_value(params = {})
100
+ bottom = params[:randomFloatLowerBound] || @defaultLowest
101
+ top = params[:randomFloatUpperBound] || @defaultHighest
102
+ bottom, top = [bottom,top].min, [bottom,top].max
103
+ range = top - bottom
104
+ (rand*range) + bottom
105
+ end
106
+
107
+ def self.from_s(string_value)
108
+ return string_value.to_f
109
+ end
110
+
111
+ def self.any_value
112
+ self.random_value
113
+ end
101
114
  end
102
- end
115
+ end
data/lib/nudge.rb CHANGED
@@ -35,4 +35,6 @@ require 'search/operators/basic_operators'
35
35
  require 'search/operators/samplers_and_selectors'
36
36
  require 'search/operators/evaluators'
37
37
  require 'search/stations/station'
38
- require 'search/experiments/experiment'
38
+ require 'search/experiments/experiment'
39
+
40
+ include NudgeType
@@ -28,9 +28,7 @@ module Nudge
28
28
  attr_reader :id
29
29
 
30
30
  def initialize(listing)
31
- @helperParser =
32
-
33
- @genome = listing
31
+ @helperParser = @genome = listing
34
32
  raise(ArgumentError, "Nudge program cannot be parsed") if Individual.helperParser.parse(genome) == nil
35
33
  @program = Individual.helperParser.parse(genome).to_points
36
34
  @scores = Hash.new