2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
29#include <initializer_list>
43#include <unordered_map>
44#include <unordered_set>
51
52
53
54
59using u128 =
unsigned __int128;
63
64
66inline void throw_assertion_error(
const std::string &condition,
67 const std::string &msg,
const char *file,
69 throw std::runtime_error(
"tgen: " + msg +
" (assertion `" + condition +
70 "` failed at " + file +
":" +
71 std::to_string(line) +
")");
73inline void throw_assertion_error(
const std::string &condition,
74 const char *file,
int line) {
75 throw std::runtime_error(
"tgen: assertion `" + condition +
"` failed at " +
76 std::string(file) +
":" + std::to_string(line));
78inline std::runtime_error error(
const std::string &msg) {
79 return std::runtime_error(
"tgen: " + msg);
81inline std::runtime_error contradiction_error(
const std::string &type,
82 const std::string &msg =
"") {
84 std::string error_msg =
85 type +
": invalid " + type +
" (contradictory restrictions)";
87 error_msg +=
": " + msg;
88 return error(error_msg);
90inline std::runtime_error
91complex_restrictions_error(
const std::string &type,
92 const std::string &msg =
"") {
94 std::string error_msg =
95 type +
": cannot represent " + type +
" (complex restrictions)";
97 error_msg +=
": " + msg;
98 return error(error_msg);
100inline void tgen_ensure_against_bug(
bool cond,
const std::string &msg =
"") {
102 std::string error_msg;
104 error_msg =
"tgen: " + msg +
"\n";
105 error_msg +=
"tgen: THERE IS A BUG IN TGEN; PLEASE CONTACT MAINTAINERS";
106 throw std::runtime_error(error_msg);
111#define tgen_ensure(cond, ...)
113 tgen::detail::throw_assertion_error(#cond, ##__VA_ARGS__, __FILE__,
117inline bool registered =
false;
118inline void ensure_registered() {
120 "tgen was not registered! You should call "
121 "tgen::register_gen(argc, argv) before running tgen functions");
127template <
typename T,
typename =
void>
struct is_container : std::false_type {};
129struct is_container<T,
130 std::void_t<
typename std::remove_reference_t<T>::value_type,
131 decltype(std::begin(std::declval<T>())),
132 decltype(std::end(std::declval<T>()))>>
135template <
typename Char,
typename Traits,
typename Alloc>
136struct is_container<std::basic_string<Char, Traits, Alloc>> : std::false_type {
138template <
typename Char,
typename Traits,
typename Alloc>
139struct is_container<
const std::basic_string<Char, Traits, Alloc>>
140 : std::false_type {};
141template <
typename Char,
typename Traits,
typename Alloc>
142struct is_container<std::basic_string<Char, Traits, Alloc> &>
143 : std::false_type {};
144template <
typename Char,
typename Traits,
typename Alloc>
145struct is_container<
const std::basic_string<Char, Traits, Alloc> &>
146 : std::false_type {};
149template <
typename T>
struct is_pair : std::false_type {};
150template <
typename A,
typename B>
151struct is_pair<std::pair<A, B>> : std::true_type {};
153template <
typename T>
struct is_tuple : std::false_type {};
154template <
typename... Ts>
155struct is_tuple<std::tuple<Ts...>> : std::true_type {};
159 : std::bool_constant<!is_container<T>::value
and !is_tuple<T>::value
and
160 !is_pair<T>::value> {};
163struct is_container_multiline
164 : std::bool_constant<is_container<T>::value
and
165 !is_scalar<
typename std::remove_cv_t<
166 std::remove_reference_t<T>>::value_type>::value> {
169template <
typename T>
struct is_pair_multiline : std::false_type {};
170template <
typename A,
typename B>
171struct is_pair_multiline<std::pair<A, B>>
172 : std::bool_constant<!is_scalar<A>::value
or !is_scalar<B>::value> {};
174template <
typename Tuple>
struct is_tuple_multiline : std::false_type {};
175template <
typename... Ts>
176struct is_tuple_multiline<std::tuple<Ts...>>
177 : std::bool_constant<(!is_scalar<Ts>::value
or ...)> {};
180template <
typename>
inline constexpr bool dependent_false_v =
false;
183
184
187using is_sequential_tag =
void;
190template <
typename T,
typename =
void>
191struct is_associative_container : std::false_type {};
193struct is_associative_container<
194 T, std::void_t<
typename T::key_type,
typename T::key_compare>>
198template <
typename T,
typename =
void>
199struct is_sequential : std::false_type {};
202 T, std::void_t<
typename std::decay_t<T>::tgen_is_sequential_tag>>
206
207
210inline std::mt19937 rng;
213
214
219 bool IsCont = detail::is_container<std::decay_t<T>>::value>
220struct print_cols_view;
223template <
typename T>
struct print_cols_view<T,
true> {
225 decltype(std::begin(std::declval<
const T &>())) it;
227 print_cols_view(
const T &v) : value(v), it(v.begin()) {}
229 std::size_t size()
const {
return value.size(); }
230 decltype(
auto) get(std::size_t)
const {
return *it; }
231 void advance() { ++it; }
235template <
typename T>
struct print_cols_view<T,
false> {
238 print_cols_view(
const T &v) : value(v) {}
240 std::size_t size()
const {
return value.size(); }
241 decltype(
auto) get(std::size_t i)
const {
return value[i]; }
246
247
251constexpr int distinct_attempt_multiplier = 84;
254template <
typename Seen,
typename Fn>
255auto try_generate_distinct(Seen &seen, Fn &&next,
bool insert =
true)
256 -> std::optional<std::invoke_result_t<Fn &>> {
257 using T = std::invoke_result_t<Fn &>;
259 distinct_attempt_multiplier * std::max<size_t>(1, seen.size());
260 for (size_t i = 0; i < attempts; ++i) {
263 if (seen.insert(val).second)
265 }
else if (seen.count(val) == 0)
274
275
278enum class compiler_kind { gcc, clang, unknown };
286 compiler_value(compiler_kind kind = compiler_kind::unknown,
int major = 0,
288 : kind_(kind), major_(major), minor_(minor) {}
297 cpp_value(std::optional<
int> version = std::nullopt)
298 : version_(version ? *version : 0) {
300 tgen_ensure(*version == 17
or *version == 20
or *version == 23,
301 "unsupported C++ version (use 17, 20, 23)");
312
313
316template <
typename T>
struct list;
319template <
typename Func,
typename... Args>
struct distinct {
321 std::tuple<Args...> args_;
326 : func_(std::move(func)), args_(std::move(args)...) {}
348 auto val = generate_distinct(
true);
352 throw detail::error(
"distinct: no more distinct values");
354 template <
typename U>
auto gen(std::initializer_list<U> il) {
355 return gen(std::vector<U>(il));
361 for (
int i = 0; i < size; ++i)
362 res.push_back(gen());
364 return typename list<T>::value(res);
370 bool empty() {
return generate_distinct(
false) == std::nullopt; }
376 auto val = generate_distinct(
true);
382 return typename list<T>::value(res);
386 friend std::ostream &operator<<(std::ostream &out,
const distinct &) {
388 detail::dependent_false_v<
distinct>,
389 "distinct: cannot print a distinct generator. Maybe you forgot to "
397 auto generate_distinct(
bool insert) {
398 return detail::try_generate_distinct(
399 seen_, [&] {
return std::apply(func_, args_); }, insert);
402template <
typename Func,
typename... Args>
403distinct(Func, Args...) ->
distinct<Func, Args...>;
407 const Gen &self()
const {
return *
static_cast<
const Gen *>(
this); }
409 template <
typename... Args>
auto gen_list(
int size, Args &&...args)
const {
410 std::vector<
typename Gen::value> res;
412 for (
int i = 0; i < size; ++i)
413 res.push_back(
static_cast<
const Gen *>(
this)->gen(
414 std::forward<Args>(args)...));
416 return typename list<
typename Gen::value>::value(res);
420 template <
typename Pred,
typename... Args>
421 auto gen_until(Pred predicate,
int max_tries, Args &&...args)
const {
422 for (
int i = 0; i < max_tries; ++i) {
423 typename Gen::value val =
static_cast<
const Gen *>(
this)->gen(
424 std::forward<Args>(args)...);
430 throw detail::error(
"could not generate value matching predicate");
432 template <
typename Pred,
typename T,
typename... Args>
433 auto gen_until(Pred predicate,
int max_tries, std::initializer_list<T> il,
434 Args &&...args)
const {
435 return gen_until(predicate, max_tries, std::vector<T>(il),
436 std::forward<Args>(args)...);
440 template <
typename... Args>
auto distinct(Args &&...args)
const {
442 [self = self()](
auto &&...inner_args)
mutable ->
decltype(
auto) {
444 std::forward<
decltype(inner_args)>(inner_args)...);
446 std::forward<Args>(args)...);
448 template <
typename T,
typename... Args>
449 auto distinct(std::initializer_list<T> il, Args &&...args)
const {
450 return distinct(std::vector<T>(il), std::forward<Args>(args)...);
454 friend std::ostream &operator<<(std::ostream &out,
const gen_base &) {
455 static_assert(detail::dependent_false_v<
gen_base>,
456 "gen_base: cannot print a generator. Maybe you forgot to "
464 const Val &self()
const {
return *
static_cast<
const Val *>(
this); }
467 return self().to_std() < rhs.to_std();
475struct is_generator_value
476 : std::is_base_of<gen_value_base<std::decay_t<T>>, std::decay_t<T>> {};
481
482
488 template <
typename T>
print(
const T &val,
char sep =
' ') {
489 std::ostringstream oss;
490 write(oss, val, sep);
493 template <
typename T>
494 print(
const std::initializer_list<T> &il,
char sep =
' ') {
495 std::ostringstream oss;
496 write(oss, std::vector<T>(il), sep);
499 template <
typename T>
500 print(
const std::initializer_list<std::initializer_list<T>> &il,
502 std::ostringstream oss;
503 std::vector<std::vector<T>> mat;
504 for (
const auto &i : il)
506 write(oss, mat, sep);
510 template <
typename T>
void write(std::ostream &os,
const T &val,
char sep) {
511 if constexpr (detail::is_pair<T>::value) {
512 if constexpr (detail::is_pair_multiline<T>::value) {
513 write(os, val.first, sep);
515 write(os, val.second, sep);
518 write(os, val.first,
' ');
520 write(os, val.second,
' ');
522 }
else if constexpr (detail::is_tuple<T>::value)
523 write_tuple(os, val, sep);
524 else if constexpr (detail::is_container<T>::value)
525 write_container(os, val, sep);
526 else if constexpr (std::is_same_v<T, detail::i128>
or
527 std::is_same_v<T, detail::u128>)
528 write_128_number(os, val);
534 template <
typename T>
void write_128_number(std::ostream &os, T num) {
535 static const long long BASE = 1e18;
543 write_128_number(os, num / BASE);
544 os << std::setw(18) << std::setfill(
'0')
545 <<
static_cast<
long long>(num % BASE);
547 os <<
static_cast<
long long>(num);
550 template <
typename C>
551 void write_container(std::ostream &os,
const C &container,
char sep) {
554 for (
const auto &e : container) {
556 os << (detail::is_container_multiline<C>::value ?
'\n' : sep);
558 write(os, e, detail::is_container_multiline<C>::value ? sep :
' ');
563 template <
typename Tuple, size_t... I>
564 void write_tuple_impl(std::ostream &os,
const Tuple &tp,
char sep,
565 std::index_sequence<I...>) {
567 ((os << (first ? (first =
false,
"")
568 : (detail::is_tuple_multiline<Tuple>::value
570 : std::string(1, sep))),
571 write(os, std::get<I>(tp),
572 detail::is_tuple_multiline<Tuple>::value ? sep :
' ')),
575 template <
typename T>
576 void write_tuple(std::ostream &os,
const T &tp,
char sep) {
577 write_tuple_impl(os, tp, sep,
578 std::make_index_sequence<std::tuple_size<T>::value>{});
581 friend std::ostream &operator<<(std::ostream &out,
const print &pr) {
588 template <
typename T>
590 template <
typename T>
591 println(
const std::initializer_list<T> &il,
char sep =
' ')
593 template <
typename T>
594 println(
const std::initializer_list<std::initializer_list<T>> &il,
598 friend std::ostream &operator<<(std::ostream &out,
const println &pr) {
599 return out << pr.s_ <<
'\n';
617 ((detail::is_container<std::decay_t<Args>>::value
or
618 detail::is_sequential<std::decay_t<Args>>::value)
and
620 "print_cols: arguments must be containers or sequential generator "
622 std::ostringstream oss;
627 void write(std::ostream &os,
const Args &...args) {
628 auto views = std::apply(
629 [](
const Args &...inner_args) {
630 return std::make_tuple(
631 detail::print_cols_view<
decltype(inner_args)>{
634 std::forward_as_tuple(args...));
636 const std::size_t n = std::get<0>(views).size();
638 auto check = [&](
const auto &v) {
639 tgen_ensure(v.size() == n,
"print_cols: sizes should be the same");
641 std::apply([&](
const auto &...v) { (check(v), ...); }, views);
643 for (std::size_t i = 0; i < n; ++i) {
647 [&](
const auto &...v) {
648 ((os << (first ?
"" :
" ") <<
print(v.get(i)),
656 std::apply([](
auto &...v) { (v.advance(), ...); }, views);
660 friend std::ostream &operator<<(std::ostream &out,
const print_cols &pr) {
666
667
677using uniform_int_t = std::conditional_t<
678 (
sizeof(T) >=
sizeof(
short)), T,
679 std::conditional_t<std::is_signed_v<T>,
int,
unsigned int>>;
685template <
typename T> T
next(T right) {
686 detail::ensure_registered();
687 if constexpr (std::is_integral_v<T>) {
688 tgen_ensure(right >= 1,
"value for `next` must be valid");
689 return static_cast<T>(
690 std::uniform_int_distribution<detail::uniform_int_t<T>>(
692 static_cast<detail::uniform_int_t<T>>(right) - 1)(detail::rng));
693 }
else if constexpr (std::is_floating_point_v<T>) {
694 tgen_ensure(right >= 0,
"value for `next` must be valid");
695 return std::uniform_real_distribution<T>(0, right)(detail::rng);
697 throw detail::error(
"invalid type for next (" +
698 std::string(
typeid(T).name()) +
")");
706template <
typename T> T
next(T left, T right) {
707 detail::ensure_registered();
708 tgen_ensure(left <= right,
"range for `next` must be valid");
709 if constexpr (std::is_integral_v<T>)
710 return static_cast<T>(
711 std::uniform_int_distribution<detail::uniform_int_t<T>>(
712 static_cast<detail::uniform_int_t<T>>(left),
713 static_cast<detail::uniform_int_t<T>>(right))(detail::rng));
714 else if constexpr (std::is_floating_point_v<T>)
715 return std::uniform_real_distribution<T>(left, right)(detail::rng);
717 throw detail::error(
"invalid type for next (" +
718 std::string(
typeid(T).name()) +
")");
743template <
typename T> T
wnext(T right,
int w) {
746 T val = next<T>(right);
747 for (
int i = 0; i < w; ++i)
748 val = std::max(val, next<T>(right));
749 for (
int i = 0; i < -w; ++i)
750 val = std::min(val, next<T>(right));
755 double x, r = next<
double>(0, 1);
758 x = std::pow(r, 1.0 / (w + 1));
760 x = 1.0 - std::pow(r, 1.0 / (-w + 1));
768template <
typename T> T
wnext(T left, T right,
int w) {
771 T val = next<T>(left, right);
772 for (
int i = 0; i < w; ++i)
773 val = std::max(val, next<T>(left, right));
774 for (
int i = 0; i < -w; ++i)
775 val = std::min(val, next<T>(left, right));
780 double x, r = next<
double>(0, 1);
783 x = std::pow(r, 1.0 / (w + 1));
785 x = 1.0 - std::pow(r, 1.0 / (-w + 1));
788 return left + T(x * (right - left));
795inline u128 next128(u128 total) {
796 tgen_ensure(total > 0,
"next128: total must be positive");
799 u128 limit = (u128(-1) / total) * total;
803 u128 r = (u128(next<uint64_t>(0, std::numeric_limits<uint64_t>::max()))
805 next<uint64_t>(0, std::numeric_limits<uint64_t>::max());
823 static_assert(std::is_arithmetic_v<T>,
824 "weighted_sampler requires an arithmetic weight type");
832 std::vector<storage_t> weight_;
833 std::vector<
int> alias_;
840 : n_(distribution.size()),
alias_(
n_) {
842 "weighted_sampler: distribution must be non-empty");
843 for (
const auto &w : distribution)
845 "weighted_sampler: distribution must be non-negative");
847 total_ = std::accumulate(distribution.begin(), distribution.end(),
850 std::queue<
int> big, small;
851 for (
int i = 0; i < n_; ++i) {
852 weight_.push_back(storage_t(n_) * storage_t(distribution[i]));
853 if (weight_[i] < total_)
859 while (!small.empty()
and !big.empty()) {
860 int s = small.front();
867 weight_[b] -= total_ - weight_[s];
868 if (weight_[b] < total_)
874 detail::tgen_ensure_against_bug(
875 small.empty(),
"weighted_sampler: small must be empty");
879 while (!big.empty()) {
882 if constexpr (std::is_integral_v<T>) {
883 detail::tgen_ensure_against_bug(
884 weight_[b] == total_,
885 "weighted_sampler: weight of big element must be total");
890 weighted_sampler(
const std::initializer_list<T> &distribution)
891 : weighted_sampler(std::vector<T>(distribution)) {}
895 static detail::u128 sample_below(detail::u128 total) {
896 return detail::next128(total);
898 static double sample_below(
double total) {
899 return tgen::next<
double>(0, total);
906 int i = tgen::next<
int>(0, n_ - 1);
907 return sample_below(total_) < weight_[i] ? i : alias_[i];
922size_t next_by_distribution(
const std::initializer_list<T> &distribution) {
923 return next_by_distribution(std::vector<T>(distribution));
931 const std::vector<T> &distribution) {
932 tgen_ensure(distribution.size() > 0,
"distribution must be non-empty");
933 tgen_ensure(k >= 0,
"number of elements to choose must be non-negative");
936 std::vector<
int> res;
937 for (
int i = 0; i < k; ++i)
938 res.push_back(am.next());
943many_by_distribution(
int k,
const std::initializer_list<T> &distribution) {
944 return many_by_distribution(k, std::vector<T>(distribution));
949template <
typename It>
void shuffle(It first, It last) {
953 for (It i = first + 1; i != last; ++i)
954 std::iter_swap(i, first + next(0,
static_cast<
int>(i - first)));
959template <
typename C> [[nodiscard]]
auto shuffled(
const C &container) {
960 if constexpr (detail::is_associative_container<C>::value) {
961 std::vector<
typename C::value_type> vec(container.begin(),
963 shuffle(vec.begin(), vec.end());
966 auto new_container = container;
967 shuffle(new_container.begin(), new_container.end());
968 return new_container;
972[[nodiscard]] std::vector<T> shuffled(
const std::initializer_list<T> &il) {
973 return shuffled(std::vector<T>(il));
979 int size = std::distance(first, last);
980 tgen_ensure(size > 0,
"cannot pick from empty range");
982 std::advance(it, next(0, size - 1));
989 return pick(container.begin(), container.end());
991template <
typename T> T pick(
const std::initializer_list<T> &il) {
992 return pick(std::vector<T>(il));
997template <
typename C,
typename T>
999 std::vector<T> distribution) {
1000 tgen_ensure(container.size() == distribution.size(),
1001 "container and distribution must have the same size");
1002 auto it = container.begin();
1003 std::advance(it, next_by_distribution(distribution));
1006template <
typename C,
typename T>
1007typename C::value_type
1008pick_by_distribution(
const C &container,
1009 const std::initializer_list<T> &distribution) {
1010 return pick_by_distribution(container, std::vector<T>(distribution));
1012template <
typename T,
typename U>
1013T pick_by_distribution(
const std::initializer_list<T> &il,
1014 const std::vector<U> &distribution) {
1015 return pick_by_distribution(std::vector<T>(il), distribution);
1017template <
typename T,
typename U>
1018T pick_by_distribution(
const std::initializer_list<T> &il,
1019 const std::initializer_list<U> &distribution) {
1020 return pick_by_distribution(std::vector<T>(il),
1021 std::vector<U>(distribution));
1026template <
typename C> C
choose(
const C &container,
int k) {
1027 tgen_ensure(0 < k
and k <=
static_cast<
int>(container.size()),
1028 "number of elements to choose must be valid");
1029 std::vector<
typename C::value_type> new_vec;
1031 int need = k, left = container.size();
1032 for (
auto cur_it = container.begin(); cur_it != container.end(); ++cur_it) {
1033 if (next(1, left--) <= need) {
1034 new_container.insert(new_container.end(), *cur_it);
1038 return new_container;
1040template <
typename T>
1041std::vector<T> choose(
const std::initializer_list<T> &il,
int k) {
1042 return choose(std::vector<T>(il), k);
1051 std::unordered_map<T, T> virtual_list_;
1054 static constexpr size_t array_pool_max =
size_t{1} << 23;
1058 : left_(left), right_(right), num_available_(right - left + 1) {}
1061 T
size()
const {
return num_available_; }
1070 T i = next<T>(0,
size() - 1);
1073 auto vi_it = virtual_list_.find(i);
1074 T vi = vi_it == virtual_list_.end() ? i : vi_it->second;
1075 auto vj_it = virtual_list_.find(j);
1076 T vj = vj_it == virtual_list_.end() ? j : vj_it->second;
1077 virtual_list_[i] = vj;
1088 tgen_ensure(count >= 0,
"distinct_range: size must be nonnegative");
1090 "distinct_range: no more values to generate");
1092 size_t range_size = right_ - left_ + 1;
1093 size_t sample_count = count;
1096 if (sample_count > 0) {
1097 if (range_size <= array_pool_max)
1098 res = sample_from_pool(sample_count, range_size);
1099 else if (sample_count * 2 > range_size)
1100 res = sample_complement(sample_count, range_size);
1102 res = sample_sparse(sample_count);
1105 num_available_ -= count;
1106 virtual_list_.clear();
1107 return typename list<T>::value(res);
1117 std::vector<T> sample_from_pool(size_t count, size_t range_size) {
1118 std::vector<T> pool(range_size);
1119 std::iota(pool.begin(), pool.end(), left_);
1120 for (size_t i = 0; i < count; ++i) {
1121 size_t j = next<size_t>(i, range_size - 1);
1122 std::swap(pool[i], pool[j]);
1130 std::vector<T> sample_complement(size_t count, size_t range_size) {
1131 size_t exclude_count = range_size - count;
1132 std::unordered_set<T> excluded;
1133 excluded.reserve(exclude_count * 2);
1135 if (exclude_count <= array_pool_max) {
1136 for (T value : sample_from_pool(exclude_count, range_size))
1137 excluded.insert(value);
1139 for (T value : sample_sparse(exclude_count))
1140 excluded.insert(value);
1145 for (T value = left_; value <= right_; ++value) {
1146 if (!excluded.count(value))
1147 res.push_back(value);
1149 detail::tgen_ensure_against_bug(
1150 res.size() == count,
"distinct_range: complement sampling failed");
1156 std::vector<T> sample_sparse(size_t count) {
1157 std::unordered_map<T, T> local_virtual;
1158 local_virtual.reserve(count * 2);
1159 T remaining = range_span();
1162 for (size_t step = 0; step < count; ++step) {
1163 T i = next<T>(0, remaining - 1);
1164 T j = remaining - 1;
1166 auto vi_it = local_virtual.find(i);
1167 T vi = vi_it == local_virtual.end() ? i : vi_it->second;
1168 auto vj_it = local_virtual.find(j);
1169 T vj = vj_it == local_virtual.end() ? j : vj_it->second;
1170 local_virtual[i] = vj;
1172 res.push_back(vi + left_);
1180 T range_span() {
return right_ - left_ + 1; }
1185 std::vector<T> list_;
1186 distinct_range<size_t> idx_;
1189 template <
typename C>
1193 distinct_container(
const std::initializer_list<T> &il)
1194 : distinct_container(std::vector<T>(il)) {}
1201 T
gen() {
return list_[idx_.gen()]; }
1207 for (
int i = 0; i < size; ++i)
1208 res.push_back(
gen());
1209 return typename list<T>::value(res);
1217 res.push_back(
gen());
1218 return typename list<T>::value(res);
1221template <
typename C>
1225
1226
1227
1228
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1246
1247
1251 detail::cpp = detail::cpp_value(version);
1255
1256
1260 return {compiler_kind::gcc, major, minor};
1265 return {compiler_kind::clang, major, minor};
1270 detail::compiler.kind_ = compiler.kind_;
1271 detail::compiler.major_ = compiler.major_;
1272 detail::compiler.minor_ = compiler.minor_;
1279inline bool process_special_opt_flags(std::string &key) {
1281 if (key.find(
"tgen::CPP:") == 0) {
1282 int prefix_len = std::string(
"tgen::CPP:").size();
1283 tgen_ensure(
static_cast<
int>(key.size()) == prefix_len + 2
and
1284 std::isdigit(key[prefix_len])
and
1285 std::isdigit(key[prefix_len + 1]),
1286 "invalid CPP format");
1287 int version = std::stoi(key.substr(prefix_len, 2));
1295 size_t prefix_len = 0;
1297 if (key.find(
"tgen::GCC") == 0) {
1298 kind = compiler_kind::gcc;
1299 prefix_len = std::string(
"tgen::GCC").size();
1300 }
else if (key.find(
"tgen::CLANG") == 0) {
1301 kind = compiler_kind::clang;
1302 prefix_len = std::string(
"tgen::CLANG").size();
1307 if (key.size() == prefix_len) {
1312 tgen_ensure(key[prefix_len] ==
':',
"invalid compiler format");
1315 std::string inside = key.substr(prefix_len, key.size() - prefix_len);
1316 int major = 0, minor = 0;
1318 size_t dot = inside.find(
'.');
1319 if (dot == std::string::npos) {
1321 std::all_of(inside.begin(), inside.end(), ::isdigit),
1322 "invalid compiler version");
1323 major = std::stoi(inside);
1325 std::string maj = inside.substr(0, dot);
1326 std::string min = inside.substr(dot + 1);
1329 std::all_of(maj.begin(), maj.end(), ::isdigit)
and
1331 "invalid compiler major version");
1333 std::all_of(min.begin(), min.end(), ::isdigit)
and
1335 "invalid compiler minor version");
1337 major = std::stoi(maj);
1338 minor = std::stoi(min);
1346inline std::vector<std::string>
1348inline std::map<std::string, std::string>
1351template <
typename T> T get_opt(
const std::string &value) {
1353 if constexpr (std::is_same_v<T,
bool>) {
1354 if (value ==
"true" or value ==
"1")
1356 if (value ==
"false" or value ==
"0")
1358 }
else if constexpr (std::is_integral_v<T>) {
1359 if constexpr (std::is_unsigned_v<T>)
1360 return static_cast<T>(std::stoull(value));
1362 return static_cast<T>(std::stoll(value));
1363 }
else if constexpr (std::is_floating_point_v<T>)
1364 return static_cast<T>(std::stold(value));
1370 throw error(
"invalid value `" + value +
"` for type " +
typeid(T).name());
1373inline void parse_opts(
int argc,
char **argv) {
1376 for (
int i = 1; i < argc; ++i) {
1377 std::string key(argv[i]);
1379 if (process_special_opt_flags(key))
1382 if (key[0] ==
'-') {
1384 "invalid opt (" + std::string(argv[i]) +
")");
1385 if (
'0' <= key[1]
and key[1] <=
'9') {
1387 pos_opts.push_back(key);
1392 key = key.substr(1);
1395 pos_opts.push_back(key);
1400 if (key[0] ==
'-') {
1402 "invalid opt (" + std::string(argv[i]) +
")");
1405 key = key.substr(1);
1412 std::size_t eq = key.find(
'=');
1413 if (eq != std::string::npos) {
1415 std::string value = key.substr(eq + 1);
1416 key = key.substr(0, eq);
1418 "expected non-empty key/value in opt (" +
1419 std::string(argv[i]) +
")");
1421 "cannot have repeated keys");
1422 named_opts[key] = value;
1426 "cannot have repeated keys");
1427 tgen_ensure(argv[i + 1],
"value cannot be empty");
1428 named_opts[key] = std::string(argv[i + 1]);
1434inline void set_seed(
int argc,
char **argv) {
1435 std::vector<uint32_t> seed;
1438 for (
int i = 1; i < argc; ++i) {
1440 int size_pos = seed.size();
1442 for (
char *s = argv[i]; *s !=
'\0'; ++s) {
1447 std::seed_seq seq(seed.begin(), seed.end());
1455 detail::ensure_registered();
1456 return index < detail::pos_opts.size();
1461 detail::ensure_registered();
1462 return detail::named_opts.count(key) != 0;
1464template <
typename K>
1465std::enable_if_t<std::is_same_v<K,
char>,
bool> has_opt(K key) {
1471template <
typename T>
1472T
opt(size_t index, std::optional<T> default_value = std::nullopt) {
1473 detail::ensure_registered();
1474 if (!has_opt(index)) {
1476 return *default_value;
1477 throw detail::error(
"cannot find opt at index " +
1478 std::to_string(index));
1480 return detail::get_opt<T>(detail::pos_opts[index]);
1485template <
typename T>
1486T
opt(
const std::string &key, std::optional<T> default_value = std::nullopt) {
1487 detail::ensure_registered();
1490 return *default_value;
1491 throw detail::error(
"cannot find opt with key " + key);
1493 return detail::get_opt<T>(detail::named_opts[key]);
1495template <
typename T,
typename K>
1496std::enable_if_t<std::is_same_v<K,
char>, T>
1497opt(K key, std::optional<T> default_value = std::nullopt) {
1498 return opt<T>(std::string(1, key), default_value);
1503 detail::set_seed(argc, argv);
1505 detail::pos_opts.clear();
1506 detail::named_opts.clear();
1507 detail::parse_opts(argc, argv);
1509 detail::registered =
true;
1515 detail::rng.seed(*seed);
1519 detail::pos_opts.clear();
1520 detail::named_opts.clear();
1522 detail::registered =
true;
1526
1527
1528
1529
1532
1533
1534
1535
1539 T value_l_, value_r_;
1540 std::set<T> values_;
1545 mutable std::vector<std::pair<T, T>>
1547 mutable std::vector<std::vector<
int>> neigh_;
1548 std::vector<std::set<
int>>
1550 bool index_constraints_{
1552 mutable bool uses_full_range_{
1557 list(
int size, T value_left, T value_right)
1558 : size_(size), value_l_(value_left), value_r_(value_right),
1559 uses_full_range_(
true) {
1560 tgen_ensure(size_ > 0,
"list: size must be positive");
1561 tgen_ensure(value_l_ <= value_r_,
"list: value range must be valid");
1567 tgen_ensure(size_ > 0,
"list: size must be positive");
1568 tgen_ensure(!values.empty(),
"list: value set must be non-empty");
1569 value_l_ = 0, value_r_ = values.size() - 1;
1570 val_range_.assign(size_, {value_l_, value_r_});
1572 for (T val : values_)
1573 value_idx_in_set_[val] = idx++;
1578 tgen_ensure(0 <= idx
and idx < size_,
"list: index must be valid");
1579 ensure_val_range_materialized();
1580 if (values_.size() == 0) {
1581 auto &[left, right] = val_range_[idx];
1582 if (left == right
and value_l_ != value_r_) {
1584 "list: must not set to two different values");
1587 "list: value must be in the defined range");
1592 "list: value must be in the set of values");
1593 auto &[left, right] = val_range_[idx];
1594 int new_val = value_idx_in_set_[val];
1596 "list: must not set to two different values");
1597 left = right = new_val;
1599 index_constraints_ =
true;
1606 std::max(idx_1, idx_2) < size_,
1607 "list: indices must be valid");
1611 ensure_val_range_materialized();
1612 ensure_neigh_allocated();
1613 index_constraints_ =
true;
1614 neigh_[idx_1].push_back(idx_2);
1615 neigh_[idx_2].push_back(idx_1);
1621 if (!indices.empty()) {
1622 std::set<
int>::iterator beg = indices.begin();
1623 for (
auto it = std::next(beg); it != indices.end(); ++it)
1631 tgen_ensure(0 <= left
and left <= right
and right < size_,
1632 "list: range indices must be valid");
1633 for (
int i = left; i < right; ++i)
1645 if (!indices.empty())
1646 diff_restrictions_.push_back(indices);
1652 std::set<
int> indices = {idx_1, idx_2};
1658 tgen_ensure(0 <= left
and left <= right
and right < size_,
1659 "list: range indices must be valid");
1660 std::vector<
int> indices(right - left + 1);
1661 std::iota(indices.begin(), indices.end(), left);
1662 return different(std::set<
int>(indices.begin(), indices.end()));
1667 std::vector<
int> indices(size_);
1668 std::iota(indices.begin(), indices.end(), 0);
1669 return different(std::set<
int>(indices.begin(), indices.end()));
1675 using tgen_is_sequential_tag = detail::is_sequential_tag;
1677 using value_type = T;
1680 std::vector<T> vec_;
1684 value(
const std::initializer_list<T> &il) : value(std::vector<T>(il)) {}
1687 int size()
const {
return vec_.size(); }
1692 "list: value: index out of bounds");
1695 const T &operator[](
int idx)
const {
1697 "list: value: index out of bounds");
1704 std::sort(vec_.begin(), vec_.end());
1711 std::reverse(vec_.begin(), vec_.end());
1725 std::vector<T> new_vec = vec_;
1726 for (
int i = 0; i < rhs
.size(); ++i)
1727 new_vec.push_back(rhs[i]);
1728 return value(new_vec);
1734 for (
int i = 0; i < size(); ++i)
1735 std::swap(vec_[i], vec_[next(0, size() - 1)]);
1741 T
pick()
const {
return vec_[next<
int>(0, size() - 1)]; }
1745 template <
typename Dist>
1748 "value and distribution must have the same size");
1749 return vec_[next_by_distribution(distribution)];
1751 template <
typename Dist>
1752 T pick_by_distribution(
1753 const std::initializer_list<Dist> &distribution)
const {
1754 return pick_by_distribution(std::vector<Dist>(distribution));
1761 "number of elements to choose must be valid");
1762 std::vector<T> new_vec;
1764 for (
int i = 0; need > 0; ++i) {
1766 if (next(1, left) <= need) {
1767 new_vec.push_back(vec_[i]);
1771 return value(new_vec);
1775 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
1776 for (
int i = 0; i < val.size(); ++i) {
1786 if constexpr (!detail::is_generator_value<T>::value) {
1789 std::vector<
typename T::std_type> vec;
1790 for (
const auto &i : vec_)
1791 vec.push_back(i.to_std());
1801 if (diff_restrictions_.empty()) {
1802 if (
auto unconstrained = try_gen_unconstrained())
1803 return *unconstrained;
1805 if (
auto all_different = try_gen_all_different())
1806 return *all_different;
1808 ensure_neigh_allocated();
1809 std::vector<T> vec(size_);
1810 std::vector<
bool> defined_idx(
1813 std::vector<
int> comp_id(size_, -1);
1814 std::vector<std::vector<
int>> comp(size_);
1818 auto define_comp = [&](
int cur_comp, T val) {
1819 for (
int idx : comp[cur_comp]) {
1822 defined_idx[idx] =
true;
1828 std::vector<
bool> vis(size_,
false);
1829 for (
int idx = 0; idx < size_; ++idx)
1832 bool value_defined =
false;
1836 std::queue<
int> q({idx});
1838 std::vector<
int> component;
1839 while (!q.empty()) {
1840 int cur_idx = q.front();
1843 component.push_back(cur_idx);
1846 auto [l, r] = val_range_at(cur_idx);
1848 if (!value_defined) {
1850 value_defined =
true;
1852 }
else if (new_value != l) {
1854 throw detail::contradiction_error(
1856 "tried to set value to `" +
1857 std::to_string(new_value) +
1858 "`, but it was already set as `" +
1859 std::to_string(l) +
"`");
1863 for (
int nxt_idx : neigh_[cur_idx]) {
1864 if (!vis[nxt_idx]) {
1865 vis[nxt_idx] =
true;
1872 for (
int cur_idx : component) {
1873 comp_id[cur_idx] = comp_count;
1874 comp[comp_id[cur_idx]].push_back(cur_idx);
1879 define_comp(comp_count, new_value);
1886 std::vector<std::set<
int>> diff_containing_comp_idx(comp_count);
1889 for (
const std::set<
int> &diff : diff_restrictions_) {
1891 if (
static_cast<uint64_t>(diff.size() - 1) +
1892 static_cast<uint64_t>(value_l_) >
1893 static_cast<uint64_t>(value_r_))
1894 throw detail::contradiction_error(
1895 "list",
"tried to generate " +
1896 std::to_string(diff.size()) +
1897 " different values, but the maximum is " +
1898 std::to_string(value_r_ - value_l_ + 1));
1902 std::set<
int> comp_ids;
1903 for (
int idx : diff) {
1904 if (comp_ids.count(comp_id[idx]))
1905 throw detail::contradiction_error(
1906 "list",
"tried to set two indices as equal and "
1908 comp_ids.insert(comp_id[idx]);
1910 diff_containing_comp_idx[comp_id[idx]].insert(dist_id);
1917 for (
auto &diff_containing : diff_containing_comp_idx)
1918 if (diff_containing.size() >= 3)
1919 throw detail::complex_restrictions_error(
1921 "one index cannot be in >= 3 'different' restrictions");
1923 std::vector<
bool> vis_diff(diff_restrictions_.size(),
false);
1924 std::vector<
bool> initially_defined_comp_idx(comp_count,
false);
1927 auto define_tree = [&](
int diff_id) {
1932 std::set<T> defined_values;
1933 for (
int idx : diff_restrictions_[diff_id])
1934 if (defined_idx[idx]) {
1937 if (defined_values.count(vec[idx]))
1938 throw detail::contradiction_error(
1940 "tried to set two indices as equal and different");
1942 defined_values.insert(vec[idx]);
1947 int new_value_count = diff_restrictions_[diff_id].size() -
1948 static_cast<
int>(defined_values.size());
1949 std::vector<T> generated_values =
1950 generate_distinct_values(new_value_count, defined_values);
1951 auto val_it = generated_values.begin();
1952 for (
int idx : diff_restrictions_[diff_id])
1953 if (defined_idx[idx]) {
1956 initially_defined_comp_idx[comp_id[idx]] =
false;
1958 define_comp(comp_id[idx], *val_it);
1964 std::queue<std::pair<
int,
int>> q;
1965 q.emplace(diff_id, -1);
1966 vis_diff[diff_id] =
true;
1967 while (!q.empty()) {
1968 auto [cur_diff, parent] = q.front();
1971 std::set<
int> neigh_diff;
1972 for (
int idx : diff_restrictions_[cur_diff])
1974 diff_containing_comp_idx[comp_id[idx]]) {
1975 if (nxt_diff == cur_diff
or nxt_diff == parent)
1979 if (vis_diff[nxt_diff])
1980 throw detail::complex_restrictions_error(
1982 "cycle found in 'different' restrictions");
1984 neigh_diff.insert(nxt_diff);
1987 for (
int nxt_diff : neigh_diff) {
1988 vis_diff[nxt_diff] =
true;
1989 q.emplace(nxt_diff, cur_diff);
1992 std::set<T> nxt_defined_values;
1993 for (
int idx2 : diff_restrictions_[nxt_diff])
1994 if (defined_idx[idx2]) {
1998 if (initially_defined_comp_idx[comp_id[idx2]])
1999 throw detail::complex_restrictions_error(
2002 nxt_defined_values.insert(vec[idx2]);
2004 int new_value_count =
2005 diff_restrictions_[nxt_diff].size() -
2006 static_cast<
int>(nxt_defined_values.size());
2007 std::vector<T> generated_values = generate_distinct_values(
2008 new_value_count, nxt_defined_values);
2009 auto val_it = generated_values.begin();
2010 for (
int idx2 : diff_restrictions_[nxt_diff])
2011 if (!defined_idx[idx2]) {
2012 define_comp(comp_id[idx2], *val_it);
2024 std::vector<std::pair<
int,
int>> defined_cnt_and_diff_idx;
2026 for (
const std::set<
int> &diff : diff_restrictions_) {
2027 int defined_cnt = 0;
2028 for (
int idx : diff)
2029 if (defined_idx[idx]) {
2031 initially_defined_comp_idx[comp_id[idx]] =
true;
2033 defined_cnt_and_diff_idx.emplace_back(defined_cnt, dist_id);
2037 std::sort(defined_cnt_and_diff_idx.rbegin(),
2038 defined_cnt_and_diff_idx.rend());
2039 for (
auto [defined_cnt, diff_idx] : defined_cnt_and_diff_idx)
2040 if (!vis_diff[diff_idx])
2041 define_tree(diff_idx);
2045 for (std::size_t dist_id = 0; dist_id < diff_restrictions_.size();
2047 if (!vis_diff[dist_id])
2048 define_tree(dist_id);
2054 for (
int idx = 0; idx < size_; ++idx)
2055 if (!defined_idx[idx])
2056 define_comp(comp_id[idx], next<T>(value_l_, value_r_));
2058 if (!values_.empty()) {
2060 std::vector<T> value_vec(values_.begin(), values_.end());
2062 val = value_vec[val];
2070 void ensure_neigh_allocated()
const {
2071 if (neigh_.size() ==
static_cast<size_t>(size_))
2073 neigh_.assign(size_, {});
2077 void ensure_val_range_materialized()
const {
2078 if (!uses_full_range_)
2080 val_range_.assign(size_, {value_l_, value_r_});
2081 uses_full_range_ =
false;
2085 std::pair<T, T> val_range_at(
int idx)
const {
2086 if (uses_full_range_)
2087 return {value_l_, value_r_};
2088 return val_range_[idx];
2094 generate_distinct_values(
int k,
const std::set<T> &forbidden_values)
const {
2095 for (
auto forbidden : forbidden_values)
2096 tgen_ensure(value_l_ <= forbidden
and forbidden <= value_r_);
2097 const T num_available =
2098 (value_r_ - value_l_ + 1) - forbidden_values.size();
2099 if (num_available < k)
2100 throw detail::complex_restrictions_error(
2101 "list",
"not enough distinct values");
2102 if (forbidden_values.empty())
2103 return distinct_range<T>(value_l_, value_r_).gen_list(k).to_std();
2105 std::map<T, T> virtual_list;
2106 std::vector<T> gen_list;
2107 for (
int i = 0; i < k; ++i) {
2108 T j = next<T>(i, num_available - 1);
2109 T vj = virtual_list.count(j) ? virtual_list[j] : j;
2110 T vi = virtual_list.count(i) ? virtual_list[i] : i;
2112 virtual_list[j] = vi, virtual_list[i] = vj;
2114 gen_list.push_back(virtual_list[i]);
2117 for (T &val : gen_list)
2120 std::vector<std::pair<T,
int>> values_sorted;
2121 for (std::size_t i = 0; i < gen_list.size(); ++i)
2122 values_sorted.emplace_back(gen_list[i], i);
2123 std::sort(values_sorted.begin(), values_sorted.end());
2124 auto cur_it = forbidden_values.begin();
2125 int smaller_forbidden_count = 0;
2126 for (
auto [val, idx] : values_sorted) {
2127 while (cur_it != forbidden_values.end()
and
2128 *cur_it <= val + smaller_forbidden_count)
2129 ++cur_it, ++smaller_forbidden_count;
2130 gen_list[idx] += smaller_forbidden_count;
2139 std::optional<
value> try_gen_unconstrained()
const {
2140 if (!values_.empty()
or index_constraints_)
2141 return std::nullopt;
2143 std::vector<T> vec(size_);
2144 for (
int i = 0; i < size_; ++i)
2145 vec[i] = next<T>(value_l_, value_r_);
2153 std::optional<
value> try_gen_all_different()
const {
2154 if (!values_.empty()
or diff_restrictions_.size() != 1)
2155 return std::nullopt;
2157 const std::set<
int> &diff = diff_restrictions_[0];
2158 if (
static_cast<
int>(diff.size()) != size_
or *diff.begin() != 0
or
2159 *diff.rbegin() != size_ - 1)
2160 return std::nullopt;
2162 if (!neigh_.empty()) {
2163 for (
const auto &adj : neigh_) {
2165 return std::nullopt;
2169 if (index_constraints_)
2170 return std::nullopt;
2172 if (
static_cast<
long long>(size_) >
2173 static_cast<
long long>(value_r_) - value_l_ + 1)
2174 throw detail::contradiction_error(
2175 "list",
"tried to generate " + std::to_string(size_) +
2176 " different values, but the maximum is " +
2177 std::to_string(value_r_ - value_l_ + 1));
2184
2185
2186
2187
2190
2191
2192
2193
2197 std::vector<std::pair<
int,
int>> defs_;
2198 std::optional<std::vector<
int>> cycle_sizes_;
2202 tgen_ensure(size_ > 0,
"permutation: size must be positive");
2208 "permutation: index must be valid");
2209 defs_.emplace_back(idx, val);
2216 size_ == std::accumulate(cycle_sizes.begin(), cycle_sizes.end(), 0),
2217 "permutation: cycle sizes must add up to size of permutation");
2218 cycle_sizes_ = cycle_sizes;
2221 permutation &cycles(
const std::initializer_list<
int> &cycle_sizes) {
2222 return cycles(std::vector<
int>(cycle_sizes));
2228 using tgen_is_sequential_tag = detail::is_sequential_tag;
2231 std::vector<
int> vec_;
2236 :
vec_(
vec), sep_(
' '), add_1_(
false) {
2237 tgen_ensure(!vec_.empty(),
"permutation: value: cannot be empty");
2238 std::vector<
bool> vis(vec_.size(),
false);
2239 for (
int i = 0; i <
size(); ++i) {
2241 vec_[i] <
static_cast<
int>(vec_.size()),
2242 "permutation: value: values must be from `0` to "
2245 "permutation: value: cannot have repeated values");
2246 vis[vec_[i]] =
true;
2249 value(
const std::initializer_list<
int> &il)
2250 : value(std::vector<
int>(il)) {}
2253 int size()
const {
return vec_.size(); }
2258 "permutation: value: index out of bounds");
2265 std::vector<
bool> vis(
size(),
false);
2268 for (
int i = 0; i <
size(); ++i)
2271 for (
int j = i; !vis[j]; j = vec_[j])
2275 return ((
size() - cycles) % 2 == 0) ? +1 : -1;
2281 for (
int i = 0; i < size(); ++i)
2289 std::reverse(vec_.begin(), vec_.end());
2296 std::vector<
int> inv(
size());
2297 for (
int i = 0; i < size(); ++i)
2320 for (
int i = 0; i < size(); ++i)
2321 std::swap(vec_[i], vec_[next(0, size() - 1)]);
2327 int pick()
const {
return vec_[next<
int>(0, size() - 1)]; }
2331 template <
typename Dist>
2334 "value and distribution must have the same size");
2335 return vec_[next_by_distribution(distribution)];
2337 template <
typename Dist>
2338 int pick_by_distribution(
2339 const std::initializer_list<Dist> &distribution)
const {
2340 return pick_by_distribution(std::vector<Dist>(distribution));
2344 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
2345 for (
int i = 0; i < val
.size(); ++i) {
2348 out << val
[i
] + val.add_1_;
2360 if (!cycle_sizes_) {
2362 std::vector<
int> idx_to_val(size_, -1), val_to_idx(size_, -1);
2363 for (
auto [idx, val] : defs_) {
2365 0 <= val
and val < size_,
2366 "permutation: value in permutation must be in [0, " +
2367 std::to_string(size_) +
")");
2369 if (idx_to_val[idx] != -1) {
2371 "permutation: cannot set an index to two "
2372 "different values");
2374 idx_to_val[idx] = val;
2376 if (val_to_idx[val] != -1) {
2378 "permutation: cannot set two indices to the "
2381 val_to_idx[val] = idx;
2384 std::vector<
int> perm(size_);
2385 std::iota(perm.begin(), perm.end(), 0);
2386 shuffle(perm.begin(), perm.end());
2388 for (
int &i : idx_to_val)
2391 while (val_to_idx[perm[cur_idx]] != -1)
2393 i = perm[cur_idx++];
2399 std::vector<
int> order(size_);
2400 std::iota(order.begin(), order.end(), 0);
2401 shuffle(order.begin(), order.end());
2403 std::vector<std::vector<
int>> cycles;
2404 for (
int cycle_size : *cycle_sizes_) {
2405 cycles.emplace_back();
2406 for (
int i = 0; i < cycle_size; ++i)
2407 cycles.back().push_back(order[idx++]);
2411 std::vector<
int> perm(size_, -1);
2412 for (
const std::vector<
int> &cycle : cycles) {
2413 int cur_size = cycle.size();
2414 for (
int i = 0; i < cur_size; ++i)
2415 perm[cycle[i]] = cycle[(i + 1) % cur_size];
2423
2424
2425
2426
2432using namespace tgen::detail;
2434inline int popcount(uint64_t x) {
return __builtin_popcountll(x); }
2436inline int ctzll(uint64_t x) {
2439 static const unsigned char index64[64] = {
2440 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
2441 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
2442 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
2443 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12};
2444 return index64[((x & -x) * 0x022FDD63CC95386D) >> 58];
2447inline uint64_t mul_mod(uint64_t a, uint64_t b, uint64_t m) {
2448 return static_cast<u128>(a) * b % m;
2453inline uint64_t expo_mod(uint64_t x, uint64_t y, uint64_t m) {
2456 uint64_t ans = expo_mod(mul_mod(x, x, m), y / 2, m);
2457 return y % 2 ? mul_mod(x, ans, m) : ans;
2466 if (n == 2
or n == 3)
2471 uint64_t r = detail::ctzll(n - 1), d = n >> r;
2473 for (
int a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) {
2474 uint64_t x = detail::expo_mod(a, d, n);
2475 if (x == 1
or x == n - 1
or a % n == 0)
2478 for (uint64_t j = 0; j < r - 1; ++j) {
2479 x = detail::mul_mod(x, x, n);
2491inline uint64_t pollard_rho(uint64_t n) {
2494 auto f = [n](uint64_t x) {
return mul_mod(x, x, n) + 1; };
2496 uint64_t x = 0, y = 0, t = 30, prd = 2, x0 = 1, q;
2497 while (t % 40 != 0
or std::gcd(prd, n) == 1) {
2500 q = mul_mod(prd, x > y ? x - y : y - x, n);
2503 x = f(x), y = f(f(y)), ++t;
2505 return std::gcd(prd, n);
2508inline std::vector<uint64_t> factor(uint64_t n) {
2513 uint64_t d = pollard_rho(n);
2514 std::vector<uint64_t> l = factor(d), r = factor(n / d);
2515 l.insert(l.end(), r.begin(), r.end());
2520template <
typename T>
2521std::runtime_error there_is_no_in_range_error(
const std::string &type, T l,
2523 return error(
"math: there is no " + type +
" in range [" +
2524 std::to_string(l) +
", " + std::to_string(r) +
"]");
2526template <
typename T>
2527std::runtime_error there_is_no_from_error(
const std::string &type, T r) {
2528 return error(
"math: there is no " + type +
" from " + std::to_string(r));
2530template <
typename T>
2531std::runtime_error there_is_no_upto_error(
const std::string &type, T r) {
2532 return error(
"math: there is no " + type +
" up to " + std::to_string(r));
2538inline i128 modular_inverse_128(i128 a, i128 mod) {
2540 "math: modular inverse requires 0 < value < mod");
2542 i128 t = 0, new_t = 1;
2543 i128 r = mod, new_r = a;
2545 while (new_r != 0) {
2548 auto tmp_t = t - q * new_t;
2552 auto tmp_r = r - q * new_r;
2557 tgen_ensure(r == 1,
"math: remainder and mod must be coprime");
2565inline bool mul_leq(uint64_t a, uint64_t b, uint64_t limit) {
2566 if (a == 0
or b == 0)
2568 return a <= limit / b;
2572inline std::optional<uint64_t> expo(uint64_t base, uint64_t exp,
2574 uint64_t result = 1;
2578 if (!mul_leq(result, base, limit))
2579 return std::nullopt;
2588 if (!mul_leq(base, base, limit))
2589 return std::nullopt;
2597inline uint64_t kth_root_floor(uint64_t n, uint64_t k) {
2598 tgen_ensure_against_bug(k > 0,
"math: value must be valid");
2599 if (k == 1
or n <= 1)
2602 uint64_t lo = 1, hi = 1ULL << ((64 + k - 1) / k);
2605 uint64_t mid = lo + (hi - lo + 1) / 2;
2607 if (expo(mid, k, n)) {
2618inline i128 gcd128(i128 a, i128 b) {
2634inline i128 mul_saturate(i128 a, i128 b) {
2636 static const i128 LIMIT =
static_cast<i128>(1) << 64;
2637 if (a == 0
or b == 0)
2648 crt() : a(0), m(1) {}
2649 crt(T a_, T m_) : a(a_), m(m_) {}
2650 crt operator*(crt C) {
2651 if (m == 0
or C.m == 0)
2654 T g = gcd128(m, C.m);
2655 if ((C.a - a) % g != 0)
2664 T inv = modular_inverse_128(m1 % m2, m2);
2666 T k = ((C.a - a) / g) % m2;
2670 k =
static_cast<u128>(k) * inv % m2;
2672 T lcm = mul_saturate(m, m2);
2674 T res = (a +
static_cast<T>((
static_cast<u128>(k) * m) % lcm)) % lcm;
2684inline constexpr long double LOG_ZERO = -INFINITY;
2685inline constexpr long double LOG_ONE = 0.0;
2687inline long double log_space(
long double x) {
2688 return x == 0.0 ? LOG_ZERO : std::log(x);
2692inline long double add_log_space(
long double a,
long double b) {
2697 return a + log1p(exp(b - a));
2702inline long double sub_log_space(
long double a,
long double b) {
2707 return a + log1p(-exp(b - a));
2716 tgen_ensure(n > 0,
"math: number to factor must be positive");
2717 auto factors = detail::factor(n);
2718 std::sort(factors.begin(), factors.end());
2726 tgen_ensure(n > 0,
"math: number to factor must be positive");
2727 std::vector<std::pair<uint64_t,
int>> primes;
2728 for (uint64_t p : factor(n)) {
2729 if (!primes.empty()
and primes.back().first == p)
2730 ++primes.back().second;
2732 primes.emplace_back(p, 1);
2741 return detail::modular_inverse_128(a, mod);
2747 tgen_ensure(n > 0,
"math: totient(0) is undefined");
2750 for (
auto [p, e] : factor_by_prime(n))
2757inline const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> &
2760 static const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> value{
2762 2, 3, 7, 23, 89, 113, 523, 887, 1129, 1327, 9551, 15683, 19609,
2763 31397, 155921, 360653, 370261, 492113, 1349533, 1357201, 2010733,
2764 4652353, 17051707, 20831323, 47326693, 122164747, 189695659,
2765 191912783, 387096133, 436273009, 1294268491, 1453168141,
2766 2300942549, 3842610773, 4302407359, 10726904659, 20678048297,
2767 22367084959, 25056082087, 42652618343, 127976334671, 182226896239,
2768 241160624143, 297501075799, 303371455241, 304599508537,
2769 416608695821, 461690510011, 614487453523, 738832927927,
2770 1346294310749, 1408695493609, 1968188556461, 2614941710599,
2771 7177162611713, 13829048559701, 19581334192423, 42842283925351,
2772 90874329411493, 171231342420521, 218209405436543, 1189459969825483,
2773 1686994940955803, 1693182318746371, 43841547845541059,
2774 55350776431903243, 80873624627234849, 203986478517455989,
2775 218034721194214273, 305405826521087869, 352521223451364323,
2776 401429925999153707, 418032645936712127, 804212830686677669,
2777 1425172824437699411, 5733241593241196731, 6787988999657777797
2779 {1, 2, 4, 6, 8, 14, 18, 20, 22, 34, 36,
2780 44, 52, 72, 86, 96, 112, 114, 118, 132, 148, 154,
2781 180, 210, 220, 222, 234, 248, 250, 282, 288, 292, 320,
2782 336, 354, 382, 384, 394, 456, 464, 468, 474, 486, 490,
2783 500, 514, 516, 532, 534, 540, 582, 588, 602, 652, 674,
2784 716, 766, 778, 804, 806, 906, 916, 924, 1132, 1184, 1198,
2785 1220, 1224, 1248, 1272, 1328, 1356, 1370, 1442, 1476, 1488, 1510}};
2794 throw detail::there_is_no_upto_error(
"prime gap", right);
2796 const auto &[P, G] = prime_gaps();
2797 for (
int i = P.size() - 1;; --i) {
2801 uint64_t real_right = std::min(right, P[i] + G[i] - 1);
2802 uint64_t prev = i > 0 ? G[i - 1] : 0;
2803 uint64_t curr = real_right - P[i];
2806 return {P[i] + 1, real_right};
2813 static const std::vector<uint64_t> highly_composites = {
2814 1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720, 840, 1260, 1680,
2815 2520, 5040, 7560, 10080, 15120, 20160, 25200, 27720, 45360, 50400, 55440,
2816 83160, 110880, 166320, 221760, 277200, 332640, 498960, 554400, 665280,
2817 720720, 1081080, 1441440, 2162160, 2882880, 3603600, 4324320, 6486480,
2818 7207200, 8648640, 10810800, 14414400, 17297280, 21621600, 32432400,
2819 36756720, 43243200, 61261200, 73513440, 110270160, 122522400, 147026880,
2820 183783600, 245044800, 294053760, 367567200, 551350800, 698377680, 735134400,
2821 1102701600, 1396755360, 2095133040, 2205403200, 2327925600, 2793510720,
2822 3491888400, 4655851200, 5587021440, 6983776800, 10475665200, 13967553600,
2823 20951330400, 27935107200, 41902660800, 48886437600, 64250746560,
2824 73329656400, 80313433200, 97772875200, 128501493120, 146659312800,
2825 160626866400, 240940299600, 293318625600, 321253732800, 481880599200,
2826 642507465600, 963761198400, 1124388064800, 1606268664000, 1686582097200,
2827 1927522396800, 2248776129600, 3212537328000, 3373164194400, 4497552259200,
2828 6746328388800, 8995104518400, 9316358251200, 13492656777600, 18632716502400,
2829 26985313555200, 27949074753600, 32607253879200, 46581791256000,
2830 48910880818800, 55898149507200, 65214507758400, 93163582512000,
2831 97821761637600, 130429015516800, 195643523275200, 260858031033600,
2832 288807105787200, 391287046550400, 577614211574400, 782574093100800,
2833 866421317361600, 1010824870255200, 1444035528936000, 1516237305382800,
2834 1732842634723200, 2021649740510400, 2888071057872000, 3032474610765600,
2835 4043299481020800, 6064949221531200, 8086598962041600, 10108248702552000,
2836 12129898443062400, 18194847664593600, 20216497405104000, 24259796886124800,
2837 30324746107656000, 36389695329187200, 48519593772249600, 60649492215312000,
2838 72779390658374400, 74801040398884800, 106858629141264000,
2839 112201560598327200, 149602080797769600, 224403121196654400,
2840 299204161595539200, 374005201994424000, 448806242393308800,
2841 673209363589963200, 748010403988848000, 897612484786617600,
2842 1122015605983272000, 1346418727179926400, 1795224969573235200,
2843 2244031211966544000, 2692837454359852800, 3066842656354276800,
2844 4381203794791824000, 4488062423933088000, 6133685312708553600,
2845 8976124847866176000, 9200527969062830400, 12267370625417107200ULL,
2846 15334213281771384000ULL, 18401055938125660800ULL};
2847 return highly_composites;
2852 for (
int i = highly_composites().size() - 1; i >= 0; --i)
2853 if (highly_composites()[i] <= right)
2854 return highly_composites()[i];
2856 throw detail::there_is_no_upto_error(
"highly composite number", right);
2862 if (right < left
or right < 2)
2863 throw detail::there_is_no_in_range_error(
"prime", left, right);
2864 left = std::max<uint64_t>(left, 2);
2865 auto [l_gap, r_gap] = prime_gap_upto(right);
2866 if (right - left + 1 <= r_gap - l_gap + 1) {
2868 std::vector<uint64_t> vals(right - left + 1);
2869 iota(vals.begin(), vals.end(), left);
2870 shuffle(vals.begin(), vals.end());
2871 for (uint64_t i : vals)
2874 throw detail::there_is_no_in_range_error(
"prime", left, right);
2879 n = next(left, right);
2887 tgen_ensure(left <= std::numeric_limits<uint64_t>::max() - 58,
2888 "math: invalid bound");
2889 for (uint64_t i = std::max<uint64_t>(2, left);; ++i)
2897 for (uint64_t i = right; i >= 2; --i)
2900 throw detail::there_is_no_upto_error(
"prime", right);
2907 for (
auto [p, e] : factor_by_prime(n))
2908 divisors *= (e + 1);
2916 int divisor_count) {
2918 "math: divisor count must be prime");
2919 int root = divisor_count - 1;
2920 uint64_t p =
gen_prime(detail::kth_root_floor(left, root)
,
2921 detail::kth_root_floor(right, root)
);
2922 return *detail::expo(p, root, right);
2929 std::vector<uint64_t> rems,
2930 std::vector<uint64_t> mods) {
2932 throw detail::there_is_no_in_range_error(
"congruent number", left,
2935 "math: number of remainders and mods must be the same");
2936 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
2939 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
2941 "math: remainder must be smaller than the mod");
2942 crt = crt * detail::crt(rems[i], mods[i]);
2945 throw detail::there_is_no_in_range_error(
"congruent number", left,
2947 if (crt.m > right) {
2948 if (!(left <= crt.a
and crt.a <= right))
2949 throw detail::there_is_no_in_range_error(
"congruent number",
2952 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
2953 if (crt.a % mods[j] != rems[j])
2954 throw detail::there_is_no_in_range_error(
"congruent number",
2960 uint64_t k_min = crt.a >= left ? 0 : ((left - crt.a) + crt.m - 1) / crt.m;
2961 uint64_t k_max = (right - crt.a) / crt.m;
2964 throw detail::there_is_no_in_range_error(
"congruent number", left,
2967 return crt.a + next(k_min, k_max) * crt.m;
2974 return gen_congruent(left, right, std::vector<uint64_t>({rem}),
2975 std::vector<uint64_t>({mod}));
2983 std::vector<uint64_t> mods) {
2985 "math: number of remainders and mods must be the same");
2986 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
2989 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
2991 "math: remainder must be smaller than the mod");
2992 crt = crt * detail::crt(rems[i], mods[i]);
2995 throw detail::there_is_no_from_error(
"congruent number", left);
2996 if (crt.m > std::numeric_limits<uint64_t>::max()) {
2998 throw detail::error(
2999 "math: congruent number does not exist or is too large");
3001 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
3002 if (crt.a % mods[j] != rems[j])
3003 throw detail::error(
"math: congruent number does "
3004 "not exist or is too large");
3011 k = ((left - crt.a) + crt.m - 1) / crt.m;
3012 detail::i128 result = crt.a + k * crt.m;
3014 if (result > std::numeric_limits<uint64_t>::max())
3015 throw detail::error(
"math: congruent number is too large");
3022 return congruent_from(left, std::vector<uint64_t>{rem},
3023 std::vector<uint64_t>{mod});
3031 std::vector<uint64_t> mods) {
3033 "math: number of remainders and mods must be the same");
3034 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
3037 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
3039 "math: remainder must be smaller than the mod");
3041 crt = crt * detail::crt(rems[i], mods[i]);
3044 throw detail::there_is_no_upto_error(
"congruent number", right);
3045 if (crt.m > right) {
3046 if (!(crt.a <= right))
3047 throw detail::there_is_no_upto_error(
"congruent number", right);
3049 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
3050 if (crt.a % mods[j] != rems[j])
3051 throw detail::there_is_no_upto_error(
"congruent number",
3058 throw detail::there_is_no_upto_error(
"congruent number", right);
3060 uint64_t k = (right - crt.a) / crt.m;
3061 detail::i128 result = crt.a + k * crt.m;
3064 throw detail::there_is_no_upto_error(
"congruent number", right);
3071 return congruent_upto(right, std::vector<uint64_t>{rem},
3072 std::vector<uint64_t>{mod});
3080 static const std::vector<uint64_t> fib = [] {
3081 std::vector<uint64_t> v = {0, 1};
3083 std::numeric_limits<uint64_t>::max() - v[v.size() - 2])
3084 v.push_back(v.back() + v[v.size() - 2]);
3096 std::optional<
int> part_right = std::nullopt) {
3097 if (!part_right.has_value())
3099 part_right = std::min(*part_right, n);
3101 "math: invalid parameters to gen_partition");
3102 tgen_ensure(part_left <= n
and *part_right > 0,
"math: no such partition");
3105 std::vector<
long double> dp(n + 1, detail::LOG_ZERO);
3106 dp[0] = detail::LOG_ONE;
3107 long double window = detail::LOG_ZERO;
3108 for (
int i = 1; i <= n; ++i) {
3110 window = detail::add_log_space(window, dp[i - part_left]);
3111 if (i >= *part_right + 1)
3112 window = detail::sub_log_space(window, dp[i - *part_right - 1]);
3115 tgen_ensure(dp[n] >= 0,
"math: no such partition");
3119 for (
int i = 1; i <= n; ++i)
3120 dp_pref[i] = detail::add_log_space(dp_pref[i - 1], dp[i]);
3122 std::vector<
int> part;
3126 int l = std::max(0, sum - *part_right), r = sum - part_left;
3127 detail::tgen_ensure_against_bug(r >= 0,
"math: r < 0 in gen_partition");
3129 int nxt_sum = std::min(sum, r);
3130 long double random = next<
long double>(0, 1);
3141 long double val_l = l ? dp_pref[l - 1] : detail::LOG_ZERO,
3143 while (nxt_sum > l
and
3144 dp_pref[nxt_sum - 1] >=
3145 val_r + detail::log_space(random +
3146 (1 - random) * exp(val_l - val_r)))
3149 part.push_back(sum - nxt_sum);
3162 std::optional<
int> part_right = std::nullopt) {
3163 if (!part_right.has_value())
3165 part_right = std::min(*part_right, n);
3167 "math: invalid parameters to gen_partition_fixed_size");
3168 tgen_ensure(
static_cast<
long long>(k) * part_left <= n
and
3169 n <=
static_cast<
long long>(k) * (*part_right),
3170 "math: no such partition");
3173 int s = n - k * part_left;
3175 std::vector<
int> part(k);
3176 if (*part_right == n) {
3178 std::vector<
int> cuts = {-1};
3180 int total = s + k - 1, bars = k - 1;
3181 for (
int i = 0; i < total
and bars > 0; ++i)
3182 if (next<
long double>(0, 1) <
3183 static_cast<
long double>(bars) / (total - i)) {
3187 cuts.push_back(total);
3190 for (
int i = 0; i < k; ++i)
3191 part[i] = cuts[i + 1] - cuts[i] - 1;
3194 int u = *part_right - part_left;
3197 std::vector<std::vector<
long double>> dp(
3198 k + 1, std::vector<
long double>(s + 1, detail::LOG_ZERO));
3199 dp[0][0] = detail::LOG_ONE;
3201 for (
int i = 1; i <= k; ++i) {
3202 std::vector<
long double> pref = dp[i - 1];
3203 for (
int j = 1; j <= s; ++j)
3204 pref[j] = detail::add_log_space(pref[j - 1], dp[i - 1][j]);
3206 for (
int j = 0; j <= s; ++j) {
3209 dp[i][j] = detail::sub_log_space(dp[i][j], pref[j - u - 1]);
3214 int left_to_distribute = s;
3215 for (
int i = k; i >= 1; --i) {
3216 long double log_total = detail::LOG_ZERO;
3217 for (
int j = 0; j <= u
and j <= left_to_distribute; ++j)
3218 log_total = detail::add_log_space(
3219 log_total, dp[i - 1][left_to_distribute - j]);
3220 detail::tgen_ensure_against_bug(
3221 log_total != detail::LOG_ZERO,
3222 "math: total == 0 in gen_partition_fixed_size");
3228 long double random =
3229 detail::log_space(next<
long double>(0, 1)) + log_total;
3231 long double cur_prob = detail::LOG_ZERO;
3233 for (
int j = 0; j <= u
and j <= left_to_distribute; ++j) {
3234 cur_prob = detail::add_log_space(
3235 cur_prob, dp[i - 1][left_to_distribute - j]);
3236 if (random < cur_prob) {
3242 part[k - i] = chosen;
3243 left_to_distribute -= chosen;
3260 uint64_t n,
int k, uint64_t part_left = 0,
3261 std::optional<uint64_t> part_right = std::nullopt) {
3262 if (!part_right.has_value())
3264 part_right = std::min(*part_right, n);
3266 detail::u128 n128 = n;
3267 detail::u128 k128 = k;
3268 detail::u128 part_left128 = part_left;
3269 detail::u128 part_right128 = *part_right;
3272 "math: invalid parameters to gen_partition_fixed_size_fast");
3274 k128 * part_left128 <= n128
and
3275 k128 * part_right128 >= n128,
3276 "math: no such partition");
3278 uint64_t slack_total = n128 - k128 * part_left128;
3279 uint64_t slack_max = part_right128 - part_left128;
3281 std::vector<uint64_t> part(k);
3283 part[0] = slack_total;
3285 std::vector<uint64_t> cuts(k - 1);
3286 for (uint64_t &d : cuts)
3287 d = next<uint64_t>(0, slack_total);
3288 std::sort(cuts.begin(), cuts.end());
3291 for (
int i = 0; i + 1 < k; ++i) {
3292 part[i] = cuts[i] - prev;
3295 part[k - 1] = slack_total - prev;
3298 auto add_part_left = [part_left](uint64_t x) -> uint64_t {
3299 detail::u128 val = x + part_left;
3300 detail::tgen_ensure_against_bug(
3301 val <= std::numeric_limits<uint64_t>::max(),
3302 "math: part + part_left exceeds uint64_t in "
3303 "gen_partition_fixed_size_fast");
3307 if (slack_max >= slack_total) {
3308 for (uint64_t &x : part)
3309 x = add_part_left(x);
3313 detail::u128 remaining = 0;
3314 for (uint64_t &x : part) {
3315 if (x > slack_max) {
3316 remaining += x - slack_max;
3319 x = add_part_left(x);
3322 if (remaining > 0) {
3323 for (uint64_t &x : part) {
3324 if (x < *part_right && remaining > 0) {
3325 detail::u128 room = *part_right - x;
3326 detail::u128 add = std::min(remaining, room);
3327 detail::u128 val = x + add;
3328 detail::tgen_ensure_against_bug(
3330 "math: part exceeds part_right after redistribution in "
3331 "gen_partition_fixed_size_fast");
3336 detail::tgen_ensure_against_bug(
3337 remaining == 0,
"math: remaining mass after redistribution in "
3338 "gen_partition_fixed_size_fast");
3348template <
typename T>
3351 std::optional<uint64_t> max_size = std::nullopt) {
3352 size_t n = elements.size();
3353 tgen_ensure(k > 0,
"math: partition_elements: k must be positive");
3355 "math: partition_elements: min_size must be non-negative");
3357 std::vector<uint64_t> sizes;
3358 if (max_size.has_value()) {
3359 sizes = gen_partition_fixed_size_fast(n, k, min_size, max_size);
3361 for (
int sz : gen_partition_fixed_size(n, k, min_size))
3362 sizes.push_back(sz);
3365 std::vector<std::vector<T>> groups;
3368 for (uint64_t sz : sizes) {
3369 groups.emplace_back(elements.begin() + pos,
3370 elements.begin() + pos + sz);
3379
3380
3381
3382
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3425 std::vector<regex_node> children_;
3426 int left_bound_, right_bound_;
3429 log_space_num_ways_;
3434 regex_node(
const std::string &pattern)
3435 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3436 if (pattern.size() == 1) {
3437 log_space_num_ways_ = math::detail::LOG_ONE;
3440 tgen_ensure_against_bug(pattern[0] ==
'[' and pattern.back() ==
']',
3441 "str: invalid regex: expected character class");
3442 int size = pattern.size() - 2;
3443 log_space_num_ways_ = math::detail::log_space(size);
3444 distinct_ = distinct_container<
char>(pattern.substr(1, size));
3447 regex_node(
const std::string &pattern, std::vector<regex_node> &children)
3448 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3449 if (pattern ==
"SEQ") {
3451 log_space_num_ways_ = math::detail::LOG_ONE;
3452 for (
const auto &child : children)
3453 log_space_num_ways_ += child.log_space_num_ways_;
3454 }
else if (pattern ==
"OR") {
3456 log_space_num_ways_ = math::detail::LOG_ZERO;
3457 for (
const auto &child : children)
3458 log_space_num_ways_ = math::detail::add_log_space(
3459 log_space_num_ways_, child.log_space_num_ways_);
3461 tgen_ensure_against_bug(
"str: invalid regex: expected SEQ or OR");
3463 children_ = std::move(children);
3467 regex_node(
int left_bound,
int right_bound, regex_node &child)
3468 : pattern_(
"REP"), left_bound_(left_bound), right_bound_(right_bound) {
3469 log_space_num_ways_ = math::detail::LOG_ZERO;
3470 for (
int i = left_bound; i <= right_bound; ++i)
3471 log_space_num_ways_ = math::detail::add_log_space(
3472 log_space_num_ways_, i * child.log_space_num_ways_);
3474 children_.push_back(std::move(child));
3480 std::vector<regex_node> cur;
3481 std::vector<regex_node> branches;
3485inline regex_node make_regex_seq(regex_state &st) {
3486 return regex_node(
"SEQ", st.cur);
3490inline regex_node finish_regex_state(regex_state &st) {
3492 if (st.branches.empty())
3493 return make_regex_seq(st);
3496 st.branches.push_back(make_regex_seq(st));
3497 return regex_node(
"OR", st.branches);
3502inline regex_node parse_regex(std::string regex) {
3503 std::string new_regex;
3504 for (
char c : regex)
3507 swap(regex, new_regex);
3509 std::vector<regex_state> stack;
3511 for (size_t i = 0; i < regex.size(); ++i) {
3516 stack.push_back(std::move(cur));
3517 cur = regex_state();
3518 }
else if (c ==
')') {
3520 regex_node node = finish_regex_state(cur);
3522 tgen_ensure(!stack.empty(),
"str: invalid regex: unmatched `)`");
3523 cur = std::move(stack.back());
3526 cur.cur.push_back(std::move(node));
3527 }
else if (c ==
'|') {
3529 regex_node node = make_regex_seq(cur);
3530 cur.branches.push_back(std::move(node));
3531 }
else if (c ==
'[') {
3535 for (++i; i < regex.size()
and regex[i] !=
']'; ++i) {
3536 if (i + 2 < regex.size()
and regex[i + 1] ==
'-') {
3537 char a = regex[i], b = regex[i + 2];
3540 for (
char x = a; x <= b; ++x)
3548 "str: invalid regex: unmatched `[`");
3549 cur.cur.emplace_back(
"[" + chars +
"]");
3550 }
else if (c ==
'{') {
3555 while (i < regex.size()
and
3556 isdigit(
static_cast<
unsigned char>(regex[i]))) {
3560 "str: invalid regex: number too large inside `{}`");
3561 l = 10 * l + (regex[i] -
'0');
3565 if (i < regex.size()
and regex[i] ==
',') {
3567 while (i < regex.size()
and
3568 isdigit(
static_cast<
unsigned char>(regex[i]))) {
3572 r <=
static_cast<
int>(1e8),
3573 "str: invalid regex: number too large inside `{}`");
3574 r = 10 * r + (regex[i] -
'0');
3581 "str: invalid regex: unmatched `{`");
3583 "str: invalid regex: missing number inside `{}`");
3585 "str: invalid regex: invalid range inside `{}`");
3589 "str: invalid regex: expected expression before `{}`");
3591 regex_node rep(l, r, cur.cur.back());
3593 cur.cur.push_back(std::move(rep));
3596 cur.cur.emplace_back(std::string(1, c));
3600 tgen_ensure(stack.empty(),
"str: invalid regex: unmatched `(`");
3601 return finish_regex_state(cur);
3605inline void gen_regex(
const regex_node &node, std::string &str) {
3607 if (node.pattern_[0] ==
'[') {
3608 str += node.pattern_[1 + next<
int>(0, node.pattern_.size() - 3)];
3613 if (node.left_bound_ != -1) {
3617 double log_rand = math::detail::log_space(next<
double>(0, 1)) +
3618 node.log_space_num_ways_;
3619 double cur_prob = math::detail::LOG_ZERO;
3620 double child_num_ways = node.children_[0].log_space_num_ways_;
3622 for (
int i = node.left_bound_; i <= node.right_bound_; ++i) {
3624 math::detail::add_log_space(cur_prob, i * child_num_ways);
3625 if (log_rand <= cur_prob) {
3626 for (
int j = 0; j < i; ++j)
3627 gen_regex(node.children_[0], str);
3632 tgen_ensure_against_bug(
false,
3633 "str: log_rand > cur_prob in REP gen_regex");
3637 if (!node.children_.empty()
and node.pattern_ ==
"SEQ") {
3638 for (
const regex_node &child : node.children_)
3639 gen_regex(child, str);
3644 if (!node.children_.empty()
and node.pattern_ ==
"OR") {
3648 double log_rand = math::detail::log_space(next<
double>(0, 1)) +
3649 node.log_space_num_ways_;
3650 double cur_prob = math::detail::LOG_ZERO;
3652 for (
const regex_node &child : node.children_) {
3653 cur_prob = math::detail::add_log_space(cur_prob,
3654 child.log_space_num_ways_);
3655 if (log_rand <= cur_prob) {
3656 gen_regex(child, str);
3661 tgen_ensure_against_bug(
false,
3662 "str: log_rand > cur_prob in OR gen_regex");
3666 detail::tgen_ensure_against_bug(
3667 node.pattern_.size() == 1,
3668 "str: invalid regex: expected single character, but got `" +
3669 node.pattern_ +
"`");
3670 str += node.pattern_[0];
3674template <
typename... Args>
3675std::string regex_format(
const std::string &s, Args &&...args) {
3676 if constexpr (
sizeof...(Args) == 0) {
3679 int size = std::snprintf(
nullptr, 0, s.c_str(), args...) + 1;
3680 std::string buf(size,
'\0');
3681 std::snprintf(buf.data(), size, s.c_str(), args...);
3690
3691
3694 std::optional<
list<
char>> list_;
3695 std::optional<detail::regex_node>
3700 str(
int size,
char value_left =
'a',
char value_right =
'z') {
3701 tgen_ensure(size > 0,
"str: size must be positive");
3702 list_ = list<
char>(size, value_left, value_right);
3707 str(
int size, std::set<
char> chars) {
3708 tgen_ensure(size > 0,
"str: size must be positive");
3709 list_ = list<
char>(size, chars);
3713 template <
typename... Args>
str(
const std::string ®ex, Args &&...args) {
3714 tgen_ensure(regex.size() > 0,
"str: regex must be non-empty");
3716 root_ = detail::parse_regex(
3717 detail::regex_format(regex, std::forward<Args>(args)...));
3722 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3723 list_->fix(idx, character);
3729 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3730 list_->equal(indices);
3736 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3737 list_->equal(idx_1, idx_2);
3743 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3744 list_->equal_range(left, right);
3750 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3757 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3758 tgen_ensure(0 <= left
and left <= right
and right < list_->size_,
3759 "str: range indices must be valid");
3760 for (
int i = left; i < right - (i - left); ++i)
3767 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3768 return palindrome(0, list_->size_ - 1);
3774 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3775 list_->different(indices);
3781 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3782 list_->different(idx_1, idx_2);
3788 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3789 list_->different_range(left, right);
3795 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3796 list_->all_different();
3802 using tgen_is_sequential_tag = detail::is_sequential_tag;
3804 using value_type =
char;
3805 using std_type = std::string;
3808 value(
const std::string &str) : str_(str) {
3809 tgen_ensure(!str_.empty(),
"str: value: cannot be empty");
3813 int size()
const {
return str_.size(); }
3818 "str: value: index out of bounds");
3821 const char &operator[](
int idx)
const {
3823 "str: value: index out of bounds");
3830 std::sort(str_.begin(), str_.end());
3837 std::reverse(str_.begin(), str_.end());
3844 for (
char &c : str_)
3845 c = std::tolower(c);
3852 for (
char &c : str_)
3853 c = std::toupper(c);
3860 return value(str_ + rhs.str_
);
3866 for (
int i = 0; i < size(); ++i)
3867 std::swap(str_[i], str_[next(0, size() - 1)]);
3877 template <
typename Dist>
3880 "value and distribution must have the same size");
3881 return str_[next_by_distribution(distribution)];
3883 template <
typename Dist>
3884 char pick_by_distribution(
3885 const std::initializer_list<Dist> &distribution)
const {
3886 return pick_by_distribution(std::vector<Dist>(distribution));
3893 "number of elements to choose must be valid");
3894 std::string new_str;
3896 for (
int i = 0; need > 0; ++i) {
3898 if (next(1, left) <= need) {
3899 new_str.push_back(str_[i]);
3907 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
3908 return out << val.str_;
3912 std::string
to_std()
const {
return std_type(str_); }
3921 std::string ret_str;
3922 gen_regex(*root_, ret_str);
3926 std::vector<
char> vec = list_->gen().to_std();
3927 return value(std::string(vec.begin(), vec.end()));
3933
3934
3935
3936
3942template <
typename T> std::pair<T, T> gen_eq(T L1, T R1, T L2, T R2) {
3943 T L = std::max(L1, L2);
3944 T R = std::min(R1, R2);
3946 tgen_ensure(L <= R,
"pair: no valid values to generate");
3947 T x = next<T>(L, R);
3952template <
typename T>
3953std::pair<u128, u128> get_n_and_m(T L1, T R1, T L2, T R2) {
3954 u128 n =
static_cast<i128>(R1) - L1 + 1;
3955 u128 m =
static_cast<i128>(R2) - L2 + 1;
3961static u128 pos_arith_sum(u128 first, u128 last, u128 num_terms) {
3962 u128 x = first + last, y = num_terms;
3975template <
typename T> std::pair<T, T> gen_neq(T L1, T R1, T L2, T R2) {
3976 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
3978 T L_intersect = std::max(L1, L2);
3979 T R_intersect = std::min(R1, R2);
3980 u128 inter =
static_cast<i128>(R_intersect) - L_intersect + 1;
3982 u128 total = n * m - inter;
3983 tgen_ensure(total > 0,
"pair: no valid values to generate");
3988 a = next<T>(L1, R1);
3989 b = next<T>(L2, R2);
4000template <
typename T>
4001std::pair<u128, u128> count_lt_regions(T L1, T R1, T L2, T R2) {
4002 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4005 i128 L_second = std::max<i128>(L2,
static_cast<i128>(L1) + 1);
4009 i128 split = std::min<i128>(R_second, R1);
4012 u128 len1 = std::max<i128>(0, split - L_second + 1);
4014 u128 count_region1 = 0;
4017 i128 first = L_second - L1;
4018 i128 last = split - L1;
4021 count_region1 = pos_arith_sum(first, last, len1);
4026 i128 L_second_region2 = std::max(L_second,
static_cast<i128>(R1) + 1);
4028 u128 len2 = std::max<i128>(0, R_second - L_second_region2 + 1);
4029 u128 count_region2 = len2 * n;
4031 return {count_region1, count_region2};
4036template <
typename T> std::pair<T, T> gen_lt(T L1, T R1, T L2, T R2) {
4037 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4041 i128 L_second = std::max<i128>(L2,
static_cast<i128>(L1) + 1);
4047 i128 split = std::min<i128>(R_second, R1);
4049 auto [count_region1, count_region2] = count_lt_regions(L1, R1, L2, R2);
4050 u128 total = count_region1 + count_region2;
4051 tgen_ensure(total > 0,
"pair: no valid values to generate");
4053 u128 k = detail::next128(total);
4054 if (k < count_region1) {
4058 u128 len1 = std::max<i128>(0, split - L_second + 1);
4065 i128 base = L_second - L1;
4066 i128 lo = 0, hi =
static_cast<i128>(len1) - 1;
4069 i128 mid = lo + (hi - lo) / 2;
4071 if (pos_arith_sum(base, base + mid, mid + 1) <= k)
4080 k -= pos_arith_sum(base, base + d - 1, d);
4082 return {L1 +
static_cast<T>(k), L_second + d};
4088 i128 L_second_region2 = std::max(L_second,
static_cast<i128>(R1) + 1);
4090 return {L1 +
static_cast<T>(k % n),
4091 L_second_region2 +
static_cast<T>(k / n)};
4097template <
typename T> std::pair<T, T> gen_gt(T L1, T R1, T L2, T R2) {
4098 auto [first, second] = gen_lt(L2, R2, L1, R1);
4099 return {second, first};
4104template <
typename T> std::pair<T, T> gen_leq(T L1, T R1, T L2, T R2) {
4106 i128 L_intersect = std::max(L1, L2);
4107 i128 R_intersect = std::min(R1, R2);
4108 u128 eq_count = std::max<i128>(0, R_intersect - L_intersect + 1);
4111 auto [lt_region1, lt_region2] = count_lt_regions(L1, R1, L2, R2);
4112 u128 lt_count = lt_region1 + lt_region2;
4114 u128 total = eq_count + lt_count;
4115 tgen_ensure(total > 0,
"pair: no valid values to generate");
4117 if (detail::next128(total) < eq_count)
4118 return gen_eq(L1, R1, L2, R2);
4119 return gen_lt(L1, R1, L2, R2);
4124template <
typename T> std::pair<T, T> gen_geq(T L1, T R1, T L2, T R2) {
4125 auto [first, second] = gen_leq(L2, R2, L1, R1);
4126 return {second, first};
4132
4133
4134
4135
4138 std::pair<T, T> first_, second_;
4140 enum class restriction_type { eq, neq, lt, gt, leq, geq, unspecified };
4141 restriction_type type_ = restriction_type::unspecified;
4145 pair(T first_left, T first_right, T second_left, T second_right)
4146 : first_(first_left, first_right), second_(second_left, second_right) {
4148 "pair: first range must be valid");
4150 "pair: second range must be valid");
4155 :
pair(both_left, both_right, both_left, both_right) {}
4159 type_ = restriction_type::eq;
4165 type_ = restriction_type::neq;
4171 type_ = restriction_type::lt;
4177 type_ = restriction_type::gt;
4183 type_ = restriction_type::leq;
4189 type_ = restriction_type::geq;
4195 using value_type = T;
4196 using std_type = std::pair<T, T>;
4198 std::pair<T, T> pair_;
4201 value(
const std::pair<T, T> &pair) : pair_(pair), sep_(
' ') {}
4203 : pair_(first, second), sep_(
' ') {}
4215 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
4216 return out << val.pair_.first << val.sep_ << val.pair_.second;
4221 if constexpr (!detail::is_generator_value<T>::value) {
4224 std::pair<
typename T::std_type,
typename T::std_type> pair(
4225 pair_.first.to_std(), pair_.second.to_std());
4234 T L1 = first_.first, R1 = first_.second;
4235 T L2 = second_.first, R2 = second_.second;
4238 case restriction_type::unspecified:
4239 return {next<T>(L1, R1), next<T>(L2, R2)};
4240 case restriction_type::eq:
4241 return detail::gen_eq<T>(L1, R1, L2, R2);
4242 case restriction_type::neq:
4243 return detail::gen_neq<T>(L1, R1, L2, R2);
4244 case restriction_type::lt:
4245 return detail::gen_lt<T>(L1, R1, L2, R2);
4246 case restriction_type::gt:
4247 return detail::gen_gt<T>(L1, R1, L2, R2);
4248 case restriction_type::leq:
4249 return detail::gen_leq<T>(L1, R1, L2, R2);
4250 case restriction_type::geq:
4251 return detail::gen_geq<T>(L1, R1, L2, R2);
4253 throw detail::error(
"pair: unknown restriction type");
4258
4259
4260
4261
4267inline std::vector<std::pair<
int,
int>> edges_from_prufer(std::vector<
int> p) {
4268 int n = p.size() + 2;
4271 std::vector<
int> d(n, 1);
4280 idx = u = find(d.begin(), d.end(), 1) - d.begin();
4283 std::vector<std::pair<
int,
int>> edges;
4285 edges.emplace_back(u, v);
4286 if (--d[v] == 1
and v < idx)
4289 idx = u = find(d.begin() + idx + 1, d.end(), 1) - d.begin();
4296 std::vector<
int> parent_;
4297 std::vector<
unsigned char> rank_;
4302 dsu(
int n) : parent_(n), rank_(n, 0) {
4303 for (
int i = 0; i < n; ++i)
4309 void add_elements(
int k) {
4310 for (
int i = 0; i < k; ++i) {
4311 int new_id = parent_.size();
4312 parent_.push_back(new_id);
4320 return parent_[i] == i ? i : parent_[i] = find(parent_[i]);
4326 bool unite(
int a,
int b) {
4331 if (rank_[a] > rank_[b])
4334 if (rank_[a] == rank_[b])
4343template <
typename VWeight,
typename EWeight>
struct wgraph;
4346
4347
4348
4349
4350
4351
4352
4353
4355template <
typename VWeight,
typename EWeight>
4358 std::set<std::pair<
int,
int>> edges_;
4363 tgen_ensure(n > 0,
"wtree: number of vertices must be positive");
4369 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n_,
4370 "wtree: vertices must be indexed in [0, n)");
4371 tgen_ensure(u != v,
"wtree: cannot add self loop to tree");
4375 edges_.emplace(u, v);
4387 std::vector<std::set<
int>> adj_;
4388 std::vector<std::pair<
int,
int>> edges_;
4391 std::optional<
int> print_parents_;
4393 std::optional<std::vector<VWeight>> vertex_weights_;
4394 std::optional<std::vector<EWeight>>
4400 value(
const std::vector<std::set<
int>> &adj)
4401 : n_(
static_cast<
int>(adj.size())),
adj_(
adj), add_1_(
false),
4402 print_n_(
false),
dsu_(
n_) {
4403 for (
int u = 0; u < n_; ++u)
4404 for (
auto v : adj[u]) {
4407 "wtree: value: vertices must be indexed in [0, n)");
4410 edges_.emplace_back(u, v);
4413 "wtree: value: initial graph must form a tree");
4420 value(
int n,
const std::vector<std::pair<
int,
int>> &edges)
4421 : n_(n),
adj_(
n), add_1_(
false), print_n_(
false),
dsu_(
n) {
4422 edges_.reserve(edges.size());
4423 for (
auto [u, v] : edges) {
4424 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n,
4425 "wtree: value: vertices must be indexed in [0, n)");
4427 "wtree: value: initial graph must form a tree");
4430 edges_.emplace_back(u, v);
4435 value(
int n,
const std::set<std::pair<
int,
int>> &edges)
4438 value(
int n,
const std::initializer_list<std::pair<
int,
int>> &edges)
4439 : value(n, std::vector<std::pair<
int,
int>>(edges)) {}
4444 value(
const typename wgraph<VWeight, EWeight>::value &g);
4448 template <
typename NewVWeight,
typename NewEWeight>
4449 typename wtree<NewVWeight, NewEWeight>::value
4450 convert_weight_types()
const {
4452 !edge_weights_.has_value(),
4453 "wtree: value: cannot convert weight type after "
4454 "assigning weights");
4456 typename wtree<NewVWeight, NewEWeight>::value new_tree(adj_);
4457 new_tree.add_1_ = add_1_;
4458 new_tree.print_n_ = print_n_;
4459 new_tree.print_parents_ = print_parents_;
4464 int n()
const {
return n_; }
4474 return vertex_weights_;
4479 return edge_weights_;
4484 template <
typename NewVWeight = VWeight>
4486 const std::vector<NewVWeight> &vertex_weights)
const {
4488 "wtree: value: must give `n` vertex weights");
4490 auto new_tree = convert_weight_types<NewVWeight, EWeight>();
4491 new_tree.vertex_weights_ = vertex_weights;
4497 template <
typename NewEWeight = EWeight>
4501 edge_weights.size() == edges().size(),
4502 "wtree: value: must give `edges().size()` edge weights");
4504 auto new_tree = convert_weight_types<VWeight, NewEWeight>();
4505 new_tree.edge_weights_ = edge_weights;
4513 "wtree: value: edge_weighted requires a tree with no "
4516 "wtree: value: tree is already edge-weighted");
4518 edge_weights_ = std::vector<EWeight>();
4542 "wtree: value: root must be -1, `n`, or in [0, n)");
4543 print_parents_ = root;
4556 std::vector<
int> new_label(
n());
4557 std::vector<
int> shuffled;
4558 for (
int i = 0; i <
n(); ++i) {
4559 if (indices.count(i))
4562 shuffled.push_back(i);
4564 std::vector<
int> targets = shuffled;
4565 tgen::shuffle(targets.begin(), targets.end());
4566 for (size_t k = 0; k < shuffled.size(); ++k)
4567 new_label[shuffled[k]] = targets[k];
4570 std::vector<std::set<
int>> new_adj(
n());
4571 for (
int u = 0; u < n(); ++u)
4572 for (
int v : adj_[u])
4573 new_adj[new_label[u]].insert(new_label[v]);
4574 adj_ = std::move(new_adj);
4577 for (
auto &[u, v] : edges_) {
4585 if (vertex_weights_.has_value()) {
4586 std::vector<VWeight> new_vw(
n());
4587 for (
int i = 0; i < n(); ++i)
4588 new_vw[new_label[i]] = (*vertex_weights_)[i];
4589 vertex_weights_ = std::move(new_vw);
4593 dsu_ = detail::dsu(n());
4594 for (
auto [u, v] : edges_)
4599 std::vector<
int> perm(edges_.size());
4600 std::iota(perm.begin(), perm.end(), 0);
4601 tgen::shuffle(perm.begin(), perm.end());
4603 std::vector<std::pair<
int,
int>> new_edges;
4604 std::optional<std::vector<EWeight>> new_ew;
4605 if (edge_weights_.has_value())
4606 new_ew = std::vector<EWeight>();
4607 for (
int i : perm) {
4608 new_edges.push_back(edges_[i]);
4609 if (new_ew.has_value())
4610 new_ew->push_back((*edge_weights_)[i]);
4613 if (new_ew.has_value())
4614 edge_weights_ = new_ew;
4625 value &add_edge(
int u,
int v, std::optional<EWeight> w = std::nullopt) {
4627 "wtree: value: vertex ids must be valid");
4632 if (adj_[u].count(v))
4637 edges_.emplace_back(u, v);
4639 "wtree: value: added edge must not create a cycle");
4641 if (w.has_value()) {
4643 "wtree: value: cannot add weighted edge to "
4644 "edge-unweighted tree");
4646 edge_weights_->push_back(*w);
4649 "wtree: value: cannot add unweighted edge to "
4650 "edge-weighted tree");
4660 std::optional<EWeight> new_w = std::nullopt) {
4663 "wtree: value: vertex ids must be valid");
4667 add_vertices(rhs.n(), rhs.vertex_weights());
4668 for (
int i = 0; i <
static_cast<
int>(rhs.edges().size()); ++i) {
4669 auto [u, v] = rhs.edges()[i];
4670 add_edge(shift + u, shift + v,
4671 rhs.edge_weights().has_value()
4672 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4677 add_edge(new_u, shift + new_v, new_w);
4687 std::set<std::pair<
int,
int>> index_pairs) {
4689 std::set<
int> idx_left, idx_right;
4690 std::vector<
int> right_id_to_left(rhs
.n(), -1);
4691 for (
auto [l, r] : index_pairs) {
4693 0 <= l
and l < n()
and 0 <= r
and r < rhs.n(),
4694 "wtree: value: vertex indices to glue must be valid");
4695 tgen_ensure(idx_left.count(l) == 0
and idx_right.count(r) == 0,
4696 "wtree: value: must not have repeated indices "
4697 "on the same side to glue");
4700 idx_right.insert(r);
4701 right_id_to_left[r] = l;
4705 std::vector<
int> new_right_id(rhs
.n(), -1);
4706 int intersection_lt = 0;
4707 std::optional<std::vector<VWeight>> rhs_vertex_weights;
4708 for (
int i = 0; i < rhs
.n(); ++i) {
4709 if (right_id_to_left[i] != -1) {
4712 new_right_id[i] = right_id_to_left[i];
4715 new_right_id[i] =
n() + i - intersection_lt;
4716 if (rhs.vertex_weights().has_value()) {
4717 if (!rhs_vertex_weights.has_value())
4718 rhs_vertex_weights = std::vector<VWeight>();
4719 rhs_vertex_weights->push_back(
4720 (*rhs.vertex_weights())[i]);
4726 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
4727 for (
int i = 0; i <
static_cast<
int>(rhs.edges().size()); ++i) {
4728 auto [u, v] = rhs.edges()[i];
4729 add_edge(new_right_id[u], new_right_id[v],
4730 rhs.edge_weights().has_value()
4731 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4738 std::initializer_list<std::pair<
int,
int>> il) {
4739 return glue(rhs, std::set<std::pair<
int,
int>>(il));
4747 std::set<std::pair<
int,
int>> index_pairs;
4748 for (
auto i : indices)
4749 index_pairs.emplace(i, i);
4750 return glue(rhs, index_pairs);
4752 value &glue(
const value &rhs,
const std::initializer_list<
int> &il) {
4753 return glue(rhs, std::set<
int>(il));
4758 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
4760 out << val.n() <<
'\n';
4763 if (val.vertex_weights()) {
4764 for (
int i = 0; i < val.n(); ++i) {
4767 out << (*val.vertex_weights())[i];
4772 tgen_ensure(
static_cast<
int>(val.edges().size()) == val.n() - 1,
4773 "wtree: value: invalid tree to print (number of edges "
4774 "must be `n` - 1)");
4777 if (val.print_parents_.has_value()) {
4779 "wtree: value: cannot print parent style if edges "
4782 int root = *val.print_parents_;
4783 bool skip_parent_0 = root == -1;
4786 if (root == val.n())
4787 root = next(0, val.n() - 1);
4789 std::vector<
int> parent(val.n(), -1);
4792 std::vector<
int> vis(val.n(),
false);
4799 for (
int v : val.adj()[u])
4807 if (skip_parent_0) {
4808 for (
int i = 1; i < val.n(); ++i) {
4811 "wtree: value: parent of i must be less than i for "
4812 "printing in parent style if root is -1");
4816 out << parent[i] + val.add_1_;
4819 for (
int i = 0; i < val.n(); ++i) {
4822 out << (parent[i] == -1 ? -1 : parent[i]) + val.add_1_;
4831 for (
int i = 0; i <
static_cast<
int>(val.edges().size()); ++i) {
4832 auto [u, v] = val.edges()[i];
4833 out << (u + val.add_1_) <<
" " << (v + val.add_1_);
4836 if (val.edge_weights().has_value())
4837 out <<
" " << (*val.edge_weights())[i];
4847 return std_type(n_, adj_);
4854 value &add_vertices(
int k, std::optional<std::vector<VWeight>>
4855 new_vertex_weights = std::nullopt) {
4858 if (new_vertex_weights.has_value()) {
4860 "wtree: value: cannot add weighted vertices to "
4861 "vertex-unweighted tree");
4863 static_cast<
int>(new_vertex_weights->size()) == k,
4864 "wtree: value: number of vertex weights must be equal "
4865 "to number of added vertices");
4867 vertex_weights_->insert(vertex_weights_->end(),
4868 new_vertex_weights->begin(),
4869 new_vertex_weights->end());
4872 "wtree: value: cannot add unweighted vertices to "
4873 "vertex-weighted tree");
4875 dsu_.add_elements(k);
4885 std::vector<std::vector<
int>> adj(n_);
4886 for (
auto [u, v] : edges_) {
4887 adj[u].push_back(v);
4888 adj[v].push_back(u);
4891 std::vector<
int> comp_size;
4892 std::vector<std::vector<
int>> component_ids;
4893 std::vector<
bool> vis(n_,
false);
4896 for (
int i = 0; i < n_; ++i) {
4902 comp_size.push_back(0);
4903 component_ids.emplace_back();
4908 component_ids.back().push_back(u);
4909 for (
int v : adj[u]) {
4920 std::vector<std::pair<
int,
int>> new_edges(edges_.begin(),
4922 if (comp_size.size() > 1) {
4923 std::vector<
int> prufer_values =
4924 many_by_distribution(comp_size.size() - 2, comp_size);
4925 for (
auto [u, v] : detail::edges_from_prufer(prufer_values))
4926 new_edges.emplace_back(pick(component_ids[u]),
4927 pick(component_ids[v]));
4930 return value(n_, new_edges);
4941 std::vector<std::pair<
int,
int>> edges;
4942 for (
int i = 1; i < n; ++i)
4943 edges.emplace_back(i, wnext<
int>(i, elongation));
4944 return value(n, edges);
4951 tgen_ensure(n > 0,
"wtree: gen_kruskal: n must be positive");
4953 return value(1, {});
4955 detail::dsu components(n);
4956 std::vector<std::pair<
int,
int>> edges;
4957 edges.reserve(n - 1);
4958 while (edges.size() < size_t(n - 1)) {
4959 int u = next(0, n - 1);
4960 int v = next(0, n - 1);
4963 if (components.unite(u, v))
4964 edges.emplace_back(u, v);
4966 return value(n, edges);
4971
4972
4984
4985
4986
4987
4993inline uint64_t undirected_edge_key(
int u,
int v) {
4996 return (
static_cast<uint64_t>(u) << 32) |
4997 static_cast<uint64_t>(
static_cast<uint32_t>(v));
5002inline uint64_t directed_edge_key(
int u,
int v) {
5003 return (
static_cast<uint64_t>(u) << 32) |
5004 static_cast<uint64_t>(
static_cast<uint32_t>(v));
5009inline long long max_graph_edges(
int n,
bool directed,
bool self_loops) {
5013 return self_loops ?
static_cast<
long long>(n) * n
5014 :
static_cast<
long long>(n) * (n - 1);
5015 return self_loops ?
static_cast<
long long>(n) * (n + 1) / 2
5016 :
static_cast<
long long>(n) * (n - 1) / 2;
5021inline std::pair<
int,
int> get_random_graph_edge(
int n,
bool directed,
5025 return {next<
int>(0, n - 1), next<
int>(0, n - 1)};
5026 int u = next<
int>(0, n - 1);
5027 int v = next<
int>(0, n - 1);
5029 v = next<
int>(0, n - 1);
5033 int u = next<
int>(0, n - 1);
5034 int v = next<
int>(0, n - 1);
5039 int u = next<
int>(0, n - 1);
5040 int v = next<
int>(0, n - 1);
5042 v = next<
int>(0, n - 1);
5051inline std::pair<
int,
int> decode_undirected_simple_edge(
int n,
long long idx) {
5052 auto base = [&](
int u) ->
long long {
5053 return static_cast<
long long>(u) * (n - 1) -
5054 static_cast<
long long>(u) * (u - 1) / 2;
5056 int lo = 0, hi = n - 2;
5058 int mid = (lo + hi + 1) / 2;
5059 if (base(mid) <= idx)
5064 return {lo, lo + 1 +
int(idx - base(lo))};
5070inline std::pair<
int,
int> decode_undirected_loops_edge(
int n,
long long idx) {
5071 auto base = [&](
int u) ->
long long {
5072 return static_cast<
long long>(u) * n -
5073 static_cast<
long long>(u) * (u - 1) / 2;
5075 int lo = 0, hi = n - 1;
5077 int mid = (lo + hi + 1) / 2;
5078 if (base(mid) <= idx)
5083 return {lo, lo +
int(idx - base(lo))};
5088inline std::pair<
int,
int> decode_directed_simple_edge(
int n,
long long idx) {
5089 int u = idx / (n - 1);
5090 int rem = idx % (n - 1);
5091 return {u, rem + (rem >= u)};
5096inline std::pair<
int,
int>
5097decode_graph_edge_index(
int n,
long long idx,
bool directed,
bool self_loops) {
5100 return {
int(idx / n),
int(idx % n)};
5101 return decode_directed_simple_edge(n, idx);
5104 return decode_undirected_loops_edge(n, idx);
5105 return decode_undirected_simple_edge(n, idx);
5111
5112
5113
5114
5115
5116
5117
5118
5120template <
typename VWeight,
typename EWeight>
5123 std::set<std::pair<
int,
int>> edges_;
5125 bool has_self_loops_;
5131 wgraph(
int n,
int m,
bool is_directed =
false,
bool has_self_loops =
false)
5132 : n_(n), m_(m), is_directed_(is_directed),
5133 has_self_loops_(has_self_loops) {
5134 tgen_ensure(n > 0,
"wgraph: number of vertices must be positive");
5140 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n_,
5141 "wgraph: vertices must be indexed in [0, n)");
5143 if (!is_directed_
and u > v)
5145 edges_.emplace(u, v);
5146 tgen_ensure(
static_cast<
int>(edges_.size()) <= m_,
5147 "wgraph: too many edges were added");
5161 std::vector<std::set<
int>> adj_;
5162 std::vector<std::pair<
int,
int>> edges_;
5166 mutable bool adj_built_{
5169 std::optional<std::vector<VWeight>> vertex_weights_;
5170 std::optional<std::vector<EWeight>>
5176 value(
const std::vector<std::set<
int>> &adj,
bool is_directed =
false)
5177 : n_(
static_cast<
int>(adj.size())),
adj_(
adj),
5178 is_directed_(is_directed), add_1_(
false), print_nm_(
false),
5180 for (
int u = 0; u < n_; ++u)
5181 for (
auto v : adj[u]) {
5184 "wgraph: value: vertices must be indexed in [0, n)");
5188 if (is_directed_
or u <= v)
5189 edges_.emplace_back(u, v);
5197 value(
int n,
const std::vector<std::pair<
int,
int>> &edges = {},
5198 bool is_directed =
false)
5199 : n_(n),
edges_(), is_directed_(is_directed), add_1_(
false),
5200 print_nm_(
false), adj_built_(
false) {
5201 edges_.reserve(edges.size());
5202 std::unordered_set<uint64_t> seen;
5203 seen.reserve(edges.size() * 2 + 1);
5204 for (
auto [u, v] : edges) {
5206 0 <= std::min(u, v)
and std::max(u, v) < n,
5207 "wgraph: value: vertices must be indexed in [0, n)");
5208 if (!is_directed_
and u > v)
5210 uint64_t key = is_directed_ ? detail::directed_edge_key(u, v)
5211 : detail::undirected_edge_key(u, v);
5212 if (seen.insert(key).second)
5213 edges_.emplace_back(u, v);
5216 value(
int n,
const std::set<std::pair<
int,
int>> &edges,
5217 bool is_directed =
false)
5222 value(
int n,
const std::initializer_list<std::pair<
int,
int>> &edges,
5223 bool is_directed =
false)
5224 : value(n, std::vector<std::pair<
int,
int>>(edges), is_directed) {}
5229 :
value(t.n(), t.edges(),
false) {
5230 if (t.vertex_weights().has_value()) {
5231 vertex_weights_ = *t.vertex_weights();
5233 if (t.edge_weights().has_value()) {
5234 edge_weights_ = *t.edge_weights();
5240 template <
typename NewVWeight,
typename NewEWeight>
5241 typename wgraph<NewVWeight, NewEWeight>::value
5242 convert_weight_types()
const {
5244 !edge_weights_.has_value(),
5245 "wgraph: value: cannot convert weight type after "
5246 "assigning weights");
5249 typename wgraph<NewVWeight, NewEWeight>::value new_graph(
5250 adj_, is_directed_);
5251 new_graph.is_directed_ = is_directed_;
5252 new_graph.add_1_ = add_1_;
5253 new_graph.print_nm_ = print_nm_;
5258 int n()
const {
return n_; }
5261 int m()
const {
return edges_.size(); }
5277 return vertex_weights_;
5282 return edge_weights_;
5287 template <
typename NewVWeight = VWeight>
5289 const std::vector<NewVWeight> &vertex_weights)
const {
5291 "wgraph: value: must give `n` vertex weights");
5293 auto new_graph = convert_weight_types<NewVWeight, EWeight>();
5294 new_graph.vertex_weights_ = vertex_weights;
5300 template <
typename NewEWeight = EWeight>
5304 "wgraph: value: must give `m` edge weights");
5306 auto new_graph = convert_weight_types<VWeight, NewEWeight>();
5307 new_graph.edge_weights_ = edge_weights;
5315 "wgraph: value: edge_weighted requires a graph with no "
5318 "wgraph: value: graph is already edge-weighted");
5320 edge_weights_ = std::vector<EWeight>();
5348 std::vector<
int> new_label(
n());
5349 std::vector<
int> shuffled;
5350 for (
int i = 0; i <
n(); ++i) {
5351 if (indices.count(i))
5354 shuffled.push_back(i);
5356 std::vector<
int> targets = shuffled;
5357 tgen::shuffle(targets.begin(), targets.end());
5358 for (size_t k = 0; k < shuffled.size(); ++k)
5359 new_label[shuffled[k]] = targets[k];
5362 std::vector<std::set<
int>> new_adj(
n());
5363 for (
int u = 0; u < n(); ++u)
5364 for (
int v : adj_[u])
5365 new_adj[new_label[u]].insert(new_label[v]);
5369 for (
auto &[u, v] : edges_) {
5372 if (!is_directed_
and u > v)
5377 if (vertex_weights_.has_value()) {
5378 std::vector<VWeight> new_vw(
n());
5379 for (
int i = 0; i < n(); ++i)
5380 new_vw[new_label[i]] = (*vertex_weights_)[i];
5381 vertex_weights_ = new_vw;
5386 std::vector<
int> perm(edges_.size());
5387 std::iota(perm.begin(), perm.end(), 0);
5388 tgen::shuffle(perm.begin(), perm.end());
5390 std::vector<std::pair<
int,
int>> new_edges;
5391 std::optional<std::vector<EWeight>> new_ew;
5392 if (edge_weights_.has_value())
5393 new_ew = std::vector<EWeight>();
5394 for (
int i : perm) {
5395 new_edges.push_back(edges_[i]);
5396 if (new_ew.has_value())
5397 new_ew->push_back((*edge_weights_)[i]);
5401 if (new_ew.has_value())
5402 edge_weights_ = new_ew;
5415 new_vertex_weights = std::nullopt) {
5419 if (new_vertex_weights.has_value()) {
5421 "wgraph: value: cannot add weighted vertices to "
5422 "vertex-unweighted graph");
5424 static_cast<
int>(new_vertex_weights->size()) == k,
5425 "wgraph: value: number of vertex weights must be equal "
5426 "to number of added vertices");
5428 vertex_weights_->insert(vertex_weights_->end(),
5429 new_vertex_weights->begin(),
5430 new_vertex_weights->end());
5433 "wgraph: value: cannot add unweighted vertices to "
5434 "vertex-weighted graph");
5444 "wgraph: value: vertex ids must be valid");
5449 if (adj_[u].count(v))
5455 edges_.emplace_back(u, v);
5457 if (w.has_value()) {
5459 "wgraph: value: cannot add weighted edge to "
5460 "edge-unweighted graph");
5462 edge_weights_->push_back(*w);
5465 "wgraph: value: cannot add unweighted edge to "
5466 "edge-weighted graph");
5476 std::optional<EWeight> new_w = std::nullopt) {
5479 "wgraph: value: vertex ids must be valid");
5483 add_vertices(rhs.n(), rhs.vertex_weights());
5484 for (
int i = 0; i < rhs
.m(); ++i) {
5485 auto [u, v] = rhs.edges()[i];
5487 rhs.edge_weights().has_value()
5488 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5503 std::set<std::pair<
int,
int>> index_pairs) {
5506 "wgraph: value: graphs must have the same is_directed value");
5509 std::set<
int> idx_left, idx_right;
5510 std::vector<
int> right_id_to_left(rhs
.n(), -1);
5511 for (
auto [l, r] : index_pairs) {
5513 0 <= l
and l < n()
and 0 <= r
and r < rhs.n(),
5514 "wgraph: value: vertex indices to glue must be valid");
5515 tgen_ensure(idx_left.count(l) == 0
and idx_right.count(r) == 0,
5516 "wgraph: value: must not have repeated indices "
5517 "on the same side to glue");
5520 idx_right.insert(r);
5521 right_id_to_left[r] = l;
5525 std::vector<
int> new_right_id(rhs
.n(), -1);
5526 int intersection_lt = 0;
5527 std::optional<std::vector<VWeight>> rhs_vertex_weights;
5528 for (
int i = 0; i < rhs
.n(); ++i) {
5529 if (right_id_to_left[i] != -1) {
5532 new_right_id[i] = right_id_to_left[i];
5535 new_right_id[i] =
n() + i - intersection_lt;
5536 if (rhs.vertex_weights().has_value()) {
5537 if (!rhs_vertex_weights.has_value())
5538 rhs_vertex_weights = std::vector<VWeight>();
5539 rhs_vertex_weights->push_back(
5540 (*rhs.vertex_weights())[i]);
5546 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
5547 for (
int i = 0; i < rhs
.m(); ++i) {
5548 auto [u, v] = rhs.edges()[i];
5550 rhs.edge_weights().has_value()
5551 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5558 std::initializer_list<std::pair<
int,
int>> il) {
5559 return glue(rhs, std::set<std::pair<
int,
int>>(il));
5567 std::set<std::pair<
int,
int>> index_pairs;
5568 for (
auto i : indices)
5569 index_pairs.emplace(i, i);
5570 return glue(rhs, index_pairs);
5572 value &glue(
const value &rhs,
const std::initializer_list<
int> &il) {
5573 return glue(rhs, std::set<
int>(il));
5580 return glue(rhs, std::set<
int>());
5588 "wgraph: value: can choose at most `m` edges from graph");
5590 std::vector<std::pair<
int,
int>> new_edges;
5591 std::optional<std::vector<EWeight>> new_edge_weights;
5594 for (
int i = 0; i <
m(); ++i) {
5595 if (next(1, left--) <= num_edges) {
5596 new_edges.push_back(edges()[i]);
5597 if (edge_weights_.has_value()) {
5598 if (!new_edge_weights.has_value())
5599 new_edge_weights = std::vector<EWeight>();
5600 new_edge_weights->push_back((*edge_weights())[i]);
5607 edge_weights_ = new_edge_weights;
5608 rebuild_adj_from_edge_list();
5620 "wgraph: value: random_connected_subgraph is only for "
5621 "undirected graphs");
5624 "wgraph: value: can choose at most `m` edges from graph");
5628 std::vector<std::vector<std::pair<
int,
int>>> incident(
n());
5629 for (
int i = 0; i <
m(); ++i) {
5630 auto [u, v] = edges_[i];
5631 incident[u].emplace_back(v, i);
5632 incident[v].emplace_back(u, i);
5636 std::vector<
bool> vis(
n(),
false);
5637 std::vector<
int> queue;
5638 std::vector<
bool> in_tree(
m(),
false);
5639 int forest_edges = 0;
5641 for (
int start = 0; start <
n(); ++start) {
5645 queue.push_back(start);
5647 while (!queue.empty()) {
5648 int i = tgen::next<
int>(0, queue.size() - 1);
5650 std::swap(queue[i], queue.back());
5653 for (
auto [v, edge_idx] : incident[u]) {
5657 in_tree[edge_idx] =
true;
5664 num_edges >= forest_edges,
5665 "wgraph: value: random_connected_subgraph needs at least "
5666 "`n - c` edges, where `c` is the number of connected "
5670 std::vector<
int> tree_idx, rest_idx;
5671 for (
int i = 0; i <
m(); ++i) {
5673 tree_idx.push_back(i);
5675 rest_idx.push_back(i);
5678 tgen::shuffle(rest_idx.begin(), rest_idx.end());
5680 std::vector<
int> chosen_idx;
5681 chosen_idx.insert(chosen_idx.end(), tree_idx.begin(),
5683 chosen_idx.insert(chosen_idx.end(), rest_idx.begin(),
5684 rest_idx.begin() + num_edges - forest_edges);
5686 detail::tgen_ensure_against_bug(
5687 static_cast<
int>(chosen_idx.size()) == num_edges,
5688 "wgraph: value: chose a wrong number of edges");
5690 std::vector<std::pair<
int,
int>> new_edges;
5691 std::optional<std::vector<EWeight>> new_edge_weights;
5692 if (edge_weights_.has_value())
5693 new_edge_weights = std::vector<EWeight>();
5694 for (
int i : chosen_idx) {
5695 new_edges.push_back(edges_[i]);
5696 if (new_edge_weights.has_value())
5697 new_edge_weights->push_back((*edge_weights_)[i]);
5701 edge_weights_ = new_edge_weights;
5702 rebuild_adj_from_edge_list();
5710 "wgraph: value: cannot compute complement of "
5711 "edge-weighted graph");
5713 value complement = *
this;
5714 complement.ensure_adj_built();
5715 std::vector<std::pair<
int,
int>> compl_edges;
5716 for (
int i = 0; i < complement.n_; ++i) {
5717 std::set<
int> complement_adj;
5718 for (
int j = 0; j < complement.n_; ++j) {
5720 if (j == i
and complement.adj_[i].count(j))
5722 if (j != i
and !complement.adj_[i].count(j))
5726 complement_adj.insert(j);
5728 if (i <= j
or complement.is_directed_) {
5729 compl_edges.emplace_back(i, j);
5733 std::swap(complement.adj_[i], complement_adj);
5735 std::swap(complement.edges_, compl_edges);
5744 "wgraph: value: graphs must have the same "
5745 "is_directed value");
5748 rhs.vertex_weights().has_value(),
5749 "wgraph: value: cannot concatenate vertex-weighted "
5750 "wgraph to unweighted");
5752 rhs.edge_weights().has_value(),
5753 "wgraph: value: cannot concatenate edge-weighted "
5754 "wgraph to unweighted");
5756 value concat = *
this;
5757 concat.glue(rhs, std::set<std::pair<
int,
int>>());
5758 concat.add_1_ = add_1_ | rhs.add_1_;
5759 concat.print_nm_ = print_nm_ | rhs.print_nm_;
5766 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
5769 out << val.n() <<
" " << val.m() <<
'\n';
5772 if (val.vertex_weights()) {
5773 for (
int i = 0; i < val.n(); ++i) {
5776 out << (*val.vertex_weights())[i];
5782 for (
int i = 0; i < val.m(); ++i) {
5783 auto [u, v] = val.edges()[i];
5784 out << (u + val.add_1_) <<
" " << (v + val.add_1_);
5787 if (val.edge_weights().has_value())
5788 out <<
" " << (*val.edge_weights())[i];
5799 return std_type(n_, m(), adj_);
5806 void rebuild_adj_from_edge_list() {
5807 adj_.assign(n_, {});
5808 for (
auto [u, v] : edges_) {
5818 void ensure_adj_built()
const {
5821 const_cast<
value *>(
this)->rebuild_adj_from_edge_list();
5829 "wgraph: graphs must have the same is_directed value");
5831 for (
auto [u, v] : rhs.edges())
5841 detail::tgen_ensure_against_bug(
static_cast<
int>(edges_.size()) <= m_,
5842 "wgraph: too many edges were added");
5845 if (
static_cast<
int>(edges_.size()) == m_)
5846 return value(n_, edges_, is_directed_);
5851 if (
auto indexed = try_gen_by_edge_index())
5855 return gen_remaining_edges(
5856 std::vector<std::pair<
int,
int>>(edges_.begin(), edges_.end()));
5866 "wgraph: get_connected is only for undirected graphs");
5868 "wgraph: connected graph needs at least n - 1 edges");
5870 std::vector<std::pair<
int,
int>> edges;
5873 if (edges_.empty()) {
5875 std::vector<
int> prufer(n_ - 2);
5876 for (
int i = 0; i < n_ - 2; ++i)
5877 prufer[i] = next<
int>(0, n_ - 1);
5878 for (
auto [u, v] : detail::edges_from_prufer(std::move(prufer)))
5879 edges.emplace_back(u, v);
5882 edges.assign(edges_.begin(), edges_.end());
5884 std::vector<std::vector<
int>> adj(n_);
5885 for (
auto [u, v] : edges_) {
5886 adj[u].push_back(v);
5887 adj[v].push_back(u);
5890 std::vector<
int> comp_size;
5891 std::vector<std::vector<
int>> component_ids;
5892 std::vector<
bool> vis(n_,
false);
5895 for (
int i = 0; i < n_; ++i) {
5901 comp_size.push_back(0);
5902 component_ids.emplace_back();
5907 component_ids.back().push_back(u);
5908 for (
int v : adj[u]) {
5917 if (component_ids.size() > 1) {
5918 std::vector<
int> prufer_values =
5919 many_by_distribution(component_ids.size() - 2, comp_size);
5921 detail::edges_from_prufer(std::move(prufer_values)))
5922 edges.emplace_back(pick(component_ids[u]),
5923 pick(component_ids[v]));
5927 return gen_remaining_edges(std::move(edges));
5940 "wgraph: get_acyclic is only for directed graphs");
5942 if (edges_.empty()) {
5943 std::vector<
int> order(n_);
5944 std::iota(order.begin(), order.end(), 0);
5945 for (
int i = n_ - 1; i > 0; --i)
5946 std::swap(order[i], order[next(0, i)]);
5948 const long long max_pairs =
5949 static_cast<
long long>(n_) * (n_ - 1) / 2;
5951 "wgraph: not enough edges to generate");
5953 std::vector<std::pair<
int,
int>> edges;
5955 for (
long long idx : distinct_range<
long long>(0, max_pairs - 1)
5958 auto [i, j] = detail::decode_undirected_simple_edge(n_, idx);
5959 edges.emplace_back(order[i], order[j]);
5961 return value(n_, edges,
true);
5964 std::vector<std::vector<
int>> adj(n_);
5965 std::vector<
int> indeg(n_, 0);
5966 for (
auto [u, v] : edges_) {
5967 adj[u].push_back(v);
5971 std::vector<
int> available;
5972 for (
int i = 0; i < n_; ++i)
5974 available.push_back(i);
5977 std::vector<
int> order;
5978 while (!available.empty()) {
5979 int idx = next(0,
static_cast<
int>(available.size()) - 1);
5980 int u = available[idx];
5981 std::swap(available[idx], available.back());
5982 available.pop_back();
5985 for (
int v : adj[u])
5986 if (--indeg[v] == 0)
5987 available.push_back(v);
5991 "wgraph: preset edges contain a directed cycle");
5993 value acyclic(n_, edges_,
true);
5997 detail::tgen_ensure_against_bug(acyclic.m() <= m_,
5998 "wgraph: too many edges were added");
6000 if (acyclic.m() < m_) {
6001 std::vector<
int> order_pos(n_);
6002 for (
int i = 0; i < n_; ++i)
6003 order_pos[order[i]] = i;
6005 std::unordered_set<uint64_t> seen;
6006 seen.reserve(m_ * 2);
6007 for (
auto [u, v] : acyclic.edges())
6009 detail::undirected_edge_key(order_pos[u], order_pos[v]));
6011 const long long max_pairs =
6012 static_cast<
long long>(n_) * (n_ - 1) / 2;
6013 while (acyclic.m() < m_) {
6014 std::pair<
int,
int> edge;
6015 if (!detail::try_generate_distinct(seen, [&] {
6016 long long idx = next<
long long>(0, max_pairs - 1);
6017 edge = detail::decode_undirected_simple_edge(n_, idx);
6018 return detail::undirected_edge_key(edge.first,
6021 throw detail::error(
"wgraph: not enough edges to generate");
6022 acyclic.add_edge(order[edge.first], order[edge.second]);
6042 bool is_directed =
false) {
6045 "wgraph: skewed graph needs at least n - 1 edges to be connected");
6047 "wgraph: gen_skewed spread must be at least 2");
6049 value skewed(n, {}, is_directed);
6051 std::vector<
int> parent(n), depth(n, 0);
6053 for (
int i = 1; i < n; ++i) {
6054 int p = wnext<
int>(i, elongation);
6056 depth[i] = depth[p] + 1;
6057 skewed.add_edge(p, i);
6060 const int extra = m - (n - 1);
6067 constexpr int naive_ancestor_spread = 20;
6069 if (spread <= naive_ancestor_spread) {
6070 std::vector<std::pair<
int,
int>> candidates;
6071 candidates.reserve(n * spread);
6072 for (
int u = 0; u < n; ++u) {
6073 int max_k = std::min(spread, depth[u]);
6077 for (
int k = 2; k <= max_k; ++k) {
6079 candidates.emplace_back(v, u);
6083 tgen_ensure(extra <=
static_cast<
int>(candidates.size()),
6084 "wgraph: not enough edges to generate");
6086 for (
auto [v, u] : choose(candidates, extra))
6087 skewed.add_edge(v, u);
6091 while ((1 << lg) <= n)
6094 std::vector<std::vector<
int>> up(lg, std::vector<
int>(n));
6095 for (
int v = 0; v < n; ++v)
6096 up[0][v] = parent[v];
6097 for (
int j = 1; j < lg; ++j)
6098 for (
int v = 0; v < n; ++v)
6099 up[j][v] = up[j - 1][up[j - 1][v]];
6105 std::vector<
int> distribution = depth;
6106 for (
int &d : distribution)
6107 d = std::max(0, std::min(spread - 1, d - 1));
6109 distinct extra_edges([&]() -> std::pair<
int,
int> {
6110 int u = vertex_choice.next();
6111 int k = next(2, spread);
6113 for (
int j = 0; j < lg; ++j)
6119 while (skewed.m() < m) {
6120 std::pair<
int,
int> edge;
6122 edge = extra_edges.gen();
6123 }
catch (
const std::runtime_error &e) {
6124 if (std::string(e.what()) ==
6125 "tgen: distinct: no more distinct values")
6126 throw detail::error(
6127 "wgraph: not enough edges to generate");
6131 skewed.add_edge(edge.first, edge.second);
6145 tgen_ensure(m >= 0,
"wgraph: number of edges must be nonnegative");
6146 long long num_edges = 1LL * n1 * n2;
6148 "wgraph: bipartite graph has at most n1 * n2 edges");
6152 "wgraph: connected bipartite graph needs at least n1 + n2 - 1 "
6156 std::vector<std::pair<
int,
int>> edges;
6158 for (
long long idx : distinct_range<
long long>(0, num_edges - 1)
6161 edges.emplace_back(
static_cast<
int>(idx / n2),
6162 n1 +
static_cast<
int>(idx % n2));
6163 return value(n1 + n2, std::move(edges),
false);
6166 std::unordered_set<uint64_t> used_edges;
6167 used_edges.reserve(m * 2);
6168 std::vector<std::pair<
int,
int>> edges;
6171 auto pack_edge = [](
int u,
int v) -> uint64_t {
6174 return (
static_cast<uint64_t>(u) << 32) |
static_cast<uint32_t>(v);
6177 if (n1 > 0
and n2 > 0) {
6178 std::vector<
int> prufer(n1 + n2 - 2);
6179 for (
int i = 0; i < n2 - 1; ++i)
6180 prufer[i] = next(0, n1 - 1);
6181 for (
int i = 0; i < n1 - 1; ++i)
6182 prufer[n2 - 1 + i] = next(n1, n1 + n2 - 1);
6183 shuffle(prufer.begin(), prufer.end());
6184 for (
auto [u, v] : detail::edges_from_prufer(std::move(prufer))) {
6187 if (used_edges.insert(pack_edge(u, v)).second)
6188 edges.emplace_back(u, v);
6190 detail::tgen_ensure_against_bug(
6191 used_edges.size() == size_t(n1 + n2 - 1),
6192 "wgraph: invalid bipartite spanning tree size");
6195 while (edges.size() < size_t(m)) {
6196 int u = next(0, n1 - 1);
6197 int v = next(n1, n1 + n2 - 1);
6198 if (used_edges.insert(pack_edge(u, v)).second)
6199 edges.emplace_back(u, v);
6202 return value(n1 + n2, std::move(edges),
false);
6211 std::optional<
value> try_gen_by_edge_index()
const {
6212 if (!edges_.empty())
6213 return std::nullopt;
6215 long long max_edges =
6216 detail::max_graph_edges(n_, is_directed_, has_self_loops_);
6218 throw detail::error(
"wgraph: not enough edges to generate");
6219 if (max_edges <= 0
or 2LL * m_ <= max_edges)
6220 return std::nullopt;
6222 std::vector<std::pair<
int,
int>> edges;
6224 for (
long long idx :
6225 distinct_range<
long long>(0, max_edges - 1).gen_list(m_).to_std())
6226 edges.push_back(detail::decode_graph_edge_index(
6227 n_, idx, is_directed_, has_self_loops_));
6229 return value(n_, edges, is_directed_);
6235 value gen_remaining_edges(std::vector<std::pair<
int,
int>> edges)
const {
6236 detail::tgen_ensure_against_bug(
static_cast<
int>(edges.size()) <= m_,
6237 "wgraph: too many edges were added");
6239 if (
static_cast<
int>(edges.size()) == m_)
6240 return value(n_, edges, is_directed_);
6244 std::unordered_set<uint64_t> seen;
6245 seen.reserve(m_ * 2);
6246 for (
auto [u, v] : edges) {
6247 if (!is_directed_
and u > v)
6249 seen.insert(is_directed_ ? detail::directed_edge_key(u, v)
6250 : detail::undirected_edge_key(u, v));
6253 while (
static_cast<
int>(edges.size()) < m_) {
6254 std::pair<
int,
int> edge;
6255 if (!detail::try_generate_distinct(seen, [&] {
6256 edge = detail::get_random_graph_edge(n_, is_directed_,
6258 if (!is_directed_
and edge.first > edge.second)
6259 std::swap(edge.first, edge.second);
6260 return is_directed_ ? detail::directed_edge_key(edge.first,
6262 : detail::undirected_edge_key(
6263 edge.first, edge.second);
6265 throw detail::error(
"wgraph: not enough edges to generate");
6266 edges.emplace_back(edge);
6269 return value(n_, edges, is_directed_);
6275template <
typename VWeight,
typename EWeight>
6277 const typename wgraph<VWeight, EWeight>::value &g)
6278 : n_(g.n()),
adj_(
g.
n()), add_1_(
false), print_n_(
false),
dsu_(
g.
n()) {
6279 tgen_ensure(g.n() > 0,
"wtree: value: graph must have at least one vertex");
6281 "wtree: value: graph must be undirected to form a tree");
6283 if (g.vertex_weights().has_value())
6284 vertex_weights_ = *g.vertex_weights();
6285 if (g.edge_weights().has_value())
6286 edge_weights_ = std::vector<EWeight>();
6291 std::vector<
int> order(g.m());
6292 std::iota(order.begin(), order.end(), 0);
6293 tgen::shuffle(order.begin(), order.end());
6295 std::vector<std::pair<
int,
int>> tree_edges;
6296 tree_edges.reserve(n_ - 1);
6298 for (
int i : order) {
6299 auto [u, v] = g.edges()[i];
6300 if (!dsu_.unite(u, v))
6305 tree_edges.emplace_back(u, v);
6308 if (edge_weights_.has_value())
6309 edge_weights_->push_back((*g.edge_weights())[i]);
6310 if (
static_cast<
int>(tree_edges.size()) == n_ - 1)
6314 tgen_ensure(
static_cast<
int>(tree_edges.size()) == n_ - 1,
6315 "wtree: value: graph must be connected to form a tree");
6317 edges_ = std::move(tree_edges);
6321
6322
6334
6335
6339inline graph::
value K(
int n) {
return graph(n, n * (n - 1) / 2).gen(); }
6346 graph g(n, n - 1, is_directed);
6347 for (
int i = 0; i + 1 < n; ++i)
6348 g.add_edge(i, i + 1);
6357 tgen_ensure(n >= 3,
"graph: cycle size must be at least 3");
6359 graph g(n, n, is_directed);
6360 for (
int i = 0; i < n; ++i)
6361 g.add_edge(i, (i + 1) % n);
6370 graph g(n1 + n2,
static_cast<
long long>(n1) * n2);
6371 for (
int i = 0; i < n1; ++i)
6372 for (
int j = 0; j < n2; ++j)
6373 g.add_edge(i, n1 + j);
6383
6384
6385
6386
6390using i128 = ::tgen::detail::i128;
6394 static_assert(std::is_arithmetic_v<T>,
6395 "point requires an arithmetic coordinate type");
6407 point(T x = 0, T y = 0) : x_(x), y_(y) {}
6410 T
x()
const {
return x_; }
6413 T
y()
const {
return y_; }
6417 static bool coord_eq(T a, T b) {
6418 if constexpr (std::is_integral_v<T>)
6420 constexpr T eps = T(1e-9);
6422 return d >= -eps
and d <= eps;
6427 if (!coord_eq(x_, p
.x()))
6434 return coord_eq(x_, p
.x())
and coord_eq(y_, p
.y());
6452 if constexpr (std::is_floating_point_v<T>)
6454 return product_t(x_) * p
.x() + product_t(y_) * p
.y();
6459 if constexpr (std::is_floating_point_v<T>)
6461 return product_t(x_) * p
.y() - product_t(y_) * p
.x();
6465 friend std::ostream &operator<<(std::ostream &out,
const point &p) {
6466 return out << p
.x() <<
' ' << p
.y();
6475 long long max_coord) {
6477 "geometry: random_points_general_position: n must be positive");
6479 "geometry: random_points_general_position: min_coord must be "
6480 "at most max_coord");
6482 static_cast<i128>(max_coord) - min_coord <=
6483 std::numeric_limits<
long long>::max(),
6484 "geometry: random_points_general_position: coordinate range too large");
6485 uint64_t width = max_coord - min_coord;
6490 "geometry: random_points_general_position: coordinate range "
6498 std::vector<uint64_t> x_range(p - 1);
6499 std::iota(x_range.begin(), x_range.end(), 1);
6500 shuffle(x_range.begin(), x_range.end());
6501 std::vector<i128> bx(n), by(n);
6502 for (
int i = 0; i < n; ++i) {
6503 uint64_t x = x_range[i];
6505 by[i] = math::modular_inverse(x, p);
6526 const int num_shears = 8;
6527 std::vector<i128> lin_x = bx, lin_y = by;
6529 for (
int it = 0; it < num_shears; ++it) {
6530 bool vertical_shear = next(2) == 0;
6531 int shear_r = pick({-2, -1, 1, 2});
6533 for (
int i = 0; i < n; ++i) {
6535 lin_x[i] = (lin_x[i] + shear_r * lin_y[i]) % p;
6537 lin_y[i] = (lin_y[i] + shear_r * lin_x[i]) % p;
6546 i128 min_x = lin_x[0], max_x = lin_x[0], min_y = lin_y[0], max_y = lin_y[0];
6547 for (
int i = 1; i < n; ++i) {
6548 min_x = std::min(min_x, lin_x[i]);
6549 max_x = std::max(max_x, lin_x[i]);
6550 min_y = std::min(min_y, lin_y[i]);
6551 max_y = std::max(max_y, lin_y[i]);
6555 min_coord - min_x + next<
long long>(0, width - (max_x - min_x));
6557 min_coord - min_y + next<
long long>(0, width - (max_y - min_y));
6559 std::vector<point<
long long>> pts;
6560 for (
int i = 0; i < n; ++i)
6561 pts.emplace_back(lin_x[i] + x_shift, lin_y[i] + y_shift);
6569inline i128 ccw(
const point<
long long> &a,
const point<
long long> &b,
6570 const point<
long long> &p) {
6571 return (
static_cast<i128>(b.x()) - a.x()) *
6572 (
static_cast<i128>(p.y()) - a.y()) -
6573 (
static_cast<i128>(b.y()) - a.y()) *
6574 (
static_cast<i128>(p.x()) - a.x());
6578inline i128 proj_on_ab(
const point<
long long> &P,
const point<
long long> &A,
6579 const point<
long long> &B) {
6580 return (P - A) * (B - A);
6586inline void conquer(std::vector<point<
long long>> &points,
int left,
6588 if (right - left <= 3)
6591 point<
long long> A = points[left], B = points[right - 1];
6594 bool all_collinear =
true;
6595 for (
int k = left + 1; k < right - 1; ++k) {
6596 if (ccw(A, B, points[k]) != 0) {
6597 all_collinear =
false;
6601 if (all_collinear) {
6602 std::sort(points.begin() + left, points.begin() + right,
6603 [&](
const point<
long long> &P,
const point<
long long> &Q) {
6604 return proj_on_ab(P, A, B) < proj_on_ab(Q, A, B);
6610 std::vector<
int> candidates;
6611 for (
int k = left + 1; k < right - 1; ++k) {
6612 if (ccw(A, B, points[k]) != 0)
6613 candidates.push_back(k);
6615 int ci = candidates[next(0,
static_cast<
int>(candidates.size()) - 1)];
6616 point<
long long> C = points[ci];
6618 uint64_t wa = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6619 uint64_t wb = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6620 bool a_on_positive = ccw(C, A, B) < 0;
6624 i128 proj_sum = proj_on_ab(A, A, B) + proj_on_ab(B, A, B);
6625 auto is_positive = [&](
const point<
long long> &P) ->
bool {
6626 i128 s = wa * ccw(C, A, P) + wb * ccw(C, B, P);
6631 return 2 * proj_on_ab(P, A, B) > proj_sum;
6636 if (ci != right - 2)
6637 std::swap(points[ci], points[right - 2]);
6642 if (is_positive(points[i]) == a_on_positive)
6644 else if (is_positive(points[j]) != a_on_positive)
6647 std::swap(points[i], points[j]);
6658 if (i == j
and is_positive(points[i]) == a_on_positive)
6660 std::swap(points[p], points[right - 2]);
6663 conquer(points, left, p + 1);
6665 conquer(points, p, right);
6672inline std::vector<
long long>
6673sample_sorted_distinct_in_range(
int k,
long long left,
long long right) {
6674 long long universe = right - left + 1;
6675 std::vector<
long long> res;
6680 constexpr long long pool_threshold = 8'000'000;
6681 constexpr long long pool_always_below = 500'000;
6683 if (universe <= pool_threshold
and
6684 (universe <= pool_always_below
or k >= universe / 4)) {
6685 size_t u = universe;
6687 std::vector<
long long> pool(u);
6688 std::iota(pool.begin(), pool.end(), left);
6689 size_t m = ks <= u / 2 ? ks : u - ks;
6690 for (size_t i = 0; i < m; ++i) {
6691 size_t j = next<size_t>(i, u - 1);
6692 std::swap(pool[i], pool[j]);
6695 res.assign(pool.begin(), pool.begin() + ks);
6696 std::sort(res.begin(), res.end());
6698 std::vector<
char> excluded(u, 0);
6699 for (size_t i = 0; i < m; ++i)
6700 excluded[pool[i] - left] = 1;
6701 for (
long long v = left; v <= right; ++v)
6702 if (!excluded[v - left])
6706 std::unordered_map<
long long,
long long> virtual_list;
6707 virtual_list.reserve(k * 2);
6708 for (
long long i = 0; i < k; ++i) {
6709 long long j = next<
long long>(i, universe - 1);
6710 long long vi = virtual_list.count(i) ? virtual_list[i] : i;
6711 long long vj = virtual_list.count(j) ? virtual_list[j] : j;
6712 virtual_list[j] = vi;
6713 virtual_list[i] = vj;
6714 res.push_back(virtual_list[i] + left);
6716 std::sort(res.begin(), res.end());
6725inline std::vector<
long long>
6726generate_sorted_coords_with_endpoints(
int n,
long long width) {
6727 std::vector<
long long> coords;
6729 coords.push_back(0);
6730 std::vector<
long long> inner =
6731 sample_sorted_distinct_in_range(n - 2, 1, width - 1);
6732 coords.insert(coords.end(), inner.begin(), inner.end());
6733 coords.push_back(width);
6739inline std::vector<
long long>
6740valtr_edge_components(
const std::vector<
long long> &sorted_coords) {
6741 int n = sorted_coords.size();
6742 std::vector<
long long> left, right;
6743 left.reserve(n / 2);
6744 right.reserve(n / 2);
6745 for (
int i = 1; i + 1 < n; ++i) {
6747 left.push_back(sorted_coords[i]);
6749 right.push_back(sorted_coords[i]);
6751 long long lo = sorted_coords.front(), hi = sorted_coords.back();
6752 std::vector<
long long> seq;
6755 for (
long long v : left)
6758 for (
auto it = right.rbegin(); it != right.rend(); ++it)
6761 std::vector<
long long> comps(n);
6762 for (
int i = 0; i < n; ++i)
6763 comps[i] = seq[i + 1] - seq[i];
6775 bool strict =
false) {
6777 "geometry: random_convex_polygon: n must be at least 3");
6779 "geometry: random_convex_polygon: min_coord must be at most "
6781 tgen_ensure(
static_cast<i128>(max_coord) - min_coord <=
6782 std::numeric_limits<
long long>::max(),
6783 "geometry: random_convex_polygon: coordinate range too large");
6784 long long width = max_coord - min_coord;
6787 "geometry: random_convex_polygon: coordinate range too small for n");
6792 std::vector<
long long> x_sorted =
6793 detail::generate_sorted_coords_with_endpoints(n, width);
6794 std::vector<
long long> y_sorted =
6795 detail::generate_sorted_coords_with_endpoints(n, width);
6797 std::vector<
long long> x_comp = detail::valtr_edge_components(x_sorted);
6798 std::vector<
long long> y_comp = detail::valtr_edge_components(y_sorted);
6800 std::vector<point<
long long>> edges(n);
6801 auto upper = [](
const point<
long long> &p) {
6802 return p.y() > 0
or (p.y() == 0
and p.x() > 0);
6806 int max_strict_attempts = 1;
6808 if (width < 2 * n - 1
or n > 1000)
6809 max_strict_attempts = 4;
6811 max_strict_attempts = 12;
6813 max_strict_attempts = 8;
6815 for (
int attempt = 0;; ++attempt) {
6816 shuffle(y_comp.begin(), y_comp.end());
6817 for (
int i = 0; i < n; ++i)
6818 edges[i] =
point<
long long>(x_comp[i], y_comp[i]);
6820 edges.begin(), edges.end(),
6821 [&upper](
const point<
long long> &a,
const point<
long long> &b) {
6822 bool au = upper(a), bu = upper(b);
6828 return (a * a) < (b * b);
6832 bool collinear =
false;
6833 for (
int i = 0; i < n; ++i) {
6834 const auto &cur = edges[i];
6835 const auto &nxt = edges[(i + 1) % n];
6836 if ((cur ^ nxt) == 0) {
6845 "geometry: random_convex_polygon: generation failed: "
6846 "coordinate range too small for n");
6849 i128 cur_x = 0, cur_y = 0;
6850 std::vector<i128> px(n), py(n);
6851 for (
int i = 0; i < n; ++i) {
6854 cur_x += edges[i].x();
6855 cur_y += edges[i].y();
6857 tgen::detail::tgen_ensure_against_bug(
6858 cur_x == 0
and cur_y == 0,
"geometry: random_convex_polygon: walk did "
6861 i128 min_x = px[0], min_y = py[0];
6862 for (
int i = 1; i < n; ++i) {
6863 min_x = std::min(min_x, px[i]);
6864 min_y = std::min(min_y, py[i]);
6868 i128 shift_x = min_coord - min_x;
6869 i128 shift_y = min_coord - min_y;
6871 std::vector<point<
long long>> pts;
6873 for (
int i = 0; i < n; ++i)
6874 pts.emplace_back(px[i] + shift_x, py[i] + shift_y);
6879 std::rotate(pts.begin(), pts.begin() + rot, pts.end());
6881 std::reverse(pts.begin(), pts.end());
6889 const std::vector<point<
long long>> &points) {
6890 int n = points.size();
6892 "geometry: random_simple_polygon_through_points: need at "
6896 std::set<point<
long long>>(points.begin(), points.end()).size()) ==
6898 "geometry: random_simple_polygon_through_points: points must "
6901 int idx_a = 0, idx_b = 0;
6902 for (
int i = 1; i < n; ++i) {
6903 if (points[i] < points[idx_a])
6905 if (points[idx_b] < points[i])
6908 point<
long long> A = points[idx_a], B = points[idx_b];
6910 bool all_collinear =
true;
6911 for (
int i = 0; i < n; ++i) {
6912 if (i == idx_a
or i == idx_b)
6914 if (detail::ccw(A, B, points[i]) != 0) {
6915 all_collinear =
false;
6920 "geometry: random_simple_polygon_through_points: all points "
6921 "are collinear; no simple polygon exists");
6923 std::vector<point<
long long>> chain;
6926 for (
int i = 0; i < n; ++i) {
6927 if (i == idx_a
or i == idx_b)
6929 if (detail::ccw(A, B, points[i]) > 0) {
6930 chain.push_back(points[i]);
6935 for (
int i = 0; i < n; ++i) {
6936 if (i == idx_a
or i == idx_b)
6938 if (detail::ccw(A, B, points[i]) <= 0)
6939 chain.push_back(points[i]);
6943 int n1 = 2 + left_count;
6945 detail::conquer(chain, 0, n1);
6947 detail::conquer(chain, n1 - 1, chain.size());
6951 std::vector<point<
long long>> poly;
6952 poly.insert(poly.end(), chain.begin() + 1, chain.begin() + n1);
6953 poly.insert(poly.end(), chain.begin() + n1, chain.end());
6962 "geometry: random_simple_polygon: n must be at least 3");
6964 return random_simple_polygon_through_points(
6965 random_points_general_position(n, min_coord, max_coord));
6971
6972
6973
6974
6980using namespace tgen::detail;
6984inline int hash_string(
const std::string &s,
int base,
int mod) {
6987 h = (h * base + c -
'a' + 1) % mod;
6992inline int estimate_length(
int alphabet_size,
int mod) {
6994 double base_len = 2.5 * std::log(std::sqrt(mod));
6995 double scale = std::log(alphabet_size) / std::log(2.0);
6996 double adjusted = base_len / std::max(1.0, scale * 0.7);
6998 return static_cast<
int>(std::ceil(adjusted));
7003inline std::pair<std::string, std::string>
7004birthday_attack(
const std::vector<std::string> &alphabet,
int base,
int mod) {
7006 "birthday_attack: base must be in (0, mod)");
7007 std::map<uint64_t, std::vector<
int>> seen;
7008 int length = estimate_length(alphabet.size(), mod);
7011 std::vector<
int> seq(length);
7015 for (
int i = 0; i < length; ++i) {
7016 seq[i] = next<
int>(0, alphabet.size() - 1);
7017 s += alphabet[seq[i]];
7020 int h = hash_string(s, base, mod);
7022 auto it = seen.find(h);
7023 if (it != seen.end()
and it->second != seq) {
7026 for (
int x : it->second)
7041inline std::set<
long long> std_hash_multipliers() {
7042 std::set<
long long> multipliers = {85229};
7045 bool codeforces_gcc_case =
true;
7046 if (cpp.version_ != 0
and cpp.version_ != 17)
7047 codeforces_gcc_case =
false;
7048 if (compiler.kind_ != compiler_kind::unknown
and
7049 compiler.kind_ != compiler_kind::gcc)
7050 codeforces_gcc_case =
false;
7051 if (compiler.major_ > 7)
7052 codeforces_gcc_case =
false;
7054 if (codeforces_gcc_case)
7055 multipliers.insert(107897);
7066 std::string str =
"a";
7068 while (
static_cast<
int>(str.size()) < n) {
7069 int prev_size = str.size();
7071 for (
int j = 0; j < prev_size
and static_cast<
int>(str.size()) < n; ++j)
7084 for (
int i = 0; i < size; ++i) {
7085 a +=
'a' + math::detail::popcount(i) % 2;
7086 b +=
'a' + (
'b' - a[i]);
7095 int base,
int mod) {
7097 "hack: polynomial_hash: alphabet size must be greater "
7100 "hack: polynomial_hash: base must be in (0, mod)");
7102 std::vector<std::string> alphabet(alphabet_size);
7103 for (
int i = 0; i < alphabet_size; ++i)
7104 alphabet[i] = std::string(1,
'a' + i);
7105 std::iota(alphabet.begin(), alphabet.end(),
'a');
7106 return detail::birthday_attack(alphabet, base, mod);
7113inline std::pair<std::string, std::string>
7115 std::vector<
int> mods) {
7117 "hack: polynomial_hash: bases and mods must have the same "
7120 "hack: polynomial_hash: must have at least one (base, mod) "
7123 "hack: polynomial_hash: multi-hash hack only supported "
7124 "for up to 2 (base, mod) pairs");
7126 std::vector<std::string> alphabet(alphabet_size);
7127 for (
int i = 0; i < alphabet_size; ++i)
7128 alphabet[i] = std::string(1,
'a' + i);
7129 auto [S1, T1] = detail::birthday_attack(alphabet, bases[0], mods[0]);
7130 if (bases.size() == 1)
7132 return detail::birthday_attack({S1, T1}, bases[1], mods[1]);
7138 tgen_ensure(size > 0,
"hack: std_unordered: size must be positive");
7139 std::set<
long long> multipliers = detail::std_hash_multipliers();
7141 std::set<
long long>::iterator it = multipliers.begin();
7143 std::vector<
long long> list;
7144 while (
static_cast<
int>(list.size()) < size) {
7145 list.push_back(mult * (*it));
7147 if (it == multipliers.end()) {
7148 it = multipliers.begin();
7160 std::set<std::pair<
int,
int>> queries;
7163 int sq = std::sqrt(n);
7164 for (
int i = 0; i < sq; ++i) {
7165 for (
int j = i; j < sq; ++j) {
7166 if (i * sq < n
and j * sq < n)
7167 queries.emplace(i * sq, j * sq);
7172 for (
int i = 0; i < n; ++i)
7173 if (queries.size() < size_t(q)) {
7174 queries.emplace(0, i);
7175 queries.emplace(i, i);
7176 queries.emplace(i, n - 1);
7179 std::vector<std::pair<
int,
int>> pool(queries.begin(), queries.end());
7180 while (pool.size() < size_t(q)) {
7181 int l = next(0, n - 1);
7182 pool.emplace_back(l, next(l, n - 1));
7185 return choose(shuffled(pool), q);
7193 std::vector<std::string> list;
7194 int k = 0, left = size;
7196 int cur_size = std::min(left, k + 1);
7199 char right_char = cur_size == k + 1 ?
'b' :
'c';
7200 list.push_back(std::string(cur_size - 1,
'a') + right_char);
7204 return tgen::shuffled(list);
7216 "hack: non_strict_relaxation_dijkstra_bug: needs at least 3 vertices");
7218 egraph<
int>::value g(n, {},
true);
7220 g.add_edge(0, 1, 1);
7221 g.add_edge(0, 2, 1);
7222 for (
int i = 1; i + 2 < n; i += 2) {
7223 g.add_edge(i, i + 2, 1);
7225 g.add_edge(i, i + 3, 1);
7227 g.add_edge(i + 1, i + 2, 1);
7229 g.add_edge(i + 1, i + 3, 1);
7232 return g.shuffle_except({0});
7245 "hack: stale_heap_dijkstra_bug: needs at least 4 vertices");
7248 egraph<
int>::value g(n, {},
true);
7250 for (
int i = 1; i < mid; ++i)
7251 g.add_edge(0, i, i);
7252 for (
int i = 1; i < mid; ++i)
7253 g.add_edge(i, mid, 2 * (mid - i) - 1);
7254 for (
int i = mid + 1; i < n; ++i)
7255 g.add_edge(mid, i, 1);
7257 return g.shuffle_except({0});
7268 tgen_ensure(n >= 2,
"hack: spfa: n must be at least 2");
7269 tgen_ensure(n % 2 == 0,
"hack: spfa: n must be even");
7271 egraph<
int>::value g(n, {},
true);
7274 const int k = n / 2;
7275 for (
int i = 0; i + 1 < k; ++i)
7276 g.add_edge(i, i + 1, 1);
7277 for (
int i = 0; i + 1 < k; ++i)
7278 g.add_edge(k + i, k + i + 1, 0);
7279 for (
int i = 0; i < k; ++i)
7280 g.add_edge(i, k + i, 0);
7281 for (
int i = 0; i + 1 < k; ++i)
7282 g.add_edge(k + i, i + 1, 1);
7284 return g.shuffle_except({0});
7292 tgen_ensure(k >= 1,
"hack: dinitz_worst_case: k must be at least 1");
7293 tgen_ensure(l >= 1,
"hack: dinitz_worst_case: l must be at least 1");
7295 const int p1 = 2 * l - 1;
7296 const int p2 = 2 * l;
7297 const int q1 = 2 * l + 1;
7298 const int q2 = 2 * l + 2;
7299 const int n = 4 * l + 2 * k + 2;
7301 const int flow_cap = k * k * l;
7302 const int layer_cap = k * k;
7304 auto a = [&](
int i) {
return 2 * l + 3 + 2 * i; };
7305 auto b = [&](
int i) {
return 2 * l + 4 + 2 * i; };
7306 auto t = [&](
int i) {
return 4 * l + 2 * k + 1 - i; };
7308 egraph<
int>::value g(n, {},
true);
7311 for (
int i = 0; i + 1 < 2 * l - 1; ++i)
7312 g.add_edge(i, i + 1, flow_cap);
7313 for (
int i = 0; i + 1 < 2 * l - 1; ++i)
7314 g.add_edge(t(i + 1), t(i), flow_cap);
7316 for (
int i = 0; i < 2 * l - 1; i += 2) {
7317 g.add_edge(i, i % 4 == 0 ? p1 : p2, layer_cap);
7318 g.add_edge(i % 4 == 0 ? q1 : q2, t(i), layer_cap);
7321 for (
int i = 0; i < k; ++i) {
7322 g.add_edge(p1, a(i), flow_cap);
7323 g.add_edge(p2, b(i), flow_cap);
7324 g.add_edge(a(i), q2, flow_cap);
7325 g.add_edge(b(i), q1, flow_cap);
7328 for (
int i = 0; i < k; ++i)
7329 for (
int j = 0; j < k; ++j)
7330 g.add_edge(a(i), b(j), 1);
7339 static_assert(std::is_same_v<T,
int>
or std::is_same_v<T,
long long>,
7340 "hack: mt19937_xor_hash: T must be int or long long");
7342 constexpr std::size_t deg = 19937;
7344 std::bitset<deg + 1> a, b, c;
7345 b[deg] = c[deg] = 1;
7346 std::size_t l = 0, shift = 1;
7348 std::mt19937_64 rng64;
7349 for (std::size_t n = 0; n < deg * 2; ++n) {
7351 if constexpr (std::is_same_v<T,
int>)
7352 a[deg] = rng32() & 1;
7354 a[deg] = rng64() & 1;
7356 if ((c & a).count() % 2 == 0) {
7361 std::bitset<deg + 1> oc = c;
7372 std::vector<
bool> mask(deg + 1);
7373 for (std::size_t i = 0; i <= deg; ++i)
7385 {-0.9846, -1.53251}, {0.49946, 1.19525}, {0.79916, 0.98291},
7386 {4.02136, -1.57843}, {3.92734, -2.37856}, {3.88558, -2.37188},
7394inline std::vector<
int> segment_tree_beats_worst_case_block(
int k) {
7396 "hack: segment_tree_beats_worst_case: k must be at least 1");
7398 std::vector<
int> a(k + 1), b(k + 1);
7399 std::vector<std::vector<
int>> vf(k + 1), vg(k + 1);
7405 for (
int i = 2; i <= k; ++i) {
7406 b[i] = b[i - 1] + a[i - 1];
7407 a[i] = b[i] + a[i - 1];
7408 for (
int x : vf[i - 1])
7409 vf[i].push_back(x + a[i] + b[i]);
7410 vf[i].push_back(a[i]);
7411 for (
int x : vg[i - 1])
7412 vf[i].push_back(x + a[i]);
7415 for (
int x : vg[i - 1])
7426segment_tree_beats_append_round(std::vector<std::vector<
int>> &updates,
7427 int block_len,
int an,
int bn,
int n,
7429 const int off = (round * an) % block_len;
7430 const int add_off = (off + block_len - bn) % block_len;
7431 for (
int k = 0; k < block_len; ++k) {
7432 const int s = k * block_len * block_len;
7433 const int sub_end = off + an;
7434 if (sub_end <= block_len)
7435 updates.push_back({1, s + off, s + sub_end, bn});
7437 updates.push_back({1, s + off, s + block_len, bn});
7438 updates.push_back({1, s, s + (sub_end - block_len), bn});
7440 const int add_end = add_off + bn;
7441 if (add_end <= block_len)
7442 updates.push_back({0, s + add_off, s + add_end, an});
7444 updates.push_back({0, s + add_off, s + block_len, an});
7445 updates.push_back({0, s, s + (add_end - block_len), an});
7448 updates.push_back({2, 0, n, an});
7449 for (
int k = 0; k < block_len; ++k) {
7450 const int s = k * block_len * block_len;
7451 updates.push_back({3, s + (off + an - 1) % block_len, 0});
7459inline std::pair<std::vector<
int>, std::vector<std::vector<
int>>>
7460segment_tree_beats_worst_case(
int k,
int q) {
7462 "hack: segment_tree_beats_worst_case: k must be at least 1");
7463 tgen_ensure(k <= 7,
"hack: segment_tree_beats_worst_case: k too large");
7465 "hack: segment_tree_beats_worst_case: q must be positive");
7467 const auto &fib = math::fibonacci();
7468 const int block_len = fib[k * 2 + 1];
7469 const int an = fib[k * 2];
7470 const int bn = fib[k * 2 - 1];
7472 const int len = block_len;
7473 const int total = len * len * len;
7475 std::vector<
int> block = detail::segment_tree_beats_worst_case_block(k);
7476 std::vector<
int> arr(total, 0);
7477 for (
int x = 0; x < block_len; ++x) {
7478 const int s = x * len * len;
7479 for (
int i = 0; i < block_len; ++i)
7480 arr[s + i] = block[i];
7483 std::vector<std::vector<
int>> updates;
7485 const int n = total;
7486 for (
int round = 0; updates.size() <
static_cast<std::size_t>(q); ++round) {
7487 detail::segment_tree_beats_append_round(updates, block_len, an, bn, n,
7489 if (updates.size() >
static_cast<std::size_t>(q))
7492 return {arr, updates};
7498
7499
7500
7501
7510 "misc: parenthesis: size must be a positive even number");
7514 int open = 0, close = 0;
7516 for (
int i = 0; i < size; ++i) {
7522 if (open == close) {
7528 long long a = k - open, b = k - close, h = open - close;
7533 long long num = a * (h + 2);
7534 long long den = (a + b) * (h + 1);
7536 if (next<
long long>(1, den) <= num) {
std::vector< int > many_by_distribution(int k, const std::vector< T > &distribution)
Returns many random indices with given probabilities.
auto shuffled(const C &container)
Shuffles a container.
C::value_type pick(const C &container)
Chooses a random element from container.
void shuffle(It first, It last)
Shuffles range inplace, for random_access_iterator.
T wnext(T left, T right, int w)
Returns a skewed random number in range.
It::value_type pick(It first, It last)
Chooses a random element from an iterator range.
T next(T right)
Returns a random number smaller than value.
size_t next_by_distribution(const std::vector< T > &distribution)
Returns random index with given probabilities.
C::value_type pick_by_distribution(const C &container, std::vector< T > distribution)
Chooses a random element with given probabilities.
#define tgen_ensure(cond,...)
Ensures condition is true.
T next(T left, T right)
Returns a random number in range.
T wnext(T right, int w)
Returns a skewed random number smaller than value.
C choose(const C &container, int k)
Chooses elements from container, as in a subsequence fixed length.
std::vector< point< long long > > random_simple_polygon_through_points(const std::vector< point< long long > > &points)
Generates a random simple polygon through given points.
std::vector< point< long long > > random_points_general_position(int n, long long min_coord, long long max_coord)
Generates random points in general position inside a coordinate box.
std::vector< point< long long > > random_simple_polygon(int n, long long min_coord, long long max_coord)
Generates a random simple polygon given coordinate range.
std::vector< point< long long > > random_convex_polygon(int n, long long min_coord, long long max_coord, bool strict=false)
Generates a random convex polygon with given bounding box.
wgraph< VWeight, int > vgraph
Vertex-weighted labeled graphs.
graph::value C(int n, bool is_directed=false)
Cycle graph.
wgraph< int, EWeight > egraph
Edge-weighted labeled graphs.
graph::value S(int n)
Star undirected graph.
graph::value K(int n1, int n2)
Complete bipartite undirected graph.
graph::value K(int n)
Complete undirected graph.
wgraph< int, int > graph
Unweighted labeled graphs.
graph::value P(int n, bool is_directed=false)
Path graph.
std::vector< std::pair< int, int > > mo_worst_case(int n, int q)
Query list that forces asymptotic worst-case for Mo's algorithm.
std::vector< bool > mt19937_xor_hash()
Mask that forces a zero XOR hash from std::mt19937 or std::mt19937_64.
egraph< int >::value spfa(int n)
Worst-case for FIFO-SPFA.
egraph< int >::value non_strict_relaxation_dijkstra_bug(int n)
Directed weighted graph for Dijkstra with non-strict relaxation.
std::string abacaba(int n)
Returns the prefix of the infinite word "abacabad...".
std::vector< geometry::point< double > > naive_rotating_calipers_max_dist_bug()
Convex polygon that breaks naive rotating calipers for maximum distance.
std::vector< long long > std_unordered(int size)
List of integers that tries to force collision on std::unordered_set.
std::vector< std::string > string_set_worst_case(int size)
List of strings that have high cost to insert in a std::set.
std::pair< std::string, std::string > unsigned_polynomial_hash()
Returns two strings that force polynomial hash collision for power-of-two mod.
std::pair< std::string, std::string > polynomial_hash(int alphabet_size, int base, int mod)
Returns two strings that force polynomial hash collision given base and mod.
egraph< int >::value dinitz_worst_case(int k, int l)
Flow network for Edmonds-Karp and Dinitz worst-case.
egraph< int >::value stale_heap_dijkstra_bug(int n)
Directed weighted graph for Dijkstra without a stale-heap check.
uint64_t prime_from(uint64_t left)
Computes smallest prime from given value.
uint64_t gen_divisor_count(uint64_t left, uint64_t right, int divisor_count)
Generates random number in range with a given prime number of divisors.
std::vector< int > gen_partition_fixed_size(int n, int k, int part_left=0, std::optional< int > part_right=std::nullopt)
Generates a random partition with fixed size of a number.
uint64_t totient(uint64_t n)
Euler's totient function.
uint64_t congruent_from(uint64_t left, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Computes smallest congruent from given value.
uint64_t congruent_upto(uint64_t right, uint64_t rem, uint64_t mod)
Computes largest congruent up to given value.
uint64_t gen_prime(uint64_t left, uint64_t right)
Generates a random prime in given range.
std::vector< uint64_t > factor(uint64_t n)
Factors a number into primes.
int num_divisors(uint64_t n)
Computes the number of divisors of a given number.
bool is_prime(uint64_t n)
Checks if a number is prime.
std::vector< int > gen_partition(int n, int part_left=1, std::optional< int > part_right=std::nullopt)
Generates a random partition of a number.
constexpr int FFT_MOD
FFT/NTT mod.
uint64_t gen_congruent(uint64_t left, uint64_t right, uint64_t rem, uint64_t mod)
Generates random number in range given a modular congruence.
uint64_t prime_upto(uint64_t right)
Computes largest prime up to given value.
uint64_t highly_composite_upto(uint64_t right)
Largest highly composite number up to given number.
uint64_t congruent_upto(uint64_t right, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Computes largest congruent up to given value.
std::vector< std::pair< uint64_t, int > > factor_by_prime(uint64_t n)
Factors a number into primes and its powers.
const std::vector< uint64_t > & fibonacci()
Fetches Fibonacci numbers.
uint64_t modular_inverse(uint64_t a, uint64_t mod)
Computes modular inverse.
uint64_t congruent_from(uint64_t left, uint64_t rem, uint64_t mod)
Computes smallest congruent from given value.
const std::vector< uint64_t > & highly_composites()
Fetches highly composite numbers.
std::vector< std::vector< T > > partition_elements(std::vector< T > elements, int k, int min_size=0, std::optional< uint64_t > max_size=std::nullopt)
Partitions a vector into k ordered groups.
std::vector< uint64_t > gen_partition_fixed_size_fast(uint64_t n, int k, uint64_t part_left=0, std::optional< uint64_t > part_right=std::nullopt)
Generates a fast non-uniform partition with fixed size.
uint64_t gen_congruent(uint64_t left, uint64_t right, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Generates random number in range given modular congruences.
std::pair< uint64_t, uint64_t > prime_gap_upto(uint64_t right)
Largest prime gap up to given number.
std::string gen_parenthesis(int size)
Generates a random valid parenthesis sequence.
T opt(const std::string &key, std::optional< T > default_value=std::nullopt)
Gets opt by key.
void set_compiler(compiler_value compiler)
Sets compiler.
T opt(size_t index, std::optional< T > default_value=std::nullopt)
Gets opt by key.
bool has_opt(std::size_t index)
Checks if opt at some index exists.
bool has_opt(const std::string &key)
Checks if opt with some key exists.
void set_cpp_version(int version)
Sets C++ version.
void register_gen(std::optional< long long > seed=std::nullopt)
Sets up the generator without arguments.
void register_gen(int argc, char **argv)
Sets up the generator.
wtree< VWeight, int > vtree
Vertex-weighted labeled trees.
wtree< int, EWeight > etree
Edge-weighted labeled trees.
wtree< int, int > tree
Unweighted labeled trees.
Compiler identity and version.
Distinct generator for containers.
auto gen_list(int size)
Generates a list of several distinct elements.
T gen()
Generates a distinct random element from the container.
distinct_container(const C &container)
Creates distinct generator for elements of the given container.
auto gen_all()
Generates all distinct elements left to generate.
size_t size() const
Returns the number of elements left to generate.
Distinct generator for integral ranges.
auto gen_list(int count)
Generates a list of several distinct values.
distinct_range(T left, T right)
Creates distinct generator for values in given range.
auto gen_all()
Generates all distinct values left to generate.
T gen()
Generates a distinct random value in the defined range.
T size() const
Returns the number of values left to generate.
Distinct generator for discrete uniform functions.
distinct(Func func, Args... args)
Generates a distinct generator of a discrete uniform function.
auto gen_list(int size)
Generates a list of several distinct values.
bool empty()
Checks if there is nothing left to generate.
auto gen_all()
Generates all distinct values left to generate.
auto gen()
Generates a distinct value.
Base class for generators (should not be instantiated).
auto gen_list(int size, Args &&...args) const
Generates a list of several generation calls.
auto gen_until(Pred predicate, int max_tries, Args &&...args) const
Generates a random value from the valid set until a condition is met.
auto distinct(Args &&...args) const
Creates distinct generator for current generator.
Base class for generator values (should not be instantiated).
bool operator<(const Val &rhs) const
bool operator==(const point &p) const
Coordinate-wise equality.
product_t operator*(const point &p) const
Dot product.
product_t operator^(const point &p) const
Cross product.
point operator*(T c) const
Scalar multiplication.
point operator-(const point &p) const
Vector subtraction.
point(T x=0, T y=0)
Constructs a point.
bool operator<(const point &p) const
Lexicographic order.
point operator+(const point &p) const
Vector addition.
int size() const
Returns the size of the list value.
value(const std::vector< T > &vec)
Creates a list value from a std::vector.
value & sort()
Sorts the list in non-decreasing order.
auto to_std() const
Converts the list to a std::vector.
value & separator(char sep)
Sets separator for printing.
value choose(int k) const
Chooses a uniformly random subsequence of given length.
value operator+(const value &rhs) const
Concatenates two lists.
T & operator[](int idx)
Accesses the element at some position of the list.
value & reverse()
Reverses the list.
T pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the list with given probabilities.
value & shuffle()
Shuffles the list in place.
T pick() const
Returns a uniformly random element.
list & different(int idx_1, int idx_2)
Restricts generator s.t. values at two indices are different.
list & equal(int idx_1, int idx_2)
Restricts generator s.t. values at two indices are equal.
list & all_different()
Restricts generator s.t. all values are different.
list & equal_range(int left, int right)
Restricts generator s.t. all values at index range are equal.
list(int size, std::set< T > values)
Creates list generator defined by value set.
value gen() const
Generates a uniformly random value from the set of valid lists.
list & all_equal()
Restricts generator s.t. all values are equal.
list & different(std::set< int > indices)
Restricts generator s.t. all values in index set are different.
list & different_range(int left, int right)
Restricts generator s.t. all values at index range are different.
list(int size, T value_left, T value_right)
Creates list generator defined by size and range of values.
list & fix(int idx, T val)
Restricts generator s.t. value at index is fixed.
list & equal(std::set< int > indices)
Restricts generator s.t. all values in index set are equal.
T second() const
Returns the second element of a pair value.
value(const T &first, const T &second)
Creates a pair value from first and second values.
value(const std::pair< T, T > &pair)
Creates a pair value from a std::pair.
auto to_std() const
Converts the pair to a std::pair.
T first() const
Returns the first element of a pair value.
value & separator(char sep)
Sets separator for printing.
value gen() const
Generates a uniformly random value from the set of valid pairs.
pair & neq()
Restricts generator s.t. first is not equal to second.
pair & leq()
Restricts generator s.t. first is less than or equal to second.
pair & lt()
Restricts generator s.t. first is less than second.
pair & gt()
Restricts generator s.t. first is greater than second.
pair(T both_left, T both_right)
Creates pair generator defined by range of values for both first and second.
pair & eq()
Restricts generator s.t. first is equal to second.
pair(T first_left, T first_right, T second_left, T second_right)
Creates pair generator defined by range of values for first and second.
pair & geq()
Restricts generator s.t. first is greater than or equal to second.
value & add_1()
Adds 1 for printing.
std::vector< int > to_std() const
Converts the permutation to a std::vector.
const int & operator[](int idx) const
Returns the image at some position of the permutation.
value & sort()
Sorts the permutation in non-decreasing order.
int parity() const
Parity of the permutation.
int pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the permutation with given probabilities.
int pick() const
Returns a uniformly random element.
value & reverse()
Reverses the permutation.
value(const std::vector< int > &vec)
Creates a permutation value from a std::vector.
int size() const
Returns the size of the permutation value.
value & shuffle()
Shuffles the permutation.
value & inverse()
Inverse of the permutation.
value & separator(char sep)
Sets separator for printing.
value gen() const
Generates a uniformly random value from the set of valid permutations.
permutation & cycles(const std::vector< int > &cycle_sizes)
Restricts generator s.t. cycle sizes are fixed.
permutation(int size)
Creates permutation generator defined by size.
permutation & fix(int idx, int val)
Restricts generator s.t. value at index is fixed.
Printer helper for printing containers or sequential generator elements as columns.
print_cols(const Args &...args)
Creates a printer object that prints as columns.
Printer helper for standard types.
print(const T &val, char sep=' ')
Creates a printer object.
Printer helper for standard types, printing on a new line.
println(const T &val, char sep=' ')
Creates a printer object that prints on a new line.
char pick() const
Returns a uniformly random element.
char pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the string with given probabilities.
value choose(int k) const
Chooses a uniformly random subsequence of given length.
value & lowercase()
Sets all characters to lowercase.
value & reverse()
Reverses the string.
int size() const
Returns the size of the string value.
value(const std::string &str)
Creates a string value from a std::string.
value & shuffle()
Shuffles the string.
char & operator[](int idx)
Accesses the character at some position of the string.
value & uppercase()
Sets all characters to uppercase.
value operator+(const value &rhs) const
Concatenates two strings.
std::string to_std() const
Converts the string to a std::string.
value & sort()
Sorts the characters in non-decreasing order.
str & different(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are different.
str & palindrome(int left, int right)
Restricts generator s.t. range is a palindrome.
value gen() const
Generates a uniformly random value from the set of valid strings.
str(int size, char value_left='a', char value_right='z')
Creates string generator defined by size and range of characters.
str & different(std::set< int > indices)
Restricts generator s.t. all characters in index set are different.
str(const std::string ®ex, Args &&...args)
Creates string generator defined by regex.
str & equal(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are equal.
str & equal(std::set< int > indices)
Restricts generator s.t. all characters in index set are equal.
str & equal_range(int left, int right)
Restricts generator s.t. all characters at index range are equal.
str & fix(int idx, char character)
Restricts generator s.t. character at index is fixed.
str & all_equal()
Restricts generator s.t. all values are equal.
str & different_range(int left, int right)
Restricts generator s.t. all characters at index range are different.
str & palindrome()
Restricts generator s.t. string is a palindrome.
str & all_different()
Restricts generator s.t. all characters are different.
str(int size, std::set< char > chars)
Creates string generator defined by character set.
Sampler for repeated draws from a fixed weighted distribution.
size_t next() const
Generates a random index with probability proportional to the distribution.
weighted_sampler(const std::vector< T > &distribution)
Creates a weighted sampler from a probability distribution.
value & print_nm()
Prints number of vertices and edges before edge list.
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
value operator!() const
Graph complement of unweighted graph.
std::tuple< int, int, std::vector< std::set< int > > > to_std() const
Converts the graph to std types.
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
value & add_1()
Adds 1 for printing.
int n() const
Number of vertices.
value operator+(const value &rhs) const
Concatenates two graphs (disjoint union).
value & disjoint_union(const value &rhs)
Disjoint union with another graph.
int m() const
Number of edges.
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another graph at given vertex pairs.
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
value(const std::vector< std::set< int > > &adj, bool is_directed=false)
Builds a graph from an adjacency list.
value(int n, const std::vector< std::pair< int, int > > &edges={}, bool is_directed=false)
Builds a graph from number of vertices and edge list.
wgraph< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
const std::vector< std::set< int > > & adj() const
Adjacency list.
value & add_vertices(int k, std::optional< std::vector< VWeight > > new_vertex_weights=std::nullopt)
Adds new isolated vertices.
value & random_connected_subgraph(int num_edges)
Random subgraph with a fixed number of edges that keeps components connected.
value(const typename wtree< VWeight, EWeight >::value &t)
Builds an undirected graph from a tree.
value & random_subgraph(int num_edges)
Random subgraph with a fixed number of edges.
value & edge_weighted()
Enables edge-weighted mode on an edgeless graph.
value & link(const value &rhs, int new_u, int new_v, std::optional< EWeight > new_w=std::nullopt)
Links two graphs by an new edge.
bool is_directed() const
If the graph is directed.
value & add_edge(int u, int v, std::optional< EWeight > w=std::nullopt)
Adds an edge between two vertices.
value & shuffle()
Shuffles all vertices and edge order.
wgraph< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
const std::vector< std::pair< int, int > > & edges() const
Edge list.
Labeled weighted graph generator.
wgraph(int n, int m, bool is_directed=false, bool has_self_loops=false)
Creates a graph generator for a fixed number of vertices and edges.
static value gen_bipartite(int n1, int n2, int m, bool connected=false)
Generates a random bipartite graph.
value get_connected() const
Random connected undirected graph extending preset edges.
value gen() const
Generates a uniformly random graph satisfying the constraints.
wgraph & add_edge(int u, int v)
Adds a preset edge that must appear in the generated graph.
value get_acyclic() const
Random directed acyclic graph extending preset edges.
static value gen_skewed(int n, int m, int elongation, int spread, bool is_directed=false)
Random skewed connected graph (large diameter).
wgraph & add_edges_from(const value &rhs)
Adds all edges from another graph as preset edges.
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another tree at given vertex pairs.
value & add_1()
Adds 1 for printing.
const std::vector< std::pair< int, int > > & edges() const
Edge list.
value(int n, const std::vector< std::pair< int, int > > &edges)
Builds a tree from a vertex count and an edge list.
value(const typename wgraph< VWeight, EWeight >::value &g)
Builds a tree from a graph via a Kruskal-like random spanning tree.
value & print_parents(int root=-1)
Prints in parent format instead of edge list.
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
value & edge_weighted()
Enables edge-weighted mode on an edgeless tree.
int n() const
Returns the number of vertices.
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
const std::vector< std::set< int > > & adj() const
Adjacency list.
value(const std::vector< std::set< int > > &adj)
Builds a tree from an adjacency list.
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
value & shuffle()
Shuffles vertices and edge order.
std::pair< int, std::vector< std::set< int > > > to_std() const
Converts the tree to a std types.
wtree< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
value & print_n()
Prints the number of vertices before the tree.
value & link(const value &rhs, int new_u, int new_v, std::optional< EWeight > new_w=std::nullopt)
Links two trees by an edge.
wtree< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
Labeled weighted tree generator.
wtree & add_edge(int u, int v)
Restricts generator s.t. some edge is present.
static value gen_skewed(int n, int elongation)
Random skewed tree (large diameter).
value gen() const
Generates a uniformly random value from the set of valid trees.
wtree(int n)
Creates a tree generator with specified number of vertices.
static value gen_kruskal(int n)
Kruskal-like random labeled tree.