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 bool has_self_loops =
false) {
6216 tgen_ensure(n > 0,
"wgraph: number of vertices must be positive");
6217 tgen_ensure(p >= 0
and p <= 1,
"wgraph: probability must be in [0, 1]");
6219 long long max_edges =
6220 detail::max_graph_edges(n, is_directed, has_self_loops);
6226 for (
long long i = 0; i < max_edges; ++i)
6227 if (next<
double>(0.0, 1.0) < p)
6231 "wgraph: too many edges to generate");
6232 return wgraph(n,
static_cast<
int>(m), is_directed, has_self_loops)
6242 std::optional<
value> try_gen_by_edge_index()
const {
6243 if (!edges_.empty())
6244 return std::nullopt;
6246 long long max_edges =
6247 detail::max_graph_edges(n_, is_directed_, has_self_loops_);
6249 throw detail::error(
"wgraph: not enough edges to generate");
6250 if (max_edges <= 0
or 2LL * m_ <= max_edges)
6251 return std::nullopt;
6253 std::vector<std::pair<
int,
int>> edges;
6255 for (
long long idx :
6256 distinct_range<
long long>(0, max_edges - 1).gen_list(m_).to_std())
6257 edges.push_back(detail::decode_graph_edge_index(
6258 n_, idx, is_directed_, has_self_loops_));
6260 return value(n_, edges, is_directed_);
6266 value gen_remaining_edges(std::vector<std::pair<
int,
int>> edges)
const {
6267 detail::tgen_ensure_against_bug(
static_cast<
int>(edges.size()) <= m_,
6268 "wgraph: too many edges were added");
6270 if (
static_cast<
int>(edges.size()) == m_)
6271 return value(n_, edges, is_directed_);
6275 std::unordered_set<uint64_t> seen;
6276 seen.reserve(m_ * 2);
6277 for (
auto [u, v] : edges) {
6278 if (!is_directed_
and u > v)
6280 seen.insert(is_directed_ ? detail::directed_edge_key(u, v)
6281 : detail::undirected_edge_key(u, v));
6284 while (
static_cast<
int>(edges.size()) < m_) {
6285 std::pair<
int,
int> edge;
6286 if (!detail::try_generate_distinct(seen, [&] {
6287 edge = detail::get_random_graph_edge(n_, is_directed_,
6289 if (!is_directed_
and edge.first > edge.second)
6290 std::swap(edge.first, edge.second);
6291 return is_directed_ ? detail::directed_edge_key(edge.first,
6293 : detail::undirected_edge_key(
6294 edge.first, edge.second);
6296 throw detail::error(
"wgraph: not enough edges to generate");
6297 edges.emplace_back(edge);
6300 return value(n_, edges, is_directed_);
6306template <
typename VWeight,
typename EWeight>
6308 const typename wgraph<VWeight, EWeight>::value &g)
6309 : n_(g.n()),
adj_(
g.
n()), add_1_(
false), print_n_(
false),
dsu_(
g.
n()) {
6310 tgen_ensure(g.n() > 0,
"wtree: value: graph must have at least one vertex");
6312 "wtree: value: graph must be undirected to form a tree");
6314 if (g.vertex_weights().has_value())
6315 vertex_weights_ = *g.vertex_weights();
6316 if (g.edge_weights().has_value())
6317 edge_weights_ = std::vector<EWeight>();
6322 std::vector<
int> order(g.m());
6323 std::iota(order.begin(), order.end(), 0);
6324 tgen::shuffle(order.begin(), order.end());
6326 std::vector<std::pair<
int,
int>> tree_edges;
6327 tree_edges.reserve(n_ - 1);
6329 for (
int i : order) {
6330 auto [u, v] = g.edges()[i];
6331 if (!dsu_.unite(u, v))
6336 tree_edges.emplace_back(u, v);
6339 if (edge_weights_.has_value())
6340 edge_weights_->push_back((*g.edge_weights())[i]);
6341 if (
static_cast<
int>(tree_edges.size()) == n_ - 1)
6345 tgen_ensure(
static_cast<
int>(tree_edges.size()) == n_ - 1,
6346 "wtree: value: graph must be connected to form a tree");
6348 edges_ = std::move(tree_edges);
6352
6353
6365
6366
6370inline graph::
value K(
int n) {
return graph(n, n * (n - 1) / 2).gen(); }
6377 graph g(n, n - 1, is_directed);
6378 for (
int i = 0; i + 1 < n; ++i)
6379 g.add_edge(i, i + 1);
6388 tgen_ensure(n >= 3,
"graph: cycle size must be at least 3");
6390 graph g(n, n, is_directed);
6391 for (
int i = 0; i < n; ++i)
6392 g.add_edge(i, (i + 1) % n);
6401 graph g(n1 + n2,
static_cast<
long long>(n1) * n2);
6402 for (
int i = 0; i < n1; ++i)
6403 for (
int j = 0; j < n2; ++j)
6404 g.add_edge(i, n1 + j);
6414
6415
6416
6417
6423 static_assert(std::is_arithmetic_v<T>,
6424 "point requires an arithmetic coordinate type");
6436 point(T x = 0, T y = 0) : x_(x), y_(y) {}
6439 T
x()
const {
return x_; }
6442 T
y()
const {
return y_; }
6446 static bool coord_eq(T a, T b) {
6447 if constexpr (std::is_integral_v<T>)
6449 constexpr T eps = T(1e-9);
6451 return d >= -eps
and d <= eps;
6456 if (!coord_eq(x_, p
.x()))
6463 return coord_eq(x_, p
.x())
and coord_eq(y_, p
.y());
6481 if constexpr (std::is_floating_point_v<T>)
6483 return product_t(x_) * p
.x() + product_t(y_) * p
.y();
6488 if constexpr (std::is_floating_point_v<T>)
6490 return product_t(x_) * p
.y() - product_t(y_) * p
.x();
6494 friend std::ostream &operator<<(std::ostream &out,
const point &p) {
6495 return out << p
.x() <<
' ' << p
.y();
6504 long long max_coord) {
6506 "geometry: random_points_general_position: n must be positive");
6508 "geometry: random_points_general_position: min_coord must be "
6509 "at most max_coord");
6511 static_cast<detail::i128>(max_coord) - min_coord <=
6512 std::numeric_limits<
long long>::max(),
6513 "geometry: random_points_general_position: coordinate range too large");
6514 uint64_t width = max_coord - min_coord;
6519 "geometry: random_points_general_position: coordinate range "
6528 std::vector<uint64_t> x_range(p - 1);
6529 std::iota(x_range.begin(), x_range.end(), 1);
6530 shuffle(x_range.begin(), x_range.end());
6531 std::vector<detail::i128> bx(n), by(n);
6532 for (
int i = 0; i < n; ++i) {
6533 uint64_t x = x_range[i];
6535 by[i] = math::modular_inverse(x, p);
6543 const int num_shears = 8;
6544 std::vector<detail::i128> lin_x = bx, lin_y = by;
6546 for (
int it = 0; it < num_shears; ++it) {
6547 bool vertical_shear = next(2) == 0;
6548 int shear_r = pick({-2, -1, 1, 2});
6550 for (
int i = 0; i < n; ++i) {
6552 lin_x[i] = (lin_x[i] + shear_r * lin_y[i]) % p;
6554 lin_y[i] = (lin_y[i] + shear_r * lin_x[i]) % p;
6563 detail::i128 min_x = lin_x[0], max_x = lin_x[0], min_y = lin_y[0],
6565 for (
int i = 1; i < n; ++i) {
6566 min_x = std::min(min_x, lin_x[i]);
6567 max_x = std::max(max_x, lin_x[i]);
6568 min_y = std::min(min_y, lin_y[i]);
6569 max_y = std::max(max_y, lin_y[i]);
6573 min_coord - min_x + next<
long long>(0, width - (max_x - min_x));
6575 min_coord - min_y + next<
long long>(0, width - (max_y - min_y));
6577 std::vector<point<
long long>> pts;
6578 for (
int i = 0; i < n; ++i)
6579 pts.emplace_back(lin_x[i] + x_shift, lin_y[i] + y_shift);
6585using i128 = tgen::detail::i128;
6589inline i128 ccw(
const point<
long long> &a,
const point<
long long> &b,
6590 const point<
long long> &p) {
6591 return (
static_cast<i128>(b.x()) - a.x()) *
6592 (
static_cast<i128>(p.y()) - a.y()) -
6593 (
static_cast<i128>(b.y()) - a.y()) *
6594 (
static_cast<i128>(p.x()) - a.x());
6598inline i128 proj_on_ab(
const point<
long long> &P,
const point<
long long> &A,
6599 const point<
long long> &B) {
6600 return (P - A) * (B - A);
6606inline void conquer(std::vector<point<
long long>> &points,
int left,
6608 if (right - left <= 3)
6611 point<
long long> A = points[left], B = points[right - 1];
6614 bool all_collinear =
true;
6615 for (
int k = left + 1; k < right - 1; ++k) {
6616 if (ccw(A, B, points[k]) != 0) {
6617 all_collinear =
false;
6621 if (all_collinear) {
6622 std::sort(points.begin() + left, points.begin() + right,
6623 [&](
const point<
long long> &P,
const point<
long long> &Q) {
6624 return proj_on_ab(P, A, B) < proj_on_ab(Q, A, B);
6630 std::vector<
int> candidates;
6631 for (
int k = left + 1; k < right - 1; ++k) {
6632 if (ccw(A, B, points[k]) != 0)
6633 candidates.push_back(k);
6635 int ci = candidates[next(0,
static_cast<
int>(candidates.size()) - 1)];
6636 point<
long long> C = points[ci];
6638 uint64_t wa = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6639 uint64_t wb = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6640 bool a_on_positive = ccw(C, A, B) < 0;
6644 i128 proj_sum = proj_on_ab(A, A, B) + proj_on_ab(B, A, B);
6645 auto is_positive = [&](
const point<
long long> &P) ->
bool {
6646 i128 s = wa * ccw(C, A, P) + wb * ccw(C, B, P);
6651 return 2 * proj_on_ab(P, A, B) > proj_sum;
6656 if (ci != right - 2)
6657 std::swap(points[ci], points[right - 2]);
6662 if (is_positive(points[i]) == a_on_positive)
6664 else if (is_positive(points[j]) != a_on_positive)
6667 std::swap(points[i], points[j]);
6678 if (i == j
and is_positive(points[i]) == a_on_positive)
6680 std::swap(points[p], points[right - 2]);
6683 conquer(points, left, p + 1);
6685 conquer(points, p, right);
6692inline std::vector<
long long>
6693sample_sorted_distinct_in_range(
int k,
long long left,
long long right) {
6694 long long universe = right - left + 1;
6695 std::vector<
long long> res;
6700 constexpr long long pool_threshold = 8'000'000;
6701 constexpr long long pool_always_below = 500'000;
6703 if (universe <= pool_threshold
and
6704 (universe <= pool_always_below
or k >= universe / 4)) {
6705 size_t u = universe;
6707 std::vector<
long long> pool(u);
6708 std::iota(pool.begin(), pool.end(), left);
6709 size_t m = ks <= u / 2 ? ks : u - ks;
6710 for (size_t i = 0; i < m; ++i) {
6711 size_t j = next<size_t>(i, u - 1);
6712 std::swap(pool[i], pool[j]);
6715 res.assign(pool.begin(), pool.begin() + ks);
6716 std::sort(res.begin(), res.end());
6718 std::vector<
char> excluded(u, 0);
6719 for (size_t i = 0; i < m; ++i)
6720 excluded[pool[i] - left] = 1;
6721 for (
long long v = left; v <= right; ++v)
6722 if (!excluded[v - left])
6726 std::unordered_map<
long long,
long long> virtual_list;
6727 virtual_list.reserve(k * 2);
6728 for (
long long i = 0; i < k; ++i) {
6729 long long j = next<
long long>(i, universe - 1);
6730 long long vi = virtual_list.count(i) ? virtual_list[i] : i;
6731 long long vj = virtual_list.count(j) ? virtual_list[j] : j;
6732 virtual_list[j] = vi;
6733 virtual_list[i] = vj;
6734 res.push_back(virtual_list[i] + left);
6736 std::sort(res.begin(), res.end());
6743inline std::vector<
long long>
6744valtr_edge_components(
const std::vector<
long long> &sorted_coords) {
6745 int n = sorted_coords.size();
6746 std::vector<
long long> left, right;
6747 left.reserve(n / 2);
6748 right.reserve(n / 2);
6749 for (
int i = 1; i + 1 < n; ++i) {
6751 left.push_back(sorted_coords[i]);
6753 right.push_back(sorted_coords[i]);
6755 long long lo = sorted_coords.front(), hi = sorted_coords.back();
6756 std::vector<
long long> seq;
6759 for (
long long v : left)
6762 for (
auto it = right.rbegin(); it != right.rend(); ++it)
6765 std::vector<
long long> comps(n);
6766 for (
int i = 0; i < n; ++i)
6767 comps[i] = seq[i + 1] - seq[i];
6773inline std::vector<point<
long long>>
6774simplify_strict_boundary(std::vector<point<
long long>> points) {
6775 int n = points.size();
6779 std::vector<point<
long long>> strict_points;
6780 strict_points.reserve(n);
6781 for (
int i = 0; i < n; ++i) {
6782 if (ccw(points[(i + n - 1) % n], points[i], points[(i + 1) % n]) != 0)
6783 strict_points.push_back(points[i]);
6785 return strict_points;
6790inline std::vector<point<
long long>>
6791subsample_boundary(
const std::vector<point<
long long>> &points,
int k) {
6792 int n = points.size();
6796 std::vector<point<
long long>> sampled_points;
6797 sampled_points.reserve(k);
6798 for (
int i = 0; i < k; ++i)
6799 sampled_points.push_back(points[(
static_cast<i128>(i) * n) / k]);
6800 return sampled_points;
6805inline void place_inside_box(std::vector<point<
long long>> &points,
6806 long long min_coord,
long long max_coord) {
6807 long long width = max_coord - min_coord + 1;
6809 i128 min_x = points[0].x(), max_x = points[0].x();
6810 i128 min_y = points[0].y(), max_y = points[0].y();
6811 for (
const point<
long long> &p : points) {
6812 min_x = std::min(min_x,
static_cast<i128>(p.x()));
6813 max_x = std::max(max_x,
static_cast<i128>(p.x()));
6814 min_y = std::min(min_y,
static_cast<i128>(p.y()));
6815 max_y = std::max(max_y,
static_cast<i128>(p.y()));
6818 i128 span_x = max_x - min_x;
6819 i128 span_y = max_y - min_y;
6823 next<
long long>(0, width - 1 -
static_cast<
long long>(span_x));
6826 next<
long long>(0, width - 1 -
static_cast<
long long>(span_y));
6828 for (point<
long long> &p : points)
6829 p = point<
long long>(p.x() + shift_x, p.y() + shift_y);
6834inline void randomize_cyclic_shift(std::vector<point<
long long>> &points) {
6835 int rot = next(points.size());
6837 std::rotate(points.begin(), points.begin() + rot, points.end());
6842inline std::vector<point<
long long>>
6843valtr_vertices(
int m,
const std::vector<
long long> &x_comp,
6844 std::vector<
long long> y_comp) {
6845 shuffle(y_comp.begin(), y_comp.end());
6847 std::vector<point<
long long>> edges(m);
6849 auto upper = [](
const point<
long long> &p) {
6850 return p.y() > 0
or (p.y() == 0
and p.x() > 0);
6852 for (
int i = 0; i < m; ++i)
6853 edges[i] =
point<
long long>(x_comp[i], y_comp[i]);
6855 std::sort(edges.begin(), edges.end(),
6856 [&upper](
const point<
long long> &a,
const point<
long long> &b) {
6857 bool au = upper(a), bu = upper(b);
6863 return (a * a) < (b * b);
6867 i128 cur_x = 0, cur_y = 0;
6868 std::vector<i128> px(m), py(m);
6869 for (
int i = 0; i < m; ++i) {
6872 cur_x += edges[i].x();
6873 cur_y += edges[i].y();
6875 tgen::detail::tgen_ensure_against_bug(
6876 cur_x == 0
and cur_y == 0,
6877 "geometry: random_convex_polygon: walk did not close");
6879 i128 min_x = px[0], min_y = py[0];
6880 for (
int i = 1; i < m; ++i) {
6881 min_x = std::min(min_x, px[i]);
6882 min_y = std::min(min_y, py[i]);
6886 std::vector<point<
long long>> points;
6888 for (
int i = 0; i < m; ++i)
6889 points.emplace_back(px[i] - min_x, py[i] - min_y);
6902 bool strict =
false) {
6904 "geometry: random_convex_polygon: n must be at least 3");
6906 "geometry: random_convex_polygon: min_coord must be at most "
6908 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord + 1 <=
6909 std::numeric_limits<
long long>::max(),
6910 "geometry: random_convex_polygon: coordinate range too large");
6911 long long width = max_coord - min_coord + 1;
6914 "geometry: random_convex_polygon: coordinate range too small for n");
6922 int extra = width <= n ? 0
6923 : std::min<
long long>(std::max(100, n / 1000),
6925 num_coords = n + extra;
6930 const int max_attempts = strict ? 32 : 1;
6931 for (
int i = 0; i < max_attempts; ++i) {
6933 std::vector<
long long> x_sorted =
6934 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6935 std::vector<
long long> y_sorted =
6936 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6937 std::vector<
long long> x_comp = detail::valtr_edge_components(x_sorted);
6938 std::vector<
long long> y_comp = detail::valtr_edge_components(y_sorted);
6940 std::vector<point<
long long>> points =
6941 detail::valtr_vertices(num_coords, x_comp, std::move(y_comp));
6944 std::vector<point<
long long>> simplified =
6945 detail::simplify_strict_boundary(std::move(points));
6947 if (
static_cast<
int>(simplified.size()) < n)
6950 points = detail::subsample_boundary(simplified, n);
6953 detail::place_inside_box(points, min_coord, max_coord);
6954 detail::randomize_cyclic_shift(points);
6959 throw tgen::detail::error(
6960 "geometry: random_convex_polygon: generation failed: coordinate "
6961 "range too small for n");
6969 const std::vector<point<
long long>> &points) {
6970 int n = points.size();
6972 "geometry: random_simple_polygon_through_points: need at "
6976 std::set<point<
long long>>(points.begin(), points.end()).size()) ==
6978 "geometry: random_simple_polygon_through_points: points must "
6981 int idx_a = 0, idx_b = 0;
6982 for (
int i = 1; i < n; ++i) {
6983 if (points[i] < points[idx_a])
6985 if (points[idx_b] < points[i])
6988 point<
long long> A = points[idx_a], B = points[idx_b];
6990 bool all_collinear =
true;
6991 for (
int i = 0; i < n; ++i) {
6992 if (i == idx_a
or i == idx_b)
6994 if (detail::ccw(A, B, points[i]) != 0) {
6995 all_collinear =
false;
7000 "geometry: random_simple_polygon_through_points: all points "
7001 "are collinear; no simple polygon exists");
7006 int negative_count = 0;
7007 for (
int i = 0; i < n; ++i) {
7008 if (i == idx_a
or i == idx_b)
7010 if (detail::ccw(A, B, points[i]) < 0)
7014 std::vector<point<
long long>> chain;
7017 for (
int i = 0; i < n; ++i) {
7018 if (i == idx_a
or i == idx_b)
7020 detail::i128 side = detail::ccw(A, B, points[i]);
7021 if (side < 0
or (side == 0
and negative_count == 0)) {
7022 chain.push_back(points[i]);
7027 for (
int i = 0; i < n; ++i) {
7028 if (i == idx_a
or i == idx_b)
7030 detail::i128 side = detail::ccw(A, B, points[i]);
7031 if (side > 0
or (side == 0
and negative_count != 0))
7032 chain.push_back(points[i]);
7036 int n1 = 2 + left_count;
7038 detail::conquer(chain, 0, n1);
7040 detail::conquer(chain, n1 - 1, chain.size());
7044 std::vector<point<
long long>> poly;
7045 poly.insert(poly.end(), chain.begin() + 1, chain.begin() + n1);
7046 poly.insert(poly.end(), chain.begin() + n1, chain.end());
7054inline std::vector<point<
long long>>
7055random_distinct_points_in_box(
int n,
long long min_coord,
long long max_coord) {
7056 long long width = max_coord - min_coord;
7057 i128 side_128 = width + 1;
7058 i128 universe = side_128 * side_128;
7059 tgen_ensure(universe <= std::numeric_limits<
long long>::max(),
7060 "geometry: random_simple_polygon: coordinate range too large");
7061 long long side = side_128;
7063 "geometry: random_simple_polygon: coordinate range too small "
7064 "for n distinct points");
7067 auto decode = [&](
long long key) ->
point<
long long> {
7068 return point<
long long>(min_coord + key / side, min_coord + key % side);
7074 std::vector<
long long> keys =
7075 distinct_range<
long long>(0, universe - 1).gen_list(n).to_std();
7077 std::vector<point<
long long>> points;
7079 for (
long long key : keys)
7080 points.push_back(decode(key));
7083 for (
int i = 2; i < n; ++i) {
7084 if (ccw(points[0], points[1], points[i]) != 0)
7092struct ortho_poly_edge {
7102inline bool ortho_axis_collinear(
const point<
long long> &a,
7103 const point<
long long> &b,
7104 const point<
long long> &c) {
7105 return (a.x() == b.x()
and b.x() == c.x())
or
7106 (a.y() == b.y()
and b.y() == c.y());
7111inline ortho_poly_edge
7112ortho_analyze_edge(
const std::vector<point<
long long>> &poly,
int i) {
7113 int m = poly.size();
7114 point<
long long> a = poly[i], b = poly[(i + 1) % m];
7115 ortho_poly_edge e{};
7116 if (a.y() == b.y()) {
7119 e.lo = std::min(a.x(), b.x());
7120 e.hi = std::max(a.x(), b.x());
7122 e.out_y = a.x() < b.x() ? -1 : 1;
7125 e.lo = std::min(a.y(), b.y());
7126 e.hi = std::max(a.y(), b.y());
7127 e.out_x = a.y() < b.y() ? 1 : -1;
7129 e.len = e.hi - e.lo;
7136inline bool ortho_open_seg_cross(
const point<
long long> &a,
7137 const point<
long long> &b,
7138 const point<
long long> &c,
7139 const point<
long long> &d) {
7140 if (a.y() == b.y()
and c.y() == d.y()) {
7143 long long lo1 = std::min(a.x(), b.x()), hi1 = std::max(a.x(), b.x());
7144 long long lo2 = std::min(c.x(), d.x()), hi2 = std::max(c.x(), d.x());
7145 return lo1 < hi2
and lo2 < hi1;
7147 if (a.x() == b.x()
and c.x() == d.x()) {
7150 long long lo1 = std::min(a.y(), b.y()), hi1 = std::max(a.y(), b.y());
7151 long long lo2 = std::min(c.y(), d.y()), hi2 = std::max(c.y(), d.y());
7152 return lo1 < hi2
and lo2 < hi1;
7154 if (a.y() == b.y()
and c.x() == d.x()) {
7155 long long hx = a.y(), vx = c.x();
7156 long long hlo = std::min(a.x(), b.x()), hhi = std::max(a.x(), b.x());
7157 long long vlo = std::min(c.y(), d.y()), vhi = std::max(c.y(), d.y());
7158 return hlo < vx
and vx < hhi
and vlo < hx
and hx < vhi;
7160 if (a.x() == b.x()
and c.y() == d.y()) {
7161 long long vx = a.x(), hy = c.y();
7162 long long vlo = std::min(a.y(), b.y()), vhi = std::max(a.y(), b.y());
7163 long long hlo = std::min(c.x(), d.x()), hhi = std::max(c.x(), d.x());
7164 return vlo < hy
and hy < vhi
and hlo < vx
and vx < hhi;
7171inline bool ortho_point_inside(
const std::vector<point<
long long>> &poly,
7172 point<
long long> p) {
7173 int m = poly.size();
7174 bool inside =
false;
7175 for (
int i = 0, j = m - 1; i < m; j = i++) {
7176 point<
long long> a = poly[i], b = poly[j];
7177 if ((a.y() > p.y()) != (b.y() > p.y())) {
7178 i128 x_cross = i128(b.x() - a.x()) * (p.y() - a.y()) -
7179 i128(p.x() - a.x()) * (b.y() - a.y());
7180 if ((a.y() < b.y()) ? x_cross > 0 : x_cross < 0)
7189inline bool ortho_point_strictly_interior(
point<
long long> p,
7191 point<
long long> b) {
7192 if (a.y() == b.y()) {
7195 long long lo = std::min(a.x(), b.x()), hi = std::max(a.x(), b.x());
7196 return lo < p.x()
and p.x() < hi;
7198 if (a.x() == b.x()) {
7201 long long lo = std::min(a.y(), b.y()), hi = std::max(a.y(), b.y());
7202 return lo < p.y()
and p.y() < hi;
7209inline bool ortho_point_on_segment(
point<
long long> p,
point<
long long> a,
7210 point<
long long> b) {
7211 return p == a
or p == b
or ortho_point_strictly_interior(p, a, b);
7219inline bool ortho_bump_valid(
const std::vector<point<
long long>> &poly,
7221 const std::vector<point<
long long>> &add,
7222 int edge_i,
bool inward) {
7223 int m = poly.size();
7225 for (point<
long long> v : add)
7226 for (point<
long long> q : poly)
7232 for (point<
long long> v : add) {
7233 for (
int j = 0; j < m; ++j) {
7234 point<
long long> c = poly[j], d = poly[(j + 1) % m];
7236 if (ortho_point_on_segment(v, c, d)
and
7237 !ortho_point_on_segment(v, A, B))
7239 }
else if (ortho_point_strictly_interior(v, c, d)) {
7245 auto seg_ok = [&](
point<
long long> s0,
point<
long long> s1) {
7246 for (
int j = 0; j < m; ++j) {
7249 point<
long long> c = poly[j], d = poly[(j + 1) % m];
7250 if (ortho_open_seg_cross(s0, s1, c, d))
7253 for (
int k = 0; k < m; ++k) {
7254 point<
long long> q = poly[k];
7255 if (q == s0
or q == s1
or q == A
or q == B)
7257 if (ortho_point_strictly_interior(q, s0, s1))
7263 point<
long long> prev = A;
7264 for (point<
long long> v : add) {
7265 if (!seg_ok(prev, v))
7269 if (!seg_ok(prev, B))
7273 for (point<
long long> v : add)
7274 if (!ortho_point_inside(poly, v))
7284inline bool ortho_bump_edge(std::vector<point<
long long>> &poly,
int edge_i,
7285 const ortho_poly_edge &e,
long long lo,
7286 long long hi,
long long depth,
bool inward,
7287 size_t max_vertices) {
7288 int m = poly.size();
7289 point<
long long> A = poly[edge_i], B = poly[(edge_i + 1) % m];
7291 int step_x = inward ? -e.out_x : e.out_x;
7292 int step_y = inward ? -e.out_y : e.out_y;
7294 std::vector<point<
long long>> add;
7296 long long y = e.fixed, y2 = y + step_y * depth;
7297 if (A.x() < B.x()) {
7299 add.emplace_back(lo, y);
7300 add.emplace_back(lo, y2);
7301 add.emplace_back(hi, y2);
7303 add.emplace_back(hi, y);
7306 add.emplace_back(hi, y);
7307 add.emplace_back(hi, y2);
7308 add.emplace_back(lo, y2);
7310 add.emplace_back(lo, y);
7313 long long x = e.fixed, x2 = x + step_x * depth;
7314 if (A.y() < B.y()) {
7316 add.emplace_back(x, lo);
7317 add.emplace_back(x2, lo);
7318 add.emplace_back(x2, hi);
7320 add.emplace_back(x, hi);
7323 add.emplace_back(x, hi);
7324 add.emplace_back(x2, hi);
7325 add.emplace_back(x2, lo);
7327 add.emplace_back(x, lo);
7330 if (poly.size() > max_vertices
or add.size() > max_vertices - poly.size())
7332 if (!ortho_bump_valid(poly, A, B, add, edge_i, inward))
7335 poly.insert(poly.begin() + edge_i + 1, add.begin(), add.end());
7342inline int ortho_pick_poly_edge(
const std::vector<point<
long long>> &poly,
7343 std::vector<
int> &last_used,
int &time_stamp) {
7344 int m = poly.size();
7345 if (last_used.size() !=
static_cast<size_t>(m)) {
7346 last_used.assign(m, 0);
7349 std::vector<
long long> weights(m);
7350 long long total = 0;
7351 for (
int i = 0; i < m; ++i) {
7352 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7353 weights[i] = e.len * (4 + std::min(time_stamp - last_used[i], 8));
7354 total += weights[i];
7356 long long pick = next<
long long>(0, total - 1);
7357 for (
int i = 0; i < m; ++i) {
7360 last_used[i] = ++time_stamp;
7364 last_used[m - 1] = ++time_stamp;
7371ortho_try_bump(std::vector<point<
long long>> &poly,
int n,
7372 std::vector<
int> &last_used,
int &time_stamp,
7373 bool outward_only =
false,
7374 size_t max_vertices = std::numeric_limits<size_t>::max()) {
7375 if (poly.size() < 3)
7378 int ei = ortho_pick_poly_edge(poly, last_used, time_stamp);
7379 ortho_poly_edge e = ortho_analyze_edge(poly, ei);
7386 long long span = next<
long long>(2, e.len);
7387 long long lo = next<
long long>(e.lo, e.hi - span);
7391 long long max_depth =
7392 std::clamp<
long long>(std::sqrt(n) / 2 + 2, 2LL, 12LL);
7394 next(10) == 0 ? next<
long long>(std::max(2LL, max_depth / 2), max_depth)
7395 : next<
long long>(1, std::max(2LL, max_depth / 3));
7397 bool inward = !outward_only
and next(4) == 0;
7398 return ortho_bump_edge(poly, ei, e, lo, lo + span, depth, inward,
7404inline std::vector<point<
long long>>
7405ortho_simplify_collinear(std::vector<point<
long long>> poly) {
7406 int n = poly.size();
7409 std::vector<point<
long long>> out;
7411 for (
int i = 0; i < n; ++i) {
7412 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7414 out.push_back(poly[i]);
7416 return out.size() >= 3 ? out : poly;
7421inline bool ortho_remove_one_collinear(std::vector<point<
long long>> &poly) {
7422 int n = poly.size();
7425 for (
int i = 0; i < n; ++i) {
7426 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7429 poly.erase(poly.begin() + i);
7438inline void ortho_fill_collinear(std::vector<point<
long long>> &poly,
7440 int need = target - poly.size();
7444 std::vector<point<
long long>> out;
7445 int m = poly.size();
7446 out.reserve(poly.size() + need);
7448 for (
int i = 0; i < m; ++i) {
7449 point<
long long> a = poly[i], b = poly[(i + 1) % m];
7454 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7455 long long cap = e.len - 1;
7460 long long take = std::min<
long long>(need, cap);
7461 bool forward = e.horiz ? a.x() < b.x() : a.y() < b.y();
7462 for (
long long k = 0; k < take; ++k) {
7463 long long off = (k + 1) * (cap + 1) / (take + 1);
7464 long long coord = forward ? e.lo + off : e.hi - off;
7466 out.push_back({coord, e.fixed});
7468 out.push_back({e.fixed, coord});
7482inline void ortho_fill_corrugation(std::vector<point<
long long>> &poly,
7484 size_t n_sz = poly.size();
7488 size_t extra_left = target - n_sz;
7490 std::vector<point<
long long>> out;
7491 out.reserve(target);
7492 int n = poly.size();
7494 for (
int i = 0; i < n; ++i) {
7495 point<
long long> a = poly[i], b = poly[(i + 1) % n];
7501 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7505 long long dir = (e.horiz ? a.x() < b.x() : a.y() < b.y()) ? 1 : -1;
7506 long long start = e.horiz ? a.x() : a.y();
7507 long long end = e.horiz ? b.x() : b.y();
7509 for (
long long pos = start + 2 * dir;
7510 extra_left >= 4
and (pos - end) * dir <= -3; pos += 2 * dir) {
7512 long long y2 = e.fixed + e.out_y;
7513 out.push_back({pos, e.fixed});
7514 out.push_back({pos, y2});
7515 out.push_back({pos + dir, y2});
7516 out.push_back({pos + dir, e.fixed});
7518 long long x2 = e.fixed + e.out_x;
7519 out.push_back({e.fixed, pos});
7520 out.push_back({x2, pos});
7521 out.push_back({x2, pos + dir});
7522 out.push_back({e.fixed, pos + dir});
7533inline std::vector<point<
long long>> build_orthogonal_polygon(
int n,
7535 bool scale_up = n > 1000;
7537 long long side = std::max<
long long>(3, std::sqrt(n));
7539 side = std::clamp(
static_cast<
long long>(2 * std::sqrt(std::sqrt(n))),
7541 std::vector<point<
long long>> poly = {
7542 {0, 0}, {side, 0}, {side, side}, {0, side}};
7544 int target_ops = scale_up ? std::max(1,
static_cast<
int>(4 * side - 4) / 2)
7545 : std::max(1, (n - 4) / 2);
7548 target_ops = std::min(
7550 400 +
static_cast<
int>(4 * std::sqrt(
static_cast<
double>(side))));
7552 int failure_limit = std::min(target_ops * 8, 2000);
7554 std::vector<
int> last_used;
7555 int time_stamp = 0, consecutive_failures = 0;
7556 size_t max_vertices =
7557 scale_up ? std::numeric_limits<size_t>::max() :
static_cast<size_t>(n);
7558 for (
int ops = 0; ops < target_ops;) {
7559 if (!scale_up
and poly.size() + 2 >
static_cast<size_t>(n))
7562 if (ortho_try_bump(poly, n, last_used, time_stamp, scale_up,
7565 consecutive_failures = 0;
7566 }
else if (++consecutive_failures >= failure_limit) {
7571 poly = ortho_simplify_collinear(std::move(poly));
7574 while (poly.size() >
static_cast<size_t>(n)
and
7575 ortho_remove_one_collinear(poly))
7577 long long upscale = std::max(4LL, ((n + 3) / 4 + side - 1) / side);
7578 for (point<
long long> &p : poly)
7579 p = {p.x() * upscale, p.y() * upscale};
7581 ortho_fill_corrugation(poly, n);
7583 ortho_fill_collinear(poly, n);
7585 ortho_fill_collinear(poly, n);
7601 bool strict =
false) {
7603 "geometry: random_simple_polygon: n must be at least 3");
7605 "geometry: random_simple_polygon: min_coord must be at most "
7607 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord <=
7608 std::numeric_limits<
long long>::max(),
7609 "geometry: random_simple_polygon: coordinate range too large");
7611 std::vector<point<
long long>> points =
7612 strict ? random_points_general_position(n, min_coord, max_coord)
7613 : detail::random_distinct_points_in_box(n, min_coord, max_coord);
7614 return random_simple_polygon_through_points(points);
7623 bool strict =
false) {
7625 "geometry: random_orthogonal_polygon: n must be at least 4");
7627 "geometry: random_orthogonal_polygon: min_coord must be at "
7629 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord + 1 <=
7630 std::numeric_limits<
long long>::max(),
7631 "geometry: random_orthogonal_polygon: coordinate range too "
7633 long long width = max_coord - min_coord + 1;
7635 "geometry: random_orthogonal_polygon: coordinate range too "
7638 long long min_side = std::max<
long long>(3, std::sqrt(n));
7640 min_side = std::max<
long long>(min_side, (n + 3) / 4);
7642 "geometry: random_orthogonal_polygon: coordinate range too "
7645 for (
int attempt = 0; attempt < 8; ++attempt) {
7646 std::vector<point<
long long>> poly =
7647 detail::build_orthogonal_polygon(n, strict);
7649 if (!strict
and poly.size() !=
static_cast<size_t>(n))
7652 detail::i128 min_x = poly[0].x(), max_x = poly[0].x();
7653 detail::i128 min_y = poly[0].y(), max_y = poly[0].y();
7654 for (point<
long long> p : poly) {
7655 min_x = std::min(min_x, detail::i128(p.x()));
7656 max_x = std::max(max_x, detail::i128(p.x()));
7657 min_y = std::min(min_y, detail::i128(p.y()));
7658 max_y = std::max(max_y, detail::i128(p.y()));
7660 if (max_x - min_x >= width
or max_y - min_y >= width)
7663 detail::place_inside_box(poly, min_coord, max_coord);
7664 detail::randomize_cyclic_shift(poly);
7668 throw tgen::detail::error(
7669 "geometry: random_orthogonal_polygon: generation failed");
7675
7676
7677
7678
7684using namespace tgen::detail;
7688inline int hash_string(
const std::string &s,
int base,
int mod) {
7691 h = (h * base + c -
'a' + 1) % mod;
7696inline int estimate_length(
int alphabet_size,
int mod) {
7698 double base_len = 2.5 * std::log(std::sqrt(mod));
7699 double scale = std::log(alphabet_size) / std::log(2.0);
7700 double adjusted = base_len / std::max(1.0, scale * 0.7);
7702 return static_cast<
int>(std::ceil(adjusted));
7707inline std::pair<std::string, std::string>
7708birthday_attack(
const std::vector<std::string> &alphabet,
int base,
int mod) {
7710 "birthday_attack: base must be in (0, mod)");
7711 std::map<uint64_t, std::vector<
int>> seen;
7712 int length = estimate_length(alphabet.size(), mod);
7715 std::vector<
int> seq(length);
7719 for (
int i = 0; i < length; ++i) {
7720 seq[i] = next<
int>(0, alphabet.size() - 1);
7721 s += alphabet[seq[i]];
7724 int h = hash_string(s, base, mod);
7726 auto it = seen.find(h);
7727 if (it != seen.end()
and it->second != seq) {
7730 for (
int x : it->second)
7745inline std::set<
long long> std_hash_multipliers() {
7746 std::set<
long long> multipliers = {85229};
7749 bool codeforces_gcc_case =
true;
7750 if (cpp.version_ != 0
and cpp.version_ != 17)
7751 codeforces_gcc_case =
false;
7752 if (compiler.kind_ != compiler_kind::unknown
and
7753 compiler.kind_ != compiler_kind::gcc)
7754 codeforces_gcc_case =
false;
7755 if (compiler.major_ > 7)
7756 codeforces_gcc_case =
false;
7758 if (codeforces_gcc_case)
7759 multipliers.insert(107897);
7770 std::string str =
"a";
7772 while (
static_cast<
int>(str.size()) < n) {
7773 int prev_size = str.size();
7775 for (
int j = 0; j < prev_size
and static_cast<
int>(str.size()) < n; ++j)
7788 for (
int i = 0; i < size; ++i) {
7789 a +=
'a' + math::detail::popcount(i) % 2;
7790 b +=
'a' + (
'b' - a[i]);
7799 int base,
int mod) {
7801 "hack: polynomial_hash: alphabet size must be greater "
7804 "hack: polynomial_hash: base must be in (0, mod)");
7806 std::vector<std::string> alphabet(alphabet_size);
7807 for (
int i = 0; i < alphabet_size; ++i)
7808 alphabet[i] = std::string(1,
'a' + i);
7809 std::iota(alphabet.begin(), alphabet.end(),
'a');
7810 return detail::birthday_attack(alphabet, base, mod);
7817inline std::pair<std::string, std::string>
7819 std::vector<
int> mods) {
7821 "hack: polynomial_hash: bases and mods must have the same "
7824 "hack: polynomial_hash: must have at least one (base, mod) "
7827 "hack: polynomial_hash: multi-hash hack only supported "
7828 "for up to 2 (base, mod) pairs");
7830 std::vector<std::string> alphabet(alphabet_size);
7831 for (
int i = 0; i < alphabet_size; ++i)
7832 alphabet[i] = std::string(1,
'a' + i);
7833 auto [S1, T1] = detail::birthday_attack(alphabet, bases[0], mods[0]);
7834 if (bases.size() == 1)
7836 return detail::birthday_attack({S1, T1}, bases[1], mods[1]);
7842 tgen_ensure(size > 0,
"hack: std_unordered: size must be positive");
7843 std::set<
long long> multipliers = detail::std_hash_multipliers();
7845 std::set<
long long>::iterator it = multipliers.begin();
7847 std::vector<
long long> list;
7848 while (
static_cast<
int>(list.size()) < size) {
7849 list.push_back(mult * (*it));
7851 if (it == multipliers.end()) {
7852 it = multipliers.begin();
7864 std::set<std::pair<
int,
int>> queries;
7867 int sq = std::sqrt(n);
7868 for (
int i = 0; i < sq; ++i) {
7869 for (
int j = i; j < sq; ++j) {
7870 if (i * sq < n
and j * sq < n)
7871 queries.emplace(i * sq, j * sq);
7876 for (
int i = 0; i < n; ++i)
7877 if (queries.size() < size_t(q)) {
7878 queries.emplace(0, i);
7879 queries.emplace(i, i);
7880 queries.emplace(i, n - 1);
7883 std::vector<std::pair<
int,
int>> pool(queries.begin(), queries.end());
7884 while (pool.size() < size_t(q)) {
7885 int l = next(0, n - 1);
7886 pool.emplace_back(l, next(l, n - 1));
7889 return choose(shuffled(pool), q);
7897 std::vector<std::string> list;
7898 int k = 0, left = size;
7900 int cur_size = std::min(left, k + 1);
7903 char right_char = cur_size == k + 1 ?
'b' :
'c';
7904 list.push_back(std::string(cur_size - 1,
'a') + right_char);
7908 return tgen::shuffled(list);
7920 "hack: non_strict_relaxation_dijkstra_bug: needs at least 3 vertices");
7922 egraph<
int>::value g(n, {},
true);
7924 g.add_edge(0, 1, 1);
7925 g.add_edge(0, 2, 1);
7926 for (
int i = 1; i + 2 < n; i += 2) {
7927 g.add_edge(i, i + 2, 1);
7929 g.add_edge(i, i + 3, 1);
7931 g.add_edge(i + 1, i + 2, 1);
7933 g.add_edge(i + 1, i + 3, 1);
7936 return g.shuffle_except({0});
7949 "hack: stale_heap_dijkstra_bug: needs at least 4 vertices");
7952 egraph<
int>::value g(n, {},
true);
7954 for (
int i = 1; i < mid; ++i)
7955 g.add_edge(0, i, i);
7956 for (
int i = 1; i < mid; ++i)
7957 g.add_edge(i, mid, 2 * (mid - i) - 1);
7958 for (
int i = mid + 1; i < n; ++i)
7959 g.add_edge(mid, i, 1);
7961 return g.shuffle_except({0});
7972 tgen_ensure(n >= 2,
"hack: spfa: n must be at least 2");
7973 tgen_ensure(n % 2 == 0,
"hack: spfa: n must be even");
7975 egraph<
int>::value g(n, {},
true);
7978 const int k = n / 2;
7979 for (
int i = 0; i + 1 < k; ++i)
7980 g.add_edge(i, i + 1, 1);
7981 for (
int i = 0; i + 1 < k; ++i)
7982 g.add_edge(k + i, k + i + 1, 0);
7983 for (
int i = 0; i < k; ++i)
7984 g.add_edge(i, k + i, 0);
7985 for (
int i = 0; i + 1 < k; ++i)
7986 g.add_edge(k + i, i + 1, 1);
7988 return g.shuffle_except({0});
7996 tgen_ensure(k >= 1,
"hack: dinitz_worst_case: k must be at least 1");
7997 tgen_ensure(l >= 1,
"hack: dinitz_worst_case: l must be at least 1");
7999 const int p1 = 2 * l - 1;
8000 const int p2 = 2 * l;
8001 const int q1 = 2 * l + 1;
8002 const int q2 = 2 * l + 2;
8003 const int n = 4 * l + 2 * k + 2;
8005 const int flow_cap = k * k * l;
8006 const int layer_cap = k * k;
8008 auto a = [&](
int i) {
return 2 * l + 3 + 2 * i; };
8009 auto b = [&](
int i) {
return 2 * l + 4 + 2 * i; };
8010 auto t = [&](
int i) {
return 4 * l + 2 * k + 1 - i; };
8012 egraph<
int>::value g(n, {},
true);
8015 for (
int i = 0; i + 1 < 2 * l - 1; ++i)
8016 g.add_edge(i, i + 1, flow_cap);
8017 for (
int i = 0; i + 1 < 2 * l - 1; ++i)
8018 g.add_edge(t(i + 1), t(i), flow_cap);
8020 for (
int i = 0; i < 2 * l - 1; i += 2) {
8021 g.add_edge(i, i % 4 == 0 ? p1 : p2, layer_cap);
8022 g.add_edge(i % 4 == 0 ? q1 : q2, t(i), layer_cap);
8025 for (
int i = 0; i < k; ++i) {
8026 g.add_edge(p1, a(i), flow_cap);
8027 g.add_edge(p2, b(i), flow_cap);
8028 g.add_edge(a(i), q2, flow_cap);
8029 g.add_edge(b(i), q1, flow_cap);
8032 for (
int i = 0; i < k; ++i)
8033 for (
int j = 0; j < k; ++j)
8034 g.add_edge(a(i), b(j), 1);
8043 static_assert(std::is_same_v<T,
int>
or std::is_same_v<T,
long long>,
8044 "hack: mt19937_xor_hash: T must be int or long long");
8046 constexpr std::size_t deg = 19937;
8048 std::bitset<deg + 1> a, b, c;
8049 b[deg] = c[deg] = 1;
8050 std::size_t l = 0, shift = 1;
8052 std::mt19937_64 rng64;
8053 for (std::size_t n = 0; n < deg * 2; ++n) {
8055 if constexpr (std::is_same_v<T,
int>)
8056 a[deg] = rng32() & 1;
8058 a[deg] = rng64() & 1;
8060 if ((c & a).count() % 2 == 0) {
8065 std::bitset<deg + 1> oc = c;
8076 std::vector<
bool> mask(deg + 1);
8077 for (std::size_t i = 0; i <= deg; ++i)
8089 {-0.9846, -1.53251}, {0.49946, 1.19525}, {0.79916, 0.98291},
8090 {4.02136, -1.57843}, {3.92734, -2.37856}, {3.88558, -2.37188},
8098inline std::vector<
int> segment_tree_beats_worst_case_block(
int k) {
8100 "hack: segment_tree_beats_worst_case: k must be at least 1");
8102 std::vector<
int> a(k + 1), b(k + 1);
8103 std::vector<std::vector<
int>> vf(k + 1), vg(k + 1);
8109 for (
int i = 2; i <= k; ++i) {
8110 b[i] = b[i - 1] + a[i - 1];
8111 a[i] = b[i] + a[i - 1];
8112 for (
int x : vf[i - 1])
8113 vf[i].push_back(x + a[i] + b[i]);
8114 vf[i].push_back(a[i]);
8115 for (
int x : vg[i - 1])
8116 vf[i].push_back(x + a[i]);
8119 for (
int x : vg[i - 1])
8130segment_tree_beats_append_round(std::vector<std::vector<
int>> &updates,
8131 int block_len,
int an,
int bn,
int n,
8133 const int off = (round * an) % block_len;
8134 const int add_off = (off + block_len - bn) % block_len;
8135 for (
int k = 0; k < block_len; ++k) {
8136 const int s = k * block_len * block_len;
8137 const int sub_end = off + an;
8138 if (sub_end <= block_len)
8139 updates.push_back({1, s + off, s + sub_end, bn});
8141 updates.push_back({1, s + off, s + block_len, bn});
8142 updates.push_back({1, s, s + (sub_end - block_len), bn});
8144 const int add_end = add_off + bn;
8145 if (add_end <= block_len)
8146 updates.push_back({0, s + add_off, s + add_end, an});
8148 updates.push_back({0, s + add_off, s + block_len, an});
8149 updates.push_back({0, s, s + (add_end - block_len), an});
8152 updates.push_back({2, 0, n, an});
8153 for (
int k = 0; k < block_len; ++k) {
8154 const int s = k * block_len * block_len;
8155 updates.push_back({3, s + (off + an - 1) % block_len, 0});
8163inline std::pair<std::vector<
int>, std::vector<std::vector<
int>>>
8164segment_tree_beats_worst_case(
int k,
int q) {
8166 "hack: segment_tree_beats_worst_case: k must be at least 1");
8167 tgen_ensure(k <= 7,
"hack: segment_tree_beats_worst_case: k too large");
8169 "hack: segment_tree_beats_worst_case: q must be positive");
8171 const auto &fib = math::fibonacci();
8172 const int block_len = fib[k * 2 + 1];
8173 const int an = fib[k * 2];
8174 const int bn = fib[k * 2 - 1];
8176 const int len = block_len;
8177 const int total = len * len * len;
8179 std::vector<
int> block = detail::segment_tree_beats_worst_case_block(k);
8180 std::vector<
int> arr(total, 0);
8181 for (
int x = 0; x < block_len; ++x) {
8182 const int s = x * len * len;
8183 for (
int i = 0; i < block_len; ++i)
8184 arr[s + i] = block[i];
8187 std::vector<std::vector<
int>> updates;
8189 const int n = total;
8190 for (
int round = 0; updates.size() <
static_cast<std::size_t>(q); ++round) {
8191 detail::segment_tree_beats_append_round(updates, block_len, an, bn, n,
8193 if (updates.size() >
static_cast<std::size_t>(q))
8196 return {arr, updates};
8202
8203
8204
8205
8214 "misc: parenthesis: size must be a positive even number");
8218 int open = 0, close = 0;
8220 for (
int i = 0; i < size; ++i) {
8226 if (open == close) {
8232 long long a = k - open, b = k - close, h = open - close;
8237 long long num = a * (h + 2);
8238 long long den = (a + b) * (h + 1);
8240 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.
static value gen_np(int n, double p, bool is_directed=false, bool has_self_loops=false)
Generates a random graph where each edge is included independently.
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.