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.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/.gdbinit +41 -0
  3. data/.gitignore +1 -2
  4. data/.gitmodules +3 -0
  5. data/.rubocop.yml +8 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.md +660 -0
  8. data/Makefile +1 -1
  9. data/README.md +17 -9
  10. data/Rakefile +39 -107
  11. data/bin/gdb +1 -1
  12. data/bin/gdb_loop +4 -0
  13. data/docs/FindingInstructions.md +17 -0
  14. data/docs/JIT.md +14 -0
  15. data/docs/SymbolicRegression.md +102 -0
  16. data/docs/Visualization.md +29 -0
  17. data/docs/examples/bit_insts.rb +44 -0
  18. data/docs/examples/jit.rb +26 -0
  19. data/docs/examples/loss.gif +0 -0
  20. data/docs/examples/program.png +0 -0
  21. data/docs/examples/sym_reg.rb +64 -0
  22. data/docs/examples/vis.rb +38 -0
  23. data/evoasm.gemspec +21 -15
  24. data/ext/evoasm_ext/Rakefile +3 -0
  25. data/ext/evoasm_ext/compile.rake +35 -0
  26. data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.c +226 -0
  27. data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.h +84 -0
  28. data/ext/evoasm_ext/libevoasm/src/evoasm-arch.c +52 -0
  29. data/ext/evoasm_ext/libevoasm/src/evoasm-arch.h +101 -0
  30. data/ext/evoasm_ext/libevoasm/src/evoasm-bitmap.h +158 -0
  31. data/ext/evoasm_ext/libevoasm/src/evoasm-buf.c +204 -0
  32. data/ext/evoasm_ext/libevoasm/src/evoasm-buf.h +109 -0
  33. data/ext/evoasm_ext/libevoasm/src/evoasm-domain.c +124 -0
  34. data/ext/evoasm_ext/libevoasm/src/evoasm-domain.h +279 -0
  35. data/ext/evoasm_ext/libevoasm/src/evoasm-error.c +65 -0
  36. data/ext/evoasm_ext/libevoasm/src/evoasm-error.h +108 -0
  37. data/ext/evoasm_ext/{evoasm-log.c → libevoasm/src/evoasm-log.c} +36 -18
  38. data/ext/evoasm_ext/libevoasm/src/evoasm-log.h +93 -0
  39. data/ext/evoasm_ext/libevoasm/src/evoasm-param.c +22 -0
  40. data/ext/evoasm_ext/libevoasm/src/evoasm-param.h +33 -0
  41. data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.c +192 -0
  42. data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.h +60 -0
  43. data/ext/evoasm_ext/libevoasm/src/evoasm-pop.c +1323 -0
  44. data/ext/evoasm_ext/libevoasm/src/evoasm-pop.h +107 -0
  45. data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.c +116 -0
  46. data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.h +60 -0
  47. data/ext/evoasm_ext/libevoasm/src/evoasm-program.c +1827 -0
  48. data/ext/evoasm_ext/libevoasm/src/evoasm-program.h +167 -0
  49. data/ext/evoasm_ext/libevoasm/src/evoasm-rand.c +65 -0
  50. data/ext/evoasm_ext/libevoasm/src/evoasm-rand.h +76 -0
  51. data/ext/evoasm_ext/libevoasm/src/evoasm-signal.c +106 -0
  52. data/ext/evoasm_ext/libevoasm/src/evoasm-signal.h +58 -0
  53. data/ext/evoasm_ext/libevoasm/src/evoasm-util.h +112 -0
  54. data/ext/evoasm_ext/libevoasm/src/evoasm-x64.c +925 -0
  55. data/ext/evoasm_ext/libevoasm/src/evoasm-x64.h +277 -0
  56. data/ext/evoasm_ext/libevoasm/src/evoasm.c +28 -0
  57. data/ext/evoasm_ext/libevoasm/src/evoasm.h +35 -0
  58. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-enums.h +2077 -0
  59. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.c +191203 -0
  60. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.h +1713 -0
  61. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.c +348 -0
  62. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.h +93 -0
  63. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.c +51 -0
  64. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.h +509 -0
  65. data/lib/evoasm.rb +28 -11
  66. data/lib/evoasm/buffer.rb +105 -0
  67. data/lib/evoasm/capstone.rb +100 -0
  68. data/lib/evoasm/domain.rb +116 -0
  69. data/lib/evoasm/error.rb +37 -16
  70. data/lib/evoasm/exception_error.rb +19 -0
  71. data/lib/evoasm/ffi_ext.rb +53 -0
  72. data/lib/evoasm/libevoasm.rb +286 -0
  73. data/lib/evoasm/libevoasm/x64_enums.rb +1967 -0
  74. data/lib/evoasm/parameter.rb +20 -0
  75. data/lib/evoasm/population.rb +145 -0
  76. data/lib/evoasm/population/parameters.rb +227 -0
  77. data/lib/evoasm/population/plotter.rb +89 -0
  78. data/lib/evoasm/prng.rb +64 -0
  79. data/lib/evoasm/program.rb +195 -12
  80. data/lib/evoasm/program/io.rb +144 -0
  81. data/lib/evoasm/test.rb +8 -0
  82. data/lib/evoasm/version.rb +1 -1
  83. data/lib/evoasm/x64.rb +115 -0
  84. data/lib/evoasm/x64/cpu_state.rb +95 -0
  85. data/lib/evoasm/x64/instruction.rb +109 -0
  86. data/lib/evoasm/x64/operand.rb +156 -0
  87. data/lib/evoasm/x64/parameters.rb +211 -0
  88. data/test/helpers/population_helper.rb +128 -0
  89. data/test/helpers/test_helper.rb +1 -0
  90. data/test/helpers/x64_helper.rb +24 -0
  91. data/test/integration/bitwise_reverse_test.rb +41 -0
  92. data/test/integration/gcd_test.rb +52 -0
  93. data/test/integration/popcnt_test.rb +46 -0
  94. data/test/integration/sym_reg_test.rb +68 -0
  95. data/test/unit/evoasm/buffer_test.rb +48 -0
  96. data/test/unit/evoasm/capstone_test.rb +18 -0
  97. data/test/unit/evoasm/domain_test.rb +55 -0
  98. data/test/unit/evoasm/population/parameters_test.rb +106 -0
  99. data/test/unit/evoasm/population_test.rb +96 -0
  100. data/test/unit/evoasm/prng_test.rb +47 -0
  101. data/test/unit/evoasm/x64/cpu_state_test.rb +73 -0
  102. data/test/unit/evoasm/x64/encoding_test.rb +320 -0
  103. data/test/unit/evoasm/x64/instruction_access_test.rb +177 -0
  104. data/test/unit/evoasm/x64/instruction_encoding_test.rb +780 -0
  105. data/test/unit/evoasm/x64/instruction_test.rb +62 -0
  106. data/test/unit/evoasm/x64/parameters_test.rb +65 -0
  107. data/test/unit/evoasm/x64_test.rb +52 -0
  108. metadata +195 -89
  109. data/Gemfile.rake +0 -8
  110. data/Gemfile.rake.lock +0 -51
  111. data/LICENSE.txt +0 -373
  112. data/data/tables/README.md +0 -19
  113. data/data/tables/x64.csv +0 -1684
  114. data/data/templates/evoasm-x64.c.erb +0 -319
  115. data/data/templates/evoasm-x64.h.erb +0 -126
  116. data/examples/abs.yml +0 -20
  117. data/examples/popcnt.yml +0 -17
  118. data/examples/sym_reg.yml +0 -26
  119. data/exe/evoasm-search +0 -13
  120. data/ext/evoasm_ext/evoasm-alloc.c +0 -145
  121. data/ext/evoasm_ext/evoasm-alloc.h +0 -59
  122. data/ext/evoasm_ext/evoasm-arch.c +0 -44
  123. data/ext/evoasm_ext/evoasm-arch.h +0 -161
  124. data/ext/evoasm_ext/evoasm-bitmap.h +0 -114
  125. data/ext/evoasm_ext/evoasm-buf.c +0 -130
  126. data/ext/evoasm_ext/evoasm-buf.h +0 -47
  127. data/ext/evoasm_ext/evoasm-error.c +0 -31
  128. data/ext/evoasm_ext/evoasm-error.h +0 -75
  129. data/ext/evoasm_ext/evoasm-free-list.c.tmpl +0 -121
  130. data/ext/evoasm_ext/evoasm-free-list.h.tmpl +0 -86
  131. data/ext/evoasm_ext/evoasm-log.h +0 -69
  132. data/ext/evoasm_ext/evoasm-misc.c +0 -23
  133. data/ext/evoasm_ext/evoasm-misc.h +0 -282
  134. data/ext/evoasm_ext/evoasm-param.h +0 -37
  135. data/ext/evoasm_ext/evoasm-search.c +0 -2145
  136. data/ext/evoasm_ext/evoasm-search.h +0 -214
  137. data/ext/evoasm_ext/evoasm-util.h +0 -40
  138. data/ext/evoasm_ext/evoasm-x64.c +0 -275624
  139. data/ext/evoasm_ext/evoasm-x64.h +0 -5436
  140. data/ext/evoasm_ext/evoasm.c +0 -7
  141. data/ext/evoasm_ext/evoasm.h +0 -23
  142. data/ext/evoasm_ext/evoasm_ext.c +0 -1757
  143. data/ext/evoasm_ext/extconf.rb +0 -31
  144. data/lib/evoasm/cli.rb +0 -6
  145. data/lib/evoasm/cli/search.rb +0 -127
  146. data/lib/evoasm/core_ext.rb +0 -1
  147. data/lib/evoasm/core_ext/array.rb +0 -9
  148. data/lib/evoasm/core_ext/integer.rb +0 -10
  149. data/lib/evoasm/core_ext/kwstruct.rb +0 -13
  150. data/lib/evoasm/core_ext/range.rb +0 -5
  151. data/lib/evoasm/examples.rb +0 -27
  152. data/lib/evoasm/gen.rb +0 -8
  153. data/lib/evoasm/gen/enum.rb +0 -169
  154. data/lib/evoasm/gen/name_util.rb +0 -80
  155. data/lib/evoasm/gen/state.rb +0 -176
  156. data/lib/evoasm/gen/state_dsl.rb +0 -152
  157. data/lib/evoasm/gen/strio.rb +0 -27
  158. data/lib/evoasm/gen/translator.rb +0 -1102
  159. data/lib/evoasm/gen/version.rb +0 -5
  160. data/lib/evoasm/gen/x64.rb +0 -237
  161. data/lib/evoasm/gen/x64/funcs.rb +0 -495
  162. data/lib/evoasm/gen/x64/inst.rb +0 -781
  163. data/lib/evoasm/search.rb +0 -40
  164. data/lib/evoasm/tasks/gen_task.rb +0 -86
  165. data/lib/evoasm/tasks/template_task.rb +0 -52
  166. data/test/test_helper.rb +0 -1
  167. data/test/x64/test_helper.rb +0 -19
  168. data/test/x64/x64_test.rb +0 -87
@@ -0,0 +1,60 @@
1
+ /*
2
+ * Copyright (C) 2016 Julian Aron Prenner <jap@polyadic.com>
3
+ *
4
+ * This program is free software: you can redistribute it and/or modify
5
+ * it under the terms of the GNU Affero General Public License as published by
6
+ * the Free Software Foundation, either version 3 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU Affero General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Affero General Public License
15
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include "evoasm-domain.h"
21
+ #include "evoasm-param.h"
22
+ #include "evoasm.h"
23
+
24
+ typedef float evoasm_loss_t;
25
+
26
+ #include "evoasm-program.h"
27
+ #include "evoasm-program-io.h"
28
+
29
+ #define EVOASM_POP_PARAMS_MAX_PARAMS 32
30
+
31
+ typedef enum {
32
+ EVOASM_POP_PARAMS_ERROR_CODE_INVALID
33
+ } evoasm_pop_params_error_code_t;
34
+
35
+ typedef struct evoasm_pop_params_s {
36
+ evoasm_param_id_t param_ids[EVOASM_POP_PARAMS_MAX_PARAMS];
37
+ evoasm_domain_t *domains[EVOASM_POP_PARAMS_MAX_PARAMS];
38
+ uint8_t n_params;
39
+
40
+ uint16_t n_demes;
41
+ uint16_t library_size;
42
+ uint16_t deme_size;
43
+ uint16_t kernel_size;
44
+ uint16_t program_size;
45
+ uint16_t min_module_size;
46
+ uint16_t max_module_size;
47
+ float mut_rate;
48
+ float evap_rate;
49
+
50
+ uint8_t depth;
51
+ evoasm_prng_state_t seed;
52
+ uint32_t recur_limit;
53
+ uint16_t n_insts;
54
+ evoasm_program_io_t *program_input;
55
+ evoasm_program_io_t *program_output;
56
+ evoasm_inst_id_t inst_ids[EVOASM_X64_INST_NONE];
57
+ } evoasm_pop_params_t;
58
+
59
+ bool
60
+ evoasm_pop_params_validate(evoasm_pop_params_t *pop_params);
@@ -0,0 +1,1323 @@
1
+ /*
2
+ * Copyright (C) 2016 Julian Aron Prenner
3
+ *
4
+ * This program is free software: you can redistribute it and/or modify
5
+ * it under the terms of the GNU Affero General Public License as published by
6
+ * the Free Software Foundation, either version 3 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU Affero General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Affero General Public License
15
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ */
17
+
18
+ #include "evoasm-pop.h"
19
+ #include "evoasm-signal.h"
20
+ #include "evoasm-util.h"
21
+ #include "evoasm-program.h"
22
+ #include "evoasm-error.h"
23
+
24
+ #ifdef _OPENMP
25
+
26
+ # include <omp.h>
27
+ #include <gen/evoasm-x64-params.h>
28
+
29
+ #endif
30
+
31
+ EVOASM_DEF_LOG_TAG("pop")
32
+
33
+ #define EVOASM_DEME_MIN_LOSS_SAMPLES 8
34
+ #define EVOASM_DEME_MAX_LOSS_SAMPLES 16
35
+
36
+ #define EVOASM_DEME_INDIV_OFF(deme, row, indiv_idx) \
37
+ ((size_t)((row) * (size_t)(deme)->params->deme_size + (indiv_idx)))
38
+
39
+ #define EVOASM_DEME_LOSS_SAMPLE_OFF(deme, row, indiv_idx, sample_idx) \
40
+ (EVOASM_DEME_INDIV_OFF(deme, row, indiv_idx) * EVOASM_DEME_MAX_LOSS_SAMPLES + (sample_idx))
41
+
42
+ /* first sample is replaced with median loss after update */
43
+ #define EVOASM_DEME_LOSS_OFF(deme, row, indiv_idx) \
44
+ EVOASM_DEME_LOSS_SAMPLE_OFF(deme, row, indiv_idx, 0)
45
+
46
+ #define EVOASM_DEME_PROGRAMS_ROW(deme) ((deme)->params->program_size)
47
+
48
+ #define EVOASM_DEME_PROGRAM_POS_OFF_(program_size, program_idx, pos) \
49
+ (((program_idx) * (size_t)(program_size) + (pos)))
50
+
51
+ #define EVOASM_DEME_PROGRAM_POS_OFF(deme, program_idx, pos) \
52
+ EVOASM_DEME_PROGRAM_POS_OFF_((deme)->params->program_size, program_idx, pos)
53
+
54
+ #define EVOASM_DEME_KERNEL_INST_OFF_(deme_size, kernel_size, pos, kernel_idx, inst_idx) \
55
+ ((((pos) * (deme_size) + (kernel_idx)) * (kernel_size) + (inst_idx)))
56
+
57
+ #define EVOASM_DEME_KERNEL_INST_OFF(deme, pos, kernel_idx, inst_idx) \
58
+ EVOASM_DEME_KERNEL_INST_OFF_((deme)->params->deme_size, (deme)->params->kernel_size, pos, kernel_idx, inst_idx)
59
+
60
+ #define EVOASM_DEME_N_INDIVS(deme) ((evoasm_pop_params_get_deme_height((deme)->params)) * (deme)->params->deme_size)
61
+
62
+ static evoasm_success_t
63
+ evoasm_pop_loss_data_init(evoasm_pop_loss_data_t *loss_data, size_t n_indivs) {
64
+ EVOASM_TRY_ALLOC(error, aligned_calloc, loss_data->samples, EVOASM_CACHE_LINE_SIZE,
65
+ n_indivs * EVOASM_DEME_MAX_LOSS_SAMPLES,
66
+ sizeof(evoasm_loss_t));
67
+
68
+ EVOASM_TRY_ALLOC(error, aligned_calloc, loss_data->counters, EVOASM_CACHE_LINE_SIZE,
69
+ n_indivs,
70
+ sizeof(uint8_t));
71
+
72
+ return true;
73
+ error:
74
+ return false;
75
+ }
76
+
77
+ static void
78
+ evoasm_pop_loss_data_destroy(evoasm_pop_loss_data_t *loss_data) {
79
+ evoasm_free(loss_data->samples);
80
+ evoasm_free(loss_data->counters);
81
+ }
82
+
83
+ static evoasm_success_t
84
+ evoasm_pop_program_data_init(evoasm_pop_program_data_t *program_data, size_t n_pos) {
85
+
86
+ EVOASM_TRY_ALLOC(error, aligned_calloc, program_data->jmp_offs, EVOASM_CACHE_LINE_SIZE,
87
+ n_pos,
88
+ sizeof(int16_t));
89
+ EVOASM_TRY_ALLOC(error, aligned_calloc, program_data->jmp_cond, EVOASM_CACHE_LINE_SIZE,
90
+ n_pos,
91
+ sizeof(uint8_t));
92
+
93
+ return true;
94
+
95
+ error:
96
+ return false;
97
+ }
98
+
99
+ static void
100
+ evoasm_pop_program_data_destroy(evoasm_pop_program_data_t *program_data) {
101
+ evoasm_free(program_data->jmp_offs);
102
+ evoasm_free(program_data->jmp_cond);
103
+ }
104
+
105
+ static evoasm_success_t
106
+ evoasm_pop_kernel_data_init(evoasm_pop_kernel_data_t *kernel_data,
107
+ evoasm_arch_id_t arch_id,
108
+ size_t n_insts) {
109
+
110
+
111
+ EVOASM_TRY_ALLOC(error, aligned_calloc, kernel_data->insts, EVOASM_CACHE_LINE_SIZE,
112
+ n_insts,
113
+ sizeof(evoasm_inst_id_t));
114
+
115
+ switch(arch_id) {
116
+ case EVOASM_ARCH_X64:
117
+ EVOASM_TRY_ALLOC(error, aligned_calloc, kernel_data->params.x64, EVOASM_CACHE_LINE_SIZE,
118
+ n_insts,
119
+ sizeof(evoasm_x64_basic_params_t));
120
+ break;
121
+ default:
122
+ evoasm_assert_not_reached();
123
+ }
124
+ return true;
125
+
126
+ error:
127
+ return false;
128
+ }
129
+
130
+ static void
131
+ evoasm_pop_kernel_data_destroy(evoasm_pop_kernel_data_t *kernel_data) {
132
+ evoasm_free(kernel_data->insts);
133
+ evoasm_free(kernel_data->params.data);
134
+ }
135
+
136
+ static evoasm_success_t
137
+ evoasm_pop_module_data_init(evoasm_pop_module_data_t *module_data, size_t n) {
138
+ EVOASM_TRY(error, evoasm_pop_program_data_init, &module_data->program_data, n);
139
+
140
+ EVOASM_TRY_ALLOC(error, aligned_calloc, module_data->sizes, EVOASM_CACHE_LINE_SIZE,
141
+ n,
142
+ sizeof(uint16_t));
143
+ EVOASM_TRY_ALLOC(error, aligned_calloc, module_data->pheromones, EVOASM_CACHE_LINE_SIZE,
144
+ n,
145
+ sizeof(float));
146
+ return true;
147
+ error:
148
+ return false;
149
+ }
150
+
151
+ static void
152
+ evoasm_pop_module_data_destroy(evoasm_pop_module_data_t *module_data) {
153
+ evoasm_pop_program_data_destroy(&module_data->program_data);
154
+ evoasm_free(module_data->pheromones);
155
+ evoasm_free(module_data->sizes);
156
+ }
157
+
158
+ static inline size_t
159
+ evoasm_pop_params_get_deme_height_(evoasm_pop_params_t *params) {
160
+ size_t height = params->program_size;
161
+ if(params->program_size > 1) return height + 1;
162
+ return height;
163
+ }
164
+
165
+ size_t
166
+ evoasm_pop_params_get_deme_height(evoasm_pop_params_t *params) {
167
+ return evoasm_pop_params_get_deme_height_(params);
168
+ }
169
+
170
+ static void
171
+ evoasm_deme_destroy(evoasm_deme_t *deme) {
172
+ EVOASM_TRY_WARN(evoasm_program_destroy, &deme->program);
173
+ evoasm_prng_destroy(&deme->prng);
174
+ evoasm_free(deme->blessed_indiv_idxs);
175
+ evoasm_free(deme->doomed_indiv_idxs);
176
+ evoasm_free(deme->error_counters);
177
+ evoasm_free(deme->top_losses);
178
+
179
+ evoasm_pop_kernel_data_destroy(&deme->kernel_data);
180
+ evoasm_pop_loss_data_destroy(&deme->loss_data);
181
+
182
+ evoasm_pop_kernel_data_destroy(&deme->best_kernel_data);
183
+
184
+ if(deme->params->program_size > 1) {
185
+ evoasm_pop_program_data_destroy(&deme->best_program_data);
186
+ evoasm_pop_program_data_destroy(&deme->parent_program_data);
187
+ evoasm_pop_program_data_destroy(&deme->program_data);
188
+ }
189
+
190
+ evoasm_pop_kernel_data_destroy(&deme->parent_kernel_data);
191
+ }
192
+
193
+ void
194
+ evoasm_pop_destroy(evoasm_pop_t *pop) {
195
+ evoasm_free(pop->domains);
196
+
197
+ for(int i = 0; i < pop->params->n_demes; i++) {
198
+ evoasm_deme_destroy(&pop->demes[i]);
199
+ }
200
+ evoasm_free(pop->demes);
201
+ evoasm_free(pop->summary_losses);
202
+
203
+ evoasm_pop_module_data_destroy(&pop->module_data);
204
+ }
205
+
206
+ static evoasm_success_t
207
+ evoasm_deme_init(evoasm_deme_t *deme,
208
+ evoasm_arch_id_t arch_id,
209
+ evoasm_pop_params_t *params,
210
+ evoasm_prng_state_t *seed,
211
+ evoasm_domain_t *domains) {
212
+
213
+ size_t n_examples = EVOASM_PROGRAM_INPUT_N_TUPLES(params->program_input);
214
+ static evoasm_deme_t zero_deme = {0};
215
+
216
+ *deme = zero_deme;
217
+ deme->n_examples = (uint16_t) n_examples;
218
+ deme->arch_id = arch_id;
219
+ deme->params = params;
220
+ deme->domains = domains;
221
+
222
+ evoasm_prng_init(&deme->prng, seed);
223
+
224
+ EVOASM_TRY_ALLOC(error, aligned_calloc, deme->blessed_indiv_idxs, EVOASM_CACHE_LINE_SIZE, params->deme_size,
225
+ sizeof(uint16_t));
226
+
227
+ EVOASM_TRY_ALLOC(error, aligned_calloc, deme->doomed_indiv_idxs, EVOASM_CACHE_LINE_SIZE, params->deme_size,
228
+ sizeof(uint16_t));
229
+
230
+ EVOASM_TRY(error, evoasm_program_init, &deme->program,
231
+ evoasm_get_arch_info(arch_id),
232
+ params->program_size,
233
+ params->kernel_size,
234
+ n_examples,
235
+ params->recur_limit,
236
+ true);
237
+
238
+ if(params->program_size > 1) {
239
+ EVOASM_TRY(error, evoasm_pop_program_data_init, &deme->program_data,
240
+ (size_t) params->deme_size * params->kernel_size);
241
+
242
+ EVOASM_TRY(error, evoasm_pop_program_data_init, &deme->parent_program_data,
243
+ 2u * params->program_size);
244
+
245
+ EVOASM_TRY(error, evoasm_pop_program_data_init, &deme->best_program_data, params->program_size);
246
+ }
247
+
248
+ EVOASM_TRY(error, evoasm_pop_kernel_data_init, &deme->parent_kernel_data, arch_id,
249
+ 2u * params->kernel_size);
250
+
251
+ size_t n_indivs = EVOASM_DEME_N_INDIVS(deme);
252
+ size_t height = evoasm_pop_params_get_deme_height_(deme->params);
253
+
254
+ EVOASM_TRY(error, evoasm_pop_kernel_data_init, &deme->kernel_data, arch_id,
255
+ (size_t) params->program_size * params->deme_size * params->kernel_size);
256
+ EVOASM_TRY(error, evoasm_pop_loss_data_init, &deme->loss_data, n_indivs);
257
+
258
+ EVOASM_TRY(error, evoasm_pop_kernel_data_init, &deme->best_kernel_data, arch_id,
259
+ (size_t) (params->program_size * params->kernel_size));
260
+
261
+
262
+ deme->best_loss = INFINITY;
263
+
264
+ EVOASM_TRY_ALLOC(error, aligned_calloc, deme->top_losses, EVOASM_CACHE_LINE_SIZE,
265
+ height,
266
+ sizeof(evoasm_loss_t));
267
+
268
+ for(size_t i = 0; i < height; i++) {
269
+ deme->top_losses[i] = INFINITY;
270
+ }
271
+
272
+ EVOASM_TRY_ALLOC(error, aligned_calloc, deme->error_counters, (size_t) n_examples, EVOASM_CACHE_LINE_SIZE,
273
+ sizeof(uint64_t));
274
+ deme->error_counter = 0;
275
+
276
+ return true;
277
+
278
+ error:
279
+ return false;
280
+ }
281
+
282
+ evoasm_success_t
283
+ evoasm_pop_init_domains(evoasm_pop_t *pop) {
284
+ size_t i, j, k;
285
+ evoasm_domain_t cloned_domain;
286
+
287
+ evoasm_pop_params_t *params = pop->params;
288
+
289
+ size_t domains_len = (size_t) (params->n_insts * params->n_params);
290
+ pop->domains = evoasm_calloc(domains_len,
291
+ sizeof(evoasm_domain_t));
292
+
293
+ if(!pop->domains) goto fail;
294
+
295
+ for(i = 0; i < params->n_insts; i++) {
296
+ evoasm_x64_inst_t *inst = evoasm_x64_inst_((evoasm_x64_inst_id_t) params->inst_ids[i]);
297
+ for(j = 0; j < params->n_params; j++) {
298
+ evoasm_domain_t *inst_domain = &pop->domains[i * params->n_params + j];
299
+ evoasm_param_id_t param_id = params->param_ids[j];
300
+ for(k = 0; k < inst->n_params; k++) {
301
+ evoasm_param_t *param = &inst->params[k];
302
+ if(param->id == param_id) {
303
+ evoasm_domain_t *user_domain = params->domains[param_id];
304
+ if(user_domain != NULL) {
305
+ if(evoasm_domain_is_empty(user_domain)) goto empty_domain;
306
+
307
+ evoasm_domain_clone(user_domain, &cloned_domain);
308
+ evoasm_domain_intersect(&cloned_domain, param->domain, inst_domain);
309
+ if(evoasm_domain_is_empty(inst_domain)) goto empty_domain;
310
+ } else {
311
+ evoasm_domain_clone(param->domain, inst_domain);
312
+ }
313
+ goto found;
314
+ }
315
+ }
316
+ /* not found */
317
+ inst_domain->type = EVOASM_DOMAIN_TYPE_NONE;
318
+ found:;
319
+ }
320
+ }
321
+
322
+ /*
323
+ for(i = 0; i < domains_len; i++) {
324
+ evoasm_domain_log(&pop->domains[i], EVOASM_LOG_LEVEL_WARN);
325
+ }*/
326
+
327
+ return true;
328
+
329
+ fail:
330
+ return false;
331
+
332
+ empty_domain:
333
+ evoasm_error(EVOASM_ERROR_TYPE_POP, EVOASM_ERROR_CODE_NONE,
334
+ "Empty domain");
335
+ return false;
336
+ }
337
+
338
+ evoasm_success_t
339
+ evoasm_pop_init(evoasm_pop_t *pop,
340
+ evoasm_arch_id_t arch_id,
341
+ evoasm_pop_params_t *params) {
342
+ static evoasm_pop_t zero_pop = {0};
343
+ evoasm_prng_t seed_prng;
344
+
345
+ *pop = zero_pop;
346
+
347
+ pop->params = params;
348
+
349
+ if(!evoasm_pop_params_validate(params)) goto error;
350
+
351
+ #ifdef _OPENMP
352
+ {
353
+ int max_threads;
354
+ max_threads = omp_get_max_threads();
355
+ omp_set_dynamic(0);
356
+ int n_threads = EVOASM_MIN(max_threads, params->n_demes);
357
+ omp_set_num_threads(n_threads);
358
+ evoasm_log_info("Using OpenMP with %d threads", n_threads);
359
+ }
360
+ #endif
361
+
362
+ evoasm_prng_init(&seed_prng, &params->seed);
363
+
364
+ EVOASM_TRY(error, evoasm_pop_init_domains, pop);
365
+ EVOASM_TRY(error, evoasm_pop_module_data_init, &pop->module_data, params->library_size);
366
+
367
+ EVOASM_TRY_ALLOC(error, aligned_calloc, pop->demes, EVOASM_CACHE_LINE_SIZE, (size_t) params->n_demes,
368
+ sizeof(evoasm_deme_t));
369
+
370
+ for(int i = 0; i < params->n_demes; i++) {
371
+ evoasm_prng_state_t seed;
372
+
373
+ for(int j = 0; j < EVOASM_PRNG_SEED_LEN; j++) {
374
+ seed.data[j] = evoasm_prng_rand64_(&seed_prng);
375
+ }
376
+
377
+ EVOASM_TRY(error, evoasm_deme_init,
378
+ &pop->demes[i],
379
+ arch_id,
380
+ params,
381
+ &seed,
382
+ pop->domains);
383
+ }
384
+
385
+ return true;
386
+
387
+ error:
388
+ evoasm_pop_destroy(pop);
389
+ return false;
390
+ }
391
+
392
+ static void
393
+ evoasm_deme_seed_kernel_param_x64(evoasm_deme_t *deme, evoasm_inst_id_t *inst_id_ptr,
394
+ evoasm_x64_basic_params_t *params_ptr) {
395
+ evoasm_pop_params_t *params = deme->params;
396
+ size_t n_params = params->n_params;
397
+ evoasm_prng_t *prng = &deme->prng;
398
+
399
+ size_t inst_idx = (size_t) evoasm_prng_rand_between_(prng, 0, params->n_insts - 1);
400
+ evoasm_inst_id_t inst_id = params->inst_ids[inst_idx];
401
+
402
+ *inst_id_ptr = inst_id;
403
+
404
+ /* set parameters */
405
+ for(size_t i = 0; i < n_params; i++) {
406
+ evoasm_domain_t *domain = &deme->domains[inst_idx * n_params + i];
407
+ if(domain->type < EVOASM_DOMAIN_TYPE_NONE) {
408
+ evoasm_x64_param_id_t param_id = (evoasm_x64_param_id_t) deme->params->param_ids[i];
409
+ evoasm_param_val_t param_val;
410
+
411
+ param_val = (int64_t) evoasm_domain_rand_(domain, prng);
412
+ evoasm_x64_basic_params_set_(params_ptr, param_id, param_val);
413
+ }
414
+ }
415
+ }
416
+
417
+ static void
418
+ evoasm_deme_seed_kernel_inst(evoasm_deme_t *deme,
419
+ size_t pos,
420
+ size_t kernel_idx,
421
+ size_t inst_idx) {
422
+
423
+ size_t kernel_inst_off = EVOASM_DEME_KERNEL_INST_OFF(deme, pos, kernel_idx, inst_idx);
424
+
425
+ evoasm_pop_kernel_data_t *kernel_data = &deme->kernel_data;
426
+ evoasm_inst_id_t *insts_ptr = &kernel_data->insts[kernel_inst_off];
427
+
428
+ switch(deme->arch_id) {
429
+ case EVOASM_ARCH_X64: {
430
+ evoasm_x64_basic_params_t *params_ptr = &kernel_data->params.x64[kernel_inst_off];
431
+ evoasm_deme_seed_kernel_param_x64(deme, insts_ptr, params_ptr);
432
+ break;
433
+ }
434
+ default:
435
+ evoasm_assert_not_reached();
436
+ }
437
+ }
438
+
439
+ static void
440
+ evoasm_deme_seed_kernel(evoasm_deme_t *deme, size_t pos, size_t kernel_idx) {
441
+ for(size_t i = 0; i < deme->params->kernel_size; i++) {
442
+ evoasm_deme_seed_kernel_inst(deme, pos, kernel_idx, i);
443
+ }
444
+ }
445
+
446
+ static void
447
+ evoasm_deme_seed_program_pos(evoasm_deme_t *deme,
448
+ size_t program_idx,
449
+ size_t pos) {
450
+
451
+ size_t program_pos_off = EVOASM_DEME_PROGRAM_POS_OFF(deme, program_idx, pos);
452
+ evoasm_pop_program_data_t *program_data = &deme->program_data;
453
+ evoasm_prng_t *prng = &deme->prng;
454
+ size_t program_size = deme->params->program_size;
455
+
456
+ program_data->jmp_cond[program_pos_off] =
457
+ (uint8_t) evoasm_prng_rand8_(prng);
458
+
459
+ program_data->jmp_offs[program_pos_off] =
460
+ (int16_t) (evoasm_prng_rand_between_(prng, 0, (int64_t) (program_size - 1)) - (int64_t) (program_size / 2));
461
+ }
462
+
463
+ static void
464
+ evoasm_deme_seed_program(evoasm_deme_t *deme,
465
+ size_t program_idx) {
466
+ for(size_t i = 0; i < deme->params->program_size; i++) {
467
+ evoasm_deme_seed_program_pos(deme, program_idx, i);
468
+ }
469
+ }
470
+
471
+ static void
472
+ evoasm_deme_seed(evoasm_deme_t *deme) {
473
+ if(deme->params->program_size > 1) {
474
+ for(size_t i = 0; i < deme->params->deme_size; i++) {
475
+ evoasm_deme_seed_program(deme, i);
476
+ }
477
+ }
478
+
479
+ for(size_t i = 0; i < deme->params->program_size; i++) {
480
+ for(size_t j = 0; j < deme->params->deme_size; j++) {
481
+ evoasm_deme_seed_kernel(deme, i, j);
482
+ }
483
+ }
484
+ }
485
+
486
+ evoasm_success_t
487
+ evoasm_pop_seed(evoasm_pop_t *pop) {
488
+
489
+ #pragma omp parallel for
490
+ for(size_t i = 0; i < pop->params->n_demes; i++) {
491
+ evoasm_deme_seed(&pop->demes[i]);
492
+ }
493
+ pop->seeded = true;
494
+ return true;
495
+ }
496
+
497
+ static void
498
+ evoasm_deme_load_program_(evoasm_deme_t *deme,
499
+ evoasm_program_t *program,
500
+ evoasm_pop_program_data_t *program_data,
501
+ evoasm_pop_kernel_data_t *kernel_data,
502
+ size_t program_idx,
503
+ size_t *kernel_idxs,
504
+ size_t deme_size) {
505
+
506
+ size_t program_size = deme->params->program_size;
507
+ size_t kernel_size = deme->params->kernel_size;
508
+
509
+ for(size_t i = 0; i < program_size; i++) {
510
+ size_t kernel_idx = kernel_idxs[i];
511
+ size_t inst0_off = EVOASM_DEME_KERNEL_INST_OFF_(deme_size, kernel_size, i, kernel_idx, 0);
512
+ evoasm_kernel_t *kernel = &program->kernels[i];
513
+
514
+ if(program->shallow) {
515
+ kernel->insts = &kernel_data->insts[inst0_off];
516
+ } else {
517
+ EVOASM_MEMCPY_N(kernel->insts,
518
+ &kernel_data->insts[inst0_off], kernel->size);
519
+ }
520
+
521
+ switch(deme->arch_id) {
522
+ case EVOASM_ARCH_X64:
523
+ if(program->shallow) {
524
+ kernel->params.x64 = &kernel_data->params.x64[inst0_off];
525
+ } else {
526
+ EVOASM_MEMCPY_N(kernel->params.x64,
527
+ &kernel_data->params.x64[inst0_off], kernel->size);
528
+ }
529
+ break;
530
+ default:
531
+ evoasm_assert_not_reached();
532
+ }
533
+ }
534
+
535
+ if(program_size > 1) {
536
+ for(size_t i = 0; i < program_size; i++) {
537
+ size_t program_pos_off = EVOASM_DEME_PROGRAM_POS_OFF_(program_size, program_idx, i);
538
+ program->jmp_offs[i] = program_data->jmp_offs[program_pos_off];
539
+ program->jmp_conds[i] = program_data->jmp_cond[program_pos_off];
540
+ }
541
+ }
542
+ }
543
+
544
+ static inline void
545
+ evoasm_deme_load_program(evoasm_deme_t *deme,
546
+ evoasm_program_t *program,
547
+ evoasm_pop_program_data_t *program_data,
548
+ evoasm_pop_kernel_data_t *kernel_data,
549
+ size_t program_idx,
550
+ size_t *kernel_idxs) {
551
+
552
+ evoasm_deme_load_program_(deme, program, program_data,
553
+ kernel_data, program_idx, kernel_idxs,
554
+ deme->params->deme_size);
555
+ }
556
+
557
+
558
+ static evoasm_success_t
559
+ evoasm_deme_eval_program(evoasm_deme_t *deme, evoasm_program_t *program, evoasm_loss_t *ret_loss) {
560
+ evoasm_pop_params_t *params = deme->params;
561
+
562
+ //bool prepare, bool emit_kernels, bool emit_io_load_store, bool set_io_mapping
563
+ evoasm_program_emit_flags_t emit_flags =
564
+ EVOASM_PROGRAM_EMIT_FLAG_PREPARE |
565
+ EVOASM_PROGRAM_EMIT_FLAG_EMIT_KERNELS |
566
+ EVOASM_PROGRAM_EMIT_FLAG_EMIT_IO_LOAD_STORE |
567
+ EVOASM_PROGRAM_EMIT_FLAG_SET_IO_MAPPING;
568
+
569
+ if(!evoasm_program_emit(program, params->program_input, emit_flags)) {
570
+ *ret_loss = INFINITY;
571
+
572
+ if(evoasm_last_error.code == EVOASM_PROGRAM_ERROR_CODE_NO_OUTPUT) {
573
+ /* do not abort on this error, instead just let loss be infinity */
574
+ return true;
575
+ }
576
+ return false;
577
+ }
578
+
579
+ *ret_loss = evoasm_program_eval(program, params->program_output);
580
+
581
+ return true;
582
+ }
583
+
584
+ static void
585
+ evoasm_deme_register_loss_sample(evoasm_deme_t *deme, size_t row, size_t indiv_idx, evoasm_loss_t loss) {
586
+ size_t indiv_off = EVOASM_DEME_INDIV_OFF(deme, row, indiv_idx);
587
+ size_t sample_counter = deme->loss_data.counters[indiv_off];
588
+
589
+ if(sample_counter < EVOASM_DEME_MAX_LOSS_SAMPLES) {
590
+ size_t sample_off = EVOASM_DEME_LOSS_SAMPLE_OFF(deme, row, indiv_idx, sample_counter);
591
+ deme->loss_data.samples[sample_off] = loss;
592
+ deme->loss_data.counters[indiv_off]++;
593
+ }
594
+ }
595
+
596
+
597
+ static evoasm_deme_t *
598
+ evoasm_pop_find_best_deme(evoasm_pop_t *pop) {
599
+ evoasm_deme_t *best_deme = &pop->demes[0];
600
+ evoasm_loss_t best_loss = best_deme->best_loss;
601
+
602
+ for(size_t i = 1; i < pop->params->n_demes; i++) {
603
+ evoasm_deme_t *deme = &pop->demes[i];
604
+ if(deme->best_loss < best_loss) {
605
+ best_loss = deme->best_loss;
606
+ best_deme = deme;
607
+ }
608
+ }
609
+ return best_deme;
610
+ }
611
+
612
+ evoasm_success_t
613
+ evoasm_pop_load_best_program(evoasm_pop_t *pop, evoasm_program_t *program) {
614
+
615
+ evoasm_deme_t *best_deme = evoasm_pop_find_best_deme(pop);
616
+ evoasm_pop_params_t *params = best_deme->params;
617
+
618
+ EVOASM_TRY(error, evoasm_program_init, program,
619
+ evoasm_get_arch_info(best_deme->arch_id),
620
+ params->program_size,
621
+ params->kernel_size,
622
+ best_deme->n_examples,
623
+ params->recur_limit,
624
+ false);
625
+
626
+ size_t program_idx = 0;
627
+ size_t kernel_idxs[EVOASM_PROGRAM_MAX_SIZE] = {0};
628
+
629
+ evoasm_deme_load_program_(best_deme,
630
+ program,
631
+ &best_deme->best_program_data,
632
+ &best_deme->best_kernel_data,
633
+ program_idx,
634
+ kernel_idxs,
635
+ 1);
636
+
637
+
638
+ program->_input = *params->program_input;
639
+ program->_output = *params->program_output;
640
+ program->_input.len = 0;
641
+ program->_output.len = 0;
642
+
643
+ evoasm_program_emit_flags_t emit_flags =
644
+ EVOASM_PROGRAM_EMIT_FLAG_PREPARE |
645
+ EVOASM_PROGRAM_EMIT_FLAG_EMIT_KERNELS |
646
+ EVOASM_PROGRAM_EMIT_FLAG_EMIT_IO_LOAD_STORE |
647
+ EVOASM_PROGRAM_EMIT_FLAG_SET_IO_MAPPING;
648
+
649
+ EVOASM_TRY(error, evoasm_program_emit, program, params->program_input, emit_flags);
650
+
651
+ evoasm_signal_set_exception_mask(program->exception_mask);
652
+ evoasm_loss_t loss = evoasm_program_eval(program, params->program_output);
653
+ assert(loss == best_deme->best_loss);
654
+ evoasm_signal_clear_exception_mask();
655
+
656
+ return true;
657
+
658
+ error:
659
+ return false;
660
+ }
661
+
662
+ static evoasm_success_t
663
+ evoasm_deme_test_program(evoasm_deme_t *deme, size_t program_idx, size_t *kernel_idxs, evoasm_loss_t *ret_loss) {
664
+
665
+ evoasm_loss_t loss;
666
+ evoasm_program_t *program = &deme->program;
667
+ evoasm_pop_kernel_data_t *kernel_data = &deme->kernel_data;
668
+ evoasm_pop_program_data_t *program_data = &deme->program_data;
669
+
670
+ evoasm_deme_load_program(deme, program, program_data, kernel_data, program_idx, kernel_idxs);
671
+
672
+ EVOASM_TRY(error, evoasm_deme_eval_program, deme, program, &loss);
673
+
674
+ size_t program_size = deme->params->program_size;
675
+
676
+ for(size_t i = 0; i < program_size; i++) {
677
+ evoasm_deme_register_loss_sample(deme, i, kernel_idxs[i], loss);
678
+ }
679
+
680
+ if(program_size > 1) {
681
+ evoasm_deme_register_loss_sample(deme, EVOASM_DEME_PROGRAMS_ROW(deme),
682
+ program_idx, loss);
683
+ }
684
+
685
+ *ret_loss = loss;
686
+ return true;
687
+ error:
688
+ return false;
689
+ }
690
+
691
+
692
+ static void
693
+ evoasm_pop_program_data_copy(evoasm_pop_program_data_t *program_data,
694
+ size_t off,
695
+ evoasm_pop_program_data_t *dst,
696
+ size_t dst_off,
697
+ size_t len) {
698
+
699
+ memcpy(dst->jmp_offs + dst_off, program_data->jmp_offs + off,
700
+ sizeof(int16_t) * len);
701
+ memcpy(dst->jmp_cond + dst_off, program_data->jmp_cond + off,
702
+ sizeof(uint8_t) * len);
703
+ }
704
+
705
+ static evoasm_used void
706
+ evoasm_pop_program_data_move(evoasm_pop_program_data_t *program_data,
707
+ size_t src_off,
708
+ size_t dst_off,
709
+ size_t len) {
710
+
711
+ memmove(program_data->jmp_offs + dst_off, program_data->jmp_offs + src_off,
712
+ sizeof(int16_t) * len);
713
+ memmove(program_data->jmp_cond + dst_off, program_data->jmp_cond + src_off,
714
+ sizeof(uint8_t) * len);
715
+ }
716
+
717
+
718
+ static void
719
+ evoasm_pop_kernel_data_copy(evoasm_pop_kernel_data_t *kernel_data,
720
+ evoasm_arch_id_t arch_id,
721
+ size_t off,
722
+ evoasm_pop_kernel_data_t *dst,
723
+ size_t dst_off,
724
+ size_t len) {
725
+
726
+ memcpy(dst->insts + dst_off, kernel_data->insts + off,
727
+ sizeof(evoasm_inst_id_t) * len);
728
+
729
+ switch(arch_id) {
730
+ case EVOASM_ARCH_X64:
731
+ memcpy(dst->params.x64 + dst_off, kernel_data->params.x64 + off,
732
+ sizeof(evoasm_x64_basic_params_t) * len);
733
+ break;
734
+ default:
735
+ evoasm_assert_not_reached();
736
+ }
737
+ }
738
+
739
+ static evoasm_used void
740
+ evoasm_pop_kernel_data_move(evoasm_pop_kernel_data_t *kernel_data,
741
+ evoasm_arch_id_t arch_id,
742
+ size_t src_off,
743
+ size_t dst_off,
744
+ size_t len) {
745
+
746
+ memmove(kernel_data->insts + dst_off, kernel_data->insts + src_off,
747
+ sizeof(evoasm_inst_id_t) * len);
748
+
749
+ switch(arch_id) {
750
+ case EVOASM_ARCH_X64:
751
+ memmove(kernel_data->params.x64 + dst_off, kernel_data->params.x64 + src_off,
752
+ sizeof(evoasm_x64_basic_params_t) * len);
753
+ break;
754
+ default:
755
+ evoasm_assert_not_reached();
756
+ }
757
+ }
758
+
759
+ static inline void
760
+ evoasm_deme_update_best(evoasm_deme_t *deme, evoasm_loss_t loss, size_t program_idx, size_t *kernel_idxs) {
761
+
762
+ if(loss < deme->best_loss) {
763
+ size_t src_program_pos0_off = EVOASM_DEME_PROGRAM_POS_OFF(deme, program_idx, 0);
764
+ size_t dst_program_pos0_off = EVOASM_DEME_PROGRAM_POS_OFF_(deme->params->program_size, 0, 0);
765
+
766
+ size_t program_size = deme->params->program_size;
767
+ size_t kernel_size = deme->params->kernel_size;
768
+
769
+ evoasm_log_info("new best program loss: %g", loss);
770
+ evoasm_program_log(&deme->program, EVOASM_LOG_LEVEL_INFO);
771
+
772
+ deme->best_loss = loss;
773
+
774
+ if(program_size > 1) {
775
+ evoasm_pop_program_data_copy(&deme->program_data, src_program_pos0_off,
776
+ &deme->best_program_data, dst_program_pos0_off, program_size);
777
+ }
778
+
779
+ for(size_t k = 0; k < program_size; k++) {
780
+ size_t src_kernel_inst0_off = EVOASM_DEME_KERNEL_INST_OFF(deme, k, kernel_idxs[k], 0);
781
+ size_t dst_kernel_inst0_off = EVOASM_DEME_KERNEL_INST_OFF_(1, deme->params->kernel_size, k, 0, 0);
782
+
783
+ evoasm_pop_kernel_data_copy(&deme->kernel_data, deme->arch_id, src_kernel_inst0_off,
784
+ &deme->best_kernel_data, dst_kernel_inst0_off, kernel_size);
785
+
786
+ }
787
+ }
788
+ }
789
+
790
+ static evoasm_success_t
791
+ evoasm_deme_test_programs(evoasm_deme_t *deme) {
792
+ evoasm_prng_t *prng = &deme->prng;
793
+ size_t program_size = deme->params->program_size;
794
+
795
+ for(size_t i = 0; i < deme->params->deme_size; i++) {
796
+ for(size_t j = 0; j < EVOASM_DEME_MIN_LOSS_SAMPLES; j++) {
797
+ size_t kernel_idxs[EVOASM_PROGRAM_MAX_SIZE];
798
+ evoasm_loss_t loss;
799
+
800
+ for(size_t k = 0; k < program_size; k++) {
801
+ size_t kernel_idx = (size_t) evoasm_prng_rand_between_(prng, 0,
802
+ deme->params->deme_size - 1);
803
+ kernel_idxs[k] = kernel_idx;
804
+ }
805
+
806
+ EVOASM_TRY(error, evoasm_deme_test_program, deme, i, kernel_idxs, &loss);
807
+ evoasm_deme_update_best(deme, loss, i, kernel_idxs);
808
+ }
809
+
810
+ assert(deme->loss_data.counters[EVOASM_DEME_INDIV_OFF(deme, EVOASM_DEME_PROGRAMS_ROW(deme), i)] ==
811
+ EVOASM_DEME_MIN_LOSS_SAMPLES);
812
+ }
813
+
814
+ return true;
815
+
816
+ error:
817
+ return false;
818
+ }
819
+
820
+ #include <stdlib.h>
821
+
822
+ static evoasm_success_t
823
+ evoasm_deme_test_kernels(evoasm_deme_t *deme) {
824
+
825
+ evoasm_prng_t *prng = &deme->prng;
826
+ size_t kernel_idxs[EVOASM_PROGRAM_MAX_SIZE];
827
+ size_t program_size = deme->params->program_size;
828
+
829
+ for(size_t i = 0; i < deme->params->program_size; i++) {
830
+ for(size_t j = 0; j < deme->params->deme_size; j++) {
831
+ size_t kernel_off = EVOASM_DEME_INDIV_OFF(deme, i, j);
832
+ size_t n_samples = deme->loss_data.counters[kernel_off];
833
+
834
+ for(size_t k = n_samples; k < EVOASM_DEME_MIN_LOSS_SAMPLES; k++) {
835
+ size_t program_idx;
836
+ evoasm_loss_t loss;
837
+
838
+ program_idx = (size_t) evoasm_prng_rand_between_(prng, 0, deme->params->deme_size - 1);
839
+
840
+ for(size_t l = 0; l < program_size; l++) {
841
+ size_t load_kernel_idx;
842
+
843
+ if(l == i) {
844
+ /* the current kernel */
845
+ load_kernel_idx = j;
846
+ } else {
847
+ /* some random other kernel */
848
+ load_kernel_idx = (size_t) evoasm_prng_rand_between_(prng, 0, deme->params->deme_size - 1);
849
+ }
850
+ kernel_idxs[l] = load_kernel_idx;
851
+ }
852
+ EVOASM_TRY(error, evoasm_deme_test_program, deme, program_idx, kernel_idxs, &loss);
853
+ evoasm_deme_update_best(deme, loss, program_idx, kernel_idxs);
854
+ }
855
+ }
856
+ }
857
+
858
+ return true;
859
+ error:
860
+ return false;
861
+ }
862
+
863
+ #define EVOASM_SORT_PAIR(t, a, b) \
864
+ do { \
865
+ t x = EVOASM_MIN(a, b); \
866
+ t y = EVOASM_MAX(a, b); \
867
+ (a) = x;\
868
+ (b) = y;\
869
+ } while(0);
870
+
871
+ typedef void (*evoasm_pop_loss_sort_func_t)(evoasm_loss_t *);
872
+
873
+ static int evoasm_pop_loss_cmp_func(const void *a, const void *b) {
874
+ evoasm_loss_t loss_a = *(const evoasm_loss_t *) a;
875
+ evoasm_loss_t loss_b = *(const evoasm_loss_t *) b;
876
+ return (loss_a > loss_b) - (loss_a < loss_b);
877
+ }
878
+
879
+ #define EVOASM_POP_FIND_MEDIAN_RUN_LEN 8u
880
+
881
+ static inline evoasm_loss_t
882
+ evoasm_pop_find_median_loss_(evoasm_loss_t *losses, size_t len) {
883
+
884
+ evoasm_loss_t median;
885
+ assert(len >= EVOASM_DEME_MIN_LOSS_SAMPLES && len <= EVOASM_DEME_MAX_LOSS_SAMPLES);
886
+
887
+ size_t trunc_len = EVOASM_ALIGN_DOWN(len, EVOASM_POP_FIND_MEDIAN_RUN_LEN);
888
+ size_t n_runs = trunc_len / EVOASM_POP_FIND_MEDIAN_RUN_LEN;
889
+ size_t front_idxs[EVOASM_DEME_MAX_LOSS_SAMPLES / EVOASM_POP_FIND_MEDIAN_RUN_LEN] = {0};
890
+ evoasm_loss_t scratch[EVOASM_DEME_MAX_LOSS_SAMPLES / 2];
891
+
892
+ for(size_t i = 0; i < trunc_len; i += EVOASM_POP_FIND_MEDIAN_RUN_LEN) {
893
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 0], losses[i + 1]);
894
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 2], losses[i + 3]);
895
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 0], losses[i + 2]);
896
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 1], losses[i + 3]);
897
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 1], losses[i + 2]);
898
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 4], losses[i + 5]);
899
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 6], losses[i + 7]);
900
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 4], losses[i + 6]);
901
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 5], losses[i + 7]);
902
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 5], losses[i + 6]);
903
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 0], losses[i + 4]);
904
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 1], losses[i + 5]);
905
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 1], losses[i + 4]);
906
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 2], losses[i + 6]);
907
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 3], losses[i + 7]);
908
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 3], losses[i + 6]);
909
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 2], losses[i + 4]);
910
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 3], losses[i + 5]);
911
+ EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 3], losses[i + 4]);
912
+ }
913
+
914
+ switch(n_runs) {
915
+ case 1:
916
+ return losses[EVOASM_POP_FIND_MEDIAN_RUN_LEN / 2 - 1];
917
+ case 2: {
918
+ const size_t merge_len = 8;
919
+ for(size_t i = 0; i < merge_len; i++) {
920
+ size_t loss_off0 = 0 * EVOASM_POP_FIND_MEDIAN_RUN_LEN + front_idxs[0];
921
+ size_t loss_off1 = 1 * EVOASM_POP_FIND_MEDIAN_RUN_LEN + front_idxs[1];
922
+ evoasm_loss_t loss0 = losses[loss_off0];
923
+ evoasm_loss_t loss1 = losses[loss_off1];
924
+ evoasm_loss_t min_loss;
925
+ size_t min_run_idx;
926
+
927
+ if(loss0 < loss1) {
928
+ min_run_idx = 0;
929
+ min_loss = loss0;
930
+ } else {
931
+ min_run_idx = 1;
932
+ min_loss = loss1;
933
+ }
934
+ front_idxs[min_run_idx]++;
935
+ scratch[i] = min_loss;
936
+ }
937
+ median = scratch[merge_len - 1];
938
+ break;
939
+ }
940
+ default:
941
+ evoasm_assert_not_reached();
942
+ }
943
+
944
+ #ifdef EVOASM_ENABLE_PARANOID_MODE
945
+ evoasm_loss_t median_;
946
+ qsort(losses, len, sizeof(evoasm_loss_t), evoasm_pop_loss_cmp_func);
947
+ median_ = losses[(len - 1) / 2];
948
+ assert(median == median_);
949
+ #endif
950
+
951
+ return median;
952
+ }
953
+
954
+ evoasm_loss_t
955
+ evoasm_pop_find_median_loss(evoasm_loss_t *losses, size_t len) {
956
+ return evoasm_pop_find_median_loss_(losses, len);
957
+ }
958
+
959
+ evoasm_loss_t
960
+ evoasm_pop_get_best_loss(evoasm_pop_t *pop) {
961
+ evoasm_deme_t *best_deme = evoasm_pop_find_best_deme(pop);
962
+ return best_deme->best_loss;
963
+ }
964
+
965
+ static void
966
+ evoasm_deme_eval_update(evoasm_deme_t *deme) {
967
+
968
+ evoasm_pop_loss_data_t *loss_data = &deme->loss_data;
969
+
970
+ size_t height = evoasm_pop_params_get_deme_height_(deme->params);
971
+
972
+ for(size_t i = 0; i < height; i++) {
973
+ deme->top_losses[i] = INFINITY;
974
+ }
975
+
976
+ for(size_t i = 0; i < height; i++) {
977
+ for(size_t j = 0; j < deme->params->deme_size; j++) {
978
+ size_t indiv_off = EVOASM_DEME_INDIV_OFF(deme, i, j);
979
+ size_t sample0_off = EVOASM_DEME_LOSS_SAMPLE_OFF(deme, i, j, 0);
980
+
981
+ evoasm_loss_t indiv_loss =
982
+ evoasm_pop_find_median_loss_(&loss_data->samples[sample0_off],
983
+ loss_data->counters[indiv_off]);
984
+
985
+ loss_data->samples[sample0_off] = indiv_loss;
986
+
987
+ if(indiv_loss < deme->top_losses[i]) {
988
+ evoasm_log_info("new top loss %zu: %f -> %f", i, deme->top_losses[i], indiv_loss);
989
+ deme->top_losses[i] = indiv_loss;
990
+ }
991
+ }
992
+ }
993
+ }
994
+
995
+ size_t
996
+ evoasm_pop_get_loss_samples(evoasm_pop_t *pop, size_t deme_idx, const evoasm_loss_t **losses) {
997
+ evoasm_deme_t *deme = &pop->demes[deme_idx];
998
+ size_t len = EVOASM_DEME_N_INDIVS(deme) * EVOASM_DEME_MAX_LOSS_SAMPLES;
999
+ *losses = deme->loss_data.samples;
1000
+
1001
+ return len;
1002
+ }
1003
+
1004
+ static evoasm_success_t
1005
+ evoasm_deme_eval(evoasm_deme_t *deme) {
1006
+ bool retval = true;
1007
+
1008
+ EVOASM_MEMSET_N(deme->loss_data.counters, 0, EVOASM_DEME_N_INDIVS(deme));
1009
+ //EVOASM_MEMSET_N(deme->loss_data.samples, 0, EVOASM_DEME_N_INDIVS(deme) * EVOASM_DEME_MAX_LOSS_SAMPLES);
1010
+
1011
+ if(deme->params->program_size > 1) {
1012
+ if(!evoasm_deme_test_programs(deme)) {
1013
+ retval = false;
1014
+ goto done;
1015
+ }
1016
+ }
1017
+
1018
+ if(!evoasm_deme_test_kernels(deme)) {
1019
+ retval = false;
1020
+ goto done;
1021
+ }
1022
+
1023
+ evoasm_deme_eval_update(deme);
1024
+
1025
+ done:
1026
+ return retval;
1027
+ }
1028
+
1029
+ evoasm_success_t
1030
+ evoasm_pop_eval(evoasm_pop_t *pop) {
1031
+ bool retval = true;
1032
+ size_t n_demes = pop->params->n_demes;
1033
+
1034
+ if(!pop->seeded) {
1035
+ retval = false;
1036
+ evoasm_error(EVOASM_ERROR_TYPE_POP, EVOASM_ERROR_CODE_NONE,
1037
+ "not seeded");
1038
+ goto done;
1039
+ }
1040
+
1041
+ bool *retvals = evoasm_alloca(sizeof(bool) * n_demes);
1042
+ evoasm_error_t *errors = evoasm_alloca(sizeof(evoasm_error_t) * n_demes);
1043
+
1044
+ #pragma omp parallel for
1045
+ for(size_t i = 0; i < n_demes; i++) {
1046
+ retvals[i] = evoasm_deme_eval(&pop->demes[i]);
1047
+ if(!retvals[i]) {
1048
+ errors[i] = *evoasm_get_last_error();
1049
+ }
1050
+ }
1051
+
1052
+ for(size_t i = 0; i < n_demes; i++) {
1053
+ if(!retvals[i]) {
1054
+ evoasm_set_last_error(&errors[i]);
1055
+ retval = false;
1056
+ break;
1057
+ }
1058
+ }
1059
+
1060
+ done:
1061
+ return retval;
1062
+ }
1063
+
1064
+
1065
+ static inline void
1066
+ evoasm_deme_select_indivs(evoasm_deme_t *deme, size_t row, bool programs) {
1067
+ evoasm_pop_loss_data_t *loss_data = &deme->loss_data;
1068
+ size_t n_doomed_indivs = 0;
1069
+ size_t n_blessed_indivs = 0;
1070
+ size_t deme_size = deme->params->deme_size;
1071
+
1072
+
1073
+ size_t n = 1;
1074
+ evoasm_loss_t avg_loss = 0.0;
1075
+ for(size_t i = 0; i < deme_size; i++) {
1076
+ evoasm_loss_t loss = loss_data->samples[EVOASM_DEME_LOSS_OFF(deme, row, i)];
1077
+ if(!isinf(loss)) {
1078
+ avg_loss += (loss - avg_loss) / (evoasm_loss_t) n;
1079
+ n++;
1080
+ }
1081
+ }
1082
+
1083
+ avg_loss += 0.0001f;
1084
+ for(size_t i = 0; i < deme_size; i++) {
1085
+ evoasm_loss_t loss = loss_data->samples[EVOASM_DEME_LOSS_OFF(deme, row, i)];
1086
+
1087
+ if(loss > avg_loss) {
1088
+ deme->doomed_indiv_idxs[n_doomed_indivs++] = (uint16_t) i;
1089
+ } else {
1090
+ deme->blessed_indiv_idxs[n_blessed_indivs++] = (uint16_t) i;
1091
+ }
1092
+ }
1093
+
1094
+ assert(n_blessed_indivs > 0);
1095
+ assert(n_doomed_indivs > 0);
1096
+
1097
+ deme->n_blessed_indivs = (uint16_t) n_blessed_indivs;
1098
+ deme->n_doomed_indivs = (uint16_t) n_doomed_indivs;
1099
+ }
1100
+
1101
+ static size_t
1102
+ evoasm_deme_get_indiv_size(evoasm_deme_t *deme, bool programs) {
1103
+ return programs ? deme->params->program_size : deme->params->kernel_size;
1104
+ }
1105
+
1106
+ static evoasm_force_inline inline void
1107
+ evoasm_deme_combine_indivs(evoasm_deme_t *deme, size_t row, size_t idx, bool programs) {
1108
+ evoasm_pop_loss_data_t *loss_data = &deme->loss_data;
1109
+ evoasm_pop_program_data_t *program_data = &deme->program_data;
1110
+ evoasm_pop_kernel_data_t *kernel_data = &deme->kernel_data;
1111
+ evoasm_prng_t *prng = &deme->prng;
1112
+
1113
+ size_t indiv_size = evoasm_deme_get_indiv_size(deme, programs);
1114
+
1115
+ size_t parent_idxs[2] = {
1116
+ deme->blessed_indiv_idxs[idx % deme->n_blessed_indivs],
1117
+ deme->blessed_indiv_idxs[(idx + 1) % deme->n_blessed_indivs]
1118
+ };
1119
+
1120
+ size_t child_idxs[2] = {
1121
+ deme->doomed_indiv_idxs[idx],
1122
+ deme->doomed_indiv_idxs[idx + 1]
1123
+ };
1124
+
1125
+ /* rough estimate */
1126
+ evoasm_loss_t child_loss = 0.5f * loss_data->samples[EVOASM_DEME_LOSS_OFF(deme, row, parent_idxs[0])]
1127
+ + 0.5f * loss_data->samples[EVOASM_DEME_LOSS_OFF(deme, row, parent_idxs[1])];
1128
+
1129
+ assert(isfinite(child_loss));
1130
+
1131
+ float crossover_point = evoasm_prng_randf_(prng);
1132
+ size_t seg1_len = EVOASM_MAX(1u, (size_t) (crossover_point * (float) indiv_size));
1133
+ size_t seg2_len = indiv_size - seg1_len;
1134
+
1135
+ for(size_t j = 0; j < 2; j++) {
1136
+ loss_data->samples[EVOASM_DEME_LOSS_OFF(deme, row, child_idxs[j])] = child_loss;
1137
+
1138
+ if(programs) {
1139
+ size_t parent_pos0_offs[] = {
1140
+ EVOASM_DEME_PROGRAM_POS_OFF(deme, parent_idxs[j], 0),
1141
+ EVOASM_DEME_PROGRAM_POS_OFF(deme, parent_idxs[1 - j], 0)
1142
+ };
1143
+
1144
+ size_t child_pos0_off = EVOASM_DEME_PROGRAM_POS_OFF(deme, child_idxs[j], 0);
1145
+
1146
+ evoasm_pop_program_data_copy(program_data, parent_pos0_offs[0],
1147
+ program_data, child_pos0_off, seg1_len);
1148
+ evoasm_pop_program_data_copy(program_data, parent_pos0_offs[1] + seg1_len,
1149
+ program_data, child_pos0_off + seg1_len, seg2_len);
1150
+
1151
+ } else {
1152
+ size_t parent_inst0_offs [] = {
1153
+ EVOASM_DEME_KERNEL_INST_OFF(deme, row, parent_idxs[j], 0),
1154
+ EVOASM_DEME_KERNEL_INST_OFF(deme, row, parent_idxs[1 - j], 0)
1155
+ };
1156
+ size_t child_inst0_off = EVOASM_DEME_KERNEL_INST_OFF(deme, row, child_idxs[j], 0);
1157
+
1158
+ evoasm_pop_kernel_data_copy(kernel_data, deme->arch_id, parent_inst0_offs[0],
1159
+ kernel_data, child_inst0_off, seg1_len);
1160
+ evoasm_pop_kernel_data_copy(kernel_data, deme->arch_id, parent_inst0_offs[1] + seg1_len,
1161
+ kernel_data, child_inst0_off + seg1_len, seg2_len);
1162
+ }
1163
+ }
1164
+ }
1165
+
1166
+ static evoasm_force_inline inline void
1167
+ evoasm_deme_combine(evoasm_deme_t *deme, size_t row, bool programs) {
1168
+ for(size_t i = 0; i < deme->n_doomed_indivs; i += 2) {
1169
+ evoasm_deme_combine_indivs(deme, row, i, programs);
1170
+ }
1171
+ }
1172
+
1173
+ static inline void
1174
+ evoasm_deme_calc_summary(evoasm_deme_t *deme, evoasm_loss_t *summary_losses, evoasm_loss_t *summary) {
1175
+ size_t deme_size = deme->params->deme_size;
1176
+ evoasm_pop_loss_data_t *loss_data = &deme->loss_data;
1177
+
1178
+ size_t height = evoasm_pop_params_get_deme_height_(deme->params);
1179
+
1180
+ for(size_t i = 0; i < height; i++) {
1181
+ size_t summary_off = i * 5;
1182
+
1183
+ for(size_t j = 0; j < deme_size; j++) {
1184
+ size_t loss_off = EVOASM_DEME_LOSS_OFF(deme, i, j);
1185
+ evoasm_loss_t loss = loss_data->samples[loss_off];
1186
+ summary_losses[j] = loss;
1187
+ }
1188
+
1189
+ qsort(summary_losses, deme_size, sizeof(evoasm_loss_t), evoasm_pop_loss_cmp_func);
1190
+
1191
+ for(size_t j = 0; j < 5; j++) {
1192
+ summary[summary_off + j] = summary_losses[j * (deme_size - 1) / 4];
1193
+ }
1194
+ }
1195
+ }
1196
+
1197
+ #define EVOASM_DEME_SUMMARY_LEN(pop) (5 * (evoasm_pop_params_get_deme_height_(pop->params)))
1198
+
1199
+ size_t
1200
+ evoasm_pop_summary_len(evoasm_pop_t *pop) {
1201
+ return pop->params->n_demes * EVOASM_DEME_SUMMARY_LEN(pop);
1202
+ }
1203
+
1204
+ evoasm_success_t
1205
+ evoasm_pop_calc_summary(evoasm_pop_t *pop, evoasm_loss_t *summary) {
1206
+
1207
+ const size_t deme_summary_len = EVOASM_DEME_SUMMARY_LEN(pop);
1208
+
1209
+ if(pop->summary_losses == NULL) {
1210
+ pop->summary_losses = evoasm_calloc(pop->params->deme_size, sizeof(evoasm_loss_t));
1211
+ if(!pop->summary_losses) {
1212
+ return false;
1213
+ }
1214
+ }
1215
+
1216
+ for(size_t i = 0; i < pop->params->n_demes; i++) {
1217
+ evoasm_deme_calc_summary(&pop->demes[i], pop->summary_losses, &summary[i * deme_summary_len]);
1218
+ }
1219
+
1220
+ return true;
1221
+ }
1222
+
1223
+
1224
+ #if 0
1225
+ size_t i;
1226
+ double scale = 1.0 / pop->params->size;
1227
+ double pop_loss = 0.0;
1228
+ *n_invalid = 0;
1229
+ for(i = 0; i < pop->params->size; i++) {
1230
+ double loss = pop->top_losses[i];
1231
+ if(loss != INFINITY) {
1232
+ pop_loss += scale * loss;
1233
+ } else {
1234
+ (*n_invalid)++;
1235
+ }
1236
+ }
1237
+
1238
+ if(per_example) pop_loss /= pop->n_examples;
1239
+ #endif
1240
+
1241
+ static evoasm_force_inline inline void
1242
+ evoasm_deme_mutate_indiv(evoasm_deme_t *deme, size_t row, size_t indiv_idx, bool program) {
1243
+ evoasm_prng_t *prng = &deme->prng;
1244
+ size_t indiv_size = evoasm_deme_get_indiv_size(deme, program);
1245
+
1246
+ if(evoasm_prng_randf_(prng) < deme->params->mut_rate) {
1247
+ uint64_t r = evoasm_prng_rand64_(prng);
1248
+ size_t elem_idx = (r % indiv_size);
1249
+
1250
+ if(program) {
1251
+ evoasm_deme_seed_program_pos(deme, indiv_idx, elem_idx);
1252
+ } else {
1253
+ evoasm_deme_seed_kernel_inst(deme, row, indiv_idx, elem_idx);
1254
+ }
1255
+ }
1256
+ }
1257
+
1258
+ static evoasm_force_inline inline void
1259
+ evoasm_deme_mutate(evoasm_deme_t *deme, size_t row, bool programs) {
1260
+ for(size_t i = 0; i < deme->params->deme_size; i++) {
1261
+ evoasm_deme_mutate_indiv(deme, row, i, programs);
1262
+ }
1263
+ }
1264
+
1265
+ static void
1266
+ evoasm_deme_next_gen(evoasm_deme_t *deme) {
1267
+ for(size_t i = 0; i < deme->params->program_size; i++) {
1268
+ evoasm_deme_select_indivs(deme, i, false);
1269
+ evoasm_deme_combine(deme, i, false);
1270
+ if(deme->params->mut_rate > 0) {
1271
+ evoasm_deme_mutate(deme, i, false);
1272
+ }
1273
+ }
1274
+
1275
+ if(deme->params->program_size > 1) {
1276
+ evoasm_deme_select_indivs(deme, EVOASM_DEME_PROGRAMS_ROW(deme), true);
1277
+ evoasm_deme_combine(deme, EVOASM_DEME_PROGRAMS_ROW(deme), true);
1278
+
1279
+ if(deme->params->mut_rate > 0) {
1280
+ evoasm_deme_mutate(deme, EVOASM_DEME_PROGRAMS_ROW(deme), true);
1281
+ }
1282
+ }
1283
+ }
1284
+
1285
+ void
1286
+ evoasm_pop_next_gen(evoasm_pop_t *pop) {
1287
+ #pragma omp parallel for
1288
+ for(size_t i = 0; i < pop->params->n_demes; i++) {
1289
+ evoasm_deme_next_gen(&pop->demes[i]);
1290
+ }
1291
+ }
1292
+
1293
+ #if 0
1294
+
1295
+ evoasm_pop_select(pop, blessed_indiv_idxs, pop->params->size);
1296
+ {
1297
+ double scale = 1.0 / pop->params->size;
1298
+ double pop_loss = 0.0;
1299
+ size_t n_inf = 0;
1300
+ for(i = 0; i < pop->params->size; i++) {
1301
+ double loss = pop->pop.top_losses[blessed_indiv_idxs[i]];
1302
+ if(loss != INFINITY) {
1303
+ pop_loss += scale * loss;
1304
+ }
1305
+ else {
1306
+ n_inf++;
1307
+ }
1308
+ }
1309
+
1310
+ evoasm_log_info("pop selected loss: %g/%u", pop_loss, n_inf);
1311
+ }
1312
+
1313
+ size_t i;
1314
+ for(i = 0; i < pop->params->size; i++) {
1315
+ evoasm_program_params_t *program_params = EVOASM_SEARCH_PROGRAM_PARAMS(pop, pop->pop.indivs, blessed_indiv_idxs[i]);
1316
+ assert(program_params->size > 0);
1317
+ }
1318
+
1319
+ return evoasm_pop_combine_parents(pop, blessed_indiv_idxs);
1320
+ }
1321
+ #endif
1322
+
1323
+ EVOASM_DEF_ALLOC_FREE_FUNCS(pop)