RockyML  0.0.1
A High-Performance Scientific Computing Framework
flow.h
1 /*
2  Copyright (C) 2022 Amirabbas Asadi , All Rights Reserved
3  distributed under Apache-2.0 license
4 */
5 #ifndef ROCKY_ZAGROS_FLOW_GUARD
6 #define ROCKY_ZAGROS_FLOW_GUARD
7 
8 
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>
19 
20 
21 
22 namespace rocky{
23 namespace zagros{
24 
29 template<typename T_e, int T_dim, int T_block_dim>
31 public:
32  // allocated containers
33  std::vector<std::unique_ptr<basic_scontainer<T_e, T_block_dim>>> cnt_storage;
34  // allocated strategies
35  std::map<int, std::vector<std::unique_ptr<basic_strategy<T_e, T_block_dim>>>> str_storage;
36  // mapping the containers' id to their storage blocks
37  std::map<std::string, int> cnt_map;
38  // iteration counter for nodes who runs periodically
39  std::map<int, int> iter_counter;
40  // tracking the convergence of containers
41  std::map<int, std::deque<T_e>> conv_tracker;
42  // a mask representing active variables in blocked descent
43  std::vector<int> bcd_mask;
44  // state of blocked systems
45  std::unique_ptr<basic_scontainer<T_e, T_dim>> blocked_state;
46  tbb::enumerable_thread_specific<std::vector<T_e>> th_blocked_states;
47  // a temp buffer for broadcasting best partial solution
48  std::unique_ptr<basic_scontainer<T_e, T_block_dim>> partial_best;
49  // amount of allocated memory
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);
59  }
60  return allocated_mem;
61  }
67  bool container_exist(std::string id){
68  auto it = cnt_map.find(id);
69  return it != cnt_map.end();
70  }
78  if (id == std::string("__best__"))
79  return partial_best.get();
80 
81  if (!container_exist(id)){
82  spdlog::warn("container {} does not exist", id);
83  }
84  // find the target container
85  int target_cnt_ind = cnt_map[id];
86  return cnt_storage[target_cnt_ind].get();
87  }
88  void allocate_container(std::string id, int n_particles, int group_size){
89  // allocate a continer
90  auto cnt = std::make_unique<basic_scontainer<T_e, T_block_dim>>(n_particles, group_size);
91  cnt->allocate();
92  spdlog::info("container {} was allocated. size : {:.2f} MB", id, cnt->space()/(1024.0*1024.0));
93  cnt_storage.push_back(std::move(cnt));
94  // register the id in the storage
95  cnt_map[id] = cnt_storage.size()-1;
96  }
97  // find the best partial solution in the storage
98  void update_partial_best(){
99  std::pair<T_e, int> best;
100  int best_ci = -1;
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;
106  best_ci = ci;
107  }
108  }
109  if (best.first < partial_best->values[0]){
110  // copy the best solution to the container
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));
114 
115  // copy the corresponding min value
116  partial_best->values[0] = best.first;
117  }
118  }
119  // synchronize best partial solution
120  void sync_partial_best(){
121  // Assumption : update_partial_best has been called already
122  // This function must be called before regenerating BCD mask
123  sync_broadcast_best<T_e, T_block_dim> sync_best_partial_str(partial_best.get());
124  sync_best_partial_str.apply();
125  // replace the old partial solution in solution states
126  for(int i=0; i<T_block_dim; i++)
127  blocked_state->particles[0][bcd_mask[i]] = partial_best->particles[0][i];
128  // replace the old partial solution in thread-specific states
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];
132  }
133  // reset all solution containers
134  void reset(){
135  for(auto& cnt: cnt_storage)
136  cnt->reset_values();
137  for(auto& [tag, str_vec]: str_storage)
138  for(auto& str: str_vec)
139  str->reset();
140  }
141 };
142 
143 
144 
149 template<typename T_e, int T_dim, int T_block_dim>
151  // objective system
152  system<T_e>* problem;
153  // visitor will change main storage
155  // visitor may also change the path stack in the case of composable flows
156  std::stack<int>* path_stack;
157 
158  void operator()(dena::bcd_mask_node node){}
159  void operator()(dena::log_local_best_node node){}
160  void operator()(dena::log_comet_best_node node){}
161  void operator()(dena::comm_cluster_prop_best_node node){}
162  void operator()(dena::init_uniform_node node){}
163  void operator()(dena::init_normal_node node){}
164  void operator()(dena::run_n_times_node node){
165  path_stack->push(node.sub_procedure.front());
166  }
167  void operator()(dena::run_until_no_improve_node node){
168  main_storage->conv_tracker[node.tag] = std::deque<T_e>();
169  path_stack->push(node.sub_procedure.front());
170  }
171  void operator()(dena::run_every_n_steps_node node){
172  main_storage->iter_counter[node.tag] = 0;
173  path_stack->push(node.sub_procedure.front());
174  }
175  void operator()(dena::run_with_probability_node node){
176  path_stack->push(node.sub_procedure.front());
177  }
178  void operator()(dena::container_create_node node){
179  main_storage->allocate_container(node.id, node.n_particles, node.group_size);
180  }
181  void operator()(dena::container_select_from_node node){}
182  void operator()(dena::container_eval_node node){}
183  void operator()(dena::pso_memory_create_node node){
184  // allocate required solution containers for particle swarm
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();
189 
190  using namespace dena;
191  // particles velocity
192  main_storage->allocate_container(pso::memory::particles_vel(node.memory_id), n_particles, group_size);
193  // particles memory
194  main_storage->allocate_container(pso::memory::particles_mem(node.memory_id), n_particles, group_size);
195  // groups memory
196  main_storage->allocate_container(pso::memory::groups_mem(node.memory_id), n_groups, 1);
197  // node memory
198  main_storage->allocate_container(pso::memory::node_mem(node.memory_id), 1, 1);
199  // cluster memory
200  main_storage->allocate_container(pso::memory::cluster_mem(node.memory_id), 1, 1);
201  }
202  void operator()(dena::pso_group_level_step_node node){}
203  void operator()(dena::pso_cluster_level_step_node node){}
204  void operator()(dena::mutate_gaussian_node node){
205  // allocate required solution containers for particle swarm
206  auto main_cnt = main_storage->container(node.id);
207  int n_particles = main_cnt->n_particles();
208  main_storage->allocate_container(dena::utils::temp_name(node.tag), n_particles, n_particles);
209  }
210  void operator()(dena::crossover_multipoint_node node){
211  // allocate required solution container
212  auto main_cnt = main_storage->container(node.id);
213  int n_particles = main_cnt->n_particles();
214  main_storage->allocate_container(dena::utils::temp_name(node.tag), n_particles, n_particles);
215  }
216  void operator()(dena::crossover_differential_evolution_node node){
217  // allocate required solution container
218  auto main_cnt = main_storage->container(node.id);
219  int n_particles = main_cnt->n_particles();
220  main_storage->allocate_container(dena::utils::temp_name(node.tag), n_particles, n_particles);
221  }
222  void operator()(dena::eda_mvn_fullcov_node node){
223  // allocate required solution container
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");
230  }
231  main_storage->allocate_container(dena::utils::temp_name(node.tag), T_block_dim, T_block_dim);
232  }
233  void operator()(dena::crossover_segment_node node){
234  // allocate required solution container
235  auto main_cnt = main_storage->container(node.id);
236  int n_particles = main_cnt->n_particles();
237  main_storage->allocate_container(dena::utils::temp_name(node.tag), n_particles, n_particles);
238  }
239  void operator()(dena::plot_heatmap_node node){}
240  void operator()(dena::container_recorder_node node){}
241 };
246 template<typename T_e, int T_dim, int T_block_dim>
248  // objective system
249  system<T_e>* problem;
250  // visitor will change main storage
252  // visitor may also change the path stack in the case of composable flows
253  std::stack<int>* path_stack;
254 
255  void operator()(dena::bcd_mask_node node){
256  // reserve the mask generation strategy
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));
258  // add the strategy to the container
259  main_storage->str_storage[node.tag].push_back(std::move(gen_str));
260  // reserve the mask synchronization strategy
261  auto sync_str = std::make_unique<sync_bcd_mask<T_e, T_block_dim>>(main_storage->bcd_mask.data());
262  // add the strategy to the container
263  main_storage->str_storage[node.tag].push_back(std::move(sync_str));
264  }
265  void operator()(dena::log_local_best_node node){
266  basic_scontainer<T_e, T_block_dim>* target_cnt = nullptr;
267  if(node.id.size() == 0)
268  target_cnt = main_storage->partial_best.get();
269  else
270  target_cnt = main_storage->container(node.id);
271  // reserve the strategy
272  auto str = std::make_unique<local_log_best<T_e, T_block_dim>>(problem, target_cnt, node.handler);
273  // add the strategy to the container
274  main_storage->str_storage[node.tag].push_back(std::move(str));
275  }
276  void operator()(dena::log_comet_best_node node){
277  basic_scontainer<T_e, T_block_dim>* target_cnt = nullptr;
278  if(node.id.size() == 0)
279  target_cnt = main_storage->partial_best.get();
280  else
281  target_cnt = main_storage->container(node.id);
282  // reserve the strategy
283  auto str = std::make_unique<comet_log_best<T_e, T_block_dim>>(problem, target_cnt, node.handler);
284  // add the strategy to the container
285  main_storage->str_storage[node.tag].push_back(std::move(str));
286  }
287  void operator()(dena::comm_cluster_prop_best_node node){
288  // retrieve the target container
289  auto target_cnt = main_storage->container(node.id);
290  // create and configure the strategy
291  auto str = std::make_unique<sync_broadcast_best<T_e, T_block_dim>>(target_cnt);
292  // register the strategy
293  main_storage->str_storage[node.tag].push_back(std::move(str));
294  }
295  void operator()(dena::init_uniform_node node){
296  // get the target container
297  auto target_cnt = main_storage->container(node.id);
298  // reserve the strategy
299  auto str = std::make_unique<uniform_init_strategy<T_e, T_block_dim>>(problem, target_cnt);
300  // add the strategy to the container
301  main_storage->str_storage[node.tag].push_back(std::move(str));
302  }
303  void operator()(dena::init_normal_node node){}
304  void operator()(dena::run_n_times_node node){
305  path_stack->push(node.sub_procedure.front());
306  }
307  void operator()(dena::run_with_probability_node node){
308  path_stack->push(node.sub_procedure.front());
309  }
310  void operator()(dena::run_until_no_improve_node node){
311  path_stack->push(node.sub_procedure.front());
312  }
313  void operator()(dena::run_every_n_steps_node node){
314  path_stack->push(node.sub_procedure.front());
315  }
316  void operator()(dena::container_create_node node){}
317  void operator()(dena::container_select_from_node node){
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));
322  }
323  void operator()(dena::container_eval_node node){
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));
327  }
328  void operator()(dena::pso_memory_create_node node){}
329  void operator()(dena::pso_group_level_step_node node){
330  // get memory containers
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);
339  // add the strategy to the container
340  main_storage->str_storage[node.tag].push_back(std::move(str));
341  }
342  void operator()(dena::pso_cluster_level_step_node node){
343  // get memory containers
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);
352  // add the strategy to the container
353  main_storage->str_storage[node.tag].push_back(std::move(str));
354  }
355  void operator()(dena::mutate_gaussian_node node){
356  auto main_cnt = main_storage->container(node.id);
357  auto temp_cnt = main_storage->container(dena::utils::temp_name(node.tag));
358  auto str = std::make_unique<gaussian_mutation<T_e, T_block_dim>>(problem, main_cnt, temp_cnt, node.dims, node.mu, node.sigma);
359  // add the strategy to the container
360  main_storage->str_storage[node.tag].push_back(std::move(str));
361  }
362  void operator()(dena::crossover_multipoint_node node){
363  auto main_cnt = main_storage->container(node.id);
364  auto temp_cnt = main_storage->container(dena::utils::temp_name(node.tag));
365  auto str = std::make_unique<multipoint_crossover<T_e, T_block_dim>>(problem, main_cnt, temp_cnt, node.dims);
366  // add the strategy to the container
367  main_storage->str_storage[node.tag].push_back(std::move(str));
368  }
369  void operator()(dena::crossover_differential_evolution_node node){
370  auto main_cnt = main_storage->container(node.id);
371  auto temp_cnt = main_storage->container(dena::utils::temp_name(node.tag));
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);
373  // add the strategy to the container
374  main_storage->str_storage[node.tag].push_back(std::move(str));
375  }
376  void operator()(dena::eda_mvn_fullcov_node node){
377  auto main_cnt = main_storage->container(node.id);
378  auto temp_cnt = main_storage->container(dena::utils::temp_name(node.tag));
379  auto str = std::make_unique<eda_mutivariate_normal<T_e, T_block_dim>>(problem, main_cnt, temp_cnt, T_block_dim);
380  // add the strategy to the container
381  main_storage->str_storage[node.tag].push_back(std::move(str));
382  }
383  void operator()(dena::crossover_segment_node node){
384  auto main_cnt = main_storage->container(node.id);
385  auto temp_cnt = main_storage->container(dena::utils::temp_name(node.tag));
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!");
390  }
391  auto str = std::make_unique<static_segment_crossover<T_e, T_block_dim>>(problem, main_cnt, temp_cnt, segment_length);
392  // add the strategy to the container
393  main_storage->str_storage[node.tag].push_back(std::move(str));
394  }
395  void operator()(dena::plot_heatmap_node node){
396  if (T_block_dim != 2){
397  spdlog::warn("For using heatmap the block dimension should be 2.");
398  }
399  T_e x_min = problem->lower_bound(0);
400  T_e y_min = problem->lower_bound(1);
401  T_e x_max = problem->upper_bound(0);
402  T_e y_max = problem->upper_bound(1);
403 
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));
406  }
407  void operator()(dena::container_recorder_node node){
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));
411  }
412 };
413 
418 template<typename T_e, int T_dim, int T_block_dim, typename T_traverse_fn>
420  // objective system
421  system<T_e>* problem;
422  // visitor will change main storage
424  // visitor may also change the path stack in the case of composable flows
425  T_traverse_fn* traverse_fn;
426 
427  template<typename T_n>
428  void operator()(T_n node){
429  if constexpr (std::is_base_of<dena::run_node, T_n>::value){
430  // run n times
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);
434  }
435  }
436  // run with a probability
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);
441  }
442  }
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;
446  if(p == 0)
447  (*traverse_fn)(node.sub_procedure.front(), problem, main_storage);
448  }
449  if constexpr (std::is_base_of<dena::run_until_no_improve_node, T_n>::value){
450  int checks = 0;
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();
454  checks++;
455  if(last_value < value)
456  checks = 0;
457  value = last_value;
458  // run the sub-procedure
459  (*traverse_fn)(node.sub_procedure.front(), problem, main_storage);
460  }
461 
462  }
463  return;
464  }
465  if constexpr (std::is_base_of<dena::bcd_mask_node, T_n>::value){
466  if constexpr(T_block_dim == T_dim)
467  return;
468  // synchronize best values for the current state over the cluster
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]);
472  // generate a new mask
473  main_storage->str_storage[node.tag][0]->apply();
474  // synchronize the generated mask
475  main_storage->str_storage[node.tag][1]->apply();
476  // reset all solution containers
477  main_storage->reset();
478  return;
479  }
480  if (main_storage->str_storage.find(node.tag) != main_storage->str_storage.end()){
481  for(auto& str: main_storage->str_storage[node.tag]){
482  str->apply();
483  main_storage->update_partial_best();
484  }
485  }
486 
487 
488  }
489 };
490 
495 template<typename T_e, int T_dim, int T_block_dim=T_dim>
497 public:
498  // objective system
499  system<T_e>* problem;
500  std::unique_ptr<blocked_system<T_e>> blocked_problem;
502 
503  // check if the objective system is blocked
504  constexpr bool blocked(){
505  return T_dim != T_block_dim;
506  }
507  // get problem
508  system<T_e>* get_problem(){
509  if(blocked())
510  return blocked_problem.get();
511  else
512  return problem;
513  }
514  basic_runtime(system<T_e>* problem){
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();
518 
519  if (blocked()){
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());
523  sync_bcd_mask<T_e, T_block_dim> sync_mask_str(storage.bcd_mask.data());
524  spdlog::info("broadcasting BCD mask...");
525  sync_mask_str.apply();
526  // initialize and sync the bcd state
527  storage.blocked_state = std::make_unique<basic_scontainer<T_e, T_dim>>(1, 1);
528  storage.blocked_state->allocate();
529  uniform_init_strategy<T_e, T_dim> init_bcd_state(problem, storage.blocked_state.get());
530  init_bcd_state.apply();
531  // briadcast the initialized solution
532  spdlog::info("broadcasting initial BCD solution state...");
533  sync_broadcast_best<T_e, T_dim> sync_bcd_state_str(storage.blocked_state.get());
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));
537 
538  }
539  }
540  void run(const dena::flow& fl){
541  // allocate memory for running the flow
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));
545  // allocate and assign strategies
546  this->traverse_assign(fl);
547  spdlog::info("assignment finished");
548  // run the flow recursively
549  this->traverse_run(fl);
550  }
557  void traverse_allocate(const dena::flow& fl){
558  auto it = fl.procedure.front();
559  // storage for the traversed path
560  std::stack<int> path;
561  // visitor
562  allocation_visitor<T_e, T_dim, T_block_dim> alloc_visitor {get_problem(), &storage, &path};
563  // initialize the path
564  path.push(it);
565  // iterate until there is no node in the stack
566  while(!path.empty()){
567  it = path.top();
568  // remove the visited node
569  path.pop();
570  auto current = dena::node::nodes()[it];
571  // push the next node into the stack if it's not null
572  it = dena::node::next(it);
573  if(it > -1)
574  path.push(it);
575  // visit the node
576  std::visit(alloc_visitor, current);
577  }
578  }
585  void traverse_assign(const dena::flow& fl){
586  auto it = fl.procedure.front();
587  // storage for the traversed path
588  std::stack<int> path;
589  // visitor
590  assigning_visitor<T_e, T_dim, T_block_dim> assign_visitor {get_problem(), &storage, &path};
591  // initialize the path
592  path.push(it);
593  // iterate until there is no node in the stack
594  while(!path.empty()){
595  it = path.top();
596  // remove the visited node
597  path.pop();
598  auto current = dena::node::nodes()[it];
599  // push the next node into the stack if it's not null
600  it = dena::node::next(it);
601  if(it > -1)
602  path.push(it);
603  // visit the node
604  std::visit(assign_visitor, current);
605  }
606  }
607  static void traverse_run_rec(int root, system<T_e>* problem, runtime_storage<T_e, T_dim, T_block_dim>* storage){
608  if(root == -1)
609  return;
610  // visitor
611  running_visitor<T_e, T_dim, T_block_dim, decltype(traverse_run_rec)> run_visitor {problem, storage, &traverse_run_rec};
612  // iterate until there is no node left in the stack
613  auto node = dena::node::nodes()[root];
614  std::visit(run_visitor, node);
615  traverse_run_rec(dena::node::next(root), problem, storage);
616  }
623  void traverse_run(const dena::flow& fl){
624  // running the flow and sub-flows recursively
625  this->traverse_run_rec(fl.procedure.front(), get_problem(), &storage);
626  }
627 };
628 
629 
630 }; // end of zagros
631 }; // end of rocky
632 #endif
rocky::zagros::runtime_storage::container_exist
bool container_exist(std::string id)
check if a container exists in the memory
Definition: flow.h:67
rocky::zagros::dena::utils::temp_name
static std::string temp_name(int tag)
generate the name for temporal containers
Definition: dena.h:285
rocky::zagros::dena::container_create_node
Definition: dena.h:36
rocky::zagros::blocked_system
a virtual system to implement blocked coordinate descent
Definition: system.h:59
rocky::zagros::dena::init_uniform_node
Definition: dena.h:50
rocky::zagros::dena::plot_heatmap_node
Definition: dena.h:113
rocky::zagros::dena::init_normal_node
Definition: dena.h:53
rocky::zagros::uniform_init_strategy
Uniform initializer.
Definition: init.h:24
rocky::zagros::dena::flow
Definition: dena.h:197
rocky::zagros::assigning_visitor
Assigning visitor a visitor for linking allocated strategies to the suitable solution container.
Definition: flow.h:247
rocky::zagros::dena::crossover_differential_evolution_node
Definition: dena.h:95
rocky::zagros::dena::container_select_from_node
Definition: dena.h:41
rocky::zagros::runtime_storage
runtime storage
Definition: flow.h:30
rocky::zagros::sync_broadcast_best
A Communication strategy for broadcasting best solution.
Definition: communication.h:65
rocky::zagros::running_visitor
Running visitor a visitor for traversing and running the flow.
Definition: flow.h:419
rocky::zagros::dena::container_recorder_node
Definition: dena.h:118
rocky::zagros::dena::pso_cluster_level_step_node
Definition: dena.h:80
rocky::zagros::basic_runtime::traverse_allocate
void traverse_allocate(const dena::flow &fl)
allocate required memory for running the flow
Definition: flow.h:557
rocky::zagros::dena::comm_cluster_prop_best_node
Definition: dena.h:66
rocky::zagros::dena::bcd_mask_node
Definition: dena.h:125
rocky::zagros::dena::mutate_gaussian_node
Definition: dena.h:83
rocky::zagros::dena::container_eval_node
Definition: dena.h:45
rocky::zagros::dena::run_until_no_improve_node
Definition: dena.h:132
rocky::zagros::allocation_visitor
Allocation visitor a visitor for traversing the flow and allocating required memory.
Definition: flow.h:150
rocky::zagros::basic_scontainer
a data container representing a scontainer
Definition: scontainer.h:31
rocky::zagros::sync_bcd_mask
A Communication strategy for broadcasting bcd mask.
Definition: communication.h:108
rocky::zagros::system
Definition: system.h:20
rocky::zagros::dena::eda_mvn_fullcov_node
Definition: dena.h:107
rocky::zagros::dena::pso_memory_create_node
Definition: dena.h:71
rocky::zagros::dena::crossover_segment_node
Definition: dena.h:100
rocky::zagros::dena::run_every_n_steps_node
Definition: dena.h:142
rocky::zagros::system::upper_bound
virtual T_e upper_bound()
upper bound specification should be used when upper bound is same for all parameters
Definition: system.h:41
rocky::zagros::basic_runtime::traverse_assign
void traverse_assign(const dena::flow &fl)
allocating strategies and assigning them to nodes
Definition: flow.h:585
rocky::zagros::dena::run_with_probability_node
Definition: dena.h:136
rocky::zagros::system::lower_bound
virtual T_e lower_bound()
lower bound specification should be used when lower bound is same for all parameters
Definition: system.h:28
rocky::zagros::dena::log_local_best_node
Definition: dena.h:56
rocky::zagros::dena::run_n_times_node
Definition: dena.h:139
rocky::zagros::dena::crossover_multipoint_node
Definition: dena.h:91
rocky::zagros::runtime_storage::container
basic_scontainer< T_e, T_block_dim > * container(std::string id)
access to specific container
Definition: flow.h:77
rocky::zagros::dena::log_comet_best_node
Definition: dena.h:60
rocky::zagros::dena::pso_group_level_step_node
Definition: dena.h:79
rocky::zagros::basic_runtime
base class for all runtimes
Definition: flow.h:496
rocky::zagros::basic_runtime::traverse_run
void traverse_run(const dena::flow &fl)
unnning the flow
Definition: flow.h:623