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 lo = detail::kth_root_floor(left, root);
2923 if (*detail::expo(lo, root, left) < left)
2925 uint64_t p =
gen_prime(lo
, detail::kth_root_floor(right, root)
);
2926 return *detail::expo(p, root, right);
2933 std::vector<uint64_t> rems,
2934 std::vector<uint64_t> mods) {
2936 throw detail::there_is_no_in_range_error(
"congruent number", left,
2939 "math: number of remainders and mods must be the same");
2940 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
2943 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
2945 "math: remainder must be smaller than the mod");
2946 crt = crt * detail::crt(rems[i], mods[i]);
2949 throw detail::there_is_no_in_range_error(
"congruent number", left,
2951 if (crt.m > right) {
2952 if (!(left <= crt.a
and crt.a <= right))
2953 throw detail::there_is_no_in_range_error(
"congruent number",
2956 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
2957 if (crt.a % mods[j] != rems[j])
2958 throw detail::there_is_no_in_range_error(
"congruent number",
2964 uint64_t k_min = crt.a >= left ? 0 : ((left - crt.a) + crt.m - 1) / crt.m;
2965 uint64_t k_max = (right - crt.a) / crt.m;
2968 throw detail::there_is_no_in_range_error(
"congruent number", left,
2971 return crt.a + next(k_min, k_max) * crt.m;
2978 return gen_congruent(left, right, std::vector<uint64_t>({rem}),
2979 std::vector<uint64_t>({mod}));
2987 std::vector<uint64_t> mods) {
2989 "math: number of remainders and mods must be the same");
2990 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
2993 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
2995 "math: remainder must be smaller than the mod");
2996 crt = crt * detail::crt(rems[i], mods[i]);
2999 throw detail::there_is_no_from_error(
"congruent number", left);
3000 if (crt.m > std::numeric_limits<uint64_t>::max()) {
3002 throw detail::error(
3003 "math: congruent number does not exist or is too large");
3005 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
3006 if (crt.a % mods[j] != rems[j])
3007 throw detail::error(
"math: congruent number does "
3008 "not exist or is too large");
3015 k = ((left - crt.a) + crt.m - 1) / crt.m;
3016 detail::i128 result = crt.a + k * crt.m;
3018 if (result > std::numeric_limits<uint64_t>::max())
3019 throw detail::error(
"math: congruent number is too large");
3026 return congruent_from(left, std::vector<uint64_t>{rem},
3027 std::vector<uint64_t>{mod});
3035 std::vector<uint64_t> mods) {
3037 "math: number of remainders and mods must be the same");
3038 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
3041 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
3043 "math: remainder must be smaller than the mod");
3045 crt = crt * detail::crt(rems[i], mods[i]);
3048 throw detail::there_is_no_upto_error(
"congruent number", right);
3049 if (crt.m > right) {
3050 if (!(crt.a <= right))
3051 throw detail::there_is_no_upto_error(
"congruent number", right);
3053 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
3054 if (crt.a % mods[j] != rems[j])
3055 throw detail::there_is_no_upto_error(
"congruent number",
3062 throw detail::there_is_no_upto_error(
"congruent number", right);
3064 uint64_t k = (right - crt.a) / crt.m;
3065 detail::i128 result = crt.a + k * crt.m;
3068 throw detail::there_is_no_upto_error(
"congruent number", right);
3075 return congruent_upto(right, std::vector<uint64_t>{rem},
3076 std::vector<uint64_t>{mod});
3084 static const std::vector<uint64_t> fib = [] {
3085 std::vector<uint64_t> v = {0, 1};
3087 std::numeric_limits<uint64_t>::max() - v[v.size() - 2])
3088 v.push_back(v.back() + v[v.size() - 2]);
3100 std::optional<
int> part_right = std::nullopt) {
3101 if (!part_right.has_value())
3103 part_right = std::min(*part_right, n);
3105 "math: invalid parameters to gen_partition");
3106 tgen_ensure(part_left <= n
and *part_right > 0,
"math: no such partition");
3109 std::vector<
long double> dp(n + 1, detail::LOG_ZERO);
3110 dp[0] = detail::LOG_ONE;
3111 long double window = detail::LOG_ZERO;
3112 for (
int i = 1; i <= n; ++i) {
3114 window = detail::add_log_space(window, dp[i - part_left]);
3115 if (i >= *part_right + 1)
3116 window = detail::sub_log_space(window, dp[i - *part_right - 1]);
3119 tgen_ensure(dp[n] >= 0,
"math: no such partition");
3123 for (
int i = 1; i <= n; ++i)
3124 dp_pref[i] = detail::add_log_space(dp_pref[i - 1], dp[i]);
3126 std::vector<
int> part;
3130 int l = std::max(0, sum - *part_right), r = sum - part_left;
3131 detail::tgen_ensure_against_bug(r >= 0,
"math: r < 0 in gen_partition");
3133 int nxt_sum = std::min(sum, r);
3134 long double random = next<
long double>(0, 1);
3145 long double val_l = l ? dp_pref[l - 1] : detail::LOG_ZERO,
3147 while (nxt_sum > l
and
3148 dp_pref[nxt_sum - 1] >=
3149 val_r + detail::log_space(random +
3150 (1 - random) * exp(val_l - val_r)))
3153 part.push_back(sum - nxt_sum);
3166 std::optional<
int> part_right = std::nullopt) {
3167 if (!part_right.has_value())
3169 part_right = std::min(*part_right, n);
3171 "math: invalid parameters to gen_partition_fixed_size");
3172 tgen_ensure(
static_cast<
long long>(k) * part_left <= n
and
3173 n <=
static_cast<
long long>(k) * (*part_right),
3174 "math: no such partition");
3177 int s = n - k * part_left;
3179 std::vector<
int> part(k);
3180 if (*part_right == n) {
3182 std::vector<
int> cuts = {-1};
3184 int total = s + k - 1, bars = k - 1;
3185 for (
int i = 0; i < total
and bars > 0; ++i)
3186 if (next<
long double>(0, 1) <
3187 static_cast<
long double>(bars) / (total - i)) {
3191 cuts.push_back(total);
3194 for (
int i = 0; i < k; ++i)
3195 part[i] = cuts[i + 1] - cuts[i] - 1;
3198 int u = *part_right - part_left;
3201 std::vector<std::vector<
long double>> dp(
3202 k + 1, std::vector<
long double>(s + 1, detail::LOG_ZERO));
3203 dp[0][0] = detail::LOG_ONE;
3205 for (
int i = 1; i <= k; ++i) {
3206 std::vector<
long double> pref = dp[i - 1];
3207 for (
int j = 1; j <= s; ++j)
3208 pref[j] = detail::add_log_space(pref[j - 1], dp[i - 1][j]);
3210 for (
int j = 0; j <= s; ++j) {
3213 dp[i][j] = detail::sub_log_space(dp[i][j], pref[j - u - 1]);
3218 int left_to_distribute = s;
3219 for (
int i = k; i >= 1; --i) {
3220 long double log_total = detail::LOG_ZERO;
3221 for (
int j = 0; j <= u
and j <= left_to_distribute; ++j)
3222 log_total = detail::add_log_space(
3223 log_total, dp[i - 1][left_to_distribute - j]);
3224 detail::tgen_ensure_against_bug(
3225 log_total != detail::LOG_ZERO,
3226 "math: total == 0 in gen_partition_fixed_size");
3232 long double random =
3233 detail::log_space(next<
long double>(0, 1)) + log_total;
3235 long double cur_prob = detail::LOG_ZERO;
3237 for (
int j = 0; j <= u
and j <= left_to_distribute; ++j) {
3238 cur_prob = detail::add_log_space(
3239 cur_prob, dp[i - 1][left_to_distribute - j]);
3240 if (random < cur_prob) {
3246 part[k - i] = chosen;
3247 left_to_distribute -= chosen;
3264 uint64_t n,
int k, uint64_t part_left = 0,
3265 std::optional<uint64_t> part_right = std::nullopt) {
3266 if (!part_right.has_value())
3268 part_right = std::min(*part_right, n);
3270 detail::u128 n128 = n;
3271 detail::u128 k128 = k;
3272 detail::u128 part_left128 = part_left;
3273 detail::u128 part_right128 = *part_right;
3276 "math: invalid parameters to gen_partition_fixed_size_fast");
3278 k128 * part_left128 <= n128
and
3279 k128 * part_right128 >= n128,
3280 "math: no such partition");
3282 uint64_t slack_total = n128 - k128 * part_left128;
3283 uint64_t slack_max = part_right128 - part_left128;
3285 std::vector<uint64_t> part(k);
3287 part[0] = slack_total;
3289 std::vector<uint64_t> cuts(k - 1);
3290 for (uint64_t &d : cuts)
3291 d = next<uint64_t>(0, slack_total);
3292 std::sort(cuts.begin(), cuts.end());
3295 for (
int i = 0; i + 1 < k; ++i) {
3296 part[i] = cuts[i] - prev;
3299 part[k - 1] = slack_total - prev;
3302 auto add_part_left = [part_left](uint64_t x) -> uint64_t {
3303 detail::u128 val = x + part_left;
3304 detail::tgen_ensure_against_bug(
3305 val <= std::numeric_limits<uint64_t>::max(),
3306 "math: part + part_left exceeds uint64_t in "
3307 "gen_partition_fixed_size_fast");
3311 if (slack_max >= slack_total) {
3312 for (uint64_t &x : part)
3313 x = add_part_left(x);
3317 detail::u128 remaining = 0;
3318 for (uint64_t &x : part) {
3319 if (x > slack_max) {
3320 remaining += x - slack_max;
3323 x = add_part_left(x);
3326 if (remaining > 0) {
3327 for (uint64_t &x : part) {
3328 if (x < *part_right && remaining > 0) {
3329 detail::u128 room = *part_right - x;
3330 detail::u128 add = std::min(remaining, room);
3331 detail::u128 val = x + add;
3332 detail::tgen_ensure_against_bug(
3334 "math: part exceeds part_right after redistribution in "
3335 "gen_partition_fixed_size_fast");
3340 detail::tgen_ensure_against_bug(
3341 remaining == 0,
"math: remaining mass after redistribution in "
3342 "gen_partition_fixed_size_fast");
3352template <
typename T>
3355 std::optional<uint64_t> max_size = std::nullopt) {
3356 size_t n = elements.size();
3357 tgen_ensure(k > 0,
"math: partition_elements: k must be positive");
3359 "math: partition_elements: min_size must be non-negative");
3361 std::vector<uint64_t> sizes;
3362 if (max_size.has_value()) {
3363 sizes = gen_partition_fixed_size_fast(n, k, min_size, max_size);
3365 for (
int sz : gen_partition_fixed_size(n, k, min_size))
3366 sizes.push_back(sz);
3369 std::vector<std::vector<T>> groups;
3372 for (uint64_t sz : sizes) {
3373 groups.emplace_back(elements.begin() + pos,
3374 elements.begin() + pos + sz);
3383
3384
3385
3386
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
3418
3419
3429 std::vector<regex_node> children_;
3430 int left_bound_, right_bound_;
3433 log_space_num_ways_;
3438 regex_node(
const std::string &pattern)
3439 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3440 if (pattern.size() == 1) {
3441 log_space_num_ways_ = math::detail::LOG_ONE;
3444 tgen_ensure_against_bug(pattern[0] ==
'[' and pattern.back() ==
']',
3445 "str: invalid regex: expected character class");
3446 int size = pattern.size() - 2;
3447 log_space_num_ways_ = math::detail::log_space(size);
3448 distinct_ = distinct_container<
char>(pattern.substr(1, size));
3451 regex_node(
const std::string &pattern, std::vector<regex_node> &children)
3452 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3453 if (pattern ==
"SEQ") {
3455 log_space_num_ways_ = math::detail::LOG_ONE;
3456 for (
const auto &child : children)
3457 log_space_num_ways_ += child.log_space_num_ways_;
3458 }
else if (pattern ==
"OR") {
3460 log_space_num_ways_ = math::detail::LOG_ZERO;
3461 for (
const auto &child : children)
3462 log_space_num_ways_ = math::detail::add_log_space(
3463 log_space_num_ways_, child.log_space_num_ways_);
3465 tgen_ensure_against_bug(
"str: invalid regex: expected SEQ or OR");
3467 children_ = std::move(children);
3471 regex_node(
int left_bound,
int right_bound, regex_node &child)
3472 : pattern_(
"REP"), left_bound_(left_bound), right_bound_(right_bound) {
3473 log_space_num_ways_ = math::detail::LOG_ZERO;
3474 for (
int i = left_bound; i <= right_bound; ++i)
3475 log_space_num_ways_ = math::detail::add_log_space(
3476 log_space_num_ways_, i * child.log_space_num_ways_);
3478 children_.push_back(std::move(child));
3484 std::vector<regex_node> cur;
3485 std::vector<regex_node> branches;
3489inline regex_node make_regex_seq(regex_state &st) {
3490 return regex_node(
"SEQ", st.cur);
3494inline regex_node finish_regex_state(regex_state &st) {
3496 if (st.branches.empty())
3497 return make_regex_seq(st);
3500 st.branches.push_back(make_regex_seq(st));
3501 return regex_node(
"OR", st.branches);
3506inline regex_node parse_regex(std::string regex) {
3507 std::string new_regex;
3508 for (
char c : regex)
3511 swap(regex, new_regex);
3513 std::vector<regex_state> stack;
3515 for (size_t i = 0; i < regex.size(); ++i) {
3520 stack.push_back(std::move(cur));
3521 cur = regex_state();
3522 }
else if (c ==
')') {
3524 regex_node node = finish_regex_state(cur);
3526 tgen_ensure(!stack.empty(),
"str: invalid regex: unmatched `)`");
3527 cur = std::move(stack.back());
3530 cur.cur.push_back(std::move(node));
3531 }
else if (c ==
'|') {
3533 regex_node node = make_regex_seq(cur);
3534 cur.branches.push_back(std::move(node));
3535 }
else if (c ==
'[') {
3539 for (++i; i < regex.size()
and regex[i] !=
']'; ++i) {
3540 if (i + 2 < regex.size()
and regex[i + 1] ==
'-') {
3541 char a = regex[i], b = regex[i + 2];
3544 for (
char x = a; x <= b; ++x)
3552 "str: invalid regex: unmatched `[`");
3553 cur.cur.emplace_back(
"[" + chars +
"]");
3554 }
else if (c ==
'{') {
3559 while (i < regex.size()
and
3560 isdigit(
static_cast<
unsigned char>(regex[i]))) {
3564 "str: invalid regex: number too large inside `{}`");
3565 l = 10 * l + (regex[i] -
'0');
3569 if (i < regex.size()
and regex[i] ==
',') {
3571 while (i < regex.size()
and
3572 isdigit(
static_cast<
unsigned char>(regex[i]))) {
3576 r <=
static_cast<
int>(1e8),
3577 "str: invalid regex: number too large inside `{}`");
3578 r = 10 * r + (regex[i] -
'0');
3585 "str: invalid regex: unmatched `{`");
3587 "str: invalid regex: missing number inside `{}`");
3589 "str: invalid regex: invalid range inside `{}`");
3593 "str: invalid regex: expected expression before `{}`");
3595 regex_node rep(l, r, cur.cur.back());
3597 cur.cur.push_back(std::move(rep));
3600 cur.cur.emplace_back(std::string(1, c));
3604 tgen_ensure(stack.empty(),
"str: invalid regex: unmatched `(`");
3605 return finish_regex_state(cur);
3609inline void gen_regex(
const regex_node &node, std::string &str) {
3611 if (node.pattern_[0] ==
'[') {
3612 str += node.pattern_[1 + next<
int>(0, node.pattern_.size() - 3)];
3617 if (node.left_bound_ != -1) {
3621 double log_rand = math::detail::log_space(next<
double>(0, 1)) +
3622 node.log_space_num_ways_;
3623 double cur_prob = math::detail::LOG_ZERO;
3624 double child_num_ways = node.children_[0].log_space_num_ways_;
3626 for (
int i = node.left_bound_; i <= node.right_bound_; ++i) {
3628 math::detail::add_log_space(cur_prob, i * child_num_ways);
3629 if (log_rand <= cur_prob) {
3630 for (
int j = 0; j < i; ++j)
3631 gen_regex(node.children_[0], str);
3636 tgen_ensure_against_bug(
false,
3637 "str: log_rand > cur_prob in REP gen_regex");
3641 if (!node.children_.empty()
and node.pattern_ ==
"SEQ") {
3642 for (
const regex_node &child : node.children_)
3643 gen_regex(child, str);
3648 if (!node.children_.empty()
and node.pattern_ ==
"OR") {
3652 double log_rand = math::detail::log_space(next<
double>(0, 1)) +
3653 node.log_space_num_ways_;
3654 double cur_prob = math::detail::LOG_ZERO;
3656 for (
const regex_node &child : node.children_) {
3657 cur_prob = math::detail::add_log_space(cur_prob,
3658 child.log_space_num_ways_);
3659 if (log_rand <= cur_prob) {
3660 gen_regex(child, str);
3665 tgen_ensure_against_bug(
false,
3666 "str: log_rand > cur_prob in OR gen_regex");
3670 detail::tgen_ensure_against_bug(
3671 node.pattern_.size() == 1,
3672 "str: invalid regex: expected single character, but got `" +
3673 node.pattern_ +
"`");
3674 str += node.pattern_[0];
3678template <
typename... Args>
3679std::string regex_format(
const std::string &s, Args &&...args) {
3680 if constexpr (
sizeof...(Args) == 0) {
3683 int size = std::snprintf(
nullptr, 0, s.c_str(), args...) + 1;
3684 std::string buf(size,
'\0');
3685 std::snprintf(buf.data(), size, s.c_str(), args...);
3694
3695
3698 std::optional<
list<
char>> list_;
3699 std::optional<detail::regex_node>
3704 str(
int size,
char value_left =
'a',
char value_right =
'z') {
3705 tgen_ensure(size > 0,
"str: size must be positive");
3706 list_ = list<
char>(size, value_left, value_right);
3711 str(
int size, std::set<
char> chars) {
3712 tgen_ensure(size > 0,
"str: size must be positive");
3713 list_ = list<
char>(size, chars);
3717 template <
typename... Args>
str(
const std::string ®ex, Args &&...args) {
3718 tgen_ensure(regex.size() > 0,
"str: regex must be non-empty");
3720 root_ = detail::parse_regex(
3721 detail::regex_format(regex, std::forward<Args>(args)...));
3726 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3727 list_->fix(idx, character);
3733 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3734 list_->equal(indices);
3740 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3741 list_->equal(idx_1, idx_2);
3747 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3748 list_->equal_range(left, right);
3754 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3761 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3762 tgen_ensure(0 <= left
and left <= right
and right < list_->size_,
3763 "str: range indices must be valid");
3764 for (
int i = left; i < right - (i - left); ++i)
3771 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3772 return palindrome(0, list_->size_ - 1);
3778 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3779 list_->different(indices);
3785 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3786 list_->different(idx_1, idx_2);
3792 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3793 list_->different_range(left, right);
3799 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3800 list_->all_different();
3806 using tgen_is_sequential_tag = detail::is_sequential_tag;
3808 using value_type =
char;
3809 using std_type = std::string;
3812 value(
const std::string &str) : str_(str) {
3813 tgen_ensure(!str_.empty(),
"str: value: cannot be empty");
3817 int size()
const {
return str_.size(); }
3822 "str: value: index out of bounds");
3825 const char &operator[](
int idx)
const {
3827 "str: value: index out of bounds");
3834 std::sort(str_.begin(), str_.end());
3841 std::reverse(str_.begin(), str_.end());
3848 for (
char &c : str_)
3849 c = std::tolower(c);
3856 for (
char &c : str_)
3857 c = std::toupper(c);
3864 return value(str_ + rhs.str_
);
3870 for (
int i = 0; i < size(); ++i)
3871 std::swap(str_[i], str_[next(0, size() - 1)]);
3881 template <
typename Dist>
3884 "value and distribution must have the same size");
3885 return str_[next_by_distribution(distribution)];
3887 template <
typename Dist>
3888 char pick_by_distribution(
3889 const std::initializer_list<Dist> &distribution)
const {
3890 return pick_by_distribution(std::vector<Dist>(distribution));
3897 "number of elements to choose must be valid");
3898 std::string new_str;
3900 for (
int i = 0; need > 0; ++i) {
3902 if (next(1, left) <= need) {
3903 new_str.push_back(str_[i]);
3911 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
3912 return out << val.str_;
3916 std::string
to_std()
const {
return std_type(str_); }
3925 std::string ret_str;
3926 gen_regex(*root_, ret_str);
3930 std::vector<
char> vec = list_->gen().to_std();
3931 return value(std::string(vec.begin(), vec.end()));
3937
3938
3939
3940
3946template <
typename T> std::pair<T, T> gen_eq(T L1, T R1, T L2, T R2) {
3947 T L = std::max(L1, L2);
3948 T R = std::min(R1, R2);
3950 tgen_ensure(L <= R,
"pair: no valid values to generate");
3951 T x = next<T>(L, R);
3956template <
typename T>
3957std::pair<u128, u128> get_n_and_m(T L1, T R1, T L2, T R2) {
3958 u128 n =
static_cast<i128>(R1) - L1 + 1;
3959 u128 m =
static_cast<i128>(R2) - L2 + 1;
3965static u128 pos_arith_sum(u128 first, u128 last, u128 num_terms) {
3966 u128 x = first + last, y = num_terms;
3979template <
typename T> std::pair<T, T> gen_neq(T L1, T R1, T L2, T R2) {
3980 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
3982 T L_intersect = std::max(L1, L2);
3983 T R_intersect = std::min(R1, R2);
3984 u128 inter =
static_cast<i128>(R_intersect) - L_intersect + 1;
3986 u128 total = n * m - inter;
3987 tgen_ensure(total > 0,
"pair: no valid values to generate");
3992 a = next<T>(L1, R1);
3993 b = next<T>(L2, R2);
4004template <
typename T>
4005std::pair<u128, u128> count_lt_regions(T L1, T R1, T L2, T R2) {
4006 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4009 i128 L_second = std::max<i128>(L2,
static_cast<i128>(L1) + 1);
4013 i128 split = std::min<i128>(R_second, R1);
4016 u128 len1 = std::max<i128>(0, split - L_second + 1);
4018 u128 count_region1 = 0;
4021 i128 first = L_second - L1;
4022 i128 last = split - L1;
4025 count_region1 = pos_arith_sum(first, last, len1);
4030 i128 L_second_region2 = std::max(L_second,
static_cast<i128>(R1) + 1);
4032 u128 len2 = std::max<i128>(0, R_second - L_second_region2 + 1);
4033 u128 count_region2 = len2 * n;
4035 return {count_region1, count_region2};
4040template <
typename T> std::pair<T, T> gen_lt(T L1, T R1, T L2, T R2) {
4041 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4045 i128 L_second = std::max<i128>(L2,
static_cast<i128>(L1) + 1);
4051 i128 split = std::min<i128>(R_second, R1);
4053 auto [count_region1, count_region2] = count_lt_regions(L1, R1, L2, R2);
4054 u128 total = count_region1 + count_region2;
4055 tgen_ensure(total > 0,
"pair: no valid values to generate");
4057 u128 k = detail::next128(total);
4058 if (k < count_region1) {
4062 u128 len1 = std::max<i128>(0, split - L_second + 1);
4069 i128 base = L_second - L1;
4070 i128 lo = 0, hi =
static_cast<i128>(len1) - 1;
4073 i128 mid = lo + (hi - lo) / 2;
4075 if (pos_arith_sum(base, base + mid, mid + 1) <= k)
4084 k -= pos_arith_sum(base, base + d - 1, d);
4086 return {L1 +
static_cast<T>(k), L_second + d};
4092 i128 L_second_region2 = std::max(L_second,
static_cast<i128>(R1) + 1);
4094 return {L1 +
static_cast<T>(k % n),
4095 L_second_region2 +
static_cast<T>(k / n)};
4101template <
typename T> std::pair<T, T> gen_gt(T L1, T R1, T L2, T R2) {
4102 auto [first, second] = gen_lt(L2, R2, L1, R1);
4103 return {second, first};
4108template <
typename T> std::pair<T, T> gen_leq(T L1, T R1, T L2, T R2) {
4110 i128 L_intersect = std::max(L1, L2);
4111 i128 R_intersect = std::min(R1, R2);
4112 u128 eq_count = std::max<i128>(0, R_intersect - L_intersect + 1);
4115 auto [lt_region1, lt_region2] = count_lt_regions(L1, R1, L2, R2);
4116 u128 lt_count = lt_region1 + lt_region2;
4118 u128 total = eq_count + lt_count;
4119 tgen_ensure(total > 0,
"pair: no valid values to generate");
4121 if (detail::next128(total) < eq_count)
4122 return gen_eq(L1, R1, L2, R2);
4123 return gen_lt(L1, R1, L2, R2);
4128template <
typename T> std::pair<T, T> gen_geq(T L1, T R1, T L2, T R2) {
4129 auto [first, second] = gen_leq(L2, R2, L1, R1);
4130 return {second, first};
4136
4137
4138
4139
4142 std::pair<T, T> first_, second_;
4144 enum class restriction_type { eq, neq, lt, gt, leq, geq, unspecified };
4145 restriction_type type_ = restriction_type::unspecified;
4149 pair(T first_left, T first_right, T second_left, T second_right)
4150 : first_(first_left, first_right), second_(second_left, second_right) {
4152 "pair: first range must be valid");
4154 "pair: second range must be valid");
4159 :
pair(both_left, both_right, both_left, both_right) {}
4163 type_ = restriction_type::eq;
4169 type_ = restriction_type::neq;
4175 type_ = restriction_type::lt;
4181 type_ = restriction_type::gt;
4187 type_ = restriction_type::leq;
4193 type_ = restriction_type::geq;
4199 using value_type = T;
4200 using std_type = std::pair<T, T>;
4202 std::pair<T, T> pair_;
4205 value(
const std::pair<T, T> &pair) : pair_(pair), sep_(
' ') {}
4207 : pair_(first, second), sep_(
' ') {}
4219 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
4220 return out << val.pair_.first << val.sep_ << val.pair_.second;
4225 if constexpr (!detail::is_generator_value<T>::value) {
4228 std::pair<
typename T::std_type,
typename T::std_type> pair(
4229 pair_.first.to_std(), pair_.second.to_std());
4238 T L1 = first_.first, R1 = first_.second;
4239 T L2 = second_.first, R2 = second_.second;
4242 case restriction_type::unspecified:
4243 return {next<T>(L1, R1), next<T>(L2, R2)};
4244 case restriction_type::eq:
4245 return detail::gen_eq<T>(L1, R1, L2, R2);
4246 case restriction_type::neq:
4247 return detail::gen_neq<T>(L1, R1, L2, R2);
4248 case restriction_type::lt:
4249 return detail::gen_lt<T>(L1, R1, L2, R2);
4250 case restriction_type::gt:
4251 return detail::gen_gt<T>(L1, R1, L2, R2);
4252 case restriction_type::leq:
4253 return detail::gen_leq<T>(L1, R1, L2, R2);
4254 case restriction_type::geq:
4255 return detail::gen_geq<T>(L1, R1, L2, R2);
4257 throw detail::error(
"pair: unknown restriction type");
4262
4263
4264
4265
4271inline std::vector<std::pair<
int,
int>> edges_from_prufer(std::vector<
int> p) {
4272 int n = p.size() + 2;
4275 std::vector<
int> d(n, 1);
4284 idx = u = find(d.begin(), d.end(), 1) - d.begin();
4287 std::vector<std::pair<
int,
int>> edges;
4289 edges.emplace_back(u, v);
4290 if (--d[v] == 1
and v < idx)
4293 idx = u = find(d.begin() + idx + 1, d.end(), 1) - d.begin();
4300 std::vector<
int> parent_;
4301 std::vector<
unsigned char> rank_;
4306 dsu(
int n) : parent_(n), rank_(n, 0) {
4307 for (
int i = 0; i < n; ++i)
4313 void add_elements(
int k) {
4314 for (
int i = 0; i < k; ++i) {
4315 int new_id = parent_.size();
4316 parent_.push_back(new_id);
4324 return parent_[i] == i ? i : parent_[i] = find(parent_[i]);
4330 bool unite(
int a,
int b) {
4335 if (rank_[a] > rank_[b])
4338 if (rank_[a] == rank_[b])
4347template <
typename VWeight,
typename EWeight>
struct wgraph;
4350
4351
4352
4353
4354
4355
4356
4357
4359template <
typename VWeight,
typename EWeight>
4362 std::set<std::pair<
int,
int>> edges_;
4367 tgen_ensure(n > 0,
"wtree: number of vertices must be positive");
4373 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n_,
4374 "wtree: vertices must be indexed in [0, n)");
4375 tgen_ensure(u != v,
"wtree: cannot add self loop to tree");
4379 edges_.emplace(u, v);
4391 std::vector<std::set<
int>> adj_;
4392 std::vector<std::pair<
int,
int>> edges_;
4395 std::optional<
int> print_parents_;
4397 std::optional<std::vector<VWeight>> vertex_weights_;
4398 std::optional<std::vector<EWeight>>
4404 value(
const std::vector<std::set<
int>> &adj)
4405 : n_(
static_cast<
int>(adj.size())),
adj_(
adj), add_1_(
false),
4406 print_n_(
false),
dsu_(
n_) {
4407 for (
int u = 0; u < n_; ++u)
4408 for (
auto v : adj[u]) {
4411 "wtree: value: vertices must be indexed in [0, n)");
4414 edges_.emplace_back(u, v);
4417 "wtree: value: initial graph must form a tree");
4424 value(
int n,
const std::vector<std::pair<
int,
int>> &edges)
4425 : n_(n),
adj_(
n), add_1_(
false), print_n_(
false),
dsu_(
n) {
4426 edges_.reserve(edges.size());
4427 for (
auto [u, v] : edges) {
4428 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n,
4429 "wtree: value: vertices must be indexed in [0, n)");
4431 "wtree: value: initial graph must form a tree");
4434 edges_.emplace_back(u, v);
4439 value(
int n,
const std::set<std::pair<
int,
int>> &edges)
4442 value(
int n,
const std::initializer_list<std::pair<
int,
int>> &edges)
4443 : value(n, std::vector<std::pair<
int,
int>>(edges)) {}
4448 value(
const typename wgraph<VWeight, EWeight>::value &g);
4452 template <
typename NewVWeight,
typename NewEWeight>
4453 typename wtree<NewVWeight, NewEWeight>::value
4454 convert_weight_types()
const {
4456 !edge_weights_.has_value(),
4457 "wtree: value: cannot convert weight type after "
4458 "assigning weights");
4460 typename wtree<NewVWeight, NewEWeight>::value new_tree(adj_);
4461 new_tree.add_1_ = add_1_;
4462 new_tree.print_n_ = print_n_;
4463 new_tree.print_parents_ = print_parents_;
4468 int n()
const {
return n_; }
4478 return vertex_weights_;
4483 return edge_weights_;
4488 template <
typename NewVWeight = VWeight>
4490 const std::vector<NewVWeight> &vertex_weights)
const {
4492 "wtree: value: must give `n` vertex weights");
4494 auto new_tree = convert_weight_types<NewVWeight, EWeight>();
4495 new_tree.vertex_weights_ = vertex_weights;
4501 template <
typename NewEWeight = EWeight>
4505 edge_weights.size() == edges().size(),
4506 "wtree: value: must give `edges().size()` edge weights");
4508 auto new_tree = convert_weight_types<VWeight, NewEWeight>();
4509 new_tree.edge_weights_ = edge_weights;
4517 "wtree: value: edge_weighted requires a tree with no "
4520 "wtree: value: tree is already edge-weighted");
4522 edge_weights_ = std::vector<EWeight>();
4546 "wtree: value: root must be -1, `n`, or in [0, n)");
4547 print_parents_ = root;
4560 std::vector<
int> new_label(
n());
4561 std::vector<
int> shuffled;
4562 for (
int i = 0; i <
n(); ++i) {
4563 if (indices.count(i))
4566 shuffled.push_back(i);
4568 std::vector<
int> targets = shuffled;
4569 tgen::shuffle(targets.begin(), targets.end());
4570 for (size_t k = 0; k < shuffled.size(); ++k)
4571 new_label[shuffled[k]] = targets[k];
4574 std::vector<std::set<
int>> new_adj(
n());
4575 for (
int u = 0; u < n(); ++u)
4576 for (
int v : adj_[u])
4577 new_adj[new_label[u]].insert(new_label[v]);
4578 adj_ = std::move(new_adj);
4581 for (
auto &[u, v] : edges_) {
4589 if (vertex_weights_.has_value()) {
4590 std::vector<VWeight> new_vw(
n());
4591 for (
int i = 0; i < n(); ++i)
4592 new_vw[new_label[i]] = (*vertex_weights_)[i];
4593 vertex_weights_ = std::move(new_vw);
4597 dsu_ = detail::dsu(n());
4598 for (
auto [u, v] : edges_)
4603 std::vector<
int> perm(edges_.size());
4604 std::iota(perm.begin(), perm.end(), 0);
4605 tgen::shuffle(perm.begin(), perm.end());
4607 std::vector<std::pair<
int,
int>> new_edges;
4608 std::optional<std::vector<EWeight>> new_ew;
4609 if (edge_weights_.has_value())
4610 new_ew = std::vector<EWeight>();
4611 for (
int i : perm) {
4612 new_edges.push_back(edges_[i]);
4613 if (new_ew.has_value())
4614 new_ew->push_back((*edge_weights_)[i]);
4617 if (new_ew.has_value())
4618 edge_weights_ = new_ew;
4629 value &add_edge(
int u,
int v, std::optional<EWeight> w = std::nullopt) {
4631 "wtree: value: vertex ids must be valid");
4636 if (adj_[u].count(v))
4641 edges_.emplace_back(u, v);
4643 "wtree: value: added edge must not create a cycle");
4645 if (w.has_value()) {
4647 "wtree: value: cannot add weighted edge to "
4648 "edge-unweighted tree");
4650 edge_weights_->push_back(*w);
4653 "wtree: value: cannot add unweighted edge to "
4654 "edge-weighted tree");
4664 std::optional<EWeight> new_w = std::nullopt) {
4667 "wtree: value: vertex ids must be valid");
4671 add_vertices(rhs.n(), rhs.vertex_weights());
4672 for (
int i = 0; i <
static_cast<
int>(rhs.edges().size()); ++i) {
4673 auto [u, v] = rhs.edges()[i];
4674 add_edge(shift + u, shift + v,
4675 rhs.edge_weights().has_value()
4676 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4681 add_edge(new_u, shift + new_v, new_w);
4691 std::set<std::pair<
int,
int>> index_pairs) {
4693 std::set<
int> idx_left, idx_right;
4694 std::vector<
int> right_id_to_left(rhs
.n(), -1);
4695 for (
auto [l, r] : index_pairs) {
4697 0 <= l
and l < n()
and 0 <= r
and r < rhs.n(),
4698 "wtree: value: vertex indices to glue must be valid");
4699 tgen_ensure(idx_left.count(l) == 0
and idx_right.count(r) == 0,
4700 "wtree: value: must not have repeated indices "
4701 "on the same side to glue");
4704 idx_right.insert(r);
4705 right_id_to_left[r] = l;
4709 std::vector<
int> new_right_id(rhs
.n(), -1);
4710 int intersection_lt = 0;
4711 std::optional<std::vector<VWeight>> rhs_vertex_weights;
4712 for (
int i = 0; i < rhs
.n(); ++i) {
4713 if (right_id_to_left[i] != -1) {
4716 new_right_id[i] = right_id_to_left[i];
4719 new_right_id[i] =
n() + i - intersection_lt;
4720 if (rhs.vertex_weights().has_value()) {
4721 if (!rhs_vertex_weights.has_value())
4722 rhs_vertex_weights = std::vector<VWeight>();
4723 rhs_vertex_weights->push_back(
4724 (*rhs.vertex_weights())[i]);
4730 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
4731 for (
int i = 0; i <
static_cast<
int>(rhs.edges().size()); ++i) {
4732 auto [u, v] = rhs.edges()[i];
4733 add_edge(new_right_id[u], new_right_id[v],
4734 rhs.edge_weights().has_value()
4735 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4742 std::initializer_list<std::pair<
int,
int>> il) {
4743 return glue(rhs, std::set<std::pair<
int,
int>>(il));
4751 std::set<std::pair<
int,
int>> index_pairs;
4752 for (
auto i : indices)
4753 index_pairs.emplace(i, i);
4754 return glue(rhs, index_pairs);
4756 value &glue(
const value &rhs,
const std::initializer_list<
int> &il) {
4757 return glue(rhs, std::set<
int>(il));
4762 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
4764 out << val.n() <<
'\n';
4767 if (val.vertex_weights()) {
4768 for (
int i = 0; i < val.n(); ++i) {
4771 out << (*val.vertex_weights())[i];
4776 tgen_ensure(
static_cast<
int>(val.edges().size()) == val.n() - 1,
4777 "wtree: value: invalid tree to print (number of edges "
4778 "must be `n` - 1)");
4781 if (val.print_parents_.has_value()) {
4783 "wtree: value: cannot print parent style if edges "
4786 int root = *val.print_parents_;
4787 bool skip_parent_0 = root == -1;
4790 if (root == val.n())
4791 root = next(0, val.n() - 1);
4793 std::vector<
int> parent(val.n(), -1);
4796 std::vector<
int> vis(val.n(),
false);
4803 for (
int v : val.adj()[u])
4811 if (skip_parent_0) {
4812 for (
int i = 1; i < val.n(); ++i) {
4815 "wtree: value: parent of i must be less than i for "
4816 "printing in parent style if root is -1");
4820 out << parent[i] + val.add_1_;
4823 for (
int i = 0; i < val.n(); ++i) {
4826 out << (parent[i] == -1 ? -1 : parent[i]) + val.add_1_;
4835 for (
int i = 0; i <
static_cast<
int>(val.edges().size()); ++i) {
4836 auto [u, v] = val.edges()[i];
4837 out << (u + val.add_1_) <<
" " << (v + val.add_1_);
4840 if (val.edge_weights().has_value())
4841 out <<
" " << (*val.edge_weights())[i];
4851 return std_type(n_, adj_);
4858 value &add_vertices(
int k, std::optional<std::vector<VWeight>>
4859 new_vertex_weights = std::nullopt) {
4862 if (new_vertex_weights.has_value()) {
4864 "wtree: value: cannot add weighted vertices to "
4865 "vertex-unweighted tree");
4867 static_cast<
int>(new_vertex_weights->size()) == k,
4868 "wtree: value: number of vertex weights must be equal "
4869 "to number of added vertices");
4871 vertex_weights_->insert(vertex_weights_->end(),
4872 new_vertex_weights->begin(),
4873 new_vertex_weights->end());
4876 "wtree: value: cannot add unweighted vertices to "
4877 "vertex-weighted tree");
4879 dsu_.add_elements(k);
4889 std::vector<std::vector<
int>> adj(n_);
4890 for (
auto [u, v] : edges_) {
4891 adj[u].push_back(v);
4892 adj[v].push_back(u);
4895 std::vector<
int> comp_size;
4896 std::vector<std::vector<
int>> component_ids;
4897 std::vector<
bool> vis(n_,
false);
4900 for (
int i = 0; i < n_; ++i) {
4906 comp_size.push_back(0);
4907 component_ids.emplace_back();
4912 component_ids.back().push_back(u);
4913 for (
int v : adj[u]) {
4924 std::vector<std::pair<
int,
int>> new_edges(edges_.begin(),
4926 if (comp_size.size() > 1) {
4927 std::vector<
int> prufer_values =
4928 many_by_distribution(comp_size.size() - 2, comp_size);
4929 for (
auto [u, v] : detail::edges_from_prufer(prufer_values))
4930 new_edges.emplace_back(pick(component_ids[u]),
4931 pick(component_ids[v]));
4934 return value(n_, new_edges);
4945 std::vector<std::pair<
int,
int>> edges;
4946 for (
int i = 1; i < n; ++i)
4947 edges.emplace_back(i, wnext<
int>(i, elongation));
4948 return value(n, edges);
4955 tgen_ensure(n > 0,
"wtree: gen_kruskal: n must be positive");
4957 return value(1, {});
4959 detail::dsu components(n);
4960 std::vector<std::pair<
int,
int>> edges;
4961 edges.reserve(n - 1);
4962 while (edges.size() < size_t(n - 1)) {
4963 int u = next(0, n - 1);
4964 int v = next(0, n - 1);
4967 if (components.unite(u, v))
4968 edges.emplace_back(u, v);
4970 return value(n, edges);
4975
4976
4988
4989
4990
4991
4997inline uint64_t undirected_edge_key(
int u,
int v) {
5000 return (
static_cast<uint64_t>(u) << 32) |
5001 static_cast<uint64_t>(
static_cast<uint32_t>(v));
5006inline uint64_t directed_edge_key(
int u,
int v) {
5007 return (
static_cast<uint64_t>(u) << 32) |
5008 static_cast<uint64_t>(
static_cast<uint32_t>(v));
5013inline long long max_graph_edges(
int n,
bool directed,
bool self_loops) {
5017 return self_loops ?
static_cast<
long long>(n) * n
5018 :
static_cast<
long long>(n) * (n - 1);
5019 return self_loops ?
static_cast<
long long>(n) * (n + 1) / 2
5020 :
static_cast<
long long>(n) * (n - 1) / 2;
5025inline std::pair<
int,
int> get_random_graph_edge(
int n,
bool directed,
5029 return {next<
int>(0, n - 1), next<
int>(0, n - 1)};
5030 int u = next<
int>(0, n - 1);
5031 int v = next<
int>(0, n - 1);
5033 v = next<
int>(0, n - 1);
5037 int u = next<
int>(0, n - 1);
5038 int v = next<
int>(0, n - 1);
5043 int u = next<
int>(0, n - 1);
5044 int v = next<
int>(0, n - 1);
5046 v = next<
int>(0, n - 1);
5055inline std::pair<
int,
int> decode_undirected_simple_edge(
int n,
long long idx) {
5056 auto base = [&](
int u) ->
long long {
5057 return static_cast<
long long>(u) * (n - 1) -
5058 static_cast<
long long>(u) * (u - 1) / 2;
5060 int lo = 0, hi = n - 2;
5062 int mid = (lo + hi + 1) / 2;
5063 if (base(mid) <= idx)
5068 return {lo, lo + 1 +
int(idx - base(lo))};
5074inline std::pair<
int,
int> decode_undirected_loops_edge(
int n,
long long idx) {
5075 auto base = [&](
int u) ->
long long {
5076 return static_cast<
long long>(u) * n -
5077 static_cast<
long long>(u) * (u - 1) / 2;
5079 int lo = 0, hi = n - 1;
5081 int mid = (lo + hi + 1) / 2;
5082 if (base(mid) <= idx)
5087 return {lo, lo +
int(idx - base(lo))};
5092inline std::pair<
int,
int> decode_directed_simple_edge(
int n,
long long idx) {
5093 int u = idx / (n - 1);
5094 int rem = idx % (n - 1);
5095 return {u, rem + (rem >= u)};
5100inline std::pair<
int,
int>
5101decode_graph_edge_index(
int n,
long long idx,
bool directed,
bool self_loops) {
5104 return {
int(idx / n),
int(idx % n)};
5105 return decode_directed_simple_edge(n, idx);
5108 return decode_undirected_loops_edge(n, idx);
5109 return decode_undirected_simple_edge(n, idx);
5115
5116
5117
5118
5119
5120
5121
5122
5124template <
typename VWeight,
typename EWeight>
5127 std::set<std::pair<
int,
int>> edges_;
5129 bool has_self_loops_;
5135 wgraph(
int n,
int m,
bool is_directed =
false,
bool has_self_loops =
false)
5136 : n_(n), m_(m), is_directed_(is_directed),
5137 has_self_loops_(has_self_loops) {
5138 tgen_ensure(n > 0,
"wgraph: number of vertices must be positive");
5144 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n_,
5145 "wgraph: vertices must be indexed in [0, n)");
5147 if (!is_directed_
and u > v)
5149 edges_.emplace(u, v);
5150 tgen_ensure(
static_cast<
int>(edges_.size()) <= m_,
5151 "wgraph: too many edges were added");
5165 std::vector<std::set<
int>> adj_;
5166 std::vector<std::pair<
int,
int>> edges_;
5170 mutable bool adj_built_{
5173 std::optional<std::vector<VWeight>> vertex_weights_;
5174 std::optional<std::vector<EWeight>>
5180 value(
const std::vector<std::set<
int>> &adj,
bool is_directed =
false)
5181 : n_(
static_cast<
int>(adj.size())),
adj_(
adj),
5182 is_directed_(is_directed), add_1_(
false), print_nm_(
false),
5184 for (
int u = 0; u < n_; ++u)
5185 for (
auto v : adj[u]) {
5188 "wgraph: value: vertices must be indexed in [0, n)");
5192 if (is_directed_
or u <= v)
5193 edges_.emplace_back(u, v);
5201 value(
int n,
const std::vector<std::pair<
int,
int>> &edges = {},
5202 bool is_directed =
false)
5203 : n_(n),
edges_(), is_directed_(is_directed), add_1_(
false),
5204 print_nm_(
false), adj_built_(
false) {
5205 edges_.reserve(edges.size());
5206 std::unordered_set<uint64_t> seen;
5207 seen.reserve(edges.size() * 2 + 1);
5208 for (
auto [u, v] : edges) {
5210 0 <= std::min(u, v)
and std::max(u, v) < n,
5211 "wgraph: value: vertices must be indexed in [0, n)");
5212 if (!is_directed_
and u > v)
5214 uint64_t key = is_directed_ ? detail::directed_edge_key(u, v)
5215 : detail::undirected_edge_key(u, v);
5216 if (seen.insert(key).second)
5217 edges_.emplace_back(u, v);
5220 value(
int n,
const std::set<std::pair<
int,
int>> &edges,
5221 bool is_directed =
false)
5226 value(
int n,
const std::initializer_list<std::pair<
int,
int>> &edges,
5227 bool is_directed =
false)
5228 : value(n, std::vector<std::pair<
int,
int>>(edges), is_directed) {}
5233 :
value(t.n(), t.edges(),
false) {
5234 if (t.vertex_weights().has_value()) {
5235 vertex_weights_ = *t.vertex_weights();
5237 if (t.edge_weights().has_value()) {
5238 edge_weights_ = *t.edge_weights();
5244 template <
typename NewVWeight,
typename NewEWeight>
5245 typename wgraph<NewVWeight, NewEWeight>::value
5246 convert_weight_types()
const {
5248 !edge_weights_.has_value(),
5249 "wgraph: value: cannot convert weight type after "
5250 "assigning weights");
5253 typename wgraph<NewVWeight, NewEWeight>::value new_graph(
5254 adj_, is_directed_);
5255 new_graph.is_directed_ = is_directed_;
5256 new_graph.add_1_ = add_1_;
5257 new_graph.print_nm_ = print_nm_;
5262 int n()
const {
return n_; }
5265 int m()
const {
return edges_.size(); }
5281 return vertex_weights_;
5286 return edge_weights_;
5291 template <
typename NewVWeight = VWeight>
5293 const std::vector<NewVWeight> &vertex_weights)
const {
5295 "wgraph: value: must give `n` vertex weights");
5297 auto new_graph = convert_weight_types<NewVWeight, EWeight>();
5298 new_graph.vertex_weights_ = vertex_weights;
5304 template <
typename NewEWeight = EWeight>
5308 "wgraph: value: must give `m` edge weights");
5310 auto new_graph = convert_weight_types<VWeight, NewEWeight>();
5311 new_graph.edge_weights_ = edge_weights;
5319 "wgraph: value: edge_weighted requires a graph with no "
5322 "wgraph: value: graph is already edge-weighted");
5324 edge_weights_ = std::vector<EWeight>();
5352 std::vector<
int> new_label(
n());
5353 std::vector<
int> shuffled;
5354 for (
int i = 0; i <
n(); ++i) {
5355 if (indices.count(i))
5358 shuffled.push_back(i);
5360 std::vector<
int> targets = shuffled;
5361 tgen::shuffle(targets.begin(), targets.end());
5362 for (size_t k = 0; k < shuffled.size(); ++k)
5363 new_label[shuffled[k]] = targets[k];
5366 std::vector<std::set<
int>> new_adj(
n());
5367 for (
int u = 0; u < n(); ++u)
5368 for (
int v : adj_[u])
5369 new_adj[new_label[u]].insert(new_label[v]);
5373 for (
auto &[u, v] : edges_) {
5376 if (!is_directed_
and u > v)
5381 if (vertex_weights_.has_value()) {
5382 std::vector<VWeight> new_vw(
n());
5383 for (
int i = 0; i < n(); ++i)
5384 new_vw[new_label[i]] = (*vertex_weights_)[i];
5385 vertex_weights_ = new_vw;
5390 std::vector<
int> perm(edges_.size());
5391 std::iota(perm.begin(), perm.end(), 0);
5392 tgen::shuffle(perm.begin(), perm.end());
5394 std::vector<std::pair<
int,
int>> new_edges;
5395 std::optional<std::vector<EWeight>> new_ew;
5396 if (edge_weights_.has_value())
5397 new_ew = std::vector<EWeight>();
5398 for (
int i : perm) {
5399 new_edges.push_back(edges_[i]);
5400 if (new_ew.has_value())
5401 new_ew->push_back((*edge_weights_)[i]);
5405 if (new_ew.has_value())
5406 edge_weights_ = new_ew;
5419 new_vertex_weights = std::nullopt) {
5423 if (new_vertex_weights.has_value()) {
5425 "wgraph: value: cannot add weighted vertices to "
5426 "vertex-unweighted graph");
5428 static_cast<
int>(new_vertex_weights->size()) == k,
5429 "wgraph: value: number of vertex weights must be equal "
5430 "to number of added vertices");
5432 vertex_weights_->insert(vertex_weights_->end(),
5433 new_vertex_weights->begin(),
5434 new_vertex_weights->end());
5437 "wgraph: value: cannot add unweighted vertices to "
5438 "vertex-weighted graph");
5448 "wgraph: value: vertex ids must be valid");
5453 if (adj_[u].count(v))
5459 edges_.emplace_back(u, v);
5461 if (w.has_value()) {
5463 "wgraph: value: cannot add weighted edge to "
5464 "edge-unweighted graph");
5466 edge_weights_->push_back(*w);
5469 "wgraph: value: cannot add unweighted edge to "
5470 "edge-weighted graph");
5480 std::optional<EWeight> new_w = std::nullopt) {
5483 "wgraph: value: vertex ids must be valid");
5487 add_vertices(rhs.n(), rhs.vertex_weights());
5488 for (
int i = 0; i < rhs
.m(); ++i) {
5489 auto [u, v] = rhs.edges()[i];
5491 rhs.edge_weights().has_value()
5492 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5507 std::set<std::pair<
int,
int>> index_pairs) {
5510 "wgraph: value: graphs must have the same is_directed value");
5513 std::set<
int> idx_left, idx_right;
5514 std::vector<
int> right_id_to_left(rhs
.n(), -1);
5515 for (
auto [l, r] : index_pairs) {
5517 0 <= l
and l < n()
and 0 <= r
and r < rhs.n(),
5518 "wgraph: value: vertex indices to glue must be valid");
5519 tgen_ensure(idx_left.count(l) == 0
and idx_right.count(r) == 0,
5520 "wgraph: value: must not have repeated indices "
5521 "on the same side to glue");
5524 idx_right.insert(r);
5525 right_id_to_left[r] = l;
5529 std::vector<
int> new_right_id(rhs
.n(), -1);
5530 int intersection_lt = 0;
5531 std::optional<std::vector<VWeight>> rhs_vertex_weights;
5532 for (
int i = 0; i < rhs
.n(); ++i) {
5533 if (right_id_to_left[i] != -1) {
5536 new_right_id[i] = right_id_to_left[i];
5539 new_right_id[i] =
n() + i - intersection_lt;
5540 if (rhs.vertex_weights().has_value()) {
5541 if (!rhs_vertex_weights.has_value())
5542 rhs_vertex_weights = std::vector<VWeight>();
5543 rhs_vertex_weights->push_back(
5544 (*rhs.vertex_weights())[i]);
5550 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
5551 for (
int i = 0; i < rhs
.m(); ++i) {
5552 auto [u, v] = rhs.edges()[i];
5554 rhs.edge_weights().has_value()
5555 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5562 std::initializer_list<std::pair<
int,
int>> il) {
5563 return glue(rhs, std::set<std::pair<
int,
int>>(il));
5571 std::set<std::pair<
int,
int>> index_pairs;
5572 for (
auto i : indices)
5573 index_pairs.emplace(i, i);
5574 return glue(rhs, index_pairs);
5576 value &glue(
const value &rhs,
const std::initializer_list<
int> &il) {
5577 return glue(rhs, std::set<
int>(il));
5584 return glue(rhs, std::set<
int>());
5592 "wgraph: value: can choose at most `m` edges from graph");
5594 std::vector<std::pair<
int,
int>> new_edges;
5595 std::optional<std::vector<EWeight>> new_edge_weights;
5598 for (
int i = 0; i <
m(); ++i) {
5599 if (next(1, left--) <= num_edges) {
5600 new_edges.push_back(edges()[i]);
5601 if (edge_weights_.has_value()) {
5602 if (!new_edge_weights.has_value())
5603 new_edge_weights = std::vector<EWeight>();
5604 new_edge_weights->push_back((*edge_weights())[i]);
5611 edge_weights_ = new_edge_weights;
5612 rebuild_adj_from_edge_list();
5624 "wgraph: value: random_connected_subgraph is only for "
5625 "undirected graphs");
5628 "wgraph: value: can choose at most `m` edges from graph");
5632 std::vector<std::vector<std::pair<
int,
int>>> incident(
n());
5633 for (
int i = 0; i <
m(); ++i) {
5634 auto [u, v] = edges_[i];
5635 incident[u].emplace_back(v, i);
5636 incident[v].emplace_back(u, i);
5640 std::vector<
bool> vis(
n(),
false);
5641 std::vector<
int> queue;
5642 std::vector<
bool> in_tree(
m(),
false);
5643 int forest_edges = 0;
5645 for (
int start = 0; start <
n(); ++start) {
5649 queue.push_back(start);
5651 while (!queue.empty()) {
5652 int i = tgen::next<
int>(0, queue.size() - 1);
5654 std::swap(queue[i], queue.back());
5657 for (
auto [v, edge_idx] : incident[u]) {
5661 in_tree[edge_idx] =
true;
5668 num_edges >= forest_edges,
5669 "wgraph: value: random_connected_subgraph needs at least "
5670 "`n - c` edges, where `c` is the number of connected "
5674 std::vector<
int> tree_idx, rest_idx;
5675 for (
int i = 0; i <
m(); ++i) {
5677 tree_idx.push_back(i);
5679 rest_idx.push_back(i);
5682 tgen::shuffle(rest_idx.begin(), rest_idx.end());
5684 std::vector<
int> chosen_idx;
5685 chosen_idx.insert(chosen_idx.end(), tree_idx.begin(),
5687 chosen_idx.insert(chosen_idx.end(), rest_idx.begin(),
5688 rest_idx.begin() + num_edges - forest_edges);
5690 detail::tgen_ensure_against_bug(
5691 static_cast<
int>(chosen_idx.size()) == num_edges,
5692 "wgraph: value: chose a wrong number of edges");
5694 std::vector<std::pair<
int,
int>> new_edges;
5695 std::optional<std::vector<EWeight>> new_edge_weights;
5696 if (edge_weights_.has_value())
5697 new_edge_weights = std::vector<EWeight>();
5698 for (
int i : chosen_idx) {
5699 new_edges.push_back(edges_[i]);
5700 if (new_edge_weights.has_value())
5701 new_edge_weights->push_back((*edge_weights_)[i]);
5705 edge_weights_ = new_edge_weights;
5706 rebuild_adj_from_edge_list();
5714 "wgraph: value: cannot compute complement of "
5715 "edge-weighted graph");
5717 value complement = *
this;
5718 complement.ensure_adj_built();
5719 std::vector<std::pair<
int,
int>> compl_edges;
5720 for (
int i = 0; i < complement.n_; ++i) {
5721 std::set<
int> complement_adj;
5722 for (
int j = 0; j < complement.n_; ++j) {
5724 if (j == i
and complement.adj_[i].count(j))
5726 if (j != i
and !complement.adj_[i].count(j))
5730 complement_adj.insert(j);
5732 if (i <= j
or complement.is_directed_) {
5733 compl_edges.emplace_back(i, j);
5737 std::swap(complement.adj_[i], complement_adj);
5739 std::swap(complement.edges_, compl_edges);
5748 "wgraph: value: graphs must have the same "
5749 "is_directed value");
5752 rhs.vertex_weights().has_value(),
5753 "wgraph: value: cannot concatenate vertex-weighted "
5754 "wgraph to unweighted");
5756 rhs.edge_weights().has_value(),
5757 "wgraph: value: cannot concatenate edge-weighted "
5758 "wgraph to unweighted");
5760 value concat = *
this;
5761 concat.glue(rhs, std::set<std::pair<
int,
int>>());
5762 concat.add_1_ = add_1_ | rhs.add_1_;
5763 concat.print_nm_ = print_nm_ | rhs.print_nm_;
5770 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
5773 out << val.n() <<
" " << val.m() <<
'\n';
5776 if (val.vertex_weights()) {
5777 for (
int i = 0; i < val.n(); ++i) {
5780 out << (*val.vertex_weights())[i];
5786 for (
int i = 0; i < val.m(); ++i) {
5787 auto [u, v] = val.edges()[i];
5788 out << (u + val.add_1_) <<
" " << (v + val.add_1_);
5791 if (val.edge_weights().has_value())
5792 out <<
" " << (*val.edge_weights())[i];
5803 return std_type(n_, m(), adj_);
5810 void rebuild_adj_from_edge_list() {
5811 adj_.assign(n_, {});
5812 for (
auto [u, v] : edges_) {
5822 void ensure_adj_built()
const {
5825 const_cast<
value *>(
this)->rebuild_adj_from_edge_list();
5833 "wgraph: graphs must have the same is_directed value");
5835 for (
auto [u, v] : rhs.edges())
5845 detail::tgen_ensure_against_bug(
static_cast<
int>(edges_.size()) <= m_,
5846 "wgraph: too many edges were added");
5849 if (
static_cast<
int>(edges_.size()) == m_)
5850 return value(n_, edges_, is_directed_);
5855 if (
auto indexed = try_gen_by_edge_index())
5859 return gen_remaining_edges(
5860 std::vector<std::pair<
int,
int>>(edges_.begin(), edges_.end()));
5870 "wgraph: get_connected is only for undirected graphs");
5872 "wgraph: connected graph needs at least n - 1 edges");
5874 std::vector<std::pair<
int,
int>> edges;
5877 if (edges_.empty()) {
5879 std::vector<
int> prufer(n_ - 2);
5880 for (
int i = 0; i < n_ - 2; ++i)
5881 prufer[i] = next<
int>(0, n_ - 1);
5882 for (
auto [u, v] : detail::edges_from_prufer(std::move(prufer)))
5883 edges.emplace_back(u, v);
5886 edges.assign(edges_.begin(), edges_.end());
5888 std::vector<std::vector<
int>> adj(n_);
5889 for (
auto [u, v] : edges_) {
5890 adj[u].push_back(v);
5891 adj[v].push_back(u);
5894 std::vector<
int> comp_size;
5895 std::vector<std::vector<
int>> component_ids;
5896 std::vector<
bool> vis(n_,
false);
5899 for (
int i = 0; i < n_; ++i) {
5905 comp_size.push_back(0);
5906 component_ids.emplace_back();
5911 component_ids.back().push_back(u);
5912 for (
int v : adj[u]) {
5921 if (component_ids.size() > 1) {
5922 std::vector<
int> prufer_values =
5923 many_by_distribution(component_ids.size() - 2, comp_size);
5925 detail::edges_from_prufer(std::move(prufer_values)))
5926 edges.emplace_back(pick(component_ids[u]),
5927 pick(component_ids[v]));
5931 return gen_remaining_edges(std::move(edges));
5944 "wgraph: get_acyclic is only for directed graphs");
5946 if (edges_.empty()) {
5947 std::vector<
int> order(n_);
5948 std::iota(order.begin(), order.end(), 0);
5949 for (
int i = n_ - 1; i > 0; --i)
5950 std::swap(order[i], order[next(0, i)]);
5952 const long long max_pairs =
5953 static_cast<
long long>(n_) * (n_ - 1) / 2;
5955 "wgraph: not enough edges to generate");
5957 std::vector<std::pair<
int,
int>> edges;
5959 for (
long long idx : distinct_range<
long long>(0, max_pairs - 1)
5962 auto [i, j] = detail::decode_undirected_simple_edge(n_, idx);
5963 edges.emplace_back(order[i], order[j]);
5965 return value(n_, edges,
true);
5968 std::vector<std::vector<
int>> adj(n_);
5969 std::vector<
int> indeg(n_, 0);
5970 for (
auto [u, v] : edges_) {
5971 adj[u].push_back(v);
5975 std::vector<
int> available;
5976 for (
int i = 0; i < n_; ++i)
5978 available.push_back(i);
5981 std::vector<
int> order;
5982 while (!available.empty()) {
5983 int idx = next(0,
static_cast<
int>(available.size()) - 1);
5984 int u = available[idx];
5985 std::swap(available[idx], available.back());
5986 available.pop_back();
5989 for (
int v : adj[u])
5990 if (--indeg[v] == 0)
5991 available.push_back(v);
5995 "wgraph: preset edges contain a directed cycle");
5997 value acyclic(n_, edges_,
true);
6001 detail::tgen_ensure_against_bug(acyclic.m() <= m_,
6002 "wgraph: too many edges were added");
6004 if (acyclic.m() < m_) {
6005 std::vector<
int> order_pos(n_);
6006 for (
int i = 0; i < n_; ++i)
6007 order_pos[order[i]] = i;
6009 std::unordered_set<uint64_t> seen;
6010 seen.reserve(m_ * 2);
6011 for (
auto [u, v] : acyclic.edges())
6013 detail::undirected_edge_key(order_pos[u], order_pos[v]));
6015 const long long max_pairs =
6016 static_cast<
long long>(n_) * (n_ - 1) / 2;
6017 while (acyclic.m() < m_) {
6018 std::pair<
int,
int> edge;
6019 if (!detail::try_generate_distinct(seen, [&] {
6020 long long idx = next<
long long>(0, max_pairs - 1);
6021 edge = detail::decode_undirected_simple_edge(n_, idx);
6022 return detail::undirected_edge_key(edge.first,
6025 throw detail::error(
"wgraph: not enough edges to generate");
6026 acyclic.add_edge(order[edge.first], order[edge.second]);
6046 bool is_directed =
false) {
6049 "wgraph: skewed graph needs at least n - 1 edges to be connected");
6051 "wgraph: gen_skewed spread must be at least 2");
6053 value skewed(n, {}, is_directed);
6055 std::vector<
int> parent(n), depth(n, 0);
6057 for (
int i = 1; i < n; ++i) {
6058 int p = wnext<
int>(i, elongation);
6060 depth[i] = depth[p] + 1;
6061 skewed.add_edge(p, i);
6064 const int extra = m - (n - 1);
6071 constexpr int naive_ancestor_spread = 20;
6073 if (spread <= naive_ancestor_spread) {
6074 std::vector<std::pair<
int,
int>> candidates;
6075 candidates.reserve(n * spread);
6076 for (
int u = 0; u < n; ++u) {
6077 int max_k = std::min(spread, depth[u]);
6081 for (
int k = 2; k <= max_k; ++k) {
6083 candidates.emplace_back(v, u);
6087 tgen_ensure(extra <=
static_cast<
int>(candidates.size()),
6088 "wgraph: not enough edges to generate");
6090 for (
auto [v, u] : choose(candidates, extra))
6091 skewed.add_edge(v, u);
6095 while ((1 << lg) <= n)
6098 std::vector<std::vector<
int>> up(lg, std::vector<
int>(n));
6099 for (
int v = 0; v < n; ++v)
6100 up[0][v] = parent[v];
6101 for (
int j = 1; j < lg; ++j)
6102 for (
int v = 0; v < n; ++v)
6103 up[j][v] = up[j - 1][up[j - 1][v]];
6109 std::vector<
int> distribution = depth;
6110 for (
int &d : distribution)
6111 d = std::max(0, std::min(spread - 1, d - 1));
6113 distinct extra_edges([&]() -> std::pair<
int,
int> {
6114 int u = vertex_choice.next();
6115 int k = next(2, spread);
6117 for (
int j = 0; j < lg; ++j)
6123 while (skewed.m() < m) {
6124 std::pair<
int,
int> edge;
6126 edge = extra_edges.gen();
6127 }
catch (
const std::runtime_error &e) {
6128 if (std::string(e.what()) ==
6129 "tgen: distinct: no more distinct values")
6130 throw detail::error(
6131 "wgraph: not enough edges to generate");
6135 skewed.add_edge(edge.first, edge.second);
6149 tgen_ensure(m >= 0,
"wgraph: number of edges must be nonnegative");
6150 long long num_edges = 1LL * n1 * n2;
6152 "wgraph: bipartite graph has at most n1 * n2 edges");
6156 "wgraph: connected bipartite graph needs at least n1 + n2 - 1 "
6160 std::vector<std::pair<
int,
int>> edges;
6162 for (
long long idx : distinct_range<
long long>(0, num_edges - 1)
6165 edges.emplace_back(
static_cast<
int>(idx / n2),
6166 n1 +
static_cast<
int>(idx % n2));
6167 return value(n1 + n2, std::move(edges),
false);
6170 std::unordered_set<uint64_t> used_edges;
6171 used_edges.reserve(m * 2);
6172 std::vector<std::pair<
int,
int>> edges;
6175 auto pack_edge = [](
int u,
int v) -> uint64_t {
6178 return (
static_cast<uint64_t>(u) << 32) |
static_cast<uint32_t>(v);
6181 if (n1 > 0
and n2 > 0) {
6182 std::vector<
int> prufer(n1 + n2 - 2);
6183 for (
int i = 0; i < n2 - 1; ++i)
6184 prufer[i] = next(0, n1 - 1);
6185 for (
int i = 0; i < n1 - 1; ++i)
6186 prufer[n2 - 1 + i] = next(n1, n1 + n2 - 1);
6187 shuffle(prufer.begin(), prufer.end());
6188 for (
auto [u, v] : detail::edges_from_prufer(std::move(prufer))) {
6191 if (used_edges.insert(pack_edge(u, v)).second)
6192 edges.emplace_back(u, v);
6194 detail::tgen_ensure_against_bug(
6195 used_edges.size() == size_t(n1 + n2 - 1),
6196 "wgraph: invalid bipartite spanning tree size");
6199 while (edges.size() < size_t(m)) {
6200 int u = next(0, n1 - 1);
6201 int v = next(n1, n1 + n2 - 1);
6202 if (used_edges.insert(pack_edge(u, v)).second)
6203 edges.emplace_back(u, v);
6206 return value(n1 + n2, std::move(edges),
false);
6215 std::optional<
value> try_gen_by_edge_index()
const {
6216 if (!edges_.empty())
6217 return std::nullopt;
6219 long long max_edges =
6220 detail::max_graph_edges(n_, is_directed_, has_self_loops_);
6222 throw detail::error(
"wgraph: not enough edges to generate");
6223 if (max_edges <= 0
or 2LL * m_ <= max_edges)
6224 return std::nullopt;
6226 std::vector<std::pair<
int,
int>> edges;
6228 for (
long long idx :
6229 distinct_range<
long long>(0, max_edges - 1).gen_list(m_).to_std())
6230 edges.push_back(detail::decode_graph_edge_index(
6231 n_, idx, is_directed_, has_self_loops_));
6233 return value(n_, edges, is_directed_);
6239 value gen_remaining_edges(std::vector<std::pair<
int,
int>> edges)
const {
6240 detail::tgen_ensure_against_bug(
static_cast<
int>(edges.size()) <= m_,
6241 "wgraph: too many edges were added");
6243 if (
static_cast<
int>(edges.size()) == m_)
6244 return value(n_, edges, is_directed_);
6248 std::unordered_set<uint64_t> seen;
6249 seen.reserve(m_ * 2);
6250 for (
auto [u, v] : edges) {
6251 if (!is_directed_
and u > v)
6253 seen.insert(is_directed_ ? detail::directed_edge_key(u, v)
6254 : detail::undirected_edge_key(u, v));
6257 while (
static_cast<
int>(edges.size()) < m_) {
6258 std::pair<
int,
int> edge;
6259 if (!detail::try_generate_distinct(seen, [&] {
6260 edge = detail::get_random_graph_edge(n_, is_directed_,
6262 if (!is_directed_
and edge.first > edge.second)
6263 std::swap(edge.first, edge.second);
6264 return is_directed_ ? detail::directed_edge_key(edge.first,
6266 : detail::undirected_edge_key(
6267 edge.first, edge.second);
6269 throw detail::error(
"wgraph: not enough edges to generate");
6270 edges.emplace_back(edge);
6273 return value(n_, edges, is_directed_);
6279template <
typename VWeight,
typename EWeight>
6281 const typename wgraph<VWeight, EWeight>::value &g)
6282 : n_(g.n()),
adj_(
g.
n()), add_1_(
false), print_n_(
false),
dsu_(
g.
n()) {
6283 tgen_ensure(g.n() > 0,
"wtree: value: graph must have at least one vertex");
6285 "wtree: value: graph must be undirected to form a tree");
6287 if (g.vertex_weights().has_value())
6288 vertex_weights_ = *g.vertex_weights();
6289 if (g.edge_weights().has_value())
6290 edge_weights_ = std::vector<EWeight>();
6295 std::vector<
int> order(g.m());
6296 std::iota(order.begin(), order.end(), 0);
6297 tgen::shuffle(order.begin(), order.end());
6299 std::vector<std::pair<
int,
int>> tree_edges;
6300 tree_edges.reserve(n_ - 1);
6302 for (
int i : order) {
6303 auto [u, v] = g.edges()[i];
6304 if (!dsu_.unite(u, v))
6309 tree_edges.emplace_back(u, v);
6312 if (edge_weights_.has_value())
6313 edge_weights_->push_back((*g.edge_weights())[i]);
6314 if (
static_cast<
int>(tree_edges.size()) == n_ - 1)
6318 tgen_ensure(
static_cast<
int>(tree_edges.size()) == n_ - 1,
6319 "wtree: value: graph must be connected to form a tree");
6321 edges_ = std::move(tree_edges);
6325
6326
6338
6339
6343inline graph::
value K(
int n) {
return graph(n, n * (n - 1) / 2).gen(); }
6350 graph g(n, n - 1, is_directed);
6351 for (
int i = 0; i + 1 < n; ++i)
6352 g.add_edge(i, i + 1);
6361 tgen_ensure(n >= 3,
"graph: cycle size must be at least 3");
6363 graph g(n, n, is_directed);
6364 for (
int i = 0; i < n; ++i)
6365 g.add_edge(i, (i + 1) % n);
6374 graph g(n1 + n2,
static_cast<
long long>(n1) * n2);
6375 for (
int i = 0; i < n1; ++i)
6376 for (
int j = 0; j < n2; ++j)
6377 g.add_edge(i, n1 + j);
6387
6388
6389
6390
6396 static_assert(std::is_arithmetic_v<T>,
6397 "point requires an arithmetic coordinate type");
6409 point(T x = 0, T y = 0) : x_(x), y_(y) {}
6412 T
x()
const {
return x_; }
6415 T
y()
const {
return y_; }
6419 static bool coord_eq(T a, T b) {
6420 if constexpr (std::is_integral_v<T>)
6422 constexpr T eps = T(1e-9);
6424 return d >= -eps
and d <= eps;
6429 if (!coord_eq(x_, p
.x()))
6436 return coord_eq(x_, p
.x())
and coord_eq(y_, p
.y());
6454 if constexpr (std::is_floating_point_v<T>)
6456 return product_t(x_) * p
.x() + product_t(y_) * p
.y();
6461 if constexpr (std::is_floating_point_v<T>)
6463 return product_t(x_) * p
.y() - product_t(y_) * p
.x();
6467 friend std::ostream &operator<<(std::ostream &out,
const point &p) {
6468 return out << p
.x() <<
' ' << p
.y();
6477 long long max_coord) {
6479 "geometry: random_points_general_position: n must be positive");
6481 "geometry: random_points_general_position: min_coord must be "
6482 "at most max_coord");
6484 static_cast<detail::i128>(max_coord) - min_coord <=
6485 std::numeric_limits<
long long>::max(),
6486 "geometry: random_points_general_position: coordinate range too large");
6487 uint64_t width = max_coord - min_coord;
6492 "geometry: random_points_general_position: coordinate range "
6501 std::vector<uint64_t> x_range(p - 1);
6502 std::iota(x_range.begin(), x_range.end(), 1);
6503 shuffle(x_range.begin(), x_range.end());
6504 std::vector<detail::i128> bx(n), by(n);
6505 for (
int i = 0; i < n; ++i) {
6506 uint64_t x = x_range[i];
6508 by[i] = math::modular_inverse(x, p);
6516 const int num_shears = 8;
6517 std::vector<detail::i128> lin_x = bx, lin_y = by;
6519 for (
int it = 0; it < num_shears; ++it) {
6520 bool vertical_shear = next(2) == 0;
6521 int shear_r = pick({-2, -1, 1, 2});
6523 for (
int i = 0; i < n; ++i) {
6525 lin_x[i] = (lin_x[i] + shear_r * lin_y[i]) % p;
6527 lin_y[i] = (lin_y[i] + shear_r * lin_x[i]) % p;
6536 detail::i128 min_x = lin_x[0], max_x = lin_x[0], min_y = lin_y[0],
6538 for (
int i = 1; i < n; ++i) {
6539 min_x = std::min(min_x, lin_x[i]);
6540 max_x = std::max(max_x, lin_x[i]);
6541 min_y = std::min(min_y, lin_y[i]);
6542 max_y = std::max(max_y, lin_y[i]);
6546 min_coord - min_x + next<
long long>(0, width - (max_x - min_x));
6548 min_coord - min_y + next<
long long>(0, width - (max_y - min_y));
6550 std::vector<point<
long long>> pts;
6551 for (
int i = 0; i < n; ++i)
6552 pts.emplace_back(lin_x[i] + x_shift, lin_y[i] + y_shift);
6558using i128 = tgen::detail::i128;
6562inline i128 ccw(
const point<
long long> &a,
const point<
long long> &b,
6563 const point<
long long> &p) {
6564 return (
static_cast<i128>(b.x()) - a.x()) *
6565 (
static_cast<i128>(p.y()) - a.y()) -
6566 (
static_cast<i128>(b.y()) - a.y()) *
6567 (
static_cast<i128>(p.x()) - a.x());
6571inline i128 proj_on_ab(
const point<
long long> &P,
const point<
long long> &A,
6572 const point<
long long> &B) {
6573 return (P - A) * (B - A);
6579inline void conquer(std::vector<point<
long long>> &points,
int left,
6581 if (right - left <= 3)
6584 point<
long long> A = points[left], B = points[right - 1];
6587 bool all_collinear =
true;
6588 for (
int k = left + 1; k < right - 1; ++k) {
6589 if (ccw(A, B, points[k]) != 0) {
6590 all_collinear =
false;
6594 if (all_collinear) {
6595 std::sort(points.begin() + left, points.begin() + right,
6596 [&](
const point<
long long> &P,
const point<
long long> &Q) {
6597 return proj_on_ab(P, A, B) < proj_on_ab(Q, A, B);
6603 std::vector<
int> candidates;
6604 for (
int k = left + 1; k < right - 1; ++k) {
6605 if (ccw(A, B, points[k]) != 0)
6606 candidates.push_back(k);
6608 int ci = candidates[next(0,
static_cast<
int>(candidates.size()) - 1)];
6609 point<
long long> C = points[ci];
6611 uint64_t wa = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6612 uint64_t wb = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6613 bool a_on_positive = ccw(C, A, B) < 0;
6617 i128 proj_sum = proj_on_ab(A, A, B) + proj_on_ab(B, A, B);
6618 auto is_positive = [&](
const point<
long long> &P) ->
bool {
6619 i128 s = wa * ccw(C, A, P) + wb * ccw(C, B, P);
6624 return 2 * proj_on_ab(P, A, B) > proj_sum;
6629 if (ci != right - 2)
6630 std::swap(points[ci], points[right - 2]);
6635 if (is_positive(points[i]) == a_on_positive)
6637 else if (is_positive(points[j]) != a_on_positive)
6640 std::swap(points[i], points[j]);
6651 if (i == j
and is_positive(points[i]) == a_on_positive)
6653 std::swap(points[p], points[right - 2]);
6656 conquer(points, left, p + 1);
6658 conquer(points, p, right);
6665inline std::vector<
long long>
6666sample_sorted_distinct_in_range(
int k,
long long left,
long long right) {
6667 long long universe = right - left + 1;
6668 std::vector<
long long> res;
6673 constexpr long long pool_threshold = 8'000'000;
6674 constexpr long long pool_always_below = 500'000;
6676 if (universe <= pool_threshold
and
6677 (universe <= pool_always_below
or k >= universe / 4)) {
6678 size_t u = universe;
6680 std::vector<
long long> pool(u);
6681 std::iota(pool.begin(), pool.end(), left);
6682 size_t m = ks <= u / 2 ? ks : u - ks;
6683 for (size_t i = 0; i < m; ++i) {
6684 size_t j = next<size_t>(i, u - 1);
6685 std::swap(pool[i], pool[j]);
6688 res.assign(pool.begin(), pool.begin() + ks);
6689 std::sort(res.begin(), res.end());
6691 std::vector<
char> excluded(u, 0);
6692 for (size_t i = 0; i < m; ++i)
6693 excluded[pool[i] - left] = 1;
6694 for (
long long v = left; v <= right; ++v)
6695 if (!excluded[v - left])
6699 std::unordered_map<
long long,
long long> virtual_list;
6700 virtual_list.reserve(k * 2);
6701 for (
long long i = 0; i < k; ++i) {
6702 long long j = next<
long long>(i, universe - 1);
6703 long long vi = virtual_list.count(i) ? virtual_list[i] : i;
6704 long long vj = virtual_list.count(j) ? virtual_list[j] : j;
6705 virtual_list[j] = vi;
6706 virtual_list[i] = vj;
6707 res.push_back(virtual_list[i] + left);
6709 std::sort(res.begin(), res.end());
6716inline std::vector<
long long>
6717valtr_edge_components(
const std::vector<
long long> &sorted_coords) {
6718 int n = sorted_coords.size();
6719 std::vector<
long long> left, right;
6720 left.reserve(n / 2);
6721 right.reserve(n / 2);
6722 for (
int i = 1; i + 1 < n; ++i) {
6724 left.push_back(sorted_coords[i]);
6726 right.push_back(sorted_coords[i]);
6728 long long lo = sorted_coords.front(), hi = sorted_coords.back();
6729 std::vector<
long long> seq;
6732 for (
long long v : left)
6735 for (
auto it = right.rbegin(); it != right.rend(); ++it)
6738 std::vector<
long long> comps(n);
6739 for (
int i = 0; i < n; ++i)
6740 comps[i] = seq[i + 1] - seq[i];
6746inline std::vector<point<
long long>>
6747simplify_strict_boundary(std::vector<point<
long long>> points) {
6748 int n = points.size();
6752 std::vector<point<
long long>> strict_points;
6753 strict_points.reserve(n);
6754 for (
int i = 0; i < n; ++i) {
6755 if (ccw(points[(i + n - 1) % n], points[i], points[(i + 1) % n]) != 0)
6756 strict_points.push_back(points[i]);
6758 return strict_points;
6763inline std::vector<point<
long long>>
6764subsample_boundary(
const std::vector<point<
long long>> &points,
int k) {
6765 int n = points.size();
6769 std::vector<point<
long long>> sampled_points;
6770 sampled_points.reserve(k);
6771 for (
int i = 0; i < k; ++i)
6772 sampled_points.push_back(points[(
static_cast<i128>(i) * n) / k]);
6773 return sampled_points;
6778inline void place_inside_box(std::vector<point<
long long>> &points,
6779 long long min_coord,
long long max_coord) {
6780 long long width = max_coord - min_coord + 1;
6782 i128 min_x = points[0].x(), max_x = points[0].x();
6783 i128 min_y = points[0].y(), max_y = points[0].y();
6784 for (
const point<
long long> &p : points) {
6785 min_x = std::min(min_x,
static_cast<i128>(p.x()));
6786 max_x = std::max(max_x,
static_cast<i128>(p.x()));
6787 min_y = std::min(min_y,
static_cast<i128>(p.y()));
6788 max_y = std::max(max_y,
static_cast<i128>(p.y()));
6791 i128 span_x = max_x - min_x;
6792 i128 span_y = max_y - min_y;
6796 next<
long long>(0, width - 1 -
static_cast<
long long>(span_x));
6799 next<
long long>(0, width - 1 -
static_cast<
long long>(span_y));
6801 for (point<
long long> &p : points)
6802 p = point<
long long>(p.x() + shift_x, p.y() + shift_y);
6807inline void randomize_cyclic_shift(std::vector<point<
long long>> &points) {
6808 int rot = next(points.size());
6810 std::rotate(points.begin(), points.begin() + rot, points.end());
6815inline std::vector<point<
long long>>
6816valtr_vertices(
int m,
const std::vector<
long long> &x_comp,
6817 std::vector<
long long> y_comp) {
6818 shuffle(y_comp.begin(), y_comp.end());
6820 std::vector<point<
long long>> edges(m);
6822 auto upper = [](
const point<
long long> &p) {
6823 return p.y() > 0
or (p.y() == 0
and p.x() > 0);
6825 for (
int i = 0; i < m; ++i)
6826 edges[i] =
point<
long long>(x_comp[i], y_comp[i]);
6828 std::sort(edges.begin(), edges.end(),
6829 [&upper](
const point<
long long> &a,
const point<
long long> &b) {
6830 bool au = upper(a), bu = upper(b);
6836 return (a * a) < (b * b);
6840 i128 cur_x = 0, cur_y = 0;
6841 std::vector<i128> px(m), py(m);
6842 for (
int i = 0; i < m; ++i) {
6845 cur_x += edges[i].x();
6846 cur_y += edges[i].y();
6848 tgen::detail::tgen_ensure_against_bug(
6849 cur_x == 0
and cur_y == 0,
6850 "geometry: random_convex_polygon: walk did not close");
6852 i128 min_x = px[0], min_y = py[0];
6853 for (
int i = 1; i < m; ++i) {
6854 min_x = std::min(min_x, px[i]);
6855 min_y = std::min(min_y, py[i]);
6859 std::vector<point<
long long>> points;
6861 for (
int i = 0; i < m; ++i)
6862 points.emplace_back(px[i] - min_x, py[i] - min_y);
6875 bool strict =
false) {
6877 "geometry: random_convex_polygon: n must be at least 3");
6879 "geometry: random_convex_polygon: min_coord must be at most "
6881 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord + 1 <=
6882 std::numeric_limits<
long long>::max(),
6883 "geometry: random_convex_polygon: coordinate range too large");
6884 long long width = max_coord - min_coord + 1;
6887 "geometry: random_convex_polygon: coordinate range too small for n");
6895 int extra = width <= n ? 0
6896 : std::min<
long long>(std::max(100, n / 1000),
6898 num_coords = n + extra;
6903 const int max_attempts = strict ? 32 : 1;
6904 for (
int i = 0; i < max_attempts; ++i) {
6906 std::vector<
long long> x_sorted =
6907 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6908 std::vector<
long long> y_sorted =
6909 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6910 std::vector<
long long> x_comp = detail::valtr_edge_components(x_sorted);
6911 std::vector<
long long> y_comp = detail::valtr_edge_components(y_sorted);
6913 std::vector<point<
long long>> points =
6914 detail::valtr_vertices(num_coords, x_comp, std::move(y_comp));
6917 std::vector<point<
long long>> simplified =
6918 detail::simplify_strict_boundary(std::move(points));
6920 if (
static_cast<
int>(simplified.size()) < n)
6923 points = detail::subsample_boundary(simplified, n);
6926 detail::place_inside_box(points, min_coord, max_coord);
6927 detail::randomize_cyclic_shift(points);
6932 throw tgen::detail::error(
6933 "geometry: random_convex_polygon: generation failed: coordinate "
6934 "range too small for n");
6942 const std::vector<point<
long long>> &points) {
6943 int n = points.size();
6945 "geometry: random_simple_polygon_through_points: need at "
6949 std::set<point<
long long>>(points.begin(), points.end()).size()) ==
6951 "geometry: random_simple_polygon_through_points: points must "
6954 int idx_a = 0, idx_b = 0;
6955 for (
int i = 1; i < n; ++i) {
6956 if (points[i] < points[idx_a])
6958 if (points[idx_b] < points[i])
6961 point<
long long> A = points[idx_a], B = points[idx_b];
6963 bool all_collinear =
true;
6964 for (
int i = 0; i < n; ++i) {
6965 if (i == idx_a
or i == idx_b)
6967 if (detail::ccw(A, B, points[i]) != 0) {
6968 all_collinear =
false;
6973 "geometry: random_simple_polygon_through_points: all points "
6974 "are collinear; no simple polygon exists");
6979 int negative_count = 0;
6980 for (
int i = 0; i < n; ++i) {
6981 if (i == idx_a
or i == idx_b)
6983 if (detail::ccw(A, B, points[i]) < 0)
6987 std::vector<point<
long long>> chain;
6990 for (
int i = 0; i < n; ++i) {
6991 if (i == idx_a
or i == idx_b)
6993 detail::i128 side = detail::ccw(A, B, points[i]);
6994 if (side < 0
or (side == 0
and negative_count == 0)) {
6995 chain.push_back(points[i]);
7000 for (
int i = 0; i < n; ++i) {
7001 if (i == idx_a
or i == idx_b)
7003 detail::i128 side = detail::ccw(A, B, points[i]);
7004 if (side > 0
or (side == 0
and negative_count != 0))
7005 chain.push_back(points[i]);
7009 int n1 = 2 + left_count;
7011 detail::conquer(chain, 0, n1);
7013 detail::conquer(chain, n1 - 1, chain.size());
7017 std::vector<point<
long long>> poly;
7018 poly.insert(poly.end(), chain.begin() + 1, chain.begin() + n1);
7019 poly.insert(poly.end(), chain.begin() + n1, chain.end());
7027inline std::vector<point<
long long>>
7028random_distinct_points_in_box(
int n,
long long min_coord,
long long max_coord) {
7029 long long width = max_coord - min_coord;
7030 i128 side_128 = width + 1;
7031 i128 universe = side_128 * side_128;
7032 tgen_ensure(universe <= std::numeric_limits<
long long>::max(),
7033 "geometry: random_simple_polygon: coordinate range too large");
7034 long long side = side_128;
7036 "geometry: random_simple_polygon: coordinate range too small "
7037 "for n distinct points");
7040 auto decode = [&](
long long key) ->
point<
long long> {
7041 return point<
long long>(min_coord + key / side, min_coord + key % side);
7047 std::vector<
long long> keys =
7048 distinct_range<
long long>(0, universe - 1).gen_list(n).to_std();
7050 std::vector<point<
long long>> points;
7052 for (
long long key : keys)
7053 points.push_back(decode(key));
7056 for (
int i = 2; i < n; ++i) {
7057 if (ccw(points[0], points[1], points[i]) != 0)
7065struct ortho_poly_edge {
7075inline bool ortho_axis_collinear(
const point<
long long> &a,
7076 const point<
long long> &b,
7077 const point<
long long> &c) {
7078 return (a.x() == b.x()
and b.x() == c.x())
or
7079 (a.y() == b.y()
and b.y() == c.y());
7084inline ortho_poly_edge
7085ortho_analyze_edge(
const std::vector<point<
long long>> &poly,
int i) {
7086 int m = poly.size();
7087 point<
long long> a = poly[i], b = poly[(i + 1) % m];
7088 ortho_poly_edge e{};
7089 if (a.y() == b.y()) {
7092 e.lo = std::min(a.x(), b.x());
7093 e.hi = std::max(a.x(), b.x());
7095 e.out_y = a.x() < b.x() ? -1 : 1;
7098 e.lo = std::min(a.y(), b.y());
7099 e.hi = std::max(a.y(), b.y());
7100 e.out_x = a.y() < b.y() ? 1 : -1;
7102 e.len = e.hi - e.lo;
7109inline bool ortho_open_seg_cross(
const point<
long long> &a,
7110 const point<
long long> &b,
7111 const point<
long long> &c,
7112 const point<
long long> &d) {
7113 if (a.y() == b.y()
and c.y() == d.y()) {
7116 long long lo1 = std::min(a.x(), b.x()), hi1 = std::max(a.x(), b.x());
7117 long long lo2 = std::min(c.x(), d.x()), hi2 = std::max(c.x(), d.x());
7118 return lo1 < hi2
and lo2 < hi1;
7120 if (a.x() == b.x()
and c.x() == d.x()) {
7123 long long lo1 = std::min(a.y(), b.y()), hi1 = std::max(a.y(), b.y());
7124 long long lo2 = std::min(c.y(), d.y()), hi2 = std::max(c.y(), d.y());
7125 return lo1 < hi2
and lo2 < hi1;
7127 if (a.y() == b.y()
and c.x() == d.x()) {
7128 long long hx = a.y(), vx = c.x();
7129 long long hlo = std::min(a.x(), b.x()), hhi = std::max(a.x(), b.x());
7130 long long vlo = std::min(c.y(), d.y()), vhi = std::max(c.y(), d.y());
7131 return hlo < vx
and vx < hhi
and vlo < hx
and hx < vhi;
7133 if (a.x() == b.x()
and c.y() == d.y()) {
7134 long long vx = a.x(), hy = c.y();
7135 long long vlo = std::min(a.y(), b.y()), vhi = std::max(a.y(), b.y());
7136 long long hlo = std::min(c.x(), d.x()), hhi = std::max(c.x(), d.x());
7137 return vlo < hy
and hy < vhi
and hlo < vx
and vx < hhi;
7144inline bool ortho_point_inside(
const std::vector<point<
long long>> &poly,
7145 point<
long long> p) {
7146 int m = poly.size();
7147 bool inside =
false;
7148 for (
int i = 0, j = m - 1; i < m; j = i++) {
7149 point<
long long> a = poly[i], b = poly[j];
7150 if ((a.y() > p.y()) != (b.y() > p.y())) {
7151 i128 x_cross = i128(b.x() - a.x()) * (p.y() - a.y()) -
7152 i128(p.x() - a.x()) * (b.y() - a.y());
7153 if ((a.y() < b.y()) ? x_cross > 0 : x_cross < 0)
7162inline bool ortho_point_strictly_interior(
point<
long long> p,
7164 point<
long long> b) {
7165 if (a.y() == b.y()) {
7168 long long lo = std::min(a.x(), b.x()), hi = std::max(a.x(), b.x());
7169 return lo < p.x()
and p.x() < hi;
7171 if (a.x() == b.x()) {
7174 long long lo = std::min(a.y(), b.y()), hi = std::max(a.y(), b.y());
7175 return lo < p.y()
and p.y() < hi;
7182inline bool ortho_point_on_segment(
point<
long long> p,
point<
long long> a,
7183 point<
long long> b) {
7184 return p == a
or p == b
or ortho_point_strictly_interior(p, a, b);
7192inline bool ortho_bump_valid(
const std::vector<point<
long long>> &poly,
7194 const std::vector<point<
long long>> &add,
7195 int edge_i,
bool inward) {
7196 int m = poly.size();
7198 for (point<
long long> v : add)
7199 for (point<
long long> q : poly)
7205 for (point<
long long> v : add) {
7206 for (
int j = 0; j < m; ++j) {
7207 point<
long long> c = poly[j], d = poly[(j + 1) % m];
7209 if (ortho_point_on_segment(v, c, d)
and
7210 !ortho_point_on_segment(v, A, B))
7212 }
else if (ortho_point_strictly_interior(v, c, d)) {
7218 auto seg_ok = [&](
point<
long long> s0,
point<
long long> s1) {
7219 for (
int j = 0; j < m; ++j) {
7222 point<
long long> c = poly[j], d = poly[(j + 1) % m];
7223 if (ortho_open_seg_cross(s0, s1, c, d))
7226 for (
int k = 0; k < m; ++k) {
7227 point<
long long> q = poly[k];
7228 if (q == s0
or q == s1
or q == A
or q == B)
7230 if (ortho_point_strictly_interior(q, s0, s1))
7236 point<
long long> prev = A;
7237 for (point<
long long> v : add) {
7238 if (!seg_ok(prev, v))
7242 if (!seg_ok(prev, B))
7246 for (point<
long long> v : add)
7247 if (!ortho_point_inside(poly, v))
7257inline bool ortho_bump_edge(std::vector<point<
long long>> &poly,
int edge_i,
7258 const ortho_poly_edge &e,
long long lo,
7259 long long hi,
long long depth,
bool inward) {
7260 int m = poly.size();
7261 point<
long long> A = poly[edge_i], B = poly[(edge_i + 1) % m];
7263 int step_x = inward ? -e.out_x : e.out_x;
7264 int step_y = inward ? -e.out_y : e.out_y;
7266 std::vector<point<
long long>> add;
7268 long long y = e.fixed, y2 = y + step_y * depth;
7269 if (A.x() < B.x()) {
7271 add.emplace_back(lo, y);
7272 add.emplace_back(lo, y2);
7273 add.emplace_back(hi, y2);
7275 add.emplace_back(hi, y);
7278 add.emplace_back(hi, y);
7279 add.emplace_back(hi, y2);
7280 add.emplace_back(lo, y2);
7282 add.emplace_back(lo, y);
7285 long long x = e.fixed, x2 = x + step_x * depth;
7286 if (A.y() < B.y()) {
7288 add.emplace_back(x, lo);
7289 add.emplace_back(x2, lo);
7290 add.emplace_back(x2, hi);
7292 add.emplace_back(x, hi);
7295 add.emplace_back(x, hi);
7296 add.emplace_back(x2, hi);
7297 add.emplace_back(x2, lo);
7299 add.emplace_back(x, lo);
7302 if (!ortho_bump_valid(poly, A, B, add, edge_i, inward))
7305 poly.insert(poly.begin() + edge_i + 1, add.begin(), add.end());
7312inline int ortho_pick_poly_edge(
const std::vector<point<
long long>> &poly,
7313 std::vector<
int> &last_used,
int &time_stamp) {
7314 int m = poly.size();
7315 if (last_used.size() !=
static_cast<size_t>(m)) {
7316 last_used.assign(m, 0);
7319 std::vector<
long long> weights(m);
7320 long long total = 0;
7321 for (
int i = 0; i < m; ++i) {
7322 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7323 weights[i] = e.len * (4 + std::min(time_stamp - last_used[i], 8));
7324 total += weights[i];
7326 long long pick = next<
long long>(0, total - 1);
7327 for (
int i = 0; i < m; ++i) {
7330 last_used[i] = ++time_stamp;
7334 last_used[m - 1] = ++time_stamp;
7340inline bool ortho_try_bump(std::vector<point<
long long>> &poly,
int n,
7341 std::vector<
int> &last_used,
int &time_stamp,
7342 bool outward_only =
false) {
7343 if (poly.size() < 3)
7346 int ei = ortho_pick_poly_edge(poly, last_used, time_stamp);
7347 ortho_poly_edge e = ortho_analyze_edge(poly, ei);
7354 long long span = next<
long long>(2, e.len);
7355 long long lo = next<
long long>(e.lo, e.hi - span);
7359 long long max_depth =
7360 std::clamp<
long long>(std::sqrt(n) / 2 + 2, 2LL, 12LL);
7362 next(10) == 0 ? next<
long long>(std::max(2LL, max_depth / 2), max_depth)
7363 : next<
long long>(1, std::max(2LL, max_depth / 3));
7365 bool inward = !outward_only
and next(4) == 0;
7366 return ortho_bump_edge(poly, ei, e, lo, lo + span, depth, inward);
7371inline std::vector<point<
long long>>
7372ortho_simplify_collinear(std::vector<point<
long long>> poly) {
7373 int n = poly.size();
7376 std::vector<point<
long long>> out;
7378 for (
int i = 0; i < n; ++i) {
7379 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7381 out.push_back(poly[i]);
7383 return out.size() >= 3 ? out : poly;
7388inline bool ortho_remove_one_collinear(std::vector<point<
long long>> &poly) {
7389 int n = poly.size();
7392 for (
int i = 0; i < n; ++i) {
7393 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7396 poly.erase(poly.begin() + i);
7405inline void ortho_fill_collinear(std::vector<point<
long long>> &poly,
7407 int need = target - poly.size();
7411 std::vector<point<
long long>> out;
7412 int m = poly.size();
7413 out.reserve(poly.size() + need);
7415 for (
int i = 0; i < m; ++i) {
7416 point<
long long> a = poly[i], b = poly[(i + 1) % m];
7421 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7422 long long cap = e.len - 1;
7427 long long take = std::min<
long long>(need, cap);
7428 bool forward = e.horiz ? a.x() < b.x() : a.y() < b.y();
7429 for (
long long k = 0; k < take; ++k) {
7430 long long off = (k + 1) * (cap + 1) / (take + 1);
7431 long long coord = forward ? e.lo + off : e.hi - off;
7433 out.push_back({coord, e.fixed});
7435 out.push_back({e.fixed, coord});
7449inline void ortho_fill_corrugation(std::vector<point<
long long>> &poly,
7451 size_t n_sz = poly.size();
7455 size_t extra_left = target - n_sz;
7457 std::vector<point<
long long>> out;
7458 out.reserve(target);
7459 int n = poly.size();
7461 for (
int i = 0; i < n; ++i) {
7462 point<
long long> a = poly[i], b = poly[(i + 1) % n];
7468 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7472 long long dir = (e.horiz ? a.x() < b.x() : a.y() < b.y()) ? 1 : -1;
7473 long long start = e.horiz ? a.x() : a.y();
7474 long long end = e.horiz ? b.x() : b.y();
7476 for (
long long pos = start + 2 * dir;
7477 extra_left >= 4
and (pos - end) * dir <= -3; pos += 2 * dir) {
7479 long long y2 = e.fixed + e.out_y;
7480 out.push_back({pos, e.fixed});
7481 out.push_back({pos, y2});
7482 out.push_back({pos + dir, y2});
7483 out.push_back({pos + dir, e.fixed});
7485 long long x2 = e.fixed + e.out_x;
7486 out.push_back({e.fixed, pos});
7487 out.push_back({x2, pos});
7488 out.push_back({x2, pos + dir});
7489 out.push_back({e.fixed, pos + dir});
7500inline std::vector<point<
long long>> build_orthogonal_polygon(
int n,
7502 bool scale_up = n > 1000;
7504 long long side = std::max<
long long>(3, std::sqrt(n));
7506 side = std::clamp(
static_cast<
long long>(2 * std::sqrt(std::sqrt(n))),
7508 std::vector<point<
long long>> poly = {
7509 {0, 0}, {side, 0}, {side, side}, {0, side}};
7511 int target_ops = scale_up ? std::max(1,
static_cast<
int>(4 * side - 4) / 2)
7512 : std::max(1, (n - 4) / 2);
7515 target_ops = std::min(
7517 400 +
static_cast<
int>(4 * std::sqrt(
static_cast<
double>(side))));
7519 int failure_limit = std::min(target_ops * 8, 2000);
7521 std::vector<
int> last_used;
7522 int time_stamp = 0, consecutive_failures = 0;
7523 for (
int ops = 0; ops < target_ops;) {
7524 if (!scale_up
and poly.size() + 2 >
static_cast<size_t>(n))
7527 if (ortho_try_bump(poly, n, last_used, time_stamp, scale_up)) {
7529 consecutive_failures = 0;
7530 }
else if (++consecutive_failures >= failure_limit) {
7535 poly = ortho_simplify_collinear(std::move(poly));
7538 while (poly.size() >
static_cast<size_t>(n)
and
7539 ortho_remove_one_collinear(poly))
7541 long long upscale = std::max(4LL, ((n + 3) / 4 + side - 1) / side);
7542 for (point<
long long> &p : poly)
7543 p = {p.x() * upscale, p.y() * upscale};
7545 ortho_fill_corrugation(poly, n);
7547 ortho_fill_collinear(poly, n);
7549 ortho_fill_collinear(poly, n);
7565 bool strict =
false) {
7567 "geometry: random_simple_polygon: n must be at least 3");
7569 "geometry: random_simple_polygon: min_coord must be at most "
7571 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord <=
7572 std::numeric_limits<
long long>::max(),
7573 "geometry: random_simple_polygon: coordinate range too large");
7575 std::vector<point<
long long>> points =
7576 strict ? random_points_general_position(n, min_coord, max_coord)
7577 : detail::random_distinct_points_in_box(n, min_coord, max_coord);
7578 return random_simple_polygon_through_points(points);
7587 bool strict =
false) {
7589 "geometry: random_orthogonal_polygon: n must be at least 4");
7591 "geometry: random_orthogonal_polygon: min_coord must be at "
7593 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord + 1 <=
7594 std::numeric_limits<
long long>::max(),
7595 "geometry: random_orthogonal_polygon: coordinate range too "
7597 long long width = max_coord - min_coord + 1;
7599 "geometry: random_orthogonal_polygon: coordinate range too "
7602 long long min_side = std::max<
long long>(3, std::sqrt(n));
7604 min_side = std::max<
long long>(min_side, (n + 3) / 4);
7606 "geometry: random_orthogonal_polygon: coordinate range too "
7609 for (
int attempt = 0; attempt < 8; ++attempt) {
7610 std::vector<point<
long long>> poly =
7611 detail::build_orthogonal_polygon(n, strict);
7613 if (!strict
and poly.size() !=
static_cast<size_t>(n))
7616 detail::i128 min_x = poly[0].x(), max_x = poly[0].x();
7617 detail::i128 min_y = poly[0].y(), max_y = poly[0].y();
7618 for (point<
long long> p : poly) {
7619 min_x = std::min(min_x, detail::i128(p.x()));
7620 max_x = std::max(max_x, detail::i128(p.x()));
7621 min_y = std::min(min_y, detail::i128(p.y()));
7622 max_y = std::max(max_y, detail::i128(p.y()));
7624 if (max_x - min_x >= width
or max_y - min_y >= width)
7627 detail::place_inside_box(poly, min_coord, max_coord);
7628 detail::randomize_cyclic_shift(poly);
7632 throw tgen::detail::error(
7633 "geometry: random_orthogonal_polygon: generation failed");
7639
7640
7641
7642
7648using namespace tgen::detail;
7652inline int hash_string(
const std::string &s,
int base,
int mod) {
7655 h = (h * base + c -
'a' + 1) % mod;
7660inline int estimate_length(
int alphabet_size,
int mod) {
7662 double base_len = 2.5 * std::log(std::sqrt(mod));
7663 double scale = std::log(alphabet_size) / std::log(2.0);
7664 double adjusted = base_len / std::max(1.0, scale * 0.7);
7666 return static_cast<
int>(std::ceil(adjusted));
7671inline std::pair<std::string, std::string>
7672birthday_attack(
const std::vector<std::string> &alphabet,
int base,
int mod) {
7674 "birthday_attack: base must be in (0, mod)");
7675 std::map<uint64_t, std::vector<
int>> seen;
7676 int length = estimate_length(alphabet.size(), mod);
7679 std::vector<
int> seq(length);
7683 for (
int i = 0; i < length; ++i) {
7684 seq[i] = next<
int>(0, alphabet.size() - 1);
7685 s += alphabet[seq[i]];
7688 int h = hash_string(s, base, mod);
7690 auto it = seen.find(h);
7691 if (it != seen.end()
and it->second != seq) {
7694 for (
int x : it->second)
7709inline std::set<
long long> std_hash_multipliers() {
7710 std::set<
long long> multipliers = {85229};
7713 bool codeforces_gcc_case =
true;
7714 if (cpp.version_ != 0
and cpp.version_ != 17)
7715 codeforces_gcc_case =
false;
7716 if (compiler.kind_ != compiler_kind::unknown
and
7717 compiler.kind_ != compiler_kind::gcc)
7718 codeforces_gcc_case =
false;
7719 if (compiler.major_ > 7)
7720 codeforces_gcc_case =
false;
7722 if (codeforces_gcc_case)
7723 multipliers.insert(107897);
7734 std::string str =
"a";
7736 while (
static_cast<
int>(str.size()) < n) {
7737 int prev_size = str.size();
7739 for (
int j = 0; j < prev_size
and static_cast<
int>(str.size()) < n; ++j)
7752 for (
int i = 0; i < size; ++i) {
7753 a +=
'a' + math::detail::popcount(i) % 2;
7754 b +=
'a' + (
'b' - a[i]);
7763 int base,
int mod) {
7765 "hack: polynomial_hash: alphabet size must be greater "
7768 "hack: polynomial_hash: base must be in (0, mod)");
7770 std::vector<std::string> alphabet(alphabet_size);
7771 for (
int i = 0; i < alphabet_size; ++i)
7772 alphabet[i] = std::string(1,
'a' + i);
7773 std::iota(alphabet.begin(), alphabet.end(),
'a');
7774 return detail::birthday_attack(alphabet, base, mod);
7781inline std::pair<std::string, std::string>
7783 std::vector<
int> mods) {
7785 "hack: polynomial_hash: bases and mods must have the same "
7788 "hack: polynomial_hash: must have at least one (base, mod) "
7791 "hack: polynomial_hash: multi-hash hack only supported "
7792 "for up to 2 (base, mod) pairs");
7794 std::vector<std::string> alphabet(alphabet_size);
7795 for (
int i = 0; i < alphabet_size; ++i)
7796 alphabet[i] = std::string(1,
'a' + i);
7797 auto [S1, T1] = detail::birthday_attack(alphabet, bases[0], mods[0]);
7798 if (bases.size() == 1)
7800 return detail::birthday_attack({S1, T1}, bases[1], mods[1]);
7806 tgen_ensure(size > 0,
"hack: std_unordered: size must be positive");
7807 std::set<
long long> multipliers = detail::std_hash_multipliers();
7809 std::set<
long long>::iterator it = multipliers.begin();
7811 std::vector<
long long> list;
7812 while (
static_cast<
int>(list.size()) < size) {
7813 list.push_back(mult * (*it));
7815 if (it == multipliers.end()) {
7816 it = multipliers.begin();
7828 std::set<std::pair<
int,
int>> queries;
7831 int sq = std::sqrt(n);
7832 for (
int i = 0; i < sq; ++i) {
7833 for (
int j = i; j < sq; ++j) {
7834 if (i * sq < n
and j * sq < n)
7835 queries.emplace(i * sq, j * sq);
7840 for (
int i = 0; i < n; ++i)
7841 if (queries.size() < size_t(q)) {
7842 queries.emplace(0, i);
7843 queries.emplace(i, i);
7844 queries.emplace(i, n - 1);
7847 std::vector<std::pair<
int,
int>> pool(queries.begin(), queries.end());
7848 while (pool.size() < size_t(q)) {
7849 int l = next(0, n - 1);
7850 pool.emplace_back(l, next(l, n - 1));
7853 return choose(shuffled(pool), q);
7861 std::vector<std::string> list;
7862 int k = 0, left = size;
7864 int cur_size = std::min(left, k + 1);
7867 char right_char = cur_size == k + 1 ?
'b' :
'c';
7868 list.push_back(std::string(cur_size - 1,
'a') + right_char);
7872 return tgen::shuffled(list);
7884 "hack: non_strict_relaxation_dijkstra_bug: needs at least 3 vertices");
7886 egraph<
int>::value g(n, {},
true);
7888 g.add_edge(0, 1, 1);
7889 g.add_edge(0, 2, 1);
7890 for (
int i = 1; i + 2 < n; i += 2) {
7891 g.add_edge(i, i + 2, 1);
7893 g.add_edge(i, i + 3, 1);
7895 g.add_edge(i + 1, i + 2, 1);
7897 g.add_edge(i + 1, i + 3, 1);
7900 return g.shuffle_except({0});
7913 "hack: stale_heap_dijkstra_bug: needs at least 4 vertices");
7916 egraph<
int>::value g(n, {},
true);
7918 for (
int i = 1; i < mid; ++i)
7919 g.add_edge(0, i, i);
7920 for (
int i = 1; i < mid; ++i)
7921 g.add_edge(i, mid, 2 * (mid - i) - 1);
7922 for (
int i = mid + 1; i < n; ++i)
7923 g.add_edge(mid, i, 1);
7925 return g.shuffle_except({0});
7936 tgen_ensure(n >= 2,
"hack: spfa: n must be at least 2");
7937 tgen_ensure(n % 2 == 0,
"hack: spfa: n must be even");
7939 egraph<
int>::value g(n, {},
true);
7942 const int k = n / 2;
7943 for (
int i = 0; i + 1 < k; ++i)
7944 g.add_edge(i, i + 1, 1);
7945 for (
int i = 0; i + 1 < k; ++i)
7946 g.add_edge(k + i, k + i + 1, 0);
7947 for (
int i = 0; i < k; ++i)
7948 g.add_edge(i, k + i, 0);
7949 for (
int i = 0; i + 1 < k; ++i)
7950 g.add_edge(k + i, i + 1, 1);
7952 return g.shuffle_except({0});
7960 tgen_ensure(k >= 1,
"hack: dinitz_worst_case: k must be at least 1");
7961 tgen_ensure(l >= 1,
"hack: dinitz_worst_case: l must be at least 1");
7963 const int p1 = 2 * l - 1;
7964 const int p2 = 2 * l;
7965 const int q1 = 2 * l + 1;
7966 const int q2 = 2 * l + 2;
7967 const int n = 4 * l + 2 * k + 2;
7969 const int flow_cap = k * k * l;
7970 const int layer_cap = k * k;
7972 auto a = [&](
int i) {
return 2 * l + 3 + 2 * i; };
7973 auto b = [&](
int i) {
return 2 * l + 4 + 2 * i; };
7974 auto t = [&](
int i) {
return 4 * l + 2 * k + 1 - i; };
7976 egraph<
int>::value g(n, {},
true);
7979 for (
int i = 0; i + 1 < 2 * l - 1; ++i)
7980 g.add_edge(i, i + 1, flow_cap);
7981 for (
int i = 0; i + 1 < 2 * l - 1; ++i)
7982 g.add_edge(t(i + 1), t(i), flow_cap);
7984 for (
int i = 0; i < 2 * l - 1; i += 2) {
7985 g.add_edge(i, i % 4 == 0 ? p1 : p2, layer_cap);
7986 g.add_edge(i % 4 == 0 ? q1 : q2, t(i), layer_cap);
7989 for (
int i = 0; i < k; ++i) {
7990 g.add_edge(p1, a(i), flow_cap);
7991 g.add_edge(p2, b(i), flow_cap);
7992 g.add_edge(a(i), q2, flow_cap);
7993 g.add_edge(b(i), q1, flow_cap);
7996 for (
int i = 0; i < k; ++i)
7997 for (
int j = 0; j < k; ++j)
7998 g.add_edge(a(i), b(j), 1);
8007 static_assert(std::is_same_v<T,
int>
or std::is_same_v<T,
long long>,
8008 "hack: mt19937_xor_hash: T must be int or long long");
8010 constexpr std::size_t deg = 19937;
8012 std::bitset<deg + 1> a, b, c;
8013 b[deg] = c[deg] = 1;
8014 std::size_t l = 0, shift = 1;
8016 std::mt19937_64 rng64;
8017 for (std::size_t n = 0; n < deg * 2; ++n) {
8019 if constexpr (std::is_same_v<T,
int>)
8020 a[deg] = rng32() & 1;
8022 a[deg] = rng64() & 1;
8024 if ((c & a).count() % 2 == 0) {
8029 std::bitset<deg + 1> oc = c;
8040 std::vector<
bool> mask(deg + 1);
8041 for (std::size_t i = 0; i <= deg; ++i)
8053 {-0.9846, -1.53251}, {0.49946, 1.19525}, {0.79916, 0.98291},
8054 {4.02136, -1.57843}, {3.92734, -2.37856}, {3.88558, -2.37188},
8062inline std::vector<
int> segment_tree_beats_worst_case_block(
int k) {
8064 "hack: segment_tree_beats_worst_case: k must be at least 1");
8066 std::vector<
int> a(k + 1), b(k + 1);
8067 std::vector<std::vector<
int>> vf(k + 1), vg(k + 1);
8073 for (
int i = 2; i <= k; ++i) {
8074 b[i] = b[i - 1] + a[i - 1];
8075 a[i] = b[i] + a[i - 1];
8076 for (
int x : vf[i - 1])
8077 vf[i].push_back(x + a[i] + b[i]);
8078 vf[i].push_back(a[i]);
8079 for (
int x : vg[i - 1])
8080 vf[i].push_back(x + a[i]);
8083 for (
int x : vg[i - 1])
8094segment_tree_beats_append_round(std::vector<std::vector<
int>> &updates,
8095 int block_len,
int an,
int bn,
int n,
8097 const int off = (round * an) % block_len;
8098 const int add_off = (off + block_len - bn) % block_len;
8099 for (
int k = 0; k < block_len; ++k) {
8100 const int s = k * block_len * block_len;
8101 const int sub_end = off + an;
8102 if (sub_end <= block_len)
8103 updates.push_back({1, s + off, s + sub_end, bn});
8105 updates.push_back({1, s + off, s + block_len, bn});
8106 updates.push_back({1, s, s + (sub_end - block_len), bn});
8108 const int add_end = add_off + bn;
8109 if (add_end <= block_len)
8110 updates.push_back({0, s + add_off, s + add_end, an});
8112 updates.push_back({0, s + add_off, s + block_len, an});
8113 updates.push_back({0, s, s + (add_end - block_len), an});
8116 updates.push_back({2, 0, n, an});
8117 for (
int k = 0; k < block_len; ++k) {
8118 const int s = k * block_len * block_len;
8119 updates.push_back({3, s + (off + an - 1) % block_len, 0});
8127inline std::pair<std::vector<
int>, std::vector<std::vector<
int>>>
8128segment_tree_beats_worst_case(
int k,
int q) {
8130 "hack: segment_tree_beats_worst_case: k must be at least 1");
8131 tgen_ensure(k <= 7,
"hack: segment_tree_beats_worst_case: k too large");
8133 "hack: segment_tree_beats_worst_case: q must be positive");
8135 const auto &fib = math::fibonacci();
8136 const int block_len = fib[k * 2 + 1];
8137 const int an = fib[k * 2];
8138 const int bn = fib[k * 2 - 1];
8140 const int len = block_len;
8141 const int total = len * len * len;
8143 std::vector<
int> block = detail::segment_tree_beats_worst_case_block(k);
8144 std::vector<
int> arr(total, 0);
8145 for (
int x = 0; x < block_len; ++x) {
8146 const int s = x * len * len;
8147 for (
int i = 0; i < block_len; ++i)
8148 arr[s + i] = block[i];
8151 std::vector<std::vector<
int>> updates;
8153 const int n = total;
8154 for (
int round = 0; updates.size() <
static_cast<std::size_t>(q); ++round) {
8155 detail::segment_tree_beats_append_round(updates, block_len, an, bn, n,
8157 if (updates.size() >
static_cast<std::size_t>(q))
8160 return {arr, updates};
8166
8167
8168
8169
8178 "misc: parenthesis: size must be a positive even number");
8182 int open = 0, close = 0;
8184 for (
int i = 0; i < size; ++i) {
8190 if (open == close) {
8196 long long a = k - open, b = k - close, h = open - close;
8201 long long num = a * (h + 2);
8202 long long den = (a + b) * (h + 1);
8204 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.