malachite_base/sets/random.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::num::conversion::traits::ExactFrom;
10use crate::num::random::geometric::{
11 GeometricRandomNaturalValues, geometric_random_unsigned_inclusive_range,
12 geometric_random_unsigneds,
13};
14use crate::num::random::{
15 RandomUnsignedInclusiveRange, RandomUnsignedRange, random_unsigned_inclusive_range,
16 random_unsigned_range,
17};
18use crate::random::Seed;
19#[cfg(not(feature = "test_build"))]
20use alloc::collections::BTreeSet;
21use core::hash::Hash;
22#[cfg(not(feature = "test_build"))]
23use hashbrown::HashSet;
24#[cfg(feature = "test_build")]
25use std::collections::{BTreeSet, HashSet};
26
27/// Generates random [`HashSet`]s of a fixed length, where the [`Vec`]s have no repeated elements,
28/// and the elements are in ascending order.
29///
30/// This `struct` is created by [`random_hash_sets_fixed_length`]; see its documentation for more.
31#[derive(Clone, Debug)]
32pub struct RandomHashSetsFixedLength<I: Iterator>
33where
34 I::Item: Eq + Hash,
35{
36 len: usize,
37 xs: I,
38}
39
40impl<I: Iterator> Iterator for RandomHashSetsFixedLength<I>
41where
42 I::Item: Eq + Hash,
43{
44 type Item = HashSet<I::Item>;
45
46 #[inline]
47 fn next(&mut self) -> Option<HashSet<I::Item>> {
48 let mut set = HashSet::new();
49 while set.len() < self.len {
50 set.insert(self.xs.next().unwrap());
51 }
52 Some(set)
53 }
54}
55
56/// Randomly generates [`HashSet`]s of a given length.
57///
58/// The input iterator must generate at least `len` distinct elements; otherwise, this iterator will
59/// hang.
60///
61/// $$
62/// P((x\_i)\_{i=0}^{n-1}) = n!\prod\_{i=0}^{n-1}P(x\_i).
63/// $$
64///
65/// If `len` is 0, the output consists of the empty set, repeated.
66///
67/// `xs` must be infinite.
68///
69/// # Expected complexity per iteration
70/// $T(i) = O(\ell T^\prime(i))$
71///
72/// $M(i) = O(\ell M^\prime(i))$
73///
74/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
75/// $M^\prime$ are the time and memory functions of `xs`, and $\ell$ is `len`.
76///
77/// If `xs` can repeat values, extra draws are needed to reach the required number of distinct
78/// elements, and an iteration fails to terminate if fewer distinct values are reachable than the
79/// requested length.
80///
81/// # Expected complexity per iteration
82/// $T(i) = O(m T^\prime(i))$
83///
84/// $M(i) = O(m M^\prime(i))$
85///
86/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
87/// $M^\prime$ are the time and memory functions of the iterators produced by `xs_gen`, and $m$ is
88/// `mean_length_numerator / mean_length_denominator`.
89///
90/// If `xs` can repeat values, extra draws are needed to reach the required number of distinct
91/// elements, and an iteration fails to terminate if fewer distinct values are reachable than the
92/// requested length.
93///
94/// # Examples
95/// ```
96/// use itertools::Itertools;
97/// use malachite_base::num::random::random_unsigned_inclusive_range;
98/// use malachite_base::random::EXAMPLE_SEED;
99/// use malachite_base::sets::random::random_hash_sets_fixed_length;
100/// use maplit::hashset;
101///
102/// let xss = random_hash_sets_fixed_length(
103/// 2,
104/// random_unsigned_inclusive_range::<u32>(EXAMPLE_SEED, 1, 100),
105/// )
106/// .take(10)
107/// .collect_vec();
108/// assert_eq!(
109/// xss,
110/// &[
111/// hashset! {24, 95},
112/// hashset! {71, 99},
113/// hashset! {53, 93},
114/// hashset! {34, 85},
115/// hashset! {2, 48},
116/// hashset! {11, 55},
117/// hashset! {18, 48},
118/// hashset! {90, 93},
119/// hashset! {67, 93},
120/// hashset! {93, 95}
121/// ]
122/// );
123/// ```
124#[inline]
125pub fn random_hash_sets_fixed_length<I: Iterator>(len: u64, xs: I) -> RandomHashSetsFixedLength<I>
126where
127 I::Item: Eq + Hash,
128{
129 RandomHashSetsFixedLength {
130 len: usize::exact_from(len),
131 xs,
132 }
133}
134
135/// Generates random [`HashSet`]s with lengths from an iterator.
136#[derive(Clone, Debug)]
137pub struct RandomHashSets<T: Eq + Hash, I: Iterator<Item = u64>, J: Iterator<Item = T>> {
138 lengths: I,
139 xs: J,
140}
141
142impl<T: Eq + Hash, I: Iterator<Item = u64>, J: Iterator<Item = T>> Iterator
143 for RandomHashSets<T, I, J>
144{
145 type Item = HashSet<T>;
146
147 fn next(&mut self) -> Option<HashSet<T>> {
148 let len = usize::exact_from(self.lengths.next().unwrap());
149 let mut set = HashSet::new();
150 while set.len() < len {
151 set.insert(self.xs.next().unwrap());
152 }
153 Some(set)
154 }
155}
156
157/// Generates random [`HashSet`]s using elements from an iterator and with lengths from another
158/// iterator.
159///
160/// The input iterator must generate at least many distinct elements as any number generated by the
161/// lengths iterator; otherwise, this iterator will hang.
162///
163/// $$
164/// P((x\_i)\_{i=0}^{n-1}) = n!P(n)\prod\_{i=0}^{n-1}P(x\_i).
165/// $$
166///
167/// `lengths` and `xs` must be infinite.
168///
169/// # Expected complexity per iteration
170/// $T(i) = O(T^{\prime\prime}(i) + \ell T^\prime(i))$
171///
172/// $M(i) = O(M^{\prime\prime}(i) + \ell M^\prime(i))$
173///
174/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
175/// $M^\prime$ are the time and memory functions of the iterators produced by `xs_gen`,
176/// $T^{\prime\prime}$ and $M^{\prime\prime}$ are the time and memory functions of `lengths`, and
177/// $\ell$ is the $i$th generated length.
178///
179/// If `xs` can repeat values, extra draws are needed to reach the required number of distinct
180/// elements, and an iteration fails to terminate if fewer distinct values are reachable than the
181/// requested length.
182///
183/// # Examples
184/// ```
185/// use itertools::Itertools;
186/// use malachite_base::num::random::random_primitive_ints;
187/// use malachite_base::random::EXAMPLE_SEED;
188/// use malachite_base::sets::random::random_hash_sets_from_length_iterator;
189/// use malachite_base::vecs::random_values_from_vec;
190/// use maplit::hashset;
191///
192/// let xs = random_hash_sets_from_length_iterator(
193/// EXAMPLE_SEED,
194/// &|seed| random_values_from_vec(seed, vec![0, 2, 4]),
195/// &random_primitive_ints::<u8>,
196/// );
197/// let values = xs.take(20).collect_vec();
198/// assert_eq!(
199/// values,
200/// &[
201/// hashset! {11, 85},
202/// hashset! {134, 136, 200, 235},
203/// hashset! {203, 223},
204/// hashset! {38, 177, 217, 235},
205/// hashset! {32, 162, 166, 234},
206/// hashset! {30, 218},
207/// hashset! {},
208/// hashset! {90, 106},
209/// hashset! {},
210/// hashset! {9, 151, 204, 216},
211/// hashset! {78, 97, 213, 253},
212/// hashset! {39, 91},
213/// hashset! {170, 175, 191, 232},
214/// hashset! {2, 233},
215/// hashset! {22, 35, 198, 217},
216/// hashset! {17, 32, 114, 173},
217/// hashset! {65, 114, 121, 222},
218/// hashset! {},
219/// hashset! {25, 144, 148, 173},
220/// hashset! {}
221/// ]
222/// );
223/// ```
224#[inline]
225pub fn random_hash_sets_from_length_iterator<
226 T: Eq + Hash,
227 I: Iterator<Item = u64>,
228 J: Iterator<Item = T>,
229>(
230 seed: Seed,
231 lengths_gen: &dyn Fn(Seed) -> I,
232 xs_gen: &dyn Fn(Seed) -> J,
233) -> RandomHashSets<T, I, J> {
234 RandomHashSets {
235 lengths: lengths_gen(seed.fork("lengths")),
236 xs: xs_gen(seed.fork("xs")),
237 }
238}
239
240/// Generates random [`HashSet`]s using elements from an iterator.
241///
242/// The lengths of the [`HashSet`]s are sampled from a geometric distribution with a specified mean
243/// $m$, equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than 0.
244///
245/// Strictly speaking, the input iterator must generate infinitely many distinct elements. In
246/// practice it only needs to generate $k$ distinct elements, where $k$ is the largest length
247/// actually sampled from the geometric distribution. For example, if `mean_length_numerator /
248/// mean_length_denominator` is significantly lower than 256, then it's ok to use
249/// `random_unsigneds::<u8>`.
250///
251/// $$
252/// P((x\_i)\_{i=0}^{n-1}) = n!P_g(n)\prod\_{i=0}^{n-1}P(x\_i),
253/// $$
254/// where $P_g(n)$ is the probability function described in [`geometric_random_unsigneds`].
255///
256/// `xs_gen` must be infinite.
257///
258/// # Expected complexity per iteration
259/// $T(i) = O(m T^\prime(i))$
260///
261/// $M(i) = O(m M^\prime(i))$
262///
263/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
264/// $M^\prime$ are the time and memory functions of `xs`, and $m$ is `mean_length_numerator /
265/// mean_length_denominator`.
266///
267/// # Panics
268/// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or, if after being
269/// reduced to lowest terms, their sum is greater than or equal to $2^{64}$.
270///
271/// # Examples
272/// ```
273/// use itertools::Itertools;
274/// use malachite_base::num::random::random_primitive_ints;
275/// use malachite_base::random::EXAMPLE_SEED;
276/// use malachite_base::sets::random::random_hash_sets;
277/// use maplit::hashset;
278///
279/// let xs = random_hash_sets(EXAMPLE_SEED, &random_primitive_ints::<u8>, 4, 1);
280/// let values = xs.take(20).collect_vec();
281/// assert_eq!(
282/// values,
283/// &[
284/// hashset! {},
285/// hashset! {11, 32, 38, 85, 134, 136, 162, 166, 177, 200, 203, 217, 223, 235},
286/// hashset! {30, 90, 218, 234},
287/// hashset! {9, 106, 204, 216},
288/// hashset! {151},
289/// hashset! {},
290/// hashset! {78, 91, 97, 213, 253},
291/// hashset! {39, 191},
292/// hashset! {170, 175, 232, 233},
293/// hashset! {},
294/// hashset! {2, 22, 35, 114, 198, 217},
295/// hashset! {},
296/// hashset! {},
297/// hashset! {17, 25, 32, 65, 79, 114, 121, 144, 148, 173, 222},
298/// hashset! {52, 69, 73, 91, 115, 137, 153, 178},
299/// hashset! {},
300/// hashset! {34, 95, 112},
301/// hashset! {},
302/// hashset! {106, 130, 167, 168, 197},
303/// hashset! {86, 101, 122, 150, 172, 177, 207, 218, 221}
304/// ]
305/// );
306/// ```
307#[inline]
308pub fn random_hash_sets<I: Iterator>(
309 seed: Seed,
310 xs_gen: &dyn Fn(Seed) -> I,
311 mean_length_numerator: u64,
312 mean_length_denominator: u64,
313) -> RandomHashSets<I::Item, GeometricRandomNaturalValues<u64>, I>
314where
315 I::Item: Eq + Hash,
316{
317 random_hash_sets_from_length_iterator(
318 seed,
319 &|seed_2| {
320 geometric_random_unsigneds(seed_2, mean_length_numerator, mean_length_denominator)
321 },
322 xs_gen,
323 )
324}
325
326/// Generates random [`HashSet`]s with a minimum length, using elements from an iterator.
327///
328/// Strictly speaking, the input iterator must generate infinitely many distinct elements. In
329/// practice it only needs to generate $k$ distinct elements, where $k$ is the largest length
330/// actually sampled from the geometric distribution. For example, if `mean_length_numerator /
331/// mean_length_denominator` is significantly lower than 256, then it's ok to use
332/// `random_unsigneds::<u8>`.
333///
334/// $$
335/// P((x\_i)\_{i=0}^{n-1}) = n!P_g(n)\prod\_{i=0}^{n-1}P(x\_i),
336/// $$
337/// where $P_g(n)$ is the probability function described in
338/// [`geometric_random_unsigned_inclusive_range`] with $a$ equal to `min_length` and `b` to
339/// `u64::MAX`.
340///
341/// `xs_gen` must be infinite.
342///
343/// # Expected complexity per iteration
344/// $T(i) = O(m T^\prime(i))$
345///
346/// $M(i) = O(m M^\prime(i))$
347///
348/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
349/// $M^\prime$ are the time and memory functions of the iterators produced by `xs_gen`, and $m$ is
350/// `mean_length_numerator / mean_length_denominator`.
351///
352/// If `xs` can repeat values, extra draws are needed to reach the required number of distinct
353/// elements, and an iteration fails to terminate if fewer distinct values are reachable than the
354/// requested length.
355///
356/// # Panics
357/// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, if their ratio is less
358/// than or equal to `min_length`, or if they are too large and manipulating them leads to
359/// arithmetic overflow.
360///
361/// # Examples
362/// ```
363/// use itertools::Itertools;
364/// use malachite_base::num::random::random_primitive_ints;
365/// use malachite_base::random::EXAMPLE_SEED;
366/// use malachite_base::sets::random::random_hash_sets_min_length;
367/// use maplit::hashset;
368///
369/// let xs = random_hash_sets_min_length(EXAMPLE_SEED, 2, &random_primitive_ints::<u8>, 6, 1);
370/// let values = xs.take(20).collect_vec();
371/// assert_eq!(
372/// values,
373/// &[
374/// hashset! {11, 85},
375/// hashset! {
376/// 30, 32, 38, 90, 134, 136, 162, 166, 177, 200, 203, 217, 218, 223, 234, 235
377/// },
378/// hashset! {9, 106, 151, 204, 213, 216},
379/// hashset! {39, 78, 91, 97, 191, 253},
380/// hashset! {170, 175, 232},
381/// hashset! {2, 233},
382/// hashset! {17, 22, 32, 35, 114, 198, 217},
383/// hashset! {65, 114, 121, 173},
384/// hashset! {25, 79, 144, 148, 173, 222},
385/// hashset! {52, 115},
386/// hashset! {34, 69, 73, 91, 112, 137, 153, 178},
387/// hashset! {95, 106},
388/// hashset! {167, 197},
389/// hashset! {74, 86, 101, 115, 122, 130, 150, 168, 172, 177, 207, 218, 221},
390/// hashset! {9, 48, 52, 109, 123, 133, 159, 201, 247, 250},
391/// hashset! {196, 235},
392/// hashset! {40, 68, 97, 104, 190},
393/// hashset! {7, 216},
394/// hashset! {11, 24, 43, 112, 157, 216, 217},
395/// hashset! {29, 51, 55, 65, 84, 89, 103, 135, 191, 206, 211}
396/// ]
397/// );
398/// ```
399#[inline]
400pub fn random_hash_sets_min_length<I: Iterator>(
401 seed: Seed,
402 min_length: u64,
403 xs_gen: &dyn Fn(Seed) -> I,
404 mean_length_numerator: u64,
405 mean_length_denominator: u64,
406) -> RandomHashSets<I::Item, GeometricRandomNaturalValues<u64>, I>
407where
408 I::Item: Eq + Hash,
409{
410 random_hash_sets_from_length_iterator(
411 seed,
412 &|seed_2| {
413 geometric_random_unsigned_inclusive_range(
414 seed_2,
415 min_length,
416 u64::MAX,
417 mean_length_numerator,
418 mean_length_denominator,
419 )
420 },
421 xs_gen,
422 )
423}
424
425/// Generates random [`HashSet`]s with lengths in $[a, b)$, using elements from an iterator.
426///
427/// The lengths of the [`HashSet`]s are sampled from a uniform distribution on $[a, b)$. $a$ must be
428/// less than $b$.
429///
430/// The input iterator must generate at least $b$ distinct elements.
431///
432/// $$
433/// P((x\_i)\_{i=0}^{n-1}, a, b) = \frac{n!}{b - a}\prod\_{i=0}^{n-1}P(x\_i).
434/// $$
435///
436/// `xs_gen` must be infinite.
437///
438/// # Expected complexity per iteration
439/// $T(i) = O(b T^\prime(i))$
440///
441/// $M(i) = O(b M^\prime(i))$
442///
443/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
444/// $M^\prime$ are the time and memory functions of the iterators produced by `xs_gen`, and $b$ is
445/// `b`.
446///
447/// If `xs` can repeat values, extra draws are needed to reach the required number of distinct
448/// elements, and an iteration fails to terminate if fewer distinct values are reachable than the
449/// requested length.
450///
451/// # Panics
452/// Panics if $a \geq b$.
453///
454/// # Examples
455/// ```
456/// use itertools::Itertools;
457/// use malachite_base::num::random::random_primitive_ints;
458/// use malachite_base::random::EXAMPLE_SEED;
459/// use malachite_base::sets::random::random_hash_sets_length_range;
460/// use maplit::hashset;
461///
462/// let xs = random_hash_sets_length_range(EXAMPLE_SEED, 2, 5, &random_primitive_ints::<u8>);
463/// let values = xs.take(20).collect_vec();
464/// assert_eq!(
465/// values,
466/// &[
467/// hashset! {11, 85, 136},
468/// hashset! {134, 200, 203, 235},
469/// hashset! {38, 223, 235},
470/// hashset! {32, 162, 177, 217},
471/// hashset! {30, 166, 218, 234},
472/// hashset! {9, 90, 106},
473/// hashset! {204, 216},
474/// hashset! {97, 151, 213},
475/// hashset! {78, 253},
476/// hashset! {39, 91, 175, 191},
477/// hashset! {2, 170, 232, 233},
478/// hashset! {22, 35, 217},
479/// hashset! {17, 32, 114, 198},
480/// hashset! {65, 114, 173},
481/// hashset! {25, 121, 173, 222},
482/// hashset! {79, 115, 144, 148},
483/// hashset! {52, 69, 73, 137},
484/// hashset! {91, 153},
485/// hashset! {34, 95, 112, 178},
486/// hashset! {106, 167}
487/// ]
488/// );
489/// ```
490#[inline]
491pub fn random_hash_sets_length_range<I: Iterator>(
492 seed: Seed,
493 a: u64,
494 b: u64,
495 xs_gen: &dyn Fn(Seed) -> I,
496) -> RandomHashSets<I::Item, RandomUnsignedRange<u64>, I>
497where
498 I::Item: Eq + Hash,
499{
500 random_hash_sets_from_length_iterator(
501 seed,
502 &|seed_2| random_unsigned_range(seed_2, a, b),
503 xs_gen,
504 )
505}
506
507/// Generates random [`HashSet`]s with lengths in $[a, b]$, using elements from an iterator.
508///
509/// The lengths of the [`HashSet`]s are sampled from a uniform distribution on $[a, b)$. $a$ must be
510/// less than or equal to $b$.
511///
512/// The input iterator must generate at least $b$ distinct elements.
513///
514/// $$
515/// P((x\_i)\_{i=0}^{n-1}, a, b) = \frac{n!}{b - a + 1}\prod\_{i=0}^{n-1}P(x\_i).
516/// $$
517///
518/// `xs_gen` must be infinite.
519///
520/// # Expected complexity per iteration
521/// $T(i) = O(b T^\prime(i))$
522///
523/// $M(i) = O(b M^\prime(i))$
524///
525/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
526/// $M^\prime$ are the time and memory functions of the iterators produced by `xs_gen`, and $b$ is
527/// `b`.
528///
529/// If `xs` can repeat values, extra draws are needed to reach the required number of distinct
530/// elements, and an iteration fails to terminate if fewer distinct values are reachable than the
531/// requested length.
532///
533/// # Panics
534/// Panics if $a \geq b$.
535///
536/// # Examples
537/// ```
538/// use itertools::Itertools;
539/// use malachite_base::num::random::random_primitive_ints;
540/// use malachite_base::random::EXAMPLE_SEED;
541/// use malachite_base::sets::random::random_hash_sets_length_inclusive_range;
542/// use maplit::hashset;
543///
544/// let xs =
545/// random_hash_sets_length_inclusive_range(EXAMPLE_SEED, 2, 4, &random_primitive_ints::<u8>);
546/// let values = xs.take(20).collect_vec();
547/// assert_eq!(
548/// values,
549/// &[
550/// hashset! {11, 85, 136},
551/// hashset! {134, 200, 203, 235},
552/// hashset! {38, 223, 235},
553/// hashset! {32, 162, 177, 217},
554/// hashset! {30, 166, 218, 234},
555/// hashset! {9, 90, 106},
556/// hashset! {204, 216},
557/// hashset! {97, 151, 213},
558/// hashset! {78, 253},
559/// hashset! {39, 91, 175, 191},
560/// hashset! {2, 170, 232, 233},
561/// hashset! {22, 35, 217},
562/// hashset! {17, 32, 114, 198},
563/// hashset! {65, 114, 173},
564/// hashset! {25, 121, 173, 222},
565/// hashset! {79, 115, 144, 148},
566/// hashset! {52, 69, 73, 137},
567/// hashset! {91, 153},
568/// hashset! {34, 95, 112, 178},
569/// hashset! {106, 167}
570/// ]
571/// );
572/// ```
573#[inline]
574pub fn random_hash_sets_length_inclusive_range<I: Iterator>(
575 seed: Seed,
576 a: u64,
577 b: u64,
578 xs_gen: &dyn Fn(Seed) -> I,
579) -> RandomHashSets<I::Item, RandomUnsignedInclusiveRange<u64>, I>
580where
581 I::Item: Eq + Hash,
582{
583 random_hash_sets_from_length_iterator(
584 seed,
585 &|seed_2| random_unsigned_inclusive_range(seed_2, a, b),
586 xs_gen,
587 )
588}
589
590/// Generates random [`BTreeSet`]s of a fixed length, where the [`Vec`]s have no repeated elements,
591/// and the elements are in ascending order.
592///
593/// This `struct` is created by [`random_b_tree_sets_fixed_length`]; see its documentation for more.
594#[derive(Clone, Debug)]
595pub struct RandomBTreeSetsFixedLength<I: Iterator>
596where
597 I::Item: Ord,
598{
599 len: usize,
600 xs: I,
601}
602
603impl<I: Iterator> Iterator for RandomBTreeSetsFixedLength<I>
604where
605 I::Item: Ord,
606{
607 type Item = BTreeSet<I::Item>;
608
609 #[inline]
610 fn next(&mut self) -> Option<BTreeSet<I::Item>> {
611 let mut set = BTreeSet::new();
612 while set.len() < self.len {
613 set.insert(self.xs.next().unwrap());
614 }
615 Some(set)
616 }
617}
618
619/// Randomly generates [`BTreeSet`]s of a given length.
620///
621/// The input iterator must generate at least `len` distinct elements; otherwise, this iterator will
622/// hang.
623///
624/// $$
625/// P((x\_i)\_{i=0}^{n-1}) = n!\prod\_{i=0}^{n-1}P(x\_i).
626/// $$
627///
628/// If `len` is 0, the output consists of the empty set, repeated.
629///
630/// `xs` must be infinite.
631///
632/// # Expected complexity per iteration
633/// $T(i) = O(\ell \log \ell \cdot T^\prime(i))$
634///
635/// $M(i) = O(\ell M^\prime(i))$
636///
637/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
638/// $M^\prime$ are the time and memory functions of `xs`, and $\ell$ is `len`.
639///
640/// If `xs` can repeat values, extra draws are needed to reach the required number of distinct
641/// elements, and an iteration fails to terminate if fewer distinct values are reachable than the
642/// requested length.
643///
644/// # Expected complexity per iteration
645/// $T(i) = O(m \log m \cdot T^\prime(i))$
646///
647/// $M(i) = O(m M^\prime(i))$
648///
649/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
650/// $M^\prime$ are the time and memory functions of the iterators produced by `xs_gen`, and $m$ is
651/// `mean_length_numerator / mean_length_denominator`.
652///
653/// If `xs` can repeat values, extra draws are needed to reach the required number of distinct
654/// elements, and an iteration fails to terminate if fewer distinct values are reachable than the
655/// requested length.
656///
657/// # Examples
658/// ```
659/// use itertools::Itertools;
660/// use malachite_base::num::random::random_unsigned_inclusive_range;
661/// use malachite_base::random::EXAMPLE_SEED;
662/// use malachite_base::sets::random::random_b_tree_sets_fixed_length;
663/// use maplit::btreeset;
664///
665/// let xss = random_b_tree_sets_fixed_length(
666/// 2,
667/// random_unsigned_inclusive_range::<u32>(EXAMPLE_SEED, 1, 100),
668/// )
669/// .take(10)
670/// .collect_vec();
671/// assert_eq!(
672/// xss,
673/// &[
674/// btreeset! {24, 95},
675/// btreeset! {71, 99},
676/// btreeset! {53, 93},
677/// btreeset! {34, 85},
678/// btreeset! {2, 48},
679/// btreeset! {11, 55},
680/// btreeset! {18, 48},
681/// btreeset! {90, 93},
682/// btreeset! {67, 93},
683/// btreeset! {93, 95}
684/// ]
685/// );
686/// ```
687#[inline]
688pub fn random_b_tree_sets_fixed_length<I: Iterator>(
689 len: u64,
690 xs: I,
691) -> RandomBTreeSetsFixedLength<I>
692where
693 I::Item: Ord,
694{
695 RandomBTreeSetsFixedLength {
696 len: usize::exact_from(len),
697 xs,
698 }
699}
700
701/// Generates random [`BTreeSet`]s with lengths from an iterator.
702#[derive(Clone, Debug)]
703pub struct RandomBTreeSets<T: Ord, I: Iterator<Item = u64>, J: Iterator<Item = T>> {
704 lengths: I,
705 xs: J,
706}
707
708impl<T: Ord, I: Iterator<Item = u64>, J: Iterator<Item = T>> Iterator for RandomBTreeSets<T, I, J> {
709 type Item = BTreeSet<T>;
710
711 fn next(&mut self) -> Option<BTreeSet<T>> {
712 let len = usize::exact_from(self.lengths.next().unwrap());
713 let mut set = BTreeSet::new();
714 while set.len() < len {
715 set.insert(self.xs.next().unwrap());
716 }
717 Some(set)
718 }
719}
720
721/// Generates random [`BTreeSet`]s using elements from an iterator and with lengths from another
722/// iterator.
723///
724/// The input iterator must generate at least many distinct elements as any number generated by the
725/// lengths iterator; otherwise, this iterator will hang.
726///
727/// $$
728/// P((x\_i)\_{i=0}^{n-1}) = n!P(n)\prod\_{i=0}^{n-1}P(x\_i).
729/// $$
730///
731/// `lengths` and `xs` must be infinite.
732///
733/// # Expected complexity per iteration
734/// $T(i) = O(T^{\prime\prime}(i) + \ell \log \ell \cdot T^\prime(i))$
735///
736/// $M(i) = O(M^{\prime\prime}(i) + \ell M^\prime(i))$
737///
738/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
739/// $M^\prime$ are the time and memory functions of the iterators produced by `xs_gen`,
740/// $T^{\prime\prime}$ and $M^{\prime\prime}$ are the time and memory functions of `lengths`, and
741/// $\ell$ is the $i$th generated length.
742///
743/// If `xs` can repeat values, extra draws are needed to reach the required number of distinct
744/// elements, and an iteration fails to terminate if fewer distinct values are reachable than the
745/// requested length.
746///
747/// # Examples
748/// ```
749/// use itertools::Itertools;
750/// use malachite_base::num::random::random_primitive_ints;
751/// use malachite_base::random::EXAMPLE_SEED;
752/// use malachite_base::sets::random::random_b_tree_sets_from_length_iterator;
753/// use malachite_base::vecs::random_values_from_vec;
754/// use maplit::btreeset;
755///
756/// let xs = random_b_tree_sets_from_length_iterator(
757/// EXAMPLE_SEED,
758/// &|seed| random_values_from_vec(seed, vec![0, 2, 4]),
759/// &random_primitive_ints::<u8>,
760/// );
761/// let values = xs.take(20).collect_vec();
762/// assert_eq!(
763/// values,
764/// &[
765/// btreeset! {11, 85},
766/// btreeset! {134, 136, 200, 235},
767/// btreeset! {203, 223},
768/// btreeset! {38, 177, 217, 235},
769/// btreeset! {32, 162, 166, 234},
770/// btreeset! {30, 218},
771/// btreeset! {},
772/// btreeset! {90, 106},
773/// btreeset! {},
774/// btreeset! {9, 151, 204, 216},
775/// btreeset! {78, 97, 213, 253},
776/// btreeset! {39, 91},
777/// btreeset! {170, 175, 191, 232},
778/// btreeset! {2, 233},
779/// btreeset! {22, 35, 198, 217},
780/// btreeset! {17, 32, 114, 173},
781/// btreeset! {65, 114, 121, 222},
782/// btreeset! {},
783/// btreeset! {25, 144, 148, 173},
784/// btreeset! {}
785/// ]
786/// );
787/// ```
788#[inline]
789pub fn random_b_tree_sets_from_length_iterator<
790 T: Ord,
791 I: Iterator<Item = u64>,
792 J: Iterator<Item = T>,
793>(
794 seed: Seed,
795 lengths_gen: &dyn Fn(Seed) -> I,
796 xs_gen: &dyn Fn(Seed) -> J,
797) -> RandomBTreeSets<T, I, J> {
798 RandomBTreeSets {
799 lengths: lengths_gen(seed.fork("lengths")),
800 xs: xs_gen(seed.fork("xs")),
801 }
802}
803
804/// Generates random [`BTreeSet`]s using elements from an iterator.
805///
806/// The lengths of the [`BTreeSet`]s are sampled from a geometric distribution with a specified mean
807/// $m$, equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than 0.
808///
809/// Strictly speaking, the input iterator must generate infinitely many distinct elements. In
810/// practice it only needs to generate $k$ distinct elements, where $k$ is the largest length
811/// actually sampled from the geometric distribution. For example, if `mean_length_numerator /
812/// mean_length_denominator` is significantly lower than 256, then it's ok to use
813/// `random_unsigneds::<u8>`.
814///
815/// $$
816/// P((x\_i)\_{i=0}^{n-1}) = n!P_g(n)\prod\_{i=0}^{n-1}P(x\_i),
817/// $$
818/// where $P_g(n)$ is the probability function described in [`geometric_random_unsigneds`].
819///
820/// `xs_gen` must be infinite.
821///
822/// # Expected complexity per iteration
823/// $T(i) = O(m \log m T^\prime(i))$
824///
825/// $M(i) = O(m M^\prime(i))$
826///
827/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
828/// $M^\prime$ are the time and memory functions of `xs`, and $m$ is `mean_length_numerator /
829/// mean_length_denominator`.
830///
831/// # Panics
832/// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or, if after being
833/// reduced to lowest terms, their sum is greater than or equal to $2^{64}$.
834///
835/// # Examples
836/// ```
837/// use itertools::Itertools;
838/// use malachite_base::num::random::random_primitive_ints;
839/// use malachite_base::random::EXAMPLE_SEED;
840/// use malachite_base::sets::random::random_b_tree_sets;
841/// use maplit::btreeset;
842///
843/// let xs = random_b_tree_sets(EXAMPLE_SEED, &random_primitive_ints::<u8>, 4, 1);
844/// let values = xs.take(20).collect_vec();
845/// assert_eq!(
846/// values,
847/// &[
848/// btreeset! {},
849/// btreeset! {11, 32, 38, 85, 134, 136, 162, 166, 177, 200, 203, 217, 223, 235},
850/// btreeset! {30, 90, 218, 234},
851/// btreeset! {9, 106, 204, 216},
852/// btreeset! {151},
853/// btreeset! {},
854/// btreeset! {78, 91, 97, 213, 253},
855/// btreeset! {39, 191},
856/// btreeset! {170, 175, 232, 233},
857/// btreeset! {},
858/// btreeset! {2, 22, 35, 114, 198, 217},
859/// btreeset! {},
860/// btreeset! {},
861/// btreeset! {17, 25, 32, 65, 79, 114, 121, 144, 148, 173, 222},
862/// btreeset! {52, 69, 73, 91, 115, 137, 153, 178},
863/// btreeset! {},
864/// btreeset! {34, 95, 112},
865/// btreeset! {},
866/// btreeset! {106, 130, 167, 168, 197},
867/// btreeset! {86, 101, 122, 150, 172, 177, 207, 218, 221}
868/// ]
869/// );
870/// ```
871#[inline]
872pub fn random_b_tree_sets<I: Iterator>(
873 seed: Seed,
874 xs_gen: &dyn Fn(Seed) -> I,
875 mean_length_numerator: u64,
876 mean_length_denominator: u64,
877) -> RandomBTreeSets<I::Item, GeometricRandomNaturalValues<u64>, I>
878where
879 I::Item: Ord,
880{
881 random_b_tree_sets_from_length_iterator(
882 seed,
883 &|seed_2| {
884 geometric_random_unsigneds(seed_2, mean_length_numerator, mean_length_denominator)
885 },
886 xs_gen,
887 )
888}
889
890/// Generates random [`BTreeSet`]s with a minimum length, using elements from an iterator.
891///
892/// Strictly speaking, the input iterator must generate infinitely many distinct elements. In
893/// practice it only needs to generate $k$ distinct elements, where $k$ is the largest length
894/// actually sampled from the geometric distribution. For example, if `mean_length_numerator /
895/// mean_length_denominator` is significantly lower than 256, then it's ok to use
896/// `random_unsigneds::<u8>`.
897///
898/// $$
899/// P((x\_i)\_{i=0}^{n-1}) = n!P_g(n)\prod\_{i=0}^{n-1}P(x\_i),
900/// $$
901/// where $P_g(n)$ is the probability function described in
902/// [`geometric_random_unsigned_inclusive_range`], with $a$ equal to `min_length` and `b` to
903/// `u64::MAX`.
904///
905/// `xs_gen` must be infinite.
906///
907/// # Expected complexity per iteration
908/// $T(i) = O(m \log m \cdot T^\prime(i))$
909///
910/// $M(i) = O(m M^\prime(i))$
911///
912/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
913/// $M^\prime$ are the time and memory functions of the iterators produced by `xs_gen`, and $m$ is
914/// `mean_length_numerator / mean_length_denominator`.
915///
916/// If `xs` can repeat values, extra draws are needed to reach the required number of distinct
917/// elements, and an iteration fails to terminate if fewer distinct values are reachable than the
918/// requested length.
919///
920/// # Panics
921/// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, if their ratio is less
922/// than or equal to `min_length`, or if they are too large and manipulating them leads to
923/// arithmetic overflow.
924///
925/// # Examples
926/// ```
927/// use itertools::Itertools;
928/// use malachite_base::num::random::random_primitive_ints;
929/// use malachite_base::random::EXAMPLE_SEED;
930/// use malachite_base::sets::random::random_b_tree_sets_min_length;
931/// use maplit::btreeset;
932///
933/// let xs = random_b_tree_sets_min_length(EXAMPLE_SEED, 2, &random_primitive_ints::<u8>, 6, 1);
934/// let values = xs.take(20).collect_vec();
935/// assert_eq!(
936/// values,
937/// &[
938/// btreeset! {11, 85},
939/// btreeset! {
940/// 30, 32, 38, 90, 134, 136, 162, 166, 177, 200, 203, 217, 218, 223, 234, 235
941/// },
942/// btreeset! {9, 106, 151, 204, 213, 216},
943/// btreeset! {39, 78, 91, 97, 191, 253},
944/// btreeset! {170, 175, 232},
945/// btreeset! {2, 233},
946/// btreeset! {17, 22, 32, 35, 114, 198, 217},
947/// btreeset! {65, 114, 121, 173},
948/// btreeset! {25, 79, 144, 148, 173, 222},
949/// btreeset! {52, 115},
950/// btreeset! {34, 69, 73, 91, 112, 137, 153, 178},
951/// btreeset! {95, 106},
952/// btreeset! {167, 197},
953/// btreeset! {74, 86, 101, 115, 122, 130, 150, 168, 172, 177, 207, 218, 221},
954/// btreeset! {9, 48, 52, 109, 123, 133, 159, 201, 247, 250},
955/// btreeset! {196, 235},
956/// btreeset! {40, 68, 97, 104, 190},
957/// btreeset! {7, 216},
958/// btreeset! {11, 24, 43, 112, 157, 216, 217},
959/// btreeset! {29, 51, 55, 65, 84, 89, 103, 135, 191, 206, 211}
960/// ]
961/// );
962/// ```
963#[inline]
964pub fn random_b_tree_sets_min_length<I: Iterator>(
965 seed: Seed,
966 min_length: u64,
967 xs_gen: &dyn Fn(Seed) -> I,
968 mean_length_numerator: u64,
969 mean_length_denominator: u64,
970) -> RandomBTreeSets<I::Item, GeometricRandomNaturalValues<u64>, I>
971where
972 I::Item: Ord,
973{
974 random_b_tree_sets_from_length_iterator(
975 seed,
976 &|seed_2| {
977 geometric_random_unsigned_inclusive_range(
978 seed_2,
979 min_length,
980 u64::MAX,
981 mean_length_numerator,
982 mean_length_denominator,
983 )
984 },
985 xs_gen,
986 )
987}
988
989/// Generates random [`BTreeSet`]s with lengths in $[a, b]$, using elements from an iterator.
990///
991/// The lengths of the [`BTreeSet`]s are sampled from a uniform distribution on $[a, b)$. $a$ must
992/// be less than or equal to $b$.
993///
994/// The input iterator must generate at least $b$ distinct elements.
995///
996/// $$
997/// P((x\_i)\_{i=0}^{n-1}, a, b) = \frac{n!}{b - a + 1}\prod\_{i=0}^{n-1}P(x\_i).
998/// $$
999///
1000/// `xs_gen` must be infinite.
1001///
1002/// # Expected complexity per iteration
1003/// $T(i) = O(b \log b \cdot T^\prime(i))$
1004///
1005/// $M(i) = O(b M^\prime(i))$
1006///
1007/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
1008/// $M^\prime$ are the time and memory functions of the iterators produced by `xs_gen`, and $b$ is
1009/// `b`.
1010///
1011/// If `xs` can repeat values, extra draws are needed to reach the required number of distinct
1012/// elements, and an iteration fails to terminate if fewer distinct values are reachable than the
1013/// requested length.
1014///
1015/// # Panics
1016/// Panics if $a \geq b$.
1017///
1018/// # Examples
1019/// ```
1020/// use itertools::Itertools;
1021/// use malachite_base::num::random::random_primitive_ints;
1022/// use malachite_base::random::EXAMPLE_SEED;
1023/// use malachite_base::sets::random::random_b_tree_sets_length_range;
1024/// use maplit::btreeset;
1025///
1026/// let xs = random_b_tree_sets_length_range(EXAMPLE_SEED, 2, 5, &random_primitive_ints::<u8>);
1027/// let values = xs.take(20).collect_vec();
1028/// assert_eq!(
1029/// values,
1030/// &[
1031/// btreeset! {11, 85, 136},
1032/// btreeset! {134, 200, 203, 235},
1033/// btreeset! {38, 223, 235},
1034/// btreeset! {32, 162, 177, 217},
1035/// btreeset! {30, 166, 218, 234},
1036/// btreeset! {9, 90, 106},
1037/// btreeset! {204, 216},
1038/// btreeset! {97, 151, 213},
1039/// btreeset! {78, 253},
1040/// btreeset! {39, 91, 175, 191},
1041/// btreeset! {2, 170, 232, 233},
1042/// btreeset! {22, 35, 217},
1043/// btreeset! {17, 32, 114, 198},
1044/// btreeset! {65, 114, 173},
1045/// btreeset! {25, 121, 173, 222},
1046/// btreeset! {79, 115, 144, 148},
1047/// btreeset! {52, 69, 73, 137},
1048/// btreeset! {91, 153},
1049/// btreeset! {34, 95, 112, 178},
1050/// btreeset! {106, 167}
1051/// ]
1052/// );
1053/// ```
1054#[inline]
1055pub fn random_b_tree_sets_length_range<I: Iterator>(
1056 seed: Seed,
1057 a: u64,
1058 b: u64,
1059 xs_gen: &dyn Fn(Seed) -> I,
1060) -> RandomBTreeSets<I::Item, RandomUnsignedRange<u64>, I>
1061where
1062 I::Item: Ord,
1063{
1064 random_b_tree_sets_from_length_iterator(
1065 seed,
1066 &|seed_2| random_unsigned_range(seed_2, a, b),
1067 xs_gen,
1068 )
1069}
1070
1071/// Generates random [`BTreeSet`]s with lengths in $[a, b]$, using elements from an iterator.
1072///
1073/// The lengths of the [`BTreeSet`]s are sampled from a uniform distribution on $[a, b)$. $a$ must
1074/// be less than or equal to $b$.
1075///
1076/// The input iterator must generate at least $b$ distinct elements.
1077///
1078/// $$
1079/// P((x\_i)\_{i=0}^{n-1}, a, b) = \frac{n!}{b - a + 1}\prod\_{i=0}^{n-1}P(x\_i).
1080/// $$
1081///
1082/// `xs_gen` must be infinite.
1083///
1084/// # Expected complexity per iteration
1085/// $T(i) = O(b \log b \cdot T^\prime(i))$
1086///
1087/// $M(i) = O(b M^\prime(i))$
1088///
1089/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
1090/// $M^\prime$ are the time and memory functions of the iterators produced by `xs_gen`, and $b$ is
1091/// `b`.
1092///
1093/// If `xs` can repeat values, extra draws are needed to reach the required number of distinct
1094/// elements, and an iteration fails to terminate if fewer distinct values are reachable than the
1095/// requested length.
1096///
1097/// # Panics
1098/// Panics if $a \geq b$.
1099///
1100/// # Examples
1101/// ```
1102/// use itertools::Itertools;
1103/// use malachite_base::num::random::random_primitive_ints;
1104/// use malachite_base::random::EXAMPLE_SEED;
1105/// use malachite_base::sets::random::random_b_tree_sets_length_inclusive_range;
1106/// use maplit::btreeset;
1107///
1108/// let xs =
1109/// random_b_tree_sets_length_inclusive_range(EXAMPLE_SEED, 2, 4, &random_primitive_ints::<u8>);
1110/// let values = xs.take(20).collect_vec();
1111/// assert_eq!(
1112/// values,
1113/// &[
1114/// btreeset! {11, 85, 136},
1115/// btreeset! {134, 200, 203, 235},
1116/// btreeset! {38, 223, 235},
1117/// btreeset! {32, 162, 177, 217},
1118/// btreeset! {30, 166, 218, 234},
1119/// btreeset! {9, 90, 106},
1120/// btreeset! {204, 216},
1121/// btreeset! {97, 151, 213},
1122/// btreeset! {78, 253},
1123/// btreeset! {39, 91, 175, 191},
1124/// btreeset! {2, 170, 232, 233},
1125/// btreeset! {22, 35, 217},
1126/// btreeset! {17, 32, 114, 198},
1127/// btreeset! {65, 114, 173},
1128/// btreeset! {25, 121, 173, 222},
1129/// btreeset! {79, 115, 144, 148},
1130/// btreeset! {52, 69, 73, 137},
1131/// btreeset! {91, 153},
1132/// btreeset! {34, 95, 112, 178},
1133/// btreeset! {106, 167}
1134/// ]
1135/// );
1136/// ```
1137#[inline]
1138pub fn random_b_tree_sets_length_inclusive_range<I: Iterator>(
1139 seed: Seed,
1140 a: u64,
1141 b: u64,
1142 xs_gen: &dyn Fn(Seed) -> I,
1143) -> RandomBTreeSets<I::Item, RandomUnsignedInclusiveRange<u64>, I>
1144where
1145 I::Item: Ord,
1146{
1147 random_b_tree_sets_from_length_iterator(
1148 seed,
1149 &|seed_2| random_unsigned_inclusive_range(seed_2, a, b),
1150 xs_gen,
1151 )
1152}