Skip to main content

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}