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;
256template <
typename Seen,
typename Fn>
257auto try_generate_distinct(Seen &seen, Fn &&next,
bool insert =
true)
258 -> std::optional<std::invoke_result_t<Fn &>> {
259 using T = std::invoke_result_t<Fn &>;
261 distinct_attempt_multiplier * std::max<size_t>(1, seen.size());
262 for (size_t i = 0; i < attempts; ++i) {
265 if (seen.insert(val).second)
267 }
else if (seen.count(val) == 0)
276
277
280enum class compiler_kind { gcc, clang, unknown };
288 compiler_value(compiler_kind kind = compiler_kind::unknown,
int major = 0,
290 : kind_(kind), major_(major), minor_(minor) {}
299 cpp_value(std::optional<
int> version = std::nullopt)
300 : version_(version ? *version : 0) {
302 tgen_ensure(*version == 17
or *version == 20
or *version == 23,
303 "unsupported C++ version (use 17, 20, 23)");
314
315
318template <
typename T>
struct list;
321template <
typename Func,
typename... Args>
struct distinct {
323 std::tuple<Args...> args_;
328 : func_(std::move(func)), args_(std::move(args)...) {}
350 auto val = generate_distinct(
true);
354 throw detail::error(
"distinct: no more distinct values");
356 template <
typename U>
auto gen(std::initializer_list<U> il) {
357 return gen(std::vector<U>(il));
363 for (
int i = 0; i < size; ++i)
364 res.push_back(gen());
366 return typename list<T>::value(res);
372 bool empty() {
return generate_distinct(
false) == std::nullopt; }
378 auto val = generate_distinct(
true);
384 return typename list<T>::value(res);
388 friend std::ostream &operator<<(std::ostream &out,
const distinct &) {
390 detail::dependent_false_v<
distinct>,
391 "distinct: cannot print a distinct generator. Maybe you forgot to "
399 auto generate_distinct(
bool insert) {
400 return detail::try_generate_distinct(
401 seen_, [&] {
return std::apply(func_, args_); }, insert);
404template <
typename Func,
typename... Args>
405distinct(Func, Args...) ->
distinct<Func, Args...>;
409 const Gen &self()
const {
return *
static_cast<
const Gen *>(
this); }
411 template <
typename... Args>
auto gen_list(
int size, Args &&...args)
const {
412 std::vector<
typename Gen::value> res;
414 for (
int i = 0; i < size; ++i)
415 res.push_back(
static_cast<
const Gen *>(
this)->gen(
416 std::forward<Args>(args)...));
418 return typename list<
typename Gen::value>::value(res);
422 template <
typename Pred,
typename... Args>
423 auto gen_until(Pred predicate,
int max_tries, Args &&...args)
const {
424 for (
int i = 0; i < max_tries; ++i) {
425 typename Gen::value val =
static_cast<
const Gen *>(
this)->gen(
426 std::forward<Args>(args)...);
432 throw detail::error(
"could not generate value matching predicate");
434 template <
typename Pred,
typename T,
typename... Args>
435 auto gen_until(Pred predicate,
int max_tries, std::initializer_list<T> il,
436 Args &&...args)
const {
437 return gen_until(predicate, max_tries, std::vector<T>(il),
438 std::forward<Args>(args)...);
442 template <
typename... Args>
auto distinct(Args &&...args)
const {
444 [self = self()](
auto &&...inner_args)
mutable ->
decltype(
auto) {
446 std::forward<
decltype(inner_args)>(inner_args)...);
448 std::forward<Args>(args)...);
450 template <
typename T,
typename... Args>
451 auto distinct(std::initializer_list<T> il, Args &&...args)
const {
452 return distinct(std::vector<T>(il), std::forward<Args>(args)...);
456 friend std::ostream &operator<<(std::ostream &out,
const gen_base &) {
457 static_assert(detail::dependent_false_v<
gen_base>,
458 "gen_base: cannot print a generator. Maybe you forgot to "
466 const Val &self()
const {
return *
static_cast<
const Val *>(
this); }
469 return self().to_std() < rhs.to_std();
477struct is_generator_value
478 : std::is_base_of<gen_value_base<std::decay_t<T>>, std::decay_t<T>> {};
483
484
490 template <
typename T>
print(
const T &val,
char sep =
' ') {
491 std::ostringstream oss;
492 write(oss, val, sep);
495 template <
typename T>
496 print(
const std::initializer_list<T> &il,
char sep =
' ') {
497 std::ostringstream oss;
498 write(oss, std::vector<T>(il), sep);
501 template <
typename T>
502 print(
const std::initializer_list<std::initializer_list<T>> &il,
504 std::ostringstream oss;
505 std::vector<std::vector<T>> mat;
506 for (
const auto &i : il)
508 write(oss, mat, sep);
512 template <
typename T>
void write(std::ostream &os,
const T &val,
char sep) {
513 if constexpr (detail::is_pair<T>::value) {
514 if constexpr (detail::is_pair_multiline<T>::value) {
515 write(os, val.first, sep);
517 write(os, val.second, sep);
520 write(os, val.first,
' ');
522 write(os, val.second,
' ');
524 }
else if constexpr (detail::is_tuple<T>::value)
525 write_tuple(os, val, sep);
526 else if constexpr (detail::is_container<T>::value)
527 write_container(os, val, sep);
528 else if constexpr (std::is_same_v<T, detail::i128>
or
529 std::is_same_v<T, detail::u128>)
530 write_128_number(os, val);
536 template <
typename T>
void write_128_number(std::ostream &os, T num) {
537 static const long long BASE = 1e18;
545 write_128_number(os, num / BASE);
546 os << std::setw(18) << std::setfill(
'0')
547 <<
static_cast<
long long>(num % BASE);
549 os <<
static_cast<
long long>(num);
552 template <
typename C>
553 void write_container(std::ostream &os,
const C &container,
char sep) {
556 for (
const auto &e : container) {
558 os << (detail::is_container_multiline<C>::value ?
'\n' : sep);
560 write(os, e, detail::is_container_multiline<C>::value ? sep :
' ');
565 template <
typename Tuple, size_t... I>
566 void write_tuple_impl(std::ostream &os,
const Tuple &tp,
char sep,
567 std::index_sequence<I...>) {
569 ((os << (first ? (first =
false,
"")
570 : (detail::is_tuple_multiline<Tuple>::value
572 : std::string(1, sep))),
573 write(os, std::get<I>(tp),
574 detail::is_tuple_multiline<Tuple>::value ? sep :
' ')),
577 template <
typename T>
578 void write_tuple(std::ostream &os,
const T &tp,
char sep) {
579 write_tuple_impl(os, tp, sep,
580 std::make_index_sequence<std::tuple_size<T>::value>{});
583 friend std::ostream &operator<<(std::ostream &out,
const print &pr) {
590 template <
typename T>
592 template <
typename T>
593 println(
const std::initializer_list<T> &il,
char sep =
' ')
595 template <
typename T>
596 println(
const std::initializer_list<std::initializer_list<T>> &il,
600 friend std::ostream &operator<<(std::ostream &out,
const println &pr) {
601 return out << pr.s_ <<
'\n';
619 ((detail::is_container<std::decay_t<Args>>::value
or
620 detail::is_sequential<std::decay_t<Args>>::value)
and
622 "print_cols: arguments must be containers or sequential generator "
624 std::ostringstream oss;
629 void write(std::ostream &os,
const Args &...args) {
630 auto views = std::apply(
631 [](
const Args &...inner_args) {
632 return std::make_tuple(
633 detail::print_cols_view<
decltype(inner_args)>{
636 std::forward_as_tuple(args...));
638 const std::size_t n = std::get<0>(views).size();
640 auto check = [&](
const auto &v) {
641 tgen_ensure(v.size() == n,
"print_cols: sizes should be the same");
643 std::apply([&](
const auto &...v) { (check(v), ...); }, views);
645 for (std::size_t i = 0; i < n; ++i) {
649 [&](
const auto &...v) {
650 ((os << (first ?
"" :
" ") <<
print(v.get(i)),
658 std::apply([](
auto &...v) { (v.advance(), ...); }, views);
662 friend std::ostream &operator<<(std::ostream &out,
const print_cols &pr) {
668
669
679using uniform_int_t = std::conditional_t<
680 (
sizeof(T) >=
sizeof(
short)), T,
681 std::conditional_t<std::is_signed_v<T>,
int,
unsigned int>>;
687template <
typename T> T
next(T right) {
688 detail::ensure_registered();
689 if constexpr (std::is_integral_v<T>) {
690 tgen_ensure(right >= 1,
"value for `next` must be valid");
691 return static_cast<T>(
692 std::uniform_int_distribution<detail::uniform_int_t<T>>(
694 static_cast<detail::uniform_int_t<T>>(right) - 1)(detail::rng));
695 }
else if constexpr (std::is_floating_point_v<T>) {
696 tgen_ensure(right >= 0,
"value for `next` must be valid");
697 return std::uniform_real_distribution<T>(0, right)(detail::rng);
699 throw detail::error(
"invalid type for next (" +
700 std::string(
typeid(T).name()) +
")");
708template <
typename T> T
next(T left, T right) {
709 detail::ensure_registered();
710 tgen_ensure(left <= right,
"range for `next` must be valid");
711 if constexpr (std::is_integral_v<T>)
712 return static_cast<T>(
713 std::uniform_int_distribution<detail::uniform_int_t<T>>(
714 static_cast<detail::uniform_int_t<T>>(left),
715 static_cast<detail::uniform_int_t<T>>(right))(detail::rng));
716 else if constexpr (std::is_floating_point_v<T>)
717 return std::uniform_real_distribution<T>(left, right)(detail::rng);
719 throw detail::error(
"invalid type for next (" +
720 std::string(
typeid(T).name()) +
")");
745template <
typename T> T
wnext(T right,
int w) {
748 T val = next<T>(right);
749 for (
int i = 0; i < w; ++i)
750 val = std::max(val, next<T>(right));
751 for (
int i = 0; i < -w; ++i)
752 val = std::min(val, next<T>(right));
757 double x, r = next<
double>(0, 1);
760 x = std::pow(r, 1.0 / (w + 1));
762 x = 1.0 - std::pow(r, 1.0 / (-w + 1));
770template <
typename T> T
wnext(T left, T right,
int w) {
773 T val = next<T>(left, right);
774 for (
int i = 0; i < w; ++i)
775 val = std::max(val, next<T>(left, right));
776 for (
int i = 0; i < -w; ++i)
777 val = std::min(val, next<T>(left, right));
782 double x, r = next<
double>(0, 1);
785 x = std::pow(r, 1.0 / (w + 1));
787 x = 1.0 - std::pow(r, 1.0 / (-w + 1));
790 return left + T(x * (right - left));
797inline u128 next128(u128 total) {
798 tgen_ensure(total > 0,
"next128: total must be positive");
801 u128 limit = (u128(-1) / total) * total;
805 u128 r = (u128(next<uint64_t>(0, std::numeric_limits<uint64_t>::max()))
807 next<uint64_t>(0, std::numeric_limits<uint64_t>::max());
825 static_assert(std::is_arithmetic_v<T>,
826 "weighted_sampler requires an arithmetic weight type");
834 std::vector<storage_t> weight_;
835 std::vector<
int> alias_;
842 : n_(distribution.size()),
alias_(
n_) {
844 "weighted_sampler: distribution must be non-empty");
845 for (
const auto &w : distribution)
847 "weighted_sampler: distribution must be non-negative");
849 total_ = std::accumulate(distribution.begin(), distribution.end(),
852 std::queue<
int> big, small;
853 for (
int i = 0; i < n_; ++i) {
854 weight_.push_back(storage_t(n_) * storage_t(distribution[i]));
855 if (weight_[i] < total_)
861 while (!small.empty()
and !big.empty()) {
862 int s = small.front();
869 weight_[b] -= total_ - weight_[s];
870 if (weight_[b] < total_)
876 detail::tgen_ensure_against_bug(
877 small.empty(),
"weighted_sampler: small must be empty");
881 while (!big.empty()) {
884 if constexpr (std::is_integral_v<T>) {
885 detail::tgen_ensure_against_bug(
886 weight_[b] == total_,
887 "weighted_sampler: weight of big element must be total");
892 weighted_sampler(
const std::initializer_list<T> &distribution)
893 : weighted_sampler(std::vector<T>(distribution)) {}
897 static detail::u128 sample_below(detail::u128 total) {
898 return detail::next128(total);
900 static double sample_below(
double total) {
901 return tgen::next<
double>(0, total);
908 int i = tgen::next<
int>(0, n_ - 1);
909 return sample_below(total_) < weight_[i] ? i : alias_[i];
924size_t next_by_distribution(
const std::initializer_list<T> &distribution) {
925 return next_by_distribution(std::vector<T>(distribution));
933 const std::vector<T> &distribution) {
934 tgen_ensure(distribution.size() > 0,
"distribution must be non-empty");
935 tgen_ensure(k >= 0,
"number of elements to choose must be non-negative");
938 std::vector<
int> res;
939 for (
int i = 0; i < k; ++i)
940 res.push_back(am.next());
945many_by_distribution(
int k,
const std::initializer_list<T> &distribution) {
946 return many_by_distribution(k, std::vector<T>(distribution));
951template <
typename It>
void shuffle(It first, It last) {
955 for (It i = first + 1; i != last; ++i)
956 std::iter_swap(i, first + next(0,
static_cast<
int>(i - first)));
961template <
typename C> [[nodiscard]]
auto shuffled(
const C &container) {
962 if constexpr (detail::is_associative_container<C>::value) {
963 std::vector<
typename C::value_type> vec(container.begin(),
965 shuffle(vec.begin(), vec.end());
968 auto new_container = container;
969 shuffle(new_container.begin(), new_container.end());
970 return new_container;
974[[nodiscard]] std::vector<T> shuffled(
const std::initializer_list<T> &il) {
975 return shuffled(std::vector<T>(il));
981 int size = std::distance(first, last);
982 tgen_ensure(size > 0,
"cannot pick from empty range");
984 std::advance(it, next(0, size - 1));
991 return pick(container.begin(), container.end());
993template <
typename T> T pick(
const std::initializer_list<T> &il) {
994 return pick(std::vector<T>(il));
999template <
typename C,
typename T>
1001 std::vector<T> distribution) {
1002 tgen_ensure(container.size() == distribution.size(),
1003 "container and distribution must have the same size");
1004 auto it = container.begin();
1005 std::advance(it, next_by_distribution(distribution));
1008template <
typename C,
typename T>
1009typename C::value_type
1010pick_by_distribution(
const C &container,
1011 const std::initializer_list<T> &distribution) {
1012 return pick_by_distribution(container, std::vector<T>(distribution));
1014template <
typename T,
typename U>
1015T pick_by_distribution(
const std::initializer_list<T> &il,
1016 const std::vector<U> &distribution) {
1017 return pick_by_distribution(std::vector<T>(il), distribution);
1019template <
typename T,
typename U>
1020T pick_by_distribution(
const std::initializer_list<T> &il,
1021 const std::initializer_list<U> &distribution) {
1022 return pick_by_distribution(std::vector<T>(il),
1023 std::vector<U>(distribution));
1028template <
typename C> C
choose(
const C &container,
int k) {
1029 tgen_ensure(0 < k
and k <=
static_cast<
int>(container.size()),
1030 "number of elements to choose must be valid");
1031 std::vector<
typename C::value_type> new_vec;
1033 int need = k, left = container.size();
1034 for (
auto cur_it = container.begin(); cur_it != container.end(); ++cur_it) {
1035 if (next(1, left--) <= need) {
1036 new_container.insert(new_container.end(), *cur_it);
1040 return new_container;
1042template <
typename T>
1043std::vector<T> choose(
const std::initializer_list<T> &il,
int k) {
1044 return choose(std::vector<T>(il), k);
1053 std::unordered_map<T, T> virtual_list_;
1056 static constexpr size_t array_pool_max =
size_t{1} << 23;
1060 : left_(left), right_(right), num_available_(right - left + 1) {}
1063 T
size()
const {
return num_available_; }
1072 T i = next<T>(0,
size() - 1);
1075 auto vi_it = virtual_list_.find(i);
1076 T vi = vi_it == virtual_list_.end() ? i : vi_it->second;
1077 auto vj_it = virtual_list_.find(j);
1078 T vj = vj_it == virtual_list_.end() ? j : vj_it->second;
1079 virtual_list_[i] = vj;
1090 tgen_ensure(count >= 0,
"distinct_range: size must be nonnegative");
1092 "distinct_range: no more values to generate");
1094 size_t range_size = right_ - left_ + 1;
1095 size_t sample_count = count;
1098 if (sample_count > 0) {
1099 if (range_size <= array_pool_max)
1100 res = sample_from_pool(sample_count, range_size);
1101 else if (sample_count * 2 > range_size)
1102 res = sample_complement(sample_count, range_size);
1104 res = sample_sparse(sample_count);
1107 num_available_ -= count;
1108 virtual_list_.clear();
1109 return typename list<T>::value(res);
1119 std::vector<T> sample_from_pool(size_t count, size_t range_size) {
1120 std::vector<T> pool(range_size);
1121 std::iota(pool.begin(), pool.end(), left_);
1122 for (size_t i = 0; i < count; ++i) {
1123 size_t j = next<size_t>(i, range_size - 1);
1124 std::swap(pool[i], pool[j]);
1132 std::vector<T> sample_complement(size_t count, size_t range_size) {
1133 size_t exclude_count = range_size - count;
1134 std::unordered_set<T> excluded;
1135 excluded.reserve(exclude_count * 2);
1137 if (exclude_count <= array_pool_max) {
1138 for (T value : sample_from_pool(exclude_count, range_size))
1139 excluded.insert(value);
1141 for (T value : sample_sparse(exclude_count))
1142 excluded.insert(value);
1147 for (T value = left_; value <= right_; ++value) {
1148 if (!excluded.count(value))
1149 res.push_back(value);
1151 detail::tgen_ensure_against_bug(
1152 res.size() == count,
"distinct_range: complement sampling failed");
1158 std::vector<T> sample_sparse(size_t count) {
1159 std::unordered_map<T, T> local_virtual;
1160 local_virtual.reserve(count * 2);
1161 T remaining = range_span();
1164 for (size_t step = 0; step < count; ++step) {
1165 T i = next<T>(0, remaining - 1);
1166 T j = remaining - 1;
1168 auto vi_it = local_virtual.find(i);
1169 T vi = vi_it == local_virtual.end() ? i : vi_it->second;
1170 auto vj_it = local_virtual.find(j);
1171 T vj = vj_it == local_virtual.end() ? j : vj_it->second;
1172 local_virtual[i] = vj;
1174 res.push_back(vi + left_);
1182 T range_span() {
return right_ - left_ + 1; }
1187 std::vector<T> list_;
1188 distinct_range<size_t> idx_;
1191 template <
typename C>
1195 distinct_container(
const std::initializer_list<T> &il)
1196 : distinct_container(std::vector<T>(il)) {}
1203 T
gen() {
return list_[idx_.gen()]; }
1209 for (
int i = 0; i < size; ++i)
1210 res.push_back(
gen());
1211 return typename list<T>::value(res);
1219 res.push_back(
gen());
1220 return typename list<T>::value(res);
1223template <
typename C>
1227
1228
1229
1230
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1248
1249
1253 detail::cpp = detail::cpp_value(version);
1257
1258
1262 return {compiler_kind::gcc, major, minor};
1267 return {compiler_kind::clang, major, minor};
1272 detail::compiler.kind_ = compiler.kind_;
1273 detail::compiler.major_ = compiler.major_;
1274 detail::compiler.minor_ = compiler.minor_;
1281inline bool process_special_opt_flags(std::string &key) {
1283 if (key.find(
"tgen::CPP:") == 0) {
1284 int prefix_len = std::string(
"tgen::CPP:").size();
1285 tgen_ensure(
static_cast<
int>(key.size()) == prefix_len + 2
and
1286 std::isdigit(key[prefix_len])
and
1287 std::isdigit(key[prefix_len + 1]),
1288 "invalid CPP format");
1289 int version = std::stoi(key.substr(prefix_len, 2));
1297 size_t prefix_len = 0;
1299 if (key.find(
"tgen::GCC") == 0) {
1300 kind = compiler_kind::gcc;
1301 prefix_len = std::string(
"tgen::GCC").size();
1302 }
else if (key.find(
"tgen::CLANG") == 0) {
1303 kind = compiler_kind::clang;
1304 prefix_len = std::string(
"tgen::CLANG").size();
1309 if (key.size() == prefix_len) {
1314 tgen_ensure(key[prefix_len] ==
':',
"invalid compiler format");
1317 std::string inside = key.substr(prefix_len, key.size() - prefix_len);
1318 int major = 0, minor = 0;
1320 size_t dot = inside.find(
'.');
1321 if (dot == std::string::npos) {
1323 std::all_of(inside.begin(), inside.end(), ::isdigit),
1324 "invalid compiler version");
1325 major = std::stoi(inside);
1327 std::string maj = inside.substr(0, dot);
1328 std::string min = inside.substr(dot + 1);
1331 std::all_of(maj.begin(), maj.end(), ::isdigit)
and
1333 "invalid compiler major version");
1335 std::all_of(min.begin(), min.end(), ::isdigit)
and
1337 "invalid compiler minor version");
1339 major = std::stoi(maj);
1340 minor = std::stoi(min);
1348inline std::vector<std::string>
1350inline std::map<std::string, std::string>
1353template <
typename T> T get_opt(
const std::string &value) {
1355 if constexpr (std::is_same_v<T,
bool>) {
1356 if (value ==
"true" or value ==
"1")
1358 if (value ==
"false" or value ==
"0")
1360 }
else if constexpr (std::is_integral_v<T>) {
1361 if constexpr (std::is_unsigned_v<T>)
1362 return static_cast<T>(std::stoull(value));
1364 return static_cast<T>(std::stoll(value));
1365 }
else if constexpr (std::is_floating_point_v<T>)
1366 return static_cast<T>(std::stold(value));
1372 throw error(
"invalid value `" + value +
"` for type " +
typeid(T).name());
1375inline void parse_opts(
int argc,
char **argv) {
1378 for (
int i = 1; i < argc; ++i) {
1379 std::string key(argv[i]);
1381 if (process_special_opt_flags(key))
1384 if (key[0] ==
'-') {
1386 "invalid opt (" + std::string(argv[i]) +
")");
1387 if (
'0' <= key[1]
and key[1] <=
'9') {
1389 pos_opts.push_back(key);
1394 key = key.substr(1);
1397 pos_opts.push_back(key);
1402 if (key[0] ==
'-') {
1404 "invalid opt (" + std::string(argv[i]) +
")");
1407 key = key.substr(1);
1414 std::size_t eq = key.find(
'=');
1415 if (eq != std::string::npos) {
1417 std::string value = key.substr(eq + 1);
1418 key = key.substr(0, eq);
1420 "expected non-empty key/value in opt (" +
1421 std::string(argv[i]) +
")");
1423 "cannot have repeated keys");
1424 named_opts[key] = value;
1428 "cannot have repeated keys");
1429 tgen_ensure(argv[i + 1],
"value cannot be empty");
1430 named_opts[key] = std::string(argv[i + 1]);
1436inline void set_seed(
int argc,
char **argv) {
1437 std::vector<uint32_t> seed;
1440 for (
int i = 1; i < argc; ++i) {
1442 int size_pos = seed.size();
1444 for (
char *s = argv[i]; *s !=
'\0'; ++s) {
1449 std::seed_seq seq(seed.begin(), seed.end());
1457 detail::ensure_registered();
1458 return index < detail::pos_opts.size();
1463 detail::ensure_registered();
1464 return detail::named_opts.count(key) != 0;
1466template <
typename K>
1467std::enable_if_t<std::is_same_v<K,
char>,
bool> has_opt(K key) {
1473template <
typename T>
1474T
opt(size_t index, std::optional<T> default_value = std::nullopt) {
1475 detail::ensure_registered();
1476 if (!has_opt(index)) {
1478 return *default_value;
1479 throw detail::error(
"cannot find opt at index " +
1480 std::to_string(index));
1482 return detail::get_opt<T>(detail::pos_opts[index]);
1487template <
typename T>
1488T
opt(
const std::string &key, std::optional<T> default_value = std::nullopt) {
1489 detail::ensure_registered();
1492 return *default_value;
1493 throw detail::error(
"cannot find opt with key " + key);
1495 return detail::get_opt<T>(detail::named_opts[key]);
1497template <
typename T,
typename K>
1498std::enable_if_t<std::is_same_v<K,
char>, T>
1499opt(K key, std::optional<T> default_value = std::nullopt) {
1500 return opt<T>(std::string(1, key), default_value);
1505 detail::set_seed(argc, argv);
1507 detail::pos_opts.clear();
1508 detail::named_opts.clear();
1509 detail::parse_opts(argc, argv);
1511 detail::registered =
true;
1517 detail::rng.seed(*seed);
1521 detail::pos_opts.clear();
1522 detail::named_opts.clear();
1524 detail::registered =
true;
1528
1529
1530
1531
1534
1535
1536
1537
1541 T value_l_, value_r_;
1542 std::set<T> values_;
1547 mutable std::vector<std::pair<T, T>>
1549 mutable std::vector<std::vector<
int>> neigh_;
1550 std::vector<std::set<
int>>
1552 bool index_constraints_{
1554 mutable bool uses_full_range_{
1559 list(
int size, T value_left, T value_right)
1560 : size_(size), value_l_(value_left), value_r_(value_right),
1561 uses_full_range_(
true) {
1562 tgen_ensure(size_ > 0,
"list: size must be positive");
1563 tgen_ensure(value_l_ <= value_r_,
"list: value range must be valid");
1569 tgen_ensure(size_ > 0,
"list: size must be positive");
1570 tgen_ensure(!values.empty(),
"list: value set must be non-empty");
1571 value_l_ = 0, value_r_ = values.size() - 1;
1572 val_range_.assign(size_, {value_l_, value_r_});
1574 for (T val : values_)
1575 value_idx_in_set_[val] = idx++;
1580 tgen_ensure(0 <= idx
and idx < size_,
"list: index must be valid");
1581 ensure_val_range_materialized();
1582 if (values_.size() == 0) {
1583 auto &[left, right] = val_range_[idx];
1584 if (left == right
and value_l_ != value_r_) {
1586 "list: must not set to two different values");
1589 "list: value must be in the defined range");
1594 "list: value must be in the set of values");
1595 auto &[left, right] = val_range_[idx];
1596 int new_val = value_idx_in_set_[val];
1598 "list: must not set to two different values");
1599 left = right = new_val;
1601 index_constraints_ =
true;
1608 std::max(idx_1, idx_2) < size_,
1609 "list: indices must be valid");
1613 ensure_val_range_materialized();
1614 ensure_neigh_allocated();
1615 index_constraints_ =
true;
1616 neigh_[idx_1].push_back(idx_2);
1617 neigh_[idx_2].push_back(idx_1);
1623 if (!indices.empty()) {
1624 std::set<
int>::iterator beg = indices.begin();
1625 for (
auto it = std::next(beg); it != indices.end(); ++it)
1633 tgen_ensure(0 <= left
and left <= right
and right < size_,
1634 "list: range indices must be valid");
1635 for (
int i = left; i < right; ++i)
1647 if (!indices.empty())
1648 diff_restrictions_.push_back(indices);
1654 std::set<
int> indices = {idx_1, idx_2};
1660 tgen_ensure(0 <= left
and left <= right
and right < size_,
1661 "list: range indices must be valid");
1662 std::vector<
int> indices(right - left + 1);
1663 std::iota(indices.begin(), indices.end(), left);
1664 return different(std::set<
int>(indices.begin(), indices.end()));
1669 std::vector<
int> indices(size_);
1670 std::iota(indices.begin(), indices.end(), 0);
1671 return different(std::set<
int>(indices.begin(), indices.end()));
1677 using tgen_is_sequential_tag = detail::is_sequential_tag;
1679 using value_type = T;
1682 std::vector<T> vec_;
1686 value(
const std::initializer_list<T> &il) : value(std::vector<T>(il)) {}
1689 int size()
const {
return vec_.size(); }
1694 "list: value: index out of bounds");
1697 const T &operator[](
int idx)
const {
1699 "list: value: index out of bounds");
1706 std::sort(vec_.begin(), vec_.end());
1713 std::reverse(vec_.begin(), vec_.end());
1727 std::vector<T> new_vec = vec_;
1728 for (
int i = 0; i < rhs
.size(); ++i)
1729 new_vec.push_back(rhs[i]);
1730 return value(new_vec);
1736 for (
int i = 0; i < size(); ++i)
1737 std::swap(vec_[i], vec_[next(0, size() - 1)]);
1743 T
pick()
const {
return vec_[next<
int>(0, size() - 1)]; }
1747 template <
typename Dist>
1750 "value and distribution must have the same size");
1751 return vec_[next_by_distribution(distribution)];
1753 template <
typename Dist>
1754 T pick_by_distribution(
1755 const std::initializer_list<Dist> &distribution)
const {
1756 return pick_by_distribution(std::vector<Dist>(distribution));
1763 "number of elements to choose must be valid");
1764 std::vector<T> new_vec;
1766 for (
int i = 0; need > 0; ++i) {
1768 if (next(1, left) <= need) {
1769 new_vec.push_back(vec_[i]);
1773 return value(new_vec);
1777 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
1778 for (
int i = 0; i < val.size(); ++i) {
1788 if constexpr (!detail::is_generator_value<T>::value) {
1791 std::vector<
typename T::std_type> vec;
1792 for (
const auto &i : vec_)
1793 vec.push_back(i.to_std());
1803 if (diff_restrictions_.empty()) {
1804 if (
auto unconstrained = try_gen_unconstrained())
1805 return *unconstrained;
1807 if (
auto all_different = try_gen_all_different())
1808 return *all_different;
1810 ensure_neigh_allocated();
1811 std::vector<T> vec(size_);
1812 std::vector<
bool> defined_idx(
1815 std::vector<
int> comp_id(size_, -1);
1816 std::vector<std::vector<
int>> comp(size_);
1820 auto define_comp = [&](
int cur_comp, T val) {
1821 for (
int idx : comp[cur_comp]) {
1824 defined_idx[idx] =
true;
1830 std::vector<
bool> vis(size_,
false);
1831 for (
int idx = 0; idx < size_; ++idx)
1834 bool value_defined =
false;
1838 std::queue<
int> q({idx});
1840 std::vector<
int> component;
1841 while (!q.empty()) {
1842 int cur_idx = q.front();
1845 component.push_back(cur_idx);
1848 auto [l, r] = val_range_at(cur_idx);
1850 if (!value_defined) {
1852 value_defined =
true;
1854 }
else if (new_value != l) {
1856 throw detail::contradiction_error(
1858 "tried to set value to `" +
1859 std::to_string(new_value) +
1860 "`, but it was already set as `" +
1861 std::to_string(l) +
"`");
1865 for (
int nxt_idx : neigh_[cur_idx]) {
1866 if (!vis[nxt_idx]) {
1867 vis[nxt_idx] =
true;
1874 for (
int cur_idx : component) {
1875 comp_id[cur_idx] = comp_count;
1876 comp[comp_id[cur_idx]].push_back(cur_idx);
1881 define_comp(comp_count, new_value);
1888 std::vector<std::set<
int>> diff_containing_comp_idx(comp_count);
1891 for (
const std::set<
int> &diff : diff_restrictions_) {
1893 if (
static_cast<uint64_t>(diff.size() - 1) +
1894 static_cast<uint64_t>(value_l_) >
1895 static_cast<uint64_t>(value_r_))
1896 throw detail::contradiction_error(
1897 "list",
"tried to generate " +
1898 std::to_string(diff.size()) +
1899 " different values, but the maximum is " +
1900 std::to_string(value_r_ - value_l_ + 1));
1904 std::set<
int> comp_ids;
1905 for (
int idx : diff) {
1906 if (comp_ids.count(comp_id[idx]))
1907 throw detail::contradiction_error(
1908 "list",
"tried to set two indices as equal and "
1910 comp_ids.insert(comp_id[idx]);
1912 diff_containing_comp_idx[comp_id[idx]].insert(dist_id);
1919 for (
auto &diff_containing : diff_containing_comp_idx)
1920 if (diff_containing.size() >= 3)
1921 throw detail::complex_restrictions_error(
1923 "one index cannot be in >= 3 'different' restrictions");
1925 std::vector<
bool> vis_diff(diff_restrictions_.size(),
false);
1926 std::vector<
bool> initially_defined_comp_idx(comp_count,
false);
1929 auto define_tree = [&](
int diff_id) {
1934 std::set<T> defined_values;
1935 for (
int idx : diff_restrictions_[diff_id])
1936 if (defined_idx[idx]) {
1939 if (defined_values.count(vec[idx]))
1940 throw detail::contradiction_error(
1942 "tried to set two indices as equal and different");
1944 defined_values.insert(vec[idx]);
1949 int new_value_count = diff_restrictions_[diff_id].size() -
1950 static_cast<
int>(defined_values.size());
1951 std::vector<T> generated_values =
1952 generate_distinct_values(new_value_count, defined_values);
1953 auto val_it = generated_values.begin();
1954 for (
int idx : diff_restrictions_[diff_id])
1955 if (defined_idx[idx]) {
1958 initially_defined_comp_idx[comp_id[idx]] =
false;
1960 define_comp(comp_id[idx], *val_it);
1966 std::queue<std::pair<
int,
int>> q;
1967 q.emplace(diff_id, -1);
1968 vis_diff[diff_id] =
true;
1969 while (!q.empty()) {
1970 auto [cur_diff, parent] = q.front();
1973 std::set<
int> neigh_diff;
1974 for (
int idx : diff_restrictions_[cur_diff])
1976 diff_containing_comp_idx[comp_id[idx]]) {
1977 if (nxt_diff == cur_diff
or nxt_diff == parent)
1981 if (vis_diff[nxt_diff])
1982 throw detail::complex_restrictions_error(
1984 "cycle found in 'different' restrictions");
1986 neigh_diff.insert(nxt_diff);
1989 for (
int nxt_diff : neigh_diff) {
1990 vis_diff[nxt_diff] =
true;
1991 q.emplace(nxt_diff, cur_diff);
1994 std::set<T> nxt_defined_values;
1995 for (
int idx2 : diff_restrictions_[nxt_diff])
1996 if (defined_idx[idx2]) {
2000 if (initially_defined_comp_idx[comp_id[idx2]])
2001 throw detail::complex_restrictions_error(
2004 nxt_defined_values.insert(vec[idx2]);
2006 int new_value_count =
2007 diff_restrictions_[nxt_diff].size() -
2008 static_cast<
int>(nxt_defined_values.size());
2009 std::vector<T> generated_values = generate_distinct_values(
2010 new_value_count, nxt_defined_values);
2011 auto val_it = generated_values.begin();
2012 for (
int idx2 : diff_restrictions_[nxt_diff])
2013 if (!defined_idx[idx2]) {
2014 define_comp(comp_id[idx2], *val_it);
2026 std::vector<std::pair<
int,
int>> defined_cnt_and_diff_idx;
2028 for (
const std::set<
int> &diff : diff_restrictions_) {
2029 int defined_cnt = 0;
2030 for (
int idx : diff)
2031 if (defined_idx[idx]) {
2033 initially_defined_comp_idx[comp_id[idx]] =
true;
2035 defined_cnt_and_diff_idx.emplace_back(defined_cnt, dist_id);
2039 std::sort(defined_cnt_and_diff_idx.rbegin(),
2040 defined_cnt_and_diff_idx.rend());
2041 for (
auto [defined_cnt, diff_idx] : defined_cnt_and_diff_idx)
2042 if (!vis_diff[diff_idx])
2043 define_tree(diff_idx);
2047 for (std::size_t dist_id = 0; dist_id < diff_restrictions_.size();
2049 if (!vis_diff[dist_id])
2050 define_tree(dist_id);
2056 for (
int idx = 0; idx < size_; ++idx)
2057 if (!defined_idx[idx])
2058 define_comp(comp_id[idx], next<T>(value_l_, value_r_));
2060 if (!values_.empty()) {
2062 std::vector<T> value_vec(values_.begin(), values_.end());
2064 val = value_vec[val];
2072 void ensure_neigh_allocated()
const {
2073 if (neigh_.size() ==
static_cast<size_t>(size_))
2075 neigh_.assign(size_, {});
2079 void ensure_val_range_materialized()
const {
2080 if (!uses_full_range_)
2082 val_range_.assign(size_, {value_l_, value_r_});
2083 uses_full_range_ =
false;
2087 std::pair<T, T> val_range_at(
int idx)
const {
2088 if (uses_full_range_)
2089 return {value_l_, value_r_};
2090 return val_range_[idx];
2096 generate_distinct_values(
int k,
const std::set<T> &forbidden_values)
const {
2097 for (
auto forbidden : forbidden_values)
2098 tgen_ensure(value_l_ <= forbidden
and forbidden <= value_r_);
2099 const T num_available =
2100 (value_r_ - value_l_ + 1) - forbidden_values.size();
2101 if (num_available < k)
2102 throw detail::complex_restrictions_error(
2103 "list",
"not enough distinct values");
2104 if (forbidden_values.empty())
2105 return distinct_range<T>(value_l_, value_r_).gen_list(k).to_std();
2107 std::map<T, T> virtual_list;
2108 std::vector<T> gen_list;
2109 for (
int i = 0; i < k; ++i) {
2110 T j = next<T>(i, num_available - 1);
2111 T vj = virtual_list.count(j) ? virtual_list[j] : j;
2112 T vi = virtual_list.count(i) ? virtual_list[i] : i;
2114 virtual_list[j] = vi, virtual_list[i] = vj;
2116 gen_list.push_back(virtual_list[i]);
2119 for (T &val : gen_list)
2122 std::vector<std::pair<T,
int>> values_sorted;
2123 for (std::size_t i = 0; i < gen_list.size(); ++i)
2124 values_sorted.emplace_back(gen_list[i], i);
2125 std::sort(values_sorted.begin(), values_sorted.end());
2126 auto cur_it = forbidden_values.begin();
2127 int smaller_forbidden_count = 0;
2128 for (
auto [val, idx] : values_sorted) {
2129 while (cur_it != forbidden_values.end()
and
2130 *cur_it <= val + smaller_forbidden_count)
2131 ++cur_it, ++smaller_forbidden_count;
2132 gen_list[idx] += smaller_forbidden_count;
2141 std::optional<
value> try_gen_unconstrained()
const {
2142 if (!values_.empty()
or index_constraints_)
2143 return std::nullopt;
2145 std::vector<T> vec(size_);
2146 for (
int i = 0; i < size_; ++i)
2147 vec[i] = next<T>(value_l_, value_r_);
2155 std::optional<
value> try_gen_all_different()
const {
2156 if (!values_.empty()
or diff_restrictions_.size() != 1)
2157 return std::nullopt;
2159 const std::set<
int> &diff = diff_restrictions_[0];
2160 if (
static_cast<
int>(diff.size()) != size_
or *diff.begin() != 0
or
2161 *diff.rbegin() != size_ - 1)
2162 return std::nullopt;
2164 if (!neigh_.empty()) {
2165 for (
const auto &adj : neigh_) {
2167 return std::nullopt;
2171 if (index_constraints_)
2172 return std::nullopt;
2174 if (
static_cast<
long long>(size_) >
2175 static_cast<
long long>(value_r_) - value_l_ + 1)
2176 throw detail::contradiction_error(
2177 "list",
"tried to generate " + std::to_string(size_) +
2178 " different values, but the maximum is " +
2179 std::to_string(value_r_ - value_l_ + 1));
2186
2187
2188
2189
2192
2193
2194
2195
2199 std::vector<std::pair<
int,
int>> defs_;
2200 std::optional<std::vector<
int>> cycle_sizes_;
2204 tgen_ensure(size_ > 0,
"permutation: size must be positive");
2210 "permutation: index must be valid");
2211 defs_.emplace_back(idx, val);
2218 size_ == std::accumulate(cycle_sizes.begin(), cycle_sizes.end(), 0),
2219 "permutation: cycle sizes must add up to size of permutation");
2220 cycle_sizes_ = cycle_sizes;
2223 permutation &cycles(
const std::initializer_list<
int> &cycle_sizes) {
2224 return cycles(std::vector<
int>(cycle_sizes));
2230 using tgen_is_sequential_tag = detail::is_sequential_tag;
2233 std::vector<
int> vec_;
2238 :
vec_(
vec), sep_(
' '), add_1_(
false) {
2239 tgen_ensure(!vec_.empty(),
"permutation: value: cannot be empty");
2240 std::vector<
bool> vis(vec_.size(),
false);
2241 for (
int i = 0; i <
size(); ++i) {
2243 vec_[i] <
static_cast<
int>(vec_.size()),
2244 "permutation: value: values must be from `0` to "
2247 "permutation: value: cannot have repeated values");
2248 vis[vec_[i]] =
true;
2251 value(
const std::initializer_list<
int> &il)
2252 : value(std::vector<
int>(il)) {}
2255 int size()
const {
return vec_.size(); }
2260 "permutation: value: index out of bounds");
2267 std::vector<
bool> vis(
size(),
false);
2270 for (
int i = 0; i <
size(); ++i)
2273 for (
int j = i; !vis[j]; j = vec_[j])
2277 return ((
size() - cycles) % 2 == 0) ? +1 : -1;
2283 for (
int i = 0; i < size(); ++i)
2291 std::reverse(vec_.begin(), vec_.end());
2298 std::vector<
int> inv(
size());
2299 for (
int i = 0; i < size(); ++i)
2322 for (
int i = 0; i < size(); ++i)
2323 std::swap(vec_[i], vec_[next(0, size() - 1)]);
2329 int pick()
const {
return vec_[next<
int>(0, size() - 1)]; }
2333 template <
typename Dist>
2336 "value and distribution must have the same size");
2337 return vec_[next_by_distribution(distribution)];
2339 template <
typename Dist>
2340 int pick_by_distribution(
2341 const std::initializer_list<Dist> &distribution)
const {
2342 return pick_by_distribution(std::vector<Dist>(distribution));
2346 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
2347 for (
int i = 0; i < val
.size(); ++i) {
2350 out << val
[i
] + val.add_1_;
2362 if (!cycle_sizes_) {
2364 std::vector<
int> idx_to_val(size_, -1), val_to_idx(size_, -1);
2365 for (
auto [idx, val] : defs_) {
2367 0 <= val
and val < size_,
2368 "permutation: value in permutation must be in [0, " +
2369 std::to_string(size_) +
")");
2371 if (idx_to_val[idx] != -1) {
2373 "permutation: cannot set an index to two "
2374 "different values");
2376 idx_to_val[idx] = val;
2378 if (val_to_idx[val] != -1) {
2380 "permutation: cannot set two indices to the "
2383 val_to_idx[val] = idx;
2386 std::vector<
int> perm(size_);
2387 std::iota(perm.begin(), perm.end(), 0);
2388 shuffle(perm.begin(), perm.end());
2390 for (
int &i : idx_to_val)
2393 while (val_to_idx[perm[cur_idx]] != -1)
2395 i = perm[cur_idx++];
2401 std::vector<
int> order(size_);
2402 std::iota(order.begin(), order.end(), 0);
2403 shuffle(order.begin(), order.end());
2405 std::vector<std::vector<
int>> cycles;
2406 for (
int cycle_size : *cycle_sizes_) {
2407 cycles.emplace_back();
2408 for (
int i = 0; i < cycle_size; ++i)
2409 cycles.back().push_back(order[idx++]);
2413 std::vector<
int> perm(size_, -1);
2414 for (
const std::vector<
int> &cycle : cycles) {
2415 int cur_size = cycle.size();
2416 for (
int i = 0; i < cur_size; ++i)
2417 perm[cycle[i]] = cycle[(i + 1) % cur_size];
2425
2426
2427
2428
2434using namespace tgen::detail;
2436inline int popcount(uint64_t x) {
return __builtin_popcountll(x); }
2438inline int ctzll(uint64_t x) {
2441 static const unsigned char index64[64] = {
2442 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
2443 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
2444 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
2445 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12};
2446 return index64[((x & -x) * 0x022FDD63CC95386D) >> 58];
2449inline uint64_t mul_mod(uint64_t a, uint64_t b, uint64_t m) {
2450 return static_cast<u128>(a) * b % m;
2455inline uint64_t expo_mod(uint64_t x, uint64_t y, uint64_t m) {
2458 uint64_t ans = expo_mod(mul_mod(x, x, m), y / 2, m);
2459 return y % 2 ? mul_mod(x, ans, m) : ans;
2468 if (n == 2
or n == 3)
2473 uint64_t r = detail::ctzll(n - 1), d = n >> r;
2475 for (
int a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) {
2476 uint64_t x = detail::expo_mod(a, d, n);
2477 if (x == 1
or x == n - 1
or a % n == 0)
2480 for (uint64_t j = 0; j < r - 1; ++j) {
2481 x = detail::mul_mod(x, x, n);
2493inline uint64_t pollard_rho(uint64_t n) {
2496 auto f = [n](uint64_t x) {
return mul_mod(x, x, n) + 1; };
2498 uint64_t x = 0, y = 0, t = 30, prd = 2, x0 = 1, q;
2499 while (t % 40 != 0
or std::gcd(prd, n) == 1) {
2502 q = mul_mod(prd, x > y ? x - y : y - x, n);
2505 x = f(x), y = f(f(y)), ++t;
2507 return std::gcd(prd, n);
2510inline std::vector<uint64_t> factor(uint64_t n) {
2515 uint64_t d = pollard_rho(n);
2516 std::vector<uint64_t> l = factor(d), r = factor(n / d);
2517 l.insert(l.end(), r.begin(), r.end());
2522template <
typename T>
2523std::runtime_error there_is_no_in_range_error(
const std::string &type, T l,
2525 return error(
"math: there is no " + type +
" in range [" +
2526 std::to_string(l) +
", " + std::to_string(r) +
"]");
2528template <
typename T>
2529std::runtime_error there_is_no_from_error(
const std::string &type, T r) {
2530 return error(
"math: there is no " + type +
" from " + std::to_string(r));
2532template <
typename T>
2533std::runtime_error there_is_no_upto_error(
const std::string &type, T r) {
2534 return error(
"math: there is no " + type +
" up to " + std::to_string(r));
2540inline i128 modular_inverse_128(i128 a, i128 mod) {
2542 "math: modular inverse requires 0 < value < mod");
2544 i128 t = 0, new_t = 1;
2545 i128 r = mod, new_r = a;
2547 while (new_r != 0) {
2550 auto tmp_t = t - q * new_t;
2554 auto tmp_r = r - q * new_r;
2559 tgen_ensure(r == 1,
"math: remainder and mod must be coprime");
2567inline bool mul_leq(uint64_t a, uint64_t b, uint64_t limit) {
2568 if (a == 0
or b == 0)
2570 return a <= limit / b;
2574inline std::optional<uint64_t> expo(uint64_t base, uint64_t exp,
2576 uint64_t result = 1;
2580 if (!mul_leq(result, base, limit))
2581 return std::nullopt;
2590 if (!mul_leq(base, base, limit))
2591 return std::nullopt;
2599inline uint64_t kth_root_floor(uint64_t n, uint64_t k) {
2600 tgen_ensure_against_bug(k > 0,
"math: value must be valid");
2601 if (k == 1
or n <= 1)
2604 uint64_t lo = 1, hi = 1ULL << ((64 + k - 1) / k);
2607 uint64_t mid = lo + (hi - lo + 1) / 2;
2609 if (expo(mid, k, n)) {
2620inline i128 gcd128(i128 a, i128 b) {
2636inline i128 mul_saturate(i128 a, i128 b) {
2638 static const i128 LIMIT =
static_cast<i128>(1) << 64;
2639 if (a == 0
or b == 0)
2650 crt() : a(0), m(1) {}
2651 crt(T a_, T m_) : a(a_), m(m_) {}
2652 crt operator*(crt C) {
2653 if (m == 0
or C.m == 0)
2656 T g = gcd128(m, C.m);
2657 if ((C.a - a) % g != 0)
2666 T inv = modular_inverse_128(m1 % m2, m2);
2668 T k = ((C.a - a) / g) % m2;
2672 k =
static_cast<u128>(k) * inv % m2;
2674 T lcm = mul_saturate(m, m2);
2676 T res = (a +
static_cast<T>((
static_cast<u128>(k) * m) % lcm)) % lcm;
2686inline constexpr long double LOG_ZERO = -INFINITY;
2687inline constexpr long double LOG_ONE = 0.0;
2689inline long double log_space(
long double x) {
2690 return x == 0.0 ? LOG_ZERO : std::log(x);
2694inline long double add_log_space(
long double a,
long double b) {
2699 return a + log1p(exp(b - a));
2704inline long double sub_log_space(
long double a,
long double b) {
2709 return a + log1p(-exp(b - a));
2718 tgen_ensure(n > 0,
"math: number to factor must be positive");
2719 auto factors = detail::factor(n);
2720 std::sort(factors.begin(), factors.end());
2728 tgen_ensure(n > 0,
"math: number to factor must be positive");
2729 std::vector<std::pair<uint64_t,
int>> primes;
2730 for (uint64_t p : factor(n)) {
2731 if (!primes.empty()
and primes.back().first == p)
2732 ++primes.back().second;
2734 primes.emplace_back(p, 1);
2743 return detail::modular_inverse_128(a, mod);
2749 tgen_ensure(n > 0,
"math: totient(0) is undefined");
2752 for (
auto [p, e] : factor_by_prime(n))
2759inline const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> &
2762 static const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> value{
2764 2, 3, 7, 23, 89, 113, 523, 887, 1129, 1327, 9551, 15683, 19609,
2765 31397, 155921, 360653, 370261, 492113, 1349533, 1357201, 2010733,
2766 4652353, 17051707, 20831323, 47326693, 122164747, 189695659,
2767 191912783, 387096133, 436273009, 1294268491, 1453168141,
2768 2300942549, 3842610773, 4302407359, 10726904659, 20678048297,
2769 22367084959, 25056082087, 42652618343, 127976334671, 182226896239,
2770 241160624143, 297501075799, 303371455241, 304599508537,
2771 416608695821, 461690510011, 614487453523, 738832927927,
2772 1346294310749, 1408695493609, 1968188556461, 2614941710599,
2773 7177162611713, 13829048559701, 19581334192423, 42842283925351,
2774 90874329411493, 171231342420521, 218209405436543, 1189459969825483,
2775 1686994940955803, 1693182318746371, 43841547845541059,
2776 55350776431903243, 80873624627234849, 203986478517455989,
2777 218034721194214273, 305405826521087869, 352521223451364323,
2778 401429925999153707, 418032645936712127, 804212830686677669,
2779 1425172824437699411, 5733241593241196731, 6787988999657777797
2781 {1, 2, 4, 6, 8, 14, 18, 20, 22, 34, 36,
2782 44, 52, 72, 86, 96, 112, 114, 118, 132, 148, 154,
2783 180, 210, 220, 222, 234, 248, 250, 282, 288, 292, 320,
2784 336, 354, 382, 384, 394, 456, 464, 468, 474, 486, 490,
2785 500, 514, 516, 532, 534, 540, 582, 588, 602, 652, 674,
2786 716, 766, 778, 804, 806, 906, 916, 924, 1132, 1184, 1198,
2787 1220, 1224, 1248, 1272, 1328, 1356, 1370, 1442, 1476, 1488, 1510}};
2796 throw detail::there_is_no_upto_error(
"prime gap", right);
2798 const auto &[P, G] = prime_gaps();
2799 for (
int i = P.size() - 1;; --i) {
2803 uint64_t real_right = std::min(right, P[i] + G[i] - 1);
2804 uint64_t prev = i > 0 ? G[i - 1] : 0;
2805 uint64_t curr = real_right - P[i];
2808 return {P[i] + 1, real_right};
2815 static const std::vector<uint64_t> highly_composites = {
2816 1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720, 840, 1260, 1680,
2817 2520, 5040, 7560, 10080, 15120, 20160, 25200, 27720, 45360, 50400, 55440,
2818 83160, 110880, 166320, 221760, 277200, 332640, 498960, 554400, 665280,
2819 720720, 1081080, 1441440, 2162160, 2882880, 3603600, 4324320, 6486480,
2820 7207200, 8648640, 10810800, 14414400, 17297280, 21621600, 32432400,
2821 36756720, 43243200, 61261200, 73513440, 110270160, 122522400, 147026880,
2822 183783600, 245044800, 294053760, 367567200, 551350800, 698377680, 735134400,
2823 1102701600, 1396755360, 2095133040, 2205403200, 2327925600, 2793510720,
2824 3491888400, 4655851200, 5587021440, 6983776800, 10475665200, 13967553600,
2825 20951330400, 27935107200, 41902660800, 48886437600, 64250746560,
2826 73329656400, 80313433200, 97772875200, 128501493120, 146659312800,
2827 160626866400, 240940299600, 293318625600, 321253732800, 481880599200,
2828 642507465600, 963761198400, 1124388064800, 1606268664000, 1686582097200,
2829 1927522396800, 2248776129600, 3212537328000, 3373164194400, 4497552259200,
2830 6746328388800, 8995104518400, 9316358251200, 13492656777600, 18632716502400,
2831 26985313555200, 27949074753600, 32607253879200, 46581791256000,
2832 48910880818800, 55898149507200, 65214507758400, 93163582512000,
2833 97821761637600, 130429015516800, 195643523275200, 260858031033600,
2834 288807105787200, 391287046550400, 577614211574400, 782574093100800,
2835 866421317361600, 1010824870255200, 1444035528936000, 1516237305382800,
2836 1732842634723200, 2021649740510400, 2888071057872000, 3032474610765600,
2837 4043299481020800, 6064949221531200, 8086598962041600, 10108248702552000,
2838 12129898443062400, 18194847664593600, 20216497405104000, 24259796886124800,
2839 30324746107656000, 36389695329187200, 48519593772249600, 60649492215312000,
2840 72779390658374400, 74801040398884800, 106858629141264000,
2841 112201560598327200, 149602080797769600, 224403121196654400,
2842 299204161595539200, 374005201994424000, 448806242393308800,
2843 673209363589963200, 748010403988848000, 897612484786617600,
2844 1122015605983272000, 1346418727179926400, 1795224969573235200,
2845 2244031211966544000, 2692837454359852800, 3066842656354276800,
2846 4381203794791824000, 4488062423933088000, 6133685312708553600,
2847 8976124847866176000, 9200527969062830400, 12267370625417107200ULL,
2848 15334213281771384000ULL, 18401055938125660800ULL};
2849 return highly_composites;
2854 for (
int i = highly_composites().size() - 1; i >= 0; --i)
2855 if (highly_composites()[i] <= right)
2856 return highly_composites()[i];
2858 throw detail::there_is_no_upto_error(
"highly composite number", right);
2864 if (right < left
or right < 2)
2865 throw detail::there_is_no_in_range_error(
"prime", left, right);
2866 left = std::max<uint64_t>(left, 2);
2867 auto [l_gap, r_gap] = prime_gap_upto(right);
2868 if (right - left + 1 <= r_gap - l_gap + 1) {
2870 std::vector<uint64_t> vals(right - left + 1);
2871 iota(vals.begin(), vals.end(), left);
2872 shuffle(vals.begin(), vals.end());
2873 for (uint64_t i : vals)
2876 throw detail::there_is_no_in_range_error(
"prime", left, right);
2881 n = next(left, right);
2889 tgen_ensure(left <= std::numeric_limits<uint64_t>::max() - 58,
2890 "math: invalid bound");
2891 for (uint64_t i = std::max<uint64_t>(2, left);; ++i)
2899 for (uint64_t i = right; i >= 2; --i)
2902 throw detail::there_is_no_upto_error(
"prime", right);
2909 for (
auto [p, e] : factor_by_prime(n))
2910 divisors *= (e + 1);
2918 int divisor_count) {
2920 "math: divisor count must be prime");
2921 int root = divisor_count - 1;
2922 uint64_t p =
gen_prime(detail::kth_root_floor(left, root)
,
2923 detail::kth_root_floor(right, root)
);
2924 return *detail::expo(p, root, right);
2931 std::vector<uint64_t> rems,
2932 std::vector<uint64_t> mods) {
2934 throw detail::there_is_no_in_range_error(
"congruent number", left,
2937 "math: number of remainders and mods must be the same");
2938 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
2941 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
2943 "math: remainder must be smaller than the mod");
2944 crt = crt * detail::crt(rems[i], mods[i]);
2947 throw detail::there_is_no_in_range_error(
"congruent number", left,
2949 if (crt.m > right) {
2950 if (!(left <= crt.a
and crt.a <= right))
2951 throw detail::there_is_no_in_range_error(
"congruent number",
2954 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
2955 if (crt.a % mods[j] != rems[j])
2956 throw detail::there_is_no_in_range_error(
"congruent number",
2962 uint64_t k_min = crt.a >= left ? 0 : ((left - crt.a) + crt.m - 1) / crt.m;
2963 uint64_t k_max = (right - crt.a) / crt.m;
2966 throw detail::there_is_no_in_range_error(
"congruent number", left,
2969 return crt.a + next(k_min, k_max) * crt.m;
2976 return gen_congruent(left, right, std::vector<uint64_t>({rem}),
2977 std::vector<uint64_t>({mod}));
2985 std::vector<uint64_t> mods) {
2987 "math: number of remainders and mods must be the same");
2988 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
2991 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
2993 "math: remainder must be smaller than the mod");
2994 crt = crt * detail::crt(rems[i], mods[i]);
2997 throw detail::there_is_no_from_error(
"congruent number", left);
2998 if (crt.m > std::numeric_limits<uint64_t>::max()) {
3000 throw detail::error(
3001 "math: congruent number does not exist or is too large");
3003 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
3004 if (crt.a % mods[j] != rems[j])
3005 throw detail::error(
"math: congruent number does "
3006 "not exist or is too large");
3013 k = ((left - crt.a) + crt.m - 1) / crt.m;
3014 detail::i128 result = crt.a + k * crt.m;
3016 if (result > std::numeric_limits<uint64_t>::max())
3017 throw detail::error(
"math: congruent number is too large");
3024 return congruent_from(left, std::vector<uint64_t>{rem},
3025 std::vector<uint64_t>{mod});
3033 std::vector<uint64_t> mods) {
3035 "math: number of remainders and mods must be the same");
3036 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
3039 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
3041 "math: remainder must be smaller than the mod");
3043 crt = crt * detail::crt(rems[i], mods[i]);
3046 throw detail::there_is_no_upto_error(
"congruent number", right);
3047 if (crt.m > right) {
3048 if (!(crt.a <= right))
3049 throw detail::there_is_no_upto_error(
"congruent number", right);
3051 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
3052 if (crt.a % mods[j] != rems[j])
3053 throw detail::there_is_no_upto_error(
"congruent number",
3060 throw detail::there_is_no_upto_error(
"congruent number", right);
3062 uint64_t k = (right - crt.a) / crt.m;
3063 detail::i128 result = crt.a + k * crt.m;
3066 throw detail::there_is_no_upto_error(
"congruent number", right);
3073 return congruent_upto(right, std::vector<uint64_t>{rem},
3074 std::vector<uint64_t>{mod});
3082 static const std::vector<uint64_t> fib = [] {
3083 std::vector<uint64_t> v = {0, 1};
3085 std::numeric_limits<uint64_t>::max() - v[v.size() - 2])
3086 v.push_back(v.back() + v[v.size() - 2]);
3098 std::optional<
int> part_right = std::nullopt) {
3099 if (!part_right.has_value())
3101 part_right = std::min(*part_right, n);
3103 "math: invalid parameters to gen_partition");
3104 tgen_ensure(part_left <= n
and *part_right > 0,
"math: no such partition");
3107 std::vector<
long double> dp(n + 1, detail::LOG_ZERO);
3108 dp[0] = detail::LOG_ONE;
3109 long double window = detail::LOG_ZERO;
3110 for (
int i = 1; i <= n; ++i) {
3112 window = detail::add_log_space(window, dp[i - part_left]);
3113 if (i >= *part_right + 1)
3114 window = detail::sub_log_space(window, dp[i - *part_right - 1]);
3117 tgen_ensure(dp[n] >= 0,
"math: no such partition");
3121 for (
int i = 1; i <= n; ++i)
3122 dp_pref[i] = detail::add_log_space(dp_pref[i - 1], dp[i]);
3124 std::vector<
int> part;
3128 int l = std::max(0, sum - *part_right), r = sum - part_left;
3129 detail::tgen_ensure_against_bug(r >= 0,
"math: r < 0 in gen_partition");
3131 int nxt_sum = std::min(sum, r);
3132 long double random = next<
long double>(0, 1);
3143 long double val_l = l ? dp_pref[l - 1] : detail::LOG_ZERO,
3145 while (nxt_sum > l
and
3146 dp_pref[nxt_sum - 1] >=
3147 val_r + detail::log_space(random +
3148 (1 - random) * exp(val_l - val_r)))
3151 part.push_back(sum - nxt_sum);
3164 std::optional<
int> part_right = std::nullopt) {
3165 if (!part_right.has_value())
3167 part_right = std::min(*part_right, n);
3169 "math: invalid parameters to gen_partition_fixed_size");
3170 tgen_ensure(
static_cast<
long long>(k) * part_left <= n
and
3171 n <=
static_cast<
long long>(k) * (*part_right),
3172 "math: no such partition");
3175 int s = n - k * part_left;
3177 std::vector<
int> part(k);
3178 if (*part_right == n) {
3180 std::vector<
int> cuts = {-1};
3182 int total = s + k - 1, bars = k - 1;
3183 for (
int i = 0; i < total
and bars > 0; ++i)
3184 if (next<
long double>(0, 1) <
3185 static_cast<
long double>(bars) / (total - i)) {
3189 cuts.push_back(total);
3192 for (
int i = 0; i < k; ++i)
3193 part[i] = cuts[i + 1] - cuts[i] - 1;
3196 int u = *part_right - part_left;
3199 std::vector<std::vector<
long double>> dp(
3200 k + 1, std::vector<
long double>(s + 1, detail::LOG_ZERO));
3201 dp[0][0] = detail::LOG_ONE;
3203 for (
int i = 1; i <= k; ++i) {
3204 std::vector<
long double> pref = dp[i - 1];
3205 for (
int j = 1; j <= s; ++j)
3206 pref[j] = detail::add_log_space(pref[j - 1], dp[i - 1][j]);
3208 for (
int j = 0; j <= s; ++j) {
3211 dp[i][j] = detail::sub_log_space(dp[i][j], pref[j - u - 1]);
3216 int left_to_distribute = s;
3217 for (
int i = k; i >= 1; --i) {
3218 long double log_total = detail::LOG_ZERO;
3219 for (
int j = 0; j <= u
and j <= left_to_distribute; ++j)
3220 log_total = detail::add_log_space(
3221 log_total, dp[i - 1][left_to_distribute - j]);
3222 detail::tgen_ensure_against_bug(
3223 log_total != detail::LOG_ZERO,
3224 "math: total == 0 in gen_partition_fixed_size");
3230 long double random =
3231 detail::log_space(next<
long double>(0, 1)) + log_total;
3233 long double cur_prob = detail::LOG_ZERO;
3235 for (
int j = 0; j <= u
and j <= left_to_distribute; ++j) {
3236 cur_prob = detail::add_log_space(
3237 cur_prob, dp[i - 1][left_to_distribute - j]);
3238 if (random < cur_prob) {
3244 part[k - i] = chosen;
3245 left_to_distribute -= chosen;
3262 uint64_t n,
int k, uint64_t part_left = 0,
3263 std::optional<uint64_t> part_right = std::nullopt) {
3264 if (!part_right.has_value())
3266 part_right = std::min(*part_right, n);
3268 detail::u128 n128 = n;
3269 detail::u128 k128 = k;
3270 detail::u128 part_left128 = part_left;
3271 detail::u128 part_right128 = *part_right;
3274 "math: invalid parameters to gen_partition_fixed_size_fast");
3276 k128 * part_left128 <= n128
and
3277 k128 * part_right128 >= n128,
3278 "math: no such partition");
3280 uint64_t slack_total = n128 - k128 * part_left128;
3281 uint64_t slack_max = part_right128 - part_left128;
3283 std::vector<uint64_t> part(k);
3285 part[0] = slack_total;
3287 std::vector<uint64_t> cuts(k - 1);
3288 for (uint64_t &d : cuts)
3289 d = next<uint64_t>(0, slack_total);
3290 std::sort(cuts.begin(), cuts.end());
3293 for (
int i = 0; i + 1 < k; ++i) {
3294 part[i] = cuts[i] - prev;
3297 part[k - 1] = slack_total - prev;
3300 auto add_part_left = [part_left](uint64_t x) -> uint64_t {
3301 detail::u128 val = x + part_left;
3302 detail::tgen_ensure_against_bug(
3303 val <= std::numeric_limits<uint64_t>::max(),
3304 "math: part + part_left exceeds uint64_t in "
3305 "gen_partition_fixed_size_fast");
3309 if (slack_max >= slack_total) {
3310 for (uint64_t &x : part)
3311 x = add_part_left(x);
3315 detail::u128 remaining = 0;
3316 for (uint64_t &x : part) {
3317 if (x > slack_max) {
3318 remaining += x - slack_max;
3321 x = add_part_left(x);
3324 if (remaining > 0) {
3325 for (uint64_t &x : part) {
3326 if (x < *part_right && remaining > 0) {
3327 detail::u128 room = *part_right - x;
3328 detail::u128 add = std::min(remaining, room);
3329 detail::u128 val = x + add;
3330 detail::tgen_ensure_against_bug(
3332 "math: part exceeds part_right after redistribution in "
3333 "gen_partition_fixed_size_fast");
3338 detail::tgen_ensure_against_bug(
3339 remaining == 0,
"math: remaining mass after redistribution in "
3340 "gen_partition_fixed_size_fast");
3350template <
typename T>
3353 std::optional<uint64_t> max_size = std::nullopt) {
3354 size_t n = elements.size();
3355 tgen_ensure(k > 0,
"math: partition_elements: k must be positive");
3357 "math: partition_elements: min_size must be non-negative");
3359 std::vector<uint64_t> sizes;
3360 if (max_size.has_value()) {
3361 sizes = gen_partition_fixed_size_fast(n, k, min_size, max_size);
3363 for (
int sz : gen_partition_fixed_size(n, k, min_size))
3364 sizes.push_back(sz);
3367 std::vector<std::vector<T>> groups;
3370 for (uint64_t sz : sizes) {
3371 groups.emplace_back(elements.begin() + pos,
3372 elements.begin() + pos + sz);
3381
3382
3383
3384
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
3416
3417
3427 std::vector<regex_node> children_;
3428 int left_bound_, right_bound_;
3431 log_space_num_ways_;
3436 regex_node(
const std::string &pattern)
3437 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3438 if (pattern.size() == 1) {
3439 log_space_num_ways_ = math::detail::LOG_ONE;
3442 tgen_ensure_against_bug(pattern[0] ==
'[' and pattern.back() ==
']',
3443 "str: invalid regex: expected character class");
3444 int size = pattern.size() - 2;
3445 log_space_num_ways_ = math::detail::log_space(size);
3446 distinct_ = distinct_container<
char>(pattern.substr(1, size));
3449 regex_node(
const std::string &pattern, std::vector<regex_node> &children)
3450 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3451 if (pattern ==
"SEQ") {
3453 log_space_num_ways_ = math::detail::LOG_ONE;
3454 for (
const auto &child : children)
3455 log_space_num_ways_ += child.log_space_num_ways_;
3456 }
else if (pattern ==
"OR") {
3458 log_space_num_ways_ = math::detail::LOG_ZERO;
3459 for (
const auto &child : children)
3460 log_space_num_ways_ = math::detail::add_log_space(
3461 log_space_num_ways_, child.log_space_num_ways_);
3463 tgen_ensure_against_bug(
"str: invalid regex: expected SEQ or OR");
3465 children_ = std::move(children);
3469 regex_node(
int left_bound,
int right_bound, regex_node &child)
3470 : pattern_(
"REP"), left_bound_(left_bound), right_bound_(right_bound) {
3471 log_space_num_ways_ = math::detail::LOG_ZERO;
3472 for (
int i = left_bound; i <= right_bound; ++i)
3473 log_space_num_ways_ = math::detail::add_log_space(
3474 log_space_num_ways_, i * child.log_space_num_ways_);
3476 children_.push_back(std::move(child));
3482 std::vector<regex_node> cur;
3483 std::vector<regex_node> branches;
3487inline regex_node make_regex_seq(regex_state &st) {
3488 return regex_node(
"SEQ", st.cur);
3492inline regex_node finish_regex_state(regex_state &st) {
3494 if (st.branches.empty())
3495 return make_regex_seq(st);
3498 st.branches.push_back(make_regex_seq(st));
3499 return regex_node(
"OR", st.branches);
3504inline regex_node parse_regex(std::string regex) {
3505 std::string new_regex;
3506 for (
char c : regex)
3509 swap(regex, new_regex);
3511 std::vector<regex_state> stack;
3513 for (size_t i = 0; i < regex.size(); ++i) {
3518 stack.push_back(std::move(cur));
3519 cur = regex_state();
3520 }
else if (c ==
')') {
3522 regex_node node = finish_regex_state(cur);
3524 tgen_ensure(!stack.empty(),
"str: invalid regex: unmatched `)`");
3525 cur = std::move(stack.back());
3528 cur.cur.push_back(std::move(node));
3529 }
else if (c ==
'|') {
3531 regex_node node = make_regex_seq(cur);
3532 cur.branches.push_back(std::move(node));
3533 }
else if (c ==
'[') {
3537 for (++i; i < regex.size()
and regex[i] !=
']'; ++i) {
3538 if (i + 2 < regex.size()
and regex[i + 1] ==
'-') {
3539 char a = regex[i], b = regex[i + 2];
3542 for (
char x = a; x <= b; ++x)
3550 "str: invalid regex: unmatched `[`");
3551 cur.cur.emplace_back(
"[" + chars +
"]");
3552 }
else if (c ==
'{') {
3557 while (i < regex.size()
and
3558 isdigit(
static_cast<
unsigned char>(regex[i]))) {
3562 "str: invalid regex: number too large inside `{}`");
3563 l = 10 * l + (regex[i] -
'0');
3567 if (i < regex.size()
and regex[i] ==
',') {
3569 while (i < regex.size()
and
3570 isdigit(
static_cast<
unsigned char>(regex[i]))) {
3574 r <=
static_cast<
int>(1e8),
3575 "str: invalid regex: number too large inside `{}`");
3576 r = 10 * r + (regex[i] -
'0');
3583 "str: invalid regex: unmatched `{`");
3585 "str: invalid regex: missing number inside `{}`");
3587 "str: invalid regex: invalid range inside `{}`");
3591 "str: invalid regex: expected expression before `{}`");
3593 regex_node rep(l, r, cur.cur.back());
3595 cur.cur.push_back(std::move(rep));
3598 cur.cur.emplace_back(std::string(1, c));
3602 tgen_ensure(stack.empty(),
"str: invalid regex: unmatched `(`");
3603 return finish_regex_state(cur);
3607inline void gen_regex(
const regex_node &node, std::string &str) {
3609 if (node.pattern_[0] ==
'[') {
3610 str += node.pattern_[1 + next<
int>(0, node.pattern_.size() - 3)];
3615 if (node.left_bound_ != -1) {
3619 double log_rand = math::detail::log_space(next<
double>(0, 1)) +
3620 node.log_space_num_ways_;
3621 double cur_prob = math::detail::LOG_ZERO;
3622 double child_num_ways = node.children_[0].log_space_num_ways_;
3624 for (
int i = node.left_bound_; i <= node.right_bound_; ++i) {
3626 math::detail::add_log_space(cur_prob, i * child_num_ways);
3627 if (log_rand <= cur_prob) {
3628 for (
int j = 0; j < i; ++j)
3629 gen_regex(node.children_[0], str);
3634 tgen_ensure_against_bug(
false,
3635 "str: log_rand > cur_prob in REP gen_regex");
3639 if (!node.children_.empty()
and node.pattern_ ==
"SEQ") {
3640 for (
const regex_node &child : node.children_)
3641 gen_regex(child, str);
3646 if (!node.children_.empty()
and node.pattern_ ==
"OR") {
3650 double log_rand = math::detail::log_space(next<
double>(0, 1)) +
3651 node.log_space_num_ways_;
3652 double cur_prob = math::detail::LOG_ZERO;
3654 for (
const regex_node &child : node.children_) {
3655 cur_prob = math::detail::add_log_space(cur_prob,
3656 child.log_space_num_ways_);
3657 if (log_rand <= cur_prob) {
3658 gen_regex(child, str);
3663 tgen_ensure_against_bug(
false,
3664 "str: log_rand > cur_prob in OR gen_regex");
3668 detail::tgen_ensure_against_bug(
3669 node.pattern_.size() == 1,
3670 "str: invalid regex: expected single character, but got `" +
3671 node.pattern_ +
"`");
3672 str += node.pattern_[0];
3676template <
typename... Args>
3677std::string regex_format(
const std::string &s, Args &&...args) {
3678 if constexpr (
sizeof...(Args) == 0) {
3681 int size = std::snprintf(
nullptr, 0, s.c_str(), args...) + 1;
3682 std::string buf(size,
'\0');
3683 std::snprintf(buf.data(), size, s.c_str(), args...);
3692
3693
3696 std::optional<
list<
char>> list_;
3697 std::optional<detail::regex_node>
3702 str(
int size,
char value_left =
'a',
char value_right =
'z') {
3703 tgen_ensure(size > 0,
"str: size must be positive");
3704 list_ = list<
char>(size, value_left, value_right);
3709 str(
int size, std::set<
char> chars) {
3710 tgen_ensure(size > 0,
"str: size must be positive");
3711 list_ = list<
char>(size, chars);
3715 template <
typename... Args>
str(
const std::string ®ex, Args &&...args) {
3716 tgen_ensure(regex.size() > 0,
"str: regex must be non-empty");
3718 root_ = detail::parse_regex(
3719 detail::regex_format(regex, std::forward<Args>(args)...));
3724 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3725 list_->fix(idx, character);
3731 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3732 list_->equal(indices);
3738 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3739 list_->equal(idx_1, idx_2);
3745 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3746 list_->equal_range(left, right);
3752 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3759 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3760 tgen_ensure(0 <= left
and left <= right
and right < list_->size_,
3761 "str: range indices must be valid");
3762 for (
int i = left; i < right - (i - left); ++i)
3769 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3770 return palindrome(0, list_->size_ - 1);
3776 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3777 list_->different(indices);
3783 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3784 list_->different(idx_1, idx_2);
3790 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3791 list_->different_range(left, right);
3797 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3798 list_->all_different();
3804 using tgen_is_sequential_tag = detail::is_sequential_tag;
3806 using value_type =
char;
3807 using std_type = std::string;
3810 value(
const std::string &str) : str_(str) {
3811 tgen_ensure(!str_.empty(),
"str: value: cannot be empty");
3815 int size()
const {
return str_.size(); }
3820 "str: value: index out of bounds");
3823 const char &operator[](
int idx)
const {
3825 "str: value: index out of bounds");
3832 std::sort(str_.begin(), str_.end());
3839 std::reverse(str_.begin(), str_.end());
3846 for (
char &c : str_)
3847 c = std::tolower(c);
3854 for (
char &c : str_)
3855 c = std::toupper(c);
3862 return value(str_ + rhs.str_
);
3868 for (
int i = 0; i < size(); ++i)
3869 std::swap(str_[i], str_[next(0, size() - 1)]);
3879 template <
typename Dist>
3882 "value and distribution must have the same size");
3883 return str_[next_by_distribution(distribution)];
3885 template <
typename Dist>
3886 char pick_by_distribution(
3887 const std::initializer_list<Dist> &distribution)
const {
3888 return pick_by_distribution(std::vector<Dist>(distribution));
3895 "number of elements to choose must be valid");
3896 std::string new_str;
3898 for (
int i = 0; need > 0; ++i) {
3900 if (next(1, left) <= need) {
3901 new_str.push_back(str_[i]);
3909 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
3910 return out << val.str_;
3914 std::string
to_std()
const {
return std_type(str_); }
3923 std::string ret_str;
3924 gen_regex(*root_, ret_str);
3928 std::vector<
char> vec = list_->gen().to_std();
3929 return value(std::string(vec.begin(), vec.end()));
3935
3936
3937
3938
3944template <
typename T> std::pair<T, T> gen_eq(T L1, T R1, T L2, T R2) {
3945 T L = std::max(L1, L2);
3946 T R = std::min(R1, R2);
3948 tgen_ensure(L <= R,
"pair: no valid values to generate");
3949 T x = next<T>(L, R);
3954template <
typename T>
3955std::pair<u128, u128> get_n_and_m(T L1, T R1, T L2, T R2) {
3956 u128 n =
static_cast<i128>(R1) - L1 + 1;
3957 u128 m =
static_cast<i128>(R2) - L2 + 1;
3963static u128 pos_arith_sum(u128 first, u128 last, u128 num_terms) {
3964 u128 x = first + last, y = num_terms;
3977template <
typename T> std::pair<T, T> gen_neq(T L1, T R1, T L2, T R2) {
3978 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
3980 T L_intersect = std::max(L1, L2);
3981 T R_intersect = std::min(R1, R2);
3982 u128 inter =
static_cast<i128>(R_intersect) - L_intersect + 1;
3984 u128 total = n * m - inter;
3985 tgen_ensure(total > 0,
"pair: no valid values to generate");
3990 a = next<T>(L1, R1);
3991 b = next<T>(L2, R2);
4002template <
typename T>
4003std::pair<u128, u128> count_lt_regions(T L1, T R1, T L2, T R2) {
4004 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4007 i128 L_second = std::max<i128>(L2,
static_cast<i128>(L1) + 1);
4011 i128 split = std::min<i128>(R_second, R1);
4014 u128 len1 = std::max<i128>(0, split - L_second + 1);
4016 u128 count_region1 = 0;
4019 i128 first = L_second - L1;
4020 i128 last = split - L1;
4023 count_region1 = pos_arith_sum(first, last, len1);
4028 i128 L_second_region2 = std::max(L_second,
static_cast<i128>(R1) + 1);
4030 u128 len2 = std::max<i128>(0, R_second - L_second_region2 + 1);
4031 u128 count_region2 = len2 * n;
4033 return {count_region1, count_region2};
4038template <
typename T> std::pair<T, T> gen_lt(T L1, T R1, T L2, T R2) {
4039 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4043 i128 L_second = std::max<i128>(L2,
static_cast<i128>(L1) + 1);
4049 i128 split = std::min<i128>(R_second, R1);
4051 auto [count_region1, count_region2] = count_lt_regions(L1, R1, L2, R2);
4052 u128 total = count_region1 + count_region2;
4053 tgen_ensure(total > 0,
"pair: no valid values to generate");
4055 u128 k = detail::next128(total);
4056 if (k < count_region1) {
4060 u128 len1 = std::max<i128>(0, split - L_second + 1);
4067 i128 base = L_second - L1;
4068 i128 lo = 0, hi =
static_cast<i128>(len1) - 1;
4071 i128 mid = lo + (hi - lo) / 2;
4073 if (pos_arith_sum(base, base + mid, mid + 1) <= k)
4082 k -= pos_arith_sum(base, base + d - 1, d);
4084 return {L1 +
static_cast<T>(k), L_second + d};
4090 i128 L_second_region2 = std::max(L_second,
static_cast<i128>(R1) + 1);
4092 return {L1 +
static_cast<T>(k % n),
4093 L_second_region2 +
static_cast<T>(k / n)};
4099template <
typename T> std::pair<T, T> gen_gt(T L1, T R1, T L2, T R2) {
4100 auto [first, second] = gen_lt(L2, R2, L1, R1);
4101 return {second, first};
4106template <
typename T> std::pair<T, T> gen_leq(T L1, T R1, T L2, T R2) {
4108 i128 L_intersect = std::max(L1, L2);
4109 i128 R_intersect = std::min(R1, R2);
4110 u128 eq_count = std::max<i128>(0, R_intersect - L_intersect + 1);
4113 auto [lt_region1, lt_region2] = count_lt_regions(L1, R1, L2, R2);
4114 u128 lt_count = lt_region1 + lt_region2;
4116 u128 total = eq_count + lt_count;
4117 tgen_ensure(total > 0,
"pair: no valid values to generate");
4119 if (detail::next128(total) < eq_count)
4120 return gen_eq(L1, R1, L2, R2);
4121 return gen_lt(L1, R1, L2, R2);
4126template <
typename T> std::pair<T, T> gen_geq(T L1, T R1, T L2, T R2) {
4127 auto [first, second] = gen_leq(L2, R2, L1, R1);
4128 return {second, first};
4134
4135
4136
4137
4140 std::pair<T, T> first_, second_;
4142 enum class restriction_type { eq, neq, lt, gt, leq, geq, unspecified };
4143 restriction_type type_ = restriction_type::unspecified;
4147 pair(T first_left, T first_right, T second_left, T second_right)
4148 : first_(first_left, first_right), second_(second_left, second_right) {
4150 "pair: first range must be valid");
4152 "pair: second range must be valid");
4157 :
pair(both_left, both_right, both_left, both_right) {}
4161 type_ = restriction_type::eq;
4167 type_ = restriction_type::neq;
4173 type_ = restriction_type::lt;
4179 type_ = restriction_type::gt;
4185 type_ = restriction_type::leq;
4191 type_ = restriction_type::geq;
4197 using value_type = T;
4198 using std_type = std::pair<T, T>;
4200 std::pair<T, T> pair_;
4203 value(
const std::pair<T, T> &pair) : pair_(pair), sep_(
' ') {}
4205 : pair_(first, second), sep_(
' ') {}
4217 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
4218 return out << val.pair_.first << val.sep_ << val.pair_.second;
4223 if constexpr (!detail::is_generator_value<T>::value) {
4226 std::pair<
typename T::std_type,
typename T::std_type> pair(
4227 pair_.first.to_std(), pair_.second.to_std());
4236 T L1 = first_.first, R1 = first_.second;
4237 T L2 = second_.first, R2 = second_.second;
4240 case restriction_type::unspecified:
4241 return {next<T>(L1, R1), next<T>(L2, R2)};
4242 case restriction_type::eq:
4243 return detail::gen_eq<T>(L1, R1, L2, R2);
4244 case restriction_type::neq:
4245 return detail::gen_neq<T>(L1, R1, L2, R2);
4246 case restriction_type::lt:
4247 return detail::gen_lt<T>(L1, R1, L2, R2);
4248 case restriction_type::gt:
4249 return detail::gen_gt<T>(L1, R1, L2, R2);
4250 case restriction_type::leq:
4251 return detail::gen_leq<T>(L1, R1, L2, R2);
4252 case restriction_type::geq:
4253 return detail::gen_geq<T>(L1, R1, L2, R2);
4255 throw detail::error(
"pair: unknown restriction type");
4260
4261
4262
4263
4269inline std::vector<std::pair<
int,
int>> edges_from_prufer(std::vector<
int> p) {
4270 int n = p.size() + 2;
4273 std::vector<
int> d(n, 1);
4282 idx = u = find(d.begin(), d.end(), 1) - d.begin();
4285 std::vector<std::pair<
int,
int>> edges;
4287 edges.emplace_back(u, v);
4288 if (--d[v] == 1
and v < idx)
4291 idx = u = find(d.begin() + idx + 1, d.end(), 1) - d.begin();
4298 std::vector<
int> parent_;
4299 std::vector<
unsigned char> rank_;
4304 dsu(
int n) : parent_(n), rank_(n, 0) {
4305 for (
int i = 0; i < n; ++i)
4311 void add_elements(
int k) {
4312 for (
int i = 0; i < k; ++i) {
4313 int new_id = parent_.size();
4314 parent_.push_back(new_id);
4322 return parent_[i] == i ? i : parent_[i] = find(parent_[i]);
4328 bool unite(
int a,
int b) {
4333 if (rank_[a] > rank_[b])
4336 if (rank_[a] == rank_[b])
4345template <
typename VWeight,
typename EWeight>
struct wgraph;
4348
4349
4350
4351
4352
4353
4354
4355
4357template <
typename VWeight,
typename EWeight>
4360 std::set<std::pair<
int,
int>> edges_;
4365 tgen_ensure(n > 0,
"wtree: number of vertices must be positive");
4371 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n_,
4372 "wtree: vertices must be indexed in [0, n)");
4373 tgen_ensure(u != v,
"wtree: cannot add self loop to tree");
4377 edges_.emplace(u, v);
4389 std::vector<std::set<
int>> adj_;
4390 std::vector<std::pair<
int,
int>> edges_;
4393 std::optional<
int> print_parents_;
4395 std::optional<std::vector<VWeight>> vertex_weights_;
4396 std::optional<std::vector<EWeight>>
4402 value(
const std::vector<std::set<
int>> &adj)
4403 : n_(
static_cast<
int>(adj.size())),
adj_(
adj), add_1_(
false),
4404 print_n_(
false),
dsu_(
n_) {
4405 for (
int u = 0; u < n_; ++u)
4406 for (
auto v : adj[u]) {
4409 "wtree: value: vertices must be indexed in [0, n)");
4412 edges_.emplace_back(u, v);
4415 "wtree: value: initial graph must form a tree");
4422 value(
int n,
const std::vector<std::pair<
int,
int>> &edges)
4423 : n_(n),
adj_(
n), add_1_(
false), print_n_(
false),
dsu_(
n) {
4424 edges_.reserve(edges.size());
4425 for (
auto [u, v] : edges) {
4426 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n,
4427 "wtree: value: vertices must be indexed in [0, n)");
4429 "wtree: value: initial graph must form a tree");
4432 edges_.emplace_back(u, v);
4437 value(
int n,
const std::set<std::pair<
int,
int>> &edges)
4440 value(
int n,
const std::initializer_list<std::pair<
int,
int>> &edges)
4441 : value(n, std::vector<std::pair<
int,
int>>(edges)) {}
4446 value(
const typename wgraph<VWeight, EWeight>::value &g);
4450 template <
typename NewVWeight,
typename NewEWeight>
4451 typename wtree<NewVWeight, NewEWeight>::value
4452 convert_weight_types()
const {
4454 !edge_weights_.has_value(),
4455 "wtree: value: cannot convert weight type after "
4456 "assigning weights");
4458 typename wtree<NewVWeight, NewEWeight>::value new_tree(adj_);
4459 new_tree.add_1_ = add_1_;
4460 new_tree.print_n_ = print_n_;
4461 new_tree.print_parents_ = print_parents_;
4466 int n()
const {
return n_; }
4476 return vertex_weights_;
4481 return edge_weights_;
4486 template <
typename NewVWeight = VWeight>
4488 const std::vector<NewVWeight> &vertex_weights)
const {
4490 "wtree: value: must give `n` vertex weights");
4492 auto new_tree = convert_weight_types<NewVWeight, EWeight>();
4493 new_tree.vertex_weights_ = vertex_weights;
4499 template <
typename NewEWeight = EWeight>
4503 edge_weights.size() == edges().size(),
4504 "wtree: value: must give `edges().size()` edge weights");
4506 auto new_tree = convert_weight_types<VWeight, NewEWeight>();
4507 new_tree.edge_weights_ = edge_weights;
4515 "wtree: value: edge_weighted requires a tree with no "
4518 "wtree: value: tree is already edge-weighted");
4520 edge_weights_ = std::vector<EWeight>();
4544 "wtree: value: root must be -1, `n`, or in [0, n)");
4545 print_parents_ = root;
4558 std::vector<
int> new_label(
n());
4559 std::vector<
int> shuffled;
4560 for (
int i = 0; i <
n(); ++i) {
4561 if (indices.count(i))
4564 shuffled.push_back(i);
4566 std::vector<
int> targets = shuffled;
4567 tgen::shuffle(targets.begin(), targets.end());
4568 for (size_t k = 0; k < shuffled.size(); ++k)
4569 new_label[shuffled[k]] = targets[k];
4572 std::vector<std::set<
int>> new_adj(
n());
4573 for (
int u = 0; u < n(); ++u)
4574 for (
int v : adj_[u])
4575 new_adj[new_label[u]].insert(new_label[v]);
4576 adj_ = std::move(new_adj);
4579 for (
auto &[u, v] : edges_) {
4587 if (vertex_weights_.has_value()) {
4588 std::vector<VWeight> new_vw(
n());
4589 for (
int i = 0; i < n(); ++i)
4590 new_vw[new_label[i]] = (*vertex_weights_)[i];
4591 vertex_weights_ = std::move(new_vw);
4595 dsu_ = detail::dsu(n());
4596 for (
auto [u, v] : edges_)
4601 std::vector<
int> perm(edges_.size());
4602 std::iota(perm.begin(), perm.end(), 0);
4603 tgen::shuffle(perm.begin(), perm.end());
4605 std::vector<std::pair<
int,
int>> new_edges;
4606 std::optional<std::vector<EWeight>> new_ew;
4607 if (edge_weights_.has_value())
4608 new_ew = std::vector<EWeight>();
4609 for (
int i : perm) {
4610 new_edges.push_back(edges_[i]);
4611 if (new_ew.has_value())
4612 new_ew->push_back((*edge_weights_)[i]);
4615 if (new_ew.has_value())
4616 edge_weights_ = new_ew;
4627 value &add_edge(
int u,
int v, std::optional<EWeight> w = std::nullopt) {
4629 "wtree: value: vertex ids must be valid");
4634 if (adj_[u].count(v))
4639 edges_.emplace_back(u, v);
4641 "wtree: value: added edge must not create a cycle");
4643 if (w.has_value()) {
4645 "wtree: value: cannot add weighted edge to "
4646 "edge-unweighted tree");
4648 edge_weights_->push_back(*w);
4651 "wtree: value: cannot add unweighted edge to "
4652 "edge-weighted tree");
4662 std::optional<EWeight> new_w = std::nullopt) {
4665 "wtree: value: vertex ids must be valid");
4669 add_vertices(rhs.n(), rhs.vertex_weights());
4670 for (
int i = 0; i <
static_cast<
int>(rhs.edges().size()); ++i) {
4671 auto [u, v] = rhs.edges()[i];
4672 add_edge(shift + u, shift + v,
4673 rhs.edge_weights().has_value()
4674 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4679 add_edge(new_u, shift + new_v, new_w);
4689 std::set<std::pair<
int,
int>> index_pairs) {
4691 std::set<
int> idx_left, idx_right;
4692 std::vector<
int> right_id_to_left(rhs
.n(), -1);
4693 for (
auto [l, r] : index_pairs) {
4695 0 <= l
and l < n()
and 0 <= r
and r < rhs.n(),
4696 "wtree: value: vertex indices to glue must be valid");
4697 tgen_ensure(idx_left.count(l) == 0
and idx_right.count(r) == 0,
4698 "wtree: value: must not have repeated indices "
4699 "on the same side to glue");
4702 idx_right.insert(r);
4703 right_id_to_left[r] = l;
4707 std::vector<
int> new_right_id(rhs
.n(), -1);
4708 int intersection_lt = 0;
4709 std::optional<std::vector<VWeight>> rhs_vertex_weights;
4710 for (
int i = 0; i < rhs
.n(); ++i) {
4711 if (right_id_to_left[i] != -1) {
4714 new_right_id[i] = right_id_to_left[i];
4717 new_right_id[i] =
n() + i - intersection_lt;
4718 if (rhs.vertex_weights().has_value()) {
4719 if (!rhs_vertex_weights.has_value())
4720 rhs_vertex_weights = std::vector<VWeight>();
4721 rhs_vertex_weights->push_back(
4722 (*rhs.vertex_weights())[i]);
4728 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
4729 for (
int i = 0; i <
static_cast<
int>(rhs.edges().size()); ++i) {
4730 auto [u, v] = rhs.edges()[i];
4731 add_edge(new_right_id[u], new_right_id[v],
4732 rhs.edge_weights().has_value()
4733 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4740 std::initializer_list<std::pair<
int,
int>> il) {
4741 return glue(rhs, std::set<std::pair<
int,
int>>(il));
4749 std::set<std::pair<
int,
int>> index_pairs;
4750 for (
auto i : indices)
4751 index_pairs.emplace(i, i);
4752 return glue(rhs, index_pairs);
4754 value &glue(
const value &rhs,
const std::initializer_list<
int> &il) {
4755 return glue(rhs, std::set<
int>(il));
4760 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
4762 out << val.n() <<
'\n';
4765 if (val.vertex_weights()) {
4766 for (
int i = 0; i < val.n(); ++i) {
4769 out << (*val.vertex_weights())[i];
4774 tgen_ensure(
static_cast<
int>(val.edges().size()) == val.n() - 1,
4775 "wtree: value: invalid tree to print (number of edges "
4776 "must be `n` - 1)");
4779 if (val.print_parents_.has_value()) {
4781 "wtree: value: cannot print parent style if edges "
4784 int root = *val.print_parents_;
4785 bool skip_parent_0 = root == -1;
4788 if (root == val.n())
4789 root = next(0, val.n() - 1);
4791 std::vector<
int> parent(val.n(), -1);
4794 std::vector<
int> vis(val.n(),
false);
4801 for (
int v : val.adj()[u])
4809 if (skip_parent_0) {
4810 for (
int i = 1; i < val.n(); ++i) {
4813 "wtree: value: parent of i must be less than i for "
4814 "printing in parent style if root is -1");
4818 out << parent[i] + val.add_1_;
4821 for (
int i = 0; i < val.n(); ++i) {
4824 out << (parent[i] == -1 ? -1 : parent[i]) + val.add_1_;
4833 for (
int i = 0; i <
static_cast<
int>(val.edges().size()); ++i) {
4834 auto [u, v] = val.edges()[i];
4835 out << (u + val.add_1_) <<
" " << (v + val.add_1_);
4838 if (val.edge_weights().has_value())
4839 out <<
" " << (*val.edge_weights())[i];
4849 return std_type(n_, adj_);
4856 value &add_vertices(
int k, std::optional<std::vector<VWeight>>
4857 new_vertex_weights = std::nullopt) {
4860 if (new_vertex_weights.has_value()) {
4862 "wtree: value: cannot add weighted vertices to "
4863 "vertex-unweighted tree");
4865 static_cast<
int>(new_vertex_weights->size()) == k,
4866 "wtree: value: number of vertex weights must be equal "
4867 "to number of added vertices");
4869 vertex_weights_->insert(vertex_weights_->end(),
4870 new_vertex_weights->begin(),
4871 new_vertex_weights->end());
4874 "wtree: value: cannot add unweighted vertices to "
4875 "vertex-weighted tree");
4877 dsu_.add_elements(k);
4887 std::vector<std::vector<
int>> adj(n_);
4888 for (
auto [u, v] : edges_) {
4889 adj[u].push_back(v);
4890 adj[v].push_back(u);
4893 std::vector<
int> comp_size;
4894 std::vector<std::vector<
int>> component_ids;
4895 std::vector<
bool> vis(n_,
false);
4898 for (
int i = 0; i < n_; ++i) {
4904 comp_size.push_back(0);
4905 component_ids.emplace_back();
4910 component_ids.back().push_back(u);
4911 for (
int v : adj[u]) {
4922 std::vector<std::pair<
int,
int>> new_edges(edges_.begin(),
4924 if (comp_size.size() > 1) {
4925 std::vector<
int> prufer_values =
4926 many_by_distribution(comp_size.size() - 2, comp_size);
4927 for (
auto [u, v] : detail::edges_from_prufer(prufer_values))
4928 new_edges.emplace_back(pick(component_ids[u]),
4929 pick(component_ids[v]));
4932 return value(n_, new_edges);
4943 std::vector<std::pair<
int,
int>> edges;
4944 for (
int i = 1; i < n; ++i)
4945 edges.emplace_back(i, wnext<
int>(i, elongation));
4946 return value(n, edges);
4953 tgen_ensure(n > 0,
"wtree: gen_kruskal: n must be positive");
4955 return value(1, {});
4957 detail::dsu components(n);
4958 std::vector<std::pair<
int,
int>> edges;
4959 edges.reserve(n - 1);
4960 while (edges.size() < size_t(n - 1)) {
4961 int u = next(0, n - 1);
4962 int v = next(0, n - 1);
4965 if (components.unite(u, v))
4966 edges.emplace_back(u, v);
4968 return value(n, edges);
4973
4974
4986
4987
4988
4989
4995inline uint64_t undirected_edge_key(
int u,
int v) {
4998 return (
static_cast<uint64_t>(u) << 32) |
4999 static_cast<uint64_t>(
static_cast<uint32_t>(v));
5004inline uint64_t directed_edge_key(
int u,
int v) {
5005 return (
static_cast<uint64_t>(u) << 32) |
5006 static_cast<uint64_t>(
static_cast<uint32_t>(v));
5011inline long long max_graph_edges(
int n,
bool directed,
bool self_loops) {
5015 return self_loops ?
static_cast<
long long>(n) * n
5016 :
static_cast<
long long>(n) * (n - 1);
5017 return self_loops ?
static_cast<
long long>(n) * (n + 1) / 2
5018 :
static_cast<
long long>(n) * (n - 1) / 2;
5023inline std::pair<
int,
int> get_random_graph_edge(
int n,
bool directed,
5027 return {next<
int>(0, n - 1), next<
int>(0, n - 1)};
5028 int u = next<
int>(0, n - 1);
5029 int v = next<
int>(0, n - 1);
5031 v = next<
int>(0, n - 1);
5035 int u = next<
int>(0, n - 1);
5036 int v = next<
int>(0, n - 1);
5041 int u = next<
int>(0, n - 1);
5042 int v = next<
int>(0, n - 1);
5044 v = next<
int>(0, n - 1);
5053inline std::pair<
int,
int> decode_undirected_simple_edge(
int n,
long long idx) {
5054 auto base = [&](
int u) ->
long long {
5055 return static_cast<
long long>(u) * (n - 1) -
5056 static_cast<
long long>(u) * (u - 1) / 2;
5058 int lo = 0, hi = n - 2;
5060 int mid = (lo + hi + 1) / 2;
5061 if (base(mid) <= idx)
5066 return {lo, lo + 1 +
int(idx - base(lo))};
5072inline std::pair<
int,
int> decode_undirected_loops_edge(
int n,
long long idx) {
5073 auto base = [&](
int u) ->
long long {
5074 return static_cast<
long long>(u) * n -
5075 static_cast<
long long>(u) * (u - 1) / 2;
5077 int lo = 0, hi = n - 1;
5079 int mid = (lo + hi + 1) / 2;
5080 if (base(mid) <= idx)
5085 return {lo, lo +
int(idx - base(lo))};
5090inline std::pair<
int,
int> decode_directed_simple_edge(
int n,
long long idx) {
5091 int u = idx / (n - 1);
5092 int rem = idx % (n - 1);
5093 return {u, rem + (rem >= u)};
5098inline std::pair<
int,
int>
5099decode_graph_edge_index(
int n,
long long idx,
bool directed,
bool self_loops) {
5102 return {
int(idx / n),
int(idx % n)};
5103 return decode_directed_simple_edge(n, idx);
5106 return decode_undirected_loops_edge(n, idx);
5107 return decode_undirected_simple_edge(n, idx);
5113
5114
5115
5116
5117
5118
5119
5120
5122template <
typename VWeight,
typename EWeight>
5125 std::set<std::pair<
int,
int>> edges_;
5127 bool has_self_loops_;
5133 wgraph(
int n,
int m,
bool is_directed =
false,
bool has_self_loops =
false)
5134 : n_(n), m_(m), is_directed_(is_directed),
5135 has_self_loops_(has_self_loops) {
5136 tgen_ensure(n > 0,
"wgraph: number of vertices must be positive");
5142 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n_,
5143 "wgraph: vertices must be indexed in [0, n)");
5145 if (!is_directed_
and u > v)
5147 edges_.emplace(u, v);
5148 tgen_ensure(
static_cast<
int>(edges_.size()) <= m_,
5149 "wgraph: too many edges were added");
5163 std::vector<std::set<
int>> adj_;
5164 std::vector<std::pair<
int,
int>> edges_;
5168 mutable bool adj_built_{
5171 std::optional<std::vector<VWeight>> vertex_weights_;
5172 std::optional<std::vector<EWeight>>
5178 value(
const std::vector<std::set<
int>> &adj,
bool is_directed =
false)
5179 : n_(
static_cast<
int>(adj.size())),
adj_(
adj),
5180 is_directed_(is_directed), add_1_(
false), print_nm_(
false),
5182 for (
int u = 0; u < n_; ++u)
5183 for (
auto v : adj[u]) {
5186 "wgraph: value: vertices must be indexed in [0, n)");
5190 if (is_directed_
or u <= v)
5191 edges_.emplace_back(u, v);
5199 value(
int n,
const std::vector<std::pair<
int,
int>> &edges = {},
5200 bool is_directed =
false)
5201 : n_(n),
edges_(), is_directed_(is_directed), add_1_(
false),
5202 print_nm_(
false), adj_built_(
false) {
5203 edges_.reserve(edges.size());
5204 std::unordered_set<uint64_t> seen;
5205 seen.reserve(edges.size() * 2 + 1);
5206 for (
auto [u, v] : edges) {
5208 0 <= std::min(u, v)
and std::max(u, v) < n,
5209 "wgraph: value: vertices must be indexed in [0, n)");
5210 if (!is_directed_
and u > v)
5212 uint64_t key = is_directed_ ? detail::directed_edge_key(u, v)
5213 : detail::undirected_edge_key(u, v);
5214 if (seen.insert(key).second)
5215 edges_.emplace_back(u, v);
5218 value(
int n,
const std::set<std::pair<
int,
int>> &edges,
5219 bool is_directed =
false)
5224 value(
int n,
const std::initializer_list<std::pair<
int,
int>> &edges,
5225 bool is_directed =
false)
5226 : value(n, std::vector<std::pair<
int,
int>>(edges), is_directed) {}
5231 :
value(t.n(), t.edges(),
false) {
5232 if (t.vertex_weights().has_value()) {
5233 vertex_weights_ = *t.vertex_weights();
5235 if (t.edge_weights().has_value()) {
5236 edge_weights_ = *t.edge_weights();
5242 template <
typename NewVWeight,
typename NewEWeight>
5243 typename wgraph<NewVWeight, NewEWeight>::value
5244 convert_weight_types()
const {
5246 !edge_weights_.has_value(),
5247 "wgraph: value: cannot convert weight type after "
5248 "assigning weights");
5251 typename wgraph<NewVWeight, NewEWeight>::value new_graph(
5252 adj_, is_directed_);
5253 new_graph.is_directed_ = is_directed_;
5254 new_graph.add_1_ = add_1_;
5255 new_graph.print_nm_ = print_nm_;
5260 int n()
const {
return n_; }
5263 int m()
const {
return edges_.size(); }
5279 return vertex_weights_;
5284 return edge_weights_;
5289 template <
typename NewVWeight = VWeight>
5291 const std::vector<NewVWeight> &vertex_weights)
const {
5293 "wgraph: value: must give `n` vertex weights");
5295 auto new_graph = convert_weight_types<NewVWeight, EWeight>();
5296 new_graph.vertex_weights_ = vertex_weights;
5302 template <
typename NewEWeight = EWeight>
5306 "wgraph: value: must give `m` edge weights");
5308 auto new_graph = convert_weight_types<VWeight, NewEWeight>();
5309 new_graph.edge_weights_ = edge_weights;
5317 "wgraph: value: edge_weighted requires a graph with no "
5320 "wgraph: value: graph is already edge-weighted");
5322 edge_weights_ = std::vector<EWeight>();
5350 std::vector<
int> new_label(
n());
5351 std::vector<
int> shuffled;
5352 for (
int i = 0; i <
n(); ++i) {
5353 if (indices.count(i))
5356 shuffled.push_back(i);
5358 std::vector<
int> targets = shuffled;
5359 tgen::shuffle(targets.begin(), targets.end());
5360 for (size_t k = 0; k < shuffled.size(); ++k)
5361 new_label[shuffled[k]] = targets[k];
5364 std::vector<std::set<
int>> new_adj(
n());
5365 for (
int u = 0; u < n(); ++u)
5366 for (
int v : adj_[u])
5367 new_adj[new_label[u]].insert(new_label[v]);
5371 for (
auto &[u, v] : edges_) {
5374 if (!is_directed_
and u > v)
5379 if (vertex_weights_.has_value()) {
5380 std::vector<VWeight> new_vw(
n());
5381 for (
int i = 0; i < n(); ++i)
5382 new_vw[new_label[i]] = (*vertex_weights_)[i];
5383 vertex_weights_ = new_vw;
5388 std::vector<
int> perm(edges_.size());
5389 std::iota(perm.begin(), perm.end(), 0);
5390 tgen::shuffle(perm.begin(), perm.end());
5392 std::vector<std::pair<
int,
int>> new_edges;
5393 std::optional<std::vector<EWeight>> new_ew;
5394 if (edge_weights_.has_value())
5395 new_ew = std::vector<EWeight>();
5396 for (
int i : perm) {
5397 new_edges.push_back(edges_[i]);
5398 if (new_ew.has_value())
5399 new_ew->push_back((*edge_weights_)[i]);
5403 if (new_ew.has_value())
5404 edge_weights_ = new_ew;
5417 new_vertex_weights = std::nullopt) {
5421 if (new_vertex_weights.has_value()) {
5423 "wgraph: value: cannot add weighted vertices to "
5424 "vertex-unweighted graph");
5426 static_cast<
int>(new_vertex_weights->size()) == k,
5427 "wgraph: value: number of vertex weights must be equal "
5428 "to number of added vertices");
5430 vertex_weights_->insert(vertex_weights_->end(),
5431 new_vertex_weights->begin(),
5432 new_vertex_weights->end());
5435 "wgraph: value: cannot add unweighted vertices to "
5436 "vertex-weighted graph");
5446 "wgraph: value: vertex ids must be valid");
5451 if (adj_[u].count(v))
5457 edges_.emplace_back(u, v);
5459 if (w.has_value()) {
5461 "wgraph: value: cannot add weighted edge to "
5462 "edge-unweighted graph");
5464 edge_weights_->push_back(*w);
5467 "wgraph: value: cannot add unweighted edge to "
5468 "edge-weighted graph");
5478 std::optional<EWeight> new_w = std::nullopt) {
5481 "wgraph: value: vertex ids must be valid");
5485 add_vertices(rhs.n(), rhs.vertex_weights());
5486 for (
int i = 0; i < rhs
.m(); ++i) {
5487 auto [u, v] = rhs.edges()[i];
5489 rhs.edge_weights().has_value()
5490 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5505 std::set<std::pair<
int,
int>> index_pairs) {
5508 "wgraph: value: graphs must have the same is_directed value");
5511 std::set<
int> idx_left, idx_right;
5512 std::vector<
int> right_id_to_left(rhs
.n(), -1);
5513 for (
auto [l, r] : index_pairs) {
5515 0 <= l
and l < n()
and 0 <= r
and r < rhs.n(),
5516 "wgraph: value: vertex indices to glue must be valid");
5517 tgen_ensure(idx_left.count(l) == 0
and idx_right.count(r) == 0,
5518 "wgraph: value: must not have repeated indices "
5519 "on the same side to glue");
5522 idx_right.insert(r);
5523 right_id_to_left[r] = l;
5527 std::vector<
int> new_right_id(rhs
.n(), -1);
5528 int intersection_lt = 0;
5529 std::optional<std::vector<VWeight>> rhs_vertex_weights;
5530 for (
int i = 0; i < rhs
.n(); ++i) {
5531 if (right_id_to_left[i] != -1) {
5534 new_right_id[i] = right_id_to_left[i];
5537 new_right_id[i] =
n() + i - intersection_lt;
5538 if (rhs.vertex_weights().has_value()) {
5539 if (!rhs_vertex_weights.has_value())
5540 rhs_vertex_weights = std::vector<VWeight>();
5541 rhs_vertex_weights->push_back(
5542 (*rhs.vertex_weights())[i]);
5548 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
5549 for (
int i = 0; i < rhs
.m(); ++i) {
5550 auto [u, v] = rhs.edges()[i];
5552 rhs.edge_weights().has_value()
5553 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5560 std::initializer_list<std::pair<
int,
int>> il) {
5561 return glue(rhs, std::set<std::pair<
int,
int>>(il));
5569 std::set<std::pair<
int,
int>> index_pairs;
5570 for (
auto i : indices)
5571 index_pairs.emplace(i, i);
5572 return glue(rhs, index_pairs);
5574 value &glue(
const value &rhs,
const std::initializer_list<
int> &il) {
5575 return glue(rhs, std::set<
int>(il));
5582 return glue(rhs, std::set<
int>());
5590 "wgraph: value: can choose at most `m` edges from graph");
5592 std::vector<std::pair<
int,
int>> new_edges;
5593 std::optional<std::vector<EWeight>> new_edge_weights;
5596 for (
int i = 0; i <
m(); ++i) {
5597 if (next(1, left--) <= num_edges) {
5598 new_edges.push_back(edges()[i]);
5599 if (edge_weights_.has_value()) {
5600 if (!new_edge_weights.has_value())
5601 new_edge_weights = std::vector<EWeight>();
5602 new_edge_weights->push_back((*edge_weights())[i]);
5609 edge_weights_ = new_edge_weights;
5610 rebuild_adj_from_edge_list();
5622 "wgraph: value: random_connected_subgraph is only for "
5623 "undirected graphs");
5626 "wgraph: value: can choose at most `m` edges from graph");
5630 std::vector<std::vector<std::pair<
int,
int>>> incident(
n());
5631 for (
int i = 0; i <
m(); ++i) {
5632 auto [u, v] = edges_[i];
5633 incident[u].emplace_back(v, i);
5634 incident[v].emplace_back(u, i);
5638 std::vector<
bool> vis(
n(),
false);
5639 std::vector<
int> queue;
5640 std::vector<
bool> in_tree(
m(),
false);
5641 int forest_edges = 0;
5643 for (
int start = 0; start <
n(); ++start) {
5647 queue.push_back(start);
5649 while (!queue.empty()) {
5650 int i = tgen::next<
int>(0, queue.size() - 1);
5652 std::swap(queue[i], queue.back());
5655 for (
auto [v, edge_idx] : incident[u]) {
5659 in_tree[edge_idx] =
true;
5666 num_edges >= forest_edges,
5667 "wgraph: value: random_connected_subgraph needs at least "
5668 "`n - c` edges, where `c` is the number of connected "
5672 std::vector<
int> tree_idx, rest_idx;
5673 for (
int i = 0; i <
m(); ++i) {
5675 tree_idx.push_back(i);
5677 rest_idx.push_back(i);
5680 tgen::shuffle(rest_idx.begin(), rest_idx.end());
5682 std::vector<
int> chosen_idx;
5683 chosen_idx.insert(chosen_idx.end(), tree_idx.begin(),
5685 chosen_idx.insert(chosen_idx.end(), rest_idx.begin(),
5686 rest_idx.begin() + num_edges - forest_edges);
5688 detail::tgen_ensure_against_bug(
5689 static_cast<
int>(chosen_idx.size()) == num_edges,
5690 "wgraph: value: chose a wrong number of edges");
5692 std::vector<std::pair<
int,
int>> new_edges;
5693 std::optional<std::vector<EWeight>> new_edge_weights;
5694 if (edge_weights_.has_value())
5695 new_edge_weights = std::vector<EWeight>();
5696 for (
int i : chosen_idx) {
5697 new_edges.push_back(edges_[i]);
5698 if (new_edge_weights.has_value())
5699 new_edge_weights->push_back((*edge_weights_)[i]);
5703 edge_weights_ = new_edge_weights;
5704 rebuild_adj_from_edge_list();
5712 "wgraph: value: cannot compute complement of "
5713 "edge-weighted graph");
5715 value complement = *
this;
5716 complement.ensure_adj_built();
5717 std::vector<std::pair<
int,
int>> compl_edges;
5718 for (
int i = 0; i < complement.n_; ++i) {
5719 std::set<
int> complement_adj;
5720 for (
int j = 0; j < complement.n_; ++j) {
5722 if (j == i
and complement.adj_[i].count(j))
5724 if (j != i
and !complement.adj_[i].count(j))
5728 complement_adj.insert(j);
5730 if (i <= j
or complement.is_directed_) {
5731 compl_edges.emplace_back(i, j);
5735 std::swap(complement.adj_[i], complement_adj);
5737 std::swap(complement.edges_, compl_edges);
5746 "wgraph: value: graphs must have the same "
5747 "is_directed value");
5750 rhs.vertex_weights().has_value(),
5751 "wgraph: value: cannot concatenate vertex-weighted "
5752 "wgraph to unweighted");
5754 rhs.edge_weights().has_value(),
5755 "wgraph: value: cannot concatenate edge-weighted "
5756 "wgraph to unweighted");
5758 value concat = *
this;
5759 concat.glue(rhs, std::set<std::pair<
int,
int>>());
5760 concat.add_1_ = add_1_ | rhs.add_1_;
5761 concat.print_nm_ = print_nm_ | rhs.print_nm_;
5768 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
5771 out << val.n() <<
" " << val.m() <<
'\n';
5774 if (val.vertex_weights()) {
5775 for (
int i = 0; i < val.n(); ++i) {
5778 out << (*val.vertex_weights())[i];
5784 for (
int i = 0; i < val.m(); ++i) {
5785 auto [u, v] = val.edges()[i];
5786 out << (u + val.add_1_) <<
" " << (v + val.add_1_);
5789 if (val.edge_weights().has_value())
5790 out <<
" " << (*val.edge_weights())[i];
5801 return std_type(n_, m(), adj_);
5808 void rebuild_adj_from_edge_list() {
5809 adj_.assign(n_, {});
5810 for (
auto [u, v] : edges_) {
5820 void ensure_adj_built()
const {
5823 const_cast<
value *>(
this)->rebuild_adj_from_edge_list();
5831 "wgraph: graphs must have the same is_directed value");
5833 for (
auto [u, v] : rhs.edges())
5843 detail::tgen_ensure_against_bug(
static_cast<
int>(edges_.size()) <= m_,
5844 "wgraph: too many edges were added");
5847 if (
static_cast<
int>(edges_.size()) == m_)
5848 return value(n_, edges_, is_directed_);
5853 if (
auto indexed = try_gen_by_edge_index())
5857 return gen_remaining_edges(
5858 std::vector<std::pair<
int,
int>>(edges_.begin(), edges_.end()));
5868 "wgraph: get_connected is only for undirected graphs");
5870 "wgraph: connected graph needs at least n - 1 edges");
5872 std::vector<std::pair<
int,
int>> edges;
5875 if (edges_.empty()) {
5877 std::vector<
int> prufer(n_ - 2);
5878 for (
int i = 0; i < n_ - 2; ++i)
5879 prufer[i] = next<
int>(0, n_ - 1);
5880 for (
auto [u, v] : detail::edges_from_prufer(std::move(prufer)))
5881 edges.emplace_back(u, v);
5884 edges.assign(edges_.begin(), edges_.end());
5886 std::vector<std::vector<
int>> adj(n_);
5887 for (
auto [u, v] : edges_) {
5888 adj[u].push_back(v);
5889 adj[v].push_back(u);
5892 std::vector<
int> comp_size;
5893 std::vector<std::vector<
int>> component_ids;
5894 std::vector<
bool> vis(n_,
false);
5897 for (
int i = 0; i < n_; ++i) {
5903 comp_size.push_back(0);
5904 component_ids.emplace_back();
5909 component_ids.back().push_back(u);
5910 for (
int v : adj[u]) {
5919 if (component_ids.size() > 1) {
5920 std::vector<
int> prufer_values =
5921 many_by_distribution(component_ids.size() - 2, comp_size);
5923 detail::edges_from_prufer(std::move(prufer_values)))
5924 edges.emplace_back(pick(component_ids[u]),
5925 pick(component_ids[v]));
5929 return gen_remaining_edges(std::move(edges));
5942 "wgraph: get_acyclic is only for directed graphs");
5944 if (edges_.empty()) {
5945 std::vector<
int> order(n_);
5946 std::iota(order.begin(), order.end(), 0);
5947 for (
int i = n_ - 1; i > 0; --i)
5948 std::swap(order[i], order[next(0, i)]);
5950 const long long max_pairs =
5951 static_cast<
long long>(n_) * (n_ - 1) / 2;
5953 "wgraph: not enough edges to generate");
5955 std::vector<std::pair<
int,
int>> edges;
5957 for (
long long idx : distinct_range<
long long>(0, max_pairs - 1)
5960 auto [i, j] = detail::decode_undirected_simple_edge(n_, idx);
5961 edges.emplace_back(order[i], order[j]);
5963 return value(n_, edges,
true);
5966 std::vector<std::vector<
int>> adj(n_);
5967 std::vector<
int> indeg(n_, 0);
5968 for (
auto [u, v] : edges_) {
5969 adj[u].push_back(v);
5973 std::vector<
int> available;
5974 for (
int i = 0; i < n_; ++i)
5976 available.push_back(i);
5979 std::vector<
int> order;
5980 while (!available.empty()) {
5981 int idx = next(0,
static_cast<
int>(available.size()) - 1);
5982 int u = available[idx];
5983 std::swap(available[idx], available.back());
5984 available.pop_back();
5987 for (
int v : adj[u])
5988 if (--indeg[v] == 0)
5989 available.push_back(v);
5993 "wgraph: preset edges contain a directed cycle");
5995 value acyclic(n_, edges_,
true);
5999 detail::tgen_ensure_against_bug(acyclic.m() <= m_,
6000 "wgraph: too many edges were added");
6002 if (acyclic.m() < m_) {
6003 std::vector<
int> order_pos(n_);
6004 for (
int i = 0; i < n_; ++i)
6005 order_pos[order[i]] = i;
6007 std::unordered_set<uint64_t> seen;
6008 seen.reserve(m_ * 2);
6009 for (
auto [u, v] : acyclic.edges())
6011 detail::undirected_edge_key(order_pos[u], order_pos[v]));
6013 const long long max_pairs =
6014 static_cast<
long long>(n_) * (n_ - 1) / 2;
6015 while (acyclic.m() < m_) {
6016 std::pair<
int,
int> edge;
6017 if (!detail::try_generate_distinct(seen, [&] {
6018 long long idx = next<
long long>(0, max_pairs - 1);
6019 edge = detail::decode_undirected_simple_edge(n_, idx);
6020 return detail::undirected_edge_key(edge.first,
6023 throw detail::error(
"wgraph: not enough edges to generate");
6024 acyclic.add_edge(order[edge.first], order[edge.second]);
6044 bool is_directed =
false) {
6047 "wgraph: skewed graph needs at least n - 1 edges to be connected");
6049 "wgraph: gen_skewed spread must be at least 2");
6051 value skewed(n, {}, is_directed);
6053 std::vector<
int> parent(n), depth(n, 0);
6055 for (
int i = 1; i < n; ++i) {
6056 int p = wnext<
int>(i, elongation);
6058 depth[i] = depth[p] + 1;
6059 skewed.add_edge(p, i);
6062 const int extra = m - (n - 1);
6069 constexpr int naive_ancestor_spread = 20;
6071 if (spread <= naive_ancestor_spread) {
6072 std::vector<std::pair<
int,
int>> candidates;
6073 candidates.reserve(n * spread);
6074 for (
int u = 0; u < n; ++u) {
6075 int max_k = std::min(spread, depth[u]);
6079 for (
int k = 2; k <= max_k; ++k) {
6081 candidates.emplace_back(v, u);
6085 tgen_ensure(extra <=
static_cast<
int>(candidates.size()),
6086 "wgraph: not enough edges to generate");
6088 for (
auto [v, u] : choose(candidates, extra))
6089 skewed.add_edge(v, u);
6093 while ((1 << lg) <= n)
6096 std::vector<std::vector<
int>> up(lg, std::vector<
int>(n));
6097 for (
int v = 0; v < n; ++v)
6098 up[0][v] = parent[v];
6099 for (
int j = 1; j < lg; ++j)
6100 for (
int v = 0; v < n; ++v)
6101 up[j][v] = up[j - 1][up[j - 1][v]];
6107 std::vector<
int> distribution = depth;
6108 for (
int &d : distribution)
6109 d = std::max(0, std::min(spread - 1, d - 1));
6111 distinct extra_edges([&]() -> std::pair<
int,
int> {
6112 int u = vertex_choice.next();
6113 int k = next(2, spread);
6115 for (
int j = 0; j < lg; ++j)
6121 while (skewed.m() < m) {
6122 std::pair<
int,
int> edge;
6124 edge = extra_edges.gen();
6125 }
catch (
const std::runtime_error &e) {
6126 if (std::string(e.what()) ==
6127 "tgen: distinct: no more distinct values")
6128 throw detail::error(
6129 "wgraph: not enough edges to generate");
6133 skewed.add_edge(edge.first, edge.second);
6147 tgen_ensure(m >= 0,
"wgraph: number of edges must be nonnegative");
6148 long long num_edges = 1LL * n1 * n2;
6150 "wgraph: bipartite graph has at most n1 * n2 edges");
6154 "wgraph: connected bipartite graph needs at least n1 + n2 - 1 "
6158 std::vector<std::pair<
int,
int>> edges;
6160 for (
long long idx : distinct_range<
long long>(0, num_edges - 1)
6163 edges.emplace_back(
static_cast<
int>(idx / n2),
6164 n1 +
static_cast<
int>(idx % n2));
6165 return value(n1 + n2, std::move(edges),
false);
6168 std::unordered_set<uint64_t> used_edges;
6169 used_edges.reserve(m * 2);
6170 std::vector<std::pair<
int,
int>> edges;
6173 auto pack_edge = [](
int u,
int v) -> uint64_t {
6176 return (
static_cast<uint64_t>(u) << 32) |
static_cast<uint32_t>(v);
6179 if (n1 > 0
and n2 > 0) {
6180 std::vector<
int> prufer(n1 + n2 - 2);
6181 for (
int i = 0; i < n2 - 1; ++i)
6182 prufer[i] = next(0, n1 - 1);
6183 for (
int i = 0; i < n1 - 1; ++i)
6184 prufer[n2 - 1 + i] = next(n1, n1 + n2 - 1);
6185 shuffle(prufer.begin(), prufer.end());
6186 for (
auto [u, v] : detail::edges_from_prufer(std::move(prufer))) {
6189 if (used_edges.insert(pack_edge(u, v)).second)
6190 edges.emplace_back(u, v);
6192 detail::tgen_ensure_against_bug(
6193 used_edges.size() == size_t(n1 + n2 - 1),
6194 "wgraph: invalid bipartite spanning tree size");
6197 while (edges.size() < size_t(m)) {
6198 int u = next(0, n1 - 1);
6199 int v = next(n1, n1 + n2 - 1);
6200 if (used_edges.insert(pack_edge(u, v)).second)
6201 edges.emplace_back(u, v);
6204 return value(n1 + n2, std::move(edges),
false);
6213 std::optional<
value> try_gen_by_edge_index()
const {
6214 if (!edges_.empty())
6215 return std::nullopt;
6217 long long max_edges =
6218 detail::max_graph_edges(n_, is_directed_, has_self_loops_);
6220 throw detail::error(
"wgraph: not enough edges to generate");
6221 if (max_edges <= 0
or 2LL * m_ <= max_edges)
6222 return std::nullopt;
6224 std::vector<std::pair<
int,
int>> edges;
6226 for (
long long idx :
6227 distinct_range<
long long>(0, max_edges - 1).gen_list(m_).to_std())
6228 edges.push_back(detail::decode_graph_edge_index(
6229 n_, idx, is_directed_, has_self_loops_));
6231 return value(n_, edges, is_directed_);
6237 value gen_remaining_edges(std::vector<std::pair<
int,
int>> edges)
const {
6238 detail::tgen_ensure_against_bug(
static_cast<
int>(edges.size()) <= m_,
6239 "wgraph: too many edges were added");
6241 if (
static_cast<
int>(edges.size()) == m_)
6242 return value(n_, edges, is_directed_);
6246 std::unordered_set<uint64_t> seen;
6247 seen.reserve(m_ * 2);
6248 for (
auto [u, v] : edges) {
6249 if (!is_directed_
and u > v)
6251 seen.insert(is_directed_ ? detail::directed_edge_key(u, v)
6252 : detail::undirected_edge_key(u, v));
6255 while (
static_cast<
int>(edges.size()) < m_) {
6256 std::pair<
int,
int> edge;
6257 if (!detail::try_generate_distinct(seen, [&] {
6258 edge = detail::get_random_graph_edge(n_, is_directed_,
6260 if (!is_directed_
and edge.first > edge.second)
6261 std::swap(edge.first, edge.second);
6262 return is_directed_ ? detail::directed_edge_key(edge.first,
6264 : detail::undirected_edge_key(
6265 edge.first, edge.second);
6267 throw detail::error(
"wgraph: not enough edges to generate");
6268 edges.emplace_back(edge);
6271 return value(n_, edges, is_directed_);
6277template <
typename VWeight,
typename EWeight>
6279 const typename wgraph<VWeight, EWeight>::value &g)
6280 : n_(g.n()),
adj_(
g.
n()), add_1_(
false), print_n_(
false),
dsu_(
g.
n()) {
6281 tgen_ensure(g.n() > 0,
"wtree: value: graph must have at least one vertex");
6283 "wtree: value: graph must be undirected to form a tree");
6285 if (g.vertex_weights().has_value())
6286 vertex_weights_ = *g.vertex_weights();
6287 if (g.edge_weights().has_value())
6288 edge_weights_ = std::vector<EWeight>();
6293 std::vector<
int> order(g.m());
6294 std::iota(order.begin(), order.end(), 0);
6295 tgen::shuffle(order.begin(), order.end());
6297 std::vector<std::pair<
int,
int>> tree_edges;
6298 tree_edges.reserve(n_ - 1);
6300 for (
int i : order) {
6301 auto [u, v] = g.edges()[i];
6302 if (!dsu_.unite(u, v))
6307 tree_edges.emplace_back(u, v);
6310 if (edge_weights_.has_value())
6311 edge_weights_->push_back((*g.edge_weights())[i]);
6312 if (
static_cast<
int>(tree_edges.size()) == n_ - 1)
6316 tgen_ensure(
static_cast<
int>(tree_edges.size()) == n_ - 1,
6317 "wtree: value: graph must be connected to form a tree");
6319 edges_ = std::move(tree_edges);
6323
6324
6336
6337
6341inline graph::
value K(
int n) {
return graph(n, n * (n - 1) / 2).gen(); }
6348 graph g(n, n - 1, is_directed);
6349 for (
int i = 0; i + 1 < n; ++i)
6350 g.add_edge(i, i + 1);
6359 tgen_ensure(n >= 3,
"graph: cycle size must be at least 3");
6361 graph g(n, n, is_directed);
6362 for (
int i = 0; i < n; ++i)
6363 g.add_edge(i, (i + 1) % n);
6372 graph g(n1 + n2,
static_cast<
long long>(n1) * n2);
6373 for (
int i = 0; i < n1; ++i)
6374 for (
int j = 0; j < n2; ++j)
6375 g.add_edge(i, n1 + j);
6385
6386
6387
6388
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<detail::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 "
6499 std::vector<uint64_t> x_range(p - 1);
6500 std::iota(x_range.begin(), x_range.end(), 1);
6501 shuffle(x_range.begin(), x_range.end());
6502 std::vector<detail::i128> bx(n), by(n);
6503 for (
int i = 0; i < n; ++i) {
6504 uint64_t x = x_range[i];
6506 by[i] = math::modular_inverse(x, p);
6514 const int num_shears = 8;
6515 std::vector<detail::i128> lin_x = bx, lin_y = by;
6517 for (
int it = 0; it < num_shears; ++it) {
6518 bool vertical_shear = next(2) == 0;
6519 int shear_r = pick({-2, -1, 1, 2});
6521 for (
int i = 0; i < n; ++i) {
6523 lin_x[i] = (lin_x[i] + shear_r * lin_y[i]) % p;
6525 lin_y[i] = (lin_y[i] + shear_r * lin_x[i]) % p;
6534 detail::i128 min_x = lin_x[0], max_x = lin_x[0], min_y = lin_y[0],
6536 for (
int i = 1; i < n; ++i) {
6537 min_x = std::min(min_x, lin_x[i]);
6538 max_x = std::max(max_x, lin_x[i]);
6539 min_y = std::min(min_y, lin_y[i]);
6540 max_y = std::max(max_y, lin_y[i]);
6544 min_coord - min_x + next<
long long>(0, width - (max_x - min_x));
6546 min_coord - min_y + next<
long long>(0, width - (max_y - min_y));
6548 std::vector<point<
long long>> pts;
6549 for (
int i = 0; i < n; ++i)
6550 pts.emplace_back(lin_x[i] + x_shift, lin_y[i] + y_shift);
6556using i128 = tgen::detail::i128;
6560inline i128 ccw(
const point<
long long> &a,
const point<
long long> &b,
6561 const point<
long long> &p) {
6562 return (
static_cast<i128>(b.x()) - a.x()) *
6563 (
static_cast<i128>(p.y()) - a.y()) -
6564 (
static_cast<i128>(b.y()) - a.y()) *
6565 (
static_cast<i128>(p.x()) - a.x());
6569inline i128 proj_on_ab(
const point<
long long> &P,
const point<
long long> &A,
6570 const point<
long long> &B) {
6571 return (P - A) * (B - A);
6577inline void conquer(std::vector<point<
long long>> &points,
int left,
6579 if (right - left <= 3)
6582 point<
long long> A = points[left], B = points[right - 1];
6585 bool all_collinear =
true;
6586 for (
int k = left + 1; k < right - 1; ++k) {
6587 if (ccw(A, B, points[k]) != 0) {
6588 all_collinear =
false;
6592 if (all_collinear) {
6593 std::sort(points.begin() + left, points.begin() + right,
6594 [&](
const point<
long long> &P,
const point<
long long> &Q) {
6595 return proj_on_ab(P, A, B) < proj_on_ab(Q, A, B);
6601 std::vector<
int> candidates;
6602 for (
int k = left + 1; k < right - 1; ++k) {
6603 if (ccw(A, B, points[k]) != 0)
6604 candidates.push_back(k);
6606 int ci = candidates[next(0,
static_cast<
int>(candidates.size()) - 1)];
6607 point<
long long> C = points[ci];
6609 uint64_t wa = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6610 uint64_t wb = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6611 bool a_on_positive = ccw(C, A, B) < 0;
6615 i128 proj_sum = proj_on_ab(A, A, B) + proj_on_ab(B, A, B);
6616 auto is_positive = [&](
const point<
long long> &P) ->
bool {
6617 i128 s = wa * ccw(C, A, P) + wb * ccw(C, B, P);
6622 return 2 * proj_on_ab(P, A, B) > proj_sum;
6627 if (ci != right - 2)
6628 std::swap(points[ci], points[right - 2]);
6633 if (is_positive(points[i]) == a_on_positive)
6635 else if (is_positive(points[j]) != a_on_positive)
6638 std::swap(points[i], points[j]);
6649 if (i == j
and is_positive(points[i]) == a_on_positive)
6651 std::swap(points[p], points[right - 2]);
6654 conquer(points, left, p + 1);
6656 conquer(points, p, right);
6663inline std::vector<
long long>
6664sample_sorted_distinct_in_range(
int k,
long long left,
long long right) {
6665 long long universe = right - left + 1;
6666 std::vector<
long long> res;
6671 constexpr long long pool_threshold = 8'000'000;
6672 constexpr long long pool_always_below = 500'000;
6674 if (universe <= pool_threshold
and
6675 (universe <= pool_always_below
or k >= universe / 4)) {
6676 size_t u = universe;
6678 std::vector<
long long> pool(u);
6679 std::iota(pool.begin(), pool.end(), left);
6680 size_t m = ks <= u / 2 ? ks : u - ks;
6681 for (size_t i = 0; i < m; ++i) {
6682 size_t j = next<size_t>(i, u - 1);
6683 std::swap(pool[i], pool[j]);
6686 res.assign(pool.begin(), pool.begin() + ks);
6687 std::sort(res.begin(), res.end());
6689 std::vector<
char> excluded(u, 0);
6690 for (size_t i = 0; i < m; ++i)
6691 excluded[pool[i] - left] = 1;
6692 for (
long long v = left; v <= right; ++v)
6693 if (!excluded[v - left])
6697 std::unordered_map<
long long,
long long> virtual_list;
6698 virtual_list.reserve(k * 2);
6699 for (
long long i = 0; i < k; ++i) {
6700 long long j = next<
long long>(i, universe - 1);
6701 long long vi = virtual_list.count(i) ? virtual_list[i] : i;
6702 long long vj = virtual_list.count(j) ? virtual_list[j] : j;
6703 virtual_list[j] = vi;
6704 virtual_list[i] = vj;
6705 res.push_back(virtual_list[i] + left);
6707 std::sort(res.begin(), res.end());
6714inline std::vector<
long long>
6715valtr_edge_components(
const std::vector<
long long> &sorted_coords) {
6716 int n = sorted_coords.size();
6717 std::vector<
long long> left, right;
6718 left.reserve(n / 2);
6719 right.reserve(n / 2);
6720 for (
int i = 1; i + 1 < n; ++i) {
6722 left.push_back(sorted_coords[i]);
6724 right.push_back(sorted_coords[i]);
6726 long long lo = sorted_coords.front(), hi = sorted_coords.back();
6727 std::vector<
long long> seq;
6730 for (
long long v : left)
6733 for (
auto it = right.rbegin(); it != right.rend(); ++it)
6736 std::vector<
long long> comps(n);
6737 for (
int i = 0; i < n; ++i)
6738 comps[i] = seq[i + 1] - seq[i];
6744inline std::vector<point<
long long>>
6745simplify_strict_boundary(std::vector<point<
long long>> points) {
6746 int n = points.size();
6750 std::vector<point<
long long>> strict_points;
6751 strict_points.reserve(n);
6752 for (
int i = 0; i < n; ++i) {
6753 if (ccw(points[(i + n - 1) % n], points[i], points[(i + 1) % n]) != 0)
6754 strict_points.push_back(points[i]);
6756 return strict_points;
6761inline std::vector<point<
long long>>
6762subsample_boundary(
const std::vector<point<
long long>> &points,
int k) {
6763 int n = points.size();
6767 std::vector<point<
long long>> sampled_points;
6768 sampled_points.reserve(k);
6769 for (
int i = 0; i < k; ++i)
6770 sampled_points.push_back(points[(
static_cast<i128>(i) * n) / k]);
6771 return sampled_points;
6776inline void place_inside_box(std::vector<point<
long long>> &points,
6777 long long min_coord,
long long max_coord) {
6778 long long width = max_coord - min_coord + 1;
6780 i128 min_x = points[0].x(), max_x = points[0].x();
6781 i128 min_y = points[0].y(), max_y = points[0].y();
6782 for (
const point<
long long> &p : points) {
6783 min_x = std::min(min_x,
static_cast<i128>(p.x()));
6784 max_x = std::max(max_x,
static_cast<i128>(p.x()));
6785 min_y = std::min(min_y,
static_cast<i128>(p.y()));
6786 max_y = std::max(max_y,
static_cast<i128>(p.y()));
6789 i128 span_x = max_x - min_x;
6790 i128 span_y = max_y - min_y;
6794 next<
long long>(0, width - 1 -
static_cast<
long long>(span_x));
6797 next<
long long>(0, width - 1 -
static_cast<
long long>(span_y));
6799 for (point<
long long> &p : points)
6800 p = point<
long long>(p.x() + shift_x, p.y() + shift_y);
6805inline void randomize_cyclic_shift(std::vector<point<
long long>> &points) {
6806 int rot = next(points.size());
6808 std::rotate(points.begin(), points.begin() + rot, points.end());
6813inline std::vector<point<
long long>>
6814valtr_vertices(
int m,
const std::vector<
long long> &x_comp,
6815 std::vector<
long long> y_comp) {
6816 shuffle(y_comp.begin(), y_comp.end());
6818 std::vector<point<
long long>> edges(m);
6820 auto upper = [](
const point<
long long> &p) {
6821 return p.y() > 0
or (p.y() == 0
and p.x() > 0);
6823 for (
int i = 0; i < m; ++i)
6824 edges[i] =
point<
long long>(x_comp[i], y_comp[i]);
6826 std::sort(edges.begin(), edges.end(),
6827 [&upper](
const point<
long long> &a,
const point<
long long> &b) {
6828 bool au = upper(a), bu = upper(b);
6834 return (a * a) < (b * b);
6838 i128 cur_x = 0, cur_y = 0;
6839 std::vector<i128> px(m), py(m);
6840 for (
int i = 0; i < m; ++i) {
6843 cur_x += edges[i].x();
6844 cur_y += edges[i].y();
6846 tgen::detail::tgen_ensure_against_bug(
6847 cur_x == 0
and cur_y == 0,
6848 "geometry: random_convex_polygon: walk did not close");
6850 i128 min_x = px[0], min_y = py[0];
6851 for (
int i = 1; i < m; ++i) {
6852 min_x = std::min(min_x, px[i]);
6853 min_y = std::min(min_y, py[i]);
6857 std::vector<point<
long long>> points;
6859 for (
int i = 0; i < m; ++i)
6860 points.emplace_back(px[i] - min_x, py[i] - min_y);
6873 bool strict =
false) {
6875 "geometry: random_convex_polygon: n must be at least 3");
6877 "geometry: random_convex_polygon: min_coord must be at most "
6879 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord + 1 <=
6880 std::numeric_limits<
long long>::max(),
6881 "geometry: random_convex_polygon: coordinate range too large");
6882 long long width = max_coord - min_coord + 1;
6885 "geometry: random_convex_polygon: coordinate range too small for n");
6893 int extra = width <= n ? 0
6894 : std::min<
long long>(std::max(100, n / 1000),
6896 num_coords = n + extra;
6901 const int max_attempts = strict ? 32 : 1;
6902 for (
int i = 0; i < max_attempts; ++i) {
6904 std::vector<
long long> x_sorted =
6905 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6906 std::vector<
long long> y_sorted =
6907 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6908 std::vector<
long long> x_comp = detail::valtr_edge_components(x_sorted);
6909 std::vector<
long long> y_comp = detail::valtr_edge_components(y_sorted);
6911 std::vector<point<
long long>> points =
6912 detail::valtr_vertices(num_coords, x_comp, std::move(y_comp));
6915 std::vector<point<
long long>> simplified =
6916 detail::simplify_strict_boundary(std::move(points));
6918 if (
static_cast<
int>(simplified.size()) < n)
6921 points = detail::subsample_boundary(simplified, n);
6924 detail::place_inside_box(points, min_coord, max_coord);
6925 detail::randomize_cyclic_shift(points);
6930 throw tgen::detail::error(
6931 "geometry: random_convex_polygon: generation failed: coordinate "
6932 "range too small for n");
6940 const std::vector<point<
long long>> &points) {
6941 int n = points.size();
6943 "geometry: random_simple_polygon_through_points: need at "
6947 std::set<point<
long long>>(points.begin(), points.end()).size()) ==
6949 "geometry: random_simple_polygon_through_points: points must "
6952 int idx_a = 0, idx_b = 0;
6953 for (
int i = 1; i < n; ++i) {
6954 if (points[i] < points[idx_a])
6956 if (points[idx_b] < points[i])
6959 point<
long long> A = points[idx_a], B = points[idx_b];
6961 bool all_collinear =
true;
6962 for (
int i = 0; i < n; ++i) {
6963 if (i == idx_a
or i == idx_b)
6965 if (detail::ccw(A, B, points[i]) != 0) {
6966 all_collinear =
false;
6971 "geometry: random_simple_polygon_through_points: all points "
6972 "are collinear; no simple polygon exists");
6974 std::vector<point<
long long>> chain;
6977 for (
int i = 0; i < n; ++i) {
6978 if (i == idx_a
or i == idx_b)
6980 if (detail::ccw(A, B, points[i]) <= 0) {
6981 chain.push_back(points[i]);
6986 for (
int i = 0; i < n; ++i) {
6987 if (i == idx_a
or i == idx_b)
6989 if (detail::ccw(A, B, points[i]) > 0)
6990 chain.push_back(points[i]);
6994 int n1 = 2 + left_count;
6996 detail::conquer(chain, 0, n1);
6998 detail::conquer(chain, n1 - 1, chain.size());
7002 std::vector<point<
long long>> poly;
7003 poly.insert(poly.end(), chain.begin() + 1, chain.begin() + n1);
7004 poly.insert(poly.end(), chain.begin() + n1, chain.end());
7012inline std::vector<point<
long long>>
7013random_distinct_points_in_box(
int n,
long long min_coord,
long long max_coord) {
7014 long long width = max_coord - min_coord;
7015 i128 side_128 = width + 1;
7016 i128 universe = side_128 * side_128;
7017 tgen_ensure(universe <= std::numeric_limits<
long long>::max(),
7018 "geometry: random_simple_polygon: coordinate range too large");
7019 long long side = side_128;
7021 "geometry: random_simple_polygon: coordinate range too small "
7022 "for n distinct points");
7025 auto decode = [&](
long long key) ->
point<
long long> {
7026 return point<
long long>(min_coord + key / side, min_coord + key % side);
7032 std::vector<
long long> keys =
7033 distinct_range<
long long>(0, universe - 1).gen_list(n).to_std();
7035 std::vector<point<
long long>> points;
7037 for (
long long key : keys)
7038 points.push_back(decode(key));
7041 for (
int i = 2; i < n; ++i) {
7042 if (ccw(points[0], points[1], points[i]) != 0)
7050struct ortho_poly_edge {
7060inline bool ortho_axis_collinear(
const point<
long long> &a,
7061 const point<
long long> &b,
7062 const point<
long long> &c) {
7063 return (a.x() == b.x()
and b.x() == c.x())
or
7064 (a.y() == b.y()
and b.y() == c.y());
7069inline ortho_poly_edge
7070ortho_analyze_edge(
const std::vector<point<
long long>> &poly,
int i) {
7071 int m = poly.size();
7072 point<
long long> a = poly[i], b = poly[(i + 1) % m];
7073 ortho_poly_edge e{};
7074 if (a.y() == b.y()) {
7077 e.lo = std::min(a.x(), b.x());
7078 e.hi = std::max(a.x(), b.x());
7080 e.out_y = a.x() < b.x() ? -1 : 1;
7083 e.lo = std::min(a.y(), b.y());
7084 e.hi = std::max(a.y(), b.y());
7085 e.out_x = a.y() < b.y() ? 1 : -1;
7087 e.len = e.hi - e.lo;
7094inline bool ortho_open_seg_cross(
const point<
long long> &a,
7095 const point<
long long> &b,
7096 const point<
long long> &c,
7097 const point<
long long> &d) {
7098 if (a.y() == b.y()
and c.y() == d.y()) {
7101 long long lo1 = std::min(a.x(), b.x()), hi1 = std::max(a.x(), b.x());
7102 long long lo2 = std::min(c.x(), d.x()), hi2 = std::max(c.x(), d.x());
7103 return lo1 < hi2
and lo2 < hi1;
7105 if (a.x() == b.x()
and c.x() == d.x()) {
7108 long long lo1 = std::min(a.y(), b.y()), hi1 = std::max(a.y(), b.y());
7109 long long lo2 = std::min(c.y(), d.y()), hi2 = std::max(c.y(), d.y());
7110 return lo1 < hi2
and lo2 < hi1;
7112 if (a.y() == b.y()
and c.x() == d.x()) {
7113 long long hx = a.y(), vx = c.x();
7114 long long hlo = std::min(a.x(), b.x()), hhi = std::max(a.x(), b.x());
7115 long long vlo = std::min(c.y(), d.y()), vhi = std::max(c.y(), d.y());
7116 return hlo < vx
and vx < hhi
and vlo < hx
and hx < vhi;
7118 if (a.x() == b.x()
and c.y() == d.y()) {
7119 long long vx = a.x(), hy = c.y();
7120 long long vlo = std::min(a.y(), b.y()), vhi = std::max(a.y(), b.y());
7121 long long hlo = std::min(c.x(), d.x()), hhi = std::max(c.x(), d.x());
7122 return vlo < hy
and hy < vhi
and hlo < vx
and vx < hhi;
7129inline bool ortho_point_inside(
const std::vector<point<
long long>> &poly,
7130 point<
long long> p) {
7131 int m = poly.size();
7132 bool inside =
false;
7133 for (
int i = 0, j = m - 1; i < m; j = i++) {
7134 point<
long long> a = poly[i], b = poly[j];
7135 if ((a.y() > p.y()) != (b.y() > p.y())) {
7136 i128 x_cross = i128(b.x() - a.x()) * (p.y() - a.y()) -
7137 i128(p.x() - a.x()) * (b.y() - a.y());
7138 if ((a.y() < b.y()) ? x_cross > 0 : x_cross < 0)
7147inline bool ortho_seg_hits_boundary(
const std::vector<point<
long long>> &poly,
7148 int edge_i,
point<
long long> s0,
7149 point<
long long> s1) {
7150 int m = poly.size();
7151 for (
int j = 0; j < m; ++j) {
7154 if (ortho_open_seg_cross(s0, s1, poly[j], poly[(j + 1) % m]))
7164inline bool ortho_bump_valid(
const std::vector<point<
long long>> &poly,
7166 const std::vector<point<
long long>> &add,
7167 int edge_i,
bool inward) {
7169 for (point<
long long> v : add) {
7170 for (point<
long long> q : poly)
7176 point<
long long> prev = A;
7177 for (point<
long long> v : add) {
7178 if (ortho_seg_hits_boundary(poly, edge_i, prev, v))
7182 if (ortho_seg_hits_boundary(poly, edge_i, prev, B))
7188 for (point<
long long> v : add)
7189 if (!ortho_point_inside(poly, v))
7199inline bool ortho_bump_edge(std::vector<point<
long long>> &poly,
int edge_i,
7200 const ortho_poly_edge &e,
long long lo,
7201 long long hi,
long long depth,
bool inward) {
7202 int m = poly.size();
7203 point<
long long> A = poly[edge_i], B = poly[(edge_i + 1) % m];
7205 int step_x = inward ? -e.out_x : e.out_x;
7206 int step_y = inward ? -e.out_y : e.out_y;
7208 std::vector<point<
long long>> add;
7210 long long y = e.fixed, y2 = y + step_y * depth;
7211 if (A.x() < B.x()) {
7213 add.emplace_back(lo, y);
7214 add.emplace_back(lo, y2);
7215 add.emplace_back(hi, y2);
7217 add.emplace_back(hi, y);
7220 add.emplace_back(hi, y);
7221 add.emplace_back(hi, y2);
7222 add.emplace_back(lo, y2);
7224 add.emplace_back(lo, y);
7227 long long x = e.fixed, x2 = x + step_x * depth;
7228 if (A.y() < B.y()) {
7230 add.emplace_back(x, lo);
7231 add.emplace_back(x2, lo);
7232 add.emplace_back(x2, hi);
7234 add.emplace_back(x, hi);
7237 add.emplace_back(x, hi);
7238 add.emplace_back(x2, hi);
7239 add.emplace_back(x2, lo);
7241 add.emplace_back(x, lo);
7244 if (!ortho_bump_valid(poly, A, B, add, edge_i, inward))
7247 poly.insert(poly.begin() + edge_i + 1, add.begin(), add.end());
7254inline int ortho_pick_poly_edge(
const std::vector<point<
long long>> &poly,
7255 std::vector<
int> &last_used,
int &time_stamp) {
7256 int m = poly.size();
7257 if (
static_cast<
int>(last_used.size()) != m) {
7258 last_used.assign(m, 0);
7261 int global_timestamp = time_stamp;
7262 std::vector<
long long> weights(m);
7263 long long total = 0;
7264 for (
int i = 0; i < m; ++i) {
7265 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7266 weights[i] = e.len * (4 + std::min(global_timestamp - last_used[i], 8));
7267 total += weights[i];
7269 long long pick = next<
long long>(0, total - 1);
7270 for (
int i = 0; i < m; ++i) {
7273 last_used[i] = ++time_stamp;
7277 last_used[m - 1] = ++time_stamp;
7283inline bool ortho_try_bump(std::vector<point<
long long>> &poly,
int n,
7284 std::vector<
int> &last_used,
int &time_stamp) {
7285 if (poly.size() < 3)
7288 int ei = ortho_pick_poly_edge(poly, last_used, time_stamp);
7289 ortho_poly_edge e = ortho_analyze_edge(poly, ei);
7296 long long span = next<
long long>(2, e.len);
7297 long long lo = next<
long long>(e.lo, e.hi - span);
7301 long long max_depth =
7302 std::clamp<
long long>((
long long)(std::sqrt(n)) / 2 + 2, 2LL, 12LL);
7304 next(10) == 0 ? next<
long long>(std::max(2LL, max_depth / 2), max_depth)
7305 : next<
long long>(1, std::max(2LL, max_depth / 3));
7308 constexpr int ortho_inward_prob_denom = 4;
7309 return ortho_bump_edge(poly, ei, e, lo, lo + span, depth,
7310 next(ortho_inward_prob_denom) == 0);
7315inline std::vector<point<
long long>>
7316ortho_simplify_collinear(std::vector<point<
long long>> poly) {
7317 int n = poly.size();
7320 std::vector<point<
long long>> out;
7322 for (
int i = 0; i < n; ++i) {
7323 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7325 out.push_back(poly[i]);
7327 return out.size() >= 3 ? out : poly;
7332inline bool ortho_remove_one_collinear(std::vector<point<
long long>> &poly) {
7333 int n = poly.size();
7336 for (
int i = 0; i < n; ++i) {
7337 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7340 poly.erase(poly.begin() + i);
7349inline void ortho_fill_collinear(std::vector<point<
long long>> &poly,
7351 int need = target -
static_cast<
int>(poly.size());
7355 std::vector<point<
long long>> out;
7356 int m =
static_cast<
int>(poly.size());
7357 out.reserve(poly.size() +
static_cast<size_t>(need));
7359 for (
int i = 0; i < m; ++i) {
7360 point<
long long> a = poly[i], b = poly[(i + 1) % m];
7365 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7366 long long cap = e.len - 1;
7371 long long take = std::min<
long long>(need, cap);
7372 bool forward = e.horiz ? a.x() < b.x() : a.y() < b.y();
7373 for (
long long k = 0; k < take; ++k) {
7374 long long off = (k + 1) * (cap + 1) / (take + 1);
7375 long long coord = forward ? e.lo + off : e.hi - off;
7377 out.push_back({coord, e.fixed});
7379 out.push_back({e.fixed, coord});
7383 poly = std::move(out);
7388inline std::vector<point<
long long>> build_orthogonal_polygon(
int n,
7391 long long side = std::max(3LL,
static_cast<
long long>(std::sqrt(n)));
7393 side = std::max(side,
static_cast<
long long>((n + 3) / 4));
7394 std::vector<point<
long long>> poly = {
7395 {0, 0}, {side, 0}, {side, side}, {0, side}};
7398 int target_ops = std::max(1, (n - 4) / 2);
7402 target_ops = std::min(
7404 400 +
static_cast<
int>(4 * std::sqrt(
static_cast<
double>(n))));
7406 int failure_limit = std::min(target_ops * 8, 2000);
7408 std::vector<
int> last_used;
7409 int time_stamp = 0, consecutive_failures = 0;
7410 for (
int ops = 0; ops < target_ops;) {
7412 if (
static_cast<
int>(poly.size()) + 2 > n)
7415 if (ortho_try_bump(poly, n, last_used, time_stamp)) {
7417 consecutive_failures = 0;
7418 }
else if (++consecutive_failures >= failure_limit) {
7424 poly = ortho_simplify_collinear(std::move(poly));
7427 while (
static_cast<
int>(poly.size()) > n
and
7428 ortho_remove_one_collinear(poly))
7432 ortho_fill_collinear(poly, n);
7448 bool strict =
false) {
7450 "geometry: random_simple_polygon: n must be at least 3");
7452 "geometry: random_simple_polygon: min_coord must be at most "
7454 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord <=
7455 std::numeric_limits<
long long>::max(),
7456 "geometry: random_simple_polygon: coordinate range too large");
7458 std::vector<point<
long long>> points =
7459 strict ? random_points_general_position(n, min_coord, max_coord)
7460 : detail::random_distinct_points_in_box(n, min_coord, max_coord);
7461 return random_simple_polygon_through_points(points);
7469 bool strict =
false) {
7471 "geometry: random_orthogonal_polygon: n must be at least 4");
7473 "geometry: random_orthogonal_polygon: min_coord must be at "
7475 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord + 1 <=
7476 std::numeric_limits<
long long>::max(),
7477 "geometry: random_orthogonal_polygon: coordinate range too "
7479 long long width = max_coord - min_coord + 1;
7481 "geometry: random_orthogonal_polygon: coordinate range too "
7484 std::vector<point<
long long>> poly =
7485 detail::build_orthogonal_polygon(n, strict);
7487 detail::i128 min_x = poly[0].x(), max_x = poly[0].x();
7488 detail::i128 min_y = poly[0].y(), max_y = poly[0].y();
7489 for (
const point<
long long> &p : poly) {
7490 min_x = std::min(min_x,
static_cast<detail::i128>(p.x()));
7491 max_x = std::max(max_x,
static_cast<detail::i128>(p.x()));
7492 min_y = std::min(min_y,
static_cast<detail::i128>(p.y()));
7493 max_y = std::max(max_y,
static_cast<detail::i128>(p.y()));
7495 tgen_ensure(max_x - min_x < width
and max_y - min_y < width,
7496 "geometry: random_orthogonal_polygon: coordinate range too "
7499 detail::place_inside_box(poly, min_coord, max_coord);
7500 detail::randomize_cyclic_shift(poly);
7507
7508
7509
7510
7516using namespace tgen::detail;
7520inline int hash_string(
const std::string &s,
int base,
int mod) {
7523 h = (h * base + c -
'a' + 1) % mod;
7528inline int estimate_length(
int alphabet_size,
int mod) {
7530 double base_len = 2.5 * std::log(std::sqrt(mod));
7531 double scale = std::log(alphabet_size) / std::log(2.0);
7532 double adjusted = base_len / std::max(1.0, scale * 0.7);
7534 return static_cast<
int>(std::ceil(adjusted));
7539inline std::pair<std::string, std::string>
7540birthday_attack(
const std::vector<std::string> &alphabet,
int base,
int mod) {
7542 "birthday_attack: base must be in (0, mod)");
7543 std::map<uint64_t, std::vector<
int>> seen;
7544 int length = estimate_length(alphabet.size(), mod);
7547 std::vector<
int> seq(length);
7551 for (
int i = 0; i < length; ++i) {
7552 seq[i] = next<
int>(0, alphabet.size() - 1);
7553 s += alphabet[seq[i]];
7556 int h = hash_string(s, base, mod);
7558 auto it = seen.find(h);
7559 if (it != seen.end()
and it->second != seq) {
7562 for (
int x : it->second)
7577inline std::set<
long long> std_hash_multipliers() {
7578 std::set<
long long> multipliers = {85229};
7581 bool codeforces_gcc_case =
true;
7582 if (cpp.version_ != 0
and cpp.version_ != 17)
7583 codeforces_gcc_case =
false;
7584 if (compiler.kind_ != compiler_kind::unknown
and
7585 compiler.kind_ != compiler_kind::gcc)
7586 codeforces_gcc_case =
false;
7587 if (compiler.major_ > 7)
7588 codeforces_gcc_case =
false;
7590 if (codeforces_gcc_case)
7591 multipliers.insert(107897);
7602 std::string str =
"a";
7604 while (
static_cast<
int>(str.size()) < n) {
7605 int prev_size = str.size();
7607 for (
int j = 0; j < prev_size
and static_cast<
int>(str.size()) < n; ++j)
7620 for (
int i = 0; i < size; ++i) {
7621 a +=
'a' + math::detail::popcount(i) % 2;
7622 b +=
'a' + (
'b' - a[i]);
7631 int base,
int mod) {
7633 "hack: polynomial_hash: alphabet size must be greater "
7636 "hack: polynomial_hash: base must be in (0, mod)");
7638 std::vector<std::string> alphabet(alphabet_size);
7639 for (
int i = 0; i < alphabet_size; ++i)
7640 alphabet[i] = std::string(1,
'a' + i);
7641 std::iota(alphabet.begin(), alphabet.end(),
'a');
7642 return detail::birthday_attack(alphabet, base, mod);
7649inline std::pair<std::string, std::string>
7651 std::vector<
int> mods) {
7653 "hack: polynomial_hash: bases and mods must have the same "
7656 "hack: polynomial_hash: must have at least one (base, mod) "
7659 "hack: polynomial_hash: multi-hash hack only supported "
7660 "for up to 2 (base, mod) pairs");
7662 std::vector<std::string> alphabet(alphabet_size);
7663 for (
int i = 0; i < alphabet_size; ++i)
7664 alphabet[i] = std::string(1,
'a' + i);
7665 auto [S1, T1] = detail::birthday_attack(alphabet, bases[0], mods[0]);
7666 if (bases.size() == 1)
7668 return detail::birthday_attack({S1, T1}, bases[1], mods[1]);
7674 tgen_ensure(size > 0,
"hack: std_unordered: size must be positive");
7675 std::set<
long long> multipliers = detail::std_hash_multipliers();
7677 std::set<
long long>::iterator it = multipliers.begin();
7679 std::vector<
long long> list;
7680 while (
static_cast<
int>(list.size()) < size) {
7681 list.push_back(mult * (*it));
7683 if (it == multipliers.end()) {
7684 it = multipliers.begin();
7696 std::set<std::pair<
int,
int>> queries;
7699 int sq = std::sqrt(n);
7700 for (
int i = 0; i < sq; ++i) {
7701 for (
int j = i; j < sq; ++j) {
7702 if (i * sq < n
and j * sq < n)
7703 queries.emplace(i * sq, j * sq);
7708 for (
int i = 0; i < n; ++i)
7709 if (queries.size() < size_t(q)) {
7710 queries.emplace(0, i);
7711 queries.emplace(i, i);
7712 queries.emplace(i, n - 1);
7715 std::vector<std::pair<
int,
int>> pool(queries.begin(), queries.end());
7716 while (pool.size() < size_t(q)) {
7717 int l = next(0, n - 1);
7718 pool.emplace_back(l, next(l, n - 1));
7721 return choose(shuffled(pool), q);
7729 std::vector<std::string> list;
7730 int k = 0, left = size;
7732 int cur_size = std::min(left, k + 1);
7735 char right_char = cur_size == k + 1 ?
'b' :
'c';
7736 list.push_back(std::string(cur_size - 1,
'a') + right_char);
7740 return tgen::shuffled(list);
7752 "hack: non_strict_relaxation_dijkstra_bug: needs at least 3 vertices");
7754 egraph<
int>::value g(n, {},
true);
7756 g.add_edge(0, 1, 1);
7757 g.add_edge(0, 2, 1);
7758 for (
int i = 1; i + 2 < n; i += 2) {
7759 g.add_edge(i, i + 2, 1);
7761 g.add_edge(i, i + 3, 1);
7763 g.add_edge(i + 1, i + 2, 1);
7765 g.add_edge(i + 1, i + 3, 1);
7768 return g.shuffle_except({0});
7781 "hack: stale_heap_dijkstra_bug: needs at least 4 vertices");
7784 egraph<
int>::value g(n, {},
true);
7786 for (
int i = 1; i < mid; ++i)
7787 g.add_edge(0, i, i);
7788 for (
int i = 1; i < mid; ++i)
7789 g.add_edge(i, mid, 2 * (mid - i) - 1);
7790 for (
int i = mid + 1; i < n; ++i)
7791 g.add_edge(mid, i, 1);
7793 return g.shuffle_except({0});
7804 tgen_ensure(n >= 2,
"hack: spfa: n must be at least 2");
7805 tgen_ensure(n % 2 == 0,
"hack: spfa: n must be even");
7807 egraph<
int>::value g(n, {},
true);
7810 const int k = n / 2;
7811 for (
int i = 0; i + 1 < k; ++i)
7812 g.add_edge(i, i + 1, 1);
7813 for (
int i = 0; i + 1 < k; ++i)
7814 g.add_edge(k + i, k + i + 1, 0);
7815 for (
int i = 0; i < k; ++i)
7816 g.add_edge(i, k + i, 0);
7817 for (
int i = 0; i + 1 < k; ++i)
7818 g.add_edge(k + i, i + 1, 1);
7820 return g.shuffle_except({0});
7828 tgen_ensure(k >= 1,
"hack: dinitz_worst_case: k must be at least 1");
7829 tgen_ensure(l >= 1,
"hack: dinitz_worst_case: l must be at least 1");
7831 const int p1 = 2 * l - 1;
7832 const int p2 = 2 * l;
7833 const int q1 = 2 * l + 1;
7834 const int q2 = 2 * l + 2;
7835 const int n = 4 * l + 2 * k + 2;
7837 const int flow_cap = k * k * l;
7838 const int layer_cap = k * k;
7840 auto a = [&](
int i) {
return 2 * l + 3 + 2 * i; };
7841 auto b = [&](
int i) {
return 2 * l + 4 + 2 * i; };
7842 auto t = [&](
int i) {
return 4 * l + 2 * k + 1 - i; };
7844 egraph<
int>::value g(n, {},
true);
7847 for (
int i = 0; i + 1 < 2 * l - 1; ++i)
7848 g.add_edge(i, i + 1, flow_cap);
7849 for (
int i = 0; i + 1 < 2 * l - 1; ++i)
7850 g.add_edge(t(i + 1), t(i), flow_cap);
7852 for (
int i = 0; i < 2 * l - 1; i += 2) {
7853 g.add_edge(i, i % 4 == 0 ? p1 : p2, layer_cap);
7854 g.add_edge(i % 4 == 0 ? q1 : q2, t(i), layer_cap);
7857 for (
int i = 0; i < k; ++i) {
7858 g.add_edge(p1, a(i), flow_cap);
7859 g.add_edge(p2, b(i), flow_cap);
7860 g.add_edge(a(i), q2, flow_cap);
7861 g.add_edge(b(i), q1, flow_cap);
7864 for (
int i = 0; i < k; ++i)
7865 for (
int j = 0; j < k; ++j)
7866 g.add_edge(a(i), b(j), 1);
7875 static_assert(std::is_same_v<T,
int>
or std::is_same_v<T,
long long>,
7876 "hack: mt19937_xor_hash: T must be int or long long");
7878 constexpr std::size_t deg = 19937;
7880 std::bitset<deg + 1> a, b, c;
7881 b[deg] = c[deg] = 1;
7882 std::size_t l = 0, shift = 1;
7884 std::mt19937_64 rng64;
7885 for (std::size_t n = 0; n < deg * 2; ++n) {
7887 if constexpr (std::is_same_v<T,
int>)
7888 a[deg] = rng32() & 1;
7890 a[deg] = rng64() & 1;
7892 if ((c & a).count() % 2 == 0) {
7897 std::bitset<deg + 1> oc = c;
7908 std::vector<
bool> mask(deg + 1);
7909 for (std::size_t i = 0; i <= deg; ++i)
7921 {-0.9846, -1.53251}, {0.49946, 1.19525}, {0.79916, 0.98291},
7922 {4.02136, -1.57843}, {3.92734, -2.37856}, {3.88558, -2.37188},
7930inline std::vector<
int> segment_tree_beats_worst_case_block(
int k) {
7932 "hack: segment_tree_beats_worst_case: k must be at least 1");
7934 std::vector<
int> a(k + 1), b(k + 1);
7935 std::vector<std::vector<
int>> vf(k + 1), vg(k + 1);
7941 for (
int i = 2; i <= k; ++i) {
7942 b[i] = b[i - 1] + a[i - 1];
7943 a[i] = b[i] + a[i - 1];
7944 for (
int x : vf[i - 1])
7945 vf[i].push_back(x + a[i] + b[i]);
7946 vf[i].push_back(a[i]);
7947 for (
int x : vg[i - 1])
7948 vf[i].push_back(x + a[i]);
7951 for (
int x : vg[i - 1])
7962segment_tree_beats_append_round(std::vector<std::vector<
int>> &updates,
7963 int block_len,
int an,
int bn,
int n,
7965 const int off = (round * an) % block_len;
7966 const int add_off = (off + block_len - bn) % block_len;
7967 for (
int k = 0; k < block_len; ++k) {
7968 const int s = k * block_len * block_len;
7969 const int sub_end = off + an;
7970 if (sub_end <= block_len)
7971 updates.push_back({1, s + off, s + sub_end, bn});
7973 updates.push_back({1, s + off, s + block_len, bn});
7974 updates.push_back({1, s, s + (sub_end - block_len), bn});
7976 const int add_end = add_off + bn;
7977 if (add_end <= block_len)
7978 updates.push_back({0, s + add_off, s + add_end, an});
7980 updates.push_back({0, s + add_off, s + block_len, an});
7981 updates.push_back({0, s, s + (add_end - block_len), an});
7984 updates.push_back({2, 0, n, an});
7985 for (
int k = 0; k < block_len; ++k) {
7986 const int s = k * block_len * block_len;
7987 updates.push_back({3, s + (off + an - 1) % block_len, 0});
7995inline std::pair<std::vector<
int>, std::vector<std::vector<
int>>>
7996segment_tree_beats_worst_case(
int k,
int q) {
7998 "hack: segment_tree_beats_worst_case: k must be at least 1");
7999 tgen_ensure(k <= 7,
"hack: segment_tree_beats_worst_case: k too large");
8001 "hack: segment_tree_beats_worst_case: q must be positive");
8003 const auto &fib = math::fibonacci();
8004 const int block_len = fib[k * 2 + 1];
8005 const int an = fib[k * 2];
8006 const int bn = fib[k * 2 - 1];
8008 const int len = block_len;
8009 const int total = len * len * len;
8011 std::vector<
int> block = detail::segment_tree_beats_worst_case_block(k);
8012 std::vector<
int> arr(total, 0);
8013 for (
int x = 0; x < block_len; ++x) {
8014 const int s = x * len * len;
8015 for (
int i = 0; i < block_len; ++i)
8016 arr[s + i] = block[i];
8019 std::vector<std::vector<
int>> updates;
8021 const int n = total;
8022 for (
int round = 0; updates.size() <
static_cast<std::size_t>(q); ++round) {
8023 detail::segment_tree_beats_append_round(updates, block_len, an, bn, n,
8025 if (updates.size() >
static_cast<std::size_t>(q))
8028 return {arr, updates};
8034
8035
8036
8037
8046 "misc: parenthesis: size must be a positive even number");
8050 int open = 0, close = 0;
8052 for (
int i = 0; i < size; ++i) {
8058 if (open == close) {
8064 long long a = k - open, b = k - close, h = open - close;
8069 long long num = a * (h + 2);
8070 long long den = (a + b) * (h + 1);
8072 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_convex_polygon(int n, long long min_coord, long long max_coord, bool strict=false)
Generates a random convex polygon with given coordinate range.
std::vector< point< long long > > random_simple_polygon(int n, long long min_coord, long long max_coord, bool strict=false)
Generates a random simple polygon given coordinate range.
std::vector< point< long long > > random_orthogonal_polygon(int n, long long min_coord, long long max_coord, bool strict=false)
Generates a random orthogonal simple polygon.
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.