evoasm 0.0.2.pre7 → 0.1.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|