5 #ifndef ROCKY_ZAGROS_FLOW_GUARD
6 #define ROCKY_ZAGROS_FLOW_GUARD
9 #include<rocky/zagros/strategies/init.h>
10 #include<rocky/zagros/strategies/log.h>
11 #include<rocky/zagros/strategies/pso.h>
12 #include<rocky/zagros/strategies/analysis.h>
13 #include<rocky/zagros/strategies/genetic.h>
14 #include<rocky/zagros/strategies/differential_evolution.h>
15 #include<rocky/zagros/strategies/eda.h>
16 #include<rocky/zagros/strategies/blocked_descent.h>
17 #include<rocky/zagros/strategies/container_manipulation.h>
18 #include<rocky/zagros/dena.h>
29 template<
typename T_e,
int T_dim,
int T_block_dim>
33 std::vector<std::unique_ptr<basic_scontainer<T_e, T_block_dim>>> cnt_storage;
35 std::map<int, std::vector<std::unique_ptr<basic_strategy<T_e, T_block_dim>>>> str_storage;
37 std::map<std::string, int> cnt_map;
39 std::map<int, int> iter_counter;
41 std::map<int, std::deque<T_e>> conv_tracker;
43 std::vector<int> bcd_mask;
45 std::unique_ptr<basic_scontainer<T_e, T_dim>> blocked_state;
46 tbb::enumerable_thread_specific<std::vector<T_e>> th_blocked_states;
48 std::unique_ptr<basic_scontainer<T_e, T_block_dim>> partial_best;
50 size_t container_space(){
51 size_t allocated_mem = 0;
52 for(
auto const& cnt: cnt_storage)
53 allocated_mem += cnt->space();
54 if constexpr(T_dim != T_block_dim){
55 allocated_mem += blocked_state->space();
56 allocated_mem += partial_best->space();
57 for(
auto const& th_state: th_blocked_states)
58 allocated_mem += th_state.size() *
sizeof(T_e);
68 auto it = cnt_map.find(
id);
69 return it != cnt_map.end();
78 if (
id == std::string(
"__best__"))
79 return partial_best.get();
82 spdlog::warn(
"container {} does not exist",
id);
85 int target_cnt_ind = cnt_map[id];
86 return cnt_storage[target_cnt_ind].get();
88 void allocate_container(std::string
id,
int n_particles,
int group_size){
90 auto cnt = std::make_unique<basic_scontainer<T_e, T_block_dim>>(n_particles, group_size);
92 spdlog::info(
"container {} was allocated. size : {:.2f} MB",
id, cnt->space()/(1024.0*1024.0));
93 cnt_storage.push_back(std::move(cnt));
95 cnt_map[id] = cnt_storage.size()-1;
98 void update_partial_best(){
99 std::pair<T_e, int> best;
101 best.first = std::numeric_limits<T_e>::max();
102 for(
int ci=0; ci<cnt_storage.size(); ci++){
103 auto min_and_index = cnt_storage[ci]->best_min_index();
104 if((min_and_index.first < best.first) || best_ci == -1){
105 best = min_and_index;
109 if (best.first < partial_best->values[0]){
111 std::copy(cnt_storage[best_ci]->particle(best.second),
112 cnt_storage[best_ci]->particle(best.second)+T_block_dim,
113 partial_best->particle(0));
116 partial_best->values[0] = best.first;
120 void sync_partial_best(){
123 sync_broadcast_best<T_e, T_block_dim> sync_best_partial_str(partial_best.get());
124 sync_best_partial_str.apply();
126 for(
int i=0; i<T_block_dim; i++)
127 blocked_state->particles[0][bcd_mask[i]] = partial_best->particles[0][i];
129 for(
auto& th_state: th_blocked_states)
130 for(
int i=0; i<T_block_dim; i++)
131 th_state[bcd_mask[i]] = partial_best->particles[0][i];
135 for(
auto& cnt: cnt_storage)
137 for(
auto& [tag, str_vec]: str_storage)
138 for(
auto& str: str_vec)
149 template<
typename T_e,
int T_dim,
int T_block_dim>
156 std::stack<int>* path_stack;
165 path_stack->push(node.sub_procedure.front());
168 main_storage->conv_tracker[node.tag] = std::deque<T_e>();
169 path_stack->push(node.sub_procedure.front());
172 main_storage->iter_counter[node.tag] = 0;
173 path_stack->push(node.sub_procedure.front());
176 path_stack->push(node.sub_procedure.front());
179 main_storage->allocate_container(node.id, node.n_particles, node.group_size);
185 auto main_cnt = main_storage->
container(node.main_cnt_id);
186 int n_particles = main_cnt->n_particles();
187 int n_groups = main_cnt->n_groups();
188 int group_size = main_cnt->group_size();
190 using namespace dena;
192 main_storage->allocate_container(pso::memory::particles_vel(node.memory_id), n_particles, group_size);
194 main_storage->allocate_container(pso::memory::particles_mem(node.memory_id), n_particles, group_size);
196 main_storage->allocate_container(pso::memory::groups_mem(node.memory_id), n_groups, 1);
198 main_storage->allocate_container(pso::memory::node_mem(node.memory_id), 1, 1);
200 main_storage->allocate_container(pso::memory::cluster_mem(node.memory_id), 1, 1);
206 auto main_cnt = main_storage->
container(node.id);
207 int n_particles = main_cnt->n_particles();
212 auto main_cnt = main_storage->
container(node.id);
213 int n_particles = main_cnt->n_particles();
218 auto main_cnt = main_storage->
container(node.id);
219 int n_particles = main_cnt->n_particles();
224 auto main_cnt = main_storage->
container(node.id);
225 int n_particles = main_cnt->n_particles();
226 int temp_size = T_block_dim;
227 if(n_particles < temp_size){
228 temp_size = n_particles;
229 spdlog::warn(
"For using EDA it is recommended to choose number of particles larger than BCD block");
235 auto main_cnt = main_storage->
container(node.id);
236 int n_particles = main_cnt->n_particles();
246 template<
typename T_e,
int T_dim,
int T_block_dim>
253 std::stack<int>* path_stack;
257 auto gen_str = std::make_unique<bcd_mask_uniform_random<T_e, T_block_dim>>(
dynamic_cast<blocked_system<T_e>*
>(problem), &(main_storage->bcd_mask));
259 main_storage->str_storage[node.tag].push_back(std::move(gen_str));
261 auto sync_str = std::make_unique<sync_bcd_mask<T_e, T_block_dim>>(main_storage->bcd_mask.data());
263 main_storage->str_storage[node.tag].push_back(std::move(sync_str));
267 if(node.id.size() == 0)
268 target_cnt = main_storage->partial_best.get();
270 target_cnt = main_storage->
container(node.id);
272 auto str = std::make_unique<local_log_best<T_e, T_block_dim>>(problem, target_cnt, node.handler);
274 main_storage->str_storage[node.tag].push_back(std::move(str));
278 if(node.id.size() == 0)
279 target_cnt = main_storage->partial_best.get();
281 target_cnt = main_storage->
container(node.id);
283 auto str = std::make_unique<comet_log_best<T_e, T_block_dim>>(problem, target_cnt, node.handler);
285 main_storage->str_storage[node.tag].push_back(std::move(str));
289 auto target_cnt = main_storage->
container(node.id);
291 auto str = std::make_unique<sync_broadcast_best<T_e, T_block_dim>>(target_cnt);
293 main_storage->str_storage[node.tag].push_back(std::move(str));
297 auto target_cnt = main_storage->
container(node.id);
299 auto str = std::make_unique<uniform_init_strategy<T_e, T_block_dim>>(problem, target_cnt);
301 main_storage->str_storage[node.tag].push_back(std::move(str));
305 path_stack->push(node.sub_procedure.front());
308 path_stack->push(node.sub_procedure.front());
311 path_stack->push(node.sub_procedure.front());
314 path_stack->push(node.sub_procedure.front());
318 auto des_cnt = main_storage->
container(node.des);
319 auto src_cnt = main_storage->
container(node.src);
320 auto str = std::make_unique<select_from_strategy<T_e, T_block_dim>>(des_cnt, src_cnt);
321 main_storage->str_storage[node.tag].push_back(std::move(str));
324 auto cnt = main_storage->
container(node.id);
325 auto str = std::make_unique<eval_strategy<T_e, T_block_dim>>(problem, cnt);
326 main_storage->str_storage[node.tag].push_back(std::move(str));
331 using namespace dena;
332 auto main_cnt = main_storage->
container(node.main_cnt_id);
333 auto particles_v = main_storage->
container(pso::memory::particles_vel(node.memory_id));
334 auto particles_mem = main_storage->
container(pso::memory::particles_mem(node.memory_id));
335 auto groups_mem = main_storage->
container(pso::memory::groups_mem(node.memory_id));
336 auto node_mem = main_storage->
container(pso::memory::node_mem(node.memory_id));
337 auto cluster_mem = main_storage->
container(pso::memory::cluster_mem(node.memory_id));
338 auto str = std::make_unique<pso_l1_strategy<T_e, T_block_dim>>(problem, main_cnt, particles_v, particles_mem, groups_mem, node_mem, cluster_mem);
340 main_storage->str_storage[node.tag].push_back(std::move(str));
344 using namespace dena;
345 auto main_cnt = main_storage->
container(node.main_cnt_id);
346 auto particles_v = main_storage->
container(pso::memory::particles_vel(node.memory_id));
347 auto particles_mem = main_storage->
container(pso::memory::particles_mem(node.memory_id));
348 auto groups_mem = main_storage->
container(pso::memory::groups_mem(node.memory_id));
349 auto node_mem = main_storage->
container(pso::memory::node_mem(node.memory_id));
350 auto cluster_mem = main_storage->
container(pso::memory::cluster_mem(node.memory_id));
351 auto str = std::make_unique<pso_l3_strategy<T_e, T_block_dim>>(problem, main_cnt, particles_v, particles_mem, groups_mem, node_mem, cluster_mem);
353 main_storage->str_storage[node.tag].push_back(std::move(str));
356 auto main_cnt = main_storage->
container(node.id);
358 auto str = std::make_unique<gaussian_mutation<T_e, T_block_dim>>(problem, main_cnt, temp_cnt, node.dims, node.mu, node.sigma);
360 main_storage->str_storage[node.tag].push_back(std::move(str));
363 auto main_cnt = main_storage->
container(node.id);
365 auto str = std::make_unique<multipoint_crossover<T_e, T_block_dim>>(problem, main_cnt, temp_cnt, node.dims);
367 main_storage->str_storage[node.tag].push_back(std::move(str));
370 auto main_cnt = main_storage->
container(node.id);
372 auto str = std::make_unique<basic_differential_evolution<T_e, T_block_dim>>(problem, main_cnt, temp_cnt, node.crossover_prob, node.differential_weight);
374 main_storage->str_storage[node.tag].push_back(std::move(str));
377 auto main_cnt = main_storage->
container(node.id);
379 auto str = std::make_unique<eda_mutivariate_normal<T_e, T_block_dim>>(problem, main_cnt, temp_cnt, T_block_dim);
381 main_storage->str_storage[node.tag].push_back(std::move(str));
384 auto main_cnt = main_storage->
container(node.id);
386 int segment_length = node.segment_length;
387 if (segment_length >= T_block_dim){
388 int segment_length = std::max(T_block_dim-1, 1);
389 spdlog::warn(
"segment length must be less than BCD block size!");
391 auto str = std::make_unique<static_segment_crossover<T_e, T_block_dim>>(problem, main_cnt, temp_cnt, segment_length);
393 main_storage->str_storage[node.tag].push_back(std::move(str));
396 if (T_block_dim != 2){
397 spdlog::warn(
"For using heatmap the block dimension should be 2.");
404 auto str = std::make_unique<loss_projection_2d<T_e, T_block_dim>>(problem, node.label, node.width, node.height, x_min, y_min, x_max, y_max);
405 main_storage->str_storage[node.tag].push_back(std::move(str));
408 auto main_cnt = main_storage->
container(node.id);
409 auto str = std::make_unique<container_position_recorder<T_e, T_block_dim>>(problem, main_cnt, node.handler);
410 main_storage->str_storage[node.tag].push_back(std::move(str));
418 template<
typename T_e,
int T_dim,
int T_block_dim,
typename T_traverse_fn>
425 T_traverse_fn* traverse_fn;
427 template<
typename T_n>
428 void operator()(T_n node){
429 if constexpr (std::is_base_of<dena::run_node, T_n>::value){
431 if constexpr (std::is_base_of<dena::run_n_times_node, T_n>::value){
432 for(
int i=0; i<node.n_iters; i++){
433 (*traverse_fn)(node.sub_procedure.front(), problem, main_storage);
437 if constexpr (std::is_base_of<dena::run_with_probability_node, T_n>::value){
438 float sample = utils::random::uniform<float>(0.0, 1.0);
439 if(sample < node.prob){
440 (*traverse_fn)(node.sub_procedure.front(), problem, main_storage);
443 if constexpr (std::is_base_of<dena::run_every_n_steps_node, T_n>::value){
444 int p = main_storage->iter_counter[node.tag];
445 main_storage->iter_counter[node.tag] = (p+1) % node.period;
447 (*traverse_fn)(node.sub_procedure.front(), problem, main_storage);
449 if constexpr (std::is_base_of<dena::run_until_no_improve_node, T_n>::value){
451 T_e value = main_storage->
container(node.id)->best_min();
452 while(checks < node.max_check){
453 T_e last_value = main_storage->
container(node.id)->best_min();
455 if(last_value < value)
459 (*traverse_fn)(node.sub_procedure.front(), problem, main_storage);
465 if constexpr (std::is_base_of<dena::bcd_mask_node, T_n>::value){
466 if constexpr(T_block_dim == T_dim)
469 main_storage->update_partial_best();
470 main_storage->sync_partial_best();
471 spdlog::info(
"synchronizing BCD mask. best solution: {}", main_storage->partial_best->values[0]);
473 main_storage->str_storage[node.tag][0]->apply();
475 main_storage->str_storage[node.tag][1]->apply();
477 main_storage->reset();
480 if (main_storage->str_storage.find(node.tag) != main_storage->str_storage.end()){
481 for(
auto& str: main_storage->str_storage[node.tag]){
483 main_storage->update_partial_best();
495 template<
typename T_e,
int T_dim,
int T_block_dim=T_dim>
500 std::unique_ptr<blocked_system<T_e>> blocked_problem;
504 constexpr
bool blocked(){
505 return T_dim != T_block_dim;
510 return blocked_problem.get();
515 this->problem = problem;
516 storage.partial_best = std::make_unique<basic_scontainer<T_e, T_block_dim>>(1, 1);
517 storage.partial_best->allocate();
520 storage.bcd_mask.resize(T_block_dim);
521 std::iota(storage.bcd_mask.begin(), storage.bcd_mask.end(), 0);
522 this->blocked_problem = std::make_unique<blocked_system<T_e>>(problem, T_dim, T_block_dim, storage.bcd_mask.data());
524 spdlog::info(
"broadcasting BCD mask...");
525 sync_mask_str.apply();
527 storage.blocked_state = std::make_unique<basic_scontainer<T_e, T_dim>>(1, 1);
528 storage.blocked_state->allocate();
530 init_bcd_state.apply();
532 spdlog::info(
"broadcasting initial BCD solution state...");
534 sync_bcd_state_str.apply();
535 storage.th_blocked_states = tbb::enumerable_thread_specific<std::vector<T_e>>(storage.blocked_state->particles[0]);
536 this->blocked_problem->set_solution_state(&(storage.th_blocked_states));
542 this->traverse_allocate(fl);
543 spdlog::info(
"allocation finished");
544 spdlog::info(
"total runtime storage : {:.2f} MB", this->storage.container_space()/(1024.0*1024.0));
546 this->traverse_assign(fl);
547 spdlog::info(
"assignment finished");
549 this->traverse_run(fl);
558 auto it = fl.procedure.front();
560 std::stack<int> path;
566 while(!path.empty()){
570 auto current = dena::node::nodes()[it];
572 it = dena::node::next(it);
576 std::visit(alloc_visitor, current);
586 auto it = fl.procedure.front();
588 std::stack<int> path;
594 while(!path.empty()){
598 auto current = dena::node::nodes()[it];
600 it = dena::node::next(it);
604 std::visit(assign_visitor, current);
611 running_visitor<T_e, T_dim, T_block_dim, decltype(traverse_run_rec)> run_visitor {problem, storage, &traverse_run_rec};
613 auto node = dena::node::nodes()[root];
614 std::visit(run_visitor, node);
615 traverse_run_rec(dena::node::next(root), problem, storage);
625 this->traverse_run_rec(fl.procedure.front(), get_problem(), &storage);