evoasm 0.0.2.pre7 → 0.1.0.pre2
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/.gdbinit +41 -0
- data/.gitignore +1 -2
- data/.gitmodules +3 -0
- data/.rubocop.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE.md +660 -0
- data/Makefile +1 -1
- data/README.md +17 -9
- data/Rakefile +39 -107
- data/bin/gdb +1 -1
- data/bin/gdb_loop +4 -0
- data/docs/FindingInstructions.md +17 -0
- data/docs/JIT.md +14 -0
- data/docs/SymbolicRegression.md +102 -0
- data/docs/Visualization.md +29 -0
- data/docs/examples/bit_insts.rb +44 -0
- data/docs/examples/jit.rb +26 -0
- data/docs/examples/loss.gif +0 -0
- data/docs/examples/program.png +0 -0
- data/docs/examples/sym_reg.rb +64 -0
- data/docs/examples/vis.rb +38 -0
- data/evoasm.gemspec +21 -15
- data/ext/evoasm_ext/Rakefile +3 -0
- data/ext/evoasm_ext/compile.rake +35 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.c +226 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.h +84 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-arch.c +52 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-arch.h +101 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-bitmap.h +158 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-buf.c +204 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-buf.h +109 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-domain.c +124 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-domain.h +279 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-error.c +65 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-error.h +108 -0
- data/ext/evoasm_ext/{evoasm-log.c → libevoasm/src/evoasm-log.c} +36 -18
- data/ext/evoasm_ext/libevoasm/src/evoasm-log.h +93 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-param.c +22 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-param.h +33 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.c +192 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.h +60 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-pop.c +1323 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-pop.h +107 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.c +116 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.h +60 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-program.c +1827 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-program.h +167 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-rand.c +65 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-rand.h +76 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-signal.c +106 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-signal.h +58 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-util.h +112 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-x64.c +925 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-x64.h +277 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm.c +28 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm.h +35 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-enums.h +2077 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.c +191203 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.h +1713 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.c +348 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.h +93 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.c +51 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.h +509 -0
- data/lib/evoasm.rb +28 -11
- data/lib/evoasm/buffer.rb +105 -0
- data/lib/evoasm/capstone.rb +100 -0
- data/lib/evoasm/domain.rb +116 -0
- data/lib/evoasm/error.rb +37 -16
- data/lib/evoasm/exception_error.rb +19 -0
- data/lib/evoasm/ffi_ext.rb +53 -0
- data/lib/evoasm/libevoasm.rb +286 -0
- data/lib/evoasm/libevoasm/x64_enums.rb +1967 -0
- data/lib/evoasm/parameter.rb +20 -0
- data/lib/evoasm/population.rb +145 -0
- data/lib/evoasm/population/parameters.rb +227 -0
- data/lib/evoasm/population/plotter.rb +89 -0
- data/lib/evoasm/prng.rb +64 -0
- data/lib/evoasm/program.rb +195 -12
- data/lib/evoasm/program/io.rb +144 -0
- data/lib/evoasm/test.rb +8 -0
- data/lib/evoasm/version.rb +1 -1
- data/lib/evoasm/x64.rb +115 -0
- data/lib/evoasm/x64/cpu_state.rb +95 -0
- data/lib/evoasm/x64/instruction.rb +109 -0
- data/lib/evoasm/x64/operand.rb +156 -0
- data/lib/evoasm/x64/parameters.rb +211 -0
- data/test/helpers/population_helper.rb +128 -0
- data/test/helpers/test_helper.rb +1 -0
- data/test/helpers/x64_helper.rb +24 -0
- data/test/integration/bitwise_reverse_test.rb +41 -0
- data/test/integration/gcd_test.rb +52 -0
- data/test/integration/popcnt_test.rb +46 -0
- data/test/integration/sym_reg_test.rb +68 -0
- data/test/unit/evoasm/buffer_test.rb +48 -0
- data/test/unit/evoasm/capstone_test.rb +18 -0
- data/test/unit/evoasm/domain_test.rb +55 -0
- data/test/unit/evoasm/population/parameters_test.rb +106 -0
- data/test/unit/evoasm/population_test.rb +96 -0
- data/test/unit/evoasm/prng_test.rb +47 -0
- data/test/unit/evoasm/x64/cpu_state_test.rb +73 -0
- data/test/unit/evoasm/x64/encoding_test.rb +320 -0
- data/test/unit/evoasm/x64/instruction_access_test.rb +177 -0
- data/test/unit/evoasm/x64/instruction_encoding_test.rb +780 -0
- data/test/unit/evoasm/x64/instruction_test.rb +62 -0
- data/test/unit/evoasm/x64/parameters_test.rb +65 -0
- data/test/unit/evoasm/x64_test.rb +52 -0
- metadata +195 -89
- data/Gemfile.rake +0 -8
- data/Gemfile.rake.lock +0 -51
- data/LICENSE.txt +0 -373
- data/data/tables/README.md +0 -19
- data/data/tables/x64.csv +0 -1684
- data/data/templates/evoasm-x64.c.erb +0 -319
- data/data/templates/evoasm-x64.h.erb +0 -126
- data/examples/abs.yml +0 -20
- data/examples/popcnt.yml +0 -17
- data/examples/sym_reg.yml +0 -26
- data/exe/evoasm-search +0 -13
- data/ext/evoasm_ext/evoasm-alloc.c +0 -145
- data/ext/evoasm_ext/evoasm-alloc.h +0 -59
- data/ext/evoasm_ext/evoasm-arch.c +0 -44
- data/ext/evoasm_ext/evoasm-arch.h +0 -161
- data/ext/evoasm_ext/evoasm-bitmap.h +0 -114
- data/ext/evoasm_ext/evoasm-buf.c +0 -130
- data/ext/evoasm_ext/evoasm-buf.h +0 -47
- data/ext/evoasm_ext/evoasm-error.c +0 -31
- data/ext/evoasm_ext/evoasm-error.h +0 -75
- data/ext/evoasm_ext/evoasm-free-list.c.tmpl +0 -121
- data/ext/evoasm_ext/evoasm-free-list.h.tmpl +0 -86
- data/ext/evoasm_ext/evoasm-log.h +0 -69
- data/ext/evoasm_ext/evoasm-misc.c +0 -23
- data/ext/evoasm_ext/evoasm-misc.h +0 -282
- data/ext/evoasm_ext/evoasm-param.h +0 -37
- data/ext/evoasm_ext/evoasm-search.c +0 -2145
- data/ext/evoasm_ext/evoasm-search.h +0 -214
- data/ext/evoasm_ext/evoasm-util.h +0 -40
- data/ext/evoasm_ext/evoasm-x64.c +0 -275624
- data/ext/evoasm_ext/evoasm-x64.h +0 -5436
- data/ext/evoasm_ext/evoasm.c +0 -7
- data/ext/evoasm_ext/evoasm.h +0 -23
- data/ext/evoasm_ext/evoasm_ext.c +0 -1757
- data/ext/evoasm_ext/extconf.rb +0 -31
- data/lib/evoasm/cli.rb +0 -6
- data/lib/evoasm/cli/search.rb +0 -127
- data/lib/evoasm/core_ext.rb +0 -1
- data/lib/evoasm/core_ext/array.rb +0 -9
- data/lib/evoasm/core_ext/integer.rb +0 -10
- data/lib/evoasm/core_ext/kwstruct.rb +0 -13
- data/lib/evoasm/core_ext/range.rb +0 -5
- data/lib/evoasm/examples.rb +0 -27
- data/lib/evoasm/gen.rb +0 -8
- data/lib/evoasm/gen/enum.rb +0 -169
- data/lib/evoasm/gen/name_util.rb +0 -80
- data/lib/evoasm/gen/state.rb +0 -176
- data/lib/evoasm/gen/state_dsl.rb +0 -152
- data/lib/evoasm/gen/strio.rb +0 -27
- data/lib/evoasm/gen/translator.rb +0 -1102
- data/lib/evoasm/gen/version.rb +0 -5
- data/lib/evoasm/gen/x64.rb +0 -237
- data/lib/evoasm/gen/x64/funcs.rb +0 -495
- data/lib/evoasm/gen/x64/inst.rb +0 -781
- data/lib/evoasm/search.rb +0 -40
- data/lib/evoasm/tasks/gen_task.rb +0 -86
- data/lib/evoasm/tasks/template_task.rb +0 -52
- data/test/test_helper.rb +0 -1
- data/test/x64/test_helper.rb +0 -19
- data/test/x64/x64_test.rb +0 -87
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'evoasm/domain'
|
|
2
|
+
|
|
3
|
+
module Evoasm
|
|
4
|
+
# Base class for all parameters.
|
|
5
|
+
class Parameter < FFI::Pointer
|
|
6
|
+
|
|
7
|
+
# @return [Integer] a numeric identifier for this parameter
|
|
8
|
+
def id
|
|
9
|
+
Libevoasm.param_get_id self
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# @return [Domain] the domain associated with this parameter
|
|
13
|
+
def domain
|
|
14
|
+
domain = Domain.wrap Libevoasm.param_get_domain(self)
|
|
15
|
+
domain.autorelease = false
|
|
16
|
+
|
|
17
|
+
domain
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
require 'evoasm/error'
|
|
2
|
+
require 'ffi'
|
|
3
|
+
|
|
4
|
+
module Evoasm
|
|
5
|
+
class Population < FFI::AutoPointer
|
|
6
|
+
|
|
7
|
+
# @return [Population::Parameters] population parameters
|
|
8
|
+
attr_reader :parameters
|
|
9
|
+
|
|
10
|
+
# @!visibility private
|
|
11
|
+
def self.release(ptr)
|
|
12
|
+
Libevoasm.pop_destroy(ptr)
|
|
13
|
+
Libevoasm.pop_free(ptr)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @param parameters [Population::Parameters] the population parameters
|
|
17
|
+
# @param architecture [Symbol] architecture, currently only +:x64+ is supported
|
|
18
|
+
def initialize(parameters, architecture = Evoasm.architecture)
|
|
19
|
+
@parameters = parameters
|
|
20
|
+
|
|
21
|
+
ptr = Libevoasm.pop_alloc
|
|
22
|
+
unless Libevoasm.pop_init ptr, architecture, @parameters
|
|
23
|
+
raise Error.last
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
super(ptr)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Evaluates all programs and kernels in the population
|
|
30
|
+
# @return [void]
|
|
31
|
+
def evaluate
|
|
32
|
+
unless Libevoasm.pop_eval self
|
|
33
|
+
raise Error.last
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Seeds the population with random individuals
|
|
38
|
+
# @return [void]
|
|
39
|
+
def seed
|
|
40
|
+
Libevoasm.pop_seed self
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @return [Float] the loss of the best program found so far
|
|
44
|
+
# @see #best_program
|
|
45
|
+
def best_loss
|
|
46
|
+
Libevoasm.pop_get_best_loss self
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @return [Program] the best program found so far
|
|
50
|
+
def best_program
|
|
51
|
+
program = Program.new
|
|
52
|
+
unless Libevoasm.pop_load_best_program self, program
|
|
53
|
+
raise Error.last
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
program
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @!visibility private
|
|
60
|
+
def loss_samples
|
|
61
|
+
Array.new(@parameters.deme_count) do |deme_index|
|
|
62
|
+
data_ptr_ptr = FFI::MemoryPointer.new :pointer, 1
|
|
63
|
+
len = Libevoasm.pop_get_loss_samples self, deme_index, data_ptr_ptr
|
|
64
|
+
data_ptr = data_ptr_ptr.read_pointer
|
|
65
|
+
data_ptr.read_array_of_float len
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Gives a five-number summary for each deme, program and kernel.
|
|
70
|
+
# @return [Array] a 2-dimensional array of summaries.
|
|
71
|
+
def summary(flat: false)
|
|
72
|
+
summary_len = Libevoasm.pop_summary_len self
|
|
73
|
+
summary_ptr = FFI::MemoryPointer.new :float, summary_len
|
|
74
|
+
unless Libevoasm.pop_calc_summary self, summary_ptr
|
|
75
|
+
raise Error.last
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
summary = summary_ptr.read_array_of_float(summary_len).each_slice(summary_len / @parameters.deme_count).to_a
|
|
79
|
+
unless flat
|
|
80
|
+
summary.map!{|deme_summary| deme_summary.each_slice(5).to_a}
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
summary
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Execute a single generational cycle
|
|
87
|
+
# @return [void]
|
|
88
|
+
def next_generation!
|
|
89
|
+
Libevoasm.pop_next_gen self
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Stops the process started by {#run}
|
|
93
|
+
# @return [void]
|
|
94
|
+
def stop
|
|
95
|
+
@stop = true
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Plots the loss function
|
|
99
|
+
# @return [void]
|
|
100
|
+
def plot(filename = nil)
|
|
101
|
+
@plotter ||= Plotter.new self, filename
|
|
102
|
+
@plotter.update
|
|
103
|
+
@plotter.plot
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Starts the evolutionary process on this population
|
|
107
|
+
# @param loss [Float] stop process if a program is found whose loss is less or equal than the specified loss
|
|
108
|
+
# @param min_generations [Integer] minimum number of generations to run
|
|
109
|
+
# @param max_generations [Integer] maximum number of generations to run
|
|
110
|
+
# @param seed [Bool] whether the population should be seeded before starting
|
|
111
|
+
# @yield [self]
|
|
112
|
+
# @yieldreturn a truthy value to stop the process
|
|
113
|
+
# @return [Program] the best program found
|
|
114
|
+
|
|
115
|
+
def run(loss: nil, min_generations: nil, max_generations: 10, seed: true, &block)
|
|
116
|
+
self.seed if seed
|
|
117
|
+
best_program = nil
|
|
118
|
+
best_loss = nil
|
|
119
|
+
generation = 1
|
|
120
|
+
|
|
121
|
+
loop do
|
|
122
|
+
evaluate
|
|
123
|
+
|
|
124
|
+
best_program = self.best_program
|
|
125
|
+
best_loss = self.best_loss
|
|
126
|
+
|
|
127
|
+
block[self]
|
|
128
|
+
|
|
129
|
+
break if @stop
|
|
130
|
+
min_generations_reached = min_generations.nil? || generation >= min_generations
|
|
131
|
+
break if min_generations_reached && loss && best_loss <= loss
|
|
132
|
+
break if generation >= max_generations
|
|
133
|
+
|
|
134
|
+
next_generation!
|
|
135
|
+
generation += 1
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
@stop = false
|
|
139
|
+
return best_program, best_loss
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
require 'evoasm/population/parameters'
|
|
145
|
+
require 'evoasm/population/plotter'
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
require 'evoasm/prng'
|
|
2
|
+
require 'evoasm/program/io'
|
|
3
|
+
require 'evoasm/domain'
|
|
4
|
+
|
|
5
|
+
module Evoasm
|
|
6
|
+
class Population
|
|
7
|
+
|
|
8
|
+
class Parameters < FFI::AutoPointer
|
|
9
|
+
|
|
10
|
+
# @!visibility private
|
|
11
|
+
def self.release(ptr)
|
|
12
|
+
Libevoasm.pop_params_free ptr
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @return [Program::Input] input examples
|
|
16
|
+
attr_reader :input
|
|
17
|
+
|
|
18
|
+
# @return [Program::Output] output examples
|
|
19
|
+
attr_reader :output
|
|
20
|
+
|
|
21
|
+
# @param architecture [Symbol] the machine architecture (currently only +:x64+ is supported)
|
|
22
|
+
# @yield [self]
|
|
23
|
+
def initialize(architecture = Evoasm.architecture, &block)
|
|
24
|
+
ptr = Libevoasm.pop_params_alloc
|
|
25
|
+
Libevoasm.pop_params_init ptr
|
|
26
|
+
|
|
27
|
+
case architecture
|
|
28
|
+
when :x64
|
|
29
|
+
@inst_id_enum_type = Libevoasm.enum_type :x64_inst_id
|
|
30
|
+
@param_id_enum_type = Libevoasm.enum_type :x64_param_id
|
|
31
|
+
else
|
|
32
|
+
raise "unknown architecture #{architecture}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
super(ptr)
|
|
36
|
+
|
|
37
|
+
self.seed = PRNG::DEFAULT_SEED
|
|
38
|
+
|
|
39
|
+
if block
|
|
40
|
+
block[self]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @!attribute mutation_rate
|
|
45
|
+
# @return [Float 0..1] the mutation rate
|
|
46
|
+
def mutation_rate
|
|
47
|
+
Libevoasm.pop_params_get_mut_rate(self)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def mutation_rate=(mutation_rate)
|
|
51
|
+
Libevoasm.pop_params_set_mut_rate self, mutation_rate
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @!attribute deme_size
|
|
55
|
+
# @return [Integer] the number of individuals per deme
|
|
56
|
+
def deme_size
|
|
57
|
+
Libevoasm.pop_params_get_deme_size self
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def deme_size=(deme_size)
|
|
61
|
+
Libevoasm.pop_params_set_deme_size self, deme_size
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @!attribute deme_count
|
|
65
|
+
# @return [Integer] the number of demes in the population
|
|
66
|
+
def deme_count
|
|
67
|
+
Libevoasm.pop_params_get_n_demes self
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def deme_count=(deme_count)
|
|
71
|
+
Libevoasm.pop_params_set_n_demes self, deme_count
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# @!attribute parameters
|
|
75
|
+
# @return [Array<Symbol>] the list of architecture-dependent instruction parameters to use
|
|
76
|
+
def parameters
|
|
77
|
+
Array.new(Libevoasm.pop_params_get_n_params self) do |index|
|
|
78
|
+
parameters_enum_type[Libevoasm.pop_params_get_param(self, index)]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def parameters=(parameter_names)
|
|
83
|
+
parameter_names.each_with_index do |parameter_name, index|
|
|
84
|
+
Libevoasm.pop_params_set_param(self, index, parameters_enum_type[parameter_name])
|
|
85
|
+
end
|
|
86
|
+
Libevoasm.pop_params_set_n_params(self, parameter_names.size)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# @!attribute domains
|
|
90
|
+
# @return [Hash{Symbol => Array, Range}] a hash whose values indicate user-defined domains for the parameters given as keys
|
|
91
|
+
def domains
|
|
92
|
+
parameters.map do |parameter_name|
|
|
93
|
+
domain_ptr = Libevoasm.pop_params_get_domain(self, parameter_name)
|
|
94
|
+
domain = @domains.find { |domain| domain == domain_ptr }
|
|
95
|
+
[parameter_name, domain]
|
|
96
|
+
end.to_h
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def domains=(domains_hash)
|
|
100
|
+
domains = []
|
|
101
|
+
domains_hash.each do |parameter_name, domain_value|
|
|
102
|
+
domain = Domain.for domain_value
|
|
103
|
+
success = Libevoasm.pop_params_set_domain(self, parameter_name, domain)
|
|
104
|
+
if !success
|
|
105
|
+
raise ArgumentError, "no such parameter #{parameter_name}"
|
|
106
|
+
end
|
|
107
|
+
domains << domain
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# keep reference to prevent disposal by GC
|
|
111
|
+
@domains = domains
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# @!visibility private
|
|
115
|
+
def deme_height
|
|
116
|
+
Libevoasm.pop_params_get_deme_height self
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# @!attribute seed
|
|
120
|
+
# @return [Array<Integer>] the seed for the random number generator
|
|
121
|
+
def seed
|
|
122
|
+
Array.new(PRNG::SEED_SIZE) do |index|
|
|
123
|
+
Libevoasm.pop_params_get_seed(self, index)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def seed=(seed)
|
|
128
|
+
if seed.size != PRNG::SEED_SIZE
|
|
129
|
+
raise ArgumentError, 'invalid seed size'
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
seed.each_with_index do |seed_value, index|
|
|
133
|
+
Libevoasm.pop_params_set_seed(self, index, seed_value)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Validate the parameters
|
|
138
|
+
# @raise [Error] if the parameters are invalid
|
|
139
|
+
def validate!
|
|
140
|
+
unless Libevoasm.pop_params_validate(self)
|
|
141
|
+
raise Error.last
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# @!attribute instructions
|
|
146
|
+
# @return [Symbol, Instruction] the list of instructions to use
|
|
147
|
+
def instructions
|
|
148
|
+
Array.new(Libevoasm.pop_params_get_n_insts self) do |index|
|
|
149
|
+
@inst_id_enum_type[Libevoasm.pop_params_get_inst(self, index)]
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
def instructions=(instructions)
|
|
153
|
+
instructions.each_with_index do |instruction, index|
|
|
154
|
+
name =
|
|
155
|
+
if instruction.is_a? Symbol
|
|
156
|
+
instruction
|
|
157
|
+
else
|
|
158
|
+
instruction.name
|
|
159
|
+
end
|
|
160
|
+
Libevoasm.pop_params_set_inst(self, index, name)
|
|
161
|
+
end
|
|
162
|
+
Libevoasm.pop_params_set_n_insts(self, instructions.size)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# @!attribute kernel_size
|
|
166
|
+
# @return [Integer] the size of program kernels (number of instructions per kernel)
|
|
167
|
+
def kernel_size
|
|
168
|
+
Libevoasm.pop_params_get_kernel_size self
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def kernel_size=(kernel_size)
|
|
172
|
+
Libevoasm.pop_params_set_kernel_size self, kernel_size
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# @!attribute program_size
|
|
176
|
+
# @return [Integer] the size of programs (number of kernels per program)
|
|
177
|
+
def program_size
|
|
178
|
+
Libevoasm.pop_params_get_program_size self
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def program_size=(program_size)
|
|
182
|
+
Libevoasm.pop_params_set_program_size self, program_size
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# @!attribute recur_limit
|
|
186
|
+
# @return [Integer] the size of programs (number of kernels per program)
|
|
187
|
+
def recur_limit
|
|
188
|
+
Libevoasm.pop_params_get_recur_limit self
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def recur_limit=(recur_limit)
|
|
192
|
+
Libevoasm.pop_params_set_recur_limit self, recur_limit
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# @!attribute examples
|
|
196
|
+
# @return [Hash] shorthand to set expected program input and output
|
|
197
|
+
# @see #input
|
|
198
|
+
# @see #output
|
|
199
|
+
def examples
|
|
200
|
+
input.zip(output).to_h
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def examples=(examples)
|
|
204
|
+
input_examples = examples.keys.map { |k| Array(k) }
|
|
205
|
+
output_examples = examples.values.map { |k| Array(k) }
|
|
206
|
+
|
|
207
|
+
self.input = Program::Input.new input_examples
|
|
208
|
+
self.output = Program::Output.new output_examples
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def input=(input)
|
|
212
|
+
@input = input
|
|
213
|
+
Libevoasm.pop_params_set_program_input self, input
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def output=(output)
|
|
217
|
+
@output = output
|
|
218
|
+
Libevoasm.pop_params_set_program_output self, output
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
private
|
|
222
|
+
def parameters_enum_type
|
|
223
|
+
@param_id_enum_type
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
module Evoasm
|
|
2
|
+
class Population
|
|
3
|
+
|
|
4
|
+
# Visualizes the population loss functions using {http://gnuplot.sourceforge.net Gnuplot}
|
|
5
|
+
class Plotter
|
|
6
|
+
MAX_SAMPLE_COUNT = 1024
|
|
7
|
+
|
|
8
|
+
# @!visibility private
|
|
9
|
+
def self.__open__
|
|
10
|
+
@pipe ||= IO.popen('gnuplot -persist', 'w')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @param population [Population] the population to plot
|
|
14
|
+
def initialize(population, filename = nil)
|
|
15
|
+
@population = population
|
|
16
|
+
|
|
17
|
+
@pipe = self.class.__open__
|
|
18
|
+
#@pipe = File.open('/tmp/test.txt', 'w')
|
|
19
|
+
|
|
20
|
+
if filename
|
|
21
|
+
case filename
|
|
22
|
+
when /\.gif$/
|
|
23
|
+
@pipe.puts 'set term gif animate delay 20 size 1280, 1024 crop'
|
|
24
|
+
@pipe.puts %Q{set output "#{filename}"}
|
|
25
|
+
else
|
|
26
|
+
raise ArgumentError, "unknown output filetype"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
@pipe.puts 'set xtics'
|
|
31
|
+
@pipe.puts 'set ytics'
|
|
32
|
+
@pipe.puts 'set grid'
|
|
33
|
+
@pipe.puts 'set style fill transparent solid 0.2 noborder'
|
|
34
|
+
@pipe.puts 'set datafile missing "Infinity"'
|
|
35
|
+
@pipe.puts 'set lmargin 0.5'
|
|
36
|
+
@pipe.puts 'set rmargin 0.5'
|
|
37
|
+
@pipe.puts 'set tmargin 0.5'
|
|
38
|
+
@pipe.puts 'set bmargin 0.5'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Updates data points
|
|
42
|
+
# @return [nil]
|
|
43
|
+
def update
|
|
44
|
+
@data ||= Array.new(@population.parameters.deme_count) { Array.new(@population.parameters.deme_height) { [] } }
|
|
45
|
+
summary = @population.summary
|
|
46
|
+
|
|
47
|
+
summary.each_with_index do |deme_summary, deme_index|
|
|
48
|
+
deme_summary.each_with_index do |layer_summary, layer_index|
|
|
49
|
+
samples = @data[deme_index][layer_index]
|
|
50
|
+
samples[samples.size % MAX_SAMPLE_COUNT] = layer_summary
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Plots (or replots) the current data points
|
|
56
|
+
# @return [nil]
|
|
57
|
+
def plot
|
|
58
|
+
@pipe.puts "set multiplot layout #{@data[0].size}, #{@data.size}"
|
|
59
|
+
|
|
60
|
+
key = true
|
|
61
|
+
|
|
62
|
+
@data.each do |deme_summary|
|
|
63
|
+
deme_summary.each do |layer_summary|
|
|
64
|
+
@pipe.puts "set key #{key ? 'on' : 'off'}"
|
|
65
|
+
key = false
|
|
66
|
+
@pipe.write %Q{plot '-' using 1:2:3 with filledcurves title 'IQR',}
|
|
67
|
+
@pipe.write %Q{ '-' using 1:2 with lp title 'Min',}
|
|
68
|
+
@pipe.puts %Q{ '-' using 1:2 with lp lt 1 pt 5 ps 1.5 lw 2 title 'Median'}
|
|
69
|
+
|
|
70
|
+
layer_summary.each_with_index do |sample, sample_index|
|
|
71
|
+
@pipe.puts "#{sample_index} #{sample[1]} #{sample[3]}"
|
|
72
|
+
end
|
|
73
|
+
@pipe.puts 'e'
|
|
74
|
+
layer_summary.each_with_index do |sample, sample_index|
|
|
75
|
+
@pipe.puts "#{sample_index} #{sample[0]}"
|
|
76
|
+
end
|
|
77
|
+
@pipe.puts 'e'
|
|
78
|
+
layer_summary.each_with_index do |sample, sample_index|
|
|
79
|
+
@pipe.puts "#{sample_index} #{sample[2]}"
|
|
80
|
+
end
|
|
81
|
+
@pipe.puts 'e'
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
@pipe.puts "unset multiplot"
|
|
85
|
+
@pipe.flush
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|