biopsy 0.1.7 → 0.1.9
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.
- checksums.yaml +4 -4
- data/lib/biopsy/experiment.rb +17 -9
- data/lib/biopsy/objectives/fastest_optimum.rb +1 -1
- data/lib/biopsy/optimisers/parameter_sweeper.rb +39 -11
- data/lib/biopsy/settings.rb +4 -2
- data/lib/biopsy/target.rb +23 -1
- data/lib/biopsy/version.rb +2 -2
- data/test/helper.rb +4 -0
- data/test/test_experiment.rb +22 -4
- data/test/test_target.rb +9 -0
- metadata +34 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd71d61a677d1be5a428a38587f2a81a2215f3ef
|
4
|
+
data.tar.gz: ce06d5dd2fadae096a852560cff2093fc5db249c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d400127139fdd1c30a39e1304fd23ebe87cc95bbb2ac0f304de3492057a5b27069f038dfe7940ecc03c89a5311ccdf2d234a5420d3e9d8b1530607f053023e2b
|
7
|
+
data.tar.gz: 3145eb5f5826d1e90745986e1305eff1f10eb327a74107077dee0807d1f8735281ce056edf9e43b9e567442afa94122b0dcc512264ca4877f2e28f31f92f3fdd
|
data/lib/biopsy/experiment.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# Optimisation Framework: Experiment
|
2
2
|
#
|
3
3
|
# == Description
|
4
4
|
#
|
@@ -12,6 +12,8 @@
|
|
12
12
|
# cycle. It takes user input, runs the target program, the objective function(s)
|
13
13
|
# and the optimisation algorithm, looping through the optimisation cycle until
|
14
14
|
# completion and then returning the output.
|
15
|
+
require 'logger'
|
16
|
+
|
15
17
|
module Biopsy
|
16
18
|
|
17
19
|
class Experiment
|
@@ -19,10 +21,11 @@ module Biopsy
|
|
19
21
|
attr_reader :inputs, :outputs, :retain_intermediates, :target, :start, :algorithm
|
20
22
|
|
21
23
|
# Returns a new Experiment
|
22
|
-
def initialize(target, options
|
24
|
+
def initialize(target, options:{}, threads:4, start:nil, algorithm:nil, verbosity: :quiet)
|
23
25
|
@threads = threads
|
24
26
|
@start = start
|
25
27
|
@algorithm = algorithm
|
28
|
+
@verbosity = verbosity
|
26
29
|
if target.is_a? Target
|
27
30
|
@target = target
|
28
31
|
else
|
@@ -38,7 +41,7 @@ module Biopsy
|
|
38
41
|
|
39
42
|
# return the set of parameters to evaluate first
|
40
43
|
def select_starting_point
|
41
|
-
return
|
44
|
+
return if !@start.nil?
|
42
45
|
if @algorithm && @algorithm.knows_starting_point?
|
43
46
|
@start = @algorithm.select_starting_point
|
44
47
|
else
|
@@ -53,6 +56,7 @@ module Biopsy
|
|
53
56
|
|
54
57
|
# select the optimisation algorithm to use
|
55
58
|
def select_algorithm
|
59
|
+
return if !algorithm.nil?
|
56
60
|
max = Settings.instance.sweep_cutoff
|
57
61
|
n = @target.count_parameter_permutations
|
58
62
|
if n < max
|
@@ -82,13 +86,15 @@ module Biopsy
|
|
82
86
|
@best = @algorithm.best
|
83
87
|
ptext = @best[:parameters].each_pair.map{ |k, v| "#{k}:#{v}" }.join(", ")
|
84
88
|
if (@best && @best.has_key?(:score) && best && best.has_key?(:score) && @best[:score] > best[:score])
|
85
|
-
puts "found a new best score: #{@best[:score]} for parameters #{ptext}"
|
89
|
+
puts "found a new best score: #{@best[:score]} for parameters #{ptext}" unless @verbosity == :silent
|
86
90
|
end
|
87
91
|
# have we finished?
|
88
92
|
in_progress = !@algorithm.finished?
|
89
93
|
end
|
90
94
|
@algorithm.write_data if @algorithm.respond_to? :write_data
|
91
|
-
|
95
|
+
unless @verbosity == :silent
|
96
|
+
puts "found optimum score: #{@best[:score]} for parameters #{@best[:parameters]} in #{@iteration_count} iterations."
|
97
|
+
end
|
92
98
|
return @best
|
93
99
|
end
|
94
100
|
|
@@ -118,10 +124,12 @@ module Biopsy
|
|
118
124
|
end
|
119
125
|
|
120
126
|
def print_progress(iteration, params, score, best)
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
127
|
+
unless [:silent, :quiet].include? @verbosity
|
128
|
+
ptext = params.each_pair.map{ |k, v| "#{k}:#{v}" }.join(", ")
|
129
|
+
msg = "run #{iteration}. parameters: #{ptext} | score: #{score}"
|
130
|
+
msg += " | best #{best[:score]}" if (best && best.has_key?(:score))
|
131
|
+
puts msg
|
132
|
+
end
|
125
133
|
end
|
126
134
|
|
127
135
|
def cleanup
|
@@ -24,7 +24,7 @@ module Biopsy
|
|
24
24
|
|
25
25
|
attr_reader :combinations
|
26
26
|
|
27
|
-
def initialize(ranges, threads
|
27
|
+
def initialize(ranges, threads:1, limit:1000)
|
28
28
|
@ranges = ranges
|
29
29
|
# parameter_counter: a count of input parameters to be used
|
30
30
|
@parameter_counter = 1
|
@@ -32,29 +32,41 @@ module Biopsy
|
|
32
32
|
@combinations = []
|
33
33
|
# if the number of threads is set, update the global variable, if not default to 1
|
34
34
|
@threads = threads
|
35
|
+
# set the limit to the number of parameters
|
36
|
+
@limit = limit
|
35
37
|
# convert all options to an array so it can be handled by the generate_combinations() method
|
36
38
|
# ..this is for users entering single values e.g 4 as a parameter
|
37
39
|
@ranges.each { |key, value| value = [value] unless value.kind_of? Array }
|
38
|
-
self.generate_combinations
|
40
|
+
self.generate_combinations(0, {})
|
39
41
|
# restrict to a subsample?
|
40
|
-
|
41
|
-
|
42
|
+
|
43
|
+
if @limit < @combinations.size
|
44
|
+
@combinations = @combinations.sample @limit
|
42
45
|
end
|
43
46
|
end
|
44
47
|
|
45
48
|
def setup *args
|
46
|
-
|
49
|
+
@best = {
|
50
|
+
:parameters => nil,
|
51
|
+
:score => nil
|
52
|
+
}
|
47
53
|
end
|
48
54
|
|
49
55
|
# return the next parameter set to evaluate
|
50
|
-
def run_one_iteration
|
51
|
-
@
|
52
|
-
|
53
|
-
nil
|
56
|
+
def run_one_iteration(parameters, score)
|
57
|
+
@current = {:parameters => parameters, :score => score}
|
58
|
+
self.update_best?
|
59
|
+
@combinations.pop rescue nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def update_best?
|
63
|
+
if @best[:score].nil? || @current[:score] > @best[:score]
|
64
|
+
@best = @current.clone
|
65
|
+
end
|
54
66
|
end
|
55
67
|
|
56
68
|
# generate all the parameter combinations to be applied
|
57
|
-
def generate_combinations(index
|
69
|
+
def generate_combinations(index, opts)
|
58
70
|
if index == @ranges.length
|
59
71
|
@combinations << opts.clone
|
60
72
|
return
|
@@ -67,13 +79,29 @@ module Biopsy
|
|
67
79
|
end
|
68
80
|
end
|
69
81
|
|
82
|
+
def best
|
83
|
+
@best
|
84
|
+
end
|
85
|
+
|
70
86
|
def knows_starting_point?
|
71
87
|
true
|
72
88
|
end
|
73
89
|
|
74
90
|
def select_starting_point
|
75
|
-
|
91
|
+
return @combinations.pop
|
92
|
+
end
|
93
|
+
|
94
|
+
def random_start_point
|
95
|
+
return @combinations.pop
|
96
|
+
end
|
97
|
+
|
98
|
+
def finished?
|
99
|
+
return @combinations.empty?
|
76
100
|
end
|
77
101
|
|
102
|
+
# True if this algorithm chooses its own starting point
|
103
|
+
def knows_starting_point?
|
104
|
+
true
|
105
|
+
end
|
78
106
|
end
|
79
107
|
end
|
data/lib/biopsy/settings.rb
CHANGED
@@ -51,7 +51,8 @@ module Biopsy
|
|
51
51
|
# specified, the default location ('~/.biopsyrc') is used.
|
52
52
|
# Settings loaded from the file are merged into any
|
53
53
|
# previously loaded settings.
|
54
|
-
def load
|
54
|
+
def load config_file
|
55
|
+
config_file ||= @config_file
|
55
56
|
newsets = YAML::load_file(config_file)
|
56
57
|
raise 'Config file was not valid YAML' if newsets == false
|
57
58
|
newsets.deep_symbolize.each_pair do |key, value|
|
@@ -65,7 +66,8 @@ module Biopsy
|
|
65
66
|
|
66
67
|
# Saves the settings to a YAML config file. If no file is
|
67
68
|
# specified, the default location ('~/.biopsyrc') is used.
|
68
|
-
def save
|
69
|
+
def save config_file
|
70
|
+
config_file ||= @config_file
|
69
71
|
File.open(config_file, 'w') do |f|
|
70
72
|
f.puts self.to_s
|
71
73
|
end
|
data/lib/biopsy/target.rb
CHANGED
@@ -126,6 +126,28 @@ module Biopsy
|
|
126
126
|
@parameters.each_pair.map{ |k, v| v }.reduce(1) { |n, arr| n * arr.size }
|
127
127
|
end
|
128
128
|
|
129
|
-
|
129
|
+
# pass calls to missing methods to the constructor iff
|
130
|
+
# the constructor's class directly defines that method
|
131
|
+
def method_missing(meth, *args, &block)
|
132
|
+
const_methods = @constructor.class.instance_methods(false)
|
133
|
+
if const_methods.include? meth
|
134
|
+
@constructor
|
135
|
+
else
|
136
|
+
super
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# accurately report ability to respond to methods passed
|
141
|
+
# to constructor
|
142
|
+
def method_missing(meth, *args, &block)
|
143
|
+
const_methods = @constructor.class.instance_methods(false)
|
144
|
+
if const_methods.include? meth
|
145
|
+
true
|
146
|
+
else
|
147
|
+
super
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
end # end of class Target
|
130
152
|
|
131
153
|
end # end of module Biopsy
|
data/lib/biopsy/version.rb
CHANGED
data/test/helper.rb
CHANGED
data/test/test_experiment.rb
CHANGED
@@ -5,6 +5,7 @@ class TestExperiment < Test::Unit::TestCase
|
|
5
5
|
context "Experiment" do
|
6
6
|
|
7
7
|
setup do
|
8
|
+
# create a target called 'target_test'
|
8
9
|
@h = Helper.new
|
9
10
|
@h.setup_tmp_dir
|
10
11
|
|
@@ -46,8 +47,8 @@ class TestExperiment < Test::Unit::TestCase
|
|
46
47
|
end
|
47
48
|
|
48
49
|
should "respect user's choice of starting point" do
|
49
|
-
s = {:a =>
|
50
|
-
e = Biopsy::Experiment.new('target_test', start
|
50
|
+
s = {:a => 4, :b => 2}
|
51
|
+
e = Biopsy::Experiment.new('target_test', start: s, verbosity: :silent)
|
51
52
|
assert_equal s, e.start
|
52
53
|
end
|
53
54
|
|
@@ -57,15 +58,32 @@ class TestExperiment < Test::Unit::TestCase
|
|
57
58
|
end
|
58
59
|
|
59
60
|
should "return an optimal set of parameters and score when run" do
|
60
|
-
# Kernel.srand 123
|
61
61
|
Dir.chdir @h.tmp_dir do
|
62
|
-
e = Biopsy::Experiment.new('target_test')
|
62
|
+
e = Biopsy::Experiment.new('target_test', verbosity: :silent)
|
63
63
|
known_best = -4
|
64
64
|
best_found = e.run[:score]
|
65
65
|
assert known_best < best_found
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
+
should "run really quickly when starting from the optimal parameters" do
|
70
|
+
Dir.chdir @h.tmp_dir do
|
71
|
+
s = {:a => 4, :b => 4, :c => 4}
|
72
|
+
e = Biopsy::Experiment.new('target_test', start: s, verbosity: :silent)
|
73
|
+
known_best = -4
|
74
|
+
best_found = e.run[:score]
|
75
|
+
assert known_best < best_found
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
should "run using the parameter sweeper (with limit)" do
|
80
|
+
Dir.chdir @h.tmp_dir do
|
81
|
+
p = Biopsy::ParameterSweeper.new(@target.parameters, limit: 250)
|
82
|
+
e = Biopsy::Experiment.new('target_test', algorithm: p, verbosity: :silent)
|
83
|
+
best_found = e.run[:score]
|
84
|
+
assert best_found != nil
|
85
|
+
end
|
86
|
+
end
|
69
87
|
end # Experiment context
|
70
88
|
|
71
89
|
end # TestExperiment
|
data/test/test_target.rb
CHANGED
@@ -95,6 +95,15 @@ class TestTarget < Test::Unit::TestCase
|
|
95
95
|
File.delete @target.constructor_path
|
96
96
|
end
|
97
97
|
|
98
|
+
should "pass missing method calls to constructor iff it directly defines them" do
|
99
|
+
# this method is defined on the constructor in helper.rb
|
100
|
+
assert_send([@target, :fake_method],
|
101
|
+
'valid method not passed to constructor')
|
102
|
+
assert_raise NoMethodError do
|
103
|
+
@target.totes_fake_method
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
98
107
|
end # Target context
|
99
108
|
|
100
109
|
end # TestTarget context
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: biopsy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 10.
|
19
|
+
version: '10.3'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 10.
|
26
|
+
version: '10.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: threach
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: turn
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,30 +142,30 @@ executables: []
|
|
128
142
|
extensions: []
|
129
143
|
extra_rdoc_files: []
|
130
144
|
files:
|
145
|
+
- LICENSE.txt
|
146
|
+
- README.md
|
131
147
|
- Rakefile
|
132
148
|
- lib/biopsy.rb
|
133
|
-
- lib/biopsy/
|
149
|
+
- lib/biopsy/base_extensions.rb
|
150
|
+
- lib/biopsy/experiment.rb
|
151
|
+
- lib/biopsy/objective_function.rb
|
134
152
|
- lib/biopsy/objective_handler.rb
|
135
153
|
- lib/biopsy/objectives/fastest_optimum.rb
|
136
|
-
- lib/biopsy/settings.rb
|
137
|
-
- lib/biopsy/optimisers/tabu_search.rb
|
138
154
|
- lib/biopsy/optimisers/genetic_algorithm.rb
|
139
|
-
- lib/biopsy/optimisers/spea2.rb
|
140
155
|
- lib/biopsy/optimisers/parameter_sweeper.rb
|
141
|
-
- lib/biopsy/
|
156
|
+
- lib/biopsy/optimisers/spea2.rb
|
157
|
+
- lib/biopsy/optimisers/tabu_search.rb
|
158
|
+
- lib/biopsy/settings.rb
|
142
159
|
- lib/biopsy/target.rb
|
143
|
-
- lib/biopsy/
|
144
|
-
- lib/biopsy/experiment.rb
|
145
|
-
- test/test_target.rb
|
146
|
-
- test/test_hash.rb
|
147
|
-
- test/test_string.rb
|
160
|
+
- lib/biopsy/version.rb
|
148
161
|
- test/helper.rb
|
149
|
-
- test/
|
162
|
+
- test/test_experiment.rb
|
150
163
|
- test/test_file.rb
|
164
|
+
- test/test_hash.rb
|
165
|
+
- test/test_objective_handler.rb
|
151
166
|
- test/test_settings.rb
|
152
|
-
- test/
|
153
|
-
-
|
154
|
-
- LICENSE.txt
|
167
|
+
- test/test_string.rb
|
168
|
+
- test/test_target.rb
|
155
169
|
homepage: https://github.com/Blahah/biopsy
|
156
170
|
licenses: []
|
157
171
|
metadata: {}
|
@@ -171,8 +185,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
171
185
|
version: '0'
|
172
186
|
requirements: []
|
173
187
|
rubyforge_project:
|
174
|
-
rubygems_version: 2.
|
188
|
+
rubygems_version: 2.2.2
|
175
189
|
signing_key:
|
176
190
|
specification_version: 4
|
177
191
|
summary: framework for optimising any computational pipeline or program
|
178
192
|
test_files: []
|
193
|
+
has_rdoc:
|