QuIDS: Quantum Irregular Dynamic Simulator
qcgd.hpp
1
2#include <string>
3#include <ctime>
4#include <iostream>
5#include <iomanip> // std::setprecision
6
7#include "../quids.hpp"
8
9namespace quids::rules::qcgd {
10 namespace utils {
11 inline void hash_combine(std::size_t& seed, size_t const value_64) {
12 static size_t magic_number = 0xc6a4a7935bd1e995;
13 static auto shift = 47;
14
15 seed *= magic_number;
16 seed ^= value_64 >> shift;
17 seed *= magic_number;
18
19 seed ^= value_64;
20 seed *= magic_number;
21
22 // Completely arbitrary number, to prevent 0's
23 // from hashing to 0.
24 seed += 0xe6546b64;
25 }
26 }
27
28 namespace graphs {
29 enum {
30 dot_l_t = -3,
31 dot_r_t,
32 element_t,
33 pair_t
34 };
35 struct sub_node {
36 int16_t hmlz_and_element;
37 int16_t right_or_type;
38 size_t hash;
39
40 sub_node(int16_t element) : right_or_type(element_t), hash(element) {
41 hmlz_and_element = element == 0 ? -1 : element + 1;
42 }
43 sub_node(sub_node const &node, int16_t type) : right_or_type(type) {
44 if (type == dot_l_t && node.hmlz_and_element < 0) {
45 hmlz_and_element = -1;
46 } else
47 hmlz_and_element = 1;
48
49 hash = node.hash;
50 utils::hash_combine(hash, type);
51 }
52 sub_node(sub_node const &left, sub_node const &right, int16_t right_offset) : right_or_type(right_offset) {
53 if (left.hmlz_and_element < 0 || right.hmlz_and_element < 0) {
54 hmlz_and_element = -1;
55 } else
56 hmlz_and_element = 1;
57
58 hash = left.hash;
59 utils::hash_combine(hash, right.hash);
60 }
61 };
62
63 uint16_t inline &num_nodes(char *object_begin) {
64 return *((uint16_t*)object_begin);
65 }
66
67 uint16_t inline const num_nodes(char const *object_begin) {
68 return *((uint16_t*)object_begin);
69 }
70
71 uint16_t inline *node_name_begin(char *object_begin) {
72 uint16_t num_nodes_ = num_nodes(object_begin);
73 auto offset = sizeof(uint16_t) + 2*num_nodes_;
74 return (uint16_t*)(object_begin + offset);
75 }
76 uint16_t inline const *node_name_begin(char const *object_begin) {
77 uint16_t num_nodes_ = num_nodes(object_begin);
78 auto offset = sizeof(uint16_t) + 2*num_nodes_;
79 return (const uint16_t*)(object_begin + offset);
80 }
81 uint16_t inline &node_name_begin(char *object_begin, int node) { return node_name_begin(object_begin)[node]; }
82 uint16_t inline const node_name_begin(char const *object_begin, int node) { return node_name_begin(object_begin)[node]; }
83
84
85 sub_node inline *node_name(char *object_begin) {
86 uint16_t num_nodes_ = num_nodes(object_begin);
87 auto offset = 2*sizeof(uint16_t) + (2 + sizeof(uint16_t))*num_nodes_;
88 return (sub_node*)(object_begin + offset);
89 }
90 sub_node inline const *node_name(char const *object_begin) {
91 uint16_t num_nodes_ = num_nodes(object_begin);
92 auto offset = 2*sizeof(uint16_t) + (2 + sizeof(uint16_t))*num_nodes_;
93 return (const sub_node*)(object_begin + offset);
94 }
95 sub_node inline &node_name(char *object_begin, int node) { return node_name(object_begin)[node]; }
96 sub_node inline const node_name(char const *object_begin, int node) { return node_name(object_begin)[node]; }
97
98 bool inline *left(char *object_begin) { return (bool*)(object_begin + sizeof(uint16_t)); }
99 bool inline const *left(char const *object_begin) { return (const bool*)(object_begin + sizeof(uint16_t)); }
100 bool inline &left(char *object_begin, int node) { return left(object_begin)[node]; }
101 bool inline const left(char const *object_begin, int node) { return left(object_begin)[node]; }
102
103 bool inline *right(char *object_begin) {
104 uint16_t num_nodes_ = num_nodes(object_begin);
105 return (bool*)(object_begin + sizeof(uint16_t) + num_nodes_);
106 }
107 bool inline const *right(char const *object_begin) {
108 uint16_t num_nodes_ = num_nodes(object_begin);
109 return (const bool*)(object_begin + sizeof(uint16_t) + num_nodes_);
110 }
111 bool inline &right(char *object_begin, int node) { return right(object_begin)[node]; }
112 bool inline const right(char const *object_begin, int node) { return right(object_begin)[node]; }
113
114 void inline randomize(char *object_begin) {
115 uint16_t num_nodes_ = num_nodes(object_begin);
116 for (auto i = 0; i < num_nodes_; ++i) {
117 left(object_begin, i) = rand() & 1;
118 right(object_begin, i) = rand() & 1;
119 }
120 }
121
122 size_t inline hash_graph(char const *object_begin) {
123 size_t left_hash = 0;
124 size_t right_hash = 0;
125 size_t name_hash = 0;
126
127 bool const *left_ = left(object_begin);
128 bool const *right_ = right(object_begin);
129 auto const *node_begin = node_name_begin(object_begin);
130 auto const *node_name_ = node_name(object_begin);
131
132 uint16_t const num_nodes_ = num_nodes(object_begin);
133 for (auto i = 0; i < num_nodes_; ++i) {
134 if (left_[i])
135 utils::hash_combine(left_hash, i);
136
137 if (right_[i])
138 utils::hash_combine(right_hash, i);
139
140 utils::hash_combine(name_hash, node_name_[node_begin[i]].hash);
141 }
142
143 utils::hash_combine(name_hash, left_hash);
144 utils::hash_combine(name_hash, right_hash);
145 return name_hash;
146 }
147 }
148
149 namespace operations {
150 template<class T>
151 bool inline equal(T* begin_1, T* end_1, T* begin_2, T* end_2) {
152 size_t n_bit = std::distance(begin_1, end_1);
153 if (n_bit != std::distance(begin_2, end_2))
154 return false;
155
156 for (auto i = 0; i < n_bit; ++i)
157 if(begin_1[i] != begin_2[i])
158 return false;
159
160 return true;
161 }
162
163 template<class T>
164 T inline *copy(T const *parent_begin, T const *parent_end, T* child_begin) {
165 for (auto it = parent_begin; it != parent_end; ++it)
166 *(child_begin++) = *it;
167 return child_begin;
168 }
169
170 bool inline has_most_left_zero(graphs::sub_node *object_begin) {
171 return object_begin->hmlz_and_element < 0;
172 }
173
174 void inline get_operations(char const *parent_begin, uint16_t node, bool &split, bool &merge) {
175 merge = false;
176 split = graphs::left(parent_begin, node) && graphs::right(parent_begin, node);
177 if (!split && node + 1 < graphs::num_nodes(parent_begin))
178 merge = graphs::left(parent_begin, node) && graphs::right(parent_begin, node + 1) && !graphs::left(parent_begin, node + 1);
179 }
180
181 graphs::sub_node inline *merge(graphs::sub_node const *left_begin, graphs::sub_node const *left_end,
182 graphs::sub_node const *right_begin, graphs::sub_node const *right_end,
183 graphs::sub_node *child_begin) {
184
185 if (left_begin->right_or_type == graphs::dot_l_t && right_begin->right_or_type == graphs::dot_r_t)
186 if ((left_begin + 1)->hash == (right_begin + 1)->hash)
187 return copy(left_begin + 1, left_end, child_begin);
188
189 *(child_begin++) = graphs::sub_node(*left_begin, *right_begin, std::distance(left_begin, left_end) + 1);
190 child_begin = copy(left_begin, left_end, child_begin);
191 return copy(right_begin, right_end, child_begin);
192 }
193
194 graphs::sub_node inline *left(graphs::sub_node const *parent_begin, graphs::sub_node const *parent_end, graphs::sub_node *child_begin) {
195 if (parent_begin->right_or_type >= 0)
196 return copy(parent_begin + 1, parent_begin + parent_begin->right_or_type, child_begin);
197
198 *(child_begin++) = graphs::sub_node(*parent_begin, graphs::dot_l_t);
199 return copy(parent_begin, parent_end, child_begin);
200 }
201
202 graphs::sub_node inline *right(graphs::sub_node const *parent_begin, graphs::sub_node const *parent_end, graphs::sub_node *child_begin) {
203 if (parent_begin->right_or_type >= 0)
204 return copy(parent_begin + parent_begin->right_or_type, parent_end, child_begin);
205
206 *(child_begin++) = graphs::sub_node(*parent_begin, graphs::dot_r_t);
207 return copy(parent_begin, parent_end, child_begin);
208 }
209 }
210
211 namespace utils {
212 size_t max_print_num_graphs = -1;
213
214 void make_graph(char* &object_begin, char* &object_end, uint16_t size) {
215 static auto per_node_size = 2 + sizeof(uint16_t) + sizeof(graphs::sub_node);
216 auto object_size = 2*sizeof(uint16_t) + per_node_size*size;
217
218 object_begin = new char[object_size];
219 object_end = object_begin + object_size;
220
221 graphs::num_nodes(object_begin) = size;
222
223 graphs::node_name_begin(object_begin, 0) = 0;
224 for (auto i = 0; i < size; ++i) {
225 graphs::left(object_begin, i) = 0;
226 graphs::right(object_begin, i) = 0;
227 graphs::node_name_begin(object_begin, i + 1) = i + 1;
228 graphs::node_name(object_begin, i) = graphs::sub_node(i);
229 }
230 }
231
232 void randomize(quids::it_t &iter) {
233 uint size;
234 mag_t *mag_;
235 char *begin;
236 for (auto gid = 0; gid < iter.num_object; ++gid) {;
237 iter.get_object(gid, begin, size, mag_);
238 graphs::randomize(begin);
239 }
240 }
241
242 void print(quids::it_t const &iter) {
243 static std::function<void(graphs::sub_node const*)> print_node_name = [](graphs::sub_node const *sub_node) {
244 if (sub_node->right_or_type == graphs::element_t) {
245 std::cout << std::abs(sub_node->hmlz_and_element) - 1;
246
247 } else if (sub_node->right_or_type == graphs::dot_l_t) {
248 std::cout << "(";
249 print_node_name(sub_node + 1);
250 std::cout << ").l";
251
252 } else if (sub_node->right_or_type == graphs::dot_r_t) {
253 std::cout << "(";
254 print_node_name(sub_node + 1);
255 std::cout << ").r";
256
257 } else {
258 std::cout << "(";
259 print_node_name(sub_node + 1);
260 std::cout << ")∨(";
261 print_node_name(sub_node + sub_node->right_or_type);
262 std::cout << ")";
263 }
264 };
265
266 size_t *gids = new size_t[iter.num_object];
267 std::iota(gids, gids + iter.num_object, 0);
268 __gnu_parallel::sort(gids, gids + iter.num_object, [&](size_t gid1, size_t gid2) {
269 uint size_;
270 char const *begin_;
271
272 mag_t mag1, mag2;
273 iter.get_object(gid1, begin_, size_, mag1);
274 iter.get_object(gid2, begin_, size_, mag2);
275
276 return std::norm(mag1) > std::norm(mag2);
277 });
278
279 size_t num_prints = std::min(iter.num_object, max_print_num_graphs);
280 for (auto i = 0; i < num_prints; ++i) {
281 size_t gid = gids[i];
282
283 uint size;
284 mag_t mag;
285 char const *begin;
286 iter.get_object(gid, begin, size, mag);
287
288 uint16_t const num_nodes = graphs::num_nodes(begin);
289
290 PROBA_TYPE real = std::abs(mag.real()) < quids::tolerance ? 0 : mag.real();
291 PROBA_TYPE imag = std::abs(mag.imag()) < quids::tolerance ? 0 : mag.imag();
292
293 std::cout <<std::fixed<<std::setprecision(5)<< "\t" << real << (imag <= -1e-5 ? " - " : " + ") << std::abs(imag) << "i ";
294
295 for (auto i = 0; i < num_nodes; ++i) {
296 auto name_begin = graphs::node_name_begin(begin, i);
297
298 std::cout << "-|" << (graphs::left(begin, i) ? "<" : " ") << "|";
299 print_node_name(graphs::node_name(begin) + name_begin);
300 std::cout << "|" << (graphs::right(begin, i) ? ">" : " ") << "|-";
301 }
302 std::cout << "\n";
303 }
304
305 if (num_prints < iter.num_object)
306 std::cout << "\t...and " << iter.num_object - num_prints << " other graphs\n";
307 }
308
309 void serialize(quids::it_t const &iter, quids::sy_it_t const &sy_it, uint indentation=0) {
310 PROBA_TYPE interference_ratio = 1;
311 PROBA_TYPE deletion_ratio = 1;
312 if (sy_it.num_object > 0) {
313 interference_ratio = ((PROBA_TYPE)sy_it.num_object_after_interferences) / ((PROBA_TYPE)sy_it.num_object);
314 deletion_ratio = ((PROBA_TYPE)iter.num_object) / ((PROBA_TYPE)sy_it.num_object_after_interferences);
315 }
316
317 PROBA_TYPE avg_size = iter.average_value([](char const *object_begin, char const *object_end) {
318 return (PROBA_TYPE)graphs::num_nodes(object_begin);
319 });
320 PROBA_TYPE avg_squared_size = iter.average_value([](char const *object_begin, char const *object_end) {
321 PROBA_TYPE num_nodes = graphs::num_nodes(object_begin);
322 return num_nodes*num_nodes;
323 });
324 PROBA_TYPE avg_density = iter.average_value([](char const *object_begin, char const *object_end) {
325 PROBA_TYPE num_nodes = graphs::num_nodes(object_begin);
326
327 PROBA_TYPE density = 0;
328 for (auto i = 0; i < num_nodes; ++i)
329 density += graphs::left(object_begin, i) + graphs::right(object_begin, i);
330 density /= 2*num_nodes;
331
332 return density;
333 });
334 PROBA_TYPE avg_squared_density = iter.average_value([](char const *object_begin, char const *object_end) {
335 PROBA_TYPE num_nodes = graphs::num_nodes(object_begin);
336
337 PROBA_TYPE density = 0;
338 for (auto i = 0; i < num_nodes; ++i)
339 density += graphs::left(object_begin, i) + graphs::right(object_begin, i);
340 density /= 2*num_nodes;
341
342 return density*density;
343 });
344
345 PROBA_TYPE std_dev_size = avg_squared_size - avg_size*avg_size;
346 std_dev_size = std_dev_size < quids::tolerance ? 0 : std::sqrt(avg_squared_size);
347
348 PROBA_TYPE std_dev_density = avg_squared_density - avg_density*avg_density;
349 std_dev_density = std_dev_density < quids::tolerance ? 0 : std::sqrt(std_dev_density);
350
351 auto const print_indentation = [=]() {
352 for (auto i = 0; i < indentation; ++i)
353 std::cout << "\t";
354 };
355
356 std::cout << "{\n";
357 print_indentation(); std::cout << "\t\"total_proba\" : " << iter.total_proba << ",\n";
358 print_indentation(); std::cout << "\t\"num_graphs\" : " << iter.num_object << ",\n";
359 print_indentation(); std::cout << "\t\"avg_size\" : " << avg_size << ",\n";
360 print_indentation(); std::cout << "\t\"std_dev_size\" : " << std_dev_size << ",\n";
361 print_indentation(); std::cout << "\t\"avg_density\" : " << avg_density << ",\n";
362 print_indentation(); std::cout << "\t\"std_dev_density\" : " << std_dev_density << ",\n";
363 print_indentation(); std::cout << "\t\"interference_ratio\" : " << interference_ratio << ",\n";
364 print_indentation(); std::cout << "\t\"deletion_ratio\" : " << deletion_ratio << "\n";
365 print_indentation(); std::cout << "}";
366 }
367
368#ifdef MPI_VERSION
369 void serialize(quids::mpi::mpi_it_t const &iter, quids::mpi::mpi_sy_it_t const &sy_it, MPI_Comm communicator, uint indentation=0) {
370 int rank;
371 MPI_Comm_rank(communicator, &rank);
372
373 size_t total_num_object = iter.get_total_num_object(communicator);
374
375 PROBA_TYPE interference_ratio = 1;
376 PROBA_TYPE deletion_ratio = 1;
377
378 PROBA_TYPE total_num_object_after_interferences = sy_it.get_total_num_object_after_interferences(communicator);
379
380 if (total_num_object_after_interferences >= 0) {
381 interference_ratio = total_num_object_after_interferences / (PROBA_TYPE)sy_it.get_total_num_object(communicator);
382 deletion_ratio = (PROBA_TYPE)total_num_object / total_num_object_after_interferences;
383 }
384
385 PROBA_TYPE avg_size = iter.average_value([](char const *object_begin, char const *object_end) {
386 return (PROBA_TYPE)graphs::num_nodes(object_begin);
387 }, communicator);
388
389 PROBA_TYPE avg_squared_size = iter.average_value([](char const *object_begin, char const *object_end) {
390 PROBA_TYPE num_nodes = graphs::num_nodes(object_begin);
391 return num_nodes*num_nodes;
392 }, communicator);
393
394 PROBA_TYPE avg_density = iter.average_value([](char const *object_begin, char const *object_end) {
395 PROBA_TYPE num_nodes = graphs::num_nodes(object_begin);
396
397 PROBA_TYPE density = 0;
398 for (auto i = 0; i < num_nodes; ++i)
399 density += graphs::left(object_begin, i) + graphs::right(object_begin, i);
400 density /= 2*num_nodes;
401
402 return density;
403 }, communicator);
404
405 PROBA_TYPE avg_squared_density = iter.average_value([](char const *object_begin, char const *object_end) {
406 PROBA_TYPE num_nodes = graphs::num_nodes(object_begin);
407
408 PROBA_TYPE density = 0;
409 for (auto i = 0; i < num_nodes; ++i)
410 density += graphs::left(object_begin, i) + graphs::right(object_begin, i);
411 density /= 2*num_nodes;
412
413 return density*density;
414 }, communicator);
415
416 PROBA_TYPE std_dev_size = avg_squared_size - avg_size*avg_size;
417 std_dev_size = std_dev_size < quids::tolerance ? 0 : std::sqrt(avg_squared_size);
418
419 PROBA_TYPE std_dev_density = avg_squared_density - avg_density*avg_density;
420 std_dev_density = std_dev_density < quids::tolerance ? 0 : std::sqrt(std_dev_density);
421
422 auto const print_indentation = [=]() {
423 for (auto i = 0; i < indentation; ++i)
424 std::cout << "\t";
425 };
426
427 if (rank == 0) {
428 std::cout << "{\n";
429 print_indentation(); std::cout << "\t\"total_proba\" : " << iter.total_proba << ",\n";
430 print_indentation(); std::cout << "\t\"num_graphs\" : " << total_num_object << ",\n";
431 print_indentation(); std::cout << "\t\"avg_size\" : " << avg_size << ",\n";
432 print_indentation(); std::cout << "\t\"std_dev_size\" : " << std_dev_size << ",\n";
433 print_indentation(); std::cout << "\t\"avg_density\" : " << avg_density << ",\n";
434 print_indentation(); std::cout << "\t\"std_dev_density\" : " << std_dev_density << ",\n";
435 print_indentation(); std::cout << "\t\"interference_ratio\" : " << interference_ratio << ",\n";
436 print_indentation(); std::cout << "\t\"deletion_ratio\" : " << deletion_ratio << "\n";
437 print_indentation(); std::cout << "}";
438 }
439 }
440#endif
441 }
442
443 void step(char *parent_begin, char *parent_end, mag_t &mag) {
444 uint16_t num_nodes = graphs::num_nodes(parent_begin);
445 auto left_ = graphs::left(parent_begin);
446 auto right_ = graphs::right(parent_begin);
447 std::rotate(left_, left_ + 1, left_ + num_nodes);
448 std::rotate(right_, right_ + num_nodes - 1, right_ + num_nodes);
449 }
450
451 void reversed_step(char *parent_begin, char *parent_end, mag_t &mag) {
452 uint16_t num_nodes = graphs::num_nodes(parent_begin);
453 auto left_ = graphs::left(parent_begin);
454 auto right_ = graphs::right(parent_begin);
455 std::rotate(right_, right_ + 1, right_ + num_nodes);
456 std::rotate(left_, left_ + num_nodes - 1, left_ + num_nodes);
457 }
458
459 class erase_create : public quids::rule {
460 mag_t do_ = 1;
461 mag_t do_not = 0;
462 mag_t do_conj = 1;
463 mag_t do_not_conj = 0;
464
465 public:
466 erase_create(PROBA_TYPE theta, PROBA_TYPE phi = 0, PROBA_TYPE xi = 0) {
467 do_ = std::polar(std::sin(theta), phi);
468 do_not = std::polar(std::cos(theta), xi);
469 do_conj = std::conj(do_);
470 do_not_conj = std::conj(do_not);
471 }
472 inline size_t hasher(char const *parent_begin, char const *parent_end) const override {
473 return graphs::hash_graph(parent_begin);
474 }
475 inline void get_num_child(char const *parent_begin, char const *parent_end, uint &num_child, uint &max_child_size) const override {
476 max_child_size = std::distance(parent_begin, parent_end);
477
478 uint16_t num_nodes = graphs::num_nodes(parent_begin);
479
480 num_child = 1;
481 for (int i = 0; i < num_nodes; ++i) {
482 bool Xor = graphs::left(parent_begin, i) ^ graphs::right(parent_begin, i);
483 if (Xor == 0)
484 num_child *= 2;
485 }
486 }
487 inline void populate_child(char const *parent_begin, char const *parent_end, char* const child_begin, uint const child_id_, uint &size, mag_t &mag) const override {
488 operations::copy(parent_begin, parent_end, child_begin);
489 size = std::distance(parent_begin, parent_end);
490
491 uint child_id = child_id_;
492
493 uint16_t num_nodes = graphs::num_nodes(parent_begin);
494 for (int i = 0; i < num_nodes; ++i) {
495 bool &left = graphs::left(child_begin, i);
496 bool &right = graphs::right(child_begin, i);
497
498 uint8_t sum = left + right;
499 if ((sum & 1) == 0) {
500 bool conj = sum / 2;
501 if (child_id & 1) {
502 mag *= conj ? do_conj : do_;
503 left = !left;
504 right = !right;
505 } else
506 mag *= conj ? -do_not_conj : do_not;
507 child_id >>= 1;
508 }
509 }
510 }
511 inline void populate_child_simple(char const *parent_begin, char const *parent_end, char* const child_begin, uint const child_id_) const override {
512 operations::copy(parent_begin, parent_end, child_begin);
513
514 uint child_id = child_id_;
515
516 uint16_t num_nodes = graphs::num_nodes(parent_begin);
517 for (int i = 0; i < num_nodes; ++i) {
518 bool &left = graphs::left(child_begin, i);
519 bool &right = graphs::right(child_begin, i);
520
521 uint8_t sum = left + right;
522 if ((sum & 1) == 0) {
523 bool conj = sum / 2;
524 if (child_id & 1) {
525 left = !left;
526 right = !right;
527 }
528 child_id >>= 1;
529 }
530 }
531 }
532 };
533
534 class coin : public quids::rule {
535 mag_t do_ = 1;
536 mag_t do_not = 0;
537 mag_t do_conj = 1;
538 mag_t do_not_conj = 0;
539
540 public:
541 coin(PROBA_TYPE theta, PROBA_TYPE phi = 0, PROBA_TYPE xi = 0) {
542 do_ = std::polar(std::sin(theta), phi);
543 do_not = std::polar(std::cos(theta), xi);
544 do_conj = std::conj(do_);
545 do_not_conj = std::conj(do_not);
546 }
547 inline size_t hasher(char const *parent_begin, char const *parent_end) const override {
548 return graphs::hash_graph(parent_begin);
549 }
550 inline void get_num_child(char const *parent_begin, char const *parent_end, uint &num_child, uint &max_child_size) const override {
551 max_child_size = std::distance(parent_begin, parent_end);
552
553 uint16_t num_nodes = graphs::num_nodes(parent_begin);
554
555 num_child = 1;
556 for (int i = 0; i < num_nodes; ++i) {
557 bool Xor = graphs::left(parent_begin, i) ^ graphs::right(parent_begin, i);
558 if (Xor /* == 1 */)
559 num_child *= 2;
560 }
561 }
562 inline void populate_child(char const *parent_begin, char const *parent_end, char* const child_begin, uint const child_id_, uint &size, mag_t &mag) const override {
563 operations::copy(parent_begin, parent_end, child_begin);
564 size = std::distance(parent_begin, parent_end);
565
566 uint child_id = child_id_;
567
568 uint16_t num_nodes = graphs::num_nodes(parent_begin);
569 for (int i = 0; i < num_nodes; ++i) {
570 bool &left = graphs::left(child_begin, i);
571 bool &right = graphs::right(child_begin, i);
572
573 if (left ^ right /* == 1 */) {
574 bool conj = left;
575 if (child_id & 1) {
576 mag *= conj ? do_conj : do_;
577 left = !left;
578 right = !right;
579 } else
580 mag *= conj ? -do_not_conj : do_not;
581 child_id >>= 1;
582 }
583 }
584 }
585 inline void populate_child_simple(char const *parent_begin, char const *parent_end, char* const child_begin, uint const child_id_) const override {
586 operations::copy(parent_begin, parent_end, child_begin);
587
588 uint child_id = child_id_;
589
590 uint16_t num_nodes = graphs::num_nodes(parent_begin);
591 for (int i = 0; i < num_nodes; ++i) {
592 bool &left = graphs::left(child_begin, i);
593 bool &right = graphs::right(child_begin, i);
594
595 if (left ^ right /* == 1 */) {
596 bool conj = left;
597 if (child_id & 1) {
598 left = !left;
599 right = !right;
600 }
601 child_id >>= 1;
602 }
603 }
604 }
605 };
606
607 class split_merge : public quids::rule {
608 mag_t do_ = 1;
609 mag_t do_not = 0;
610 mag_t do_conj = 1;
611 mag_t do_not_conj = 0;
612
613 public:
614 split_merge(PROBA_TYPE theta, PROBA_TYPE phi = 0, PROBA_TYPE xi = 0) {
615 do_ = std::polar(std::sin(theta), phi);
616 do_not = std::polar(std::cos(theta), xi);
617 do_conj = std::conj(do_);
618 do_not_conj = std::conj(do_not);
619 }
620 inline size_t hasher(char const *parent_begin, char const *parent_end) const override {
621 return graphs::hash_graph(parent_begin);
622 }
623 inline void get_num_child(char const *parent_begin, char const *parent_end, uint &num_child, uint &max_child_size) const override {
624 max_child_size = 4*std::distance(parent_begin, parent_end);
625
626 uint16_t num_nodes = graphs::num_nodes(parent_begin);
627
628 bool last_merge = false;
629 bool first_split = graphs::left(parent_begin, 0) && graphs::right(parent_begin, 0);
630 if (!first_split && num_nodes > 1)
631 last_merge = graphs::right(parent_begin, 0) && graphs::left(parent_begin, num_nodes - 1) && !graphs::right(parent_begin, num_nodes - 1);
632
633 num_child = first_split || last_merge ? 2 : 1;
634
635 for (int i = first_split; i < num_nodes - last_merge; ++i) {
636 /* get opeartions */
637 bool split, merge;
638 operations::get_operations(parent_begin, i, split, merge);
639 if (split || merge)
640 num_child *= 2;
641 }
642 }
643 inline void populate_child(char const *parent_begin, char const *parent_end, char* const child_begin, uint const child_id_, uint &size, mag_t &mag) const override {
644 uint child_id = child_id_;
645 uint16_t num_nodes = graphs::num_nodes(parent_begin);
646
647 /* check for first split or last merge */
648 bool last_merge = false;
649 bool first_split = graphs::left(parent_begin, 0) && graphs::right(parent_begin, 0);
650 if (!first_split && num_nodes > 1)
651 last_merge = graphs::right(parent_begin, 0) && graphs::left(parent_begin, num_nodes - 1) && !graphs::right(parent_begin, num_nodes - 1);
652 bool first_split_overflow = false;
653
654 /* proba for first split or last merge */
655 first_split &= child_id; //forget last split if it shouldn't happend
656 if (first_split) {
657 mag *= do_;
658 child_id >>= 1;
659 }
660 if (last_merge) {
661 if (child_id & 1) {
662 mag *= do_conj;
663 } else {
664 last_merge = false;
665 mag *= -do_not_conj;
666 }
667 child_id >>= 1;
668 }
669
670 uint16_t &child_num_nodes = graphs::num_nodes(child_begin);
671 child_num_nodes = num_nodes + first_split - last_merge;
672
673 /* first path to get the final size */
674 uint child_id_copy = child_id;
675 for (int i = first_split + last_merge; i < num_nodes - last_merge; ++i) {
676 /* get opeartions */
677 bool split, merge;
678 operations::get_operations(parent_begin, i, split, merge);
679
680 /* check if the operation needs to be done */
681 if (merge || split) {
682 if (child_id_copy & 1) {
683 /* increment num nodes */
684 child_num_nodes += split - merge;
685
686 /* get proba */
687 if (split) {
688 mag *= do_;
689 } else
690 mag *= do_conj;
691 } else
692 /* get proba */
693 if (split) {
694 mag *= do_not;
695 } else
696 mag *= -do_not_conj;
697
698 child_id_copy >>= 1;
699 }
700 }
701
702 /* util variable */
703 auto parent_node_name_begin = graphs::node_name(parent_begin);
704 auto child_node_name_begin = graphs::node_name(child_begin);
705 graphs::node_name_begin(child_begin, 0) = 0;
706
707 /* do first split */
708 if (first_split) {
709 bool has_most_left_zero = true;
710 if (parent_node_name_begin->right_or_type >= 0)
711 if ((parent_node_name_begin + 1)->hmlz_and_element > 0)
712 has_most_left_zero = false;
713
714 if (has_most_left_zero) {
715 /* set particules position */
716 graphs::left(child_begin, 0) = true;
717 graphs::right(child_begin, 0) = false;
718 graphs::left(child_begin, 1) = false;
719 graphs::right(child_begin, 1) = true;
720
721 /* split first node */
722 auto node_name_end = operations::left(parent_node_name_begin,
723 parent_node_name_begin + graphs::node_name_begin(parent_begin, 1),
724 child_node_name_begin);
725
726 graphs::node_name_begin(child_begin, 1) = std::distance(child_node_name_begin, node_name_end);
727
728 node_name_end = operations::right(parent_node_name_begin,
729 parent_node_name_begin + graphs::node_name_begin(parent_begin, 1),
730 node_name_end);
731
732 graphs::node_name_begin(child_begin, 2) = std::distance(child_node_name_begin, node_name_end);
733 } else {
734 first_split_overflow = true;
735
736 /* set particules position */
737 graphs::left(child_begin, child_num_nodes - 1) = true;
738 graphs::right(child_begin, child_num_nodes - 1) = false;
739 graphs::left(child_begin, 0) = false;
740 graphs::right(child_begin, 0) = true;
741
742 /* split first node */
743 auto node_name_end = operations::right(parent_node_name_begin,
744 parent_node_name_begin + graphs::node_name_begin(parent_begin, 1),
745 child_node_name_begin);
746
747 graphs::node_name_begin(child_begin, 1) = std::distance(child_node_name_begin, node_name_end);
748 }
749 }
750
751 /* do last merge */
752 if (last_merge) {
753 graphs::left(child_begin, 0) = true;
754 graphs::right(child_begin, 0) = true;
755
756 /* merge nodes */
757 auto node_name_end = operations::merge(parent_node_name_begin + graphs::node_name_begin(parent_begin, num_nodes - 1),
758 parent_node_name_begin + graphs::node_name_begin(parent_begin, num_nodes),
759 parent_node_name_begin,
760 parent_node_name_begin + graphs::node_name_begin(parent_begin, 1),
761 child_node_name_begin);
762
763 graphs::node_name_begin(child_begin, 1) = std::distance(child_node_name_begin, node_name_end);
764 }
765
766 /* split merge every other node */
767 int offset = first_split - first_split_overflow;
768 for (int i = first_split + last_merge; i < num_nodes - last_merge; ++i) {
769
770 /* get opeartions */
771 bool split, merge;
772 operations::get_operations(parent_begin, i, split, merge);
773
774 /* check if the operation needs to be done */
775 bool Do = false;
776 if (merge || split) {
777 Do = child_id & 1;
778 if (Do) {
779 if (split) {
780 /* set particule position */
781 graphs::left(child_begin, i + offset) = true;
782 graphs::right(child_begin, i + offset) = false;
783 graphs::left(child_begin, i + offset + 1) = false;
784 graphs::right(child_begin, i + offset + 1) = true;
785
786 /* split left node */
787 auto node_name_end = operations::left(parent_node_name_begin + graphs::node_name_begin(parent_begin, i),
788 parent_node_name_begin + graphs::node_name_begin(parent_begin, i + 1),
789 child_node_name_begin + graphs::node_name_begin(child_begin, i + offset));
790
791 graphs::node_name_begin(child_begin, i + 1 + offset) = std::distance(child_node_name_begin, node_name_end);
792
793 /* split right node */
794 node_name_end = operations::right(parent_node_name_begin + graphs::node_name_begin(parent_begin, i),
795 parent_node_name_begin + graphs::node_name_begin(parent_begin, i + 1),
796 child_node_name_begin + graphs::node_name_begin(child_begin, i + offset + 1));
797
798 graphs::node_name_begin(child_begin, i + 1 + offset + 1) = std::distance(child_node_name_begin, node_name_end);
799 } else {
800 /* set particule position */
801 graphs::left(child_begin, i + offset) = true;
802 graphs::right(child_begin, i + offset) = true;
803
804 /* merge nodes */
805 auto node_name_end = operations::merge(parent_node_name_begin + graphs::node_name_begin(parent_begin, i),
806 parent_node_name_begin + graphs::node_name_begin(parent_begin, i + 1),
807 parent_node_name_begin + graphs::node_name_begin(parent_begin, i + 1),
808 parent_node_name_begin + graphs::node_name_begin(parent_begin, i + 2),
809 child_node_name_begin + graphs::node_name_begin(child_begin, i + offset));
810
811 graphs::node_name_begin(child_begin, i + 1 + offset) = std::distance(child_node_name_begin, node_name_end);
812 }
813
814 /* increment num nodes */
815 offset += split - merge;
816 i += merge;
817 }
818
819 /* roll child id */
820 child_id >>= 1;
821 }
822
823 if (!Do) {
824 /* set particule position */
825 graphs::left(child_begin, i + offset) = graphs::left(parent_begin, i);
826 graphs::right(child_begin, i + offset) = graphs::right(parent_begin, i);
827
828 /* copy node */
829 auto node_name_end = operations::copy(parent_node_name_begin + graphs::node_name_begin(parent_begin, i),
830 parent_node_name_begin + graphs::node_name_begin(parent_begin, i + 1),
831 child_node_name_begin + graphs::node_name_begin(child_begin, i + offset));
832
833 graphs::node_name_begin(child_begin, i + 1 + offset) = std::distance(child_node_name_begin, node_name_end);
834 }
835 }
836
837 /* finish first split */
838 if (first_split_overflow) {
839 /* split first node */
840 auto node_name_end = operations::left(parent_node_name_begin,
841 parent_node_name_begin + graphs::node_name_begin(parent_begin, 1),
842 child_node_name_begin + graphs::node_name_begin(child_begin, child_num_nodes - 1));
843
844 graphs::node_name_begin(child_begin, child_num_nodes) = std::distance(child_node_name_begin, node_name_end);
845 }
846
847 size = std::distance(child_begin, (char*)(child_node_name_begin + graphs::node_name_begin(child_begin, child_num_nodes)));
848 }
849
850 inline void populate_child_simple(char const *parent_begin, char const *parent_end, char* const child_begin, uint const child_id_) const override {
851 uint child_id = child_id_;
852 uint16_t num_nodes = graphs::num_nodes(parent_begin);
853
854 /* check for first split or last merge */
855 bool last_merge = false;
856 bool first_split = graphs::left(parent_begin, 0) && graphs::right(parent_begin, 0);
857 if (!first_split && num_nodes > 1)
858 last_merge = graphs::right(parent_begin, 0) && graphs::left(parent_begin, num_nodes - 1) && !graphs::right(parent_begin, num_nodes - 1);
859 bool first_split_overflow = false;
860
861 /* proba for first split or last merge */
862 first_split &= child_id; //forget last split if it shouldn't happend
863 if (first_split)
864 child_id >>= 1;
865 if (last_merge) {
866 if (!(child_id & 1))
867 last_merge = false;
868 child_id >>= 1;
869 }
870
871 uint16_t &child_num_nodes = graphs::num_nodes(child_begin);
872 child_num_nodes = num_nodes + first_split - last_merge;
873
874 /* first path to get the final size */
875 uint child_id_copy = child_id;
876 for (int i = first_split + last_merge; i < num_nodes - last_merge; ++i) {
877 /* get opeartions */
878 bool split, merge;
879 operations::get_operations(parent_begin, i, split, merge);
880
881 /* check if the operation needs to be done */
882 if (merge || split) {
883 if (child_id_copy & 1)
884 /* increment num nodes */
885 child_num_nodes += split - merge;
886
887 child_id_copy >>= 1;
888 }
889 }
890
891 /* util variable */
892 auto parent_node_name_begin = graphs::node_name(parent_begin);
893 auto child_node_name_begin = graphs::node_name(child_begin);
894 graphs::node_name_begin(child_begin, 0) = 0;
895
896 /* do first split */
897 if (first_split) {
898 bool has_most_left_zero = true;
899 if (parent_node_name_begin->right_or_type >= 0)
900 if ((parent_node_name_begin + 1)->hmlz_and_element > 0)
901 has_most_left_zero = false;
902
903 if (has_most_left_zero) {
904 /* set particules position */
905 graphs::left(child_begin, 0) = true;
906 graphs::right(child_begin, 0) = false;
907 graphs::left(child_begin, 1) = false;
908 graphs::right(child_begin, 1) = true;
909
910 /* split first node */
911 auto node_name_end = operations::left(parent_node_name_begin,
912 parent_node_name_begin + graphs::node_name_begin(parent_begin, 1),
913 child_node_name_begin);
914
915 graphs::node_name_begin(child_begin, 1) = std::distance(child_node_name_begin, node_name_end);
916
917 node_name_end = operations::right(parent_node_name_begin,
918 parent_node_name_begin + graphs::node_name_begin(parent_begin, 1),
919 node_name_end);
920
921 graphs::node_name_begin(child_begin, 2) = std::distance(child_node_name_begin, node_name_end);
922 } else {
923 first_split_overflow = true;
924
925 /* set particules position */
926 graphs::left(child_begin, child_num_nodes - 1) = true;
927 graphs::right(child_begin, child_num_nodes - 1) = false;
928 graphs::left(child_begin, 0) = false;
929 graphs::right(child_begin, 0) = true;
930
931 /* split first node */
932 auto node_name_end = operations::right(parent_node_name_begin,
933 parent_node_name_begin + graphs::node_name_begin(parent_begin, 1),
934 child_node_name_begin);
935
936 graphs::node_name_begin(child_begin, 1) = std::distance(child_node_name_begin, node_name_end);
937 }
938 }
939
940 /* do last merge */
941 if (last_merge) {
942 graphs::left(child_begin, 0) = true;
943 graphs::right(child_begin, 0) = true;
944
945 /* merge nodes */
946 auto node_name_end = operations::merge(parent_node_name_begin + graphs::node_name_begin(parent_begin, num_nodes - 1),
947 parent_node_name_begin + graphs::node_name_begin(parent_begin, num_nodes),
948 parent_node_name_begin,
949 parent_node_name_begin + graphs::node_name_begin(parent_begin, 1),
950 child_node_name_begin);
951
952 graphs::node_name_begin(child_begin, 1) = std::distance(child_node_name_begin, node_name_end);
953 }
954
955 /* split merge every other node */
956 int offset = first_split - first_split_overflow;
957 for (int i = first_split + last_merge; i < num_nodes - last_merge; ++i) {
958
959 /* get opeartions */
960 bool split, merge;
961 operations::get_operations(parent_begin, i, split, merge);
962
963 /* check if the operation needs to be done */
964 bool Do = false;
965 if (merge || split) {
966 Do = child_id & 1;
967 if (Do) {
968 if (split) {
969 /* set particule position */
970 graphs::left(child_begin, i + offset) = true;
971 graphs::right(child_begin, i + offset) = false;
972 graphs::left(child_begin, i + offset + 1) = false;
973 graphs::right(child_begin, i + offset + 1) = true;
974
975 /* split left node */
976 auto node_name_end = operations::left(parent_node_name_begin + graphs::node_name_begin(parent_begin, i),
977 parent_node_name_begin + graphs::node_name_begin(parent_begin, i + 1),
978 child_node_name_begin + graphs::node_name_begin(child_begin, i + offset));
979
980 graphs::node_name_begin(child_begin, i + 1 + offset) = std::distance(child_node_name_begin, node_name_end);
981
982 /* split right node */
983 node_name_end = operations::right(parent_node_name_begin + graphs::node_name_begin(parent_begin, i),
984 parent_node_name_begin + graphs::node_name_begin(parent_begin, i + 1),
985 child_node_name_begin + graphs::node_name_begin(child_begin, i + offset + 1));
986
987 graphs::node_name_begin(child_begin, i + 1 + offset + 1) = std::distance(child_node_name_begin, node_name_end);
988 } else {
989 /* set particule position */
990 graphs::left(child_begin, i + offset) = true;
991 graphs::right(child_begin, i + offset) = true;
992
993 /* merge nodes */
994 auto node_name_end = operations::merge(parent_node_name_begin + graphs::node_name_begin(parent_begin, i),
995 parent_node_name_begin + graphs::node_name_begin(parent_begin, i + 1),
996 parent_node_name_begin + graphs::node_name_begin(parent_begin, i + 1),
997 parent_node_name_begin + graphs::node_name_begin(parent_begin, i + 2),
998 child_node_name_begin + graphs::node_name_begin(child_begin, i + offset));
999
1000 graphs::node_name_begin(child_begin, i + 1 + offset) = std::distance(child_node_name_begin, node_name_end);
1001 }
1002
1003 /* increment num nodes */
1004 offset += split - merge;
1005 i += merge;
1006 }
1007
1008 /* roll child id */
1009 child_id >>= 1;
1010 }
1011
1012 if (!Do) {
1013 /* set particule position */
1014 graphs::left(child_begin, i + offset) = graphs::left(parent_begin, i);
1015 graphs::right(child_begin, i + offset) = graphs::right(parent_begin, i);
1016
1017 /* copy node */
1018 auto node_name_end = operations::copy(parent_node_name_begin + graphs::node_name_begin(parent_begin, i),
1019 parent_node_name_begin + graphs::node_name_begin(parent_begin, i + 1),
1020 child_node_name_begin + graphs::node_name_begin(child_begin, i + offset));
1021
1022 graphs::node_name_begin(child_begin, i + 1 + offset) = std::distance(child_node_name_begin, node_name_end);
1023 }
1024 }
1025
1026 /* finish first split */
1027 if (first_split_overflow) {
1028 /* split first node */
1029 auto node_name_end = operations::left(parent_node_name_begin,
1030 parent_node_name_begin + graphs::node_name_begin(parent_begin, 1),
1031 child_node_name_begin + graphs::node_name_begin(child_begin, child_num_nodes - 1));
1032
1033 graphs::node_name_begin(child_begin, child_num_nodes) = std::distance(child_node_name_begin, node_name_end);
1034 }
1035 }
1036 };
1037
1038 namespace flags {
1039 typedef std::vector<std::tuple<int, bool, quids::modifier_t, quids::rule_t*, quids::modifier_t, quids::rule_t*>> simulator_t;
1040
1041 namespace {
1042 std::string strip(std::string &input, std::string const separator) {
1043 std::string result;
1044
1045 size_t end = input.find(separator);
1046
1047 if (end == std::string::npos) {
1048 result = input;
1049 input = "";
1050 } else {
1051 result = input.substr(0, end);
1052 input.erase(0, end + separator.length());
1053 }
1054
1055 return result;
1056 }
1057
1058 std::string parse(std::string const input, std::string const key, std::string const separator) {
1059 size_t begin = input.find(key);
1060 if (begin == std::string::npos)
1061 return "";
1062
1063 size_t end = input.find(separator);
1064 end = end == std::string::npos ? input.size() : end;
1065
1066 return input.substr(begin + key.length(), end - begin);
1067 }
1068
1069 int parse_int_with_default(std::string const input, std::string const key, std::string const separator, int Default) {
1070 std::string string_value = parse(input, key, separator);
1071 if (string_value == "")
1072 return Default;
1073
1074 return std::atoi(string_value.c_str());
1075 }
1076
1077 float parse_float_with_default(std::string const input, std::string const key, std::string const separator, float Default) {
1078 std::string string_value = parse(input, key, separator);
1079 if (string_value == "")
1080 return Default;
1081
1082 return std::atof(string_value.c_str());
1083 }
1084 }
1085
1086 std::tuple<uint, uint, size_t> read_n_iter(const char* argv) {
1087 std::string string_arg = argv;
1088
1089 int n_iters = std::atoi(strip(string_arg, ",").c_str());
1090
1091 std::string string_seed = parse(string_arg, "seed=", ",");
1092 if (string_seed != "") {
1093 std::srand(std::atoi(string_seed.c_str()));
1094 } else
1095 std::srand(std::time(0));
1096
1097 int reversed_n_iters = parse_int_with_default(string_arg, "reversed_n_iter=", ",", 0);
1098
1099 utils::max_print_num_graphs = parse_int_with_default(string_arg, "max_print_num_graphs=", ",", utils::max_print_num_graphs);
1100
1101 quids::tolerance = parse_float_with_default(string_arg, "tolerance=", ",", quids::tolerance);
1102 quids::safety_margin = parse_float_with_default(string_arg, "safety_margin=", ",", quids::safety_margin);
1103
1104 quids::align_byte_length = parse_int_with_default(string_arg, "align=", ",", quids::align_byte_length);
1105
1106 quids::simple_truncation = parse_int_with_default(string_arg, "simple_truncate=", ",", quids::simple_truncation);
1107 quids::load_balancing_bucket_per_thread = parse_int_with_default(string_arg, "load_balancing_bucket_per_thread=", ",", quids::load_balancing_bucket_per_thread);
1108
1109 #ifdef MPI_VERSION
1110 quids::mpi::min_equalize_size = parse_int_with_default(string_arg, "min_equalize_size=", ",", quids::mpi::min_equalize_size);
1111 quids::mpi::equalize_inbalance = parse_float_with_default(string_arg, "equalize_inbalance=", ",", quids::mpi::equalize_inbalance);
1112 #endif
1113
1114 size_t max_num_object = parse_int_with_default(string_arg, "max_num_object=", ",", 0);
1115
1116 return {n_iters, reversed_n_iters, max_num_object};
1117 }
1118
1119 void read_state(const char* argv, quids::it_t &state) {
1120 std::string string_args = argv;
1121
1122 std::string string_arg;
1123 while ((string_arg = strip(string_args, ";")) != "") {
1124 int n_node = std::atoi(strip(string_arg, ",").c_str());
1125 int n_graphs = parse_int_with_default(string_arg, "n_graphs=", ",", 1);
1126 float real = parse_float_with_default(string_arg, "real=", ",", 1) / std::sqrt((float)n_graphs);
1127 float imag = parse_float_with_default(string_arg, "imag=", ",", 0) / std::sqrt((float)n_graphs);
1128
1129 for (auto i = 0; i < n_graphs; ++i) {
1130 char *begin, *end;
1131 utils::make_graph(begin, end, n_node);
1132 state.append(begin, end, {real, imag});
1133 }
1134 }
1135
1136 utils::randomize(state);
1137 }
1138
1139 simulator_t read_rule(const char* argv, debug_t mid_step_function=[](const char*){}) {
1140 std::string string_args = argv;
1141
1142 simulator_t simulator;
1143
1144 std::string string_arg;
1145 while ((string_arg = strip(string_args, ";")) != "") {
1146 std::string rule_name = strip(string_arg, ",");
1147 float theta = M_PI*parse_float_with_default(string_arg, "theta=", ",", 0.25);
1148 float phi = M_PI*parse_float_with_default(string_arg, "phi=", ",", 0);
1149 float xi = M_PI*parse_float_with_default(string_arg, "xi=", ",", 0);
1150 int n_iter = parse_int_with_default(string_arg, "n_iter=", ",", 1);
1151
1152 if (rule_name == "split_merge") {
1153 simulator.push_back({n_iter, true, NULL, new split_merge(theta, phi, xi), NULL, new split_merge(theta, phi, -xi)});
1154 } else if (rule_name == "erase_create") {
1155 simulator.push_back({n_iter, true, NULL, new erase_create(theta, phi, xi), NULL, new erase_create(theta, phi, -xi)});
1156 } else if (rule_name == "coin") {
1157 simulator.push_back({n_iter, true, NULL, new coin(theta, phi, xi), NULL, new coin(theta, phi, -xi)});
1158 } else if (rule_name == "step") {
1159 simulator.push_back({n_iter, false, step, NULL, reversed_step, NULL});
1160 } else if (rule_name == "reversed_step") {
1161 simulator.push_back({n_iter, false, reversed_step, NULL, step, NULL});
1162 }
1163 }
1164
1165 return simulator;
1166 }
1167
1168 std::tuple<uint, uint, simulator_t, size_t> parse_simulation(const char* argv, it_t &state, debug_t mid_step_function=[](const char*){}) {
1169 std::string string_args = argv;
1170
1171 auto [n_iter, reversed_n_iters, max_num_object] = read_n_iter(strip(string_args, "|").c_str());
1172 read_state(strip(string_args, "|").c_str(), state);
1173 auto simulator = read_rule(string_args.c_str(), mid_step_function);
1174
1175 return {n_iter, reversed_n_iters, simulator, max_num_object};
1176 }
1177 }
1178}
class represneting a dynamic (or rule).
Definition: quids.hpp:100
size_t min_equalize_size
minimum number of object that should be attained (in at least one node) before equalizing (load-shari...
Definition: quids_mpi.hpp:46
class mpi_iteration mpi_it_t
mpi iteration type
Definition: quids_mpi.hpp:59
class mpi_symbolic_iteration mpi_sy_it_t
mpi symbolic iteration type
Definition: quids_mpi.hpp:61
float equalize_inbalance
maximum imbalance between nodes (max_obj - avg_obj)/max_obj allowed before equalizing.
Definition: quids_mpi.hpp:48
std::complex< PROBA_TYPE > mag_t
complex magnitude type
Definition: quids.hpp:73
class symbolic_iteration sy_it_t
symbolic iteration type
Definition: quids.hpp:77
std::function< void(const char *step)> debug_t
debuging function type
Definition: quids.hpp:85
class iteration it_t
iteration class type
Definition: quids.hpp:75
int load_balancing_bucket_per_thread
number of load balancing buckets per thread
Definition: quids.hpp:63
float safety_margin
memory safety margin (0.2 = 80% memory usage target)
Definition: quids.hpp:61
PROBA_TYPE tolerance
tolerance for objects (remove objects with a smaller probability)
Definition: quids.hpp:59
uint align_byte_length
amount of byte to align objects to
Definition: quids.hpp:57
bool simple_truncation
simple truncation toggle - disable probabilistic truncation, increasing "accuracy" but reducing the r...
Definition: quids.hpp:69